Ejemplo n.º 1
0
 public static bool TryGiveJobFromJoyGiverDefDirect(JobGiver_Work __instance, ref Job __result, JoyGiverDef def, Pawn pawn)
 {
     pawnx    = pawn;
     defx     = def;
     __result = defx.Worker.TryGiveJob(pawnx);
     return(false);
 }
Ejemplo n.º 2
0
        private static Job GiverTryGiveJobPrioritized(JobGiver_Work __instance, Pawn pawn, WorkGiver giver, IntVec3 cell)
        {
            if (!__instance.PawnCanUseWorkGiver(pawn, giver))
            {
                return(null);
            }
            try
            {
                Job job = giver.NonScanJob(pawn);
                if (job != null)
                {
                    return(job);
                }
                WorkGiver_Scanner scanner = giver as WorkGiver_Scanner;
                if (scanner != null)
                {
                    if (giver.def.scanThings)
                    {
                        Predicate <Thing> predicate;
                        if (scanner is WorkGiver_DoBill workGiver_DoBill)
                        {
                            predicate = (Thing t) => !t.IsForbidden(pawn) && WorkGiver_Scanner_Patch.HasJobOnThing(workGiver_DoBill, pawn, t);
                        }
                        else
                        {
                            predicate = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t);
                        }

                        List <Thing> thingList = cell.GetThingList(pawn.Map);
                        for (int i = 0; i < thingList.Count; i++)
                        {
                            Thing thing = thingList[i];
                            if (scanner.PotentialWorkThingRequest.Accepts(thing) && predicate(thing))
                            {
                                Job job2 = scanner.JobOnThing(pawn, thing);
                                if (job2 != null)
                                {
                                    job2.workGiverDef = giver.def;
                                }
                                return(job2);
                            }
                        }
                    }
                    if (giver.def.scanCells && !cell.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, cell))
                    {
                        Job job3 = scanner.JobOnCell(pawn, cell);
                        if (job3 != null)
                        {
                            job3.workGiverDef = giver.def;
                        }
                        return(job3);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(string.Concat(pawn, " threw exception in GiverTryGiveJobTargeted on WorkGiver ", giver.def.defName, ": ", ex.ToString()));
            }
            return(null);
        }
Ejemplo n.º 3
0
 private static bool Prefix(JobGiver_Work __instance, Pawn pawn, ref ThinkResult __result)
 {
     if (!Active)
     {
         return(true);
     }
     __result = Detour(__instance, pawn);
     return(false);
 }
Ejemplo n.º 4
0
        public void Notify_WorkPriorityDisabled(WorkTypeDef wType)
        {
            JobGiver_Work jobGiver_Work = this.lastJobGiver as JobGiver_Work;

            if (jobGiver_Work != null && this.lastGivenWorkType == wType)
            {
                this.pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, true);
            }
        }
Ejemplo n.º 5
0
        private static ThinkResult Detour(JobGiver_Work __instance, Pawn pawn)
        {
            if (__instance.emergency && pawn.mindState.priorityWork.IsPrioritized)

            {
                var workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
                for (var i = 0; i < workGiversByPriority.Count; i++)
                {
                    var worker = workGiversByPriority[i].Worker;
                    var job    = __instance.GiverTryGiveJobPrioritized(pawn, worker, pawn.mindState.priorityWork.Cell);
                    if (job != null)
                    {
                        job.playerForced = true;
                        return(new ThinkResult(job, __instance, workGiversByPriority[i].tagToGive));
                    }
                }

                pawn.mindState.priorityWork.Clear();
            }

            var list = __instance.emergency
                ? pawn.workSettings.WorkGiversInOrderEmergency
                : pawn.workSettings.WorkGiversInOrderNormal;

            var num = -999;
            var bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            var coo = list.Count;

            for (var j = 0; j < coo; j++)
            {
                var workGiver = list[j];

                string namer()
                {
                    var daffy = string.Empty;

                    if (ByWorkType)
                    {
                        daffy = workGiver.def?.workType?.defName;
                    }
                    else
                    {
                        daffy =
                            $"{workGiver.def?.defName} - {workGiver.def?.workType.defName} - {workGiver.def?.modContentPack?.Name}";
                    }

                    //if (true)
                    //{
                    //    daffy += $" - { TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)).ToString()} - {pawn.Name.ToStringShort}";
                    //}

                    if (RequestTypes && workGiver is WorkGiver_Scanner scan)
                    {
                        daffy += $" - {scan.PotentialWorkThingRequest}";
                        if (scan.PotentialWorkThingRequest.group ==
                            ThingRequestGroup.BuildingArtificial)
                        {
                            daffy += " VERY BAD!";
                        }
                    }

                    return(daffy);
                }

                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }

                if (__instance.PawnCanUseWorkGiver(pawn, workGiver))
                {
                    var name = string.Empty;

                    if (ByWorkType)
                    {
                        name = workGiver.def.workType.defName;
                    }
                    else
                    {
                        name = workGiver.def.defName;
                    }

                    //if (true)
                    //{
                    //    name = string.Intern(name + pawn.Name.ToStringShort);
                    //}
                    if (workGiver is WorkGiver_Scanner scanny)
                    {
                        name += $"{scanny.PotentialWorkThingRequest}";
                    }


                    try
                    {
                        var job2 = workGiver.NonScanJob(pawn);
                        if (job2 != null)
                        {
                            return(new ThinkResult(job2, __instance, list[j].def.tagToGive));
                        }



                        if (workGiver is WorkGiver_Scanner scanner)
                        {
                            Analyzer.Start(name, namer, workGiver.GetType(), workGiver.def, pawn);

                            if (scanner.def.scanThings)
                            {
                                bool Predicate(Thing t)
                                {
                                    return(!t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t));
                                }

                                var   enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                                Thing thing;
                                if (scanner.Prioritized)
                                {
                                    var enumerable2 = enumerable;
                                    if (enumerable2 == null)
                                    {
                                        enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }

                                    if (scanner.AllowUnreachable)
                                    {
                                        thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, Predicate, x => scanner.GetPriority(pawn, x));
                                    }
                                    else
                                    {
                                        var traverseParams = TraverseParms.For(pawn, scanner.MaxPathDanger(pawn));
                                        var validator      = (Predicate <Thing>)Predicate;
                                        thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map,
                                                                                         enumerable2,
                                                                                         scanner.PathEndMode, traverseParams, 9999f, validator,
                                                                                         x => scanner.GetPriority(pawn, x));
                                    }
                                }
                                else if (scanner.AllowUnreachable)
                                {
                                    var enumerable3 = enumerable;
                                    if (enumerable3 == null)
                                    {
                                        enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }

                                    thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, Predicate);
                                }
                                else
                                {
                                    giver = workGiver;
                                    key   = name;
                                    Analyzer.Start(name, namer, workGiver.GetType(), workGiver.def, pawn);
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                                             scanner.PotentialWorkThingRequest,
                                                                             scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)),
                                                                             9999f, Predicate, enumerable, 0,
                                                                             scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);

                                    giver = null;
                                }

                                if (thing != null)
                                {
                                    bestTargetOfLastPriority = thing;
                                    scannerWhoProvidedTarget = scanner;
                                }
                            }



                            if (scanner.def.scanCells)
                            {
                                var closestDistSquared = 99999f;
                                var bestPriority       = float.MinValue;
                                var prioritized        = scanner.Prioritized;
                                var allowUnreachable   = scanner.AllowUnreachable;
                                var maxDanger          = scanner.MaxPathDanger(pawn);
                                foreach (var intVec in scanner.PotentialWorkCellsGlobal(pawn))
                                {
                                    var flag = false;
                                    var num4 = (intVec - pawn.Position).LengthHorizontalSquared;
                                    var num5 = 0f;
                                    if (prioritized)
                                    {
                                        if (!intVec.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, intVec))
                                        {
                                            if (!allowUnreachable &&
                                                !pawn.CanReach(intVec, scanner.PathEndMode, maxDanger))
                                            {
                                                continue;
                                            }

                                            num5 = scanner.GetPriority(pawn, intVec);
                                            if (num5 > bestPriority || num5 == bestPriority && num4 < closestDistSquared)
                                            {
                                                flag = true;
                                            }
                                        }
                                    }
                                    else if (num4 < closestDistSquared && !intVec.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, intVec))
                                    {
                                        if (!allowUnreachable && !pawn.CanReach(intVec, scanner.PathEndMode, maxDanger))
                                        {
                                            continue;
                                        }

                                        flag = true;
                                    }

                                    if (flag)
                                    {
                                        bestTargetOfLastPriority = new TargetInfo(intVec, pawn.Map);
                                        scannerWhoProvidedTarget = scanner;
                                        closestDistSquared       = num4;
                                        bestPriority             = num5;
                                    }
                                }
                            }


                            Analyzer.Stop(name);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ",
                                                ex.ToString()));
                    }

                    if (bestTargetOfLastPriority.IsValid)
                    {
                        //  pawn.mindState.lastGivenWorkType = workGiver.def.workType;
                        Job job3;
                        if (bestTargetOfLastPriority.HasThing)
                        {
                            job3 = scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                        }
                        else
                        {
                            job3 = scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell);
                        }

                        if (job3 != null)
                        {
                            job3.workGiverDef = scannerWhoProvidedTarget.def;
                            return(new ThinkResult(job3, __instance, list[j].def.tagToGive));
                        }

                        Log.ErrorOnce(
                            string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority,
                                          " but yielded no actual job for pawn ", pawn,
                                          ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    }

                    num = workGiver.def.priorityInType;
                }
            }

            return(ThinkResult.NoJob);
        }
Ejemplo n.º 6
0
        internal static void AddUndraftedOrders(Vector3 clickPos, Pawn pawn, List <FloatMenuOption> opts)
        {
            IntVec3 clickCell = IntVec3.FromVector3(clickPos);
            bool    flag      = false;
            bool    flag2     = false;

            foreach (Thing current in Find.ThingGrid.ThingsAt(clickCell))
            {
                flag2 = true;
                if (pawn.CanReach(current, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn))
                {
                    flag = true;
                    break;
                }
            }
            if (flag2 && !flag)
            {
                opts.Add(new FloatMenuOption("(" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null, 0f, null));
                return;
            }
            JobGiver_Work jobGiver_Work = pawn.thinker.TryGetMainTreeThinkNode <JobGiver_Work>();

            if (jobGiver_Work != null)
            {
                foreach (Thing current2 in Find.ThingGrid.ThingsAt(clickCell))
                {
                    Pawn pawn2 = Find.Reservations.FirstReserverOf(current2, pawn.Faction, true);
                    if (pawn2 != null && pawn2 != pawn)
                    {
                        opts.Add(new FloatMenuOption("IsReservedBy".Translate(new object[]
                        {
                            current2.LabelShort.CapitalizeFirst(),
                            pawn2.LabelShort
                        }), null, MenuOptionPriority.Medium, null, null, 0f, null));
                    }
                    else
                    {
                        foreach (WorkTypeDef current3 in DefDatabase <WorkTypeDef> .AllDefsListForReading)
                        {
                            for (int i = 0; i < current3.workGiversByPriority.Count; i++)
                            {
                                WorkGiver_Scanner workGiver_Scanner = current3.workGiversByPriority[i].Worker as WorkGiver_Scanner;
                                if (workGiver_Scanner != null && workGiver_Scanner.def.directOrderable && !workGiver_Scanner.ShouldSkip(pawn))
                                {
                                    JobFailReason.Clear();
                                    if (workGiver_Scanner.PotentialWorkThingRequest.Accepts(current2) || (workGiver_Scanner.PotentialWorkThingsGlobal(pawn) != null && workGiver_Scanner.PotentialWorkThingsGlobal(pawn).Contains(current2)))
                                    {
                                        Job job;
                                        if (!workGiver_Scanner.HasJobOnThingForced(pawn, current2))
                                        {
                                            job = null;
                                        }
                                        else
                                        {
                                            job = workGiver_Scanner.JobOnThingForced(pawn, current2);
                                        }
                                        if (job == null)
                                        {
                                            if (JobFailReason.HaveReason)
                                            {
                                                string label3 = "CannotGenericWork".Translate(new object[]
                                                {
                                                    workGiver_Scanner.def.verb,
                                                    current2.LabelShort
                                                }) + " (" + JobFailReason.Reason + ")";
                                                opts.Add(new FloatMenuOption(label3, null, MenuOptionPriority.Medium, null, null, 0f, null));
                                            }
                                        }
                                        else
                                        {
                                            WorkTypeDef     workType        = workGiver_Scanner.def.workType;
                                            Action          action          = null;
                                            PawnCapacityDef pawnCapacityDef = workGiver_Scanner.MissingRequiredCapacity(pawn);
                                            string          label;
                                            if (pawnCapacityDef != null)
                                            {
                                                label = "CannotMissingHealthActivities".Translate(new object[]
                                                {
                                                    pawnCapacityDef.label
                                                });
                                            }
                                            else if (pawn.jobs.curJob != null && pawn.jobs.curJob.JobIsSameAs(job))
                                            {
                                                label = "CannotGenericAlreadyAm".Translate(new object[]
                                                {
                                                    workType.gerundLabel,
                                                    current2.LabelShort
                                                });
                                            }
                                            else if (pawn.workSettings.GetPriority(workType) == 0)
                                            {
                                                label = "CannotPrioritizeIsNotA".Translate(new object[]
                                                {
                                                    pawn.NameStringShort,
                                                    workType.pawnLabel
                                                });
                                            }
                                            else if (job.def == JobDefOf.Research && current2 is Building_ResearchBench)
                                            {
                                                label = "CannotPrioritizeResearch".Translate();
                                            }
                                            else if (current2.IsForbidden(pawn))
                                            {
                                                if (!current2.Position.InAllowedArea(pawn))
                                                {
                                                    label = "CannotPrioritizeForbiddenOutsideAllowedArea".Translate(new object[]
                                                    {
                                                        current2.Label
                                                    });
                                                }
                                                else
                                                {
                                                    label = "CannotPrioritizeForbidden".Translate(new object[]
                                                    {
                                                        current2.Label
                                                    });
                                                }
                                            }
                                            else if (!pawn.CanReach(current2, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn))
                                            {
                                                label = current2.Label + ": " + "NoPath".Translate();
                                            }
                                            else
                                            {
                                                label = "PrioritizeGeneric".Translate(new object[]
                                                {
                                                    workGiver_Scanner.def.gerund,
                                                    current2.Label
                                                });
                                                Job localJob = job;
                                                WorkGiver_Scanner localScanner = workGiver_Scanner;
                                                action = delegate
                                                {
                                                    pawn.thinker.GetMainTreeThinkNode <JobGiver_Work>().TryStartPrioritizedWorkOn(pawn, localJob, localScanner, clickCell);
                                                };
                                            }
                                            if (!opts.Any((FloatMenuOption op) => op.Label == label.TrimEnd(new char[0])))
                                            {
                                                opts.Add(new FloatMenuOption(label, action, MenuOptionPriority.Medium, null, null, 0f, null));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                Pawn pawn3 = Find.Reservations.FirstReserverOf(clickCell, pawn.Faction, true);
                if (pawn3 != null && pawn3 != pawn)
                {
                    opts.Add(new FloatMenuOption("IsReservedBy".Translate(new object[]
                    {
                        "AreaLower".Translate(),
                        pawn3.LabelShort
                    }).CapitalizeFirst(), null, MenuOptionPriority.Medium, null, null, 0f, null));
                }
                else
                {
                    foreach (WorkTypeDef current4 in DefDatabase <WorkTypeDef> .AllDefsListForReading)
                    {
                        for (int j = 0; j < current4.workGiversByPriority.Count; j++)
                        {
                            WorkGiver_Scanner workGiver_Scanner2 = current4.workGiversByPriority[j].Worker as WorkGiver_Scanner;
                            if (workGiver_Scanner2 != null && workGiver_Scanner2.def.directOrderable && !workGiver_Scanner2.ShouldSkip(pawn))
                            {
                                JobFailReason.Clear();
                                if (workGiver_Scanner2.PotentialWorkCellsGlobal(pawn).Contains(clickCell))
                                {
                                    Job job2;
                                    if (!workGiver_Scanner2.HasJobOnCell(pawn, clickCell))
                                    {
                                        job2 = null;
                                    }
                                    else
                                    {
                                        job2 = workGiver_Scanner2.JobOnCell(pawn, clickCell);
                                    }
                                    if (job2 == null)
                                    {
                                        if (JobFailReason.HaveReason)
                                        {
                                            string label2 = "CannotGenericWork".Translate(new object[]
                                            {
                                                workGiver_Scanner2.def.verb,
                                                "AreaLower".Translate()
                                            }) + " (" + JobFailReason.Reason + ")";
                                            opts.Add(new FloatMenuOption(label2, null, MenuOptionPriority.Medium, null, null, 0f, null));
                                        }
                                    }
                                    else
                                    {
                                        WorkTypeDef     workType2        = workGiver_Scanner2.def.workType;
                                        Action          action2          = null;
                                        PawnCapacityDef pawnCapacityDef2 = workGiver_Scanner2.MissingRequiredCapacity(pawn);
                                        string          label;
                                        if (pawnCapacityDef2 != null)
                                        {
                                            label = "CannotMissingHealthActivities".Translate(new object[]
                                            {
                                                pawnCapacityDef2.label
                                            });
                                        }
                                        else if (pawn.jobs.curJob != null && pawn.jobs.curJob.JobIsSameAs(job2))
                                        {
                                            label = "CannotGenericAlreadyAm".Translate(new object[]
                                            {
                                                workType2.gerundLabel,
                                                "AreaLower".Translate()
                                            });
                                        }
                                        else if (pawn.workSettings.GetPriority(workType2) == 0)
                                        {
                                            label = "CannotPrioritizeIsNotA".Translate(new object[]
                                            {
                                                pawn.NameStringShort,
                                                workType2.pawnLabel
                                            });
                                        }
                                        else if (!pawn.CanReach(clickCell, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn))
                                        {
                                            label = "AreaLower".Translate().CapitalizeFirst() + ": " + "NoPath".Translate();
                                        }
                                        else
                                        {
                                            label = "PrioritizeGeneric".Translate(new object[]
                                            {
                                                workGiver_Scanner2.def.gerund,
                                                "AreaLower".Translate()
                                            });
                                            Job localJob = job2;
                                            WorkGiver_Scanner localScanner = workGiver_Scanner2;
                                            action2 = delegate
                                            {
                                                pawn.thinker.GetMainTreeThinkNode <JobGiver_Work>().TryStartPrioritizedWorkOn(pawn, localJob, localScanner, clickCell);
                                            };
                                        }
                                        if (!opts.Any((FloatMenuOption op) => op.Label == label.TrimEnd(new char[0])))
                                        {
                                            opts.Add(new FloatMenuOption(label, action2, MenuOptionPriority.Medium, null, null, 0f, null));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 7
0
        private static ThinkResult Detour(JobGiver_Work __instance, Pawn pawn)
        {
            if (__instance.emergency && pawn.mindState.priorityWork.IsPrioritized)
            {
                List <WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
                for (int i = 0; i < workGiversByPriority.Count; i++)
                {
                    WorkGiver worker = workGiversByPriority[i].Worker;
                    int       refire = 0;
                    try
                    {
                        refire = refires[worker.def];
                    }
                    catch (Exception)
                    {
                        refires.Add(worker.def, 0);
                    }
                    if (refire > 0)
                    {
                        continue;
                    }


                    Job job = __instance.GiverTryGiveJobPrioritized(pawn, worker, pawn.mindState.priorityWork.Cell);
                    if (job != null)
                    {
                        job.playerForced = true;

                        return(new ThinkResult(job, __instance, workGiversByPriority[i].tagToGive));
                    }
                    refires[worker.def] = refireLength;
                }

                pawn.mindState.priorityWork.Clear();
            }

            List <WorkGiver> list = __instance.emergency ? pawn.workSettings.WorkGiversInOrderEmergency : pawn.workSettings.WorkGiversInOrderNormal;

            int               num = -999;
            TargetInfo        bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            int               coo = list.Count;

            Profiler prof = null;

            for (int j = 0; j < coo; j++)
            {
                WorkGiver workGiver = list[j];
                int       refire    = 0;
                try
                {
                    refire = refires[workGiver.def];
                }
                catch (Exception)
                {
                    refires.Add(workGiver.def, 0);
                }
                if (refire > 0)
                {
                    continue;
                }

                if (!H_TryIssueJobPackageTrans.meths.TryGetValue(workGiver, out var meth))
                {
                    if (workGiver is WorkGiver_Scanner)
                    {
                        if (workGiver.def.scanThings)
                        {
                            meth = AccessTools.Method(workGiver.GetType(), "PotentialWorkThingsGlobal");
                        }
                        else
                        {
                            meth = AccessTools.Method(workGiver.GetType(), "PotentialWorkCellsGlobal");
                        }
                    }
                    else
                    {
                        meth = AccessTools.Method(workGiver.GetType(), "NonScanJob");
                    }
                    H_TryIssueJobPackageTrans.meths.Add(workGiver, meth);
                }

                string namer()
                {
                    string daffy = string.Empty;

                    if (ByWorkType)
                    {
                        daffy = workGiver.def?.workType?.defName;
                    }
                    else
                    {
                        daffy = $"{workGiver.def?.defName} - {workGiver.def?.workType.defName} - {workGiver.def?.modContentPack?.Name}";
                    }

                    if (RequestTypes && workGiver is WorkGiver_Scanner scan)
                    {
                        daffy += $" - {scan.PotentialWorkThingRequest}";
                        if (scan.PotentialWorkThingRequest.group ==
                            ThingRequestGroup.BuildingArtificial)
                        {
                            daffy += " VERY BAD!";
                        }
                    }

                    return(daffy);
                }

                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }

                if (__instance.PawnCanUseWorkGiver(pawn, workGiver))
                {
                    string name = string.Empty;

                    if (ByWorkType)
                    {
                        name = workGiver.def.workType.defName;
                    }
                    else
                    {
                        name = workGiver.def.defName;
                    }

                    //if (true)
                    //{
                    //    name = string.Intern(name + pawn.Name.ToStringShort);
                    //}
                    if (workGiver is WorkGiver_Scanner scanny)
                    {
                        name += $"{scanny.PotentialWorkThingRequest}";
                    }

                    try
                    {
                        prof = ProfileController.Start(name, namer, workGiver.GetType(), workGiver.def, pawn, meth);
                        Job job2 = workGiver.NonScanJob(pawn);
                        prof.Stop();

                        if (job2 != null)
                        {
                            return(new ThinkResult(job2, __instance, list[j].def.tagToGive));
                        }

                        if (workGiver is WorkGiver_Scanner scanner)
                        {
                            if (scanner.def.scanThings)
                            {
                                bool Predicate(Thing t)
                                {
                                    return(!t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t));
                                }
                                prof = ProfileController.Start(name, namer, workGiver.GetType(), workGiver.def, pawn, meth);
                                IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn)?.Where(x => scanner.HasJobOnThing(pawn, x));

                                //if (scanner is WorkGiver_Repair repair)
                                //{
                                //    foreach (var repairableBuilding in pawn.Map.listerBuildingsRepairable.RepairableBuildings(pawn.Faction))
                                //    {
                                //        Log.Warning($"repair scan on {repairableBuilding}");
                                //    }
                                //}

                                Thing thing;
                                if (scanner.Prioritized)
                                {
                                    IEnumerable <Thing> enumerable2 = enumerable;
                                    if (enumerable2 == null)
                                    {
                                        enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }

                                    if (scanner.AllowUnreachable)
                                    {
                                        thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, Predicate, x => scanner.GetPriority(pawn, x));
                                    }
                                    else
                                    {
                                        TraverseParms traverseParams = TraverseParms.For(pawn, scanner.MaxPathDanger(pawn));
                                        // var validator = (Predicate<Thing>)Predicate;
                                        thing = GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map,
                                                                                         enumerable2,
                                                                                         scanner.PathEndMode, traverseParams, 9999f, Predicate,
                                                                                         x => scanner.GetPriority(pawn, x));
                                    }
                                }
                                else if (scanner.AllowUnreachable)
                                {
                                    IEnumerable <Thing> enumerable3 = enumerable;
                                    if (enumerable3 == null)
                                    {
                                        enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                    }

                                    thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, Predicate);
                                }
                                else
                                {
                                    giver = workGiver;
                                    key   = name;

                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map,
                                                                             scanner.PotentialWorkThingRequest,
                                                                             scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)),
                                                                             9999f, Predicate, enumerable, 0,
                                                                             scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);

                                    giver = null;
                                }

                                prof.Stop();

                                if (thing != null)
                                {
                                    bestTargetOfLastPriority = thing;
                                    scannerWhoProvidedTarget = scanner;
                                }
                            }


                            if (scanner.def.scanCells)
                            {
                                prof = ProfileController.Start(name, namer, workGiver.GetType(), workGiver.def, pawn, meth);
                                float  closestDistSquared = 99999f;
                                float  bestPriority       = float.MinValue;
                                bool   prioritized        = scanner.Prioritized;
                                bool   allowUnreachable   = scanner.AllowUnreachable;
                                Danger maxDanger          = scanner.MaxPathDanger(pawn);
                                foreach (IntVec3 intVec in scanner.PotentialWorkCellsGlobal(pawn))
                                {
                                    bool  flag = false;
                                    int   num4 = (intVec - pawn.Position).LengthHorizontalSquared;
                                    float num5 = 0f;
                                    if (prioritized)
                                    {
                                        if (!intVec.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, intVec))
                                        {
                                            if (!allowUnreachable &&
                                                !pawn.CanReach(intVec, scanner.PathEndMode, maxDanger))
                                            {
                                                goto jamalam;
                                            }

                                            num5 = scanner.GetPriority(pawn, intVec);
                                            if (num5 > bestPriority || num5 == bestPriority && num4 < closestDistSquared)
                                            {
                                                flag = true;
                                            }
                                        }
                                    }
                                    else if (num4 < closestDistSquared && !intVec.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, intVec))
                                    {
                                        if (!allowUnreachable && !pawn.CanReach(intVec, scanner.PathEndMode, maxDanger))
                                        {
                                            goto jamalam;
                                        }

                                        flag = true;
                                    }

                                    if (flag)
                                    {
                                        bestTargetOfLastPriority = new TargetInfo(intVec, pawn.Map);
                                        scannerWhoProvidedTarget = scanner;
                                        closestDistSquared       = num4;
                                        bestPriority             = num5;
                                    }
                                }
                                prof.Stop();
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ",
                                                ex.ToString()));
                    }

                    if (bestTargetOfLastPriority.IsValid)
                    {
                        //  pawn.mindState.lastGivenWorkType = workGiver.def.workType;
                        prof = ProfileController.Start(name, namer, workGiver.GetType(), workGiver.def, pawn, meth);
                        Job job3;
                        if (bestTargetOfLastPriority.HasThing)
                        {
                            job3 = scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                        }
                        else
                        {
                            job3 = scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell);
                        }
                        prof.Stop();
                        if (job3 != null)
                        {
                            job3.workGiverDef = scannerWhoProvidedTarget.def;
                            return(new ThinkResult(job3, __instance, list[j].def.tagToGive));
                        }

                        Log.ErrorOnce(
                            string.Concat("Analyzer: ", scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority,
                                          " but yielded no actual job for pawn ", pawn,
                                          ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    }


                    num = workGiver.def.priorityInType;
                }

jamalam:
                refires[workGiver.def] = refireLength;
            }

            return(ThinkResult.NoJob);
        }
Ejemplo n.º 8
0
        internal static List <FloatMenuOption> ChoicesAtFor(Vector3 clickPos, Pawn pawn)
        {
            IntVec3 clickCell = IntVec3.FromVector3(clickPos);

            DangerUtility.NotifyDirectOrderingThisFrame(pawn);
            List <FloatMenuOption> list = new List <FloatMenuOption>();

            if (!clickCell.InBounds())
            {
                return(list);
            }

            // ***** Beginning of drafted options *****

            if (pawn.Drafted)
            {
                foreach (TargetInfo attackTarg in GenUI.TargetsAt(clickPos, TargetingParameters.ForAttackHostile(), true))
                {
                    // *** Fire at option ***

                    if (pawn.equipment.Primary != null && !pawn.equipment.PrimaryEq.PrimaryVerb.verbProps.MeleeRange)
                    {
                        string str;
                        Action rangedAct = FloatMenuUtility.GetRangedAttackAction(pawn, attackTarg, out str);
                        string text      = "FireAt".Translate(new object[]
                        {
                            attackTarg.Thing.LabelCap
                        });
                        FloatMenuOption floatMenuOption = new FloatMenuOption();
                        floatMenuOption.priority = MenuOptionPriority.High;
                        if (rangedAct == null)
                        {
                            text = text + " (" + str + ")";
                        }
                        else
                        {
                            floatMenuOption.autoTakeable = true;
                            floatMenuOption.action       = new Action(delegate
                            {
                                MoteThrower.ThrowStatic(attackTarg.Thing.DrawPos, ThingDefOf.Mote_FeedbackAttack, 1f);
                                rangedAct();
                            });
                        }
                        floatMenuOption.label = text;
                        list.Add(floatMenuOption);
                    }

                    // *** Melee attack option ***

                    string str2;
                    Action meleeAct = FloatMenuUtility.GetMeleeAttackAction(pawn, attackTarg, out str2);
                    Pawn   pawn2    = attackTarg.Thing as Pawn;
                    string text2;
                    if (pawn2 != null && pawn2.Downed)
                    {
                        text2 = "MeleeAttackToDeath".Translate(new object[]
                        {
                            attackTarg.Thing.LabelCap
                        });
                    }
                    else
                    {
                        text2 = "MeleeAttack".Translate(new object[]
                        {
                            attackTarg.Thing.LabelCap
                        });
                    }
                    Thing           thing            = attackTarg.Thing;
                    FloatMenuOption floatMenuOption2 = new FloatMenuOption(string.Empty, null, MenuOptionPriority.High, null, thing);
                    if (meleeAct == null)
                    {
                        text2 = text2 + " (" + str2 + ")";
                    }
                    else
                    {
                        floatMenuOption2.action = new Action(delegate
                        {
                            MoteThrower.ThrowStatic(attackTarg.Thing.DrawPos, ThingDefOf.Mote_FeedbackAttack, 1f);
                            meleeAct();
                        });
                    }
                    floatMenuOption2.label = text2;
                    list.Add(floatMenuOption2);
                }

                // *** Arrest option ***

                if (pawn.RaceProps.Humanlike && !pawn.Downed)
                {
                    foreach (TargetInfo current2 in GenUI.TargetsAt(clickPos, TargetingParameters.ForArrest(pawn), true))
                    {
                        TargetInfo dest = current2;
                        if (!pawn.CanReach(dest, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                        {
                            list.Add(new FloatMenuOption("CannotArrest".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null));
                        }
                        else if (!pawn.CanReserve(dest.Thing, 1))
                        {
                            list.Add(new FloatMenuOption("CannotArrest".Translate() + ": " + "Reserved".Translate(), null, MenuOptionPriority.Medium, null, null));
                        }
                        else
                        {
                            Pawn   pTarg  = (Pawn)dest.Thing;
                            Action action = new Action(delegate
                            {
                                Building_Bed building_Bed = RestUtility.FindBedFor(pTarg, pawn, true, false, false);
                                if (building_Bed == null)
                                {
                                    Messages.Message("CannotArrest".Translate() + ": " + "NoPrisonerBed".Translate(), pTarg, MessageSound.RejectInput);
                                    return;
                                }
                                Job job           = new Job(JobDefOf.Arrest, pTarg, building_Bed);
                                job.playerForced  = true;
                                job.maxNumToCarry = 1;
                                pawn.drafter.TakeOrderedJob(job);
                                TutorUtility.DoModalDialogIfNotKnown(ConceptDefOf.ArrestingCreatesEnemies);
                            });
                            List <FloatMenuOption> arg_3F1_0 = list;
                            Thing thing = dest.Thing;
                            arg_3F1_0.Add(new FloatMenuOption("TryToArrest".Translate(new object[]
                            {
                                dest.Thing.LabelCap
                            }), action, MenuOptionPriority.Medium, null, thing));
                        }
                    }
                }

                // *** Goto option ***

                int num = GenRadial.NumCellsInRadius(2.9f);
                for (int i = 0; i < num; i++)
                {
                    IntVec3 curLoc = GenRadial.RadialPattern[i] + clickCell;
                    if (curLoc.Standable())
                    {
                        if (curLoc != pawn.Position)
                        {
                            if (!pawn.CanReach(curLoc, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                            {
                                FloatMenuOption item = new FloatMenuOption("CannotGoNoPath".Translate(), null, MenuOptionPriority.Low, null, null);
                                list.Add(item);
                            }
                            else
                            {
                                Action action2 = new Action(delegate
                                {
                                    IntVec3 dest     = Pawn_DraftController.BestGotoDestNear(curLoc, pawn);
                                    Job job          = new Job(JobDefOf.Goto, dest);
                                    job.playerForced = true;
                                    pawn.drafter.TakeOrderedJob(job);
                                    MoteThrower.ThrowStatic(dest, ThingDefOf.Mote_FeedbackGoto, 1f);
                                });
                                list.Add(new FloatMenuOption("GoHere".Translate(), action2, MenuOptionPriority.Low, null, null)
                                {
                                    autoTakeable = true
                                });
                            }
                        }
                        break;
                    }
                }
            }

            // *** End of drafted options ***

            // *** Beginning of humanlike options ***

            if (pawn.RaceProps.Humanlike)
            {
                int num2 = 0;
                if (pawn.story != null)
                {
                    num2 = pawn.story.traits.DegreeOfTrait(TraitDefOf.DrugDesire);
                }

                // *** Consume option ***

                foreach (Thing current3 in clickCell.GetThingList())
                {
                    Thing t = current3;
                    if (t.def.ingestible != null && pawn.RaceProps.CanEverEat(t) && t.IngestibleNow)
                    {
                        FloatMenuOption item2;
                        if (t.def.ingestible.isPleasureDrug && num2 < 0)
                        {
                            item2 = new FloatMenuOption("ConsumeThing".Translate(new object[]
                            {
                                t.LabelBaseShort
                            }) + " (" + "Teetotaler".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else if (!pawn.CanReach(t, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                        {
                            item2 = new FloatMenuOption("ConsumeThing".Translate(new object[]
                            {
                                t.LabelBaseShort
                            }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else if (!pawn.CanReserve(t, 1))
                        {
                            item2 = new FloatMenuOption("ConsumeThing".Translate(new object[]
                            {
                                t.LabelBaseShort
                            }) + " (" + "ReservedBy".Translate(new object[]
                            {
                                Find.Reservations.FirstReserverOf(t, pawn.Faction).LabelBaseShort
                            }) + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else
                        {
                            item2 = new FloatMenuOption("ConsumeThing".Translate(new object[]
                            {
                                t.LabelBaseShort
                            }), new Action(delegate
                            {
                                t.SetForbidden(false, true);
                                Job job           = new Job(JobDefOf.Ingest, t);
                                job.maxNumToCarry = t.def.ingestible.maxNumToIngestAtOnce;
                                pawn.drafter.TakeOrderedJob(job);
                            }), MenuOptionPriority.Medium, null, null);
                        }
                        list.Add(item2);
                    }
                }

                // *** Rescue/Capture downed option ***

                foreach (TargetInfo current4 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true))
                {
                    Pawn victim = (Pawn)current4.Thing;
                    if (!victim.InBed() && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1) && !victim.IsPrisonerOfColony)
                    {
                        if ((victim.Faction == Faction.OfColony && victim.MentalStateDef == null) || (victim.Faction != Faction.OfColony && victim.MentalStateDef == null && !victim.IsPrisonerOfColony && (victim.Faction == null || !victim.Faction.HostileTo(Faction.OfColony))))
                        {
                            List <FloatMenuOption> arg_8E1_0 = list;
                            Pawn victim2 = victim;
                            arg_8E1_0.Add(new FloatMenuOption("Rescue".Translate(new object[]
                            {
                                victim2.LabelCap
                            }), new Action(delegate
                            {
                                Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, false, false, false);
                                if (building_Bed == null)
                                {
                                    string str;
                                    if (victim.RaceProps.Animal)
                                    {
                                        str = "NoAnimalBed".Translate();
                                    }
                                    else
                                    {
                                        str = "NoNonPrisonerBed".Translate();
                                    }
                                    Messages.Message("CannotRescue".Translate() + ": " + str, victim, MessageSound.RejectInput);
                                    return;
                                }
                                Job job           = new Job(JobDefOf.Rescue, victim, building_Bed);
                                job.maxNumToCarry = 1;
                                job.playerForced  = true;
                                pawn.drafter.TakeOrderedJob(job);
                                ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.Rescuing, KnowledgeAmount.Total);
                            }), MenuOptionPriority.Medium, null, victim2));
                        }
                        if (victim.MentalStateDef != null || (victim.RaceProps.Humanlike && victim.Faction != Faction.OfColony))
                        {
                            List <FloatMenuOption> arg_962_0 = list;
                            Pawn victim2 = victim;
                            arg_962_0.Add(new FloatMenuOption("Capture".Translate(new object[]
                            {
                                victim2.LabelCap
                            }), new Action(delegate
                            {
                                Building_Bed building_Bed = RestUtility.FindBedFor(victim, pawn, true, false, false);
                                if (building_Bed == null)
                                {
                                    Messages.Message("CannotCapture".Translate() + ": " + "NoPrisonerBed".Translate(), victim, MessageSound.RejectInput);
                                    return;
                                }
                                Job job           = new Job(JobDefOf.Capture, victim, building_Bed);
                                job.maxNumToCarry = 1;
                                job.playerForced  = true;
                                pawn.drafter.TakeOrderedJob(job);
                                ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.Capturing, KnowledgeAmount.Total);
                            }), MenuOptionPriority.Medium, null, victim2));
                        }
                    }
                }

                // *** Carry to cryosleep option ***

                foreach (TargetInfo current5 in GenUI.TargetsAt(clickPos, TargetingParameters.ForRescue(pawn), true))
                {
                    TargetInfo targetInfo = current5;
                    Pawn       victim     = (Pawn)targetInfo.Thing;
                    if (victim.Downed && pawn.CanReserveAndReach(victim, PathEndMode.OnCell, Danger.Deadly, 1) && Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn) != null)
                    {
                        string label = "CarryToCryptosleepCasket".Translate(new object[]
                        {
                            targetInfo.Thing.LabelCap
                        });
                        JobDef jDef    = JobDefOf.CarryToCryptosleepCasket;
                        Action action3 = new Action(delegate
                        {
                            Building_CryptosleepCasket building_CryptosleepCasket = Building_CryptosleepCasket.FindCryptosleepCasketFor(victim, pawn);
                            if (building_CryptosleepCasket == null)
                            {
                                Messages.Message("CannotCarryToCryptosleepCasket".Translate() + ": " + "NoCryptosleepCasket".Translate(), victim, MessageSound.RejectInput);
                                return;
                            }
                            Job job           = new Job(jDef, victim, building_CryptosleepCasket);
                            job.maxNumToCarry = 1;
                            job.playerForced  = true;
                            pawn.drafter.TakeOrderedJob(job);
                        });
                        List <FloatMenuOption> arg_A80_0 = list;
                        Pawn victim2 = victim;
                        arg_A80_0.Add(new FloatMenuOption(label, action3, MenuOptionPriority.Medium, null, victim2));
                    }
                }

                // *** Strip option ***

                foreach (TargetInfo current6 in GenUI.TargetsAt(clickPos, TargetingParameters.ForStrip(pawn), true))
                {
                    TargetInfo      stripTarg = current6;
                    FloatMenuOption item3;
                    if (!pawn.CanReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn))
                    {
                        item3 = new FloatMenuOption("CannotStrip".Translate(new object[]
                        {
                            stripTarg.Thing.LabelCap
                        }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                    }
                    else if (!pawn.CanReserveAndReach(stripTarg, PathEndMode.ClosestTouch, Danger.Deadly, 1))
                    {
                        item3 = new FloatMenuOption("CannotStrip".Translate(new object[]
                        {
                            stripTarg.Thing.LabelCap
                        }) + " (" + "ReservedBy".Translate(new object[]
                        {
                            Find.Reservations.FirstReserverOf(stripTarg, pawn.Faction).LabelBaseShort
                        }) + ")", null, MenuOptionPriority.Medium, null, null);
                    }
                    else
                    {
                        item3 = new FloatMenuOption("Strip".Translate(new object[]
                        {
                            stripTarg.Thing.LabelCap
                        }), new Action(delegate
                        {
                            stripTarg.Thing.SetForbidden(false, false);
                            Job job          = new Job(JobDefOf.Strip, stripTarg);
                            job.playerForced = true;
                            pawn.drafter.TakeOrderedJob(job);
                        }), MenuOptionPriority.Medium, null, null);
                    }
                    list.Add(item3);
                }

                // *** Equip option ***

                CompInventory compInventory = pawn.TryGetComp <CompInventory>();      // Need compInventory here for equip and wear options

                if (pawn.equipment != null)
                {
                    ThingWithComps equipment = null;
                    List <Thing>   thingList = clickCell.GetThingList();
                    for (int j = 0; j < thingList.Count; j++)
                    {
                        if (thingList[j].TryGetComp <CompEquippable>() != null)
                        {
                            equipment = (ThingWithComps)thingList[j];
                            break;
                        }
                    }
                    if (equipment != null)
                    {
                        string          eqLabel = GenLabel.ThingLabel(equipment.def, equipment.Stuff, 1);
                        FloatMenuOption equipOption;
                        if (!pawn.CanReach(equipment, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn))
                        {
                            equipOption = new FloatMenuOption("CannotEquip".Translate(new object[]
                            {
                                eqLabel
                            }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else if (!pawn.CanReserve(equipment, 1))
                        {
                            equipOption = new FloatMenuOption("CannotEquip".Translate(new object[]
                            {
                                eqLabel
                            }) + " (" + "ReservedBy".Translate(new object[]
                            {
                                Find.Reservations.FirstReserverOf(equipment, pawn.Faction).LabelBaseShort
                            }) + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation))
                        {
                            equipOption = new FloatMenuOption("CannotEquip".Translate(new object[]
                            {
                                eqLabel
                            }) + " (" + "Incapable".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else
                        {
                            // Added check for inventory space here
                            int count;
                            if (compInventory != null && !compInventory.CanFitInInventory(equipment, out count, true))
                            {
                                equipOption = new FloatMenuOption("CannotEquip".Translate(new object[] { eqLabel }) + " (" + "CR_InventoryFull".Translate() + ")", null);
                            }
                            else
                            {
                                string equipOptionLabel = "Equip".Translate(new object[]
                                {
                                    eqLabel
                                });
                                if (equipment.def.IsRangedWeapon && pawn.story != null && pawn.story.traits.HasTrait(TraitDefOf.Brawler))
                                {
                                    equipOptionLabel = equipOptionLabel + " " + "EquipWarningBrawler".Translate();
                                }
                                equipOption = new FloatMenuOption(equipOptionLabel, new Action(delegate
                                {
                                    equipment.SetForbidden(false, true);
                                    Job job          = new Job(JobDefOf.Equip, equipment);
                                    job.playerForced = true;
                                    pawn.drafter.TakeOrderedJob(job);
                                    MoteThrower.ThrowStatic(equipment.DrawPos, ThingDefOf.Mote_FeedbackEquip, 1f);
                                    ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.EquippingWeapons, KnowledgeAmount.Total);
                                }), MenuOptionPriority.Medium, null, null);
                            }
                        }
                        list.Add(equipOption);
                    }
                }

                // *** Wear option ***

                if (pawn.apparel != null)
                {
                    Apparel apparel = Find.ThingGrid.ThingAt <Apparel>(clickCell);
                    if (apparel != null)
                    {
                        FloatMenuOption wearOption;
                        if (!pawn.CanReach(apparel, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn))
                        {
                            wearOption = new FloatMenuOption("CannotWear".Translate(new object[]
                            {
                                apparel.Label
                            }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else if (!pawn.CanReserve(apparel, 1))
                        {
                            Pawn pawn3 = Find.Reservations.FirstReserverOf(apparel, pawn.Faction);
                            wearOption = new FloatMenuOption("CannotWear".Translate(new object[]
                            {
                                apparel.Label
                            }) + " (" + "ReservedBy".Translate(new object[]
                            {
                                pawn3.LabelBaseShort
                            }) + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else if (!ApparelUtility.HasPartsToWear(pawn, apparel.def))
                        {
                            wearOption = new FloatMenuOption("CannotWear".Translate(new object[]
                            {
                                apparel.Label
                            }) + " (" + "CannotWearBecauseOfMissingBodyParts".Translate() + ")", null, MenuOptionPriority.Medium, null, null);
                        }
                        else
                        {
                            // Added check for inventory capacity
                            int count;
                            if (compInventory != null && !compInventory.CanFitInInventory(apparel, out count, false, true))
                            {
                                wearOption = new FloatMenuOption("CannotWear".Translate(new object[] { apparel.Label }) + " (" + "CR_InventoryFull".Translate() + ")", null);
                            }
                            else
                            {
                                wearOption = new FloatMenuOption("ForceWear".Translate(new object[] { apparel.LabelBaseShort }),
                                                                 new Action(delegate
                                {
                                    apparel.SetForbidden(false, true);
                                    Job job          = new Job(JobDefOf.Wear, apparel);
                                    job.playerForced = true;
                                    pawn.drafter.TakeOrderedJob(job);
                                }),
                                                                 MenuOptionPriority.Medium, null, null);
                            }
                        }
                        list.Add(wearOption);
                    }
                }

                // *** NEW: Pick up option ***

                if (compInventory != null)
                {
                    List <Thing> thingList = clickCell.GetThingList();
                    if (!thingList.NullOrEmpty <Thing>())
                    {
                        Thing item = thingList.FirstOrDefault(thing => thing.def.alwaysHaulable && !(thing is Corpse));
                        if (item != null)
                        {
                            FloatMenuOption pickUpOption;
                            int             count = 0;
                            if (!pawn.CanReach(item, PathEndMode.Touch, Danger.Deadly))
                            {
                                pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelBaseShort + " (" + "NoPath".Translate() + ")", null);
                            }
                            else if (!pawn.CanReserve(item))
                            {
                                pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelBaseShort + " (" + "ReservedBy".Translate(new object[] { Find.Reservations.FirstReserverOf(item, pawn.Faction) }), null);
                            }
                            else if (!compInventory.CanFitInInventory(item, out count))
                            {
                                pickUpOption = new FloatMenuOption("CR_CannotPickUp".Translate() + " " + item.LabelBaseShort + " (" + "CR_InventoryFull".Translate() + ")", null);
                            }
                            else
                            {
                                pickUpOption = new FloatMenuOption("CR_PickUp".Translate() + " " + item.LabelBaseShort,
                                                                   new Action(delegate
                                {
                                    item.SetForbidden(false);
                                    Job job = new Job(JobDefOf.TakeInventory, item)
                                    {
                                        maxNumToCarry = 1
                                    };
                                    job.playerForced = true;
                                    pawn.drafter.TakeOrderedJob(job);
                                }));
                            }
                            list.Add(pickUpOption);
                            if (count > 1 && item.stackCount > 1)
                            {
                                int             numToCarry        = Math.Min(count, item.stackCount);
                                FloatMenuOption pickUpStackOption = new FloatMenuOption("CR_PickUp".Translate() + " " + item.LabelBaseShort + " x" + numToCarry.ToString(),
                                                                                        new Action(delegate
                                {
                                    item.SetForbidden(false);
                                    Job job = new Job(JobDefOf.TakeInventory, item)
                                    {
                                        maxNumToCarry = numToCarry
                                    };
                                    job.playerForced = true;
                                    pawn.drafter.TakeOrderedJob(job);
                                }));
                                list.Add(pickUpStackOption);
                            }
                        }
                    }
                }

                // *** Deposit/drop equipment options ***

                if (pawn.equipment != null && pawn.equipment.Primary != null)
                {
                    Thing thing2 = Find.ThingGrid.ThingAt(clickCell, ThingDefOf.EquipmentRack);
                    if (thing2 != null)
                    {
                        if (!pawn.CanReach(thing2, PathEndMode.ClosestTouch, Danger.Deadly, false, TraverseMode.ByPawn))
                        {
                            list.Add(new FloatMenuOption("CannotDeposit".Translate(new object[]
                            {
                                pawn.equipment.Primary.LabelCap,
                                thing2.def.label
                            }) + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null));
                        }
                        else
                        {
                            using (IEnumerator <IntVec3> enumerator7 = GenAdj.CellsOccupiedBy(thing2).GetEnumerator())
                            {
                                while (enumerator7.MoveNext())
                                {
                                    IntVec3 c = enumerator7.Current;
                                    if (c.GetStorable() == null && pawn.CanReserveAndReach(c, PathEndMode.ClosestTouch, Danger.Deadly, 1))
                                    {
                                        Action action4 = new Action(delegate
                                        {
                                            ThingWithComps t;
                                            if (pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out t, pawn.Position, true))
                                            {
                                                t.SetForbidden(false, true);
                                                Job job           = new Job(JobDefOf.HaulToCell, t, c);
                                                job.haulMode      = HaulMode.ToCellStorage;
                                                job.maxNumToCarry = 1;
                                                job.playerForced  = true;
                                                pawn.drafter.TakeOrderedJob(job);
                                            }
                                        });
                                        list.Add(new FloatMenuOption("Deposit".Translate(new object[]
                                        {
                                            pawn.equipment.Primary.LabelCap,
                                            thing2.def.label
                                        }), action4, MenuOptionPriority.Medium, null, null));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    if (pawn.equipment != null && GenUI.TargetsAt(clickPos, TargetingParameters.ForSelf(pawn), true).Any <TargetInfo>())
                    {
                        Action action5 = new Action(delegate
                        {
                            ThingWithComps thingWithComps;
                            pawn.equipment.TryDropEquipment(pawn.equipment.Primary, out thingWithComps, pawn.Position, true);
                            pawn.drafter.TakeOrderedJob(new Job(JobDefOf.Wait, 20, false));
                        }
                                                    );
                        list.Add(new FloatMenuOption("Drop".Translate(new object[]
                        {
                            pawn.equipment.Primary.LabelCap
                        }), action5, MenuOptionPriority.Medium, null, null));
                    }
                }

                // *** Trade with option ***

                foreach (TargetInfo current7 in GenUI.TargetsAt(clickPos, TargetingParameters.ForTrade(), true))
                {
                    TargetInfo dest2 = current7;
                    if (!pawn.CanReach(dest2, PathEndMode.OnCell, Danger.Deadly, false, TraverseMode.ByPawn))
                    {
                        list.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null));
                    }
                    else if (!pawn.CanReserve(dest2.Thing, 1))
                    {
                        list.Add(new FloatMenuOption("CannotTrade".Translate() + " (" + "Reserved".Translate() + ")", null, MenuOptionPriority.Medium, null, null));
                    }
                    else
                    {
                        Pawn   pTarg   = (Pawn)dest2.Thing;
                        Action action6 = new Action(delegate
                        {
                            Job job          = new Job(JobDefOf.TradeWithPawn, pTarg);
                            job.playerForced = true;
                            pawn.drafter.TakeOrderedJob(job);
                            ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.InteractingWithTraders, KnowledgeAmount.Total);
                        });
                        string str3 = string.Empty;
                        if (pTarg.Faction != null)
                        {
                            str3 = " (" + pTarg.Faction.name + ")";
                        }
                        List <FloatMenuOption> arg_142E_0 = list;
                        Thing thing = dest2.Thing;
                        arg_142E_0.Add(new FloatMenuOption("TradeWith".Translate(new object[]
                        {
                            pTarg.LabelBaseShort
                        }) + str3, action6, MenuOptionPriority.Medium, null, thing));
                    }
                }
                foreach (Thing current8 in Find.ThingGrid.ThingsAt(clickCell))
                {
                    foreach (FloatMenuOption current9 in current8.GetFloatMenuOptions(pawn))
                    {
                        list.Add(current9);
                    }
                }
            }

            // *** End of humanlike options ***

            // *** Beginning of non-drafted options ***

            if (!pawn.Drafted)
            {
                bool flag  = false;
                bool flag2 = false;
                foreach (Thing current10 in Find.ThingGrid.ThingsAt(clickCell))
                {
                    flag2 = true;
                    if (pawn.CanReach(current10, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn))
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag2 && !flag)
                {
                    list.Add(new FloatMenuOption("(" + "NoPath".Translate() + ")", null, MenuOptionPriority.Medium, null, null));
                    return(list);
                }
                foreach (Thing current11 in Find.ThingGrid.ThingsAt(clickCell))
                {
                    Pawn pawn4 = Find.Reservations.FirstReserverOf(current11, pawn.Faction);
                    if (pawn4 != null && pawn4 != pawn)
                    {
                        list.Add(new FloatMenuOption("IsReservedBy".Translate(new object[]
                        {
                            current11.LabelBaseShort.CapitalizeFirst(),
                            pawn4.LabelBaseShort
                        }), null, MenuOptionPriority.Medium, null, null));
                    }
                    else
                    {
                        JobGiver_Work jobGiver_Work = pawn.thinker.TryGetMainTreeThinkNode <JobGiver_Work>();
                        if (jobGiver_Work != null)
                        {
                            foreach (WorkTypeDef current12 in DefDatabase <WorkTypeDef> .AllDefsListForReading)
                            {
                                for (int k = 0; k < current12.workGiversByPriority.Count; k++)
                                {
                                    WorkGiver_Scanner workGiver_Scanner = current12.workGiversByPriority[k].Worker as WorkGiver_Scanner;
                                    if (workGiver_Scanner != null)
                                    {
                                        if (workGiver_Scanner.def.directOrderable)
                                        {
                                            if (!workGiver_Scanner.ShouldSkip(pawn))
                                            {
                                                JobFailReason.Clear();
                                                Job job;
                                                if (!workGiver_Scanner.HasJobOnThingForced(pawn, current11))
                                                {
                                                    job = null;
                                                }
                                                else
                                                {
                                                    job = workGiver_Scanner.JobOnThingForced(pawn, current11);
                                                }
                                                if (workGiver_Scanner.PotentialWorkThingRequest.Accepts(current11) || (workGiver_Scanner.PotentialWorkThingsGlobal(pawn) != null && workGiver_Scanner.PotentialWorkThingsGlobal(pawn).Contains(current11)))
                                                {
                                                    if (job == null)
                                                    {
                                                        if (JobFailReason.HaveReason)
                                                        {
                                                            string label2 = "CannotGenericWork".Translate(new object[]
                                                            {
                                                                workGiver_Scanner.def.verb,
                                                                current11.LabelBaseShort
                                                            }) + " (" + JobFailReason.Reason + ")";
                                                            list.Add(new FloatMenuOption(label2, null, MenuOptionPriority.Medium, null, null));
                                                        }
                                                    }
                                                    else
                                                    {
                                                        string          label;
                                                        WorkTypeDef     workType        = workGiver_Scanner.def.workType;
                                                        Action          action7         = null;
                                                        PawnCapacityDef pawnCapacityDef = workGiver_Scanner.MissingRequiredCapacity(pawn);
                                                        if (pawnCapacityDef != null)
                                                        {
                                                            label = "CannotMissingHealthActivities".Translate(new object[]
                                                            {
                                                                pawnCapacityDef.label
                                                            });
                                                        }
                                                        else if (pawn.jobs.curJob != null && pawn.jobs.curJob.JobIsSameAs(job))
                                                        {
                                                            label = "CannotGenericAlreadyAm".Translate(new object[]
                                                            {
                                                                workType.gerundLabel,
                                                                current11.LabelBaseShort
                                                            });
                                                        }
                                                        else if (pawn.workSettings.GetPriority(workType) == 0)
                                                        {
                                                            label = "CannotPrioritizeIsNotA".Translate(new object[]
                                                            {
                                                                pawn.NameStringShort,
                                                                workType.pawnLabel
                                                            });
                                                        }
                                                        else if (job.def == JobDefOf.Research && current11 is Building_ResearchBench)
                                                        {
                                                            label = "CannotPrioritizeResearch".Translate();
                                                        }
                                                        else if (current11.IsForbidden(pawn))
                                                        {
                                                            label = "CannotPrioritizeForbidden".Translate(new object[]
                                                            {
                                                                current11.Label
                                                            });
                                                        }
                                                        else if (!pawn.CanReach(current11, PathEndMode.Touch, Danger.Deadly, false, TraverseMode.ByPawn))
                                                        {
                                                            label = current11.Label + ": " + "NoPath".Translate();
                                                        }
                                                        else
                                                        {
                                                            label = "PrioritizeGeneric".Translate(new object[]
                                                            {
                                                                workGiver_Scanner.def.gerund,
                                                                current11.Label
                                                            });
                                                            Job         localJob         = job;
                                                            WorkTypeDef localWorkTypeDef = workType;
                                                            action7 = new Action(delegate { pawn.thinker.GetMainTreeThinkNode <JobGiver_Work>().TryStartPrioritizedWorkOn(pawn, localJob, localWorkTypeDef); });
                                                        }
                                                        if (!list.Any(op => op.label == label))
                                                        {
                                                            list.Add(new FloatMenuOption(label, action7, MenuOptionPriority.Medium, null, null));
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // *** End of non-drafted options ***

            foreach (FloatMenuOption current13 in pawn.GetExtraFloatMenuOptionsFor(clickCell))
            {
                list.Add(current13);
            }
            DangerUtility.DoneDirectOrdering();
            return(list);
        }
Ejemplo n.º 9
0
        public static bool TryIssueJobPackage(JobGiver_Work __instance, ref ThinkResult __result, Pawn pawn, JobIssueParams jobParams)
        {
            if (__instance.emergency && pawn.mindState.priorityWork.IsPrioritized)
            {
                List <WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
                for (int i = 0; i < workGiversByPriority.Count; i++)
                {
                    WorkGiver worker = workGiversByPriority[i].Worker;
                    if (WorkGiversRelated(pawn.mindState.priorityWork.WorkGiver, worker.def))
                    {
                        Job job = GiverTryGiveJobPrioritized(pawn, worker, pawn.mindState.priorityWork.Cell);
                        if (job != null)
                        {
                            job.playerForced = true;
                            __result         = new ThinkResult(job, __instance, workGiversByPriority[i].tagToGive);
                            return(false);
                        }
                    }
                }
                pawn.mindState.priorityWork.Clear();
            }
            List <WorkGiver> list = (!__instance.emergency) ? pawn.workSettings.WorkGiversInOrderNormal : pawn.workSettings.WorkGiversInOrderEmergency;
            int               num = -999;
            TargetInfo        bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            //WorkGiver_Scanner scanner;
            IntVec3 pawnPosition;
            float   closestDistSquared;
            float   bestPriority;
            bool    prioritized;
            bool    allowUnreachable;
            Danger  maxPathDanger;

            for (int j = 0; j < list.Count; j++)
            {
                WorkGiver workGiver = list[j];
                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }
                if (!PawnCanUseWorkGiver(pawn, workGiver))
                {
                    continue;
                }
                try
                {
                    Job job2 = workGiver.NonScanJob(pawn);
                    if (job2 != null)
                    {
                        __result = new ThinkResult(job2, __instance, workGiver.def.tagToGive);
                        return(false);
                    }
                    scanner = (workGiver as WorkGiver_Scanner);

                    if (scanner != null)
                    {
                        if (scanner.def.scanThings)
                        {
                            Predicate <Thing>   validator  = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t);                         //WorkGiver_CleanFilth_Patch.HasJobOnThing
                            IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                            Thing thing;
                            if (scanner.Prioritized)
                            {
                                IEnumerable <Thing> enumerable2 = enumerable;
                                if (enumerable2 == null)
                                {
                                    enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = ((!scanner.AllowUnreachable) ?
                                         GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, enumerable2, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x)) :
                                         GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x)));
                            }
                            else if (scanner.AllowUnreachable)
                            {
                                IEnumerable <Thing> enumerable3 = enumerable;
                                if (enumerable3 == null)
                                {
                                    enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, validator);
                            }
                            else
                            {
                                //TODO: use better ThingRequest groups
                                if (
                                    workGiver.def.defName.Equals("DoctorFeedAnimals") ||
                                    workGiver.def.defName.Equals("DoctorFeedHumanlikes") ||
                                    workGiver.def.defName.Equals("DoctorTendToAnimals") ||
                                    workGiver.def.defName.Equals("DoctorTendToHumanlikes") ||
                                    workGiver.def.defName.Equals("DoBillsUseCraftingSpot") ||
                                    workGiver.def.defName.Equals("DoctorTendEmergency") ||
                                    workGiver.def.defName.Equals("HaulCorpses") ||
                                    workGiver.def.defName.Equals("FillFermentingBarrel") ||
                                    //workGiver.def.defName.Equals("HaulGeneral") ||
                                    workGiver.def.defName.Equals("HandlingFeedPatientAnimals") ||
                                    workGiver.def.defName.Equals("DoBillsButcherFlesh") ||
                                    workGiver.def.defName.Equals("DoBillsCook") ||
                                    workGiver.def.defName.Equals("DoBillsMakeApparel") ||
                                    workGiver.def.defName.Equals("Train") ||
                                    workGiver.def.defName.Equals("VisitSickPawn")
                                    )
                                {
                                    //ClosestThingReachable2 checks validator before CanReach
                                    DateTime startTime = DateTime.Now;

                                    //long
                                    thing = GenClosest_Patch.ClosestThingReachable2(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);

                                    if (DateTime.Now.Subtract(startTime).TotalMilliseconds > 200 && RimThreadedSettings.show200mswarning)
                                    {
                                        Log.Warning("ClosestThingReachable2 Took " + DateTime.Now.Subtract(startTime).TotalMilliseconds + "ms  for workGiver: " + workGiver.def.defName);
                                    }
                                }
                                else
                                {
                                    DateTime startTime = DateTime.Now;
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                    if (DateTime.Now.Subtract(startTime).TotalMilliseconds > 200 && RimThreadedSettings.show200mswarning)
                                    {
                                        Log.Warning("ClosestThingReachable Took " + DateTime.Now.Subtract(startTime).TotalMilliseconds + "ms for workGiver: " + workGiver.def.defName);
                                    }
                                }
                            }
                            if (thing != null)
                            {
                                bestTargetOfLastPriority = thing;
                                scannerWhoProvidedTarget = scanner;
                            }
                        }
                        if (scanner.def.scanCells)
                        {
                            pawnPosition       = pawn.Position;
                            closestDistSquared = 99999f;
                            bestPriority       = float.MinValue;
                            prioritized        = scanner.Prioritized;
                            allowUnreachable   = scanner.AllowUnreachable;
                            maxPathDanger      = scanner.MaxPathDanger(pawn);
                            IEnumerable <IntVec3> enumerable4;
                            if (scanner is WorkGiver_Grower workGiver_Grower)
                            {
                                RimThreaded.WorkGiver_GrowerSow_Patch_JobOnCell = 0;

                                enumerable4 = WorkGiver_Grower_Patch.PotentialWorkCellsGlobalWithoutCanReach(workGiver_Grower, pawn);
                                List <IntVec3> SortedList = enumerable4.OrderBy(o => (o - pawnPosition).LengthHorizontalSquared).ToList();
                                foreach (IntVec3 item in SortedList)
                                {
                                    ProcessCell(item);                                     //long
                                }

                                //Log.Message(RimThreaded.WorkGiver_GrowerSow_Patch_JobOnCell.ToString());
                            }
                            else
                            {
                                enumerable4 = scanner.PotentialWorkCellsGlobal(pawn);
                                IList <IntVec3> list2;
                                if ((list2 = (enumerable4 as IList <IntVec3>)) != null)
                                {
                                    for (int k = 0; k < list2.Count; k++)
                                    {
                                        ProcessCell(list2[k]);
                                    }
                                }
                                else
                                {
                                    foreach (IntVec3 item in enumerable4)
                                    {
                                        ProcessCell(item);
                                    }
                                }
                            }
                        }
                    }
                    void ProcessCell(IntVec3 c)
                    {
                        float newDistanceSquared = (c - pawnPosition).LengthHorizontalSquared;
                        float newPriority        = 0f;

                        if (prioritized)
                        {
                            newPriority = scanner.GetPriority(pawn, c);
                            if (newPriority < bestPriority)
                            {
                                return;
                            }
                        }

                        if (newDistanceSquared < closestDistSquared && !c.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, c))
                        {
                            if (!allowUnreachable && !pawn.CanReach(c, scanner.PathEndMode, maxPathDanger))
                            {
                                return;
                            }

                            bestTargetOfLastPriority = new TargetInfo(c, pawn.Map);
                            scannerWhoProvidedTarget = scanner;
                            closestDistSquared       = newDistanceSquared;
                            bestPriority             = newPriority;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ", ex.ToString()));
                }
                finally
                {
                }
                if (bestTargetOfLastPriority.IsValid)
                {
                    Job job3 = (!bestTargetOfLastPriority.HasThing) ? scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell) : scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                    if (job3 != null)
                    {
                        job3.workGiverDef = scannerWhoProvidedTarget.def;
                        __result          = new ThinkResult(job3, __instance, list[j].def.tagToGive);
                        return(false);
                    }
                    //HACK - I know. I'm awful.
                    //Log.ErrorOnce(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    Log.Warning(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."));
                }
                num = workGiver.def.priorityInType;
            }
            __result = ThinkResult.NoJob;
            return(false);
        }
Ejemplo n.º 10
0
        public static bool TryIssueJobPackage(JobGiver_Work __instance, ref ThinkResult __result, Pawn pawn, JobIssueParams jobParams)
        {
            if (__instance.emergency && pawn.mindState.priorityWork.IsPrioritized)
            {
                List <WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
                for (int i = 0; i < workGiversByPriority.Count; i++)
                {
                    WorkGiver worker = workGiversByPriority[i].Worker;
                    if (WorkGiversRelated(pawn.mindState.priorityWork.WorkGiver, worker.def))
                    {
                        Job job = GiverTryGiveJobPrioritized(pawn, worker, pawn.mindState.priorityWork.Cell);
                        if (job != null)
                        {
                            job.playerForced = true;
                            __result         = new ThinkResult(job, __instance, workGiversByPriority[i].tagToGive);
                            return(false);
                        }
                    }
                }
                pawn.mindState.priorityWork.Clear();
            }
            List <WorkGiver> list = (!__instance.emergency) ? pawn.workSettings.WorkGiversInOrderNormal : pawn.workSettings.WorkGiversInOrderEmergency;
            int               num = -999;
            TargetInfo        bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            WorkGiver_Scanner scanner;
            IntVec3           pawnPosition;
            float             closestDistSquared;
            float             bestPriority;
            bool              prioritized;
            bool              allowUnreachable;
            Danger            maxPathDanger;

            for (int j = 0; j < list.Count; j++)
            {
                WorkGiver workGiver = list[j];
                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }
                if (!PawnCanUseWorkGiver(pawn, workGiver))
                {
                    continue;
                }
                try
                {
                    Job job2 = workGiver.NonScanJob(pawn);
                    if (job2 != null)
                    {
                        __result = new ThinkResult(job2, __instance, list[j].def.tagToGive);
                        return(false);
                    }
                    scanner = (workGiver as WorkGiver_Scanner);
                    if (scanner != null)
                    {
                        if (scanner.def.scanThings)
                        {
                            Predicate <Thing>   validator  = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t);
                            IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                            Thing thing;
                            if (scanner.Prioritized)
                            {
                                IEnumerable <Thing> enumerable2 = enumerable;
                                if (enumerable2 == null)
                                {
                                    enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = ((!scanner.AllowUnreachable) ? GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, enumerable2, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x)) : GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x)));
                            }
                            else if (scanner.AllowUnreachable)
                            {
                                IEnumerable <Thing> enumerable3 = enumerable;
                                if (enumerable3 == null)
                                {
                                    enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, validator);
                            }
                            else
                            {
                                thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                            }
                            if (thing != null)
                            {
                                bestTargetOfLastPriority = thing;
                                scannerWhoProvidedTarget = scanner;
                            }
                        }
                        if (scanner.def.scanCells)
                        {
                            pawnPosition       = pawn.Position;
                            closestDistSquared = 99999f;
                            bestPriority       = float.MinValue;
                            prioritized        = scanner.Prioritized;
                            allowUnreachable   = scanner.AllowUnreachable;
                            maxPathDanger      = scanner.MaxPathDanger(pawn);
                            IEnumerable <IntVec3> enumerable4 = scanner.PotentialWorkCellsGlobal(pawn);
                            IList <IntVec3>       list2;
                            if ((list2 = (enumerable4 as IList <IntVec3>)) != null)
                            {
                                for (int k = 0; k < list2.Count; k++)
                                {
                                    ProcessCell(list2[k]);
                                }
                            }
                            else
                            {
                                foreach (IntVec3 item in enumerable4)
                                {
                                    ProcessCell(item);
                                }
                            }
                        }
                    }
                    void ProcessCell(IntVec3 c)
                    {
                        bool  flag = false;
                        float num2 = (c - pawnPosition).LengthHorizontalSquared;
                        float num3 = 0f;

                        if (prioritized)
                        {
                            if (!c.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, c))
                            {
                                if (!allowUnreachable && !pawn.CanReach(c, scanner.PathEndMode, maxPathDanger))
                                {
                                    return;
                                }
                                num3 = scanner.GetPriority(pawn, c);
                                if (num3 > bestPriority || (num3 == bestPriority && num2 < closestDistSquared))
                                {
                                    flag = true;
                                }
                            }
                        }
                        else if (num2 < closestDistSquared && !c.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, c))
                        {
                            if (!allowUnreachable && !pawn.CanReach(c, scanner.PathEndMode, maxPathDanger))
                            {
                                return;
                            }
                            flag = true;
                        }
                        if (flag)
                        {
                            bestTargetOfLastPriority = new TargetInfo(c, pawn.Map);
                            scannerWhoProvidedTarget = scanner;
                            closestDistSquared       = num2;
                            bestPriority             = num3;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ", ex.ToString()));
                }
                finally
                {
                }
                if (bestTargetOfLastPriority.IsValid)
                {
                    Job job3 = (!bestTargetOfLastPriority.HasThing) ? scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell) : scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                    if (job3 != null)
                    {
                        job3.workGiverDef = scannerWhoProvidedTarget.def;
                        __result          = new ThinkResult(job3, __instance, list[j].def.tagToGive);
                        return(false);
                    }
                    //HACK - I know. I'm awful.
                    //Log.ErrorOnce(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    Log.Warning(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."));
                }
                num = workGiver.def.priorityInType;
            }
            __result = ThinkResult.NoJob;
            return(false);
        }
Ejemplo n.º 11
0
        public static bool TryIssueJobPackage(JobGiver_Work __instance, ref ThinkResult __result, Pawn pawn, JobIssueParams jobParams)
        {
#if DEBUG
            DateTime startTime = DateTime.Now;
#endif
            if (__instance.emergency && pawn.mindState.priorityWork.IsPrioritized)
            {
                List <WorkGiverDef> workGiversByPriority = pawn.mindState.priorityWork.WorkGiver.workType.workGiversByPriority;
                for (int i = 0; i < workGiversByPriority.Count; i++)
                {
                    WorkGiver worker = workGiversByPriority[i].Worker;
                    if (__instance.WorkGiversRelated(pawn.mindState.priorityWork.WorkGiver, worker.def))
                    {
                        Job job = GiverTryGiveJobPrioritized(__instance, pawn, worker, pawn.mindState.priorityWork.Cell);
                        if (job != null)
                        {
                            job.playerForced = true;
                            __result         = new ThinkResult(job, __instance, workGiversByPriority[i].tagToGive);
                            return(false);
                        }
                    }
                }
                pawn.mindState.priorityWork.Clear();
            }
            List <WorkGiver> list = (!__instance.emergency) ? pawn.workSettings.WorkGiversInOrderNormal : pawn.workSettings.WorkGiversInOrderEmergency;
            int               num = -999;
            TargetInfo        bestTargetOfLastPriority = TargetInfo.Invalid;
            WorkGiver_Scanner scannerWhoProvidedTarget = null;
            WorkGiver_Scanner scanner;
            IntVec3           pawnPosition;
            float             closestDistSquared;
            float             bestPriority;
            bool              prioritized;
            bool              allowUnreachable;
            Danger            maxPathDanger;
            for (int j = 0; j < list.Count; j++)
            {
                WorkGiver workGiver = list[j];
                if (workGiver.def.priorityInType != num && bestTargetOfLastPriority.IsValid)
                {
                    break;
                }
                if (!__instance.PawnCanUseWorkGiver(pawn, workGiver))
                {
                    continue;
                }
                try
                {
                    Job job2 = workGiver.NonScanJob(pawn);
                    if (job2 != null)
                    {
                        __result = new ThinkResult(job2, __instance, workGiver.def.tagToGive);
                        return(false);
                    }
                    scanner = (workGiver as WorkGiver_Scanner);

                    if (scanner != null)
                    {
                        if (scanner.def.scanThings)
                        {
//----------------------THERE HAVE BEEN NO CHANGES ABOVE THIS---------------------------------

                            Predicate <Thing> validator;
                            if (scanner is WorkGiver_DoBill workGiver_DoBill)
                            {
                                validator = (Thing t) => !t.IsForbidden(pawn) && WorkGiver_Scanner_Patch.HasJobOnThing(workGiver_DoBill, pawn, t);
                            }
                            else
                            {
                                validator = (Thing t) => !t.IsForbidden(pawn) && scanner.HasJobOnThing(pawn, t);
                            }
                            IEnumerable <Thing> enumerable = scanner.PotentialWorkThingsGlobal(pawn);
                            Thing thing;
                            if (scanner.Prioritized)
                            {
                                IEnumerable <Thing> enumerable2 = enumerable;
                                if (enumerable2 == null)
                                {
                                    enumerable2 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = ((!scanner.AllowUnreachable) ?
                                         GenClosest.ClosestThing_Global_Reachable(pawn.Position, pawn.Map, enumerable2, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, (Thing x) => scanner.GetPriority(pawn, x)) :
                                         GenClosest.ClosestThing_Global(pawn.Position, enumerable2, 99999f, validator, (Thing x) => scanner.GetPriority(pawn, x)));
                            }
                            else if (scanner.AllowUnreachable)
                            {
                                IEnumerable <Thing> enumerable3 = enumerable;
                                if (enumerable3 == null)
                                {
                                    enumerable3 = pawn.Map.listerThings.ThingsMatching(scanner.PotentialWorkThingRequest);
                                }
                                thing = GenClosest.ClosestThing_Global(pawn.Position, enumerable3, 99999f, validator);
                            }
                            else
                            {
                                //TODO: use better ThingRequest groups
                                if (
                                    workGiver.def.defName.Equals("DoctorFeedAnimals") ||
                                    workGiver.def.defName.Equals("DoctorFeedHumanlikes") ||
                                    workGiver.def.defName.Equals("DoctorTendToAnimals") ||
                                    workGiver.def.defName.Equals("DoctorTendToHumanlikes") ||
                                    workGiver.def.defName.Equals("DoBillsUseCraftingSpot") ||
                                    workGiver.def.defName.Equals("DoctorTendEmergency") ||
                                    workGiver.def.defName.Equals("HaulCorpses") ||
                                    workGiver.def.defName.Equals("FillFermentingBarrel") ||
                                    workGiver.def.defName.Equals("HandlingFeedPatientAnimals") ||
                                    workGiver.def.defName.Equals("Train") ||
                                    workGiver.def.defName.Equals("VisitSickPawn") ||
                                    workGiver.def.defName.Equals("DoBillsButcherFlesh") ||
                                    workGiver.def.defName.Equals("DoBillsCook") ||
                                    workGiver.def.defName.Equals("DoBillsMakeApparel")
                                    )
                                {
                                    //long
                                    thing = GenClosest_Patch.ClosestThingReachable2(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }
                                else if (
                                    workGiver.def.defName.Equals("HaulGeneral")
                                    )
                                {
                                    //long
                                    thing = HaulingCache.ClosestThingReachable(pawn, scanner, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }

                                /*
                                 * else if(
                                 *              workGiver.def.defName.Equals("DoBillsButcherFlesh") ||
                                 *              workGiver.def.defName.Equals("DoBillsCook") ||
                                 *              workGiver.def.defName.Equals("DoBillsMakeApparel"))
                                 * {
                                 *
                                 *      thing = null;
                                 *      //ThingGrid_Patch
                                 *      int mapSizeX = pawn.Map.Size.x;
                                 *      int mapSizeZ = pawn.Map.Size.z;
                                 *      int index = pawn.Map.cellIndices.CellToIndex(pawn.Position);
                                 *      //Dictionary<Bill, float> billPointsDict = ThingGrid_Patch.thingBillPoints[t.def];
                                 *      Dictionary<WorkGiver_Scanner, Dictionary<float, List<HashSet<Thing>[]>>> ingredientDict = ThingGrid_Patch.mapIngredientDict[pawn.Map];
                                 *      ThingRequest thingReq = scanner.PotentialWorkThingRequest;
                                 *      if(!ingredientDict.TryGetValue(scanner, out Dictionary<float, List<HashSet<Thing>[]>> scoreToJumboCellsList)) {
                                 *              scoreToJumboCellsList = new Dictionary<float, List<HashSet<Thing>[]>>();
                                 *              List<Thing> thingsMatchingRequest = pawn.Map.listerThings.ThingsMatching(thingReq);
                                 *      }
                                 *
                                 * }
                                 */
                                else
                                {
                                    //long
                                    thing = GenClosest.ClosestThingReachable(pawn.Position, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                }
                            }
                            if (thing != null)
                            {
                                bestTargetOfLastPriority = thing;
                                scannerWhoProvidedTarget = scanner;
                            }
                        }
                        if (scanner.def.scanCells)
                        {
                            pawnPosition       = pawn.Position;
                            closestDistSquared = 99999f;
                            bestPriority       = float.MinValue;
                            prioritized        = scanner.Prioritized;
                            allowUnreachable   = scanner.AllowUnreachable;
                            maxPathDanger      = scanner.MaxPathDanger(pawn);
                            IEnumerable <IntVec3> enumerable4;
                            if (scanner is WorkGiver_GrowerSow workGiver_Grower)
                            {
                                //RimThreaded.WorkGiver_GrowerSow_Patch_JobOnCell = 0;

                                //thing = HaulingCache.ClosestThingReachable(pawn, scanner, pawn.Map, scanner.PotentialWorkThingRequest, scanner.PathEndMode, TraverseParms.For(pawn, scanner.MaxPathDanger(pawn)), 9999f, validator, enumerable, 0, scanner.MaxRegionsToScanBeforeGlobalSearch, enumerable != null);
                                IntVec3 bestCell = WorkGiver_Grower_Patch.ClosestLocationReachable(workGiver_Grower, pawn);
                                //Log.Message(bestCell.ToString());
                                if (bestCell.IsValid)
                                {
                                    bestTargetOfLastPriority = new TargetInfo(bestCell, pawn.Map);
                                    scannerWhoProvidedTarget = scanner;
                                }
                                //Log.Message(RimThreaded.WorkGiver_GrowerSow_Patch_JobOnCell.ToString());
                            }
                            else if (scanner is WorkGiver_GrowerHarvest workGiver_GrowerHarvest)
                            {
                                IntVec3 bestCell = WorkGiver_GrowerHarvest_Patch.ClosestLocationReachable(workGiver_GrowerHarvest, pawn);
                                if (bestCell.IsValid)
                                {
                                    bestTargetOfLastPriority = new TargetInfo(bestCell, pawn.Map);
                                    scannerWhoProvidedTarget = scanner;
                                }

                                /*
                                 * enumerable4 = workGiver_GrowerHarvest.PotentialWorkCellsGlobal(pawn);
                                 * IList<IntVec3> list2;
                                 * if ((list2 = (enumerable4 as IList<IntVec3>)) != null)
                                 * {
                                 *      for (int k = 0; k < list2.Count; k++)
                                 *      {
                                 *              ProcessCell(list2[k]);
                                 *      }
                                 * }
                                 * else
                                 * {
                                 *      foreach (IntVec3 item in enumerable4)
                                 *      {
                                 *              ProcessCell(item);
                                 *      }
                                 * }
                                 */
                            }
                            else
                            {
                                enumerable4 = scanner.PotentialWorkCellsGlobal(pawn);
                                IList <IntVec3> list2;
                                if ((list2 = (enumerable4 as IList <IntVec3>)) != null)
                                {
                                    for (int k = 0; k < list2.Count; k++)
                                    {
                                        ProcessCell(list2[k]);
                                    }
                                }
                                else
                                {
                                    foreach (IntVec3 item in enumerable4)
                                    {
                                        ProcessCell(item);
                                    }
                                }
                            }
                        }
                    }
                    void ProcessCell(IntVec3 c)
                    {
                        float newDistanceSquared = (c - pawnPosition).LengthHorizontalSquared;
                        float newPriority        = 0f;

                        if (prioritized)
                        {
                            newPriority = scanner.GetPriority(pawn, c);
                            if (newPriority < bestPriority)
                            {
                                return;
                            }
                        }

                        if (newDistanceSquared < closestDistSquared && !c.IsForbidden(pawn) && scanner.HasJobOnCell(pawn, c))
                        {
                            if (!allowUnreachable && !pawn.CanReach(c, scanner.PathEndMode, maxPathDanger))
                            {
                                return;
                            }

                            bestTargetOfLastPriority = new TargetInfo(c, pawn.Map);
                            scannerWhoProvidedTarget = scanner;
                            closestDistSquared       = newDistanceSquared;
                            bestPriority             = newPriority;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Log.Error(string.Concat(pawn, " threw exception in WorkGiver ", workGiver.def.defName, ": ", ex.ToString()));
                }
                finally
                {
                }
                if (bestTargetOfLastPriority.IsValid)
                {
                    Job job3 = (!bestTargetOfLastPriority.HasThing) ? scannerWhoProvidedTarget.JobOnCell(pawn, bestTargetOfLastPriority.Cell) : scannerWhoProvidedTarget.JobOnThing(pawn, bestTargetOfLastPriority.Thing);
                    if (job3 != null)
                    {
                        job3.workGiverDef = scannerWhoProvidedTarget.def;
                        __result          = new ThinkResult(job3, __instance, list[j].def.tagToGive);
                        return(false);
                    }

                    //If this was a cached plant job, deregister it
                    if (scannerWhoProvidedTarget is WorkGiver_GrowerSow)
                    {
                        Map          map       = pawn.Map;
                        IntVec3      cell      = bestTargetOfLastPriority.Cell;
                        List <Thing> thingList = cell.GetThingList(map);
                        foreach (Thing thing in thingList)
                        {
                            if (thing is Building_PlantGrower buildingPlantGrower)
                            {
                                PlantSowing_Cache.ReregisterObject(map, cell,
                                                                   WorkGiver_Grower_Patch.awaitingPlantCellsMapDict);
                            }
                        }
                        PlantSowing_Cache.ReregisterObject(map, cell, WorkGiver_Grower_Patch.awaitingPlantCellsMapDict);
                    }
                    //HACK - I know. I'm awful.
                    //Log.ErrorOnce(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."), 6112651);
                    Log.Warning(string.Concat(scannerWhoProvidedTarget, " provided target ", bestTargetOfLastPriority, " but yielded no actual job for pawn ", pawn, ". The CanGiveJob and JobOnX methods may not be synchronized."));
                }
                num = workGiver.def.priorityInType;

#if DEBUG
                int milli99 = (int)DateTime.Now.Subtract(startTime).TotalMilliseconds;
                if (milli99 > 300)
                {
                    Log.Warning("99 JobGiver_Work.TryIssueJobPackage Took over " + milli99.ToString() + "ms for workGiver: " + workGiver.def.defName);
                    //Log.Warning(scanner.PotentialWorkThingRequest.ToString());
                    //Log.Warning(validator.ToString());
                }
#endif
            }
            __result = ThinkResult.NoJob;
            return(false);
        }