Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interrupt work when schedule changes #189

Open
svenddpc opened this issue Sep 14, 2021 · 1 comment
Open

Interrupt work when schedule changes #189

svenddpc opened this issue Sep 14, 2021 · 1 comment

Comments

@svenddpc
Copy link

I'm not sure if it's correct/OK/good to post this here. It might be more of a help/discussion post that an actuall feature, as it might not be possible to implement as part of this mod... feel free to close/delete if it doesn't fit here :)

Problem description

When I set up very specific schedules, for instance research from 8-10 and then scanning 10-12, by pawn will often continue researching for up to an hour after the schedule has changed (in the example until around 11).

Describe the solution

The solution (if one exists) would make sure a job is cancelled/interrupted (if it's cancellable without a loss, like researching is, as opposed to butchering an animal, cooking) if the schedule no longer allows/prioritieses that job.

Alternatives

I'm not really sure how else to achieve the goal... I guess if it's consistent that the pawn will research for around an hour after the schedule has expired, one could simply set the schedule for researching to finish an hour before you'd want them to start another task, but I presume that it depends on some sort of "work chunk" under the hood that determines how often the pawn will check if it should find something else to do...

If it's not possible to do, because it's all defined in the research specific core code, would it at least be possible to do in custom work types / jobs? I'm not sure how to achieve that either. Would it for instance be possible to add a FailOn to ones own job's toil, that would fail the task if it's no longer in the pawns schedule? ... I'm not sure how one would check that...

Additional materials

@svenddpc
Copy link
Author

For now, and as an example of what I mean, I have made it work for my own JobDrivers. I've added this class (with the two private mehtods copied from JobDriver_Work):

using RimWorld;
using Verse;
using Verse.AI;

namespace WorkTab.Teaching
{
    public static class PriorityUtils
    {
        public static bool IsWorkGiverStillPriority(Pawn pawn, WorkGiver currentWorkGiver)
        {
            ThinkResult thinkResult = DetermineNextJob(pawn, out ThinkTreeDef thinkTree);
            Log.Message($"New next job for {pawn.LabelShort} determined to be {thinkResult.Job}");
            return thinkResult.Job.workGiverDef == currentWorkGiver.def;
        }

        private static ThinkResult DetermineNextJob(Pawn pawn, out ThinkTreeDef thinkTree)
        {
            ThinkResult constantThinkTreeJob = DetermineNextConstantThinkTreeJob(pawn);
            if (constantThinkTreeJob.Job != null)
            {
                thinkTree = pawn.thinker.ConstantThinkTree;
                return constantThinkTreeJob;
            }
            ThinkResult thinkResult;
            try
            {
                thinkResult = pawn.thinker.MainThinkNodeRoot.TryIssueJobPackage(pawn, new JobIssueParams());
            }
            catch (Exception ex)
            {
                JobUtility.TryStartErrorRecoverJob(pawn, pawn.ToStringSafe() + " threw exception while determining job (main)", ex);
                thinkTree = null;
                return ThinkResult.NoJob;
            }

            thinkTree = pawn.thinker.MainThinkTree;
            return thinkResult;
        }

        private static ThinkResult DetermineNextConstantThinkTreeJob(Pawn pawn)
        {
            if (pawn.thinker.ConstantThinkTree == null)
                return ThinkResult.NoJob;
            try
            {
                return pawn.thinker.ConstantThinkNodeRoot.TryIssueJobPackage(pawn, new JobIssueParams());
            }
            catch (Exception ex)
            {
                JobUtility.TryStartErrorRecoverJob(pawn, pawn.ToStringSafe() + " threw exception while determining job (constant)", ex);
            }

            return ThinkResult.NoJob;
        }

    }
}

It's not pretty, and it doesn't work for Researching, as I have to add a call to IsWorkGiverStillPriority as a FailOn callback in my JobDriver's MakeNewToils() method... but it works for me :) ... do you think something like that could somehow be incorporated/patched into the existing jobs so they would follow the scheduling more closely? I just imagine that would be nice for all people using the mod :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant