This commit is contained in:
2025-08-09 00:57:04 +08:00
parent 8d4fa0f7b8
commit 80fa9f84b3
6 changed files with 188 additions and 22 deletions

Binary file not shown.

View File

@@ -1,16 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<Defs> <Defs>
<JobDef>
<defName>WULA_IngestWulaEnergy</defName>
<driverClass>WulaFallenEmpire.JobDriver_IngestWulaEnergy</driverClass>
<reportString>正在摄取能量。</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef>
<JobDef> <JobDef>
<defName>WULA_FeedWulaPatient</defName> <defName>WULA_HaulToMaintenancePod</defName>
<driverClass>WulaFallenEmpire.JobDriver_FeedWulaPatient</driverClass> <driverClass>WulaFallenEmpire.JobDriver_HaulToMaintenancePod</driverClass>
<reportString>正在喂食能量核心。</reportString> <reportString>hauling TargetA to TargetB.</reportString>
<allowOpportunisticPrefix>true</allowOpportunisticPrefix> <allowOpportunisticPrefix>true</allowOpportunisticPrefix>
</JobDef> </JobDef>
</Defs> </Defs>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<Defs>
<WorkGiverDef>
<defName>WULA_HaulToMaintenancePod</defName>
<label>haul to maintenance pod</label>
<giverClass>WulaFallenEmpire.WorkGiver_HaulToMaintenancePod</giverClass>
<workType>Hauling</workType>
<priorityInType>20</priorityInType>
<verb>haul</verb>
<gerund>hauling</gerund>
<requiredCapacities>
<li>Manipulation</li>
</requiredCapacities>
</WorkGiverDef>
</Defs>

View File

@@ -32,12 +32,14 @@ namespace WulaFallenEmpire
} }
[StaticConstructorOnStartup] [StaticConstructorOnStartup]
public class CompMaintenancePod : ThingComp, IThingHolder public class CompMaintenancePod : ThingComp, IThingHolder, IStoreSettingsParent
{ {
// ===================== Fields ===================== // ===================== Fields =====================
private ThingOwner innerContainer; private ThingOwner innerContainer;
private CompPowerTrader powerComp; private CompPowerTrader powerComp;
private CompRefuelable refuelableComp; private StorageSettings allowedComponentSettings;
public float storedComponents = 0f;
public int capacity = 50; // Let's define a capacity
private int ticksRemaining; private int ticksRemaining;
private MaintenancePodState state = MaintenancePodState.Idle; private MaintenancePodState state = MaintenancePodState.Idle;
@@ -57,6 +59,8 @@ namespace WulaFallenEmpire
return Props.baseComponentCost + (int)(hediff.Severity * Props.componentCostPerSeverity); return Props.baseComponentCost + (int)(hediff.Severity * Props.componentCostPerSeverity);
} }
public bool CanAcceptComponents(int count) => storedComponents + count <= capacity;
// ===================== Setup ===================== // ===================== Setup =====================
public CompMaintenancePod() public CompMaintenancePod()
{ {
@@ -64,19 +68,31 @@ namespace WulaFallenEmpire
} }
public override void Initialize(CompProperties props)
{
base.Initialize(props);
allowedComponentSettings = new StorageSettings(this);
if (Props.componentDef != null)
{
allowedComponentSettings.filter = new ThingFilter();
allowedComponentSettings.filter.SetAllow(Props.componentDef, true);
}
}
public override void PostSpawnSetup(bool respawningAfterLoad) public override void PostSpawnSetup(bool respawningAfterLoad)
{ {
base.PostSpawnSetup(respawningAfterLoad); base.PostSpawnSetup(respawningAfterLoad);
powerComp = parent.TryGetComp<CompPowerTrader>(); powerComp = parent.TryGetComp<CompPowerTrader>();
refuelableComp = parent.TryGetComp<CompRefuelable>();
} }
public override void PostExposeData() public override void PostExposeData()
{ {
base.PostExposeData(); base.PostExposeData();
Scribe_Values.Look(ref state, "state", MaintenancePodState.Idle); Scribe_Values.Look(ref state, "state", MaintenancePodState.Idle);
Scribe_Values.Look(ref storedComponents, "storedComponents", 0f);
Scribe_Values.Look(ref ticksRemaining, "ticksRemaining", 0); Scribe_Values.Look(ref ticksRemaining, "ticksRemaining", 0);
Scribe_Deep.Look(ref innerContainer, "innerContainer", this); Scribe_Deep.Look(ref innerContainer, "innerContainer", this);
Scribe_Deep.Look(ref allowedComponentSettings, "allowedComponentSettings", this);
} }
// ===================== IThingHolder Implementation ===================== // ===================== IThingHolder Implementation =====================
@@ -90,6 +106,12 @@ namespace WulaFallenEmpire
return innerContainer; return innerContainer;
} }
// ===================== IStoreSettingsParent Implementation =====================
public StorageSettings GetStoreSettings() => allowedComponentSettings;
public StorageSettings GetParentStoreSettings() => null; // No parent settings
public void Notify_SettingsChanged() { }
public bool StorageTabVisible => false; // We show it in the inspect string
// ===================== Core Logic ===================== // ===================== Core Logic =====================
public override void CompTick() public override void CompTick()
{ {
@@ -119,13 +141,13 @@ namespace WulaFallenEmpire
public void StartCycle(Pawn pawn) public void StartCycle(Pawn pawn)
{ {
float required = RequiredComponents(pawn); float required = RequiredComponents(pawn);
if (refuelableComp == null || refuelableComp.Fuel < required) if (storedComponents < required)
{ {
Log.Error($"[WulaFallenEmpire] Tried to start maintenance cycle for {pawn.LabelShort} without enough components. This should have been checked earlier."); Log.Error($"[WulaFallenEmpire] Tried to start maintenance cycle for {pawn.LabelShort} without enough components. This should have been checked earlier.");
return; return;
} }
refuelableComp.ConsumeFuel(required); storedComponents -= required;
state = MaintenancePodState.Running; state = MaintenancePodState.Running;
ticksRemaining = Props.durationTicks; ticksRemaining = Props.durationTicks;
@@ -174,6 +196,13 @@ namespace WulaFallenEmpire
} }
public void AddComponents(Thing components)
{
int count = components.stackCount;
storedComponents += count;
components.Destroy();
}
// ===================== UI & Gizmos ===================== // ===================== UI & Gizmos =====================
public override string CompInspectStringExtra() public override string CompInspectStringExtra()
{ {
@@ -186,10 +215,7 @@ namespace WulaFallenEmpire
sb.AppendLine("TimeLeft".Translate() + ": " + ticksRemaining.ToStringTicksToPeriod()); sb.AppendLine("TimeLeft".Translate() + ": " + ticksRemaining.ToStringTicksToPeriod());
} }
if (refuelableComp != null) sb.AppendLine("WULA_MaintenancePod_StoredComponents".Translate() + ": " + storedComponents.ToString("F0") + " / " + capacity.ToString("F0"));
{
sb.AppendLine("WULA_MaintenancePod_StoredComponents".Translate() + ": " + refuelableComp.Fuel.ToString("F0") + " / " + refuelableComp.Props.fuelCapacity.ToString("F0"));
}
if (!PowerOn) if (!PowerOn)
{ {
@@ -217,7 +243,7 @@ namespace WulaFallenEmpire
if (p.health.hediffSet.HasHediff(Props.hediffToRemove)) if (p.health.hediffSet.HasHediff(Props.hediffToRemove))
{ {
float required = RequiredComponents(p); float required = RequiredComponents(p);
if (refuelableComp != null && refuelableComp.Fuel >= required) if (storedComponents >= required)
{ {
options.Add(new FloatMenuOption(p.LabelShort, () => options.Add(new FloatMenuOption(p.LabelShort, () =>
{ {

View File

@@ -0,0 +1,57 @@
using RimWorld;
using System;
using System.Collections.Generic;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class JobDriver_HaulToMaintenancePod : JobDriver
{
private const TargetIndex ComponentInd = TargetIndex.A;
private const TargetIndex PodInd = TargetIndex.B;
protected Thing Component => job.GetTarget(ComponentInd).Thing;
protected Building_Storage Pod => (Building_Storage)job.GetTarget(PodInd).Thing;
public override bool TryMakePreToilReservations(bool errorOnFailed)
{
return pawn.Reserve(Component, job, 1, -1, null, errorOnFailed) && pawn.Reserve(Pod, job, 1, -1, null, errorOnFailed);
}
protected override IEnumerable<Toil> MakeNewToils()
{
this.FailOnDespawnedNullOrForbidden(PodInd);
this.FailOnBurningImmobile(PodInd);
yield return Toils_Goto.GotoThing(ComponentInd, PathEndMode.ClosestTouch)
.FailOnSomeonePhysicallyInteracting(ComponentInd);
yield return Toils_Haul.StartCarryThing(ComponentInd, false, true, false)
.FailOnDestroyedNullOrForbidden(ComponentInd);
yield return Toils_Goto.GotoThing(PodInd, PathEndMode.Touch);
Toil findPlaceAndDrop = new Toil();
findPlaceAndDrop.initAction = delegate
{
Pawn actor = findPlaceAndDrop.actor;
Job curJob = actor.jobs.curJob;
Thing carriedThing = curJob.GetTarget(ComponentInd).Thing;
CompMaintenancePod podComp = curJob.GetTarget(PodInd).Thing.TryGetComp<CompMaintenancePod>();
if (podComp != null)
{
podComp.AddComponents(carriedThing);
}
else
{
// Fallback if something goes wrong, just drop it near the pod
actor.carryTracker.TryDropCarriedThing(Pod.Position, ThingPlaceMode.Near, out Thing _);
}
};
yield return findPlaceAndDrop;
}
}
}

View File

@@ -0,0 +1,71 @@
using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;
using Verse.AI;
namespace WulaFallenEmpire
{
public class WorkGiver_HaulToMaintenancePod : WorkGiver_Scanner
{
public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForDef(ThingDefOf_WULA.WULA_MaintenancePod);
public override PathEndMode PathEndMode => PathEndMode.Touch;
public override Danger MaxPathDanger(Pawn pawn) => Danger.Deadly;
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (!(t is Building building) || building.IsForbidden(pawn) || !pawn.CanReserve(building, 1, -1, null, forced))
{
return false;
}
CompMaintenancePod comp = building.GetComp<CompMaintenancePod>();
if (comp == null || comp.State != MaintenancePodState.Idle)
{
return false;
}
// Check if it needs more components
if (comp.storedComponents >= comp.capacity)
{
return false;
}
if (FindBestComponent(pawn, comp) == null)
{
JobFailReason.Is("WULA_NoComponentsToHaul".Translate());
return false;
}
return true;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
Building building = (Building)t;
CompMaintenancePod comp = building.GetComp<CompMaintenancePod>();
Thing component = FindBestComponent(pawn, comp);
if (component == null)
{
return null;
}
Job job = JobMaker.MakeJob(JobDefOf_WULA.WULA_HaulToMaintenancePod, component, t);
job.count = Math.Min(component.stackCount, (int)(comp.capacity - comp.storedComponents));
return job;
}
private Thing FindBestComponent(Pawn pawn, CompMaintenancePod podComp)
{
ThingFilter filter = podComp.GetStoreSettings().filter;
Predicate<Thing> validator = (Thing x) => !x.IsForbidden(pawn) && pawn.CanReserve(x) && filter.Allows(x);
return GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, filter.BestThingRequest, PathEndMode.ClosestTouch, TraverseParms.For(pawn), 9999f, validator);
}
}
}