Esempio n. 1
0
        private static string ApparelPart(ApparelFlags effectMask, Comp_NightVision comp)
        {
            var builder = new StringBuilder();

            builder.AppendLine(value: "StatsReport_RelevantGear".Translate());
            var nvApparel = Settings.Store.NVApparel;

            foreach (Apparel app in comp.PawnsNVApparel ?? Enumerable.Empty <Apparel>())
            {
                if (nvApparel.TryGetValue(key: app.def, value: out ApparelVisionSetting setting) &&
                    setting.HasEffect(effectMask))
                {
                    builder.AppendLine(value: app.LabelCap);
                }
            }

            return(builder.ToString());
        }
Esempio n. 2
0
        /// <summary>
        /// Tries to find the nightvision comp of the given pawn.
        /// Returns null if the pawn is null or pawn does not have comp.
        /// </summary>
        /// <param name="pawn"></param>
        /// <returns>the pawn's comp or NULL</returns>
        public static Comp_NightVision CompFor(Pawn pawn)
        {
            if (pawn == null)
            {
                return(null);
            }
            if (pawn.GetHashCode() == cachedPawnHash)
            {
                return(cachedComp);
            }
            else if (pawn.TryGetComp <Comp_NightVision>() is Comp_NightVision comp)
            {
                cachedComp     = comp;
                cachedPawnHash = pawn.GetHashCode();

                return(comp);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 3
0
        /// <summary>
        ///     For the pawn's stat inspect tab. Cleaned up a bit, still about as elegant as a panda doing the can-can
        /// </summary>
        /// <param name="glow"></param>
        /// <param name="usedApparelSetting">if apparel had an effect</param>
        /// <param name="comp"></param>
        /// <param name="needsFinalValue">if final value is added externally or we need to add it</param>
        /// <returns></returns>
        private static string BasicExplanation(float glow, out bool usedApparelSetting, Comp_NightVision comp, bool needsFinalValue = false)
        {
            var nvsum = 0f;
            var pssum = 0f;
            var sum   = 0f;

            float[] caps           = LightModifiersBase.GetCapsAtGlow(glow: glow);
            var     foundSomething = false;
            float   effect;
            var     basevalue = 0f;
            bool    lowLight  = glow.GlowIsDarkness();

            usedApparelSetting = false;


            var explanation = new StringBuilder();

            StringBuilder nvexplanation = new StringBuilder().AppendFormat(
                format: Str.ExpIntro,
                "",
                Str.MaxAtGlow(glow: glow),
                caps[2],
                Str.NightVision
                ).AppendLine();

            StringBuilder psexplanation = new StringBuilder().AppendFormat(
                format: Str.ExpIntro,
                "",
                Str.MaxAtGlow(glow: glow),
                caps[3],
                Str.Photosens
                ).AppendLine();


            explanation.AppendLine();

            if (lowLight)
            {
                basevalue = Constants.DEFAULT_FULL_LIGHT_MULTIPLIER
                            + (Constants.DEFAULT_ZERO_LIGHT_MULTIPLIER - Constants.DEFAULT_FULL_LIGHT_MULTIPLIER)
                            * (0.3f - glow)
                            / 0.3f;

                if (comp.ApparelGrantsNV)
                {
                    foundSomething = true;
                }
            }
            else
            {
                basevalue = Constants.DEFAULT_FULL_LIGHT_MULTIPLIER;

                if (glow.GlowIsBright() && comp.ApparelNullsPS)
                {
                    foundSomething = true;
                }
            }

            explanation.AppendFormat(format: "  " + Str.MultiplierLine, arg0: "StatsReport_BaseValue".Translate(), arg1: basevalue).AppendLine()
            .AppendLine();

            string StringToAppend;

            if (comp.NaturalLightModifiers.HasAnyModifier() && comp.NumberOfRemainingEyes > 0)
            {
                effect = comp.NaturalLightModifiers.GetEffectAtGlow(glow: glow);

                if (effect.IsNonTrivial())
                {
                    foundSomething = true;

                    var NumToAdd = (float)Math.Round(
                        value: effect * comp.NumberOfRemainingEyes,
                        digits: Constants.NUMBER_OF_DIGITS,
                        mode: Constants.ROUNDING
                        );

                    StringToAppend = string.Format(
                        format: "    " + Str.ModifierLine,
                        arg0: $"{comp.ParentPawn.def.LabelCap} {comp.RaceSightParts.First().LabelShort} x{comp.NumberOfRemainingEyes}",
                        arg1: effect * comp.NumberOfRemainingEyes
                        );

                    switch (comp.NaturalLightModifiers.Setting)
                    {
                    case VisionType.NVNightVision:
                        nvsum += NumToAdd;
                        nvexplanation.AppendLine(value: StringToAppend);

                        break;

                    case VisionType.NVPhotosensitivity:
                        pssum += NumToAdd;
                        psexplanation.AppendLine(value: StringToAppend);

                        break;

                    case VisionType.NVCustom:
                        sum += NumToAdd;
                        explanation.AppendLine(value: StringToAppend);

                        break;
                    }
                }
            }

            foreach (List <HediffDef> value in comp.PawnsNVHediffs.Values)
            {
                if (value.NullOrEmpty())
                {
                    continue;
                }


                var hediffLightMods = Settings.Store.HediffLightMods;
                foreach (HediffDef hediffDef in value)
                {
                    if (hediffLightMods.TryGetValue(key: hediffDef, value: out Hediff_LightModifiers hediffSetting))
                    {
                        effect = hediffSetting.GetEffectAtGlow(glow: glow, numOfEyesNormalisedFor: comp.EyeCount);

                        if (effect.IsNonTrivial())
                        {
                            foundSomething = true;

                            effect = (float)Math.Round(
                                value: effect,
                                digits: Constants.NUMBER_OF_DIGITS,
                                mode: Constants.ROUNDING
                                );

                            StringToAppend = string.Format(format: "    " + Str.ModifierLine, arg0: hediffDef.LabelCap, arg1: effect);

                            switch (hediffSetting.IntSetting)
                            {
                            case VisionType.NVNightVision:
                                nvsum += effect;
                                nvexplanation.AppendLine(value: StringToAppend);

                                break;

                            case VisionType.NVPhotosensitivity:
                                pssum += effect;
                                psexplanation.AppendLine(value: StringToAppend);

                                break;

                            case VisionType.NVCustom:
                                sum += effect;
                                explanation.AppendLine(value: StringToAppend);

                                break;
                            }
                        }
                    }
                }
            }

            void AppendPreSumIfNeeded(ref bool needed)
            {
                if (!needed)
                {
                    return;
                }

                explanation.AppendFormat(
                    format: Str.MultiplierLine,
                    arg0: "NVTotal".Translate() + " " + "NVMultiplier".Translate(),
                    arg1: sum + basevalue
                    );

                explanation.AppendLine();

                needed = false;
            }

            if (foundSomething)
            {
                if (nvsum.IsNonTrivial())
                {
                    explanation.Append(value: nvexplanation);
                    explanation.AppendLine();
                }

                if (pssum.IsNonTrivial())
                {
                    explanation.Append(value: psexplanation);
                    explanation.AppendLine();
                }

                sum += pssum + nvsum;

                explanation.AppendFormat(format: Str.ModifierLine, arg0: "NVTotal".Translate() + " " + "NVModifier".Translate(), arg1: sum);

                explanation.AppendLine();


                var needed = true;

                if (!comp.CanCheat)
                {
                    if (sum - Constants.NV_EPSILON > caps[0] || sum + Constants.NV_EPSILON < caps[1])
                    {
                        AppendPreSumIfNeeded(needed: ref needed);

                        explanation.AppendFormat(
                            format: Str.Maxline,
                            arg0: "NVTotal".Translate() + " ",
                            arg1: "max".Translate(),
                            arg2: sum > caps[0] ? caps[0] : caps[1]
                            );

                        explanation.AppendLine();
                    }

                    if (lowLight && comp.ApparelGrantsNV && sum + Constants.NV_EPSILON < caps[2])
                    {
                        AppendPreSumIfNeeded(needed: ref needed);
                        explanation.Append(value: "NVGearPresent".Translate(arg1: $"{basevalue + caps[2]:0%}"));
                        usedApparelSetting = true;
                        sum = caps[2];
                    }
                    else if (comp.ApparelNullsPS && sum + Constants.NV_EPSILON < 0)
                    {
                        AppendPreSumIfNeeded(needed: ref needed);
                        explanation.Append(value: "PSGearPresent".Translate(arg1: $"{Constants.DEFAULT_FULL_LIGHT_MULTIPLIER:0%}"));
                        usedApparelSetting = true;
                        sum = 0;
                    }
                }

                explanation.AppendLine();

                if (needsFinalValue)
                {
                    sum += basevalue;

                    explanation.AppendFormat(
                        format: Str.MultiplierLine,
                        arg0: "NVStatReport_FinalMulti".Translate(),
                        arg1: sum > caps[0] + basevalue ? caps[0] + basevalue :
                        sum < caps[1] + basevalue ? caps[1] + basevalue : sum
                        );
                }

                return(explanation.ToString());
            }

            //Fallback
            if (needsFinalValue)
            {
                return(comp.FactorFromGlow(glow: glow).ToStringPercent());
            }

            return(string.Empty);
        }
Esempio n. 4
0
 public static string ShortStatReport(float glow, Comp_NightVision comp)
 {
     return(BasicExplanation(glow: glow, usedApparelSetting: out _, comp: comp, needsFinalValue: true));
 }
Esempio n. 5
0
        public static string CompleteStatReport(StatDef stat, ApparelFlags effectMask, Comp_NightVision comp, float relevantGlow)
        {
            float factorFromGlow = comp.FactorFromGlow(glow: relevantGlow);

            return(BasicExplanation(glow: relevantGlow, usedApparelSetting: out bool UsedApparel, comp: comp)
                   + FinalValue(stat: stat, value: factorFromGlow)
                   + (effectMask != ApparelFlags.None && UsedApparel ? ApparelPart(effectMask: effectMask, comp: comp) : ""));
        }
        public static string CombatPart(Pawn pawn, Comp_NightVision comp)
        {
            var         strHelper       = new CombatStatStrHelper();
            const float NoLight         = 0f;
            const float FullLight       = 1f;
            float       noLightFactor   = comp.FactorFromGlow(glow: NoLight);
            float       fullLightFactor = comp.FactorFromGlow(glow: FullLight);


            strHelper.AddMainHeader();

            if (Settings.CombatStore.RangedHitEffectsEnabled.Value)
            {
                if (ShowRangedEffectsForPawn(pawn))
                {
                    strHelper.AddLine(Str_Combat.ShootTargetAtGlow());


                    for (var i = 1; i <= 4; i++)
                    {
                        float hit = ShotReport.HitFactorFromShooter(caster: pawn, distance: i * 5);

                        strHelper.AddLine(
                            Str_Combat.ShotChanceTransform(
                                distance: i * 5,
                                hitChance: hit,
                                nvResult: CombatHelpers.HitChanceGlowTransform(hitChance: hit,
                                                                               attGlowFactor: noLightFactor),
                                psResult: CombatHelpers.HitChanceGlowTransform(hitChance: hit,
                                                                               attGlowFactor: fullLightFactor)
                                )
                            );
                    }

                    strHelper.NextLine();
                }
                else
                {
                    // TODO add line reporting why effects are not appearing
                }
            }

            if (Settings.CombatStore.MeleeHitEffectsEnabled.Value)
            {
                if (ShowMeleeEffectsForPawn(pawn))
                {
                    float pawnDodgeVal = pawn.GetStatValue(stat: Defs_Rimworld.MeleeDodgeStat);
                    float meleeHit     = pawn.GetStatValue(stat: Defs_Rimworld.MeleeHitStat, applyPostProcess: true);

                    var caps = Settings.Store.MultiplierCaps;

                    strHelper.AddLine(Str_Combat.StrikeTargetAtGlow());


                    strHelper.AddLine(
                        Str_Combat.StrikeChanceTransform(
                            hitChance: meleeHit,
                            nvResult: CombatHelpers.HitChanceGlowTransform(hitChance: meleeHit,
                                                                           attGlowFactor: noLightFactor),
                            psResult: CombatHelpers.HitChanceGlowTransform(hitChance: meleeHit,
                                                                           attGlowFactor: fullLightFactor)
                            )
                        );

                    strHelper.NextLine();

                    strHelper.AddSurpriseAttackHeader();

                    ///////////////////////////////////////////
                    //// Surprise attack stats at 0% light ////

                    float noLightSurpAttChance =
                        CombatHelpers.SurpriseAttackChance(atkGlowFactor: noLightFactor, defGlowFactor: caps.min);
                    // attack vs pawn with minimum LM
                    strHelper.AddSurpriseAttackRow(NoLight, noLightFactor, caps.min);

                    // skip if we need more room to show dodge stats
                    if (pawnDodgeVal.IsTrivial())
                    {
                        //skip if chance was 0% vs pawn with min LM (as it won't be different
                        if (noLightSurpAttChance.IsNonTrivial())
                        {
                            // attack vs pawn with normal LM
                            noLightSurpAttChance =
                                CombatHelpers.SurpriseAttackChance(atkGlowFactor: noLightFactor, defGlowFactor: 1f);

                            strHelper.AddSurpriseAttackRow(NoLight, noLightFactor, 1);

                            // skip as above
                            if (noLightSurpAttChance.IsNonTrivial())
                            {
                                // attack vs pawn with max LM
                                strHelper.AddSurpriseAttackRow(0, noLightFactor, caps.max);
                            }
                        }
                    }
                    ////////////////////////////////////////////

                    /////////////////////////////////////////////
                    //// Surprise attack stats at 100% light ////

                    // skip if we need more room to show dodge stats
                    if (pawnDodgeVal.IsTrivial())
                    {
                        // attack vs pawn with min LM
                        strHelper.AddSurpriseAttackRow(fullLightFactor, fullLightFactor, caps.min);
                    }

                    // attack vs pawn with normal LM
                    strHelper.AddSurpriseAttackRow(fullLightFactor, fullLightFactor, 1f);
                    strHelper.NextLine();
                    /////////////////////////////////////////////

                    /////////////////////////////////////////////
                    ////             Dodge Stats             ////


                    strHelper.AddDodgeHeader();

                    // This pawns chance to dodge when attacked

                    // attacked by pawn with min LM in no light
                    strHelper.AddDodgeRow(NoLight, caps.min, noLightFactor, pawnDodgeVal);

                    // skip if pawns dodge value is zero
                    if (pawnDodgeVal.IsNonTrivial())
                    {
                        // attacked by pawn with normal LM in no light
                        strHelper.AddDodgeRow(NoLight, 1f, noLightFactor, pawnDodgeVal);

                        // attacked by pawn with max LM in no light
                        strHelper.AddDodgeRow(NoLight, caps.max, noLightFactor, pawnDodgeVal);

                        // attacked by pawn with min LM in no light
                        strHelper.AddDodgeRow(FullLight, caps.min, fullLightFactor, pawnDodgeVal);
                    }

                    //attacked by pawn with normal LM in full light
                    strHelper.AddDodgeRow(FullLight, 1, fullLightFactor, pawnDodgeVal);
                }
            }

            return(strHelper.ToString());
        }