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 @@
+
+
+