diff --git a/1.6/Assemblies/WulaFallenEmpire.dll b/1.6/Assemblies/WulaFallenEmpire.dll index 4c794e2f..f177ec77 100644 Binary files a/1.6/Assemblies/WulaFallenEmpire.dll and b/1.6/Assemblies/WulaFallenEmpire.dll differ diff --git a/1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml b/1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml new file mode 100644 index 00000000..73d90179 --- /dev/null +++ b/1.6/Defs/HediffDefs/Hediffs_WULA_Maintenance.xml @@ -0,0 +1,60 @@ + + + + WULA_Maintenance_Neglect + + 如果缺乏定期维护,身体机能将会出现衰退迹象。需要进入维护舱进行修复。 + HediffWithComps + (0.8, 0.35, 0.35) + true + +
  • + 60 + 0.004 + 0.02 +
  • +
    + +
  • + + 0 + +
  • + Consciousness + 0.1 +
  • + + +
  • + + 0.5 + +
  • + Consciousness + 0 +
  • + + +
  • + + 0.75 + +
  • + Consciousness + -0.10 +
  • + + +
  • + + 1.0 + +
  • + Consciousness + -0.25 +
  • + + +
    +
    +
    \ No newline at end of file diff --git a/1.6/Defs/JobDefs/WULA_Jobs_Maintenance.xml b/1.6/Defs/JobDefs/WULA_Jobs_Maintenance.xml new file mode 100644 index 00000000..29f026db --- /dev/null +++ b/1.6/Defs/JobDefs/WULA_Jobs_Maintenance.xml @@ -0,0 +1,17 @@ + + + + + WULA_LoadComponentsToMaintenancePod + WulaFallenEmpire.JobDriver_LoadComponents + 正在为维护舱装填零部件。 + ToCellNonStorage + + + + WULA_EnterMaintenancePod + WulaFallenEmpire.JobDriver_EnterMaintenancePod + 正在进入维护舱。 + + + \ No newline at end of file diff --git a/1.6/Defs/ThingDefs_Buildings/WULA_Buildings_Maintenance.xml b/1.6/Defs/ThingDefs_Buildings/WULA_Buildings_Maintenance.xml new file mode 100644 index 00000000..6241a359 --- /dev/null +++ b/1.6/Defs/ThingDefs_Buildings/WULA_Buildings_Maintenance.xml @@ -0,0 +1,87 @@ + + + + + WULA_MaintenancePod + + 一个为乌拉族设计的全自动维护舱。乌拉族需要定期进入其中进行身体机能的维护和校准,否则他们的身体会逐渐衰弱。维护过程需要消耗零部件。 + true + + Things/Building/Misc/BiosculpterPod/BiosculpterPod + Graphic_Multi + + (2.9,0.6,1.9) + + (3, 2) + + RealtimeOnly + true + South + Building + PassThroughOnly + 42 + true + 0.5 + false + + 250 + 20000 + 50 + 0.5 + -5 + + (3,2) + (0,0,2) + true + + 150 + 10 + 2 + + 8 + + BuildingDestroyed_Metal_Big + 1800 + + + +
  • ComponentIndustrial
  • +
    +
    +
    +
    + Misc + MinifiedThing + +
  • BuildingsMisc
  • +
    + Normal + +
  • + CompPowerTrader + 50 +
  • +
  • +
  • + 60000 + 250 + 50 + WULA_Maintenance_Neglect + ComponentIndustrial + 5 + 0 + 0.75 + BiosculpterPod_Enter + BiosculpterPod_Exit + BiosculpterPod_Operating +
  • +
    + +
  • PlaceWorker_PreventInteractionSpotOverlap
  • +
    + +
  • ITab_Storage
  • +
    +
    + +
    \ No newline at end of file diff --git a/1.6/Defs/WorkGiverDefs/WULA_WorkGivers.xml b/1.6/Defs/WorkGiverDefs/WULA_WorkGivers.xml new file mode 100644 index 00000000..dd5a0365 --- /dev/null +++ b/1.6/Defs/WorkGiverDefs/WULA_WorkGivers.xml @@ -0,0 +1,27 @@ + + + + + WULA_LoadComponentsToMaintenancePod + + WulaFallenEmpire.WorkGiver_LoadComponents + Hauling + 装填 + 装填于 + 110 + +
  • Manipulation
  • +
    +
    + + + WULA_EnterMaintenancePod + + WulaFallenEmpire.WorkGiver_EnterMaintenancePod + Patient + 进行维护 + 进行维护于 + 100 + + +
    \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Building_MaintenancePod.cs b/Source/WulaFallenEmpire/Building_MaintenancePod.cs new file mode 100644 index 00000000..ec8209eb --- /dev/null +++ b/Source/WulaFallenEmpire/Building_MaintenancePod.cs @@ -0,0 +1,35 @@ +using RimWorld; +using Verse; + +namespace WulaFallenEmpire +{ + public class CompProperties_MaintenanceCycle : CompProperties_BiosculpterPod_BaseCycle + { + public HediffDef hediffToRemove; + + public CompProperties_MaintenanceCycle() + { + compClass = typeof(CompMaintenanceCycle); + } + } + + public class CompMaintenanceCycle : CompBiosculpterPod_Cycle + { + public new CompProperties_MaintenanceCycle Props => (CompProperties_MaintenanceCycle)props; + + public override void CycleCompleted(Pawn pawn) + { + if (pawn == null) + { + return; + } + + Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.hediffToRemove); + if (hediff != null) + { + hediff.Severity = 0f; + Messages.Message("WULA_MaintenanceCycleComplete".Translate(pawn.Named("PAWN")), pawn, MessageTypeDefOf.PositiveEvent); + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/CompMaintenancePod.cs b/Source/WulaFallenEmpire/CompMaintenancePod.cs new file mode 100644 index 00000000..32a17baa --- /dev/null +++ b/Source/WulaFallenEmpire/CompMaintenancePod.cs @@ -0,0 +1,298 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + // Properties for our custom maintenance pod + public class CompProperties_MaintenancePod : CompProperties + { + public SoundDef enterSound; + public SoundDef exitSound; + public EffecterDef operatingEffecter; + public int durationTicks = 60000; // Default to 1 day + public float powerConsumptionRunning = 250f; + public float powerConsumptionIdle = 50f; + public HediffDef hediffToRemove; + public ThingDef componentDef; + public float componentCostPerSeverity = 1f; // How many components per 1.0 severity + public int baseComponentCost = 0; // A flat cost in addition to severity cost + public float minSeverityToMaintain = 0.75f; // The hediff severity required to trigger maintenance + + public CompProperties_MaintenancePod() + { + compClass = typeof(CompMaintenancePod); + } + } + + [StaticConstructorOnStartup] + public class CompMaintenancePod : ThingComp, IThingHolder, IStoreSettingsParent + { + // ===================== Fields ===================== + private ThingOwner innerContainer; + private CompPowerTrader powerComp; + private StorageSettings allowedComponentSettings; + + public float storedComponents = 0f; + private int ticksRemaining; + private MaintenancePodState state = MaintenancePodState.Idle; + + private static readonly Texture2D CancelIcon = ContentFinder.Get("UI/Designators/Cancel"); + private static readonly Texture2D EnterIcon = ContentFinder.Get("UI/Commands/PodEject"); // Re-using an icon + + // ===================== Properties ===================== + public CompProperties_MaintenancePod Props => (CompProperties_MaintenancePod)props; + public MaintenancePodState State => state; + public Pawn Occupant => innerContainer.FirstOrDefault() as Pawn; + public bool PowerOn => powerComp != null && powerComp.PowerOn; + public float RequiredComponents(Pawn pawn) + { + if (pawn == null || Props.hediffToRemove == null) return Props.baseComponentCost; + Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(Props.hediffToRemove); + if (hediff == null) return Props.baseComponentCost; + return Props.baseComponentCost + (int)(hediff.Severity * Props.componentCostPerSeverity); + } + + // ===================== Setup ===================== + public CompMaintenancePod() + { + innerContainer = new ThingOwner(this, false, LookMode.Deep); + } + + public override void Initialize(CompProperties props) + { + base.Initialize(props); + // Setup allowed thing filter for components + allowedComponentSettings = new StorageSettings(this); + if (parent.def.building.defaultStorageSettings != null) + { + allowedComponentSettings.CopyFrom(parent.def.building.defaultStorageSettings); + } + else if (Props.componentDef != null) + { + allowedComponentSettings.filter = new ThingFilter(); + allowedComponentSettings.filter.SetAllow(Props.componentDef, true); + } + } + + public override void PostSpawnSetup(bool respawningAfterLoad) + { + base.PostSpawnSetup(respawningAfterLoad); + powerComp = parent.TryGetComp(); + } + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Values.Look(ref state, "state", MaintenancePodState.Idle); + Scribe_Values.Look(ref storedComponents, "storedComponents", 0f); + Scribe_Values.Look(ref ticksRemaining, "ticksRemaining", 0); + Scribe_Deep.Look(ref innerContainer, "innerContainer", this); + Scribe_Deep.Look(ref allowedComponentSettings, "allowedComponentSettings", this); + } + + // ===================== IThingHolder Implementation ===================== + public void GetChildHolders(List outChildren) + { + ThingOwnerUtility.AppendThingHoldersFromThings(outChildren, GetDirectlyHeldThings()); + } + + public ThingOwner GetDirectlyHeldThings() + { + return innerContainer; + } + + // ===================== IStoreSettingsParent Implementation ===================== + public StorageSettings GetStoreSettings() => allowedComponentSettings; + public StorageSettings GetParentStoreSettings() => parent.def.building.fixedStorageSettings; + public void Notify_SettingsChanged() { } + public bool StorageTabVisible => true; + + + // ===================== Core Logic ===================== + public override void CompTick() + { + base.CompTick(); + + if (!parent.Spawned) return; + + if (state == MaintenancePodState.Running) + { + if (PowerOn) + { + ticksRemaining--; + if (ticksRemaining <= 0) + { + CycleFinished(); + } + } + } + + // Update power consumption based on state + if (powerComp != null) + { + powerComp.PowerOutput = - (state == MaintenancePodState.Running ? Props.powerConsumptionRunning : Props.powerConsumptionIdle); + } + } + + public void StartCycle(Pawn pawn) + { + float required = RequiredComponents(pawn); + if (storedComponents < required) + { + Log.Error($"[WulaFallenEmpire] Tried to start maintenance cycle for {pawn.LabelShort} without enough components. This should have been checked earlier."); + return; + } + + storedComponents -= required; + state = MaintenancePodState.Running; + ticksRemaining = Props.durationTicks; + + // Move pawn inside + pawn.DeSpawn(); + innerContainer.TryAdd(pawn, true); + } + + private void CycleFinished() + { + Pawn occupant = Occupant; + if (occupant == null) + { + Log.Error("[WulaFallenEmpire] Maintenance cycle finished, but no one was inside."); + state = MaintenancePodState.Idle; + return; + } + + // Apply effects + if (Props.hediffToRemove != null) + { + Hediff hediff = occupant.health.hediffSet.GetFirstHediffOfDef(Props.hediffToRemove); + if (hediff != null) + { + occupant.health.RemoveHediff(hediff); + Messages.Message("WULA_MaintenanceComplete".Translate(occupant.Named("PAWN")), occupant, MessageTypeDefOf.PositiveEvent); + } + } + + EjectPawn(); + } + + public void EjectPawn() + { + Pawn occupant = Occupant; + if (occupant != null) + { + GenPlace.TryPlaceThing(occupant, parent.InteractionCell, parent.Map, ThingPlaceMode.Near); + if (Props.exitSound != null) + { + Props.exitSound.PlayOneShot(new TargetInfo(parent.Position, parent.Map)); + } + } + innerContainer.Clear(); + state = MaintenancePodState.Idle; + } + + public void AddComponents(Thing components) + { + int count = components.stackCount; + storedComponents += count; + components.Destroy(); + } + + // ===================== UI & Gizmos ===================== + public override string CompInspectStringExtra() + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine("WULA_MaintenancePod_Status".Translate() + ": " + $"WULA_MaintenancePod_State_{state}".Translate()); + + if (state == MaintenancePodState.Running) + { + sb.AppendLine("Contains".Translate() + ": " + Occupant.NameShortColored.Resolve()); + sb.AppendLine("TimeLeft".Translate() + ": " + ticksRemaining.ToStringTicksToPeriod()); + } + + sb.AppendLine("WULA_MaintenancePod_StoredComponents".Translate() + ": " + storedComponents.ToString("F0")); + + if (!PowerOn) + { + sb.AppendLine("NoPower".Translate().Colorize(Color.red)); + } + + return sb.ToString().TrimEnd(); + } + + public override IEnumerable CompGetGizmosExtra() + { + // Gizmo to order a pawn to enter + if (state == MaintenancePodState.Idle && PowerOn) + { + var enterCommand = new Command_Action + { + defaultLabel = "WULA_MaintenancePod_Enter".Translate(), + defaultDesc = "WULA_MaintenancePod_EnterDesc".Translate(), + icon = EnterIcon, + action = () => + { + List options = new List(); + foreach (Pawn p in parent.Map.mapPawns.FreeColonists) + { + if (p.health.hediffSet.HasHediff(Props.hediffToRemove)) + { + float required = RequiredComponents(p); + if (storedComponents >= required) + { + options.Add(new FloatMenuOption(p.LabelShort, () => + { + // TODO: Create and assign job + Messages.Message("This needs a JobDriver.", MessageTypeDefOf.RejectInput); + })); + } + else + { + options.Add(new FloatMenuOption(p.LabelShort + " (" + "WULA_MaintenancePod_NotEnoughComponents".Translate(required.ToString("F0")) + ")", null)); + } + } + } + if (options.Any()) + { + Find.WindowStack.Add(new FloatMenu(options)); + } + else + { + Messages.Message("WULA_MaintenancePod_NoOneNeeds".Translate(), MessageTypeDefOf.RejectInput); + } + } + }; + yield return enterCommand; + } + + // Gizmo to cancel and eject + if (state == MaintenancePodState.Running) + { + var cancelCommand = new Command_Action + { + defaultLabel = "CommandCancelConstructionLabel".Translate(), + defaultDesc = "WULA_MaintenancePod_CancelDesc".Translate(), + icon = CancelIcon, + action = () => + { + EjectPawn(); + Messages.Message("WULA_MaintenanceCanceled".Translate(), MessageTypeDefOf.NegativeEvent); + } + }; + yield return cancelCommand; + } + } + } + + public enum MaintenancePodState + { + Idle, // Waiting for a pawn or components + Running, // Occupied and performing maintenance + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/EventSystem/Condition.cs b/Source/WulaFallenEmpire/EventSystem/Condition.cs index ba791517..064877f6 100644 --- a/Source/WulaFallenEmpire/EventSystem/Condition.cs +++ b/Source/WulaFallenEmpire/EventSystem/Condition.cs @@ -151,4 +151,28 @@ namespace WulaFallenEmpire return met; } } +public class Condition_FactionExists : Condition + { + public FactionDef factionDef; + + public override bool IsMet(out string reason) + { + if (factionDef == null) + { + reason = "FactionDef not specified in Condition_FactionExists."; + return false; + } + + bool exists = Find.FactionManager.FirstFactionOfDef(factionDef) != null; + if (!exists) + { + reason = $"Faction '{factionDef.label}' does not exist in the world."; + } + else + { + reason = ""; + } + return exists; + } + } } diff --git a/Source/WulaFallenEmpire/HediffComp_MaintenanceNeed.cs b/Source/WulaFallenEmpire/HediffComp_MaintenanceNeed.cs new file mode 100644 index 00000000..72cc6722 --- /dev/null +++ b/Source/WulaFallenEmpire/HediffComp_MaintenanceNeed.cs @@ -0,0 +1,40 @@ +using Verse; + +namespace WulaFallenEmpire +{ + public class HediffCompProperties_MaintenanceNeed : HediffCompProperties + { + public float severityPerDayBeforeThreshold = 0.0f; + public float severityPerDayAfterThreshold = 0.0f; + public float thresholdDays = 0.0f; + + public HediffCompProperties_MaintenanceNeed() + { + compClass = typeof(HediffComp_MaintenanceNeed); + } + } + + public class HediffComp_MaintenanceNeed : HediffComp + { + private HediffCompProperties_MaintenanceNeed Props => (HediffCompProperties_MaintenanceNeed)props; + + public override void CompPostTick(ref float severityAdjustment) + { + base.CompPostTick(ref severityAdjustment); + + // We adjust severity once per game day (60000 ticks) + if (parent.ageTicks % 60000 == 0) + { + float ageInDays = (float)parent.ageTicks / 60000f; + if (ageInDays < Props.thresholdDays) + { + severityAdjustment += Props.severityPerDayBeforeThreshold; + } + else + { + severityAdjustment += Props.severityPerDayAfterThreshold; + } + } + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/JobDriver_EnterMaintenancePod.cs b/Source/WulaFallenEmpire/JobDriver_EnterMaintenancePod.cs new file mode 100644 index 00000000..20dc257f --- /dev/null +++ b/Source/WulaFallenEmpire/JobDriver_EnterMaintenancePod.cs @@ -0,0 +1,42 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class JobDriver_EnterMaintenancePod : JobDriver + { + private const TargetIndex PodIndex = TargetIndex.A; + + protected Thing Pod => job.GetTarget(PodIndex).Thing; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + return pawn.Reserve(Pod, job, 1, -1, null, errorOnFailed); + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(PodIndex); + this.FailOnBurningImmobile(PodIndex); + + var podComp = Pod.TryGetComp(); + this.FailOn(() => podComp == null || podComp.State != MaintenancePodState.Idle || !podComp.PowerOn); + + // Go to the pod's interaction cell + yield return Toils_Goto.GotoThing(PodIndex, PathEndMode.InteractionCell); + + // Enter the pod + yield return new Toil + { + initAction = () => + { + podComp.StartCycle(pawn); + }, + defaultCompleteMode = ToilCompleteMode.Instant + }; + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/JobDriver_LoadComponents.cs b/Source/WulaFallenEmpire/JobDriver_LoadComponents.cs new file mode 100644 index 00000000..8dbfbd38 --- /dev/null +++ b/Source/WulaFallenEmpire/JobDriver_LoadComponents.cs @@ -0,0 +1,53 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class JobDriver_LoadComponents : JobDriver + { + private const TargetIndex PodIndex = TargetIndex.A; + private const TargetIndex ComponentIndex = TargetIndex.B; + + protected Thing Pod => job.GetTarget(PodIndex).Thing; + protected Thing Component => job.GetTarget(ComponentIndex).Thing; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + if (pawn.Reserve(Pod, job, 1, -1, null, errorOnFailed)) + { + return pawn.Reserve(Component, job, 1, -1, null, errorOnFailed); + } + return false; + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(PodIndex); + this.FailOnBurningImmobile(PodIndex); + + var podComp = Pod.TryGetComp(); + this.FailOn(() => podComp == null || podComp.State != MaintenancePodState.Idle); + + // Go and get the components + yield return Toils_Goto.GotoThing(ComponentIndex, PathEndMode.OnCell).FailOnSomeonePhysicallyInteracting(ComponentIndex); + yield return Toils_Haul.StartCarryThing(ComponentIndex); + + // Carry them to the pod + yield return Toils_Goto.GotoThing(PodIndex, PathEndMode.InteractionCell); + + // Load the components + yield return Toils_General.WaitWith(60, TargetIndex.A, true, true, false, PodIndex); + yield return new Toil + { + initAction = () => + { + podComp.AddComponents(this.GetActor().carryTracker.CarriedThing); + }, + defaultCompleteMode = ToilCompleteMode.Instant + }; + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/Job_Maintenance.cs b/Source/WulaFallenEmpire/Job_Maintenance.cs new file mode 100644 index 00000000..160c7a5b --- /dev/null +++ b/Source/WulaFallenEmpire/Job_Maintenance.cs @@ -0,0 +1,25 @@ +using RimWorld; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class JobDriver_EnterMaintenancePod : JobDriver_EnterBiosculpterPod + { + } + + public class WorkGiver_DoMaintenance : WorkGiver_Scanner + { + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WULA_MaintenancePod")); + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + return pawn.CanReserve(t, 1, -1, null, forced); + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + return JobMaker.MakeJob(DefDatabase.GetNamed("WULA_EnterMaintenancePod"), t); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WorkGiver_EnterMaintenancePod.cs b/Source/WulaFallenEmpire/WorkGiver_EnterMaintenancePod.cs new file mode 100644 index 00000000..7966c1fa --- /dev/null +++ b/Source/WulaFallenEmpire/WorkGiver_EnterMaintenancePod.cs @@ -0,0 +1,62 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class WorkGiver_EnterMaintenancePod : WorkGiver_Scanner + { + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WULA_MaintenancePod")); + + public override PathEndMode PathEndMode => PathEndMode.InteractionCell; + + // This method now checks the severity of the hediff. + public override bool ShouldSkip(Pawn pawn, bool forced = false) + { + var podDef = ThingDef.Named("WULA_MaintenancePod"); + var podProps = podDef.GetCompProperties(); + if (podProps?.hediffToRemove == null) return true; + + Hediff hediff = pawn.health.hediffSet.GetFirstHediffOfDef(podProps.hediffToRemove); + + // Skip if no hediff or if severity is below the configured threshold. + if (hediff == null || hediff.Severity < podProps.minSeverityToMaintain) + { + return true; + } + + return false; + } + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!(t is Building building) || !building.Spawned || building.IsForbidden(pawn) || !pawn.CanReserve(building, 1, -1, null, forced)) + { + return false; + } + + var podComp = building.GetComp(); + if (podComp == null || podComp.State != MaintenancePodState.Idle || !podComp.PowerOn) + { + return false; + } + + float requiredComponents = podComp.RequiredComponents(pawn); + if (podComp.storedComponents < requiredComponents) + { + JobFailReason.Is("WULA_MaintenancePod_NotEnoughComponents".Translate(requiredComponents.ToString("F0"))); + return false; + } + + return true; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + return JobMaker.MakeJob(JobDefOf.WULA_EnterMaintenancePod, t); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WorkGiver_LoadComponents.cs b/Source/WulaFallenEmpire/WorkGiver_LoadComponents.cs new file mode 100644 index 00000000..e823a16e --- /dev/null +++ b/Source/WulaFallenEmpire/WorkGiver_LoadComponents.cs @@ -0,0 +1,66 @@ +using RimWorld; +using System; +using System.Collections.Generic; +using System.Linq; +using Verse; +using Verse.AI; + +namespace WulaFallenEmpire +{ + public class WorkGiver_LoadComponents : WorkGiver_Scanner + { + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WULA_MaintenancePod")); + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + if (!(t is Building building) || !building.Spawned || building.IsForbidden(pawn) || !pawn.CanReserve(building, 1, -1, null, forced)) + { + return false; + } + + var podComp = building.GetComp(); + if (podComp == null || podComp.State != MaintenancePodState.Idle) + { + return false; + } + + // We define a "needed" threshold. Let's say we want to keep at least 10 components stocked. + // This prevents pawns from hauling one component at a time. + const int desiredStockpile = 10; + if (podComp.storedComponents >= desiredStockpile) + { + return false; + } + + if (FindBestComponent(pawn, podComp) == null) + { + JobFailReason.Is("WULA_NoComponentsToLoad".Translate()); + return false; + } + + return true; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + var podComp = t.GetComp(); + Thing component = FindBestComponent(pawn, podComp); + if (component == null) + { + return null; + } + return JobMaker.MakeJob(JobDefOf.WULA_LoadComponentsToMaintenancePod, t, component); + } + + private Thing FindBestComponent(Pawn pawn, CompMaintenancePod pod) + { + ThingDef componentDef = pod.Props.componentDef; + if (componentDef == null) return null; + + Predicate validator = (Thing x) => !x.IsForbidden(pawn) && pawn.CanReserve(x); + return GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, ThingRequest.ForDef(componentDef), PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, validator); + } + } +} \ No newline at end of file diff --git a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj index 06dfecae..f3ae8ec9 100644 --- a/Source/WulaFallenEmpire/WulaFallenEmpire.csproj +++ b/Source/WulaFallenEmpire/WulaFallenEmpire.csproj @@ -113,7 +113,7 @@ - + @@ -138,6 +138,9 @@ + + +