// 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); } } }
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); }
public static void Prefix(CombatHUDStatusPanel __instance) { if (__instance.gameObject.GetComponent <RefreshIndicator>() == null) { __instance.gameObject.AddComponent <RefreshIndicator>(); } }
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); }
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 }); } }
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); } }
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 }); } }
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()); }
void Awake() { panel = gameObject.GetComponent <CombatHUDStatusPanel>(); }