// 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); }
// 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); }
internal static bool _ShouldShowFor(this StatWorker obj, BuildableDef eDef) { // Need some reflection to access the internals StatDef _stat = typeof(StatWorker).GetField("stat", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj) as StatDef; if ( (!_stat.showIfUndefined) && (!StatUtility.StatListContains(eDef.statBases, _stat)) ) { return(false); } ThingDef thingDef = eDef as ThingDef; if ( (thingDef != null) && (thingDef.category == ThingCategory.Pawn) && ( (!_stat.showOnPawns) || ( (!_stat.showOnHumanlikes) && (thingDef.race.Humanlike) ) || ( (!_stat.showOnAnimals) && (thingDef.race.Animal) ) || ( (!_stat.showOnMechanoids) && (thingDef.race.IsMechanoid) ) ) ) { return(false); } if ( (_stat.category == StatCategoryDefOf.BasicsPawn) || (_stat.category == StatCategoryDefOf.PawnCombat) ) { if (thingDef != null) { return(thingDef.category == ThingCategory.Pawn); } return(false); } if ( (_stat.category == StatCategoryDefOf.PawnMisc) || (_stat.category == StatCategoryDefOf.PawnSocial) || (_stat.category == StatCategoryDefOf.PawnWork) ) { if ( (thingDef != null) && (thingDef.category == ThingCategory.Pawn) ) { return(thingDef.race.Humanlike); } return(false); } if (_stat.category == StatCategoryDefOf.Building) { if (thingDef == null) { return(false); } if (_stat == StatDefOf.DoorOpenSpeed) { return ((thingDef.thingClass == typeof(Building_Door)) || (thingDef.thingClass.IsSubclassOf(typeof(Building_Door)))); } return(thingDef.category == ThingCategory.Building); } if (_stat.category == StatCategoryDefOf.Apparel) { if (thingDef == null) { return(false); } if (!thingDef.IsApparel) { return(thingDef.category == ThingCategory.Pawn); } return(true); } if (_stat.category == StatCategoryDefOf.Weapon) { if (thingDef == null) { return(false); } if (!thingDef.IsMeleeWeapon) { return(thingDef.IsRangedWeapon); } return(true); } if (_stat.category == StatCategoryDefOf.BasicsNonPawn) { if (thingDef != null) { return(thingDef.category != ThingCategory.Pawn); } return(true); } if (_stat.category.displayAllByDefault) { return(true); } object[] objArray = new object[4]; string str1 = "Unhandled case: "; StatDef statDef = _stat; string str2 = ", "; BuildableDef buildableDef = eDef; objArray[0] = (object)str1; objArray[1] = (object)statDef; objArray[2] = (object)str2; objArray[3] = (object)buildableDef; Verse.Log.Error(string.Concat(objArray)); return(false); }