Ejemplo n.º 1
0
        public static void Postfix(StatTooltipData __instance, MechDef def)
        {
            try
            {
                var movement = def.GetEngineMovement();
                if (movement == null)
                {
                    return;
                }

                var tooltipData = __instance;

                tooltipData.dataList.Remove("Max Move");
                tooltipData.dataList.Remove("Max Sprint");

                var combat   = CombatGameConstants.GetInstance(UnityGameInstance.BattleTechGame);
                var hexWidth = combat.MoveConstants.ExperimentalGridDistance;
                __instance.dataList.Add("Max Move", $"{movement.WalkSpeed}m / {Mathf.Round(movement.WalkSpeed / hexWidth)} hex");
                __instance.dataList.Add("Max Sprint", $"{movement.RunSpeed}m / {Mathf.Round(movement.RunSpeed / hexWidth)} hex");
                __instance.dataList.Add("TT Walk MP", $"{movement.MovementPoint}");
            }
            catch (Exception e)
            {
                Control.mod.Logger.LogError(e);
            }
        }
        private static AbstractActor InitAbstractActor(AbstractActor actor)
        {
            // Init the combat ref for constants
            ConstructorInfo     constantsCI = AccessTools.Constructor(typeof(CombatGameConstants), new Type[] { });
            CombatGameConstants constants   = (CombatGameConstants)constantsCI.Invoke(new object[] { });

            CombatGameState cgs        = new CombatGameState();
            Traverse        constantsT = Traverse.Create(cgs).Property("Constants");

            constantsT.SetValue(constants);

            Traverse combatT = Traverse.Create(actor).Property("Combat");

            combatT.SetValue(cgs);

            // Init any required stats
            actor.StatCollection = new StatCollection();

            // ModStats
            //actor.StatCollection.AddStatistic<int>(ModStats.PunchAttackMod, 0);

            // Vanilla
            actor.StatCollection.AddStatistic <float>("SensorSignatureModifier", 1.0f);

            return(actor);
        }
Ejemplo n.º 3
0
        static UnitRole getRoleByPriorityIndex(CombatGameConstants constants, int index)
        {
            // TODO - I'm ignoring the priority value for now and just hardcoding it to be brawler, sniper, scout

            int[] counts = new int[3];
            counts[0] = constants.DynamicAIRoleConstants.brawlerMinAbs;
            counts[1] = constants.DynamicAIRoleConstants.sniperMinAbs;

            UnitRole[] dynamicRoles =
            {
                UnitRole.Brawler,
                UnitRole.Sniper
            };

            for (int roleIndex = 0; roleIndex < 3; ++roleIndex)
            {
                if (index < counts[roleIndex])
                {
                    return(dynamicRoles[roleIndex]);
                }
                index -= counts[roleIndex];
            }

            return(UnitRole.Undefined);
        }
Ejemplo n.º 4
0
        static void fillOutMinimums(List <AbstractActor> units)
        {
            if (units.Count == 0)
            {
                return;
            }

            CombatGameConstants constants = units[0].Combat.Constants;

            // TODO be smarter about doing an assignment based on priority and by fit
            int constrainedMinimumCount = constants.DynamicAIRoleConstants.brawlerMinAbs +
                                          constants.DynamicAIRoleConstants.sniperMinAbs;

            if (units.Count < constrainedMinimumCount)
            {
                // this is where we'd fill out by priority

                for (int i = 0; i < units.Count; ++i)
                {
                    UnitRole role = getRoleByPriorityIndex(constants, i);
                    units[i].DynamicUnitRole = role;
                }
            }
            else
            {
                for (int i = 0; i < constrainedMinimumCount; ++i)
                {
                    UnitRole role = getRoleByPriorityIndex(constants, i);
                    units[i].DynamicUnitRole = role;
                }
            }
        }
        public static HeatConstantsDef OverrideHeat(this CombatGameConstants @this)
        {
            var heat = @this.Heat;

            heat.ShutdownCausesInjury = overrideShutdownCausesInjury || heat.ShutdownCausesInjury;
            return(heat);
        }
Ejemplo n.º 6
0
 static void Postfix(MechBayMechInfoWidget __instance)
 {
     ModBase.Sim = __instance.sim;
     if (ModBase.combatConstants == null)
     {
         ModBase.combatConstants = CombatGameConstants.CreateFromSaved(UnityGameInstance.BattleTechGame);
     }
 }
        public static HeatConstantsDef OverrideHeat(this CombatGameConstants @this)
        {
            var heat = @this.Heat;

            if (ShutdownInjuryProtectionFeature.settings.ShutdownInjuryEnabled)
            {
                heat.ShutdownCausesInjury = receiveShutdownInjury;
            }
            return(heat);
        }
Ejemplo n.º 8
0
        private static AbstractActor InitAbstractActor(AbstractActor actor)
        {
            // Init the combat ref for constants

            ConstructorInfo     constantsCI = AccessTools.Constructor(typeof(CombatGameConstants), new Type[] { });
            CombatGameConstants constants   = (CombatGameConstants)constantsCI.Invoke(new object[] { });

            VisibilityConstantsDef visibilityDef = constants.Visibility;

            visibilityDef.UseAsymmetricalSensors     = true;
            visibilityDef.ShutDownSignatureModifier  = 0.5f;
            visibilityDef.ShutDownVisibilityModifier = 0.5f;

            Traverse visibilityT = Traverse.Create(constants).Property("Visibility");

            visibilityT.SetValue(visibilityDef);

            CombatGameState cgs        = new CombatGameState();
            Traverse        constantsT = Traverse.Create(cgs).Property("Constants");

            constantsT.SetValue(constants);

            Traverse combatT = Traverse.Create(actor).Property("Combat");

            combatT.SetValue(cgs);

            // Init any required stats
            actor.StatCollection = new StatCollection();

            // ModStats
            actor.StatCollection.AddStatistic <int>(ModStats.TacticsMod, 0);
            actor.StatCollection.AddStatistic <int>(ModStats.CurrentRoundEWCheck, 0);
            actor.StatCollection.AddStatistic <int>(ModStats.ECMShield, 0);
            actor.StatCollection.AddStatistic <int>(ModStats.ECMJamming, 0);
            actor.StatCollection.AddStatistic <int>(ModStats.AdvancedSensors, 0);
            actor.StatCollection.AddStatistic <int>(ModStats.ProbeCarrier, 0);
            actor.StatCollection.AddStatistic <int>(ModStats.PingedByProbe, 0);
            actor.StatCollection.AddStatistic <string>(ModStats.StealthEffect, "");
            actor.StatCollection.AddStatistic <string>(ModStats.MimeticEffect, "");
            actor.StatCollection.AddStatistic <int>(ModStats.MimeticCurrentSteps, 0);
            actor.StatCollection.AddStatistic <string>(ModStats.HeatVision, "");
            actor.StatCollection.AddStatistic <string>(ModStats.ZoomVision, "");
            actor.StatCollection.AddStatistic <string>(ModStats.NarcEffect, "");
            actor.StatCollection.AddStatistic <string>(ModStats.TagEffect, "");
            actor.StatCollection.AddStatistic <bool>(ModStats.SharesVision, false);
            actor.StatCollection.AddStatistic <bool>(ModStats.NightVision, false);
            actor.StatCollection.AddStatistic <int>(ModStats.DisableSensors, 2);

            // Vanilla
            actor.StatCollection.AddStatistic <float>("SensorSignatureModifier", 1.0f);



            return(actor);
        }
Ejemplo n.º 9
0
 public static bool Override_CombatGameConstants_LoadFromManifest(CombatGameConstants __instance)
 {
     try {
         if (CombatConstantJSON == null)
         {
             return(true);
         }
         __instance.FromJSON(UnZipStr(CombatConstantJSON));
         LoadMoraleResources?.Invoke(__instance, null);
         LoadMaintenanceResources?.Invoke(__instance, null);
         return(false);
     }                 catch (Exception ex) { return(Error(ex)); }
 }
Ejemplo n.º 10
0
        static bool unitsMeetMinimums(List <AbstractActor> units)
        {
            if (units.Count == 0)
            {
                return(true);
            }

            Dictionary <UnitRole, int> counts    = countRolesAfterAssignment(null, units);
            CombatGameConstants        constants = units[0].Combat.Constants;

            return((counts[UnitRole.Brawler] >= constants.DynamicAIRoleConstants.brawlerMinAbs) &&
                   (counts[UnitRole.Sniper] >= constants.DynamicAIRoleConstants.sniperMinAbs));
        }
Ejemplo n.º 11
0
 internal static void ModifiedCombatGameConstantsViaAdvangedMerge()
 {
     try
     {
         var constants = CombatGameConstants.GetInstance(UnityGameInstance.BattleTechGame);
         var hit       = constants.HitTables.HitMechLocationFromFront[ArmorLocation.CenterTorso];
         var expected  = 9;
         if (hit == expected)
         {
             Control.Logger.Log($"{LogPrefix}CombatGameConstants HitMechLocationFromFront[CenterTorso] was expected {expected}.");
         }
         else
         {
             Control.Logger.LogError($"{LogPrefix}CombatGameConstants HitMechLocationFromFront[CenterTorso] was not expected {expected}, it was {hit}.");
         }
     }
     catch (Exception e)
     {
         Control.Logger.LogError($"{LogPrefix}Could not validate CombatGameConstants modification", e);
     }
 }
Ejemplo n.º 12
0
 internal static void ModifiedCombatGameConstantsViaNormaldMerge()
 {
     try
     {
         var constants = CombatGameConstants.GetInstance(UnityGameInstance.BattleTechGame);
         var hit       = constants.Heat.InternalHeatSinkCount;
         var expected  = 42;
         if (hit == expected)
         {
             Control.Logger.Log($"{LogPrefix}CombatGameConstants.Heat.InternalHeatSinkCount was expected {expected}.");
         }
         else
         {
             Control.Logger.LogError($"{LogPrefix}CombatGameConstants.Heat.InternalHeatSinkCount was not expected {expected} it was {hit}.");
         }
     }
     catch (Exception e)
     {
         Control.Logger.LogError($"{LogPrefix}Could not validate CombatGameConstants modification", e);
     }
 }
Ejemplo n.º 13
0
            public static void Postfix(StatTooltipData __instance, MechDef def)
            {
                try
                {
                    if (!def.Chassis.ChassisTags.Contains("chassis_heatsinks"))
                    {
                        return;
                    }

                    Logger.Debug("[StatTooltipData_SetHeatData_POSTFIX] (" + def.Description.Id + ") def.Chassis.Heatsinks: " + def.Chassis.Heatsinks);

                    CombatGameConstants cgc = CombatGameConstants.GetInstance(UnityGameInstance.BattleTechGame);
                    float num = ((float)def.Chassis.Heatsinks + (float)cgc.Heat.InternalHeatSinkCount) * cgc.Heat.DefaultHeatSinkDissipationCapacity;
                    Logger.Debug("[StatTooltipData_SetHeatData_POSTFIX] (" + def.Description.Id + ") ChassisDissipationCapacity: " + num);

                    for (int i = 0; i < def.Inventory.Length; i++)
                    {
                        if (def.Inventory[i].ComponentDefType == ComponentType.HeatSink)
                        {
                            HeatSinkDef heatSinkDef = def.Inventory[i].Def as HeatSinkDef;
                            if (heatSinkDef != null)
                            {
                                num += heatSinkDef.DissipationCapacity;
                            }
                        }
                    }
                    Logger.Debug("[StatTooltipData_SetHeatData_POSTFIX] (" + def.Description.Id + ") TotalDissipationCapacity: " + num);

                    __instance.dataList.Remove("Heat Sinking");
                    __instance.dataList.Add(Strings.T("Heat Sinking"), Strings.T("{0} Heat", new object[]
                    {
                        num.ToString()
                    }));
                }
                catch (Exception e)
                {
                    Logger.Error(e);
                }
            }
        static void Postfix(object data, ref bool __result, BattleTech.UI.Tooltips.TooltipPrefab_Generic __instance)
        {
            if (!__result || ModBase.currentMech == null)
            {
                return;
            }

            if ((ModBase.Sim == null || ModBase.Sim.CurRoomState != DropshipLocation.MECH_BAY) && !ModBase.inMechLab)
            {
                return;
            }

            if (ModBase.combatConstants == null)
            {
                ModBase.combatConstants = CombatGameConstants.CreateFromSaved(UnityGameInstance.BattleTechGame);
            }

            MechDef    currentMech    = ModBase.currentMech;
            ChassisDef currentChassis = currentMech.Chassis;

            BaseDescriptionDef baseDescriptionDef = (BaseDescriptionDef)data;

            string extra_stats = string.Empty;

            switch (baseDescriptionDef.Id)
            {
            case "TooltipMechPerformanceFirepower":

                float alpha_damage      = 0;
                float alpha_instability = 0;
                float alpha_heat        = 0;

                // Calculate alpha strike total damage, heat damage and instability.
                foreach (MechComponentRef mechComponentRef in currentMech.Inventory)
                {
                    if (mechComponentRef.Def is WeaponDef weapon)
                    {
                        alpha_damage      += weapon.Damage * weapon.ShotsWhenFired;
                        alpha_instability += weapon.Instability * weapon.ShotsWhenFired;
                        alpha_heat        += weapon.HeatDamage * weapon.ShotsWhenFired;
                    }
                }

                if (alpha_damage > 0)
                {
                    if (alpha_heat > 0)
                    {
                        extra_stats += string.Format("Alpha strike damage: <b>{0}</b> ( <b>{1} H</b> )\n", alpha_damage, alpha_heat);
                    }
                    else
                    {
                        extra_stats += string.Format("Alpha strike damage: <b>{0}</b>\n", alpha_damage);
                    }
                }

                if (alpha_instability > 0)
                {
                    extra_stats += string.Format("Alpha strike stability damage: <b>{0}</b>\n", alpha_instability);
                }

                break;

            case "TooltipMechPerformanceHeat":
                HeatConstantsDef heatConstants = ModBase.combatConstants.Heat;

                float total_heat_sinking        = heatConstants.InternalHeatSinkCount * heatConstants.DefaultHeatSinkDissipationCapacity;
                float extra_engine_heat_sinking = BTMechDef.GetExtraEngineSinking(currentMech);
                total_heat_sinking += extra_engine_heat_sinking;

                float heat_sinking_ratio = 1;
                float total_weapon_heat  = 0;
                float weapon_heat_ratio  = 1;

                float jump_distance = BTMechDef.GetJumpJetsMaxDistance(currentMech);

                int max_heat = heatConstants.MaxHeat;

                foreach (MechComponentRef mechComponentRef in currentMech.Inventory)
                {
                    if (mechComponentRef.Def == null)
                    {
                        mechComponentRef.RefreshComponentDef();
                    }

                    // Weapon total heat
                    if (mechComponentRef.Def is WeaponDef weapon)
                    {
                        total_weapon_heat += (float)weapon.HeatGenerated;
                    }

                    // Heat sink total dissipation
                    else if (mechComponentRef.Def is HeatSinkDef heat_sink)
                    {
                        total_heat_sinking += heat_sink.DissipationCapacity;
                    }

                    // Bank/Exchanger effects
                    if (mechComponentRef.Def.statusEffects != null)
                    {
                        foreach (EffectData effect in mechComponentRef.Def.statusEffects)
                        {
                            StatisticEffectData statisticData = effect.statisticData;
                            if (statisticData.statName == "MaxHeat")
                            {
                                BTStatistics.ApplyEffectStatistic(statisticData, ref max_heat);
                            }
                            else if (statisticData.statName == "HeatGenerated" && statisticData.targetCollection == StatisticEffectData.TargetCollection.Weapon)
                            {
                                BTStatistics.ApplyEffectStatistic(statisticData, ref weapon_heat_ratio);
                            }
                            else if (statisticData.statName == "JumpDistanceMultiplier")
                            {
                                BTStatistics.ApplyEffectStatistic(statisticData, ref jump_distance);
                            }
                        }
                    }
                }

                total_weapon_heat  *= weapon_heat_ratio;
                total_heat_sinking *= heat_sinking_ratio;

                extra_stats += string.Format("Heat dissipation: <b>{0}</b>\n", (int)total_heat_sinking);

                if (extra_engine_heat_sinking > 0f)
                {
                    extra_stats += "Engine heat sinks: <b>double</b>\n";
                }

                if (total_weapon_heat > 0)
                {
                    extra_stats += string.Format("Alpha strike heat: <b>{0}</b>\n", (int)total_weapon_heat);
                    extra_stats += string.Format("Alpha strike heat delta: <b>{0}</b>\n", (int)(total_weapon_heat - total_heat_sinking));
                }

                extra_stats += string.Format("Max heat capacity: <b>{0}</b>\n", (int)max_heat);

                if (jump_distance > 0)
                {
                    float max_jump_heat = ((jump_distance / heatConstants.JumpHeatUnitSize) + 1) * heatConstants.JumpHeatPerUnit;
                    max_jump_heat *= heatConstants.GlobalHeatIncreaseMultiplier;
                    max_jump_heat  = Mathf.Max(heatConstants.JumpHeatMin, max_jump_heat);

                    extra_stats += string.Format("Max jump heat: <b>{0}</b>\n", (int)max_jump_heat);
                }
                break;

            case "TooltipMechPerformanceSpeed":
                float max_walk_distance   = currentChassis.MovementCapDef.MaxWalkDistance;
                float max_sprint_distance = currentChassis.MovementCapDef.MaxSprintDistance;
                float max_jump_distance   = BTMechDef.GetJumpJetsMaxDistance(currentMech);

                foreach (MechComponentRef mechComponentRef in currentMech.Inventory)
                {
                    if (mechComponentRef.Def == null)
                    {
                        mechComponentRef.RefreshComponentDef();
                    }

                    // Various movement effects
                    if (mechComponentRef.Def.statusEffects != null)
                    {
                        foreach (EffectData effect in mechComponentRef.Def.statusEffects)
                        {
                            StatisticEffectData statisticData = effect.statisticData;
                            if (statisticData.statName == "WalkSpeed")
                            {
                                BTStatistics.ApplyEffectStatistic(statisticData, ref max_walk_distance);
                            }
                            else if (statisticData.statName == "RunSpeed")
                            {
                                BTStatistics.ApplyEffectStatistic(statisticData, ref max_sprint_distance);
                            }
                            else if (statisticData.statName == "JumpDistanceMultiplier")
                            {
                                BTStatistics.ApplyEffectStatistic(statisticData, ref max_jump_distance);
                            }
                        }
                    }
                }

                extra_stats += string.Format("Walk distance: <b>{0}m</b>\n", (int)max_walk_distance);
                extra_stats += string.Format("Sprint distance: <b>{0}m</b>\n", (int)max_sprint_distance);

                if (max_jump_distance > 0)
                {
                    extra_stats += string.Format("Jump distance: <b>{0}m</b>\n", (int)max_jump_distance);
                }

                break;

            case "TooltipMechPerformanceMelee":
                float melee_damage      = currentChassis.MeleeDamage;
                float melee_instability = currentChassis.MeleeInstability;

                float dfa_damage      = currentChassis.DFADamage * 2;
                float dfa_instability = currentChassis.DFAInstability;
                float dfa_self_damage = currentChassis.DFASelfDamage;

                float support_damage = 0;
                float support_heat   = 0;

                foreach (MechComponentRef mechComponentRef in currentMech.Inventory)
                {
                    if (mechComponentRef.Def == null)
                    {
                        mechComponentRef.RefreshComponentDef();
                    }

                    // Take Melee/DFA upgrades into account
                    if (mechComponentRef.Def.statusEffects != null)
                    {
                        foreach (EffectData effect in mechComponentRef.Def.statusEffects)
                        {
                            if (effect.effectType != EffectType.StatisticEffect)
                            {
                                continue;
                            }

                            if (effect.statisticData.targetWeaponSubType == WeaponSubType.Melee)
                            {
                                if (effect.statisticData.statName == "DamagePerShot")
                                {
                                    BTStatistics.ApplyEffectStatistic(effect.statisticData, ref melee_damage);
                                }
                                else if (effect.statisticData.statName == "Instability")
                                {
                                    BTStatistics.ApplyEffectStatistic(effect.statisticData, ref melee_instability);
                                }
                            }
                            else if (effect.statisticData.targetWeaponSubType == WeaponSubType.DFA)
                            {
                                if (effect.statisticData.statName == "DamagePerShot")
                                {
                                    BTStatistics.ApplyEffectStatistic(effect.statisticData, ref dfa_damage);
                                }
                                else if (effect.statisticData.statName == "Instability")
                                {
                                    BTStatistics.ApplyEffectStatistic(effect.statisticData, ref dfa_instability);
                                }
                                else if (effect.statisticData.statName == "DFASelfDamage")
                                {
                                    BTStatistics.ApplyEffectStatistic(effect.statisticData, ref dfa_self_damage);
                                }
                            }
                        }
                    }

                    // Calculate support weapon damage
                    if (mechComponentRef.Def is WeaponDef weapon && weapon.Category == WeaponCategory.AntiPersonnel)
                    {
                        support_damage += weapon.Damage * weapon.ShotsWhenFired;
                        support_heat   += weapon.HeatDamage * weapon.ShotsWhenFired;
                    }
                }

                extra_stats += string.Format("Melee damage: <b>{0}</b> ( Stability: <b>{1}</b> )\n", (int)melee_damage, (int)melee_instability);

                if (BTMechDef.GetJumpJetsAmount(currentMech) > 0)
                {
                    extra_stats += string.Format("DFA damage: <b>{0}</b> ( Stability: <b>{1}</b> )\n", (int)dfa_damage, (int)dfa_instability);
                    extra_stats += string.Format("DFA self-damage: <b>{0}</b> ( per leg )\n", (int)dfa_self_damage);
                }

                if (support_damage > 0)
                {
                    if (support_heat > 0)
                    {
                        extra_stats += string.Format("Support weapons damage: <b>{0}</b> ( <b>{1} H</b> )\n", support_damage, support_heat);
                    }
                    else
                    {
                        extra_stats += string.Format("Support weapons damage: <b>{0}</b>\n", support_damage);
                    }
                }

                break;

            // No idea what to put on those two. Feel free to contribute.
            case "TooltipMechPerformanceRange":
                break;

            case "TooltipMechPerformanceDurability":
                break;
            }

            if (extra_stats.Length != 0)
            {
                TextMeshProUGUI body = (TextMeshProUGUI)ReflectionHelper.GetPrivateField(__instance, "body");
                body.text = string.Format("{0}\n{1}", extra_stats, body.text);
            }
        }
        public static bool Prefix(MechDef mechDef, ref float currentValue, ref float maxValue)
        {
            try
            {
                if (Combat == null)
                {
                    Combat = CombatGameConstants.CreateFromSaved(UnityGameInstance.BattleTechGame);
                }
                var totalHeatSinkDissipation = Combat.Heat.InternalHeatSinkCount * Combat.Heat.DefaultHeatSinkDissipationCapacity;
                var heatGenerationWeapons    = 0f;
                var numberOfJumpJets         = 0;

                foreach (var mechComponentRef in mechDef.Inventory)
                {
                    if (mechComponentRef.Def == null)
                    {
                        mechComponentRef.RefreshComponentDef();
                    }
                    if (mechComponentRef.Def is WeaponDef)
                    {
                        var weaponDef = (WeaponDef)mechComponentRef.Def;
                        heatGenerationWeapons += weaponDef.HeatGenerated;
                    }
                    else if (mechComponentRef.ComponentDefType == ComponentType.JumpJet)
                    {
                        if (mechComponentRef.DamageLevel < ComponentDamageLevel.NonFunctional)
                        {
                            numberOfJumpJets++;
                        }
                    }
                    else if (mechComponentRef.Def is HeatSinkDef)
                    {
                        var heatSinkDef = (HeatSinkDef)mechComponentRef.Def;
                        totalHeatSinkDissipation += heatSinkDef.DissipationCapacity;
                    }
                }

                Control.mod.Logger.LogDebug("heatGenerationWeapons=" + heatGenerationWeapons);
                Control.mod.Logger.LogDebug("totalHeatSinkDissipation=" + totalHeatSinkDissipation);

                var maxHeat = Combat.Heat.MaxHeat;
                {
                    var stats                  = new StatCollection();
                    var maxHeatStatistic       = stats.AddStatistic("MaxHeat", maxHeat);
                    var heatGeneratedStatistic = stats.AddStatistic("HeatGenerated", heatGenerationWeapons);

                    foreach (var mechComponentRef in mechDef.Inventory)
                    {
                        if (mechComponentRef.Def == null || mechComponentRef.Def.statusEffects == null)
                        {
                            continue;
                        }

                        var statusEffects = mechComponentRef.Def.statusEffects;
                        foreach (var effect in statusEffects)
                        {
                            switch (effect.statisticData.statName)
                            {
                            case "MaxHeat":
                                stats.PerformOperation(maxHeatStatistic, effect.statisticData);
                                break;

                            case "HeatGenerated":
                                if (effect.statisticData.targetCollection == StatisticEffectData.TargetCollection.Weapon)
                                {
                                    stats.PerformOperation(heatGeneratedStatistic, effect.statisticData);
                                }
                                break;
                            }
                        }
                    }

                    maxHeat = maxHeatStatistic.CurrentValue.Value <int>();
                    heatGenerationWeapons = heatGeneratedStatistic.CurrentValue.Value <float>();
                }

                Control.mod.Logger.LogDebug("maxHeat=" + maxHeat);
                Control.mod.Logger.LogDebug("heatGenerationWeapons=" + heatGenerationWeapons);

                if (numberOfJumpJets >= Combat.MoveConstants.MoveTable.Length)
                {
                    numberOfJumpJets = Combat.MoveConstants.MoveTable.Length - 1;
                }

                var heatGenerationJumpJets = 0f;
                var jumpHeatDivisor        = 3;
                if (numberOfJumpJets > 0)
                {
                    heatGenerationJumpJets += numberOfJumpJets * Combat.Heat.JumpHeatUnitSize / jumpHeatDivisor;
                }
                else
                {
                    heatGenerationJumpJets = 0f;
                }

                totalHeatSinkDissipation *= Combat.Heat.GlobalHeatSinkMultiplier;
                var totalHeatGeneration = (heatGenerationWeapons + heatGenerationJumpJets) * Combat.Heat.GlobalHeatIncreaseMultiplier;

                Control.mod.Logger.LogDebug("totalHeatGeneration=" + totalHeatGeneration);

                // rounding steps for heatSinkDissipation
                var heatDissipationPercent = Mathf.Min(totalHeatSinkDissipation / totalHeatGeneration * 100f, UnityGameInstance.BattleTechGame.MechStatisticsConstants.MaxHeatEfficiency);
                heatDissipationPercent = Mathf.Max(heatDissipationPercent, UnityGameInstance.BattleTechGame.MechStatisticsConstants.MinHeatEfficiency);

                Control.mod.Logger.LogDebug("heatDissipationPercent=" + heatDissipationPercent);

                totalHeatSinkDissipation = totalHeatGeneration * (heatDissipationPercent / 100f);

                Control.mod.Logger.LogDebug("totalHeatSinkDissipation=" + totalHeatSinkDissipation);

                var heatLeftOver       = totalHeatGeneration - totalHeatSinkDissipation;
                var unusedHeatCapacity = maxHeat - heatLeftOver;

                Control.mod.Logger.LogDebug("heatLeftOver=" + heatLeftOver);
                Control.mod.Logger.LogDebug("unusedHeatCapacity=" + unusedHeatCapacity);

                currentValue = Mathf.Round((unusedHeatCapacity / maxHeat) * 10f);
                currentValue = Mathf.Max(Mathf.Min(currentValue, 10f), 1f);
                maxValue     = 10f;
                return(false);
            }
            catch (Exception e)
            {
                Control.mod.Logger.LogError(e);
                return(true);
            }
        }