public static bool ResolveVolatileAmmoCheck(Mech mech, int heatToCheck, int rootSequenceGUID, float heatCheck)
        {
            bool          failedVolatileAmmoCheck = false;
            AmmunitionBox mostDamagingVolatile    = HeatHelper.FindMostDamagingAmmoBox(mech, true);

            if (mostDamagingVolatile != null)
            {
                failedVolatileAmmoCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.Explosion, heatToCheck, mech, heatCheck, ModText.FT_Check_Explosion);
                Mod.Log.Debug?.Write($"  failedVolatileAmmoCheck: {failedVolatileAmmoCheck}");
                if (failedVolatileAmmoCheck)
                {
                    Mod.Log.Info?.Write($"-- Volatile Ammo Explosion check failed on {CombatantUtils.Label(mech)}, forcing volatile ammo explosion");

                    if (mostDamagingVolatile != null)
                    {
                        Mod.Log.Info?.Write($" Exploding inferno ammo: {mostDamagingVolatile.UIName}");
                        WeaponHitInfo fakeHit = new WeaponHitInfo(rootSequenceGUID, -1, -1, -1, string.Empty, string.Empty, -1, null, null, null, null, null, null, null,
                                                                  new AttackDirection[] { AttackDirection.None }, null, null, null);
                        mostDamagingVolatile.DamageComponent(fakeHit, ComponentDamageLevel.Destroyed, true);
                    }
                    else
                    {
                        Mod.Log.Debug?.Write(" Unit has no Volatile ammo boxes, skipping.");
                    }
                }
            }

            return(failedVolatileAmmoCheck);
        }
Exemplo n.º 2
0
            public static bool Prefix(MechHeatSequence __instance, HeatSequenceState newState)
            {
                if (newState != HeatSequenceState.Finished)
                {
                    return(true);
                }

                Traverse          stateT       = Traverse.Create(__instance).Field("state");
                HeatSequenceState currentState = (HeatSequenceState)stateT.GetValue <int>();

                if (currentState == newState)
                {
                    return(true);
                }

                Mod.Log.Info($"MHS - executing updated logic for state: {newState} on actor:{__instance.OwningMech.DisplayName}_{__instance.OwningMech.GetPilot().Name}.");
                stateT.SetValue((int)newState);

                Traverse timeInCurrentStateT = Traverse.Create(__instance).Field("timeInCurrentState");

                timeInCurrentStateT.SetValue(0f);

                /* Finished Can be invoked from a rising state (heat being added):
                 *  Attack Sequence, artillery sequence, actor burning effect, (heatSinkStep=false, applyStartupHeatSinks=false)
                 *  On End of turn sequence - (heatSinkStep=true, applyStartupHeatSinks=false)
                 *  On Mech Startup sequence - (heatSinkStep=true, applyStartupHeatSinks=true)
                 */

                if (!__instance.PerformHeatSinkStep)
                {
                    Mod.Log.Debug($"Reconciling heat for actor: {CombatantUtils.Label(__instance.OwningMech)}");
                    Mod.Log.Debug($"  Before - currentHeat: {__instance.OwningMech.CurrentHeat}  tempHeat: {__instance.OwningMech.TempHeat}  " +
                                  $"isPastMaxHeat: {__instance.OwningMech.IsPastMaxHeat}  hasAppliedHeatSinks: {__instance.OwningMech.HasAppliedHeatSinks}");
                    // Checks for heat damage, clamps heat to max and min
                    __instance.OwningMech.ReconcileHeat(__instance.RootSequenceGUID, __instance.InstigatorID);
                    Mod.Log.Debug($"  After - currentHeat: {__instance.OwningMech.CurrentHeat}  tempHeat: {__instance.OwningMech.TempHeat}  " +
                                  $"isPastMaxHeat: {__instance.OwningMech.IsPastMaxHeat}  hasAppliedHeatSinks: {__instance.OwningMech.HasAppliedHeatSinks}");
                }

                //if (__instance.OwningMech.IsPastMaxHeat && !__instance.OwningMech.IsShutDown) {
                //    __instance.OwningMech.GenerateOverheatedSequence(__instance);
                //    return;
                //}

                if (__instance.PerformHeatSinkStep && !__instance.ApplyStartupHeatSinks)
                {
                    // We are at the end of the turn - force an overheat
                    Mod.Log.Info("AT END OF TURN - CHECKING EFFECTS");

                    MultiSequence sequence = new MultiSequence(__instance.OwningMech.Combat);

                    // Possible sequences
                    //  Shutdown
                    //  Fall from shutdown
                    //  Ammo Explosion
                    //  System damage
                    //  Pilot injury
                    //  Pilot death

                    float heatCheck  = __instance.OwningMech.HeatCheckMod(Mod.Config.Piloting.SkillMulti);
                    float pilotCheck = __instance.OwningMech.PilotCheckMod(Mod.Config.Piloting.SkillMulti);
                    Mod.Log.Debug($" Actor: {CombatantUtils.Label(__instance.OwningMech)} has gutsMulti: {heatCheck}  pilotingMulti: {pilotCheck}");

                    // Resolve Pilot Injury
                    bool failedInjuryCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.PilotInjury, __instance.OwningMech.CurrentHeat, __instance.OwningMech, heatCheck, ModConfig.FT_Check_Injury);
                    Mod.Log.Debug($"  failedInjuryCheck: {failedInjuryCheck}");
                    if (failedInjuryCheck)
                    {
                        Mod.Log.Debug("-- Pilot Injury check failed, forcing injury from heat");
                        __instance.OwningMech.pilot.InjurePilot(__instance.SequenceGUID.ToString(), __instance.RootSequenceGUID, 1, DamageType.OverheatSelf, null, __instance.OwningMech);
                        if (!__instance.OwningMech.pilot.IsIncapacitated)
                        {
                            AudioEventManager.SetPilotVOSwitch <AudioSwitch_dialog_dark_light>(AudioSwitch_dialog_dark_light.dark, __instance.OwningMech);
                            AudioEventManager.PlayPilotVO(VOEvents.Pilot_TakeDamage, __instance.OwningMech, null, null, true);
                            if (__instance.OwningMech.team.LocalPlayerControlsTeam)
                            {
                                AudioEventManager.PlayAudioEvent("audioeventdef_musictriggers_combat", "friendly_warrior_injured", null, null);
                            }
                        }
                    }

                    // Resolve System Damage
                    bool failedSystemFailureCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.SystemFailures, __instance.OwningMech.CurrentHeat, __instance.OwningMech, heatCheck, ModConfig.FT_Check_System_Failure);
                    Mod.Log.Debug($"  failedSystemFailureCheck: {failedSystemFailureCheck}");
                    if (failedSystemFailureCheck)
                    {
                        Mod.Log.Debug("-- System Failure check failed, forcing system damage");
                        List <MechComponent> functionalComponents = __instance.OwningMech.allComponents.Where(mc => mc.IsFunctional).ToList();
                        MechComponent        componentToDamage    = functionalComponents.GetRandomElement();
                        Mod.Log.Debug($" Destroying component: {componentToDamage.UIName} from heat damage.");

                        WeaponHitInfo fakeHit = new WeaponHitInfo(__instance.RootSequenceGUID, -1, -1, -1, string.Empty, string.Empty, -1, null, null, null, null, null, null, null,
                                                                  new AttackDirection[] { AttackDirection.None }, null, null, null);
                        componentToDamage.DamageComponent(fakeHit, ComponentDamageLevel.Destroyed, true);
                    }

                    // Resolve Ammo Explosion - regular ammo
                    bool          failedAmmoCheck = false;
                    AmmunitionBox mostDamaging    = HeatHelper.FindMostDamagingAmmoBox(__instance.OwningMech, false);
                    if (mostDamaging != null)
                    {
                        failedAmmoCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.Explosion, __instance.OwningMech.CurrentHeat, __instance.OwningMech, heatCheck, ModConfig.FT_Check_Explosion);
                        Mod.Log.Debug($"  failedAmmoCheck: {failedAmmoCheck}");
                        if (failedAmmoCheck)
                        {
                            Mod.Log.Debug("-- Ammo Explosion check failed, forcing ammo explosion");

                            if (mostDamaging != null)
                            {
                                Mod.Log.Debug($" Exploding ammo: {mostDamaging.UIName}");
                                WeaponHitInfo fakeHit = new WeaponHitInfo(__instance.RootSequenceGUID, -1, -1, -1, string.Empty, string.Empty, -1, null, null, null, null, null, null, null,
                                                                          new AttackDirection[] { AttackDirection.None }, null, null, null);
                                mostDamaging.DamageComponent(fakeHit, ComponentDamageLevel.Destroyed, true);
                            }
                            else
                            {
                                Mod.Log.Debug(" Unit has no ammo boxes, skipping.");
                            }
                        }
                    }

                    // Resolve Ammo Explosion - inferno ammo
                    bool          failedVolatileAmmoCheck = false;
                    AmmunitionBox mostDamagingVolatile    = HeatHelper.FindMostDamagingAmmoBox(__instance.OwningMech, true);
                    if (mostDamagingVolatile != null)
                    {
                        failedVolatileAmmoCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.Explosion, __instance.OwningMech.CurrentHeat, __instance.OwningMech, heatCheck, ModConfig.FT_Check_Explosion);
                        Mod.Log.Debug($"  failedVolatileAmmoCheck: {failedVolatileAmmoCheck}");
                        if (failedVolatileAmmoCheck)
                        {
                            Mod.Log.Debug("-- Volatile Ammo Explosion check failed, forcing volatile ammo explosion");

                            if (mostDamaging != null)
                            {
                                Mod.Log.Debug($" Exploding inferno ammo: {mostDamagingVolatile.UIName}");
                                WeaponHitInfo fakeHit = new WeaponHitInfo(__instance.RootSequenceGUID, -1, -1, -1, string.Empty, string.Empty, -1, null, null, null, null, null, null, null,
                                                                          new AttackDirection[] { AttackDirection.None }, null, null, null);
                                mostDamagingVolatile.DamageComponent(fakeHit, ComponentDamageLevel.Destroyed, true);
                            }
                            else
                            {
                                Mod.Log.Debug(" Unit has no inferno ammo boxes, skipping.");
                            }
                        }
                    }

                    bool failedShutdownCheck = false;
                    if (!__instance.OwningMech.IsShutDown)
                    {
                        // Resolve Shutdown + Fall
                        failedShutdownCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.Shutdown, __instance.OwningMech.CurrentHeat, __instance.OwningMech, heatCheck, ModConfig.FT_Check_Shutdown);
                        Mod.Log.Debug($"  failedShutdownCheck: {failedShutdownCheck}");
                        if (failedShutdownCheck)
                        {
                            Mod.Log.Debug("-- Shutdown check failed, forcing unit to shutdown");

                            string debuffText = new Text(Mod.Config.LocalizedFloaties[ModConfig.FT_Shutdown_Failed_Overide]).ToString();
                            sequence.AddChildSequence(new ShowActorInfoSequence(__instance.OwningMech, debuffText,
                                                                                FloatieMessage.MessageNature.Debuff, true), sequence.ChildSequenceCount - 1);

                            MechEmergencyShutdownSequence mechShutdownSequence = new MechEmergencyShutdownSequence(__instance.OwningMech)
                            {
                                RootSequenceGUID = __instance.SequenceGUID
                            };
                            sequence.AddChildSequence(mechShutdownSequence, sequence.ChildSequenceCount - 1);

                            if (__instance.OwningMech.IsOrWillBeProne)
                            {
                                bool failedFallingCheck = !CheckHelper.DidCheckPassThreshold(Mod.Config.Heat.ShutdownFallThreshold, __instance.OwningMech, pilotCheck, ModConfig.FT_Check_Fall);
                                Mod.Log.Debug($"  failedFallingCheck: {failedFallingCheck}");
                                if (failedFallingCheck)
                                {
                                    Mod.Log.Info("Pilot check from shutdown failed! Forcing a fall!");

                                    string fallDebuffText = new Text(Mod.Config.LocalizedFloaties[ModConfig.FT_Shutdown_Fall]).ToString();
                                    sequence.AddChildSequence(new ShowActorInfoSequence(__instance.OwningMech, fallDebuffText,
                                                                                        FloatieMessage.MessageNature.Debuff, true), sequence.ChildSequenceCount - 1);

                                    MechFallSequence mfs = new MechFallSequence(__instance.OwningMech, "Overheat", new Vector2(0f, -1f))
                                    {
                                        RootSequenceGUID = __instance.SequenceGUID
                                    };
                                    sequence.AddChildSequence(mfs, sequence.ChildSequenceCount - 1);
                                }
                                else
                                {
                                    Mod.Log.Info($"Pilot check to avoid falling passed.");
                                }
                            }
                            else
                            {
                                Mod.Log.Debug("Unit is already prone, skipping.");
                            }
                        }
                    }
                    else
                    {
                        Mod.Log.Debug("Unit is already shutdown, skipping.");
                    }

                    if (failedInjuryCheck || failedSystemFailureCheck || failedAmmoCheck || failedShutdownCheck)
                    {
                        __instance.OwningMech.Combat.MessageCenter.PublishMessage(new AddSequenceToStackMessage(sequence));
                    }

                    return(false);
                }

                if (__instance.OwningMech.GameRep != null)
                {
                    if (__instance.OwningMech.team.LocalPlayerControlsTeam)
                    {
                        if (__instance.OwningMech.CurrentHeat > __instance.OwningMech.OverheatLevel)
                        {
                            string text = string.Format("MechHeatSequence_{0}_{1}", __instance.RootSequenceGUID, __instance.SequenceGUID);
                            AudioEventManager.CreateVOQueue(text, -1f, null, null);
                            AudioEventManager.QueueVOEvent(text, VOEvents.Mech_Overheat_Warning, __instance.OwningMech);
                            AudioEventManager.StartVOQueue(1f);
                        }

                        if ((float)__instance.OwningMech.CurrentHeat > (float)__instance.OwningMech.MaxHeat - (float)(__instance.OwningMech.MaxHeat - __instance.OwningMech.OverheatLevel) * 0.333f)
                        {
                            WwiseManager.PostEvent <AudioEventList_ui>(AudioEventList_ui.ui_overheat_alarm_3, WwiseManager.GlobalAudioObject, null, null);
                        }
                        else if ((float)__instance.OwningMech.CurrentHeat > (float)__instance.OwningMech.MaxHeat - (float)(__instance.OwningMech.MaxHeat - __instance.OwningMech.OverheatLevel) * 0.666f)
                        {
                            WwiseManager.PostEvent <AudioEventList_ui>(AudioEventList_ui.ui_overheat_alarm_2, WwiseManager.GlobalAudioObject, null, null);
                        }
                        else if (__instance.OwningMech.CurrentHeat > __instance.OwningMech.OverheatLevel)
                        {
                            WwiseManager.PostEvent <AudioEventList_ui>(AudioEventList_ui.ui_overheat_alarm_1, WwiseManager.GlobalAudioObject, null, null);
                        }
                    }

                    if (__instance.OwningMech.CurrentHeat > Mod.Config.Heat.ShowLowOverheatAnim)
                    {
                        __instance.OwningMech.GameRep.StopManualPersistentVFX(__instance.OwningMech.Combat.Constants.VFXNames.heat_midHeat_persistent);
                        __instance.OwningMech.GameRep.PlayVFX(8, __instance.OwningMech.Combat.Constants.VFXNames.heat_highHeat_persistent, true, Vector3.zero, false, -1f);
                        return(false);
                    }

                    if ((float)__instance.OwningMech.CurrentHeat > Mod.Config.Heat.ShowExtremeOverheatAnim)
                    {
                        __instance.OwningMech.GameRep.StopManualPersistentVFX(__instance.OwningMech.Combat.Constants.VFXNames.heat_highHeat_persistent);
                        __instance.OwningMech.GameRep.PlayVFX(8, __instance.OwningMech.Combat.Constants.VFXNames.heat_midHeat_persistent, true, Vector3.zero, false, -1f);
                        return(false);
                    }

                    __instance.OwningMech.GameRep.StopManualPersistentVFX(__instance.OwningMech.Combat.Constants.VFXNames.heat_highHeat_persistent);
                    __instance.OwningMech.GameRep.StopManualPersistentVFX(__instance.OwningMech.Combat.Constants.VFXNames.heat_midHeat_persistent);
                }

                return(false);
            }