public void CheckIfUsed(Pawn_SurvivalToolAssignmentTracker assignmentTracker, bool changeList = false)
        {
            if (HoldingPawn == null || HoldingPawn?.NeedsSurvivalTool(this) == false ||
                HoldingPawn?.CanUseSurvivalTools() == false || HoldingPawn?.CanUseSurvivalTool(def) == false)
            {
                InUse = false;
                if (changeList && HoldingPawn?.TryGetComp <Pawn_SurvivalToolAssignmentTracker>()?.ToolsInUse.Contains(this) == true)
                {
                    HoldingPawn?.TryGetComp <Pawn_SurvivalToolAssignmentTracker>()?.ToolsInUse.Remove(this);
                }
                return;
            }
            float maxTools = HoldingPawn.GetStatValue(ST_StatDefOf.SurvivalToolCarryCapacity, false);

            if (SurvivalToolUtility.BestSurvivalToolsFor(HoldingPawn).Contains(this) &&
                (assignmentTracker?.ToolsInUse.Count < maxTools || assignmentTracker?.ToolsInUse.Contains(this) == true))
            {
                InUse = true;
                if (changeList)
                {
                    HoldingPawn?.TryGetComp <Pawn_SurvivalToolAssignmentTracker>()?.ToolsInUse.AddDistinct(this);
                }
            }
            else
            {
                InUse = false;
                if (changeList && HoldingPawn?.TryGetComp <Pawn_SurvivalToolAssignmentTracker>()?.ToolsInUse.Contains(this) == true)
                {
                    HoldingPawn?.TryGetComp <Pawn_SurvivalToolAssignmentTracker>()?.ToolsInUse.Remove(this);
                }
            }
        }
        public override void DoCell(Rect rect, Pawn pawn, PawnTable table)
        {
            Pawn_SurvivalToolAssignmentTracker toolAssignmentTracker = pawn.TryGetComp <Pawn_SurvivalToolAssignmentTracker>();

            if (toolAssignmentTracker == null)
            {
                return;
            }
            int   num  = Mathf.FloorToInt((rect.width - 4f) * 0.714285731f);
            int   num2 = Mathf.FloorToInt((rect.width - 4f) * 0.2857143f);
            float num3 = rect.x;
            bool  somethingIsForced = toolAssignmentTracker.forcedHandler.SomethingForced;
            Rect  rect2             = new Rect(num3, rect.y + 2f, (float)num, rect.height - 4f);

            if (somethingIsForced)
            {
                rect2.width -= 4f + (float)num2;
            }
            Rect rect3 = rect2;
            Pawn pawn2 = pawn;
            Func <Pawn, SurvivalToolAssignment> getPayload = (Pawn p) => p.TryGetComp <Pawn_SurvivalToolAssignmentTracker>().CurrentSurvivalToolAssignment;
            Func <Pawn, IEnumerable <Widgets.DropdownMenuElement <SurvivalToolAssignment> > > menuGenerator = new Func <Pawn, IEnumerable <Widgets.DropdownMenuElement <SurvivalToolAssignment> > >(Button_GenerateMenu);
            string buttonLabel = toolAssignmentTracker.CurrentSurvivalToolAssignment.label.Truncate(rect2.width, null);
            string label       = toolAssignmentTracker.CurrentSurvivalToolAssignment.label;

            Widgets.Dropdown(rect3, pawn2, getPayload, menuGenerator, buttonLabel, null, label, null, null, true);
            num3 += rect2.width;
            num3 += 4f;
            Rect rect4 = new Rect(num3, rect.y + 2f, (float)num2, rect.height - 4f);

            if (somethingIsForced)
            {
                if (Widgets.ButtonText(rect4, "ClearForcedApparel".Translate(), true, false, true))
                {
                    toolAssignmentTracker.forcedHandler.Reset();
                }
                TooltipHandler.TipRegion(rect4, new TipSignal(delegate()
                {
                    string text = "ForcedSurvivalTools".Translate() + ":\n";
                    foreach (Thing tool in toolAssignmentTracker.forcedHandler.ForcedTools)
                    {
                        text = text + "\n   " + tool.LabelCap;
                    }
                    return(text);
                }, pawn.GetHashCode() * 128));
                num3 += (float)num2;
                num3 += 4f;
            }

            Rect rect5 = new Rect(num3, rect.y + 2f, (float)num2, rect.height - 4f);

            if (Widgets.ButtonText(rect5, "AssignTabEdit".Translate(), true, false, true))
            {
                Find.WindowStack.Add(new Dialog_ManageSurvivalToolAssignments(toolAssignmentTracker.CurrentSurvivalToolAssignment));
            }
            num3 += (float)num2;
        }
        // This is a janky mess and a half, but works!
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (SurvivalToolsSettings.toolOptimization)
            {
                Pawn_SurvivalToolAssignmentTracker assignmentTracker = pawn.TryGetComp <Pawn_SurvivalToolAssignmentTracker>();

                // Pawn can't use tools, lacks a tool assignment tracker or it isn't yet time to re-optimise tools
                if (!pawn.CanUseSurvivalTools() || assignmentTracker == null || Find.TickManager.TicksGame < assignmentTracker.nextSurvivalToolOptimizeTick)
                {
                    return(null);
                }

                // Check if current tool assignment allows for each tool, auto-removing those that aren't allowed.
                SurvivalToolAssignment curAssignment = assignmentTracker.CurrentSurvivalToolAssignment;
                List <Thing>           heldTools     = pawn.GetHeldSurvivalTools().ToList();
                foreach (Thing tool in heldTools)
                {
                    if ((!curAssignment.filter.Allows(tool) || !pawn.NeedsSurvivalTool((SurvivalTool)tool)) && assignmentTracker.forcedHandler.AllowedToAutomaticallyDrop(tool))
                    {
                        return(pawn.DequipAndTryStoreSurvivalTool(tool));
                    }
                }

                // Look for better alternative tools to what the colonist currently has, based on what stats are relevant to the work types the colonist is assigned to
                List <Thing>   heldUsableTools   = heldTools.Where(t => heldTools.IndexOf(t).IsUnderSurvivalToolCarryLimitFor(pawn)).ToList();
                List <Thing>   mapTools          = pawn.MapHeld.listerThings.AllThings.Where(t => t is SurvivalTool).ToList();
                List <StatDef> workRelevantStats = pawn.AssignedToolRelevantWorkGiversStatDefs();
                Thing          curTool           = null;
                Thing          newTool           = null;
                float          optimality        = 0f;
                foreach (StatDef stat in workRelevantStats)
                {
                    curTool    = pawn.GetBestSurvivalTool(stat);
                    optimality = SurvivalToolScore(curTool, workRelevantStats);
                    foreach (Thing potentialToolThing in mapTools)
                    {
                        SurvivalTool potentialTool = (SurvivalTool)potentialToolThing;
                        if (StatUtility.StatListContains(potentialTool.WorkStatFactors.ToList(), stat) && curAssignment.filter.Allows(potentialTool) && potentialTool.BetterThanWorkingToollessFor(stat) &&
                            pawn.CanUseSurvivalTool(potentialTool.def) && potentialTool.IsInAnyStorage() && !potentialTool.IsForbidden(pawn) && !potentialTool.IsBurning())
                        {
                            float potentialOptimality = SurvivalToolScore(potentialTool, workRelevantStats);
                            float delta = potentialOptimality - optimality;
                            if (delta > 0f && pawn.CanReserveAndReach(potentialTool, PathEndMode.OnCell, pawn.NormalMaxDanger()))
                            {
                                newTool    = potentialTool;
                                optimality = potentialOptimality;
                            }
                        }
                    }
                    if (newTool != null)
                    {
                        break;
                    }
                }

                // Return a job based on whether or not a better tool was located

                // Failure
                if (newTool == null)
                {
                    SetNextOptimizeTick(pawn);
                    return(null);
                }

                // Success
                int heldToolOffset = 0;
                if (curTool != null && assignmentTracker.forcedHandler.AllowedToAutomaticallyDrop(curTool))
                {
                    pawn.jobs.jobQueue.EnqueueFirst(pawn.DequipAndTryStoreSurvivalTool(curTool, false));
                    heldToolOffset = -1;
                }
                if (pawn.CanCarryAnyMoreSurvivalTools(heldToolOffset))
                {
                    Job pickupJob = new Job(JobDefOf.TakeInventory, newTool)
                    {
                        count = 1
                    };
                    return(pickupJob);
                }

                // Final failure state
                SetNextOptimizeTick(pawn);
            }

            return(null);
        }
Example #4
0
        // This is a janky mess and a half, but works!
        protected override Job TryGiveJob(Pawn pawn)
        {
            Pawn_SurvivalToolAssignmentTracker assignmentTracker = pawn.TryGetComp <Pawn_SurvivalToolAssignmentTracker>();

            // Pawn can't use tools, lacks a tool assignment tracker or it isn't yet time to re-optimise tools
            if (!pawn.CanUseSurvivalTools() || assignmentTracker == null || Find.TickManager.TicksGame < assignmentTracker.nextSurvivalToolOptimizeTick)
            {
                return(null);
            }

            if (SurvivalToolsSettings.toolAutoDropExcess)
            {
                assignmentTracker.CheckToolsInUse();

                // Check if current tool assignment allows for each tool, auto-removing those that aren't allowed.
                SurvivalToolAssignment curAssignment = assignmentTracker.CurrentSurvivalToolAssignment;
                List <SurvivalTool>    heldTools     = pawn.GetHeldSurvivalTools();
                foreach (SurvivalTool tool in heldTools)
                {
                    if ((!curAssignment.filter.Allows(tool) || !pawn.NeedsSurvivalTool(tool) || !tool.InUse) && !tool.Forced &&
                        StoreUtility.TryFindBestBetterStoreCellFor(tool, pawn, pawn.Map, StoreUtility.CurrentStoragePriorityOf(tool), pawn.Faction, out IntVec3 c))
                    {
                        return(pawn.DequipAndTryStoreSurvivalTool(tool, true, c));
                    }
                }
            }
            if (SurvivalToolsSettings.toolOptimization)
            {
                SurvivalToolAssignment curAssignment     = assignmentTracker.CurrentSurvivalToolAssignment;
                List <StatDef>         workRelevantStats = pawn.AssignedToolRelevantWorkGiversStatDefs();
                List <Thing>           mapTools          = pawn.MapHeld.listerThings.AllThings.Where(t => t is SurvivalTool).ToList();

                SurvivalTool curTool    = null;
                SurvivalTool newTool    = null;
                float        optimality = 0f;
                foreach (StatDef stat in workRelevantStats)
                {
                    curTool    = pawn.GetBestSurvivalTool(stat);
                    optimality = SurvivalToolScore(curTool, workRelevantStats);
                    foreach (SurvivalTool potentialTool in mapTools)
                    {
                        if (StatUtility.StatListContains(potentialTool.WorkStatFactors.ToList(), stat) && curAssignment.filter.Allows(potentialTool) && potentialTool.BetterThanWorkingToollessFor(stat) &&
                            pawn.CanUseSurvivalTool(potentialTool.def) && potentialTool.IsInAnyStorage() && !potentialTool.IsForbidden(pawn) && !potentialTool.IsBurning())
                        {
                            float potentialOptimality = SurvivalToolScore(potentialTool, workRelevantStats);
                            float delta = potentialOptimality - optimality;
                            if (delta > 0f && pawn.CanReserveAndReach(potentialTool, PathEndMode.OnCell, pawn.NormalMaxDanger()))
                            {
                                newTool    = potentialTool;
                                optimality = potentialOptimality;
                            }
                        }
                    }
                    if (newTool != null)
                    {
                        break;
                    }
                }

                // Return a job based on whether or not a better tool was located

                // Failure
                if (newTool == null)
                {
                    SetNextOptimizeTick(pawn);
                    return(null);
                }

                // Success
                int heldToolOffset = 0;
                if (curTool != null && !curTool.Forced)
                {
                    pawn.jobs.jobQueue.EnqueueFirst(pawn.DequipAndTryStoreSurvivalTool(curTool, false));
                    heldToolOffset = -1;
                }
                if (pawn.CanCarryAnyMoreSurvivalTools(heldToolOffset))
                {
                    Job pickupJob = new Job(JobDefOf.TakeInventory, newTool)
                    {
                        count = 1
                    };
                    return(pickupJob);
                }
            }

            // Final failure state
            SetNextOptimizeTick(pawn);
            return(null);
        }