Cleaning JobGiver

Started by twoski, October 18, 2018, 01:23:57 PM

Previous topic - Next topic

twoski

I have a simple JobGiver which makes a pawn either haul something to a stockpile, or find the nearest filth and clean it:


namespace RimWorld
{
    public class JobGiver_Compulsion: ThinkNode_JobGiver
    {
        protected bool IgnoreForbid(Pawn pawn)
        {
            return pawn.InMentalState;
        }

        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.jobs.jobQueue.Count > 3 || pawn.CurJobDef == JobDefOf.Clean || pawn.CurJobDef == JobDefOf.HaulToCell || pawn.CurJobDef == JobDefOf.HaulToContainer)
            {
                return null;
            }

            if (Rand.Range(0f, 1f) < 0.5f)
            {
                List<Thing> filth = pawn.Map.listerFilthInHomeArea.FilthInHomeArea;
                Filth t = GetClosestFilth(pawn, filth);

                if (CanClean(pawn, t))
                {
                    LocalTargetInfo lt = new LocalTargetInfo(t);
                    return new Job(JobDefOf.Clean, lt);
                }
            }

            if (Rand.Range(0f, 1f) < 0.5f)
            {
                Predicate<Thing> validator = (Thing t) => !t.IsForbidden(pawn) && HaulAIUtility.PawnCanAutomaticallyHaulFast(pawn, t, true);
                Thing thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, pawn.Map.listerHaulables.ThingsPotentiallyNeedingHauling(), PathEndMode.OnCell, TraverseParms.For(pawn, Danger.Deadly, TraverseMode.ByPawn, false), 9999f, validator, null);

                if (thing != null)
                {
                    return HaulAIUtility.HaulToStorageJob(pawn, thing);
                }
            }

            return null;
        }

        Filth GetClosestFilth(Pawn pawn, List<Thing> filth)
        {
            Thing result = null;
            int minDist = int.MaxValue;

            foreach (Thing t in filth)
            {
                int dist = IntVec3Utility.ManhattanDistanceFlat(pawn.PositionHeld, t.PositionHeld);

                if (dist < minDist)
                {
                    minDist = dist;
                    result = t;
                }
            }

            return result as Filth;
        }

        bool CanClean(Pawn pawn, Thing t)
        {
            Filth filth = t as Filth;

            return filth != null && pawn.Map.areaManager.Home[filth.Position] && pawn.CanReserveAndReach(t, PathEndMode.ClosestTouch, Danger.Deadly, 1);
        }
    }
}


However, it seems that the cleaning job which worked fine in 0.9 does not work fine in 1.0. Maybe something got changed? The hauling job works fine.

Here's what i see when i'm debugging:


25594 Burton: StartJob [Clean (Job_12335) A=Thing_Filth_RubbleRock28550] lastJobEndCondition=None, jobGiver=RimWorld.JobGiver_Compulsion, cancelBusyStances=False

25594 Burton: JobDriver_CleanFilth ends current job Clean (Job_12335) A=Thing_Filth_RubbleRock28550 because of toils[1].endConditions[0]


My decompiler won't show me the toils associated to JobDriver_CleanFilth. Can anyone tell me why the toil is failing?

The pawn clearly has a path to all of the filth in the home area in my test map (and my job giver also verifies that a path is available). So it's not an issue of impossible-to-reach filth. Some other end condition is being met before the pawn can clean the filth.


Iamkriil

The only exit condition I see in JobDriver_CleanFilth is not having anything left to clean.  I've copied the pre toil reservation code and the first few lines of make new toils.  This is the only place I see a success condition and the defaultcompletemode is never.  Perhaps the target queue is not having a job added to it?  Did you consider inheriting from WorkGiver_Scanner instead of ThinkNode_JobGiver or is this supposed to be for a mental state?


public override bool TryMakePreToilReservations(bool errorOnFailed)
{
  this.pawn.ReserveAsManyAsPossible(this.job.GetTargetQueue(TargetIndex.A), this.job, 1, -1, null);
  return true;
}

protected override IEnumerable<Toil> MakeNewToils()
{
  Toil initExtractTargetFromQueue = Toils_JobTransforms.ClearDespawnedNullOrForbiddenQueuedTargets(TargetIndex.A, null);
  yield return initExtractTargetFromQueue;
  yield return Toils_JobTransforms.SucceedOnNoTargetInQueue(TargetIndex.A);

twoski

This is meant to be a mental state.... This code worked fine in 0.9, the 1.0 update caused it to stop working. I assume maybe the cleaning jobs were altered in the 1.0 update?