99 lines
3.5 KiB
C#
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);
|
|
}
|
|
}
|
|
} |