static FloatRange GetInsulationStats(Apparel apparel)
        {
            var insulationCold = apparel.GetStatValue(StatDefOf.Insulation_Cold);
            var insulationHeat = apparel.GetStatValue(StatDefOf.Insulation_Heat);

            return(new FloatRange(-insulationCold, insulationHeat));
        }
Beispiel #2
0
        public static float ApparelScoreRaw_ProtectionBaseStat(Apparel ap)
        {
            var num = ap.GetStatValue(StatDefOf.ArmorRating_Sharp)
                      + (ap.GetStatValue(StatDefOf.ArmorRating_Blunt) * 0.5f);

            return(num * 0.1f);
        }
Beispiel #3
0
        static bool Prefix(ref float __result, JobGiver_OptimizeApparel __instance, Pawn pawn, Apparel ap)
        {
            Log.Message("1 pawn is " + ((pawn == null) ? "null" : "not null"));

            if (pawn != null)
            {
                return(true);
            }
            Log.Message("2");

            if (HitPointsPercentScoreFactorCurve == null)
            {
                HitPointsPercentScoreFactorCurve        = typeof(JobGiver_OptimizeApparel).GetField("HitPointsPercentScoreFactorCurve", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as SimpleCurve;
                InsulationColdScoreFactorCurve_NeedWarm = typeof(JobGiver_OptimizeApparel).GetField("InsulationColdScoreFactorCurve_NeedWarm", BindingFlags.Static | BindingFlags.NonPublic).GetValue(null) as SimpleCurve;
                NeedWarmthFI = typeof(JobGiver_OptimizeApparel).GetField("neededWarmth", BindingFlags.Static | BindingFlags.NonPublic);
            }
            Log.Message("HitPointsPercentScoreFactorCurve is " + ((HitPointsPercentScoreFactorCurve == null) ? "null" : "not null"));
            Log.Message("InsulationColdScoreFactorCurve_NeedWarm is " + ((InsulationColdScoreFactorCurve_NeedWarm == null) ? "null" : "not null"));
            Log.Message("NeedWarmthFI is " + ((NeedWarmthFI == null) ? "null" : "not null"));
            Log.Message("NeedWarmth is " + NeedWarmthFI.GetValue(null));

            float result = 0.1f + ap.GetStatValue(StatDefOf.ArmorRating_Sharp) + ap.GetStatValue(StatDefOf.ArmorRating_Blunt);

            if (ap.def.useHitPoints)
            {
                float x = (float)ap.HitPoints / (float)ap.MaxHitPoints;
                result *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            result += ap.GetSpecialApparelScoreOffset();
            float num3 = 1f;

            if ((NeededWarmth)NeedWarmthFI.GetValue(null) == NeededWarmth.Warm)
            {
                float statValue = ap.GetStatValue(StatDefOf.Insulation_Cold);
                num3 *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            }
            result *= num3;
            if (ap.WornByCorpse)
            {
                result -= 0.5f;
                if (result > 0f)
                {
                    result *= 0.1f;
                }
            }
            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                result -= 0.5f;
                if (result > 0f)
                {
                    result *= 0.1f;
                }
            }
            __result = result;
            return(false);
        }
Beispiel #4
0
        public float CalculateApparelScoreRawInsulationColdAjust(Apparel ap)
        {
            float num3 = 1f;

            if (this.needWarmCurve != null)
            {
                float statValueAbstract = ap.GetStatValue(StatDefOf.Insulation_Cold);
                num3 *= this.needWarmCurve.Evaluate(statValueAbstract);
            }
            if (this.needCoolCurve != null)
            {
                float statValueAbstract = ap.GetStatValue(StatDefOf.Insulation_Heat);
                num3 *= this.needCoolCurve.Evaluate(statValueAbstract);
            }
            return(num3);
        }
Beispiel #5
0
        public static int GetPostArmorDamage(Pawn pawn, int amountInt, BodyPartRecord part, DamageDef damageDef)
        {
            float num = (float)amountInt;

            if (damageDef.armorCategory == null)
            {
                return(amountInt);
            }
            StatDef deflectionStat = damageDef.armorCategory.deflectionStat;

            if (pawn.apparel != null)
            {
                List <Apparel> wornApparel = pawn.apparel.WornApparel;
                for (int i = 0; i < wornApparel.Count; i++)
                {
                    Apparel apparel = wornApparel[i];
                    if (apparel.def.apparel.CoversBodyPart(part))
                    {
                        ArmorUtility.ApplyArmor(ref num, apparel.GetStatValue(deflectionStat, true), apparel, damageDef);
                        if (num < 0.001f)
                        {
                            return(0);
                        }
                    }
                }
            }
            ArmorUtility.ApplyArmor(ref num, pawn.GetStatValue(deflectionStat, true), null, damageDef);
            return(GenMath.RoundRandom(num));
        }
Beispiel #6
0
        public static float CalculateArmorByPartsCE(Pawn pawn, StatDef stat, ref string text, string unit)
        {
            text = "";
            float          num         = 0f;
            List <Apparel> wornApparel = pawn.apparel.WornApparel;

            for (int i = 0; i < wornApparel.Count; i++)
            {
                num += wornApparel[i].GetStatValue(stat, true) * wornApparel[i].def.apparel.HumanBodyCoverage;
            }
            if (num > 0.005f)
            {
                List <BodyPartRecord> bpList = pawn.RaceProps.body.AllParts;
                for (int i = 0; i < bpList.Count; i++)
                {
                    float          armorValue = 0f;
                    BodyPartRecord part       = bpList[i];
                    if (part.depth == BodyPartDepth.Outside && (part.coverage >= 0.1 || (part.def == BodyPartDefOf.Eye || part.def == BodyPartDefOf.Neck)))
                    {
                        text += part.LabelCap + ": ";
                        for (int j = wornApparel.Count - 1; j >= 0; j--)
                        {
                            Apparel apparel = wornApparel[j];
                            if (apparel.def.apparel.CoversBodyPart(part))
                            {
                                armorValue += apparel.GetStatValue(stat, true);
                            }
                        }
                        text += formatArmorValue(armorValue, unit) + "\n";
                    }
                }
            }
            return(num);
        }
 static float ApparelScoreAutoWorkPriorities(Pawn pawn, Apparel apparel)
 {
     return(WorkPriorities.WorktypeStatPriorities(pawn)
            .Select(sp => (apparel.def.equippedStatOffsets.GetStatOffsetFromList(sp.Stat)
                           + apparel.GetStatValue(sp.Stat)
                           - sp.Stat.defaultBaseValue) * sp.Weight)
            .Sum());              // NOTE: weights were already normalized to sum to 1.
 }
 public static void ShieldFromApparel(ref float armourImportance, StatDef stat, Apparel apparel, BodyPartRecord part)
 {
     if (apparel.IsShield(out var shieldComp) && shieldComp.UsableNow &&
         shieldComp.CoversBodyPart(part))
     {
         var shieldRating = Mathf.Clamp01(apparel.GetStatValue(stat) / 2);
         armourImportance *= 1 - shieldRating;
     }
 }
Beispiel #9
0
        public bool IncludeAppareL(Apparel a)
        {
            if (this.Name.Length > 0)
            {
                if (a.Label.ToLower().IndexOf(this.Name) == -1 &&
                    a.def.defName.ToLower().IndexOf(this.Name) == -1)
                {
                    return(false);
                }
            }

            if (this.Layer != null)
            {
                if (!a.def.apparel.layers.Contains(this.Layer))
                {
                    return(false);
                }
            }

            if (this.Quality != QualityRange.All)
            {
                QualityCategory q;
                if (a.TryGetQuality(out q))
                {
                    if (this.Quality.min > q || this.Quality.max < q)
                    {
                        return(false);
                    }
                }
            }

            if (this.HP > 0)
            {
                float percent = (float)a.HitPoints / a.MaxHitPoints;
                float filter  = this.HP * 0.01f;
                if (percent < filter)
                {
                    return(false);
                }
            }

            foreach (StatDefValue sdv in this.StatDefs)
            {
                if (sdv.Value > 0)
                {
                    float v = Math.Abs(a.GetStatValue(sdv.Def));
                    if (sdv.Value > v)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #10
0
        public static float GetPostArmorDamage(Pawn pawn, float amount, float armorPenetration, BodyPartRecord part, ref DamageDef damageDef, out bool deflectedByMetalArmor, out bool diminishedByMetalArmor)
        {
            deflectedByMetalArmor  = false;
            diminishedByMetalArmor = false;
            float result;

            if (damageDef.armorCategory == null)
            {
                result = amount;
            }
            else
            {
                StatDef armorRatingStat = damageDef.armorCategory.armorRatingStat;
                if (pawn.apparel != null)
                {
                    List <Apparel> wornApparel = pawn.apparel.WornApparel;
                    for (int i = wornApparel.Count - 1; i >= 0; i--)
                    {
                        Apparel apparel = wornApparel[i];
                        if (apparel.def.apparel.CoversBodyPart(part))
                        {
                            float num = amount;
                            bool  flag;
                            ArmorUtility.ApplyArmor(ref amount, armorPenetration, apparel.GetStatValue(armorRatingStat, true), apparel, ref damageDef, pawn, out flag);
                            if (amount < 0.001f)
                            {
                                deflectedByMetalArmor = flag;
                                return(0f);
                            }
                            if (amount < num && flag)
                            {
                                diminishedByMetalArmor = true;
                            }
                        }
                    }
                }
                float num2 = amount;
                bool  flag2;
                ArmorUtility.ApplyArmor(ref amount, armorPenetration, pawn.GetStatValue(armorRatingStat, true), null, ref damageDef, pawn, out flag2);
                if (amount < 0.001f)
                {
                    deflectedByMetalArmor = flag2;
                    result = 0f;
                }
                else
                {
                    if (amount < num2 && flag2)
                    {
                        diminishedByMetalArmor = true;
                    }
                    result = amount;
                }
            }
            return(result);
        }
        public static float GetApparelScore(Pawn pawn, Thing thing)
        {
            Apparel apparel = thing as Apparel;

            if (apparel is ShieldBelt && pawn.equipment.Primary != null && pawn.equipment.Primary.def.IsWeaponUsingProjectiles)
            {
                return(-1000f);
            }

            float score      = 0.1f + apparel.def.apparel.scoreOffset;
            float armorScore = apparel.GetStatValue(StatDefOf.ArmorRating_Sharp) + apparel.GetStatValue(StatDefOf.ArmorRating_Blunt) + apparel.GetStatValue(StatDefOf.ArmorRating_Heat);

            score += armorScore;

            if (apparel.def.useHitPoints)
            {
                float x = (float)apparel.HitPoints / (float)apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            score += apparel.GetSpecialApparelScoreOffset();

            //float warmthScore = 1f;
            //if (neededWarmth == NeededWarmth.Warm)
            //{
            //    float statValue = apparel.GetStatValue(StatDefOf.Insulation_Cold);
            //    warmthScore *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            //}
            //score *= warmthScore;

            // Human body is close enough
            float coverageScore = apparel.def.apparel.HumanBodyCoverage * 10.0f;

            score *= coverageScore;

            return(score);
        }
Beispiel #12
0
        private void GetInsulationStats(Apparel apparel, out float insulationCold, out float insulationHeat)
        {
            if (Outfitter.Cache.InsulationDict.TryGetValue(apparel, out var range))
            {
                insulationCold = range.min;
                insulationHeat = range.max;
                return;
            }

            // offsets on apparel
            insulationCold = apparel.GetStatValue(StatDefOf.Insulation_Cold) * -1;
            insulationHeat = apparel.GetStatValue(StatDefOf.Insulation_Heat);

            insulationCold -= apparel.def.equippedStatOffsets.GetStatOffsetFromList(StatDefOf.Insulation_Cold);
            insulationHeat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(StatDefOf.Insulation_Heat);

            // offsets on apparel infusions
            DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.ComfyTemperatureMin, out var infInsulationCold);
            DoApparelScoreRaw_PawnStatsHandlers(apparel, StatDefOf.ComfyTemperatureMax, out var infInsulationHeat);
            insulationCold += infInsulationCold;
            insulationHeat += infInsulationHeat;

            Outfitter.Cache.InsulationDict.Add(apparel, new FloatRange(insulationCold, insulationHeat));
        }
        /// <summary>
        /// When notified job is about to start, calculate unequip delay for underlying apparel.
        /// </summary>
        public override void Notify_Starting()
        {
            base.Notify_Starting();
            _apparel  = TargetThingA as Apparel;
            _duration = (int)(_apparel.GetStatValue(StatDefOf.EquipDelay) * 60f);

            List <Apparel> wornApparel = pawn.apparel.WornApparel;

            for (int num = wornApparel.Count - 1; num >= 0; num--)
            {
                if (!ApparelUtility.CanWearTogether(_apparel.def, wornApparel[num].def, pawn.RaceProps.body))
                {
                    _duration += (int)(wornApparel[num].GetStatValue(StatDefOf.EquipDelay) * 60f);
                }
            }
        }
        public void UpdateResists()
        {
            float          envResist    = 0;
            List <Apparel> wornApparels = pawn.apparel.WornApparel;

            envResist += pawn.GetStatValue(StatDef.Named("ArmorRating_Enviromental"));
            for (int i = 0; i < wornApparels.Count; i++)
            {
                Apparel wornApparel = wornApparels[i];
                envResist += wornApparel.GetStatValue(StatDef.Named("ArmorRating_Enviromental"));
            }
            //Log.Message(pawn + " ArmorRating_Enviromental = " + envResist);

            pawn.TryMakeImmune(envResist, 1, HediffDefOf.ToxicImmunity);

            Hediff hediff_OxygenAtmosphere = pawn.health.hediffSet.hediffs.Find((Hediff x) => x.def == HediffDefOf.OxygenAtmosphere);

            if (envResist < minEnvResist)
            {
                if (pawn.IsColonist || pawn.IsPrisoner)
                {
                    if (hediff_OxygenAtmosphere != null)
                    {
                        hediff_OxygenAtmosphere.Severity += 0.001f;
                    }
                    else
                    {
                        pawn.health.AddHediff(HediffDefOf.OxygenAtmosphere);
                        //Hediff hediff = pawn.health.hediffSet.hediffs.Find((Hediff x) => x.def == HediffDefOf.OxygenAtmosphere);
                        //float severity = Rand.Range(10, 100);
                        //hediff.Severity = severity / 1000;
                    }
                }
            }
            else
            {
                if (hediff_OxygenAtmosphere != null)
                {
                    hediff_OxygenAtmosphere.Severity -= 0.001f;
                    if (hediff_OxygenAtmosphere.Severity <= 0.001f)
                    {
                        pawn.health.RemoveHediff(hediff_OxygenAtmosphere);
                    }
                }
            }
        }
Beispiel #15
0
        /// <summary>
        ///     Draw overall armor in a format as "Sharp   100 Rha", wihout the double quotes
        /// </summary>
        /// <param name="selPawn"></param>
        /// <param name="curY"></param>
        /// <param name="width"></param>
        /// <param name="stat"></param>
        /// <param name="label"></param>
        /// <param name="unit"></param>
        public static void TryDrawOverallArmor(Pawn selPawn, ref float curY, float width, StatDef stat, string label, string unit)
        {
            if (selPawn.RaceProps.body != BodyDefOf.Human)
            {
                return;
            }
            float          num         = 0f;
            List <Apparel> wornApparel = selPawn.apparel.WornApparel;

            for (int i = 0; i < wornApparel.Count; i++)
            {
                num += wornApparel[i].GetStatValue(stat, true) * wornApparel[i].def.apparel.HumanBodyCoverage;
            }
            if (num > 0.005f)
            {
                Rect rect = new Rect(0f, curY, width, _standardLineHeight);
                List <BodyPartRecord> bpList = selPawn.RaceProps.body.AllParts;
                string text = "";
                for (int i = 0; i < bpList.Count; i++)
                {
                    float          armorValue = 0f;
                    BodyPartRecord part       = bpList[i];
                    if (part.depth == BodyPartDepth.Outside && (part.coverage >= 0.1 || part.def == BodyPartDefOf.Eye || part.def == BodyPartDefOf.Neck))
                    {
                        text += part.LabelCap + ": ";
                        for (int j = wornApparel.Count - 1; j >= 0; j--)
                        {
                            Apparel apparel = wornApparel[j];
                            if (apparel.def.apparel.CoversBodyPart(part))
                            {
                                armorValue += apparel.GetStatValue(stat, true);
                            }
                        }
                        text += FormatArmorValue(armorValue, unit) + "\n";
                    }
                }
                TooltipHandler.TipRegion(rect, text);

                // Draw Label
                Widgets.Label(rect, label.Truncate(200f, null));
                // Draw armor value
                rect.xMin += 200;
                Widgets.Label(rect, FormatArmorValue(num, unit));
                curY += _standardLineHeight;
            }
        }
Beispiel #16
0
        // RimWorld.ITab_Pawn_Gear
        private void TryDrawOverallArmor(ref float curY, float width, StatDef stat, string label)
        {
            if (SelPawnForGear.RaceProps.body != BodyDefOf.Human)
            {
                return;
            }
            float          num         = 0f;
            List <Apparel> wornApparel = SelPawnForGear.apparel.WornApparel;

            for (int i = 0; i < wornApparel.Count; i++)
            {
                num += Mathf.Clamp01(wornApparel[i].GetStatValue(stat, true)) * wornApparel[i].def.apparel.HumanBodyCoverage;
            }
            num = Mathf.Clamp01(num);
            if (num > 0.005f)
            {
                Rect                  rect   = new Rect(0f, curY, width, _standardLineHeight);
                BodyPartRecord        bpr    = new BodyPartRecord();
                List <BodyPartRecord> bpList = SelPawnForGear.RaceProps.body.AllParts;
                string                text   = "";
                for (int i = 0; i < bpList.Count; i++)
                {
                    float          armorValue = 0f;
                    BodyPartRecord part       = bpList[i];
                    if (part.depth == BodyPartDepth.Outside && (part.coverage >= 0.1 || (part.def == BodyPartDefOf.Eye || part.def == BodyPartDefOf.Neck)))
                    {
                        text += part.LabelCap + ": ";
                        for (int j = wornApparel.Count - 1; j >= 0; j--)
                        {
                            Apparel apparel = wornApparel[j];
                            if (apparel.def.apparel.CoversBodyPart(part))
                            {
                                armorValue += Mathf.Clamp01(apparel.GetStatValue(stat, true));
                            }
                        }
                        text += Mathf.Clamp01(armorValue).ToStringPercent() + "\n";
                    }
                }
                TooltipHandler.TipRegion(rect, text);

                Widgets.Label(rect, label.Truncate(200f, null));
                rect.xMin += 200;
                Widgets.Label(rect, num.ToStringPercent());
                curY += _standardLineHeight;
            }
        }
Beispiel #17
0
        public float GetStatValue(Apparel apparel, Saveable_StatDef stat)
        {
            float baseStat    = apparel.GetStatValue(stat.statDef, true);
            float currentStat = baseStat;

            currentStat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.statDef);

            PawnCalcForApparel.DoApparelScoreRawStatsHandlers(pawn, apparel, stat.statDef, ref currentStat);

            if (baseStat == 0)
            {
                return(currentStat);
            }
            else
            {
                return(currentStat / baseStat);
            }
        }
Beispiel #18
0
 private static bool PawnWearingRelevantGear(StatRequest req, Pawn pawn, StatDef apparelStat)
 {
     if (pawn.apparel != null)
     {
         for (int i = 0; i < pawn.apparel.WornApparel.Count; i++)
         {
             Apparel apparel = pawn.apparel.WornApparel[i];
             if (apparel.GetStatValue(apparelStat, true) != 0f)
             {
                 return(true);
             }
             if (StatWorker.StatOffsetFromGear(apparel, apparelStat) != 0f)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
Beispiel #19
0
        public static void ApparelScoreRaw_Postfix(Pawn pawn, Apparel ap, ref float __result)
        {
            //NeededWarmth neededCold = PawnApparelGenerator.CalculateNeededWarmth(pawn, pawn.Map.Tile, GenLocalDate.Twelfth(pawn));

            float num = GenTemperature.AverageTemperatureAtTileForTwelfth(pawn.Map.Tile, GenLocalDate.Twelfth(pawn));

            SimpleCurve InsulationHeatScoreFactorCurve_NeedCold = new SimpleCurve
            {
                {
                    new CurvePoint(0f, 1f),
                    true
                },
                {
                    new CurvePoint(30f, 8f),
                    true
                }
            };


            // This version uses ComfyTemperatureMax to find if needCool, not comfyTemperatureMin
            if (num < pawn.def.GetStatValueAbstract(StatDefOf.ComfyTemperatureMax, null) - 4f)
            {
                float statValue  = ap.GetStatValue(StatDefOf.Insulation_Heat, true);
                float coldFactor = 1f;
                coldFactor *= InsulationHeatScoreFactorCurve_NeedCold.Evaluate(statValue);

                __result *= coldFactor;
            }



            //if (neededCold == NeededWarmth.Cool)
            //{
            //    float statValue = ap.GetStatValue(StatDefOf.Insulation_Heat, true);
            //    float coldFactor = 1f;
            //    coldFactor *= InsulationHeatScoreFactorCurve_NeedCold.Evaluate(statValue);

            //    __result *= coldFactor;
            //}
        }
Beispiel #20
0
 public static bool IgnoreInsulationWhenWet(StatRequest req, ref float val, StatDef ___apparelStat, bool ___subtract)
 {
     if (___apparelStat != StatDefOf.Insulation_Cold || !___subtract)
     {
         return(true);
     }
     if (req.HasThing && req.Thing != null)
     {
         Pawn pawn = req.Thing as Pawn;
         if (pawn != null)
         {
             Hediff firstHediffOfDef = pawn.health.hediffSet.GetFirstHediffOfDef(DefOf_WaterIsCold.WetCold, false);
             if (firstHediffOfDef == null)
             {
                 return(true);
             }
             float multiplier = Mathf.Clamp(1f - firstHediffOfDef.Severity, ModSettings_WaterIsCold.wetInsFactor / 100f, 1f);
             if (pawn.apparel != null && multiplier > 0)
             {
                 for (int i = 0; i < pawn.apparel.WornApparel.Count; i++)
                 {
                     Apparel apparel = pawn.apparel.WornApparel[i];
                     float   num     = apparel.GetStatValue(___apparelStat, true);
                     num += StatWorker.StatOffsetFromGear(apparel, ___apparelStat);
                     if (!apparel.def.HasModExtension <WaterGear>())
                     {
                         num *= multiplier;
                     }
                     val -= num;
                 }
             }
             return(false);
         }
     }
     return(true);
 }
Beispiel #21
0
        public override void Notify_Starting()
        {
            base.Notify_Starting();
            apparel = TargetThingA as Apparel;

            mode     = job.count;
            duration = (int)(apparel.GetStatValue(StatDefOf.EquipDelay) * 60f);
            if (mode > 0)
            {
                List <Apparel> wornApparel = pawn.apparel.WornApparel;
                int            count       = wornApparel.Count;
                Log.Message("wornApparel.Count: " + wornApparel.Count);
                Log.Message("Count: " + count);
                for (int num = 0; num < count; ++num)
                {
                    Log.Message("wornApparel.Count2: " + wornApparel.Count);
                    Log.Message("num: " + num);
                    if (!ApparelUtility.CanWearTogether(apparel.def, wornApparel[num].def, pawn.RaceProps.body))
                    {
                        duration += (int)(wornApparel[num].GetStatValue(StatDefOf.EquipDelay) * 60f);
                    }
                }
            }
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            yield return(Toils_General.Wait(10, TargetIndex.None));

            yield return(new Toil
            {
                initAction = delegate()
                {
                    Thing MarkedThing = CompUnloadChecker.getFirstMarked(pawn);
                    if (MarkedThing == null)
                    {
                        EndJobWith(JobCondition.Succeeded);
                        return;
                    }
                    //
                    if (pawn.equipment.Contains(MarkedThing))
                    {
                        Equipment = (ThingWithComps)MarkedThing;
                        Apparel = null;
                    }
                    else
                    {
                        Apparel = pawn.apparel.Contains(MarkedThing) ? (Apparel)MarkedThing : null;
                        Equipment = null;
                    }

                    ThingCount firstUnloadableThing = MarkedThing == null ? default(ThingCount) : new ThingCount(MarkedThing, MarkedThing.stackCount);
                    IntVec3 c;
                    if (!StoreUtility.TryFindStoreCellNearColonyDesperate(firstUnloadableThing.Thing, pawn, out c))
                    {
                        Thing thing;
                        pawn.inventory.innerContainer.TryDrop(firstUnloadableThing.Thing, ThingPlaceMode.Near, firstUnloadableThing.Count, out thing, null, null);
                        EndJobWith(JobCondition.Succeeded);
                        return;
                    }

                    job.SetTarget(TargetIndex.A, firstUnloadableThing.Thing);
                    job.SetTarget(TargetIndex.B, c);
                    countToDrop = firstUnloadableThing.Count;
                }
            });

            yield return(Toils_Reserve.Reserve(TargetIndex.B, 1, -1, null));

            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.Touch).FailOnDestroyedOrNull(TargetIndex.A).FailOn(delegate() { return !stillUnloadable(pawn.CurJob.GetTarget(TargetIndex.A).Thing); }));

            //preintiating unequip-delay
            Toil unequip = new Toil
            {
                initAction = delegate()
                {
                    if (Equipment != null)
                    {
                        pawn.equipment.TryTransferEquipmentToContainer(Equipment, pawn.inventory.innerContainer);
                    }
                    else if (Apparel != null)
                    {
                        ThingOwner <Apparel> a = Traverse.Create(pawn.apparel).Field("wornApparel").GetValue <ThingOwner <Apparel> >();
                        a.TryTransferToContainer(Apparel, pawn.inventory.innerContainer);
                    }
                }
            };
            //if equiped, wait unequipping time
            Toil wait = new Toil();

            wait.initAction = delegate()
            {
                ticker   = 0;
                duration = Apparel != null?Apparel.GetStatValue(StatDefOf.EquipDelay, true) * 60f : Equipment != null ? 30 : 0;

                pawn.pather.StopDead();
            };
            wait.tickAction = delegate()
            {
                if (ticker >= duration)
                {
                    ReadyForNextToil();
                }
                ticker++;
            };
            wait.defaultCompleteMode = ToilCompleteMode.Never;
            wait.WithProgressBar(TargetIndex.A, () => ticker / duration);
            //unequip to inventory
            yield return(wait);

            yield return(unequip);

            //hold in hands
            yield return(new Toil
            {
                initAction = delegate()
                {
                    Thing thing = job.GetTarget(TargetIndex.A).Thing;
                    CompUnloadChecker c = thing.TryGetComp <CompUnloadChecker>();
                    if (c == null || !c.ShouldUnload)
                    {
                        EndJobWith(JobCondition.Incompletable);
                        return;
                    }
                    if (thing == null || !pawn.inventory.innerContainer.Contains(thing))
                    {
                        EndJobWith(JobCondition.Incompletable);
                        return;
                    }
                    if (!pawn.health.capacities.CapableOf(PawnCapacityDefOf.Manipulation) || !thing.def.EverStorable(false))
                    {
                        pawn.inventory.innerContainer.TryDrop(thing, ThingPlaceMode.Near, countToDrop, out thing, null, null);
                        EndJobWith(JobCondition.Succeeded);
                    }
                    else
                    {
                        pawn.inventory.innerContainer.TryTransferToContainer(thing, pawn.carryTracker.innerContainer, countToDrop, out thing, true);
                        job.count = countToDrop;
                        job.SetTarget(TargetIndex.A, thing);
                    }
                    thing.SetForbidden(false, false);
                }
            });

            Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B).FailOnDestroyedOrNull(TargetIndex.A).FailOn(delegate() { return(!stillUnloadable(pawn.CurJob.GetTarget(TargetIndex.A).Thing)); });

            yield return(carryToCell);

            yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true));

            yield break;
        }
Beispiel #23
0
        public float GetStatValue(Apparel apparel, Saveable_StatDef stat)
        {
            float baseStat = apparel.GetStatValue(stat.statDef, true);
            float currentStat = baseStat;
            currentStat += apparel.def.equippedStatOffsets.GetStatOffsetFromList(stat.statDef);

            PawnCalcForApparel.DoApparelScoreRawStatsHandlers(pawn, apparel, stat.statDef, ref currentStat);

            if (baseStat == 0)
                return currentStat;
            else
                return currentStat / baseStat;
        }
Beispiel #24
0
        public float ApparelScoreRaw([NotNull] Apparel ap)
        {
            if (RawScoreDict.ContainsKey(ap))
            {
                return(RawScoreDict[ap]);
            }

            // only allow shields to be considered if a primary weapon is equipped and is melee
            var thisPawn = _pawn;

            if (ap.def.thingClass == typeof(ShieldBelt) && thisPawn.equipment.Primary?.def.IsRangedWeapon == true)
            {
                return(-1f);
            }

            // Fail safe to prevent pawns get out of the regular temperature.
            // Might help making pawn drop equipped apparel if it's too cold/warm.
            // this.GetInsulationStats(ap, out float insulationCold, out float insulationHeat);
            // FloatRange temperatureRange = this.pawn.ComfortableTemperatureRange();
            // if (ap.Wearer != thisPawn)
            // {
            // temperatureRange.min += insulationCold;
            // temperatureRange.max += insulationHeat;
            // }
            // if (temperatureRange.min > 12 && insulationCold > 0 || temperatureRange.max < 32 && insulationHeat < 0)
            // {
            // return -3f;
            // }

            // relevant apparel stats
            var entry = GetAllOffsets(ap);

            var statBases       = entry.StatBases;
            var equippedOffsets = entry.EquippedOffsets;
            var infusedOffsets  = entry.InfusedOffsets;

            // start score at 1
            float score = 1;

            // add values for each statdef modified by the apparel
            var stats = thisPawn.GetApparelStatCache().StatCache;

            foreach (var statPriority in stats.Where(statPriority => statPriority != null))
            {
                var stat = statPriority.Stat;

                if (statBases.Contains(stat))
                {
                    var apStat = ap.GetStatValue(stat);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, apStat, ref score);
                    }
                    else
                    {
                        // add stat to base score before offsets are handled
                        // (the pawn's apparel stat cache always has armors first as it is initialized with it).
                        score += apStat * statPriority.Weight;
                    }
                }

                // equipped offsets, e.g. movement speeds
                if (equippedOffsets.Contains(stat))
                {
                    var apStat = ap.GetEquippedStatValue(_pawn, stat);

                    if (SpecialStats.Contains(stat))
                    {
                        CalculateScoreForSpecialStats(ap, statPriority, thisPawn, apStat, ref score);
                    }
                    else
                    {
                        score += apStat * statPriority.Weight;
                    }

                    // multiply score to favour items with multiple offsets
                    // score *= adjusted;

                    // debug.AppendLine( statWeightPair.Key.LabelCap + ": " + score );
                }

                // infusions
                if (!infusedOffsets.Contains(stat))
                {
                    continue;
                }

                // float statInfused = StatInfused(infusionSet, statPriority, ref dontcare);
                DoApparelScoreRaw_PawnStatsHandlers(ap, stat, out var statInfused);

                if (SpecialStats.Contains(stat))
                {
                    CalculateScoreForSpecialStats(ap, statPriority, thisPawn, statInfused, ref score);
                }
                else
                {
                    // Bug with Infused and "Ancient", it completely kills the pawn's armor
                    if (statInfused < 0 && (stat == StatDefOf.ArmorRating_Blunt ||
                                            stat == StatDefOf.ArmorRating_Sharp))
                    {
                        score = -2f;
                        return(score);
                    }

                    score += statInfused * statPriority.Weight;
                }
            }

            score += ap.GetSpecialApparelScoreOffset();

            score += ApparelScoreRaw_ProtectionBaseStat(ap);

            // offset for apparel hitpoints
            if (ap.def.useHitPoints)
            {
                var x = ap.HitPoints / (float)ap.MaxHitPoints;
                score *= ApparelStatsHelper.HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            if (ap.WornByCorpse && ThoughtUtility.CanGetThought_NewTemp(thisPawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }
            }

            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought_NewTemp(thisPawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (ThoughtUtility.CanGetThought_NewTemp(thisPawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score *= 2f;
                }
            }

            score *= ApparelScoreRaw_Temperature(ap);

            RawScoreDict.Add(ap, score);

            return(score);
        }
        public static float ApparelScoreRaw( Apparel apparel, Pawn pawn )
        {
            // relevant apparel stats
            HashSet<StatDef> equippedOffsets = new HashSet<StatDef>();
            if ( apparel.def.equippedStatOffsets != null )
            {
                foreach ( StatModifier equippedStatOffset in apparel.def.equippedStatOffsets )
                {
                    equippedOffsets.Add( equippedStatOffset.stat );
                }
            }
            HashSet<StatDef> statBases = new HashSet<StatDef>();
            if ( apparel.def.statBases != null )
            {
                foreach ( StatModifier statBase in apparel.def.statBases )
                {
                    statBases.Add( statBase.stat );
                }
            }

            // start score at 1
            float score = 1;

            // make infusions ready
            InfusionSet infusions;
            bool infused = false;
            StatMod mod;
            InfusionDef prefix = null;
            InfusionDef suffix = null;
            if ( apparel.TryGetInfusions( out infusions ) )
            {
                infused = true;
                prefix = infusions.Prefix.ToInfusionDef();
                suffix = infusions.Suffix.ToInfusionDef();
            }

            // add values for each statdef modified by the apparel
                foreach( ApparelStatCache.StatPriority statPriority in pawn.GetApparelStatCache().StatCache )
            {
                // statbases, e.g. armor
                if ( statBases.Contains( statPriority.Stat ) )
                {
                    // add stat to base score before offsets are handled ( the pawn's apparel stat cache always has armors first as it is initialized with it).
                    score += apparel.GetStatValue( statPriority.Stat ) * statPriority.Weight;
                }

                // equipped offsets, e.g. movement speeds
                if ( equippedOffsets.Contains( statPriority.Stat ) )
                {
                    // base value
                    float norm = apparel.GetStatValue( statPriority.Stat );
                    float adjusted = norm;

                    // add offset
                    adjusted += apparel.def.equippedStatOffsets.GetStatOffsetFromList( statPriority.Stat ) *
                                statPriority.Weight;

                    // normalize
                    if ( norm != 0 )
                    {
                        adjusted /= norm;
                    }

                    // multiply score to favour items with multiple offsets
                    score *= adjusted;

                    //debug.AppendLine( statWeightPair.Key.LabelCap + ": " + score );
                }

                // infusions
                if( infused ) { 
                    // prefix
                    if ( !infusions.PassPre &&
                         prefix.GetStatValue( statPriority.Stat, out mod ) )
                    {
                        score += mod.offset * statPriority.Weight;
                        score += score * ( mod.multiplier - 1 ) * statPriority.Weight;

                        //debug.AppendLine( statWeightPair.Key.LabelCap + " infusion: " + score );
                    }
                    if ( !infusions.PassSuf &&
                         suffix.GetStatValue( statPriority.Stat, out mod ) )
                    {
                        score += mod.offset * statPriority.Weight;
                        score += score * ( mod.multiplier - 1 ) * statPriority.Weight;

                        //debug.AppendLine( statWeightPair.Key.LabelCap + " infusion: " + score );
                    }
                }
            }

            // offset for apparel hitpoints 
            if ( apparel.def.useHitPoints )
            {
                // durability on 0-1 scale
                float x = apparel.HitPoints / (float)apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate( x );
            }

            // temperature
            FloatRange targetTemperatures = pawn.GetApparelStatCache().TargetTemperatures;
            float minComfyTemperature = pawn.GetStatValue( StatDefOf.ComfyTemperatureMin );
            float maxComfyTemperature  = pawn.GetStatValue( StatDefOf.ComfyTemperatureMax );

            // offsets on apparel
            float insulationCold = apparel.GetStatValue( StatDefOf.Insulation_Cold );
            float insulationHeat = apparel.GetStatValue( StatDefOf.Insulation_Heat );

            // offsets on apparel infusions
            if( infused )
            {
                // prefix
                if( !infusions.PassPre &&
                     prefix.GetStatValue( StatDefOf.ComfyTemperatureMin, out mod ) )
                {
                    insulationCold += mod.offset;
                }
                if( !infusions.PassPre &&
                     prefix.GetStatValue( StatDefOf.ComfyTemperatureMax, out mod ) )
                {
                    insulationHeat += mod.offset;
                }

                // suffix
                if( !infusions.PassSuf &&
                     suffix.GetStatValue( StatDefOf.ComfyTemperatureMin, out mod ) )
                {
                    insulationCold += mod.offset;
                }
                if( !infusions.PassSuf &&
                     suffix.GetStatValue( StatDefOf.ComfyTemperatureMax, out mod ) )
                {
                    insulationHeat += mod.offset;
                }
            }

            // if this gear is currently worn, we need to make sure the contribution to the pawn's comfy temps is removed so the gear is properly scored
            if ( pawn.apparel.WornApparel.Contains( apparel ) )
            {
                minComfyTemperature -= insulationCold;
                maxComfyTemperature -= insulationHeat;
            }

            // now for the interesting bit.
            float temperatureScoreOffset = 0f;
            float tempWeight = pawn.GetApparelStatCache().TemperatureWeight;
            float neededInsulation_Cold   = targetTemperatures.TrueMin - minComfyTemperature;  // isolation_cold is given as negative numbers < 0 means we're underdressed
            float neededInsulation_Warmth = targetTemperatures.TrueMax - maxComfyTemperature;  // isolation_warm is given as positive numbers.

            // currently too cold
            if ( neededInsulation_Cold < 0 )
            {
                temperatureScoreOffset += -insulationCold * tempWeight;
            }
            // currently warm enough
            else
            {
                // this gear would make us too cold
                if ( insulationCold > neededInsulation_Cold )
                {
                    temperatureScoreOffset += ( neededInsulation_Cold - insulationCold ) * tempWeight;
                }
            }

            // currently too warm
            if( neededInsulation_Warmth > 0 )
            {
                temperatureScoreOffset += insulationHeat * tempWeight;
            }
            // currently cool enough
            else
            {
                // this gear would make us too warm
                if( insulationHeat < neededInsulation_Warmth )
                {
                    temperatureScoreOffset += -( neededInsulation_Warmth - insulationHeat ) * tempWeight;
                }
            }

            // adjust for temperatures
            score += temperatureScoreOffset / 10f;

            return score;
        }
Beispiel #26
0
 /// <summary>
 /// Get bulk value for <paramref name="apparel"/>.
 /// </summary>
 /// <param name="apparel"> Apparel to inspect. </param>
 /// <returns> WornBulk value on <paramref name="apparel"/>. </returns>
 public static float WornBulkFor(Apparel apparel)
 {
     return(apparel.GetStatValue(CE_StatDefOf.WornBulk));
 }
Beispiel #27
0
        public static float ApparelScoreRaw(Pawn pawn, Apparel ap)
        {
            float num  = 0.1f + ap.def.apparel.scoreOffset;
            float num2 = ap.GetStatValue(StatDefOf.ArmorRating_Sharp) + ap.GetStatValue(StatDefOf.ArmorRating_Blunt) + ap.GetStatValue(StatDefOf.ArmorRating_Heat);

            num += num2;
            if (ap.def.useHitPoints)
            {
                float x = (float)ap.HitPoints / (float)ap.MaxHitPoints;
                num *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }
            num += ap.GetSpecialApparelScoreOffset();
            float num3 = 1f;

            //if (neededWarmth == NeededWarmth.Warm)
            //{
            //	float statValue = ap.GetStatValue(StatDefOf.Insulation_Cold);
            //	num3 *= InsulationColdScoreFactorCurve_NeedWarm.Evaluate(statValue);
            //}
            num *= num3;
            if (ap.WornByCorpse && (pawn == null || ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.DeadMansApparel, checkIfNullified: true)))
            {
                num -= 0.5f;
                if (num > 0f)
                {
                    num *= 0.1f;
                }
            }
            if (ap.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (pawn == null || ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelSad, checkIfNullified: true))
                {
                    num -= 0.5f;
                    if (num > 0f)
                    {
                        num *= 0.1f;
                    }
                }
                if (pawn != null && ThoughtUtility.CanGetThought(pawn, ThoughtDefOf.HumanLeatherApparelHappy, checkIfNullified: true))
                {
                    num += 0.12f;
                }
            }
            if (pawn != null && !ap.def.apparel.CorrectGenderForWearing(pawn.gender))
            {
                num *= 0.01f;
            }
            if (pawn != null && pawn.royalty != null && pawn.royalty.AllTitlesInEffectForReading.Count > 0)
            {
                tmpAllowedApparels.Clear();
                tmpRequiredApparels.Clear();
                tmpBodyPartGroupsWithRequirement.Clear();
                QualityCategory qualityCategory = QualityCategory.Awful;
                foreach (RoyalTitle item in pawn.royalty.AllTitlesInEffectForReading)
                {
                    if (item.def.requiredApparel != null)
                    {
                        for (int i = 0; i < item.def.requiredApparel.Count; i++)
                        {
                            tmpAllowedApparels.AddRange(item.def.requiredApparel[i].AllAllowedApparelForPawn(pawn, ignoreGender: false, includeWorn: true));
                            tmpRequiredApparels.AddRange(item.def.requiredApparel[i].AllRequiredApparelForPawn(pawn, ignoreGender: false, includeWorn: true));
                            tmpBodyPartGroupsWithRequirement.AddRange(item.def.requiredApparel[i].bodyPartGroupsMatchAny);
                        }
                    }
                    if ((int)item.def.requiredMinimumApparelQuality > (int)qualityCategory)
                    {
                        qualityCategory = item.def.requiredMinimumApparelQuality;
                    }
                }
                bool num4 = ap.def.apparel.bodyPartGroups.Any((BodyPartGroupDef bp) => tmpBodyPartGroupsWithRequirement.Contains(bp));
                if (ap.TryGetQuality(out QualityCategory qc) && (int)qc < (int)qualityCategory)
                {
                    num *= 0.25f;
                }
                if (num4)
                {
                    foreach (ThingDef tmpRequiredApparel in tmpRequiredApparels)
                    {
                        tmpAllowedApparels.Remove(tmpRequiredApparel);
                    }
                    if (tmpAllowedApparels.Contains(ap.def))
                    {
                        num *= 10f;
                    }
                    if (tmpRequiredApparels.Contains(ap.def))
                    {
                        num *= 25f;
                    }
                }
            }
            return(num);
        }
Beispiel #28
0
 /// <summary>
 /// When notified job is about to start, calculate unequip delay for underlying apparel.
 /// </summary>
 public override void Notify_Starting()
 {
     base.Notify_Starting();
     _apparel  = TargetThingA as Apparel;
     _duration = (int)(_apparel.GetStatValue(StatDefOf.EquipDelay) * 60f);
 }
Beispiel #29
0
 public float CalculateApparelScoreRawInsulationColdAjust(Apparel ap)
 {
     float num3 = 1f;
     if (this.needWarmCurve != null)
     {
         float statValueAbstract = ap.GetStatValue(StatDefOf.Insulation_Cold);
         num3 *= this.needWarmCurve.Evaluate(statValueAbstract);
     }
     if (this.needCoolCurve != null)
     {
         float statValueAbstract = ap.GetStatValue(StatDefOf.Insulation_Heat);
         num3 *= this.needCoolCurve.Evaluate(statValueAbstract);
     }
     return num3;
 }
Beispiel #30
0
        public static float ApparelScoreRaw(Apparel apparel, Pawn pawn)
        {
            // relevant apparel stats
            HashSet <StatDef> equippedOffsets = new HashSet <StatDef>();

            if (apparel.def.equippedStatOffsets != null)
            {
                foreach (StatModifier equippedStatOffset in apparel.def.equippedStatOffsets)
                {
                    equippedOffsets.Add(equippedStatOffset.stat);
                }
            }
            HashSet <StatDef> statBases = new HashSet <StatDef>();

            if (apparel.def.statBases != null)
            {
                foreach (StatModifier statBase in apparel.def.statBases)
                {
                    statBases.Add(statBase.stat);
                }
            }

            // start score at 1
            float score = 1;

            // make infusions ready
            InfusionSet infusions;
            bool        infused = false;
            StatMod     mod;
            InfusionDef prefix = null;
            InfusionDef suffix = null;

            if (apparel.TryGetInfusions(out infusions))
            {
                infused = true;
                prefix  = infusions.Prefix.ToInfusionDef();
                suffix  = infusions.Suffix.ToInfusionDef();
            }

            // add values for each statdef modified by the apparel
            foreach (ApparelStatCache.StatPriority statPriority in pawn.GetApparelStatCache().StatCache)
            {
                // statbases, e.g. armor
                if (statBases.Contains(statPriority.Stat))
                {
                    // add stat to base score before offsets are handled ( the pawn's apparel stat cache always has armors first as it is initialized with it).
                    score += apparel.GetStatValue(statPriority.Stat) * statPriority.Weight;
                }

                // equipped offsets, e.g. movement speeds
                if (equippedOffsets.Contains(statPriority.Stat))
                {
                    // base value
                    float norm     = apparel.GetStatValue(statPriority.Stat);
                    float adjusted = norm;

                    // add offset
                    adjusted += apparel.def.equippedStatOffsets.GetStatOffsetFromList(statPriority.Stat) *
                                statPriority.Weight;

                    // normalize
                    if (norm != 0)
                    {
                        adjusted /= norm;
                    }

                    // multiply score to favour items with multiple offsets
                    score *= adjusted;

                    //debug.AppendLine( statWeightPair.Key.LabelCap + ": " + score );
                }

                // infusions
                if (infused)
                {
                    // prefix
                    if (!infusions.PassPre &&
                        prefix.GetStatValue(statPriority.Stat, out mod))
                    {
                        score += mod.offset * statPriority.Weight;
                        score += score * (mod.multiplier - 1) * statPriority.Weight;

                        //debug.AppendLine( statWeightPair.Key.LabelCap + " infusion: " + score );
                    }
                    if (!infusions.PassSuf &&
                        suffix.GetStatValue(statPriority.Stat, out mod))
                    {
                        score += mod.offset * statPriority.Weight;
                        score += score * (mod.multiplier - 1) * statPriority.Weight;

                        //debug.AppendLine( statWeightPair.Key.LabelCap + " infusion: " + score );
                    }
                }
            }

            // offset for apparel hitpoints
            if (apparel.def.useHitPoints)
            {
                // durability on 0-1 scale
                float x = apparel.HitPoints / (float)apparel.MaxHitPoints;
                score *= HitPointsPercentScoreFactorCurve.Evaluate(x);
            }

            // temperature
            FloatRange targetTemperatures  = pawn.GetApparelStatCache().TargetTemperatures;
            float      minComfyTemperature = pawn.GetStatValue(StatDefOf.ComfyTemperatureMin);
            float      maxComfyTemperature = pawn.GetStatValue(StatDefOf.ComfyTemperatureMax);

            // offsets on apparel
            float insulationCold = apparel.GetStatValue(StatDefOf.Insulation_Cold);
            float insulationHeat = apparel.GetStatValue(StatDefOf.Insulation_Heat);

            // offsets on apparel infusions
            if (infused)
            {
                // prefix
                if (!infusions.PassPre &&
                    prefix.GetStatValue(StatDefOf.ComfyTemperatureMin, out mod))
                {
                    insulationCold += mod.offset;
                }
                if (!infusions.PassPre &&
                    prefix.GetStatValue(StatDefOf.ComfyTemperatureMax, out mod))
                {
                    insulationHeat += mod.offset;
                }

                // suffix
                if (!infusions.PassSuf &&
                    suffix.GetStatValue(StatDefOf.ComfyTemperatureMin, out mod))
                {
                    insulationCold += mod.offset;
                }
                if (!infusions.PassSuf &&
                    suffix.GetStatValue(StatDefOf.ComfyTemperatureMax, out mod))
                {
                    insulationHeat += mod.offset;
                }
            }

            // if this gear is currently worn, we need to make sure the contribution to the pawn's comfy temps is removed so the gear is properly scored
            if (pawn.apparel.WornApparel.Contains(apparel))
            {
                minComfyTemperature -= insulationCold;
                maxComfyTemperature -= insulationHeat;
            }

            // now for the interesting bit.
            float temperatureScoreOffset  = 0f;
            float tempWeight              = pawn.GetApparelStatCache().TemperatureWeight;
            float neededInsulation_Cold   = targetTemperatures.TrueMin - minComfyTemperature;  // isolation_cold is given as negative numbers < 0 means we're underdressed
            float neededInsulation_Warmth = targetTemperatures.TrueMax - maxComfyTemperature;  // isolation_warm is given as positive numbers.

            // currently too cold
            if (neededInsulation_Cold < 0)
            {
                temperatureScoreOffset += -insulationCold * tempWeight;
            }
            // currently warm enough
            else
            {
                // this gear would make us too cold
                if (insulationCold > neededInsulation_Cold)
                {
                    temperatureScoreOffset += (neededInsulation_Cold - insulationCold) * tempWeight;
                }
            }

            // currently too warm
            if (neededInsulation_Warmth > 0)
            {
                temperatureScoreOffset += insulationHeat * tempWeight;
            }
            // currently cool enough
            else
            {
                // this gear would make us too warm
                if (insulationHeat < neededInsulation_Warmth)
                {
                    temperatureScoreOffset += -(neededInsulation_Warmth - insulationHeat) * tempWeight;
                }
            }

            // adjust for temperatures
            score += temperatureScoreOffset / 10f;

            return(score);
        }
Beispiel #31
0
        /// <summary>
        /// Calculates damage through armor, depending on damage type, target and natural resistance. Also calculates deflection and adjusts damage type and impacted body part accordingly.
        /// </summary>
        /// <param name="originalDinfo">The pre-armor damage info</param>
        /// <param name="pawn">The damaged pawn</param>
        /// <param name="hitPart">The pawn's body part that has been hit</param>
        /// <param name="shieldAbsorbed">Returns true if attack did not penetrate pawn's melee shield</param>
        /// <returns>If shot is deflected returns a new dinfo cloned from the original with damage amount, Def and ForceHitPart adjusted for deflection, otherwise a clone with only the damage adjusted</returns>
        public static DamageInfo GetAfterArmorDamage(DamageInfo originalDinfo, Pawn pawn, BodyPartRecord hitPart, out bool shieldAbsorbed)
        {
            shieldAbsorbed = false;

            if (originalDinfo.Def.armorCategory == null)
            {
                return(originalDinfo);
            }

            DamageInfo dinfo           = new DamageInfo(originalDinfo);
            float      dmgAmount       = dinfo.Amount;
            bool       involveArmor    = dinfo.Def.harmAllLayersUntilOutside;
            bool       isAmbientDamage = dinfo.IsAmbientDamage();

            // In case of ambient damage (fire, electricity) we apply a percentage reduction formula based on the sum of all applicable armor
            if (isAmbientDamage)
            {
                dinfo.SetAmount(Mathf.CeilToInt(GetAmbientPostArmorDamage(dmgAmount, originalDinfo.Def.armorCategory.deflectionStat, pawn, hitPart)));
                return(dinfo);
            }

            float penAmount = GetPenetrationValue(originalDinfo);

            // Apply worn armor
            if (involveArmor && pawn.apparel != null && !pawn.apparel.WornApparel.NullOrEmpty())
            {
                List <Apparel> apparel = pawn.apparel.WornApparel;

                // Check for shields first
                Apparel shield = apparel.FirstOrDefault(x => x is Apparel_Shield);
                if (shield != null)
                {
                    // Determine whether the hit is blocked by the shield
                    bool blockedByShield = false;
                    if (!(dinfo.WeaponGear?.IsMeleeWeapon ?? false))
                    {
                        var shieldDef = shield.def.GetModExtension <ShieldDefExtension>();
                        if (shieldDef == null)
                        {
                            Log.ErrorOnce("CE :: shield " + shield.def.ToString() + " is Apparel_Shield but has no ShieldDefExtension", shield.def.GetHashCode() + 12748102);
                        }
                        else
                        {
                            bool hasCoverage = shieldDef.PartIsCoveredByShield(hitPart, pawn);
                            if (hasCoverage)
                            {
                                // Right arm is vulnerable during warmup/attack/cooldown
                                blockedByShield = !((pawn.stances?.curStance as Stance_Busy)?.verb != null && hitPart.IsInGroup(CE_BodyPartGroupDefOf.RightArm));
                            }
                        }
                    }
                    // Try to penetrate the shield
                    if (blockedByShield && !TryPenetrateArmor(dinfo.Def, shield.GetStatValue(dinfo.Def.armorCategory.deflectionStat), ref penAmount, ref dmgAmount, shield))
                    {
                        shieldAbsorbed = true;
                        dinfo.SetAmount(0);

                        // Apply secondary damage to shield
                        var props = dinfo.WeaponGear.projectile as ProjectilePropertiesCE;
                        if (props != null && !props.secondaryDamage.NullOrEmpty())
                        {
                            foreach (SecondaryDamage sec in props.secondaryDamage)
                            {
                                if (shield.Destroyed)
                                {
                                    break;
                                }
                                var secDinfo = sec.GetDinfo();
                                var pen      = GetPenetrationValue(originalDinfo);
                                var dmg      = (float)secDinfo.Amount;
                                TryPenetrateArmor(secDinfo.Def, shield.GetStatValue(secDinfo.Def.armorCategory.deflectionStat), ref pen, ref dmg, shield);
                            }
                        }

                        return(dinfo);
                    }
                }

                // Apparel is arranged in draw order, we run through reverse to go from Shell -> OnSkin
                for (int i = apparel.Count - 1; i >= 0; i--)
                {
                    if (apparel[i].def.apparel.CoversBodyPart(hitPart) &&
                        !TryPenetrateArmor(dinfo.Def, apparel[i].GetStatValue(dinfo.Def.armorCategory.deflectionStat), ref penAmount, ref dmgAmount, apparel[i]))
                    {
                        // Hit was deflected, convert damage type
                        dinfo = GetDeflectDamageInfo(dinfo, hitPart);
                        i++;    // We apply this piece of apparel twice on conversion, this means we can't use deflection on Blunt or else we get an infinite loop of eternal deflection
                    }
                    if (dmgAmount <= 0)
                    {
                        dinfo.SetAmount(0);
                        return(dinfo);
                    }
                }
            }

            // Apply natural armor
            List <BodyPartRecord> partsToHit = new List <BodyPartRecord>()
            {
                hitPart
            };

            if (involveArmor)
            {
                BodyPartRecord curPart = hitPart;
                while (curPart.parent != null && curPart.depth == BodyPartDepth.Inside)
                {
                    curPart = curPart.parent;
                    partsToHit.Add(curPart);
                }
            }
            for (int i = partsToHit.Count - 1; i >= 0; i--)
            {
                BodyPartRecord curPart        = partsToHit[i];
                bool           coveredByArmor = curPart.IsInGroup(CE_BodyPartGroupDefOf.CoveredByNaturalArmor);
                float          partArmor      = pawn.HealthScale * 0.05f; // How much armor is provided by sheer meat
                if (coveredByArmor)
                {
                    partArmor += pawn.GetStatValue(dinfo.Def.armorCategory.deflectionStat);
                }
                float unused = dmgAmount;

                // Only apply damage reduction when penetrating armored body parts
                if (coveredByArmor ? !TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref dmgAmount) : !TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref unused))
                {
                    dinfo.SetForcedHitPart(curPart);

                    /*
                     * if(coveredByArmor && pawn.RaceProps.IsMechanoid)
                     * {
                     *  // For Mechanoid natural armor, apply deflection and blunt armor
                     *  dinfo = GetDeflectDamageInfo(dinfo, curPart);
                     *  TryPenetrateArmor(dinfo.Def, partArmor, ref penAmount, ref dmgAmount);
                     * }
                     */
                    break;
                }
                if (dmgAmount <= 0)
                {
                    dinfo.SetAmount(0);
                    return(dinfo);
                }
            }

            dinfo.SetAmount(Mathf.CeilToInt(dmgAmount));
            return(dinfo);
        }
Beispiel #32
0
        public override void DoWindowContents(Rect inRect)
        {
            var conf = _pawn.GetApparelStatCache();

            var conRect = new Rect(inRect);

            conRect.height -= 50f;

            BeginArea(conRect);

            // begin main group
            BeginVertical();

            Label(GetTitle(), _headline);
            Text.Font = GameFont.Small;

            // GUI.BeginGroup(contentRect);
            var labelWidth = conRect.width - BaseValue - BaseValue - BaseValue - 48f;

            DrawLine("Status", labelWidth, "BaseMod", "Strength", "Score", _fontBold);

            Space(6f);
            Label(string.Empty, _whiteLine, Height(1));
            Space(6f);

            var apparelEntry = conf.GetAllOffsets(_apparel);

            var equippedOffsets = apparelEntry.EquippedOffsets;
            var statBases       = apparelEntry.StatBases;
            var infusedOffsets  = apparelEntry.InfusedOffsets;

            _scrollPosition = BeginScrollView(_scrollPosition, Width(conRect.width));

            // relevant apparel stats

            // start score at 1
            float score = 1;

            // add values for each statdef modified by the apparel
            foreach (var statPriority in _pawn.GetApparelStatCache().StatCache
                     .OrderBy(i => i.Stat.LabelCap))
            {
                var    stat      = statPriority.Stat;
                string statLabel = stat.LabelCap;

                // statbases, e.g. armor

                // StatCache.DoApparelScoreRaw_PawnStatsHandlers(_pawn, _apparel, statPriority.Stat, ref currentStat);
                if (statBases.Contains(stat))
                {
                    var statValue = _apparel.GetStatValue(stat);
                    var statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(_apparel, statPriority, _pawn, statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        // statValue += StatCache.StatInfused(infusionSet, statPriority, ref baseInfused);
                        statScore = statValue * statPriority.Weight;
                    }

                    score += statScore;

                    DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));
                }

                if (equippedOffsets.Contains(stat))
                {
                    var statValue = _apparel.GetEquippedStatValue(_pawn, stat);

                    // statValue += StatCache.StatInfused(infusionSet, statPriority, ref equippedInfused);
                    var statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(_apparel, statPriority, _pawn, statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        statScore = statValue * statPriority.Weight;
                    }

                    score += statScore;

                    DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));
                }

                if (!infusedOffsets.Contains(stat))
                {
                    continue;
                }

                {
                    GUI.color = Color.green; // new Color(0.5f, 1f, 1f, 1f);

                    // float statInfused = StatCache.StatInfused(infusionSet, statPriority, ref dontcare);
                    ApparelStatCache.DoApparelScoreRaw_PawnStatsHandlers(_apparel, stat, out var statValue);

                    var flag = true;

                    var statScore = 0f;
                    if (ApparelStatCache.SpecialStats.Contains(stat))
                    {
                        ApparelStatCache.CalculateScoreForSpecialStats(_apparel,
                                                                       statPriority, _pawn,
                                                                       statValue,
                                                                       ref statScore);
                    }
                    else
                    {
                        // Bug with Infused and "Ancient", it completely kills the pawn's armor
                        if (statValue < 0 &&
                            (stat == StatDefOf.ArmorRating_Blunt || stat == StatDefOf.ArmorRating_Sharp))
                        {
                            score = -2f;
                            flag  = false;
                        }

                        statScore = statValue * statPriority.Weight;
                    }

                    DrawLine(
                        statLabel,
                        labelWidth,
                        statValue.ToStringPercent("N1"),
                        statPriority.Weight.ToString("N2"),
                        statScore.ToString("N2"));

                    GUI.color = Color.white;

                    if (flag)
                    {
                        score += statScore;
                    }
                    else
                    {
                        break;
                    }
                }
            }

            GUI.color = Color.white;

            // end upper group
            EndScrollView();

            // begin lower group
            FlexibleSpace();
            Space(6f);
            Label(string.Empty, _whiteLine, Height(1));
            Space(6f);
            DrawLine(string.Empty, labelWidth, "Modifier", string.Empty, "Subtotal");

            DrawLine("BasicStatusOfApparel".Translate(), labelWidth, "1.00", "+", score.ToString("N2"));

            var special = _apparel.GetSpecialApparelScoreOffset();

            if (Math.Abs(special) > 0f)
            {
                score += special;

                DrawLine(
                    "OutfitterSpecialScore".Translate(),
                    labelWidth,
                    special.ToString("N2"),
                    "+",
                    score.ToString("N2"));
            }

            var armor = ApparelStatCache.ApparelScoreRaw_ProtectionBaseStat(_apparel);

            if (Math.Abs(armor) > 0.01f)
            {
                score += armor;

                DrawLine("OutfitterArmor".Translate(), labelWidth, armor.ToString("N2"), "+", score.ToString("N2"));
            }

            if (_apparel.def.useHitPoints)
            {
                // durability on 0-1 scale
                var x = _apparel.HitPoints / (float)_apparel.MaxHitPoints;
                score *= ApparelStatsHelper.HitPointsPercentScoreFactorCurve.Evaluate(x);

                DrawLine(
                    "OutfitterHitPoints".Translate(),
                    labelWidth,
                    x.ToString("N2"),
                    "weighted",
                    score.ToString("N2"));

                GUI.color = Color.white;
            }

            if (_apparel.WornByCorpse && ThoughtUtility.CanGetThought_NewTemp(_pawn, ThoughtDefOf.DeadMansApparel))
            {
                score -= 0.5f;
                if (score > 0f)
                {
                    score *= 0.1f;
                }

                DrawLine(
                    "OutfitterWornByCorpse".Translate(),
                    labelWidth,
                    "modified",
                    "weighted",
                    score.ToString("N2"));
            }

            if (_apparel.Stuff == ThingDefOf.Human.race.leatherDef)
            {
                if (ThoughtUtility.CanGetThought_NewTemp(_pawn, ThoughtDefOf.HumanLeatherApparelSad))
                {
                    score -= 0.5f;
                    if (score > 0f)
                    {
                        score *= 0.1f;
                    }
                }

                if (ThoughtUtility.CanGetThought_NewTemp(_pawn, ThoughtDefOf.HumanLeatherApparelHappy))
                {
                    score *= 2f;
                }

                DrawLine(
                    "OutfitterHumanLeather".Translate(),
                    labelWidth,
                    "modified",
                    "weighted",
                    score.ToString("N2"));
            }

            var temperature = conf.ApparelScoreRaw_Temperature(_apparel);

            if (Math.Abs(temperature - 1f) > 0)
            {
                score *= temperature;

                DrawLine(
                    "OutfitterTemperature".Translate(),
                    labelWidth,
                    temperature.ToString("N2"),
                    "*",
                    score.ToString("N2"));
            }

            DrawLine(
                "OutfitterTotal".Translate(),
                labelWidth,
                string.Empty,
                "=",
                conf.ApparelScoreRaw(_apparel).ToString("N2"));

            GUI.color   = Color.white;
            Text.Anchor = TextAnchor.UpperLeft;

            // end main group
            EndVertical();
            EndArea();
        }
Beispiel #33
0
 private static void ApplyInsulationScoring(Pawn pawn, Apparel apparel, ref float score)
 {
     #if DEBUG
     Log.Message("OutfitManager: Calculating scores for insulation", true);
     #endif
     if (pawn.apparel.WornApparel.Contains(apparel))
     {
         score += 0f;
     }
     else
     {
         var currentRange   = pawn.ComfortableTemperatureRange();
         var candidateRange = currentRange;
         var seasonalTemp   = pawn.Map.mapTemperature.SeasonalTemp;
         var targetRange    = new FloatRange(seasonalTemp - TemperatureRangeOffset,
                                             seasonalTemp + TemperatureRangeOffset);
         var apparelOffset = new FloatRange(-apparel.GetStatValue(StatDefOf.Insulation_Cold),
                                            apparel.GetStatValue(StatDefOf.Insulation_Heat));
         candidateRange.min += apparelOffset.min;
         candidateRange.max += apparelOffset.max;
         foreach (var wornApparel in pawn.apparel.WornApparel.Where(wornApparel =>
                                                                    !ApparelUtility.CanWearTogether(apparel.def, wornApparel.def, pawn.RaceProps.body)))
         {
             var wornInsulationRange = new FloatRange(-wornApparel.GetStatValue(StatDefOf.Insulation_Cold),
                                                      wornApparel.GetStatValue(StatDefOf.Insulation_Heat));
             candidateRange.min -= wornInsulationRange.min;
             candidateRange.max -= wornInsulationRange.max;
         }
         var insulationScore = 0f;
         var coldBenefit     = candidateRange.min <currentRange.min
             ? currentRange.min <= targetRange.min
                 ? 0
                                                   :
                                                   candidateRange.min <= targetRange.min && currentRange.min> targetRange.min
                     ?
                               currentRange.min - targetRange.min
                     : currentRange.min - candidateRange.min
                               :
                               candidateRange.min <= targetRange.min
                 ? 0
                 :
                               currentRange.min <= targetRange.min && candidateRange.min > targetRange.min
                     ?
                               targetRange.min - candidateRange.min
                     : currentRange.min - candidateRange.min;
         insulationScore += InsulationScoreCurve.Evaluate(coldBenefit);
         var heatBenefit = candidateRange.max < currentRange.max
             ? currentRange.max < targetRange.max
                 ?
                           candidateRange.max - currentRange.max
                 : candidateRange.max < targetRange.max && currentRange.max >= targetRange.max
                     ? candidateRange.max - targetRange.max
                     : 0
             :
                           candidateRange.max < targetRange.max
                 ? candidateRange.max - currentRange.max
                 :
                           currentRange.max < targetRange.max && candidateRange.max >= targetRange.max
                     ?
                           targetRange.max - currentRange.max
                     : 0;
         insulationScore += InsulationScoreCurve.Evaluate(heatBenefit);
         #if DEBUG
         Log.Message(
             $"OutfitManager: target range: {targetRange}, current range: {currentRange}, candidate range: {candidateRange}",
             true);
         Log.Message(
             $"OutfitManager: cold benefit = {coldBenefit}, heat benefit = {heatBenefit}), insulation score = {insulationScore}",
             true);
         #endif
         score += insulationScore;
     }
 }