diff --git a/Odyssey/Patches/Odyssey/PawnkindDefs/PawnKinds_Odyssey.xml b/Odyssey/Patches/Odyssey/PawnkindDefs/PawnKinds_Odyssey.xml index 9e4eb44d41..3c0649fc4d 100644 --- a/Odyssey/Patches/Odyssey/PawnkindDefs/PawnKinds_Odyssey.xml +++ b/Odyssey/Patches/Odyssey/PawnkindDefs/PawnKinds_Odyssey.xml @@ -76,6 +76,16 @@ + + Defs/PawnKindDef[defName="AncientSoldier_Leader"] + + +
  • CE_Apparel_TacVest
  • +
  • CE_Apparel_Backpack
  • +
    +
    +
    + @@ -135,7 +145,7 @@ 1 3 - + @@ -225,10 +235,10 @@ 1 3 - + - + \ No newline at end of file diff --git a/Source/CombatExtended/Harmony/Harmony_CompUniqueWeapon.cs b/Source/CombatExtended/Harmony/Harmony_CompUniqueWeapon.cs index 2feca1d366..977d56aac8 100644 --- a/Source/CombatExtended/Harmony/Harmony_CompUniqueWeapon.cs +++ b/Source/CombatExtended/Harmony/Harmony_CompUniqueWeapon.cs @@ -12,6 +12,14 @@ internal static class CompUniqueWeapon_Setup { internal static void Postfix(CompUniqueWeapon __instance, bool fromSave) { + // Unique Weapon Spawns before pawn is spawned, + // Not doing it on save load, we are not in the business of topping off the player's mags. + CompAmmoUser compAmmo = __instance.parent.TryGetComp(); + if (!fromSave && compAmmo != null && compAmmo.UseAmmo) + { + compAmmo.ResetAmmoCount(); + } + CompUnderBarrel compUnderBarrel = __instance.parent.TryGetComp(); bool underBarrelApplied = false; bool verbOverrideApplied = false; diff --git a/Source/CombatExtended/Harmony/Harmony_QuestNode_Root_AncientMercenaries.cs b/Source/CombatExtended/Harmony/Harmony_QuestNode_Root_AncientMercenaries.cs new file mode 100644 index 0000000000..d674cf9741 --- /dev/null +++ b/Source/CombatExtended/Harmony/Harmony_QuestNode_Root_AncientMercenaries.cs @@ -0,0 +1,93 @@ +using System; +using System.Linq; +using HarmonyLib; +using RimWorld; +using RimWorld.QuestGen; +using UnityEngine; +using Verse; + +namespace CombatExtended.HarmonyCE; + +// Boss gets his unique gun after loadout gen already ran, so hand him spare mags here. Read the +// weapon off the slate, not equipment.Primary - the quest nukes his gear and he grabs a sidearm. +[HarmonyPatch(typeof(QuestNode_Root_AncientMercenaries), "RunInt")] +internal static class QuestNode_Root_AncientMercenaries_RunInt +{ + private static readonly IntRange MagazineCount = new IntRange(3, 5); + + internal static void Postfix() + { + try + { + Pawn pawn = QuestGen.slate.Get("LEADER"); + ThingWithComps weapon = QuestGen.slate.Get("WEAPON") ?? (pawn.equipment?.Primary as ThingWithComps); + CompAmmoUser compAmmo = weapon?.TryGetComp(); + CompInventory inventory = pawn?.TryGetComp(); + if (pawn == null || weapon == null || compAmmo == null || !compAmmo.UseAmmo || inventory == null || pawn.inventory == null) + { + return; + } + + AmmoDef ammo = PickAmmo(compAmmo); + if (ammo == null) + { + return; + } + + compAmmo.ResetAmmoCount(ammo); + + int unit = Mathf.Max(1, compAmmo.MagSizeOverride > 0 ? compAmmo.MagSizeOverride : compAmmo.MagSize); + + // drop the old weapon's mags (dead weight, eats his carry cap) before handing out new ones + foreach (Thing dead in inventory.container.Where(t => t.def is AmmoDef && t.def != ammo).ToList()) + { + inventory.container.Remove(dead); + if (!dead.Destroyed) + { + dead.Destroy(DestroyMode.Vanish); + } + } + inventory.UpdateInventory(); + + Thing mags = ThingMaker.MakeThing(ammo); + mags.stackCount = MagazineCount.RandomInRange * unit; + if (inventory.CanFitInInventory(mags, out int maxCount)) + { + if (maxCount < mags.stackCount) + { + mags.stackCount = maxCount - (maxCount % unit); + } + if (mags.stackCount > 0) + { + inventory.container.TryAdd(mags); + } + } + else + { + Log.Warning($"[CE] Ancient mercenaries leader: no room for {ammo.defName} mags."); + } + inventory.UpdateInventory(); + } + catch (Exception ex) + { + Log.Error($"[CE] Ancient mercenaries leader ammo gen failed: {ex}"); + } + } + + private static AmmoDef PickAmmo(CompAmmoUser compAmmo) + { + if (compAmmo.Props?.ammoSet == null) + { + return null; + } + var links = compAmmo.Props.ammoSet.ammoTypes; + var avail = links.Where(a => a.ammo != null && a.ammo.alwaysHaulable && !a.ammo.menuHidden && a.ammo.generateAllowChance > 0f) + .Select(a => a.ammo) + .ToList(); + if (avail.Count == 0) + { + avail = links.Where(a => a.ammo != null).Select(a => a.ammo).ToList(); + } + return avail.Count > 0 ? avail.RandomElement() : null; + } +}