diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs index 58c3583fa..36d6cb0f6 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH.cs @@ -57,7 +57,8 @@ internal const uint Aetherflow = 166, Recitation = 16542, ChainStratagem = 7436, - DeploymentTactics = 3585; + DeploymentTactics = 3585, + EmergencyTactics = 3586; //Action Groups internal static readonly List @@ -453,7 +454,8 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (enabled) { - if (ActionReady(spell)) + if (GetPartyAvgHPPercent() <= config && + ActionReady(spell)) return spell; } } @@ -547,12 +549,14 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Check for the Galvanize shield buff. Start applying if it doesn't exist or Target HP is below % if (IsEnabled(CustomComboPreset.SCH_ST_Heal_Adloquium) && ActionReady(Adloquium) && - GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption && - (Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check - (!Config.SCH_ST_Heal_AldoquimOpts[1] || + GetTargetHPPercent(healTarget, Config.SCH_ST_Heal_IncludeShields) <= Config.SCH_ST_Heal_AdloquiumOption) + { + if (Config.SCH_ST_Heal_AldoquimOpts[2] && ActionReady(EmergencyTactics)) return EmergencyTactics; + + if ((Config.SCH_ST_Heal_AldoquimOpts[0] || FindEffectOnMember(Buffs.Galvanize, healTarget) is null) && //Ignore existing shield check + (!Config.SCH_ST_Heal_AldoquimOpts[1] || (FindEffectOnMember(SGE.Buffs.EukrasianDiagnosis, healTarget) is null && FindEffectOnMember(SGE.Buffs.EukrasianPrognosis, healTarget) is null) )) //Eukrasia Shield Check - { return OriginalHook(Adloquium); } } diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs index 21cdf5628..914d66928 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Config.cs @@ -31,6 +31,13 @@ public static UserBoolArray public static UserInt SCH_AoE_LucidOption = new("SCH_AoE_LucidOption", 6500), SCH_AoE_Heal_LucidOption = new("SCH_AoE_Heal_LucidOption", 6500), + SCH_AoE_Heal_SuccorShieldOption = new("SCH_AoE_Heal_SuccorShieldCount",4), + SCH_AoE_Heal_WhisperingDawnOption = new("SCH_AoE_Heal_WhisperingDawnOption"), + SCH_AoE_Heal_FeyIlluminationOption = new("SCH_AoE_Heal_FeyIlluminationOption"), + SCH_AoE_Heal_ConsolationOption = new("SCH_AoE_Heal_ConsolationOption"), + SCH_AoE_Heal_FeyBlessingOption = new("SCH_AoE_Heal_FeyBlessingOption"), + SCH_AoE_Heal_SeraphismOption = new("SCH_AoE_Heal_SeraphismOption"), + SCH_AoE_Heal_IndomitabilityOption = new("SCH_AoE_Heal_IndomitabilityOption"), SCH_ST_Heal_LucidOption = new("SCH_ST_Heal_LucidOption", 6500), SCH_ST_Heal_AdloquiumOption = new("SCH_ST_Heal_AdloquiumOption"), SCH_ST_Heal_LustrateOption = new("SCH_ST_Heal_LustrateOption"), @@ -129,8 +136,9 @@ internal static void Draw(CustomComboPreset preset) case CustomComboPreset.SCH_ST_Heal_Adloquium: DrawSliderInt(0, 100, SCH_ST_Heal_AdloquiumOption, $"Start using when below HP %. Set to 100 to disable this check."); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 2, 0); - DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"Check for Sage {SGE.EukrasianDiagnosis.ActionName()}/{SGE.EukrasianPrognosis.ActionName()}", "Enable to not override an existing Sage's shield.", 2, 1); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Ignore Shield Check", $"Warning, will force the use of {Adloquium.ActionName()}, and normal {Physick.ActionName()} maybe unavailable.", 3, 0); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, "Sage Shield Check", "Enable to not override an existing Sage's shield.", 3, 1); + DrawHorizontalMultiChoice(SCH_ST_Heal_AldoquimOpts, $"{EmergencyTactics.ActionName()}", $"Use {EmergencyTactics.ActionName()} before {Adloquium.ActionName()}", 3, 2); break; case CustomComboPreset.SCH_ST_Heal_Lustrate: @@ -166,28 +174,40 @@ internal static void Draw(CustomComboPreset preset) DrawSliderInt(4000, 9500, SCH_AoE_Heal_LucidOption, "MP Threshold", 150, Hundreds); break; + case CustomComboPreset.SCH_AoE_Heal: + ImGui.TextUnformatted("Note: Succor will always be available. These options are to provide optional priority to Succor."); + DrawSliderInt(0, 100, SCH_AoE_Heal_SuccorShieldOption, "Shield Check: Percentage of Party Members without shields to check for.", sliderIncrement: 25); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 6, $"{Succor.ActionName()} Priority: "); + break; + case CustomComboPreset.SCH_AoE_Heal_WhisperingDawn: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 0, $"{WhisperingDawn.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_WhisperingDawnOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 0, $"{WhisperingDawn.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_FeyIllumination: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 1, $"{FeyIllumination.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_FeyIlluminationOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 1, $"{FeyIllumination.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_FeyBlessing: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 2, $"{FeyBlessing.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_FeyBlessingOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 2, $"{FeyBlessing.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_Consolation: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 3, $"{Consolation.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_ConsolationOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 3, $"{Consolation.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_Seraphism: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 4, $"{Seraphism.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_SeraphismOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 4, $"{Seraphism.ActionName()} Priority: "); break; case CustomComboPreset.SCH_AoE_Heal_Indomitability: - DrawPriorityInput(SCH_AoE_Heals_Priority, 6, 5, $"{Indomitability.ActionName()} Priority: "); + DrawSliderInt(0, 100, SCH_AoE_Heal_IndomitabilityOption, "Start using when below party average HP %. Set to 100 to disable this check"); + DrawPriorityInput(SCH_AoE_Heals_Priority, 7, 5, $"{Indomitability.ActionName()} Priority: "); break; case CustomComboPreset.SCH_DeploymentTactics: diff --git a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs index 6c994441e..616f47429 100644 --- a/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs +++ b/XIVSlothCombo/Combos/PvE/SCH/SCH_Helper.cs @@ -19,8 +19,6 @@ internal enum OpenerState public static int GetMatchingConfigST(int i, out uint action, out bool enabled) { - var healTarget = GetHealTarget(Config.SCH_ST_Heal_Adv && Config.SCH_ST_Heal_UIMouseOver); - switch (i) { case 0: @@ -53,27 +51,31 @@ public static int GetMatchingConfigAoE(int i, out uint action, out bool enabled) case 0: action = OriginalHook(WhisperingDawn); enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_WhisperingDawn); - return 0; + return Config.SCH_AoE_Heal_WhisperingDawnOption; case 1: action = OriginalHook(FeyIllumination); enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_FeyIllumination); - return 0; + return Config.SCH_AoE_Heal_FeyIlluminationOption; case 2: action = FeyBlessing; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_FeyBlessing); - return 0; + return Config.SCH_AoE_Heal_FeyBlessingOption; case 3: action = Consolation; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Consolation) && Gauge.SeraphTimer > 0; - return 0; + return Config.SCH_AoE_Heal_ConsolationOption; case 4: action = Seraphism; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Seraphism); - return 0; + return Config.SCH_AoE_Heal_SeraphismOption; case 5: action = Indomitability; enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal_Indomitability) && Gauge.HasAetherflow(); - return 0; + return Config.SCH_AoE_Heal_IndomitabilityOption; + case 6: + action = OriginalHook(Succor); + enabled = IsEnabled(CustomComboPreset.SCH_AoE_Heal) && GetPartyBuffPercent(Buffs.Galvanize) <= Config.SCH_AoE_Heal_SuccorShieldOption; + return 0; //Don't HP Check } enabled = false; diff --git a/XIVSlothCombo/CustomCombo/Functions/Party.cs b/XIVSlothCombo/CustomCombo/Functions/Party.cs index 429bb7c02..383fa1ced 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Party.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Party.cs @@ -52,5 +52,36 @@ public static List GetPartyMembers() return null; } } + + public static float GetPartyAvgHPPercent() + { + float HP = 0; + byte Count = 0; + for (int i = 1; i <= 8; i++) //Checking all 8 available slots and skipping nulls & DCs + { + if (GetPartySlot(i) is not IBattleChara member) continue; + if (member is null) continue; //Skip nulls/disconnected people + if (member.IsDead) continue; + + HP += GetTargetHPPercent(member); + Count++; + } + return Count == 0 ? 0 : (float)HP / Count; //Div by 0 check...just in case.... + } + + public static float GetPartyBuffPercent(ushort buff) + { + byte BuffCount = 0; + byte PartyCount = 0; + for (int i = 1; i <= 8; i++) //Checking all 8 available slots and skipping nulls & DCs + { + if (GetPartySlot(i) is not IBattleChara member) continue; + if (member is null) continue; //Skip nulls/disconnected people + if (member.IsDead) continue; + if (FindEffectOnMember(buff, member) is not null) BuffCount++; + PartyCount++; + } + return PartyCount == 0 ? 0 : (float)BuffCount / PartyCount * 100f; //Div by 0 check...just in case.... + } } } diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 19c26773e..1a172d02d 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -227,6 +227,9 @@ static void CustomStyleText(string label, object? value) CustomStyleText("Relative Position:", AngleToTarget() is 2 ? "Rear" : (AngleToTarget() is 1 or 3) ? "Flank" : AngleToTarget() is 4 ? "Front" : ""); CustomStyleText("Health:", $"{EnemyHealthCurrentHp().ToString("N0")} / {EnemyHealthMaxHp().ToString("N0")} ({Math.Round(GetTargetHPPercent(), 2)}%)"); CustomStyleText("Shield:", (GetHealTarget() as ICharacter).ShieldPercentage); + CustomStyleText("Health Percent (+ Shield):", $"{GetTargetHPPercent(GetHealTarget())} / {GetTargetHPPercent(GetHealTarget(), true)}"); + CustomStyleText("Party Avg HP Percent:", $"{GetPartyAvgHPPercent()}"); + ImGui.Indent(); if (ImGui.CollapsingHeader("Relative Target Distances")) {