Esempio n. 1
0
        private float GetBaseEstimatedLifespan(SurvivalTool tool, BuildableDef def)
        {
            SurvivalToolProperties props = def.GetModExtension <SurvivalToolProperties>() ?? SurvivalToolProperties.defaultValues;

            if (!((ThingDef)def).useHitPoints)
            {
                return(float.PositiveInfinity);
            }

            // For def
            if (tool == null)
            {
                return(GenDate.TicksToDays(Mathf.RoundToInt((BaseWearInterval * def.GetStatValueAbstract(StatDefOf.MaxHitPoints)) / props.toolWearFactor)));
            }

            // For thing
            StuffPropsTool stuffProps = tool.Stuff?.GetModExtension <StuffPropsTool>() ?? StuffPropsTool.defaultValues;
            float          wearFactor = tool.def.GetModExtension <SurvivalToolProperties>().toolWearFactor *(stuffProps.wearFactorMultiplier);

            return(GenDate.TicksToDays(Mathf.RoundToInt((BaseWearInterval * tool.MaxHitPoints) / wearFactor)));
        }
        private static float SurvivalToolScore(Thing toolThing, List <StatDef> workRelevantStats)
        {
            SurvivalTool tool = toolThing as SurvivalTool;

            if (tool == null)
            {
                return(0f);
            }

            float optimality = 0f;

            foreach (StatDef stat in workRelevantStats)
            {
                optimality += StatUtility.GetStatValueFromList(tool.WorkStatFactors.ToList(), stat, 0f);
            }

            if (tool.def.useHitPoints)
            {
                float lifespanRemaining = tool.GetStatValue(ST_StatDefOf.ToolEstimatedLifespan, true) * ((float)tool.HitPoints * tool.MaxHitPoints);
                optimality *= LifespanDaysToOptimalityMultiplierCurve.Evaluate(lifespanRemaining);
            }
            return(optimality);
        }
        public override string GetExplanationUnfinalized(StatRequest req, ToStringNumberSense numberSense)
        {
            SurvivalTool tool = req.Thing as SurvivalTool;

            return($"{"StatsReport_BaseValue".Translate()}: {GetBaseEstimatedLifespan(tool, req.BuildableDef).ToString("F1")}");
        }
        public override float GetValueUnfinalized(StatRequest req, bool applyPostProcess = true)
        {
            SurvivalTool tool = req.Thing as SurvivalTool;

            return(GetBaseEstimatedLifespan(tool, req.BuildableDef));
        }
        // 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);
        }
Esempio n. 6
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);
        }