@@ -15,6 +15,8 @@ namespace STS2RitsuLib.Scaffolding.Characters.Patches
1515 /// Adds a pool-filter button for each registered mod character in the card library compendium.
1616 /// Without this patch, mod character cards are not visible in any filter category, and opening
1717 /// the card library during a run with a mod character causes a KeyNotFoundException crash.
18+ /// Buttons are inserted before the colorless pool filter when possible (then ancients, misc),
19+ /// so they stay with playable-character filters rather than after misc/token-style pools.
1820 /// </summary>
1921 public class CardLibraryCompendiumPatch : IPatchMethod
2022 {
@@ -53,6 +55,8 @@ public static void Postfix(
5355 var filterParent = referenceFilter . GetParent ( ) ;
5456 if ( filterParent == null ) return ;
5557
58+ var useOrderedInsert = TryGetModFilterInsertIndex ( __instance , filterParent , out var insertIndex ) ;
59+
5660 ShaderMaterial ? referenceMat = null ;
5761 if ( referenceFilter . GetNodeOrNull < Control > ( "Image" ) is { Material : ShaderMaterial refMat } )
5862 referenceMat = refMat ;
@@ -61,6 +65,7 @@ public static void Postfix(
6165 var updateCallable = Callable . From < NCardPoolFilter > ( f => updateMethod . Invoke ( __instance , [ f ] ) ) ;
6266 var lastHoveredField = AccessTools . Field ( typeof ( NCardLibrary ) , "_lastHoveredControl" ) ;
6367
68+ var nextIndex = insertIndex ;
6469 foreach ( var character in modCharacters )
6570 {
6671 string ? iconTexturePath = null ;
@@ -69,6 +74,11 @@ public static void Postfix(
6974
7075 var filter = CreateFilter ( character , iconTexturePath , referenceMat ) ;
7176 filterParent . AddChild ( filter , true ) ;
77+ if ( useOrderedInsert )
78+ {
79+ filterParent . MoveChild ( filter , nextIndex ) ;
80+ nextIndex ++ ;
81+ }
7282
7383 var pool = character . CardPool ;
7484 ____poolFilters . Add ( filter , c => pool . AllCardIds . Contains ( c . Id ) ) ;
@@ -80,6 +90,38 @@ public static void Postfix(
8090 }
8191 }
8292
93+ /// <summary>
94+ /// Prefer inserting mod character filters immediately before non-character pool toggles: colorless, then
95+ /// ancients, then misc (vanilla has no separate token node; those pools follow). Falls back when no anchor
96+ /// resolves under <paramref name="expectedParent" />.
97+ /// </summary>
98+ private static bool TryGetModFilterInsertIndex (
99+ NCardLibrary library ,
100+ Node expectedParent ,
101+ out int insertIndex )
102+ {
103+ ReadOnlySpan < string > anchorNames =
104+ [
105+ "%ColorlessPool" ,
106+ "%AncientsPool" ,
107+ "%MiscPool" ,
108+ ] ;
109+
110+ foreach ( var name in anchorNames )
111+ {
112+ if ( library . GetNodeOrNull < NCardPoolFilter > ( name ) is not { } anchor )
113+ continue ;
114+ if ( anchor . GetParent ( ) != expectedParent )
115+ continue ;
116+
117+ insertIndex = anchor . GetIndex ( ) ;
118+ return true ;
119+ }
120+
121+ insertIndex = 0 ;
122+ return false ;
123+ }
124+
83125 private static NCardPoolFilter CreateFilter (
84126 CharacterModel character ,
85127 string ? iconTexturePath ,
0 commit comments