This commit is contained in:
2025-07-22 19:07:21 +08:00
parent 4f524845a9
commit 15494e8a8e
26 changed files with 318 additions and 963 deletions

View File

@@ -1,111 +1,61 @@
using RimWorld;
using Verse;
using Verse.AI;
using System.Linq;
namespace WulaFallenEmpire
{
public class WorkGiver_Warden_FeedWula : WorkGiver_Scanner
public class WorkGiver_Warden_FeedWula : WorkGiver_Warden
{
private WorkGiverDefExtension_FeedWula ext;
private WorkGiverDefExtension_FeedWula Ext
{
get
{
if (ext == null)
{
ext = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
}
return ext;
}
}
public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDef.Named("WulaSpecies"));
public override PathEndMode PathEndMode => PathEndMode.ClosestTouch;
public override Danger MaxPathDanger(Pawn pawn) => Danger.Deadly;
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
Pawn prisoner = t as Pawn;
// Basic validation, similar to vanilla's WorkGiver_Warden_Feed
if (prisoner == null || prisoner == pawn || !prisoner.IsPrisonerOfColony || !prisoner.guest.CanBeBroughtFood)
{
return false;
}
// Our custom check: Is the Wula in shutdown?
Need_WulaEnergy energyNeed = prisoner.needs.TryGetNeed<Need_WulaEnergy>();
if (energyNeed == null || !energyNeed.IsShutdown)
{
return false;
}
// Vanilla check: Is the prisoner unable to feed themselves?
if (!WardenFeedUtility.ShouldBeFed(prisoner))
{
return false;
}
// CRITICAL vanilla check: Can the warden reserve the prisoner?
if (!pawn.CanReserve(prisoner, 1, -1, null, forced))
{
return false;
}
// Check for our energy source
if (Ext == null || Ext.energySourceDef == null)
{
Log.ErrorOnce("WorkGiver_Warden_FeedWula is missing the DefModExtension with a valid energySourceDef.", def.GetHashCode());
return false;
}
if (!FindBestEnergySourceFor(pawn, prisoner, out _, out _))
{
JobFailReason.Is("NoFood".Translate());
return false;
}
return true;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
Pawn prisoner = (Pawn)t;
if (FindBestEnergySourceFor(pawn, prisoner, out Thing energySource, out _))
if (!(t is Pawn prisoner) || !ShouldFeed(pawn, prisoner))
{
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_FeedWulaPatient"), energySource, prisoner);
job.count = 1;
return job;
return null;
}
return null;
Need_WulaEnergy energyNeed = prisoner.needs.TryGetNeed<Need_WulaEnergy>();
var extension = def.GetModExtension<WorkGiverDefExtension_FeedWula>();
if (energyNeed == null || energyNeed.CurLevelPercentage >= extension.feedThreshold)
{
return null;
}
if (prisoner.health.hediffSet.HasHediff(DefDatabase<HediffDef>.GetNamed("WULA_ChargingHediff")))
{
return null;
}
if (!TryFindBestEnergySourceFor(pawn, prisoner, out Thing energySource, out _))
{
return null;
}
Job job = JobMaker.MakeJob(DefDatabase<JobDef>.GetNamed("WULA_FeedWulaPatient"), energySource, prisoner);
job.count = 1;
return job;
}
private bool FindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing foodSource, out ThingDef foodDef)
private bool ShouldFeed(Pawn warden, Pawn prisoner)
{
foodSource = null;
foodDef = null;
return prisoner.IsPrisonerOfColony && prisoner.guest.CanBeBroughtFood && prisoner.needs.TryGetNeed<Need_WulaEnergy>() != null;
}
if (Ext == null || Ext.energySourceDef == null)
private bool TryFindBestEnergySourceFor(Pawn getter, Pawn eater, out Thing energySource, out ThingDef energyDef)
{
energySource = null;
energyDef = null;
var allowedThings = getter.Map.listerThings.ThingsInGroup(ThingRequestGroup.HaulableEver)
.Where(x => x.def.GetModExtension<ThingDefExtension_EnergySource>() != null);
Thing thing = GenClosest.ClosestThing_Global(eater.Position, allowedThings, 99999f,
t => t.IngestibleNow && !t.IsForbidden(getter) && getter.CanReserve(t));
if (thing != null)
{
return false;
}
foodSource = GenClosest.ClosestThingReachable(
getter.Position,
getter.Map,
ThingRequest.ForDef(Ext.energySourceDef),
PathEndMode.OnCell,
TraverseParms.For(getter),
9999f,
(Thing x) => !x.IsForbidden(getter) && getter.CanReserve(x)
);
if (foodSource != null)
{
foodDef = foodSource.def;
energySource = thing;
energyDef = thing.def;
return true;
}