// AI Helper functions below

        // Return of MaxHeat means no limit from this effect
        public static int AcceptableHeatForAIFromVolatileAmmo(this Mech mech, float heatCheckMod, float bhvarAcceptableHeatFraction)
        {
            int acceptableHeat = Mod.Config.Heat.MaxHeat;

            Mod.AILog.Info?.Write($"-- Checking volatile ammo ");
            AmmunitionBox mostDamagingVolatile = HeatHelper.FindMostDamagingAmmoBox(mech, true);

            if (mostDamagingVolatile != null)
            {
                // We have volatile ammo, success chances will be lower because of the greater chance of an ammo explosion
                foreach (KeyValuePair <int, float> kvp in Mod.Config.Heat.Explosion)
                {
                    if (kvp.Value == -1f)
                    {
                        // Guaranteed explosion, return one less than this value
                        acceptableHeat = kvp.Key - 1;
                        break;
                    }

                    float rawExplosionChance = Math.Max(0f, kvp.Value - heatCheckMod);
                    Mod.AILog.Info?.Write($"  heat: {kvp.Key} has rawChance: {kvp.Value} - pilotMod: {heatCheckMod} => raw explosionChance: {rawExplosionChance}");
                    float successChance        = 1.0f - rawExplosionChance;
                    float compoundChance       = successChance * successChance;
                    float finalExplosionChance = 1.0f - compoundChance;
                    Mod.AILog.Info?.Write($"  1.0f - compoundChance: {compoundChance} => finalExplosionChance: {finalExplosionChance}");
                    if (finalExplosionChance <= bhvarAcceptableHeatFraction)
                    {
                        acceptableHeat = kvp.Key;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            else
            {
                Mod.AILog.Info?.Write($"  No volatile ammo, skipping");
            }

            Mod.AILog.Info?.Write($"Unit: {mech.DistinctId()} has acceptableHeat: {acceptableHeat} from volatile ammo due to behVar: {bhvarAcceptableHeatFraction}.");
            return(acceptableHeat);
        }
Пример #2
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
                });
            }
        }
        // Return of MaxHeat means no limit from this effect
        public static int AcceptableHeatForAIFromRegularAmmo(this Mech mech, float heatCheckMod, float bhvarAcceptableHeatFraction)
        {
            int acceptableHeat = Mod.Config.Heat.MaxHeat;

            Mod.AILog.Info?.Write($"-- Checking regular ammo ");
            AmmunitionBox mostDamaging = HeatHelper.FindMostDamagingAmmoBox(mech, false);

            if (mostDamaging != null)
            {
                // We have regular ammo, so success chances are as on tin
                foreach (KeyValuePair <int, float> kvp in Mod.Config.Heat.Explosion)
                {
                    if (kvp.Value == -1f)
                    {
                        // Guaranteed explosion, return one less than this value
                        acceptableHeat = kvp.Key - 1;
                        break;
                    }

                    float explosionChance = Math.Max(0f, kvp.Value - heatCheckMod);
                    Mod.AILog.Info?.Write($"  heat: {kvp.Key} has rawChance: {kvp.Value} - pilotMod: {heatCheckMod} => explosionChance: {explosionChance}");
                    if (explosionChance <= bhvarAcceptableHeatFraction)
                    {
                        acceptableHeat = kvp.Key;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            else
            {
                Mod.AILog.Info?.Write($"  No regular ammo, skipping");
            }

            Mod.AILog.Info?.Write($"Unit: {mech.DistinctId()} has acceptableHeat: {acceptableHeat} from regular ammo due to behVar: {bhvarAcceptableHeatFraction}.");
            return(acceptableHeat);
        }
Пример #4
0
        public static void Postfix(CombatHUDAttackModeSelector __instance)
        {
            Mod.UILog.Trace?.Write("CHUDAMS:U - entered.");

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

            if (HUD != null && HUD.SelectedActor != null && HUD.SelectedActor is Mech)
            {
                Traverse showHeatWarningsT = Traverse.Create(__instance).Field("showHeatWarnings");
                bool     showHeatWarnings  = showHeatWarningsT.GetValue <bool>();
                if (showHeatWarnings)
                {
                    CalculatedHeat calculatedHeat = HeatHelper.CalculateHeat(HUD.SelectedActor as Mech, HUD.SelectionHandler.ProjectedHeatForState);
                    //Mod.UILog.Debug?.Write($" In CombatHUDAttackModeSelector, projectedHeat: {calculatedHeat.ThresholdHeat} vs {Mod.Config.Heat.WarnAtHeat}");
                    bool isOverheated = calculatedHeat.ThresholdHeat >= Mod.Config.Heat.WarnAtHeat;
                    bool isShutdown   = calculatedHeat.ThresholdHeat >= Mod.Config.Heat.MaxHeat;

                    Traverse updateOverheatWarningsT = Traverse.Create(__instance).Method("UpdateOverheatWarnings", new object[] { isOverheated, isShutdown });
                    updateOverheatWarningsT.GetValue();
                }
            }
        }
Пример #5
0
        public ActionResult <IEnumerable <SensorDataExDTO> > Get(string id, [FromQuery] string from, [FromQuery] string to)
        {
            List <SensorDataExDTO> retData        = new List <SensorDataExDTO>();
            List <AggregateDataEx> sensorDataList = _repository.LoadSensorDataEx(id, from, to);

            foreach (var item in sensorDataList)
            {
                var tmp = new SensorDataExDTO();
                tmp.MAC                = item.SenderMAC;
                tmp.Name               = item.SenderName;
                tmp.Temp               = item.Temperature;
                tmp.Humidity           = item.Humidity;
                tmp.IngestionTimestamp = item.IngestionTimestamp;
                tmp.TValve             = item.TValve;
                tmp.TScheduledTarget   = item.TScheduledTarget;
                tmp.BatteryLevel       = item.BatteryLevel;
                tmp.HeatIndex          = HeatHelper.GetHeatIndexCelsius(item.Temperature, item.Humidity);
                tmp.SetTempSended      = item.SetTempSended;
                tmp.TCurrentTarget     = item.TCurrentTarget;
                retData.Add(tmp);
            }

            return(retData);
        }
        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());
        }