using System; using System.Collections.Generic; using System.Linq; using System.Text; using RimWorld; using Verse; using Verse.AI.Group; using WulaFallenEmpire; namespace WulaFallenEmpire.EventSystem.AI.Tools { public class Tool_SendReinforcement : AITool { public override string Name => "send_reinforcement"; public override string Description { get { StringBuilder sb = new StringBuilder(); sb.Append("Sends military units to the player's map. If hostile, this triggers a raid. If neutral/allied, this sends reinforcements. "); float points = 0; Map map = Find.CurrentMap; if (map != null) { points = StorytellerUtility.DefaultThreatPointsNow(map); } sb.Append($"Current Raid Points Budget: {points:F0}. "); sb.Append("Available Units (Name: Cost): "); Faction faction = Find.FactionManager.FirstFactionOfDef(FactionDef.Named("Wula_PIA_Legion_Faction")); if (faction != null) { var pawnKinds = DefDatabase.AllDefs .Where(pk => faction.def.pawnGroupMakers != null && faction.def.pawnGroupMakers.Any(pgm => pgm.options.Any(o => o.kind == pk))) .Distinct() .OrderBy(pk => pk.combatPower); foreach (var pk in pawnKinds) { if (pk.combatPower > 0) { sb.Append($"{pk.defName}: {pk.combatPower:F0}, "); } } } else { sb.Append("Error: Wula_PIA_Legion_Faction not found."); } sb.Append("Usage: Provide a list of 'PawnKindDefName: Count'. Total cost must not exceed budget significantly."); return sb.ToString(); } } public override string UsageSchema => "string (e.g., 'Wula_PIA_Heavy_Unit_Melee: 2, Wula_PIA_Legion_Escort_Unit: 5')"; public override string Execute(string args) { try { Map map = Find.CurrentMap; if (map == null) return "Error: No active map."; Faction faction = Find.FactionManager.FirstFactionOfDef(FactionDef.Named("Wula_PIA_Legion_Faction")); if (faction == null) return "Error: Faction Wula_PIA_Legion_Faction not found."; // Parse args var parsedArgs = ParseXmlArgs(args); string unitString = ""; if (parsedArgs.TryGetValue("units", out string units)) { unitString = units; } else { // Fallback if (!args.Trim().StartsWith("<")) { unitString = args; } } var unitPairs = unitString.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); List pawnsToSpawn = new List(); float totalCost = 0; foreach (var pair in unitPairs) { var kv = pair.Split(':'); if (kv.Length != 2) continue; string defName = kv[0].Trim(); if (!int.TryParse(kv[1].Trim(), out int count)) continue; PawnKindDef kind = DefDatabase.GetNamed(defName, false); if (kind == null) continue; for(int i=0; i(); int goodwill = eventVarManager.GetVariable("Wula_Goodwill_To_PIA", 0); float goodwillFactor = 1.0f; bool hostile = faction.HostileTo(Faction.OfPlayer); if (hostile) { if (goodwill < -50) goodwillFactor = 1.5f; else if (goodwill < 0) goodwillFactor = 1.2f; else if (goodwill > 50) goodwillFactor = 0.8f; } else { if (goodwill < -50) goodwillFactor = 0.5f; else if (goodwill < 0) goodwillFactor = 0.8f; else if (goodwill > 50) goodwillFactor = 1.5f; } float baseMaxPoints = StorytellerUtility.DefaultThreatPointsNow(map); float adjustedMaxPoints = baseMaxPoints * goodwillFactor * 1.5f; WulaLog.Debug($"[WulaAI] send_reinforcement: totalCost={totalCost}, adjustedMaxPoints={adjustedMaxPoints}"); if (totalCost > adjustedMaxPoints) { return $"Error: Total cost {totalCost} exceeds limit {adjustedMaxPoints:F0}. Reduce unit count."; } IntVec3 spawnSpot; if (hostile) { IncidentParms parms = new IncidentParms { target = map, points = totalCost, faction = faction, forced = true, raidStrategy = RaidStrategyDefOf.ImmediateAttack }; if (!RCellFinder.TryFindRandomPawnEntryCell(out spawnSpot, map, CellFinder.EdgeRoadChance_Hostile)) { spawnSpot = CellFinder.RandomEdgeCell(map); } parms.spawnCenter = spawnSpot; // Arrive PawnsArrivalModeDefOf.EdgeWalkIn.Worker.Arrive(pawnsToSpawn, parms); // Make Lord parms.raidStrategy.Worker.MakeLords(parms, pawnsToSpawn); Find.LetterStack.ReceiveLetter("Raid", "The Legion has sent a raid force.", LetterDefOf.ThreatBig, pawnsToSpawn); return $"Success: Raid dispatched with {pawnsToSpawn.Count} units (Cost: {totalCost})."; } else { spawnSpot = DropCellFinder.TradeDropSpot(map); DropPodUtility.DropThingsNear(spawnSpot, map, pawnsToSpawn.Cast()); LordMaker.MakeNewLord(faction, new LordJob_AssistColony(faction, spawnSpot), map, pawnsToSpawn); Find.LetterStack.ReceiveLetter("Reinforcements", "The Legion has sent reinforcements.", LetterDefOf.PositiveEvent, pawnsToSpawn); return $"Success: Reinforcements dropped with {pawnsToSpawn.Count} units (Cost: {totalCost})."; } } catch (Exception ex) { return $"Error: {ex.Message}"; } } } }