diff --git a/1.6/1.6/Assemblies/ArachnaeSwarm.dll b/1.6/1.6/Assemblies/ArachnaeSwarm.dll index 8456ad8..334b1df 100644 Binary files a/1.6/1.6/Assemblies/ArachnaeSwarm.dll and b/1.6/1.6/Assemblies/ArachnaeSwarm.dll differ diff --git a/1.6/1.6/Defs/JobDefs/ARA_Jobs_Nutrition.xml b/1.6/1.6/Defs/JobDefs/ARA_Jobs_Nutrition.xml new file mode 100644 index 0000000..bef6bf4 --- /dev/null +++ b/1.6/1.6/Defs/JobDefs/ARA_Jobs_Nutrition.xml @@ -0,0 +1,11 @@ + + + + + ARA_Refuel_Nutrition + ArachnaeSwarm.JobDriver_Refuel_Nutrition + 正在为 TargetA 补充营养。 + true + + + \ No newline at end of file diff --git a/1.6/1.6/Defs/WorkGiverDefs/ARA_WorkGivers.xml b/1.6/1.6/Defs/WorkGiverDefs/ARA_WorkGivers.xml new file mode 100644 index 0000000..725e3a7 --- /dev/null +++ b/1.6/1.6/Defs/WorkGiverDefs/ARA_WorkGivers.xml @@ -0,0 +1,14 @@ + + + + ARA_Refuel_Nutrition + + ArachnaeSwarm.WorkGiver_Refuel_Nutrition + Hauling + 60 + 补充 + 补充 + true + false + + \ No newline at end of file diff --git a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj index 6b46fbc..7a9606b 100644 --- a/Source/ArachnaeSwarm/ArachnaeSwarm.csproj +++ b/Source/ArachnaeSwarm/ArachnaeSwarm.csproj @@ -146,6 +146,8 @@ + + diff --git a/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs b/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs index 3d0283c..e9e153f 100644 --- a/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs +++ b/Source/ArachnaeSwarm/Building_Comps/CompRefuelableNutrition.cs @@ -63,10 +63,7 @@ namespace ArachnaeSwarm fuelNeeded = TargetFuelLevel - Fuel; } - if (totalNutritionGained > 0 && Props.fuelGizmoLabel != null) - { - Messages.Message("MessageRefueled".Translate(parent.LabelShort, totalNutritionGained.ToString("0.##"), Props.fuelGizmoLabel), parent, MessageTypeDefOf.PositiveEvent); - } + // Let the job driver handle the message. This component should only handle logic. } public void ReceiveFuel(float amount) diff --git a/Source/ArachnaeSwarm/Jobs/JobDriver_Refuel_Nutrition.cs b/Source/ArachnaeSwarm/Jobs/JobDriver_Refuel_Nutrition.cs new file mode 100644 index 0000000..f048094 --- /dev/null +++ b/Source/ArachnaeSwarm/Jobs/JobDriver_Refuel_Nutrition.cs @@ -0,0 +1,88 @@ +using System.Collections.Generic; +using RimWorld; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + public class JobDriver_Refuel_Nutrition : JobDriver + { + private const TargetIndex RefuelableInd = TargetIndex.A; + private const TargetIndex FuelInd = TargetIndex.B; + private const int RefuelingDuration = 240; + + protected Thing Refuelable => job.GetTarget(RefuelableInd).Thing; + + // --- KEY CHANGE HERE --- + // We specifically target CompRefuelableNutrition and its children. + protected CompRefuelableNutrition RefuelableComp => Refuelable.TryGetComp(); + + protected Thing Fuel => job.GetTarget(FuelInd).Thing; + + public override bool TryMakePreToilReservations(bool errorOnFailed) + { + if (pawn.Reserve(Refuelable, job, 1, -1, null, errorOnFailed)) + { + return pawn.Reserve(Fuel, job, 1, -1, null, errorOnFailed); + } + return false; + } + + protected override IEnumerable MakeNewToils() + { + this.FailOnDespawnedNullOrForbidden(RefuelableInd); + AddEndCondition(() => !RefuelableComp.IsFull ? JobCondition.Ongoing : JobCondition.Succeeded); + AddFailCondition(() => !job.playerForced && !RefuelableComp.ShouldAutoRefuelNowIgnoringFuelPct); + AddFailCondition(() => !RefuelableComp.allowAutoRefuel && !job.playerForced); + + yield return Toils_General.DoAtomic(delegate + { + job.count = RefuelableComp.GetFuelCountToFullyRefuel(); + }); + + Toil reserveFuel = Toils_Reserve.Reserve(FuelInd); + yield return reserveFuel; + yield return Toils_Goto.GotoThing(FuelInd, PathEndMode.ClosestTouch) + .FailOnDespawnedNullOrForbidden(FuelInd) + .FailOnSomeonePhysicallyInteracting(FuelInd); + yield return Toils_Haul.StartCarryThing(FuelInd, putRemainderInQueue: false, subtractNumTakenFromJobCount: true) + .FailOnDestroyedNullOrForbidden(FuelInd); + yield return Toils_Haul.CheckForGetOpportunityDuplicate(reserveFuel, FuelInd, TargetIndex.None, takeFromValidStorage: true); + yield return Toils_Goto.GotoThing(RefuelableInd, PathEndMode.Touch); + yield return Toils_General.Wait(RefuelingDuration) + .FailOnDestroyedNullOrForbidden(FuelInd) + .FailOnDestroyedNullOrForbidden(RefuelableInd) + .FailOnCannotTouch(RefuelableInd, PathEndMode.Touch) + .WithProgressBarToilDelay(RefuelableInd); + + // Use our custom Refuel toil for CompRefuelableNutrition + yield return FinalizeRefueling_Nutrition(); + } + + // Custom Finalize Toil that uses the specific Refuel method from CompRefuelableNutrition + public Toil FinalizeRefueling_Nutrition() + { + Toil toil = new Toil(); + toil.initAction = delegate() + { + Pawn actor = toil.GetActor(); + Job curJob = actor.jobs.curJob; + Thing refuelableThing = curJob.GetTarget(RefuelableInd).Thing; + CompRefuelableNutrition refuelableComp = refuelableThing.TryGetComp(); + + if (actor.carryTracker.CarriedThing == null) + { + Log.Error(actor + " is not carrying anything to refuel with."); + // The correct way to end the job from within a Toil's action. + actor.jobs.EndCurrentJob(JobCondition.Incompletable); + return; + } + + // Call the specific Refuel method from our custom component + refuelableComp.Refuel(new List { actor.carryTracker.CarriedThing }); + }; + toil.defaultCompleteMode = ToilCompleteMode.Instant; + return toil; + } + } +} \ No newline at end of file diff --git a/Source/ArachnaeSwarm/WorkGivers/WorkGiver_Refuel_Nutrition.cs b/Source/ArachnaeSwarm/WorkGivers/WorkGiver_Refuel_Nutrition.cs new file mode 100644 index 0000000..215efd5 --- /dev/null +++ b/Source/ArachnaeSwarm/WorkGivers/WorkGiver_Refuel_Nutrition.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Linq; +using RimWorld; +using Verse; +using Verse.AI; + +namespace ArachnaeSwarm +{ + public class WorkGiver_Refuel_Nutrition : WorkGiver_Scanner + { + public override ThingRequest PotentialWorkThingRequest => ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial); + + public override PathEndMode PathEndMode => PathEndMode.Touch; + + public override IEnumerable PotentialWorkThingsGlobal(Pawn pawn) + { + // Find all buildings that have our special component. + return pawn.Map.listerBuildings.allBuildingsColonist.Where(b => + b.GetComp() != null); + } + + public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false) + { + var building = t as Building; + if (building == null) return false; + + // --- KEY CHANGE HERE --- + // Target the specific nutrition component + var refuelableComp = building.GetComp(); + if (refuelableComp == null || refuelableComp.IsFull) return false; + + if (!refuelableComp.ShouldAutoRefuelNow && !forced) return false; + + if (building.IsForbidden(pawn) || !pawn.CanReserve(building, 1, -1, null, forced)) return false; + + var fuel = FindBestFuel(pawn, refuelableComp); + if (fuel == null) + { + JobFailReason.Is("NoFuelToRefuel".Translate(refuelableComp.Props.fuelFilter.Summary)); + return false; + } + + return true; + } + + public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false) + { + var building = t as Building; + var refuelableComp = building.GetComp(); + var fuel = FindBestFuel(pawn, refuelableComp); + + // Return our custom Job + return new Job(DefDatabase.GetNamed("ARA_Refuel_Nutrition"), building, fuel); + } + + private Thing FindBestFuel(Pawn pawn, CompRefuelable refuelable) + { + var fuelFilter = refuelable.Props.fuelFilter; + return GenClosest.ClosestThingReachable( + pawn.Position, + pawn.Map, + ThingRequest.ForGroup(ThingRequestGroup.HaulableEver), + PathEndMode.ClosestTouch, + TraverseParms.For(pawn), + 9999f, + thing => !thing.IsForbidden(pawn) && fuelFilter.Allows(thing) && pawn.CanReserve(thing) + ); + } + } +} \ No newline at end of file