// Display the initiative modifiers for the current unit as a buff that folks can hover over for details.
        public static void Postfix(CombatHUDStatusPanel __instance)
        {
            Mod.Log.Debug("___ CombatHUDStatusPanel:ShowActorStatuses:post - entered.");

            if (__instance.DisplayedCombatant != null)
            {
                AbstractActor actor    = __instance.DisplayedCombatant as AbstractActor;
                bool          isPlayer = actor.team == actor.Combat.LocalPlayerTeam;
                if (isPlayer)
                {
                    Type[]   iconMethodParams   = new Type[] { typeof(SVGAsset), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) };
                    Traverse showBuffIconMethod = Traverse.Create(__instance).Method("ShowBuff", iconMethodParams);

                    Type[]   stringMethodParams   = new Type[] { typeof(string), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) };
                    Traverse showBuffStringMethod = Traverse.Create(__instance).Method("ShowBuff", stringMethodParams);

                    showBuffIconMethod.GetValue(new object[] {
                        LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusSensorLockIcon,
                        new Text("INITIATIVE", new object[0]),
                        new Text(BuildTooltipText(actor)),
                        __instance.effectIconScale,
                        false
                    });
                }
            }
        }
        public static void Postfix(CombatHUDStatusPanel __instance, List <CombatHUDStatusIndicator> ___Buffs, List <CombatHUDStatusIndicator> ___Debuffs)
        {
            Mod.Log.Trace?.Write("CHUDSP:RDC - entered.");
            if (__instance != null && __instance.DisplayedCombatant != null)
            {
                AbstractActor target = __instance.DisplayedCombatant as AbstractActor;
                // We can receive a building here, so
                if (target != null)
                {
                    if (target.Combat.HostilityMatrix.IsLocalPlayerEnemy(target.team))
                    {
                        SensorScanType scanType = SensorLockHelper.CalculateSharedLock(target, ModState.LastPlayerActorActivated);

                        // Hide the buffs and debuffs if the current scanType is less than allInfo
                        if (scanType < SensorScanType.AllInformation)
                        {
                            //// Hide the buffs and debuffs
                            ___Buffs.ForEach(si => si.gameObject.SetActive(false));
                            ___Debuffs.ForEach(si => si.gameObject.SetActive(false));
                        }
                    }

                    // Calculate stealth pips
                    Traverse stealthDisplayT = Traverse.Create(__instance).Field("stealthDisplay");
                    CombatHUDStealthBarPips stealthDisplay = stealthDisplayT.GetValue <CombatHUDStealthBarPips>();
                    VfxHelper.CalculateMimeticPips(stealthDisplay, target);
                }
            }
        }
Esempio n. 3
0
        static bool Prefix(CombatHUDStatusPanel __instance, AbstractActor actor)
        {
            if (actor.UnitType == UnitType.Vehicle)
            {
                var dmg = actor.Combat.Constants.ResolutionConstants.MeleeDamageMultiplierVehicle * 100;
                _showDebuff.Invoke(__instance,
                                   new object[]
                {
                    LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusVehicleMeleeIcon,
                    new Text(ModText.CG_Title_WeakMelee, Array.Empty <object>()),
                    new Text(ModText.CG_Text_WeakMeleeVehicles, dmg),
                    __instance.defaultIconScale, false
                });
                return(false);
            }

            if (actor.UnitType == UnitType.Turret)
            {
                var dmg = actor.Combat.Constants.ResolutionConstants.MeleeDamageMultiplierTurret * 100;
                _showDebuff.Invoke(__instance,
                                   new object[]
                {
                    LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusVehicleMeleeIcon,
                    new Text(ModText.CG_Title_WeakMelee, Array.Empty <object>()),
                    new Text(ModText.CG_Text_WeakMeleeTurrets, dmg),
                    __instance.defaultIconScale, false
                });
                return(false);
            }

            return(false);
        }
Esempio n. 4
0
 public static void Prefix(CombatHUDStatusPanel __instance)
 {
     if (__instance.gameObject.GetComponent <RefreshIndicator>() == null)
     {
         __instance.gameObject.AddComponent <RefreshIndicator>();
     }
 }
Esempio n. 5
0
 public static bool Prefix(CombatHUDStatusPanel __instance, List <WayPoint> waypoints)
 {
     if (waypoints.Count == 0)
     {
         return(false);
     }
     return(true);
 }
        public static void Postfix(CombatHUDStatusPanel __instance, AbstractActor target, float previewStealth, CombatHUDStealthBarPips ___stealthDisplay)
        {
            if (___stealthDisplay == null)
            {
                return;
            }
            Mod.Log.Trace?.Write("CHUDSP:SSI:float - entered.");

            VfxHelper.CalculateMimeticPips(___stealthDisplay, target);
        }
Esempio n. 7
0
        private static void Postfix(CombatHUDStatusPanel __instance, Mech mech)
        {
            var        type            = __instance.GetType();
            MethodInfo methodInfo      = type.GetMethod("ShowDebuff", (BindingFlags.NonPublic | BindingFlags.Instance), null, new Type[] { typeof(SVGAsset), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) }, new ParameterModifier[5]);
            int        turnsOverheated = mech.StatCollection.GetValue <int>("TurnsOverheated");

            if (mech.IsShutDown)
            {
                methodInfo.Invoke(__instance, new object[] { LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusShutDownIcon, new Text("SHUT DOWN", new object[0]), new Text("This target is easier to hit, and Called Shots can be made against this target.", new object[0]), __instance.defaultIconScale, false });
            }
            else if (mech.IsOverheated)
            {
                string descr = string.Format("This unit may trigger a Shutdown at the end of the turn unless heat falls below critical levels.\nShutdown Chance: {0:P2}\nAmmo Explosion Chance: {1:P2}", CBTHeat.GetShutdownPercentageForTurn(turnsOverheated), CBTHeat.GetAmmoExplosionPercentageForTurn(turnsOverheated));
                methodInfo.Invoke(__instance, new object[] { LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusOverheatingIcon, new Text("OVERHEATING", new object[0]), new Text(descr, new object[0]), __instance.defaultIconScale, false });
            }
        }
Esempio n. 8
0
            static void Postfix(CombatHUDStatusPanel __instance, AbstractActor target)
            {
                try
                {
                    if (target == null)
                    {
                        return;
                    }

                    Logger.Debug($"---");
                    Logger.Debug($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] target: {target.DisplayName}");
                    Logger.Info($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] target.HasJumpedThisRound: {target.HasJumpedThisRound}");
                    Logger.Info($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] target.JumpedLastRound: {target.JumpedLastRound}");
                    Logger.Info($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] target.HasMovedThisRound: {target.HasMovedThisRound}");

                    bool isMoveStatusPreview          = __instance.GetComponentInParent(typeof(MoveStatusPreview)) != null;
                    bool isCombatHUDMechTray          = __instance.GetComponentInParent(typeof(CombatHUDMechTray)) != null;
                    bool isCombatHUDTargetingComputer = __instance.GetComponentInParent(typeof(CombatHUDTargetingComputer)) != null;
                    Logger.Info($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] isMoveStatusPreview: {isMoveStatusPreview}");
                    Logger.Info($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] isCombatHUDMechTray: {isCombatHUDMechTray}");
                    Logger.Info($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] isCombatHUDTargetingComputer: {isCombatHUDTargetingComputer}");

                    //CombatHUD ___HUD = (CombatHUD)AccessTools.Property(typeof(CombatHUDStatusPanel), "HUD").GetValue(__instance, null);
                    //bool isJumpPreview = ___HUD.SelectionHandler.ActiveState.SelectionType == SelectionType.Jump;
                    //Logger.Debug($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] isJumpPreview: {isJumpPreview}");
                    Logger.Debug($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] Fields.IsJumpPreview: {Fields.IsJumpPreview}");

                    int sustainableEvasion = target.GetSustainableEvasion();
                    Logger.Debug($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] sustainableEvasion: {sustainableEvasion}");

                    bool willJumpOrHasJumped = isMoveStatusPreview ? Fields.IsJumpPreview : (target.HasJumpedThisRound || target.JumpedLastRound);
                    Logger.Debug($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] willJumpOrHasJumped: {willJumpOrHasJumped}");

                    bool suppressCoilPips = isCombatHUDTargetingComputer && !target.HasMovedThisRound;
                    Logger.Debug($"[CombatHUDStatusPanel_ShowMoveIndicators_POSTFIX] suppressCoilPips: {suppressCoilPips}");



                    Utilities.ColorEvasivePips(__instance.evasiveDisplay, willJumpOrHasJumped, sustainableEvasion, suppressCoilPips);
                }
                catch (Exception e)
                {
                    Logger.Error(e);
                }
            }
Esempio n. 9
0
        public static void Postfix(CombatHUDStatusPanel __instance, Mech mech)
        {
            Mod.UILog.Trace?.Write("CHUBSP:SSDI:POST entered.");

            var        type       = __instance.GetType();
            MethodInfo methodInfo = type.GetMethod("ShowDebuff", (BindingFlags.NonPublic | BindingFlags.Instance), null,
                                                   new Type[] { typeof(SVGAsset), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) }, new ParameterModifier[5]);

            Traverse  HUDT = Traverse.Create(__instance).Property("HUD");
            CombatHUD HUD  = HUDT.GetValue <CombatHUD>();

            CalculatedHeat calculatedHeat = HeatHelper.CalculateHeat(mech, HUD.SelectionHandler.ProjectedHeatForState);

            Mod.UILog.Debug?.Write($"In ShutdownIndicator, projectedHeat {HUD.SelectionHandler.ProjectedHeatForState} => calculatedHeat: {calculatedHeat.ThresholdHeat} vs {Mod.Config.Heat.WarnAtHeat}");
            Mod.UILog.Debug?.Write($"  current: {calculatedHeat.CurrentHeat} projected: {calculatedHeat.ProjectedHeat} temp: {calculatedHeat.TempHeat}  " +
                                   $"sinkable: {calculatedHeat.SinkableHeat}  sinkCapacity: {calculatedHeat.OverallSinkCapacity}  future: {calculatedHeat.FutureHeat}  threshold: {calculatedHeat.ThresholdHeat}");
            Mod.UILog.Debug?.Write($"  CACTerrainHeat{ calculatedHeat.CACTerrainHeat}  CurrentPathNodes: {calculatedHeat.CurrentPathNodes}  isProjectedHeat: {calculatedHeat.IsProjectedHeat}");

            if (mech.IsShutDown)
            {
                Mod.UILog.Info?.Write($" Mech {CombatantUtils.Label(mech)} is shutdown, displaying the shutdown warning");
                methodInfo.Invoke(__instance, new object[] {
                    LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusShutDownIcon,
                    new Text(Mod.LocalizedText.Tooltips[ModText.CHUDSP_TT_WARN_SHUTDOWN_TITLE]),
                    new Text(Mod.LocalizedText.Tooltips[ModText.CHUDSP_TT_WARN_SHUTDOWN_TEXT]),
                    __instance.defaultIconScale, false
                });
            }
            else if (calculatedHeat.ThresholdHeat >= Mod.Config.Heat.WarnAtHeat)
            {
                Mod.UILog.Info?.Write($"Mech {mech.DistinctId()} has thresholdHeat {calculatedHeat.ThresholdHeat} >= warningHeat: {Mod.Config.Heat.WarnAtHeat}. Displaying heat warning.");
                methodInfo.Invoke(__instance, new object[] {
                    LazySingletonBehavior <UIManager> .Instance.UILookAndColorConstants.StatusOverheatingIcon,
                    new Text(Mod.LocalizedText.Tooltips[ModText.CHUDSP_TT_WARN_OVERHEAT_TITLE]),
                    new Text(Mod.LocalizedText.Tooltips[ModText.CHUDSP_TT_WARN_OVERHEAT_TEXT]),
                    __instance.defaultIconScale, false
                });
            }
        }
Esempio n. 10
0
 public static bool Prefix(CombatHUDStatusPanel __instance)
 {
     Mod.Log.Trace("CHUBSP:SSDI:PRE entered.");
     return(false);
 }
        static bool Prefix(CombatHUDStatusPanel __instance, AbstractActor actor, AbilityDef.SpecialRules specialRulesFilter, Vector3 worldPos, Dictionary <string, CombatHUDStatusIndicator> ___effectDict)
        {
            Mod.Log.Debug?.Write($"Updating StatusEffect Panel for actor: {CombatantUtils.Label(actor)}");

            try
            {
                List <EffectData> effectsOnActor = new List <EffectData>();

                foreach (Effect effect in ModState.Combat.EffectManager.GetAllEffectsTargeting(actor))
                {
                    if (effect == null || effect.EffectData == null)
                    {
                        Mod.Log.Warn?.Write($"Effect with id: {effect?.id} has no effectData! Effect is from creatorGUID: {effect?.creatorGUID} creatorID: {effect?.creatorID} " +
                                            $"with targetId: {effect?.targetID}");
                        continue;
                    }

                    if (effect.EffectData.targetingData.specialRules != AbilityDef.SpecialRules.Aura &&
                        (effect.EffectData.targetingData.effectTriggerType != EffectTriggerType.OnDamaged || effect.triggerCount != 0)
                        )
                    {
                        Mod.Log.Debug?.Write($"Adding effectId: {effect?.EffectData?.Description?.Id} with name: {effect?.EffectData?.Description?.Name}");
                        effectsOnActor.Add(effect.EffectData);
                    }
                }

                if (specialRulesFilter == AbilityDef.SpecialRules.Aura)
                {
                    if (actor.AuraCache == null)
                    {
                        Mod.Log.Warn?.Write($"Actor: {CombatantUtils.Label(actor)} has a null aura cache.  This should not happen!");
                    }
                    else
                    {
                        Dictionary <string, List <EffectData> > dictionary = actor.AuraCache.PreviewAurasAffectingMe(actor, worldPos, null);
                        foreach (string key in dictionary.Keys)
                        {
                            List <EffectData> collection = dictionary[key];
                            Mod.Log.Debug?.Write("Adding collection from aura.");
                            effectsOnActor.AddRange(collection);
                        }
                    }
                }


                Traverse shouldShowEffectT = Traverse.Create(__instance).Method("ShouldShowEffect", new Type[] { typeof(EffectData), typeof(AbilityDef.SpecialRules) });
                Traverse showDebuffT       = Traverse.Create(__instance).Method("ShowBuff", new Type[] { typeof(string), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) });
                Traverse showBuffT         = Traverse.Create(__instance).Method("ShowDebuff", new Type[] { typeof(string), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) });
                if (shouldShowEffectT == null || showDebuffT == null || showBuffT == null)
                {
                    Mod.Log.Error?.Write("Failed to traverse necessary methods! Notify FrostRaptor - this should not happen!");
                    return(false);
                }

                ___effectDict.Clear();
                for (int i = 0; i < effectsOnActor.Count; i++)
                {
                    EffectData effectData = effectsOnActor[i];

                    if (effectData == null || effectData.Description == null ||
                        effectData.Description.Id == null || effectData.Description.Name == null)
                    {
                        Mod.Log.Error?.Write($"EffectData {effectData?.Description?.Name} has no description, id, or name! Cannot process, skipping!");
                        continue;
                    }

                    if (string.IsNullOrEmpty(effectData?.Description?.Icon))
                    {
                        continue;                                                      // No icon to display, skip.
                    }
                    bool shouldShowEffect = shouldShowEffectT.GetValue <bool>(new object[] { effectData, specialRulesFilter });
                    bool alreadyShown     = ___effectDict.ContainsKey(effectData.Description.Id);
                    Mod.Log.Debug?.Write($" -- Effect with name: {effectData?.Description?.Name} and Id: {effectData?.Description?.Id} has shouldShowEffect: {shouldShowEffect} and alreadyShown: {alreadyShown}");

                    string effectId = effectData.Description.Id;
                    if (shouldShowEffect && !alreadyShown)
                    {
                        Mod.Log.Debug?.Write($" -- Adding effect with name: {effectData?.Description?.Name} and Id: {effectData?.Description?.Id} to buff list.");
                        int num = effectsOnActor.FindAll((EffectData x) => x.Description.Id == effectId).Count;
                        if (effectData.statisticData != null &&
                            effectData.statisticData.targetCollection == StatisticEffectData.TargetCollection.Weapon &&
                            effectData.statisticData.targetWeaponSubType != WeaponSubType.Melee)
                        {
                            num = ((num > 1) ? (num / actor.Weapons.Count) : num);
                        }
                        Text text = CombatHUDStatusPanel.ProcessDetailString(effectData, (num > 0) ? num : 1);

                        CombatHUDStatusIndicator combatHUDStatusIndicator;
                        if (effectsOnActor[i].nature == EffectNature.Debuff)
                        {
                            combatHUDStatusIndicator = showDebuffT.GetValue <CombatHUDStatusIndicator>(new object[] {
                                effectData.Description.Icon, new Text(effectData.Description.Name, Array.Empty <object>()), text, __instance.effectIconScale, false
                            });
                        }
                        else
                        {
                            combatHUDStatusIndicator = showBuffT.GetValue <CombatHUDStatusIndicator>(new object[] {
                                effectData.Description.Icon, new Text(effectData.Description.Name, Array.Empty <object>()), text, __instance.effectIconScale, false
                            });
                        }

                        if (combatHUDStatusIndicator != null)
                        {
                            combatHUDStatusIndicator.AddTooltipString(text, effectsOnActor[i].nature);
                            ___effectDict[effectId] = combatHUDStatusIndicator;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Mod.Log.Error?.Write(e, $"Failed to log status effects for actor: {CombatantUtils.Label(actor)} at position: {worldPos}");
            }

            return(false);
        }
        public static void Postfix(CombatHUDStatusPanel __instance)
        {
            Mod.Log.Trace?.Write("CHUDSP:SAS - entered.");

            if (__instance.DisplayedCombatant != null)
            {
                Type[]   iconMethodParams     = new Type[] { typeof(SVGAsset), typeof(Text), typeof(Text), typeof(Vector3), typeof(bool) };
                Traverse showDebuffIconMethod = Traverse.Create(__instance).Method("ShowDebuff", iconMethodParams);
                Traverse showBuffIconMethod   = Traverse.Create(__instance).Method("ShowBuff", iconMethodParams);

                AbstractActor actor      = __instance.DisplayedCombatant as AbstractActor;
                EWState       actorState = new EWState(actor);

                DataManager dm = __instance.DisplayedCombatant.Combat.DataManager;

                bool isPlayer = actor.team == actor.Combat.LocalPlayerTeam;
                if (isPlayer)
                {
                    SVGAsset icon  = dm.GetObjectOfType <SVGAsset>(Mod.Config.Icons.VisionAndSensors, BattleTechResourceType.SVGAsset);
                    Text     title = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TITLE_VISION_AND_SENSORS]);
                    showBuffIconMethod.GetValue(new object[] { icon, title, new Text(BuildToolTip(actor)), __instance.effectIconScale, false });

                    // Disable the sensors
                    if (actor.Combat.TurnDirector.CurrentRound == 1)
                    {
                        SVGAsset sensorsDisabledIcon  = dm.GetObjectOfType <SVGAsset>(Mod.Config.Icons.SensorsDisabled, BattleTechResourceType.SVGAsset);
                        Text     sensorsDisabledTitle = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TITLE_SENSORS_DISABLED]);
                        Text     sensorsDisabledText  = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_SENSORS_DISABLED]);
                        showDebuffIconMethod.GetValue(new object[] {
                            sensorsDisabledIcon, sensorsDisabledTitle, sensorsDisabledText, __instance.effectIconScale, false
                        });
                    }
                }

                if (actorState.GetRawECMShield() != 0 || actorState.GetRawECMJammed() != 0 || actorState.ProbeCarrierMod() != 0 || actorState.PingedByProbeMod() != 0 ||
                    actorState.GetRawStealth() != null || actorState.GetRawMimetic() != null || actorState.GetRawNarcEffect() != null || actorState.GetRawTagEffect() != null)
                {
                    // Build out the detailed string
                    StringBuilder sb = new StringBuilder();

                    if (actorState.GetRawECMShield() != 0)
                    {
                        // A positive is good, a negative is bad
                        string color     = actorState.GetRawECMShield() >= 0 ? "00FF00" : "FF0000";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_ECM_SHIELD],
                                                    new object[] { color, actorState.GetRawECMShield() }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    if (actorState.GetRawECMJammed() != 0)
                    {
                        // A positive (after normalization) is good, a negative is bad
                        string color     = -1 * actorState.GetRawECMJammed() >= 0 ? "00FF00" : "FF0000";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_ECM_JAMMING],
                                                    new object[] { color, -1 * actorState.GetRawECMJammed() }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    if (actorState.ProbeCarrierMod() != 0)
                    {
                        // A positive is good, a negative is bad
                        string color     = actorState.ProbeCarrierMod() >= 0 ? "00FF00" : "FF0000";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_PROBE_CARRIER],
                                                    new object[] { color, -1 * actorState.ProbeCarrierMod() }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    // Armor
                    if (actorState.GetRawStealth() != null)
                    {
                        string color     = "00FF00";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_STEALTH],
                                                    new object[] { color, actorState.GetRawStealth().MediumRangeAttackMod, actorState.GetRawStealth().LongRangeAttackMod, actorState.GetRawStealth().ExtremeRangeAttackMod, }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    if (actorState.GetRawMimetic() != null)
                    {
                        // A positive is good (harder to hit), should be no negative?
                        string color     = "00FF00";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_MIMETIC],
                                                    new object[] { color, actorState.CurrentMimeticPips() }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    // Transient effects
                    if (actorState.PingedByProbeMod() != 0)
                    {
                        // A positive (after normalization) is good, a negative is bad
                        string color     = -1 * actorState.PingedByProbeMod() >= 0 ? "00FF00" : "FF0000";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_PROBE_EFFECT],
                                                    new object[] { color, -1 * actorState.PingedByProbeMod() }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    if (actorState.GetRawNarcEffect() != null)
                    {
                        // A positive (after normalization) is good, a negative is bad
                        string color     = -1 * actorState.GetRawNarcEffect().AttackMod >= 0 ? "00FF00" : "FF0000";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_NARC_EFFECT],
                                                    new object[] { color, -1 * actorState.GetRawNarcEffect().AttackMod }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    if (actorState.GetRawTagEffect() != null)
                    {
                        // A positive (after normalization) is good, a negative is bad
                        string color     = -1 * actorState.GetRawTagEffect().AttackMod >= 0 ? "00FF00" : "FF0000";
                        string localText = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TEXT_EW_TAG_EFFECT],
                                                    new object[] { color, -1 * actorState.GetRawTagEffect().AttackMod }
                                                    ).ToString();
                        sb.Append(localText);
                    }

                    SVGAsset icon  = dm.GetObjectOfType <SVGAsset>(Mod.Config.Icons.ElectronicWarfare, BattleTechResourceType.SVGAsset);
                    Text     title = new Text(Mod.LocalizedText.Tooltips[ModText.LT_TT_TITLE_EW]);
                    showBuffIconMethod.GetValue(new object[] { icon, title, new Text(sb.ToString()), __instance.effectIconScale, false });
                }
            }
        }
        public void UpdateText(Mech displayedMech)
        {
            CalculatedHeat calculatedHeat = HeatHelper.CalculateHeat(displayedMech, CombatHUD.SelectionHandler.ProjectedHeatForState);

            // If everything has changed, skip and avoid the update
            if (calculatedHeat.CurrentHeat == CurrentHeat &&
                calculatedHeat.TempHeat == TempHeat &&
                calculatedHeat.ProjectedHeat == ProjectedHeat &&
                calculatedHeat.CACTerrainHeat == this.CACTerrainHeat &&
                calculatedHeat.CurrentPathNodes == CurrentPathNodes)
            {
                return;
            }

            Mod.HeatLog.Debug?.Write($"Updating heat dialog for actor: {CombatantUtils.Label(displayedMech)}");
            Mod.HeatLog.Debug?.Write($"  previous values:  CurrentHeat: {CurrentHeat}  ProjectedHeat: {ProjectedHeat}  TempHeat: {TempHeat}  CACTerrainHeat: {CACTerrainHeat}  currentPathNodes: {CurrentPathNodes}");
            this.CurrentHeat      = calculatedHeat.CurrentHeat;
            this.ProjectedHeat    = calculatedHeat.ProjectedHeat;
            this.TempHeat         = calculatedHeat.TempHeat;
            this.CACTerrainHeat   = calculatedHeat.CACTerrainHeat;
            this.CurrentPathNodes = calculatedHeat.CurrentPathNodes;
            Mod.HeatLog.Debug?.Write($"  current values:  CurrentHeat: {CurrentHeat}  ProjectedHeat: {ProjectedHeat}  TempHeat: {TempHeat}  CACTerrainHeat: {CACTerrainHeat}  currentPathNodes: {CurrentPathNodes}");

            StringBuilder descSB    = new StringBuilder("");
            StringBuilder warningSB = new StringBuilder("");

            // Future heat
            descSB.Append(new Localize.Text(
                              Mod.LocalizedText.Tooltips[ModText.CHUD_TT_End_Heat], new object[] { calculatedHeat.ThresholdHeat, Mod.Config.Heat.MaxHeat }
                              ));

            // Heat line
            float heatCheck = displayedMech.HeatCheckMod(Mod.Config.SkillChecks.ModPerPointOfGuts);

            // Force a recalculation of the overheat warning
            if (calculatedHeat.FutureHeat > Mod.Config.Heat.WarnAtHeat)
            {
                Traverse             statusPanelT          = Traverse.Create(HUD.MechTray).Field("StatusPanel");
                CombatHUDStatusPanel combatHUDStatusPanel  = statusPanelT.GetValue <CombatHUDStatusPanel>();
                Traverse             showShutdownIndicator = Traverse.Create(combatHUDStatusPanel).Method("ShowShutDownIndicator", new object[] { displayedMech });
                showShutdownIndicator.GetValue();
            }

            float  sinkCapMulti      = displayedMech.DesignMaskHeatMulti(calculatedHeat.IsProjectedHeat);
            string sinkCapMultiColor = sinkCapMulti >= 1f ? "00FF00" : "FF0000";

            descSB.Append(new Localize.Text(
                              Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Heat], new object[] { calculatedHeat.FutureHeat, Mod.Config.Heat.MaxHeat, calculatedHeat.SinkableHeat, calculatedHeat.OverallSinkCapacity, sinkCapMultiColor, sinkCapMulti }
                              ));

            float threshold = 0f;

            // Check Ammo
            foreach (KeyValuePair <int, float> kvp in Mod.Config.Heat.Explosion)
            {
                if (calculatedHeat.ThresholdHeat >= kvp.Key)
                {
                    threshold = kvp.Value;
                }
            }
            if (threshold != 0f && threshold != -1f)
            {
                Mod.HeatLog.Debug?.Write($"Ammo Explosion Threshold: {threshold} vs. d100+{heatCheck * 100f}");
                descSB.Append(new Localize.Text(
                                  Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Explosion], new object[] { heatCheck * 100f, threshold * 100f }
                                  ));
            }
            else if (threshold == -1f)
            {
                Mod.HeatLog.Debug?.Write($"Ammo Explosion Guaranteed!");
                warningSB.Append(new Localize.Text(Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Explosion_Warning]));
            }

            // Check Injury
            threshold = 0f;
            foreach (KeyValuePair <int, float> kvp in Mod.Config.Heat.PilotInjury)
            {
                if (calculatedHeat.ThresholdHeat >= kvp.Key)
                {
                    threshold = kvp.Value;
                }
            }
            if (threshold != 0f)
            {
                Mod.HeatLog.Debug?.Write($"Injury Threshold: {threshold} vs. d100+{heatCheck * 100f}");
                descSB.Append(new Localize.Text(
                                  Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Injury], new object[] { heatCheck * 100f, threshold * 100f }
                                  ));
            }

            // Check System Failure
            threshold = 0f;
            foreach (KeyValuePair <int, float> kvp in Mod.Config.Heat.SystemFailures)
            {
                if (calculatedHeat.ThresholdHeat >= kvp.Key)
                {
                    threshold = kvp.Value;
                }
            }
            if (threshold != 0f)
            {
                Mod.HeatLog.Debug?.Write($"System Failure Threshold: {threshold} vs. d100+{heatCheck * 100f}");
                descSB.Append(new Localize.Text(
                                  Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Sys_Failure], new object[] { heatCheck * 100f, threshold * 100f }
                                  ));
            }

            // Check Shutdown
            threshold = 0f;
            foreach (KeyValuePair <int, float> kvp in Mod.Config.Heat.Shutdown)
            {
                if (calculatedHeat.ThresholdHeat >= kvp.Key)
                {
                    threshold = kvp.Value;
                }
            }
            if (threshold != 0f && threshold != -1f)
            {
                Mod.HeatLog.Debug?.Write($"Shutdown Threshold: {threshold} vs. d100+{heatCheck * 100f}");
                descSB.Append(new Localize.Text(
                                  Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Shutdown], new object[] { heatCheck * 100f, threshold * 100f }
                                  ));
            }
            else if (threshold == -1f)
            {
                Mod.HeatLog.Debug?.Write($"Shutdown Guaranteed!");
                warningSB.Append(new Localize.Text(Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Shutdown_Warning]));
            }

            // Attack modifiers
            int modifier = 0;

            foreach (KeyValuePair <int, int> kvp in Mod.Config.Heat.Firing)
            {
                if (calculatedHeat.ThresholdHeat >= kvp.Key)
                {
                    modifier = kvp.Value;
                }
            }
            if (modifier != 0)
            {
                Mod.HeatLog.Debug?.Write($"Attack Modifier: +{modifier}");
                descSB.Append(new Localize.Text(Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Attack], new object[] { modifier }));
            }
            modifier = 0;

            // Movement modifier
            foreach (KeyValuePair <int, int> kvp in Mod.Config.Heat.Firing)
            {
                if (calculatedHeat.ThresholdHeat >= kvp.Key)
                {
                    modifier = kvp.Value;
                }
            }
            if (modifier != 0)
            {
                Mod.HeatLog.Debug?.Write($"Movement Modifier: -{modifier * 30}m");
                descSB.Append(new Localize.Text(Mod.LocalizedText.Tooltips[ModText.CHUD_TT_Move], new object[] { modifier * 30f }));
            }

            base.SetTitleDescAndWarning("Heat", descSB.ToString(), warningSB.ToString());
        }
Esempio n. 14
0
 void Awake()
 {
     panel = gameObject.GetComponent <CombatHUDStatusPanel>();
 }