Files
ArachnaeSwarm/Source/ArachnaeSwarm/ARA_TrainingWork/JobClean/WorkGiver_ArachnaeClean.cs
2025-09-05 13:53:55 +08:00

99 lines
3.5 KiB
C#

using System.Collections.Generic;
using Verse;
using Verse.AI;
using RimWorld;
namespace ArachnaeSwarm
{
public class WorkGiver_ArachnaeClean : WorkGiver_Scanner
{
private const int MinTicksSinceThickened = 600;
public override PathEndMode PathEndMode => PathEndMode.Touch;
// --- Filth Cleaning Logic ---
public Thing FindClosestFilth(Pawn pawn)
{
return GenClosest.ClosestThing_Global(
pawn.Position,
pawn.Map.listerFilthInHomeArea.FilthInHomeArea,
maxDistance: 9999f,
validator: t => HasJobOnThing(pawn, t)
);
}
public override bool HasJobOnThing(Pawn pawn, Thing t, bool forced = false)
{
if (!(t is Filth filth)) return false;
if (!filth.Map.areaManager.Home[filth.Position]) return false;
if (filth.Fogged() || !pawn.CanReserve(t, 1, -1, null, forced)) return false;
if (filth.TicksSinceThickened < MinTicksSinceThickened) return false;
return true;
}
public override Job JobOnThing(Pawn pawn, Thing t, bool forced = false)
{
Job job = JobMaker.MakeJob(JobDefOf.Clean);
job.AddQueuedTarget(TargetIndex.A, t);
// Simplified multi-clean logic from original WorkGiver_CleanFilth
int num = 15;
for (int i = 0; i < 100; i++)
{
IntVec3 c = t.Position + GenRadial.RadialPattern[i];
if (c.InBounds(pawn.Map))
{
List<Thing> thingList = c.GetThingList(pawn.Map);
foreach(var thing in thingList)
{
if (thing != t && HasJobOnThing(pawn, thing, forced))
{
job.AddQueuedTarget(TargetIndex.A, thing);
}
}
}
if (job.GetTargetQueue(TargetIndex.A).Count >= num) break;
}
return job;
}
// --- Snow Clearing Logic ---
public IntVec3 FindClosestSnow(Pawn pawn)
{
IntVec3 bestCell = IntVec3.Invalid;
float bestDistSq = float.MaxValue;
// Efficiently iterate through the designated snow clear area
foreach (IntVec3 cell in pawn.Map.areaManager.SnowOrSandClear.ActiveCells)
{
// Check for a valid job on the cell first
if (HasJobOnCell(pawn, cell))
{
float distSq = pawn.Position.DistanceToSquared(cell);
if (distSq < bestDistSq && pawn.CanReach(cell, PathEndMode.Touch, Danger.Deadly))
{
bestDistSq = distSq;
bestCell = cell;
}
}
}
return bestCell;
}
public override bool HasJobOnCell(Pawn pawn, IntVec3 c, bool forced = false)
{
// The check for SnowOrSandClear area is implicitly handled by the caller (FindClosestSnow)
// We only need to check the snow depth and reservation status.
if (pawn.Map.snowGrid.GetDepth(c) < 0.2f) return false;
if (!pawn.CanReserve(c, 1, -1, null, forced)) return false;
return true;
}
public override Job JobOnCell(Pawn pawn, IntVec3 c, bool forced = false)
{
return JobMaker.MakeJob(JobDefOf.ClearSnow, c);
}
}
}