Where is the code which spawns troops and chooses gear from their XML equipment rosters?

Users who are viewing this thread

I had this [link] problem a while ago...

Since then I have moved my mod to XSL entirely but the issue is still not solved and I'm tired of ignoring it.

Rosters on the battlefield are still mixed, which adds unwanted and unbalanced RNG to the fights since soldiers are often either too weak or too strong because of the way their gear mixes.

Since I can't fix this issue via XSL, does anyone have any leads on how I can rewrite part of the game's code to spawn soldiers with one entire roster or another?

Was hoping I wouldn't have to touch any c# but I don't have much choice if I'm trying to make a balanced troop rework.


Here is an example of my XSL in case you were doubting if I wrote it right.
XML:
<xsl:template match='NPCCharacter[@id="sturgian_soldier"]' >
        <!-- Sturgian Soldier - T3  -->
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <face>
                <face_key_template value="BodyProperty.fighter_sturgia" />
            </face>
            <skills>
                <skill id="Athletics" value="75" />
                <skill id="Riding" value="45" />
                <skill id="OneHanded" value="100" />
                <skill id="TwoHanded" value="40" />
                <skill id="Polearm" value="70" />
                <skill id="Bow" value="40" />
                <skill id="Crossbow" value="40" />
                <skill id="Throwing" value="40" />
            </skills>
            <upgrade_targets>
                <upgrade_target id="NPCCharacter.sturgian_spearman" />
                <upgrade_target id="NPCCharacter.sturgian_berzerker" />
            </upgrade_targets>
            <Equipments>
                <EquipmentRoster>
                    <equipment slot="Item0" id="Item.sturgia_axe_2_t2" />
                    <equipment slot="Item1" id="Item.northern_round_shield" />
                    <equipment slot="Item2" id="Item.northern_spear_2_t3" />
                    <equipment slot="Head" id="Item.nasal_helmet_with_leather" />
                    <equipment slot="Body" id="Item.nordic_lamellar_vest" />
                    <equipment slot="Leg" id="Item.highland_leg_wrappings" />
                    <equipment slot="Gloves" id="Item.guarded_armwraps" />
                    <equipment slot="Cape" id="Item.battanian_chainmail_shoulder_a" />
                </EquipmentRoster>
                <EquipmentRoster>
                    <equipment slot="Item0" id="Item.sturgia_axe_2_t2" />
                    <equipment slot="Item1" id="Item.northern_round_shield" />
                    <equipment slot="Item2" id="Item.northern_spear_2_t3" />
                    <equipment slot="Head" id="Item.nasalhelm_over_leather" />
                    <equipment slot="Cape" id="Item.battanian_chainmail_shoulder_b" />
                    <equipment slot="Body" id="Item.nordic_lamellar_vest" />
                    <equipment slot="Leg" id="Item.highland_leg_wrappings" />
                    <equipment slot="Gloves" id="Item.guarded_armwraps" />
                </EquipmentRoster>
                <EquipmentSet id="sturgia_troop_civilian_template_t2" civilian="true" />
            </Equipments>
        </xsl:copy>
    </xsl:template>
 
Last edited:
Each roster is only treated as a unique equipment set in the Encyclopaedia. In game, the roosters are just treated as pools from which agents are randomly equipped. AFAIK this is Taleworlds intended behaviour to ensure variety as there will be many more agents of a type that rosters in large battles.
I don’t know if this is hard-coded in C++ or could be modified in C# to match the encyclopaedia treatment, allowing agents to be randomised from fixed rosters rather than pooling kit. You probably need to ask in the #bl-coding channel of Mount & Blade Modding discord.
 
Upvote 0
Each roster is only treated as a unique equipment set in the Encyclopaedia. In game, the roosters are just treated as pools from which agents are randomly equipped. AFAIK this is Taleworlds intended behaviour to ensure variety as there will be many more agents of a type that rosters in large battles.
I don’t know if this is hard-coded in C++ or could be modified in C# to match the encyclopaedia treatment, allowing agents to be randomised from fixed rosters rather than pooling kit. You probably need to ask in the #bl-coding channel of Mount & Blade Modding discord.
I see. The reason behind that behaviour makes total sense, but it does make it difficult to manually create your own varieties while accomodating for balance (e.g. one roster with a strong chest piece, one roster with a weak chest piece but strong cape).
I ended up finding the c# code at TaleWorlds.Core.Equipment.GetRandomEquipmentElements so I think I can make a harmony patch, but #bl-coding will be useful if I find myself stumped. Thank you @NPC99
 
Upvote 0
eyyyyy got it let's go
C#:
        [HarmonyPrefix]
        [HarmonyPatch(typeof(Equipment), nameof(Equipment.GetRandomEquipmentElements))]
        public static bool AssignGearPatch(ref Equipment __result, BasicCharacterObject character, bool randomEquipmentModifier, bool isCivilianEquipment = false, int seed = -1)
        {
            Equipment equipment = new Equipment(isCivilianEquipment);
            List<Equipment> list = character.AllEquipments.Where((Equipment eq) => eq.IsCivilian == isCivilianEquipment && !eq.IsEmpty()).ToList();
            if (list.IsEmpty())
            {
                __result = equipment;
                return false;
            }

            int count = list.Count;
            Random random = new Random(seed);
            int weaponSetNo1 = MBRandom.RandomInt(count);
            for (int i = 0; i < 12; i++)
            {
                equipment[i] = list[weaponSetNo1].GetEquipmentFromSlot((EquipmentIndex)i);
                if (randomEquipmentModifier)
                {
                    ItemModifier itemModifier = equipment[i].Item?.ItemComponent?.ItemModifierGroup?.GetRandomItemModifierLootScoreBased();
                    if (itemModifier != null)
                    {
                        equipment[i].SetModifier(itemModifier);
                    }
                }
            }

            __result = equipment;
            return false;
        }
 
Upvote 0
mrj760 Hi! Great patch, really interested in it, do you mind sharing the module of this patch? You left the code but I have no clue how to create a working module out of this correctly(
 
Upvote 0
Back
Top Bottom