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); }
// 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); }