using System.Collections.Generic; using System.Linq; using Verse; using RimWorld; using Verse.AI; using Verse.AI.Group; namespace ArachnaeSwarm { public class CompSpawnPawnFromList : ThingComp { public CompProperties_SpawnPawnFromList Props => (CompProperties_SpawnPawnFromList)props; private int spawnUntilTick = -1; private PawnKindDef spawningPawnKind; private PawnKindDef selectedPawnKind; public bool IsHatching => spawnUntilTick > 0; public override IEnumerable CompFloatMenuOptions(Pawn selPawn) { if (spawnUntilTick > 0) { yield break; // 正在延迟中,不显示菜单 } if (Props.whitelist == null || !Props.whitelist.Contains(selPawn.kindDef)) { yield break; } if (Props.pawnKinds != null) { foreach (PawnKindDef pawnKind in Props.pawnKinds) { yield return new FloatMenuOption("ARA_Incubate".Translate(pawnKind.label), () => { Job job = JobMaker.MakeJob(DefDatabase.GetNamed("ARA_IncubateJob"), parent); selectedPawnKind = pawnKind; selPawn.jobs.TryTakeOrderedJob(job); }); } } } public void StartIncubation() { spawningPawnKind = selectedPawnKind; int delay = Props.pawnKindDelays?.FirstOrDefault(pkd => pkd.pawnKind == selectedPawnKind)?.delay ?? 0; spawnUntilTick = Find.TickManager.TicksGame + delay; } public override void CompTick() { base.CompTick(); if (spawnUntilTick > 0 && Find.TickManager.TicksGame >= spawnUntilTick) { SpawnPawn(spawningPawnKind); } } private void SpawnPawn(PawnKindDef pawnKind) { try { if (pawnKind == null) { Log.Warning("CompSpawnPawnFromList: Tried to spawn pawn but pawnKind is null."); return; } if (!parent.Spawned || parent.Map == null) { Log.Error($"CompSpawnPawnFromList: Cannot spawn pawn. Parent {parent} is not spawned or map is null."); return; } int count = Props.spawnCount.RandomInRange; for (int i = 0; i < count; i++) { Pawn pawn = PawnGenerator.GeneratePawn(new PawnGenerationRequest(pawnKind, parent.Faction)); if (pawn == null) { Log.Error($"CompSpawnPawnFromList: Failed to generate pawn of kind {pawnKind.defName} for faction {parent.Faction?.Name ?? "null"}."); continue; } if (GenSpawn.Spawn(pawn, parent.Position, parent.Map) == null) { Log.Error($"CompSpawnPawnFromList: Failed to spawn pawn {pawn} at {parent.Position}."); if (!pawn.Destroyed) { pawn.Destroy(); } continue; } if (Props.lordJob != null) { try { LordJob lordJobInstance = (LordJob)System.Activator.CreateInstance(Props.lordJob); Lord lord = LordMaker.MakeNewLord(parent.Faction, lordJobInstance, parent.Map); lord.AddPawn(pawn); } catch (System.Exception e) { Log.Error($"CompSpawnPawnFromList: Error creating LordJob {Props.lordJob?.Name ?? "null"} or assigning pawn {pawn}. Exception: {e}"); } } } if (Props.destroyOnSpawn) { parent.Destroy(DestroyMode.Vanish); } } finally { spawnUntilTick = -1; spawningPawnKind = null; } } public override string CompInspectStringExtra() { if (spawnUntilTick > 0) { int remainingTicks = spawnUntilTick - Find.TickManager.TicksGame; if (remainingTicks > 0) { return "Spawning {0} in: {1}".Translate(spawningPawnKind.label, remainingTicks.ToStringTicksToPeriod()); } } else { return "ARA_NeedsInteraction".Translate(); } return null; } public override void PostExposeData() { base.PostExposeData(); Scribe_Values.Look(ref spawnUntilTick, "spawnUntilTick", -1); Scribe_Defs.Look(ref spawningPawnKind, "spawningPawnKind"); Scribe_Defs.Look(ref selectedPawnKind, "selectedPawnKind"); } } }