diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index d9d2e7a91..35f41777e 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -186,7 +186,7 @@ public enum CustomComboPreset [ReplaceSkill(AST.Gravity, AST.Gravity2)] [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("AoE DPS Feature", "Every option below (Lucid/AutoDraws/Astrodyne/etc) will also be added to Gravity", AST.JobID, 1, "", "")] + [CustomComboInfo("AoE DPS Option", "Every option below (Lucid/AutoDraws/etc) will also be added to Gravity", AST.JobID, 1, "", "")] AST_AoE_DPS = 1013, [ParentCombo(AST_ST_DPS)] @@ -202,33 +202,25 @@ public enum CustomComboPreset AST_DPS_Divination = 1016, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Card Draw Weave Option", "Draws your card", AST.JobID, 5, "", "")] + [CustomComboInfo("Card Draw Weave Option", "Draws your cards", AST.JobID, 5, "", "")] AST_DPS_AutoDraw = 1011, [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Card Play Weave Option", "Weaves your card (best used with Quick Target Cards)", AST.JobID, 6)] + [CustomComboInfo("Card Play Weave Option", "Weaves your Balance or Arrow card (best used with Quick Target Cards)", AST.JobID, 6)] AST_DPS_AutoPlay = 1037, - [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Redraw Option", "Weaves Redraw if you pull a card with a seal you already have and you can use Redraw.", AST.JobID, 7)] - AST_DPS_AutoPlay_Redraw = 1038, - - [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Astrodyne Weave Option", "Adds Astrodyne when you have 3 seals", AST.JobID, 8, "", "")] - AST_DPS_Astrodyne = 1009, - - [ParentCombo(AST_ST_DPS)] - [CustomComboInfo("Minor Arcana Weave Option", "Adds Minor Arcana", AST.JobID, 9, "", "")] - AST_DPS_AutoCrownDraw = 1012, - [ParentCombo(AST_ST_DPS)] [CustomComboInfo("Lord of Crowns Weave Option", "Adds Lord Of Crowns", AST.JobID, 10, "", "")] AST_DPS_LazyLord = 1014, + + [ParentCombo(AST_ST_DPS)] + [CustomComboInfo("Oracle Option", "Adds Oracle after Divination", AST.JobID)] + AST_DPS_Oracle = 1015, #endregion #region Healing [ReplaceSkill(AST.Benefic2)] - [CustomComboInfo("Simple Heals (Single Target)", "", AST.JobID, 2)] + [CustomComboInfo("Simple Heals (Single Target)", "Replaces Benefic II with a one button healing replacement.", AST.JobID, 2)] AST_ST_SimpleHeals = 1023, [ParentCombo(AST_ST_SimpleHeals)] @@ -248,11 +240,19 @@ public enum CustomComboPreset AST_ST_SimpleHeals_Esuna = 1039, [ParentCombo(AST_ST_SimpleHeals)] - [CustomComboInfo("Exaltation Feature", "Adds Exaltation.", AST.JobID)] + [CustomComboInfo("Exaltation Option", "Adds Exaltation.", AST.JobID)] AST_ST_SimpleHeals_Exaltation = 1028, + [ParentCombo(AST_ST_SimpleHeals)] + [CustomComboInfo("The Spire Option", "Adds The Spire when the card has been drawn", AST.JobID)] + AST_ST_SimpleHeals_Spire = 1030, + + [ParentCombo(AST_ST_SimpleHeals)] + [CustomComboInfo("The Ewer Option", "Adds The Ewer when the card has been drawn", AST.JobID)] + AST_ST_SimpleHeals_Ewer = 1032, + [ReplaceSkill(AST.AspectedHelios)] - [CustomComboInfo("Aspected Helios Feature", "Replaces Aspected Helios whenever you are under Aspected Helios regen with Helios", AST.JobID, 3, "", "")] + [CustomComboInfo("Simple Heals (AoE)", "Replaces Aspected Helios with a one button healing replacement.", AST.JobID, 3, "", "")] AST_AoE_SimpleHeals_AspectedHelios = 1010, [ParentCombo(AST_AoE_SimpleHeals_AspectedHelios)] @@ -270,6 +270,7 @@ public enum CustomComboPreset [ReplaceSkill(AST.Benefic2)] [CustomComboInfo("Benefic 2 Downgrade", "Changes Benefic 2 to Benefic when Benefic 2 is not unlocked or available.", AST.JobID, 4, "", "")] AST_Benefic = 1002, + #endregion #region Utility @@ -291,25 +292,7 @@ public enum CustomComboPreset #endregion #region Cards - [ReplaceSkill(AST.Play)] - [CustomComboInfo("Draw on Play", "Play turns into Draw when no card is drawn, as well as the usual Play behavior.", AST.JobID, 6, "", "")] - AST_Cards_DrawOnPlay = 1000, - - [ParentCombo(AST_Cards_DrawOnPlay)] - [CustomComboInfo("Redraw Feature", "Sets Play to Redraw if you pull a card with a seal you already have and you can use Redraw.", AST.JobID)] - AST_Cards_Redraw = 1032, - - [ReplaceSkill(AST.Draw)] - [CustomComboInfo("Redraw on Draw", "Sets Draw to Redraw if you have the Clarifying Draw buff.", AST.JobID)] - AST_Cards_RedrawStandalone = 1040, - - [ReplaceSkill(AST.Play)] - //Works With AST_Cards_DrawOnPlay as a feature, or by itself if AST_Cards_DrawOnPlay is disabled. - //Do not do ConflictingCombos with AST_Cards_DrawOnPlay - [CustomComboInfo("Astrodyne on Play", "Play becomes Astrodyne when you have 3 seals.", AST.JobID, 18, "", "")] - AST_Cards_AstrodyneOnPlay = 1015, - - [CustomComboInfo("Quick Target Cards", "Grabs a suitable target from the party list when you draw a card and targets them for you.", AST.JobID)] + [CustomComboInfo("Quick Target Damage Cards", "When you play the Balance or Spear, this will automatically apply the buff to a party member. It will look at DPS that suit the card first, if none found or they have buffs already, will look at the other DPS instead.", AST.JobID)] AST_Cards_QuickTargetCards = 1029, [ParentCombo(AST_Cards_QuickTargetCards)] diff --git a/XIVSlothCombo/Combos/JobHelpers/AST.cs b/XIVSlothCombo/Combos/JobHelpers/AST.cs index 16321ed9c..0399baeda 100644 --- a/XIVSlothCombo/Combos/JobHelpers/AST.cs +++ b/XIVSlothCombo/Combos/JobHelpers/AST.cs @@ -1,6 +1,7 @@ using Dalamud.Game.ClientState.JobGauge.Enums; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Plugin.Services; +using ECommons.DalamudServices; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.CustomComboNS.Functions; @@ -50,6 +51,7 @@ public static void Invoke() if (SelectedRandomMember is null || SelectedRandomMember.IsDead) { SetTarget(); + Svc.Log.Debug($"Set card to {SelectedRandomMember.Name}"); } } else @@ -68,21 +70,16 @@ private static bool SetTarget() if (GetPartySlot(i) is not IBattleChara member) continue; if (member is null) continue; //Skip nulls/disconnected people if (member.IsDead) continue; - if (OutOfRange(Bole, member)) continue; + if (OutOfRange(Balance, member)) continue; - if (FindEffectOnMember(Buffs.BalanceDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.ArrowDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.BoleDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.EwerDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.SpireDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.SpearDamage, member) is not null) continue; + if (FindEffectOnMember(Buffs.BalanceBuff, member) is not null) continue; + if (FindEffectOnMember(Buffs.SpearBuff, member) is not null) continue; if (Config.AST_QuickTarget_SkipDamageDown && TargetHasDamageDown(member)) continue; if (Config.AST_QuickTarget_SkipRezWeakness && TargetHasRezWeakness(member)) continue; PartyTargets.Add(member); } - //The inevitable "0 targets found" because of debuffs if (PartyTargets.Count == 0) { @@ -91,14 +88,10 @@ private static bool SetTarget() if (GetPartySlot(i) is not IBattleChara member) continue; if (member is null) continue; //Skip nulls/disconnected people if (member.IsDead) continue; - if (OutOfRange(Bole, member)) continue; + if (OutOfRange(Balance, member)) continue; - if (FindEffectOnMember(Buffs.BalanceDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.ArrowDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.BoleDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.EwerDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.SpireDamage, member) is not null) continue; - if (FindEffectOnMember(Buffs.SpearDamage, member) is not null) continue; + if (FindEffectOnMember(Buffs.BalanceBuff, member) is not null) continue; + if (FindEffectOnMember(Buffs.SpearBuff, member) is not null) continue; PartyTargets.Add(member); } @@ -121,22 +114,35 @@ private static bool SetTarget() for (int i = 0; i <= PartyTargets.Count - 1; i++) { byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.Id : (byte)0; - if (((cardDrawn is CardType.BALANCE or CardType.ARROW or CardType.SPEAR) && JobIDs.Melee.Contains(job)) || - ((cardDrawn is CardType.BOLE or CardType.EWER or CardType.SPIRE) && JobIDs.Ranged.Contains(job))) + if (((cardDrawn is CardType.BALANCE) && JobIDs.Melee.Contains(job)) || + ((cardDrawn is CardType.SPEAR) && JobIDs.Ranged.Contains(job))) { //TargetObject(PartyTargets[i]); SelectedRandomMember = PartyTargets[i]; return true; } } + //Give card to unsuitable DPS next + for (int i = 0; i <= PartyTargets.Count - 1; i++) + { + byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.Id : (byte)0; + if (((cardDrawn is CardType.BALANCE) && JobIDs.Ranged.Contains(job)) || + ((cardDrawn is CardType.SPEAR) && JobIDs.Melee.Contains(job))) + { + //TargetObject(PartyTargets[i]); + SelectedRandomMember = PartyTargets[i]; + return true; + } + } + //Give cards to healers/tanks if backup is turned on if (IsEnabled(CustomComboPreset.AST_Cards_QuickTargetCards_TargetExtra)) { for (int i = 0; i <= PartyTargets.Count - 1; i++) { byte job = PartyTargets[i] is IBattleChara ? (byte)(PartyTargets[i] as IBattleChara).ClassJob.Id : (byte)0; - if ((cardDrawn is CardType.BALANCE or CardType.ARROW or CardType.SPEAR && JobIDs.Tank.Contains(job)) || - (cardDrawn is CardType.BOLE or CardType.EWER or CardType.SPIRE && JobIDs.Healer.Contains(job))) + if ((cardDrawn is CardType.BALANCE && JobIDs.Tank.Contains(job)) || + (cardDrawn is CardType.SPEAR && JobIDs.Healer.Contains(job))) { //TargetObject(PartyTargets[i]); SelectedRandomMember = PartyTargets[i]; diff --git a/XIVSlothCombo/Combos/PvE/AST.cs b/XIVSlothCombo/Combos/PvE/AST.cs index 006e3cd28..1b17b5d51 100644 --- a/XIVSlothCombo/Combos/PvE/AST.cs +++ b/XIVSlothCombo/Combos/PvE/AST.cs @@ -2,7 +2,7 @@ using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Statuses; -using System; +using ECommons.DalamudServices; using System.Collections.Generic; using System.Linq; using XIVSlothCombo.Combos.PvE.Content; @@ -26,22 +26,22 @@ internal const uint FallMalefic = 25871, Gravity = 3615, Gravity2 = 25872, + Oracle = 37029, //Cards - Draw = 3590, - Play = 17055, - Redraw = 3593, - //Obsolete? Left just incase it's needed - Balance = 4401, - Bole = 4404, - Arrow = 4402, - Spear = 4403, - Ewer = 4405, - Spire = 4406, - MinorArcana = 7443, + AstralDraw = 37017, + Play1 = 37019, + Play2 = 37020, + Play3 = 37021, + Arrow = 37024, + Balance = 37023, + Bole = 37027, + Ewer = 37028, + Spear = 37026, + Spire = 37025, + MinorArcana = 37022, //LordOfCrowns = 7444, //LadyOfCrown = 7445, - Astrodyne = 25870, //Utility Divination = 16552, @@ -94,15 +94,16 @@ internal const ushort EwerDrawn = 917, SpireDrawn = 918, //The actual buff that buffs players - BalanceDamage = 1882, - BoleDamage = 1883, - ArrowDamage = 1884, - SpearDamage = 1885, - EwerDamage = 1886, - SpireDamage = 1887, + BalanceBuff = 3887, + BoleBuff = 3890, + ArrowBuff = 3888, + SpearBuff = 3889, + EwerBuff = 3891, + SpireBuff = 3892, Lightspeed = 841, SelfSynastry = 845, - TargetSynastry = 846; + TargetSynastry = 846, + Divining = 3893; } internal static class Debuffs @@ -128,9 +129,11 @@ internal static Dictionary public static class Config { public static UserInt - AST_LucidDreaming = new("ASTLucidDreamingFeature"), - AST_EssentialDignity = new("ASTCustomEssentialDignity"), - AST_ST_SimpleHeals_Esuna = new("AST_ST_SimpleHeals_Esuna"), + AST_LucidDreaming = new("ASTLucidDreamingFeature", 8000), + AST_EssentialDignity = new("ASTCustomEssentialDignity", 50), + AST_Spire = new("AST_Spire", 80), + AST_Ewer = new("AST_Ewer", 80), + AST_ST_SimpleHeals_Esuna = new("AST_ST_SimpleHeals_Esuna", 100), AST_DPS_AltMode = new("AST_DPS_AltMode"), AST_DPS_DivinationOption = new("AST_DPS_DivinationOption"), AST_DPS_LightSpeedOption = new("AST_DPS_LightSpeedOption"), @@ -142,35 +145,14 @@ public static UserBool AST_QuickTarget_SkipRezWeakness = new("AST_QuickTarget_SkipRezWeakness"), AST_ST_SimpleHeals_Adv = new("AST_ST_SimpleHeals_Adv"), AST_ST_SimpleHeals_UIMouseOver = new("AST_ST_SimpleHeals_UIMouseOver"), + AST_AoE_SimpleHeals_WeaveLady = new("AST_AoE_SimpleHeals_WeaveLady"), + AST_AoE_SimpleHeals_Opposition = new("AST_AoE_SimpleHeals_Opposition"), + AST_AoE_SimpleHeals_Horoscope = new("AST_AoE_SimpleHeals_Horoscope"), AST_ST_DPS_CombustUptime_Adv = new("AST_ST_DPS_CombustUptime_Adv"); public static UserFloat AST_ST_DPS_CombustUptime_Threshold = new("AST_ST_DPS_CombustUptime_Threshold"); } - internal class AST_Cards_DrawOnPlay : CustomCombo - { - - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.AST_Cards_DrawOnPlay; - - protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) - { - if (actionID is Play) - { - var haveCard = HasEffect(Buffs.BalanceDrawn) || HasEffect(Buffs.BoleDrawn) || HasEffect(Buffs.ArrowDrawn) || HasEffect(Buffs.SpearDrawn) || HasEffect(Buffs.EwerDrawn) || HasEffect(Buffs.SpireDrawn); - var cardDrawn = Gauge.DrawnCards[0]; - - - if (haveCard) - { - return OriginalHook(Play); - } - - return OriginalHook(Draw); - } - - return actionID; - } - } internal class AST_Benefic : CustomCombo { @@ -194,16 +176,15 @@ internal class AST_ST_DPS : CustomCombo protected override uint Invoke(uint actionID, uint lastComboMove, float comboTime, byte level) { - int spellsSinceDraw = ActionWatching.CombatActions.Any(x => x == Draw) ? ActionWatching.HowManyTimesUsedAfterAnotherAction(OriginalHook(Malefic), Draw) + - ActionWatching.HowManyTimesUsedAfterAnotherAction(OriginalHook(Combust), Draw) + - ActionWatching.HowManyTimesUsedAfterAnotherAction(OriginalHook(Gravity), Draw) : Config.AST_ST_DPS_Play_SpeedSetting; + int spellsSinceDraw = ActionWatching.CombatActions.Any(x => x == OriginalHook(AstralDraw)) ? ActionWatching.HowManyTimesUsedAfterAnotherAction(OriginalHook(Malefic), OriginalHook(AstralDraw)) + + ActionWatching.HowManyTimesUsedAfterAnotherAction(OriginalHook(Combust), OriginalHook(AstralDraw)) + + ActionWatching.HowManyTimesUsedAfterAnotherAction(OriginalHook(Gravity), OriginalHook(AstralDraw)) : Config.AST_ST_DPS_Play_SpeedSetting; if (spellsSinceDraw == 0 && DrawnCard != CardType.NONE) { spellsSinceDraw = 1; } - //Dalamud.Logging.PluginLog.Debug($"{spellsSinceDraw}"); bool AlternateMode = GetIntOptionAsBool(Config.AST_DPS_AltMode); //(0 or 1 radio values) if (((!AlternateMode && MaleficList.Contains(actionID)) || (AlternateMode && CombustList.ContainsKey(actionID)) || @@ -240,19 +221,18 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim //Play Card if (IsEnabled(CustomComboPreset.AST_DPS_AutoPlay) && - ActionReady(Play) && + ActionReady(Play1) && Gauge.DrawnCards[0] is not CardType.NONE && CanSpellWeave(actionID) && - spellsSinceDraw >= Config.AST_ST_DPS_Play_SpeedSetting && - !WasLastAction(Redraw)) - return OriginalHook(Play); + spellsSinceDraw >= Config.AST_ST_DPS_Play_SpeedSetting) + return OriginalHook(Play1); //Card Draw if (IsEnabled(CustomComboPreset.AST_DPS_AutoDraw) && - ActionReady(Draw) && - Gauge.DrawnCards[0] is CardType.NONE && + ActionReady(OriginalHook(AstralDraw)) && + Gauge.DrawnCards.All(x => x is CardType.NONE) && CanDelayedWeave(actionID)) - return Draw; + return OriginalHook(AstralDraw); //Divination if (IsEnabled(CustomComboPreset.AST_DPS_Divination) && @@ -263,10 +243,15 @@ Gauge.DrawnCards[0] is CardType.NONE && ActionWatching.NumberOfGcdsUsed >= 3) return Divination; + if (IsEnabled(CustomComboPreset.AST_DPS_Oracle) && + HasEffect(Buffs.Divining) && + CanSpellWeave(actionID)) + return Oracle; + //Minor Arcana / Lord of Crowns if (ActionReady(OriginalHook(MinorArcana)) && - ((IsEnabled(CustomComboPreset.AST_DPS_AutoCrownDraw) && Gauge.DrawnCrownCard is CardType.NONE) || - (IsEnabled(CustomComboPreset.AST_DPS_LazyLord) && Gauge.DrawnCrownCard is CardType.LORD && HasBattleTarget())) && + IsEnabled(CustomComboPreset.AST_DPS_LazyLord) && Gauge.DrawnCrownCard is CardType.LORD && + HasBattleTarget() && CanDelayedWeave(actionID)) return OriginalHook(MinorArcana); @@ -310,26 +295,30 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim { if (actionID is AspectedHelios) { + var canLady = (Config.AST_AoE_SimpleHeals_WeaveLady && CanSpellWeave(actionID)) || !Config.AST_AoE_SimpleHeals_WeaveLady; + var canHoroscope = (Config.AST_AoE_SimpleHeals_Horoscope && CanSpellWeave(actionID)) || !Config.AST_AoE_SimpleHeals_Horoscope; + var canOppose = (Config.AST_AoE_SimpleHeals_Opposition && CanSpellWeave(actionID)) || !Config.AST_AoE_SimpleHeals_Opposition; + + //Level check to exit if we can't use if (!LevelChecked(AspectedHelios)) return Helios; if (IsEnabled(CustomComboPreset.AST_AoE_SimpleHeals_LazyLady) && ActionReady(MinorArcana) && - InCombat() && Gauge.DrawnCrownCard is CardType.LADY - && CanSpellWeave(actionID)) + && canLady) return OriginalHook(MinorArcana); if (IsEnabled(CustomComboPreset.AST_AoE_SimpleHeals_CelestialOpposition) && ActionReady(CelestialOpposition) && - CanWeave(actionID)) + canOppose) return CelestialOpposition; if (IsEnabled(CustomComboPreset.AST_AoE_SimpleHeals_Horoscope)) { if (ActionReady(Horoscope) && - CanSpellWeave(actionID)) + canHoroscope) return Horoscope; if ((ActionReady(AspectedHelios) && !HasEffect(Buffs.AspectedHelios)) @@ -338,7 +327,7 @@ Gauge.DrawnCrownCard is CardType.LADY return AspectedHelios; if (HasEffect(Buffs.HoroscopeHelios) && - CanSpellWeave(actionID)) + canHoroscope) return OriginalHook(Horoscope); } @@ -351,19 +340,6 @@ Gauge.DrawnCrownCard is CardType.LADY } - internal class AST_Cards_RedrawStandalone : CustomCombo - { - protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.AST_Cards_RedrawStandalone; - - protected override uint Invoke(uint actionID, uint lastComboActionID, float comboTime, byte level) - { - if (actionID is Draw && HasEffect(Buffs.ClarifyingDraw)) - return Redraw; - - return actionID; - } - } - internal class AST_ST_SimpleHeals : CustomCombo { protected internal override CustomComboPreset Preset { get; } = CustomComboPreset.AST_ST_SimpleHeals; @@ -389,6 +365,17 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim return AspectedBenefic; } + if ((IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Spire) && + Gauge.DrawnCards[2] == CardType.SPIRE && + GetTargetHPPercent(healTarget) <= Config.AST_Spire && + CanSpellWeave(actionID)) + || + (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_Ewer) && + Gauge.DrawnCards[2] == CardType.EWER && + GetTargetHPPercent(healTarget) <= Config.AST_Ewer && + CanSpellWeave(actionID))) + return OriginalHook(Play3); + if (IsEnabled(CustomComboPreset.AST_ST_SimpleHeals_EssentialDignity) && ActionReady(EssentialDignity) && GetTargetHPPercent(healTarget) <= Config.AST_EssentialDignity && diff --git a/XIVSlothCombo/CustomCombo/Functions/Misc.cs b/XIVSlothCombo/CustomCombo/Functions/Misc.cs index 7defad19e..cc78e5a2c 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Misc.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Misc.cs @@ -25,6 +25,7 @@ public class JobIDs DRG.JobID, DRG.ClassID, MNK.JobID, MNK.ClassID, NIN.JobID, NIN.ClassID, + VPR.JobID, RPR.JobID, SAM.JobID ]; @@ -34,6 +35,7 @@ public class JobIDs BLM.JobID, BLM.ClassID, BRD.JobID, BRD.ClassID, SMN.JobID, SMN.ClassID, + PCT.JobID, MCH.JobID, RDM.JobID, DNC.JobID, diff --git a/XIVSlothCombo/CustomCombo/Functions/Target.cs b/XIVSlothCombo/CustomCombo/Functions/Target.cs index 3f6f18f28..7c578fb09 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Target.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Target.cs @@ -378,7 +378,7 @@ static internal float AngleXZ(Vector3 a, Vector3 b) } } - internal unsafe static bool OutOfRange(uint actionID, IGameObject target) => ActionWatching.OutOfRange(actionID, (StructsObject.GameObject*)Service.ClientState.LocalPlayer.Address, (StructsObject.GameObject*)target.Address); + internal unsafe static bool OutOfRange(uint actionID, IGameObject target) => ActionWatching.OutOfRange(actionID, Service.ClientState.LocalPlayer!, target); } } diff --git a/XIVSlothCombo/Data/ActionWatching.cs b/XIVSlothCombo/Data/ActionWatching.cs index 1aedc8af1..3a02f8fcb 100644 --- a/XIVSlothCombo/Data/ActionWatching.cs +++ b/XIVSlothCombo/Data/ActionWatching.cs @@ -1,6 +1,8 @@ using Dalamud.Game.ClientState.Conditions; +using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Hooking; using ECommons.DalamudServices; +using ECommons.GameFunctions; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Lumina.Excel.GeneratedSheets; @@ -10,6 +12,7 @@ using System.Runtime.InteropServices; using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS.Functions; +using XIVSlothCombo.Extensions; using XIVSlothCombo.Services; namespace XIVSlothCombo.Data @@ -102,15 +105,17 @@ private unsafe static void SendActionDetour(ulong targetObjectId, byte actionTyp private unsafe static void CheckForChangedTarget(uint actionId, ref ulong targetObjectId) { - if (actionId is AST.Balance or AST.Bole or AST.Ewer or AST.Arrow or AST.Spire or AST.Spear && + Svc.Log.Debug($"{actionId.ActionName()}"); + if (actionId is AST.Balance or AST.Spear && Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember is not null && - !OutOfRange(actionId, (GameObject*)Service.ClientState.LocalPlayer.Address, (GameObject*)Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.Address)) + !OutOfRange(actionId, Service.ClientState.LocalPlayer!, Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember)) { int targetOptions = AST.Config.AST_QuickTarget_Override; switch (targetOptions) { case 0: + Svc.Log.Debug($"Switched to {Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.Name}"); targetObjectId = Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember.GameObjectId; break; case 1: @@ -129,9 +134,9 @@ Combos.JobHelpers.AST.AST_QuickTargetCards.SelectedRandomMember is not null && } } - public static unsafe bool OutOfRange(uint actionId, GameObject* source, GameObject* target) + public static unsafe bool OutOfRange(uint actionId, IGameObject source, IGameObject target) { - return ActionManager.GetActionInRangeOrLoS(actionId, source, target) is 566; + return ActionManager.GetActionInRangeOrLoS(actionId, source.Struct(), target.Struct()) is 566; } public static uint WhichOfTheseActionsWasLast(params uint[] actions) diff --git a/XIVSlothCombo/Window/Functions/UserConfig.cs b/XIVSlothCombo/Window/Functions/UserConfig.cs index 0b5b4aa41..a78394f40 100644 --- a/XIVSlothCombo/Window/Functions/UserConfig.cs +++ b/XIVSlothCombo/Window/Functions/UserConfig.cs @@ -1244,9 +1244,25 @@ internal static void Draw(CustomComboPreset preset, bool enabled) if (preset is CustomComboPreset.AST_ST_SimpleHeals_EssentialDignity) UserConfig.DrawSliderInt(0, 100, AST.Config.AST_EssentialDignity, "Set percentage value"); + if (preset is CustomComboPreset.AST_ST_SimpleHeals_Spire) + UserConfig.DrawSliderInt(0, 100, AST.Config.AST_Spire, "Set percentage value"); + + if (preset is CustomComboPreset.AST_ST_SimpleHeals_Ewer) + UserConfig.DrawSliderInt(0, 100, AST.Config.AST_Ewer, "Set percentage value"); + if (preset is CustomComboPreset.AST_ST_SimpleHeals_Esuna) UserConfig.DrawSliderInt(0, 100, AST.Config.AST_ST_SimpleHeals_Esuna, "Stop using when below HP %. Set to Zero to disable this check"); + + if (preset is CustomComboPreset.AST_AoE_SimpleHeals_LazyLady) + UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AoE_SimpleHeals_WeaveLady, "Only Weave", "Will only weave this action."); + + if (preset is CustomComboPreset.AST_AoE_SimpleHeals_Horoscope) + UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AoE_SimpleHeals_Horoscope, "Only Weave", "Will only weave this action."); + + if (preset is CustomComboPreset.AST_AoE_SimpleHeals_CelestialOpposition) + UserConfig.DrawAdditionalBoolChoice(AST.Config.AST_AoE_SimpleHeals_Opposition, "Only Weave", "Will only weave this action."); + if (preset is CustomComboPreset.AST_Cards_QuickTargetCards) { UserConfig.DrawRadioButton(AST.Config.AST_QuickTarget_Override, "No Override", "", 0); diff --git a/XIVSlothCombo/Window/Icons.cs b/XIVSlothCombo/Window/Icons.cs index 1ce90b212..f37fa589d 100644 --- a/XIVSlothCombo/Window/Icons.cs +++ b/XIVSlothCombo/Window/Icons.cs @@ -1,15 +1,50 @@ -using Dalamud.Interface.Internal; +using Dalamud.Interface.Textures; using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Utility; using ECommons.DalamudServices; +using Lumina.Data.Files; +using System.Collections.Generic; namespace XIVSlothCombo.Window { internal static class Icons { + public static Dictionary CachedModdedIcons = new(); public static IDalamudTextureWrap? GetJobIcon(uint jobId) { if (jobId == 0 || jobId > 42) return null; - return Svc.Texture.GetFromGameIcon(new Dalamud.Interface.Textures.GameIconLookup(62100 + jobId)).GetWrapOrEmpty(); + var icon = GetTextureFromIconId(62100 + jobId); + + return icon; + } + + private static string ResolvePath(string path) => Svc.TextureSubstitution.GetSubstitutedPath(path); + + public static IDalamudTextureWrap? GetTextureFromIconId(uint iconId, uint stackCount = 0, bool hdIcon = true) + { + GameIconLookup lookup = new GameIconLookup(iconId + stackCount, false, hdIcon); + string path = Svc.Texture.GetIconPath(lookup); + string resolvePath = ResolvePath(path); + + var wrap = Svc.Texture.GetFromFile(resolvePath); + if (wrap.TryGetWrap(out var icon, out _)) + return icon; + + try + { + if (CachedModdedIcons.ContainsKey(iconId)) return CachedModdedIcons[iconId]; + var tex = Svc.Data.GameData.GetFileFromDisk(resolvePath); + var output = Svc.Texture.CreateFromRaw(RawImageSpecification.Rgba32(tex.Header.Width, tex.Header.Width), tex.GetRgbaImageData()); + if (output != null) + { + CachedModdedIcons[iconId] = output; + return output; + } + } + catch { } + + + return Svc.Texture.GetFromGame(path).GetWrapOrDefault(); } } } diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 4b655ce52..06a48d56b 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -1,4 +1,5 @@ -using Dalamud.Game.ClientState.Objects.SubKinds; +using Dalamud.Game.ClientState.JobGauge.Types; +using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; using ECommons.DalamudServices; using ImGuiNET; @@ -66,17 +67,21 @@ internal class DebugCombo : CustomCombo ImGui.TextUnformatted($"SELECTED BLU SPELLS:\n{string.Join("\n", Service.Configuration.ActiveBLUSpells.Select(x => ActionWatching.GetActionName(x)).OrderBy(x => x))}"); ImGui.EndChild(); - var pctGauge = new TmpPCTGauge(); - ImGui.InputInt("DebugNum", ref debugNum); - ImGui.Text($"{pctGauge.GetOffset(debugNum)}"); - ImGui.Text($"Pallete: {pctGauge.PalleteGauge}"); - ImGui.Text($"Paint: {pctGauge.Paint}"); - ImGui.Text($"Creature: {pctGauge.CreatureMotifDrawn}"); - ImGui.Text($"Weapon: {pctGauge.WeaponMotifDrawn}"); - ImGui.Text($"Landscape: {pctGauge.LandscapeMotifDrawn}"); - ImGui.Text($"Moogle Potrait: {pctGauge.MooglePortraitReady}"); + var gauge = CustomComboFunctions.GetJobGauge(); + ImGui.Text($"{gauge.DrawnCards[0]}"); + ImGui.Text($"{gauge.DrawnCards[1]}"); + ImGui.Text($"{gauge.DrawnCards[2]}"); + ImGui.Text($"{gauge.ActiveDraw}"); + ImGui.Text($"{gauge.DrawnCrownCard}"); - ImGui.Text($"{CustomComboFunctions.GetCooldown(CustomComboFunctions.OriginalHook(PCT.FireInRed)).CooldownRemaining}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(1).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(2).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(3).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(4).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(5).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(6).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(7).Name}"); + ImGui.Text($"{CustomComboFunctions.GetPartySlot(8).Name}"); } else diff --git a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs index 4ce891c27..19c6e76d5 100644 --- a/XIVSlothCombo/Window/Tabs/PvEFeatures.cs +++ b/XIVSlothCombo/Window/Tabs/PvEFeatures.cs @@ -51,14 +51,14 @@ internal class PvEFeatures : ConfigWindow IDalamudTextureWrap? icon = Icons.GetJobIcon(id); using (var disabled = ImRaii.Disabled(DisabledJobsPVE.Any(x => x == id))) { - if (ImGui.Selectable($"###{header}", OpenJob == jobName, ImGuiSelectableFlags.None, icon == null ? new Vector2(0) : new Vector2(0, (icon.Size.Y / 2f) * ImGui.GetIO().FontGlobalScale))) + if (ImGui.Selectable($"###{header}", OpenJob == jobName, ImGuiSelectableFlags.None, icon == null ? new Vector2(0) : new Vector2(0, (icon.Size.Y / 2f).Scale()))) { OpenJob = jobName; } ImGui.SameLine(indentwidth); if (icon != null) { - ImGui.Image(icon.ImGuiHandle, (icon.Size / 2f) * ImGui.GetIO().FontGlobalScale); + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Size.X.Scale(), icon.Size.Y.Scale()) / 2f); ImGui.SameLine(indentwidth2); } ImGui.Text($"{header} {(disabled ? "(Disabled due to update)" : "")}"); @@ -70,9 +70,9 @@ internal class PvEFeatures : ConfigWindow var id = groupedPresets[OpenJob].First().Info.JobID; IDalamudTextureWrap? icon = Icons.GetJobIcon(id); - using (var headingTab = ImRaii.Child("HeadingTab", new Vector2(ImGui.GetContentRegionAvail().X, icon is null ? 24f.Scale() : (icon.Size.Y / 2f.Scale()) + 4f))) + using (var headingTab = ImRaii.Child("HeadingTab", new Vector2(ImGui.GetContentRegionAvail().X, icon is null ? 24f.Scale() : (icon.Size.Y / 2f).Scale() + 4f))) { - if (ImGui.Button("Back")) + if (ImGui.Button("Back", new Vector2(0, 24f.Scale()))) { OpenJob = ""; return; @@ -82,7 +82,7 @@ internal class PvEFeatures : ConfigWindow { if (icon != null) { - ImGui.Image(icon.ImGuiHandle, (icon.Size / 2f.Scale())); + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Size.X.Scale(), icon.Size.Y.Scale()) / 2f); ImGui.SameLine(); } ImGuiEx.Text($"{OpenJob}"); diff --git a/XIVSlothCombo/Window/Tabs/PvPFeatures.cs b/XIVSlothCombo/Window/Tabs/PvPFeatures.cs index 4ac471dc0..cca1d0da7 100644 --- a/XIVSlothCombo/Window/Tabs/PvPFeatures.cs +++ b/XIVSlothCombo/Window/Tabs/PvPFeatures.cs @@ -55,14 +55,14 @@ internal class PvPFeatures : ConfigWindow IDalamudTextureWrap? icon = Icons.GetJobIcon(id); using (var disabled = ImRaii.Disabled(DisabledJobsPVP.Any(x => x == id))) { - if (ImGui.Selectable($"###{header}", OpenJob == jobName, ImGuiSelectableFlags.None, icon == null ? new Vector2(0) : new Vector2(0, (icon.Size.Y / 2f) * ImGui.GetIO().FontGlobalScale))) + if (ImGui.Selectable($"###{header}", OpenJob == jobName, ImGuiSelectableFlags.None, icon == null ? new Vector2(0) : new Vector2(0, (icon.Size.Y / 2f).Scale()))) { OpenJob = jobName; } ImGui.SameLine(indentwidth); if (icon != null) { - ImGui.Image(icon.ImGuiHandle, (icon.Size / 2f) * ImGui.GetIO().FontGlobalScale); + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Size.X.Scale(), icon.Size.Y.Scale()) / 2f); ImGui.SameLine(indentwidth2); } ImGui.Text($"{header} {(disabled ? "(Disabled due to update)" : "")}"); @@ -76,19 +76,21 @@ internal class PvPFeatures : ConfigWindow using (var headingTab = ImRaii.Child("PvPHeadingTab", new Vector2(ImGui.GetContentRegionAvail().X, icon is null ? 24f.Scale() : (icon.Size.Y / 2f.Scale()) + 4f))) { - if (ImGui.Button("Back")) + if (ImGui.Button("Back", new Vector2(0, 24f.Scale()))) { OpenJob = ""; return; } - - ImGui.SameLine(ImGui.GetContentRegionAvail().X / 2); - if (icon != null) + ImGui.SameLine(); + ImGuiEx.LineCentered(() => { - ImGui.Image(icon.ImGuiHandle, (icon.Size / 2f.Scale())); - ImGui.SameLine((ImGui.GetContentRegionAvail().X / 2) + 42f.Scale()); - } - ImGuiEx.Text($"{OpenJob}"); + if (icon != null) + { + ImGui.Image(icon.ImGuiHandle, new Vector2(icon.Size.X.Scale(), icon.Size.Y.Scale()) / 2f); + ImGui.SameLine(); + } + ImGuiEx.Text($"{OpenJob}"); + }); } diff --git a/XIVSlothCombo/XIVSlothCombo.cs b/XIVSlothCombo/XIVSlothCombo.cs index 0771ca298..b38145de4 100644 --- a/XIVSlothCombo/XIVSlothCombo.cs +++ b/XIVSlothCombo/XIVSlothCombo.cs @@ -24,6 +24,9 @@ using Dalamud.Utility; using XIVSlothCombo.Attributes; using Dalamud.Interface.Windowing; +using Dalamud.Game.Addon.Lifecycle; +using ECommons.DalamudServices; +using Dalamud.Game.Addon.Lifecycle.AddonArgTypes; namespace XIVSlothCombo { @@ -43,13 +46,13 @@ public sealed partial class XIVSlothCombo : IDalamudPlugin public static readonly List DisabledJobsPVE = new List() { - ADV.JobID, - AST.JobID, + //ADV.JobID, + //AST.JobID, BLM.JobID, //BLU.JobID, BRD.JobID, DNC.JobID, - DOL.JobID, + //DOL.JobID, DRG.JobID, DRK.JobID, //GNB.JobID, @@ -153,10 +156,16 @@ public XIVSlothCombo(IDalamudPluginInterface pluginInterface) #if DEBUG PvEFeatures.HasToOpenJob = false; + PvEFeatures.OpenJob = "Astrologian"; ConfigWindow.IsOpen = true; #endif } + private void AddonReceiveEvent(AddonEvent type, AddonArgs args) + { + Svc.Log.Debug($"Receive event triggered on {args.AddonName}"); + } + private static void HandleConflictedCombos() { var enabledCopy = Service.Configuration.EnabledActions.ToHashSet(); //Prevents issues later removing during enumeration