From 3776edb5b4eb308904e68d41bf8178db7896fdd1 Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 24 Oct 2019 01:43:22 -0400 Subject: [PATCH] Finished job gauge structs. Added a few gauge-related enums. Finished adding default icon replacers. --- Dalamud/Configuration/CustomComboPreset.cs | 57 ++- .../ClientState/ClientStateAddressResolver.cs | 2 +- .../ClientState/Structs/JobGauge/ASTGauge.cs | 13 + .../ClientState/Structs/JobGauge/BLMGauge.cs | 12 +- .../ClientState/Structs/JobGauge/BRDGauge.cs | 3 + .../ClientState/Structs/JobGauge/DNCGauge.cs | 12 +- .../ClientState/Structs/JobGauge/DRGGauge.cs | 3 + .../ClientState/Structs/JobGauge/DRKGauge.cs | 8 +- .../ClientState/Structs/JobGauge/GNBGauge.cs | 3 + .../ClientState/Structs/JobGauge/JobEnums.cs | 48 +++ .../ClientState/Structs/JobGauge/MCHGauge.cs | 12 +- .../ClientState/Structs/JobGauge/MNKGauge.cs | 4 + .../ClientState/Structs/JobGauge/NINGauge.cs | 4 + .../ClientState/Structs/JobGauge/PLDGauge.cs | 1 + .../ClientState/Structs/JobGauge/RDMGauge.cs | 2 + .../ClientState/Structs/JobGauge/SAMGauge.cs | 4 +- .../ClientState/Structs/JobGauge/SCHGauge.cs | 4 + .../ClientState/Structs/JobGauge/SMNGauge.cs | 19 +- .../ClientState/Structs/JobGauge/WARGauge.cs | 1 + .../ClientState/Structs/JobGauge/WHMGauge.cs | 3 + Dalamud/Game/Internal/Framework.cs | 2 +- Dalamud/Game/Internal/Gui/IconReplacer.cs | 366 ++++++++++++++---- 22 files changed, 480 insertions(+), 103 deletions(-) create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs index 965a8574d..1de3fe52d 100644 --- a/Dalamud/Configuration/CustomComboPreset.cs +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -6,6 +6,8 @@ using System.Threading.Tasks; namespace XIVLauncher.Dalamud { + + //CURRENT HIGHEST FLAG IS 45 [Flags] public enum CustomComboPreset { @@ -110,10 +112,22 @@ namespace XIVLauncher.Dalamud [CustomComboInfo("Dreadwyrm Combiner", "Now comes with Dreadwyrm Trance, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix.", 27)] SummonerDwtCombo = 1 << 28, + [CustomComboInfo("Brand of Purgatory Combo", "Replaces Fountain of Fire with Brand of Purgatory when under the affect of Hellish Conduit.", 27)] + SummonerBoPCombo = 1 << 38, + + [CustomComboInfo("ED Fester", "Change Energy Drain into Fester while you have Aetherflow stacks.", 27)] + SummonerEDFesterCombo = 1 << 39, + + [CustomComboInfo("ES Painflare", "Change Energy Siphon into Painflare while you have Aetherflow stacks.", 27)] + SummonerESPainflareCombo = 1 << 40, + // SCHOLAR [CustomComboInfo("Seraph Fey Blessing/Consolation", "Change Fey Blessing into Consolation when Seraph is out.", 28)] ScholarSeraphConsolationFeature = 1 << 29, + [CustomComboInfo("ED Aetherflow", "Change Energy Drain into Aetherflow when you have no more Aetherflow stacks.", 28)] + ScholarEnergyDrainFeature = 1 << 37, + // DANCER [CustomComboInfo("Standard Step Combo", "Standard Step on one button.", 38)] DancerStandardStepCombo = 1 << 30, @@ -128,7 +142,48 @@ namespace XIVLauncher.Dalamud DancerFanDanceCombo = 1 << 33, [CustomComboInfo("Fountain Combos", "Fountain changes into Fountain combo, prioritizing procs over combo, and Fountainfall over Reverse Cascade.", 38)] - DancerFountainCombo = 1 << 34 + DancerFountainCombo = 1 << 34, + + // WHITE MAGE + [CustomComboInfo("Solace into Misery", "Replaces Afflatus Solace with Afflatus Misery when Misery is ready to be used.", 24)] + WhiteMageSolaceMiseryFeature = 1 << 35, + + [CustomComboInfo("Rapture into Misery", "Replaces Afflatus Rapture with Afflatus Misery when Misery is ready to be used.", 24)] + WhiteMageRaptureMiseryFeature = 1 << 36, + + // BARD + [CustomComboInfo("Wanderer's into Pitch Perfect", "Replaces Wanderer's Minuet with Pitch Perfect while in WM.", 23)] + BardWandererPPFeature = 1 << 41, + + [CustomComboInfo("Heavy Shot into Straight Shot", "Replaces Heavy Shot/Burst Shot with Straight Shot/Refulgent Arrow when procced.", 23)] + BardStraightShotUpgradeFeature = 1 << 42, + + // MONK + [CustomComboInfo("Flank Positional Combo", "Replaces Snap Punch with flank positionals according to stance. When PB is active, prefer Snao (with non-max GL) > Twin (with no TS active) > Bootshine.", 20)] + MonkFlankCombo = 1 << 43, + + [CustomComboInfo("Rear Positional Combo", "Replaces Demolish with rear positionals according to stance. When PB is active, prefer Demo (with non-max GL) > Bootshine.", 20)] + MonkRearCombo = 1 << 44, + + [CustomComboInfo("Rockbreaker Combo", "Replaces Rockbreaker according to stance. When PB is active, prefer RB (with non-max GL) > Twin Snakes (with no TS active) > AotD.", 20)] + MonkAoECombo = 1 << 45, + + // RED MAGE + [CustomComboInfo("One-button White Magic", "Replaces Verstone with the following priority: Scorch > Verholy > Dual/Swiftcast Veraero > Verstone proc > Opener Veraero > Jolt.", 35)] + RedMageWhiteMagicFeature = 1 << 46, + + [CustomComboInfo("One-button Black Magic", "Replaces Verfire with the following priority: Scorch > Verflare > Dual/Swiftcast Verthunder > Verfire proc > Opener Verthunder > Jolt.", 35)] + RedMageBlackMagicFeature = 1 << 47, + + [CustomComboInfo("White Magic AoE", "Replaces Veraero 2 with Impact when Dualcast or Swiftcast are active.", 35)] + RedMageWhiteAoECombo = 1 << 48, + + [CustomComboInfo("White Magic AoE", "Replaces Verthunder 2 with Impact when Dualcast or Swiftcast are active.", 35)] + RedMageBlackAoECombo = 1 << 49, + + [CustomComboInfo("Redoublement combo", "Replaces Redoublement with its combo chain, following enchantment rules.", 35)] + RedMageMeleeCombo = 1 << 50 + } public class CustomComboInfoAttribute : Attribute diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index afa5ef597..01a54a7c8 100644 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs @@ -15,7 +15,7 @@ namespace Dalamud.Game.ClientState protected override void Setup64Bit(SigScanner sig) { ActorTable = sig.Module.BaseAddress + 0x1B29B40; LocalContentId = sig.Module.BaseAddress + 0x1B58B60; - JobGaugeData = sig.Module.BaseAddress + 0x1B2D4B4; + JobGaugeData = sig.Module.BaseAddress + 0x1B2D4C0; } } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs index ed10f470b..e6eca6548 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs @@ -9,5 +9,18 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct ASTGauge { + [FieldOffset(4)] private CardType Card; + [FieldOffset(5)] private unsafe fixed byte Seals[3]; + + public CardType DrawnCard() { + return Card; + } + + public unsafe bool ContainsSeal(SealType seal) { + if (Seals[0] == (byte)seal) return true; + if (Seals[1] == (byte)seal) return true; + if (Seals[2] == (byte)seal) return true; + return false; + } } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs index 89f2df857..a46a03553 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs @@ -9,12 +9,12 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct BLMGauge { - [FieldOffset(0xc)] public short TimeUntilNextPolyglot; //eno timer (ms) - [FieldOffset(0xe)] public short ElementTimeRemaining; //ui/af timer - [FieldOffset(0x10)] private byte ElementStance; //ui/af - [FieldOffset(0x11)] public byte NumUmbralHearts; //number of umbral hearts - [FieldOffset(0x12)] public byte NumPolyglotStacks; //number of polyglot stacks - [FieldOffset(0x13)] public bool IsEnoActive; //eno active? + [FieldOffset(0)] public short TimeUntilNextPolyglot; //eno timer (ms) + [FieldOffset(2)] public short ElementTimeRemaining; //ui/af timer + [FieldOffset(4)] private byte ElementStance; //ui/af + [FieldOffset(5)] public byte NumUmbralHearts; //number of umbral hearts + [FieldOffset(6)] public byte NumPolyglotStacks; //number of polyglot stacks + [FieldOffset(7)] public bool IsEnoActive; //eno active? public bool InUmbralIce() { return ElementStance > 4; diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs index 6bd8941d2..11eb1f5ad 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs @@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct BRDGauge { + [FieldOffset(0)] public short SongTimer; + [FieldOffset(2)] public byte NumSongStacks; + [FieldOffset(4)] public CurrentSong ActiveSong; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs index 0302015f2..b77e6f0e4 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs @@ -9,13 +9,17 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public unsafe struct DNCGauge { - [FieldOffset(0xc)] public byte NumFeathers; - [FieldOffset(0xd)] public byte Esprit; - [FieldOffset(0xe)] public fixed byte StepOrder[4]; - [FieldOffset(0x12)] public byte NumCompleteSteps; + [FieldOffset(0)] public byte NumFeathers; + [FieldOffset(1)] public byte Esprit; + [FieldOffset(2)] private fixed byte StepOrder[4]; + [FieldOffset(6)] public byte NumCompleteSteps; public bool IsDancing() { return StepOrder[0] != 0; } + + public ulong NextStep() { + return (ulong)(15999 + StepOrder[NumCompleteSteps] - 1); + } } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs index f06c09bea..fa71eb541 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs @@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct DRGGauge { + [FieldOffset(0)] public short BOTDTimer; + [FieldOffset(2)] public BOTDState BOTDState; + [FieldOffset(3)] public byte EyeCount; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs index bb4cdf455..0d160713a 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs @@ -8,9 +8,9 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct DRKGauge { - [FieldOffset(0xc)] public short Blood; - [FieldOffset(0xe)] public short DarksideTimeRemaining; - [FieldOffset(0x10)] public bool HasDarkArts; - [FieldOffset(0x12)] public short ShadowTimeRemaining; + [FieldOffset(0)] public short Blood; + [FieldOffset(2)] public short DarksideTimeRemaining; + [FieldOffset(4)] public bool HasDarkArts; + [FieldOffset(6)] public short ShadowTimeRemaining; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs index 08aba0ed1..969adda1d 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs @@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct GNBGauge { + [FieldOffset(0)] public byte NumAmmo; + [FieldOffset(2)] public short MaxTimerDuration; + [FieldOffset(4)] public byte AmmoComboStepNumber; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs new file mode 100644 index 000000000..a411b367e --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + public enum SealType : byte { + NONE = 0, SUN, MOON, CELESTIAL + } + public enum CardType : byte { + NONE = 0, BALANCE, BOLE, ARROW, SPEAR, EWER, SPIRE, + LORD = 0x70, LADY = 0x80 + } + + public enum SummonPet : byte { + IFRIT = 3, TITAN, GARUDA + } + + public enum PetGlam : byte { + NONE = 0, EMERALD, TOPAZ, RUBY + } + + [Flags] + public enum Sen : byte { + NONE = 0, + SETSU = 1 << 0, + GETSU = 1 << 1, + KA = 1 << 2, + } + + public enum BOTDState : byte { + NONE = 0, BOTD, LOTD + } + + public enum CurrentSong : byte { + MAGE = 5, ARMY = 0xA, WANDERER = 0xF + } + + public enum DismissedFairy : byte { + EOS = 6, SELENE + } + + public enum Mudras : byte { + TEN = 1, CHI = 2, JIN = 3 + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs index 73f43f3dd..e606cb751 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs @@ -10,12 +10,12 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct MCHGauge{ - [FieldOffset(0xc)] public short OverheatTimeRemaining; - [FieldOffset(0xe)] public short RobotTimeRemaining; - [FieldOffset(0x10)] public byte Heat; - [FieldOffset(0x11)] public byte Battery; - [FieldOffset(0x12)] public byte LastRobotBatteryPower; - [FieldOffset(0x13)] private byte TimerActive; + [FieldOffset(0)] public short OverheatTimeRemaining; + [FieldOffset(2)] public short RobotTimeRemaining; + [FieldOffset(4)] public byte Heat; + [FieldOffset(5)] public byte Battery; + [FieldOffset(6)] public byte LastRobotBatteryPower; + [FieldOffset(7)] private byte TimerActive; public bool IsOverheated() { return (TimerActive & 1) != 0; diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs index f7cf053d7..5741f3d7c 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs @@ -9,5 +9,9 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct MNKGauge { + [FieldOffset(0)] public byte GLTimer; + [FieldOffset(2)] public byte NumGLStacks; + [FieldOffset(3)] public byte NumChakra; + [FieldOffset(4)] public bool IsGLTimerFrozen; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs index 8c9c12a38..672e27b81 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs @@ -9,5 +9,9 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct NINGauge { + [FieldOffset(0)] public int HutonTimeLeft; + [FieldOffset(4)] public byte TCJMudrasUsed; //some sort of mask + [FieldOffset(5)] public byte Ninki; + [FieldOffset(6)] public byte NumHutonManualCasts; //wtf } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs index 33ae0e4e3..30b7f65e3 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs @@ -9,5 +9,6 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct PLDGauge { + [FieldOffset(0)] public byte GaugeAmount; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs index c2919a924..b0a2fa0c6 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs @@ -9,5 +9,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct RDMGauge { + [FieldOffset(0)] public byte WhiteGauge; + [FieldOffset(1)] public byte BlackGauge; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs index 2b0a6d532..6c10ba477 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs @@ -10,7 +10,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct SAMGauge { - [FieldOffset(0xf)] public byte Kenki; - [FieldOffset(0x10)] public byte Sen; + [FieldOffset(3)] public byte Kenki; + [FieldOffset(4)] public Sen Sen; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs index 3dc6d8ad1..5d742ee0e 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs @@ -9,5 +9,9 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct SCHGauge { + [FieldOffset(2)] public byte NumAetherflowStacks; + [FieldOffset(3)] public byte FairyGaugeAmount; + [FieldOffset(4)] public short SeraphTimer; + [FieldOffset(6)] public DismissedFairy DismissedFairy; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs index 0c76138f5..89f22fe9c 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs @@ -11,8 +11,21 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { public struct SMNGauge { //Unfinished - [FieldOffset(0xc)] public short TimerRemaining; - [FieldOffset(0xf)] public bool IsDemiActive; - [FieldOffset(0x10)] public byte NumStacks; + [FieldOffset(0)] public short TimerRemaining; + [FieldOffset(2)] public byte ReturnSummon; + [FieldOffset(3)] public byte ReturnSummonGlam; + [FieldOffset(4)] public byte NumStacks; + + public bool IsPhoenixReady() { + return (NumStacks & 0x10) > 0; + } + + public bool IsBahamutReady() { + return (NumStacks & 8) > 0; + } + + public bool HasAetherflowStacks() { + return (NumStacks & 3) > 0; + } } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs index c97db4e51..ed1ecf364 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs @@ -9,5 +9,6 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct WARGauge { + [FieldOffset(0)] public byte BeastGaugeAmount; } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs index 4ab7d1ffb..a5ad15906 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs @@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct WHMGauge { + [FieldOffset(2)] public short LilyTimer; //Counts to 30k = 30s + [FieldOffset(4)] public byte NumLilies; + [FieldOffset(5)] public byte NumBloodLily; } } diff --git a/Dalamud/Game/Internal/Framework.cs b/Dalamud/Game/Internal/Framework.cs index 72c41fd3f..b970ac49a 100644 --- a/Dalamud/Game/Internal/Framework.cs +++ b/Dalamud/Game/Internal/Framework.cs @@ -99,7 +99,7 @@ namespace Dalamud.Game.Internal { } catch (Exception ex) { Log.Error(ex, "Exception while dispatching Framework::Update event."); } - + return this.updateHook.Original(framework); } } diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 234426564..38ef4df91 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -32,7 +32,6 @@ namespace Dalamud.Game.Internal.Gui { this.Address.Setup(scanner); this.byteBase = scanner.Module.BaseAddress; - this.jobInfo = byteBase + 0x1b2d4b4; this.comboTimer = byteBase + 0x1AE1B10; this.lastComboMove = byteBase + 0x1AE1B14; @@ -71,14 +70,14 @@ namespace Dalamud.Game.Internal.Gui { /// private unsafe ulong GetIconDetour(byte self, uint actionID) { - // TODO: BRD, RDM, level checking for everything. + // TODO: More jobs, level checking for everything. // Check if player is loaded in by trying to get their buffs. // If not, skip everything until we are (game will crash cause I'm lazy). if (activeBuffArray == IntPtr.Zero) { try { activeBuffArray = FindBuffAddress(); - localCharacter = dalamud.ClientState.LocalPlayer; + Log.Verbose("ActiveBuffArray address: {ActiveBuffArray}", activeBuffArray); } catch (Exception e) { activeBuffArray = IntPtr.Zero; @@ -86,6 +85,18 @@ namespace Dalamud.Game.Internal.Gui { } } + // TODO: Update localCharacter without destroying the log with debug messages + // As it stands, don't rely on localCharacter.level for anything. + if (localCharacter == null) { + try { + localCharacter = dalamud.ClientState.LocalPlayer; + } + catch(Exception e) { + localCharacter = null; + return this.iconHook.Original(self, actionID); + } + } + // Don't clutter the spaghetti any worse than it already is. int lastMove = Marshal.ReadInt32(lastComboMove); float comboTime = (float)Marshal.ReadInt32(comboTimer); @@ -98,8 +109,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonCoerthanTormentCombo)) { if (actionID == 16477) { if (comboTime > 0) { - if (Marshal.ReadInt32(lastComboMove) == 86) return 7397; - if (Marshal.ReadInt32(lastComboMove) == 7397) return 16477; + if (lastMove == 86) return 7397; + if (lastMove == 7397) return 16477; } return 86; } @@ -112,13 +123,11 @@ namespace Dalamud.Game.Internal.Gui { if (comboTime > 0) { if (lastMove == 75 || lastMove == 16479) return 87; if (lastMove == 87) return 88; + } + if (SearchBuffArray(802)) return 3554; + if (SearchBuffArray(803)) return 3556; + if (SearchBuffArray(1863)) return 16479; - } - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(802)) return 3554; - if (SearchBuffArray(803)) return 3556; - if (SearchBuffArray(1863)) return 16479; - } return 75; } } @@ -130,14 +139,10 @@ namespace Dalamud.Game.Internal.Gui { if (comboTime > 0) { if (lastMove == 75 || lastMove == 16479) return 78; if (lastMove == 78) return 84; - - } - - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(802)) return 3554; - if (SearchBuffArray(803)) return 3556; - if (SearchBuffArray(1863)) return 16479; } + if (SearchBuffArray(802)) return 3554; + if (SearchBuffArray(803)) return 3556; + if (SearchBuffArray(1863)) return 16479; return 75; } @@ -245,9 +250,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Yukikaze with Yukikaze combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiYukikazeCombo)) { if (actionID == 7480) { - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(1233)) return 7480; - } + if (SearchBuffArray(1233)) return 7480; if (comboTime > 0) { if (lastMove == 7477) return 7480; } @@ -258,9 +261,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Gekko with Gekko combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiGekkoCombo)) { if (actionID == 7481) { - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(1233)) return 7481; - } + if (SearchBuffArray(1233)) return 7481; if (comboTime > 0) { if (lastMove == 7477) return 7478; if (lastMove == 7478) return 7481; @@ -272,9 +273,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Kasha with Kasha combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiKashaCombo)) { if (actionID == 7482) { - if (activeBuffArray != null) { - if (SearchBuffArray(1233)) return 7482; - } + if (SearchBuffArray(1233)) return 7482; if (comboTime > 0) { if (lastMove == 7477) return 7479; if (lastMove == 7479) return 7482; @@ -286,9 +285,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Mangetsu with Mangetsu combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiMangetsuCombo)) { if (actionID == 7484) { - if (activeBuffArray != null) { - if (SearchBuffArray(1233)) return 7484; - } + if (SearchBuffArray(1233)) return 7484; if (comboTime > 0) { if (lastMove == 7483) return 7484; } @@ -299,9 +296,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Oka with Oka combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiOkaCombo)) { if (actionID == 7485) { - if (activeBuffArray != null) { - if (SearchBuffArray(1233)) return 7485; - } + if (SearchBuffArray(1233)) return 7485; if (comboTime > 0) { if (lastMove == 7483) return 7485; } @@ -323,7 +318,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Armor Crush with Armor Crush combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) { - if (actionID == 2257) { + if (actionID == 3563) { if (comboTime > 0) { if (lastMove == 2240) return 2242; if (lastMove == 2242) return 3563; @@ -334,7 +329,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Aeolian Edge with Aeolian Edge combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAeolianEdgeCombo)) { - if (actionID == 2257) { + if (actionID == 2255) { if (comboTime > 0) { if (lastMove == 2240) return 2242; if (lastMove == 2242) return 2255; @@ -370,7 +365,7 @@ namespace Dalamud.Game.Internal.Gui { // TODO: Potentially add Contuation moves as well? if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerGnashingFangCombo)) { if (actionID == 16146) { - byte ammoComboState = Marshal.ReadByte(jobInfo, 0x10); + byte ammoComboState = this.dalamud.ClientState.JobGauges.Get().AmmoComboStepNumber; if (ammoComboState == 1) return 16147; if (ammoComboState == 2) return 16150; return 16146; @@ -414,6 +409,7 @@ namespace Dalamud.Game.Internal.Gui { // BLACK MAGE // Enochian changes to B4 or F4 depending on stance. + // TODO: For some reason this breaks only on my Crystal alt. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackEnochianFeature)) { if (actionID == 3575) { BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get(); @@ -435,26 +431,26 @@ namespace Dalamud.Game.Internal.Gui { // ASTROLOGIAN - // Make cards on the same button as draw + // Make cards on the same button as play if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.AstrologianCardsOnDrawFeature)) { if (actionID == 17055) { - byte x = Marshal.ReadByte(jobInfo, 0x10); - switch (x) { - case 1: + ASTGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + switch (gauge.DrawnCard()) { + case CardType.BALANCE: return 4401; - case 2: + case CardType.BOLE: return 4404; - case 3: + case CardType.ARROW: return 4402; - case 4: + case CardType.SPEAR: return 4403; - case 5: + case CardType.EWER: return 4405; - case 6: + case CardType.SPIRE: return 4406; - case 0x70: + case CardType.LORD: return 7444; - case 0x80: + case CardType.LADY: return 7445; default: return 3590; @@ -469,35 +465,77 @@ namespace Dalamud.Game.Internal.Gui { // What a monster of a button. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDwtCombo)) { if (actionID == 3581) { - byte stackState = Marshal.ReadByte(jobInfo, 0x10); - if (Marshal.ReadInt16(jobInfo, 0xc) > 0) { - if (Marshal.ReadInt16(jobInfo, 0xe) > 0) { - if (stackState > 0) return 16516; + SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.TimerRemaining > 0) { + if (gauge.ReturnSummon > 0) { + if (gauge.IsPhoenixReady()) return 16516; return 7429; } return 3582; } else { - if (stackState == 0) return 3581; - if (stackState == 8) return 7427; - if (stackState == 0x10) return 16513; + if (gauge.IsBahamutReady()) return 7427; + if (gauge.IsPhoenixReady()) return 16513; return 3581; } } } + // Ruin 1 now upgrades to Brand of Purgatory in addition to Ruin 3 and Fountain of Fire + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerBoPCombo)) { + if (actionID == 163) { + SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.TimerRemaining > 0) { + if (gauge.IsPhoenixReady()) { + if (SearchBuffArray(1867)) { + return 16515; + } + return 16514; + } + } + if (level >= 54) return 3579; + return 163; + } + } + + // Change Energy Drain into Fester + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerEDFesterCombo)) { + if (actionID == 16508) { + if (this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks()) + return 181; + return 16508; + } + } + + //Change Energy Siphon into Painflare + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerESPainflareCombo)) { + if (actionID == 16510) { + if (this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks()) + if(level >= 52) return 3578; + return 16510; + } + } + // SCHOLAR // Change Fey Blessing into Consolation when Seraph is out. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarSeraphConsolationFeature)) { if (actionID == 16543) { - if (Marshal.ReadInt16(jobInfo, 0x10) > 0) return 16546; + if (this.dalamud.ClientState.JobGauges.Get().SeraphTimer > 0) return 16546; return 16543; } } + // Change Energy Drain into Aetherflow when you have no more Aetherflow stacks. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarEnergyDrainFeature)) { + if (actionID == 167) { + if (this.dalamud.ClientState.JobGauges.Get().NumAetherflowStacks == 0) return 166; + return 167; + } + } + // DANCER - + // Standard Step is one button. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerStandardStepCombo)) { if (actionID == 15997) { @@ -508,7 +546,7 @@ namespace Dalamud.Game.Internal.Gui { } else { // C# can't implicitly cast from int to ulong. - return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + return gauge.NextStep(); } } return 15997; @@ -525,7 +563,7 @@ namespace Dalamud.Game.Internal.Gui { } else { // C# can't implicitly cast from int to ulong. - return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + return gauge.NextStep(); } } return 15998; @@ -536,10 +574,9 @@ namespace Dalamud.Game.Internal.Gui { // and Fountainfall over Reverse Cascade. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFountainCombo)) { if (actionID == 15990) { - if (activeBuffArray != null) { - if (SearchBuffArray(1815)) return 15992; - if (SearchBuffArray(1814)) return 15991; - } + if (this.dalamud.ClientState.JobGauges.Get().IsDancing()) return 15999; + if (SearchBuffArray(1815)) return 15992; + if (SearchBuffArray(1814)) return 15991; if (comboTime > 0) { if (lastMove == 15989) return 15990; } @@ -552,16 +589,12 @@ namespace Dalamud.Game.Internal.Gui { // Replaces each GCD with its procced version. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerAoeGcdFeature)) { if (actionID == 15994) { - if (activeBuffArray != null) { - if (SearchBuffArray(1817)) return 15996; - } + if (SearchBuffArray(1817)) return 15996; return 15994; } if (actionID == 15993) { - if (activeBuffArray != null) { - if (SearchBuffArray(1816)) return 15995; - } + if (SearchBuffArray(1816)) return 15995; return 15993; } } @@ -570,26 +603,209 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFanDanceCombo)) { // Fan Dance changes into Fan Dance 3 while flourishing. if (actionID == 16007) { - if (activeBuffArray != null) { - if (SearchBuffArray(1820)) return 16009; - } + if (SearchBuffArray(1820)) return 16009; return 16007; } // Fan Dance 2 changes into Fan Dance 3 while flourishing. if (actionID == 16008) { - if (activeBuffArray != null) { - if (SearchBuffArray(1820)) return 16009; - } + if (SearchBuffArray(1820)) return 16009; return 16008; } } + // WHM + + // Replace Solace with Misery when full blood lily + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WhiteMageSolaceMiseryFeature)) { + if (actionID == 16531) { + if (this.dalamud.ClientState.JobGauges.Get().NumBloodLily == 3) + return 16535; + return 16531; + } + } + + // Replace Solace with Misery when full blood lily + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WhiteMageRaptureMiseryFeature)) { + if (actionID == 16534) { + if (this.dalamud.ClientState.JobGauges.Get().NumBloodLily == 3) + return 16535; + return 16534; + } + } + + // BARD + + // Replace Wanderer's Minuet with PP when in WM. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BardWandererPPFeature)) { + if (actionID == 3559) { + if (this.dalamud.ClientState.JobGauges.Get().ActiveSong == CurrentSong.WANDERER) { + return 7404; + } + return 3559; + } + } + + // Replace HS/BS with SS/RA when procced. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BardStraightShotUpgradeFeature)) { + if (actionID == 97) { + if (SearchBuffArray(122)) { + if (level >= 70) return 7409; + return 98; + } + if (level > 76) return 16495; + return 97; + } + } + + // MONK + + // Replace Snap Punch with flank positional combo. + // During PB, Snap (with sub-max stacks) > Twin (with no active Twin) > DK + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkFlankCombo)) { + if (actionID == 56) { + if (SearchBuffArray(110)) { + MNKGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if ((gauge.NumGLStacks < 3 && level < 76) || SearchBuffArray(103)) { + return 56; + } + else if (gauge.NumGLStacks < 4 && level >= 76 && SearchBuffArray(105)) { + return 56; + } + else if (!SearchBuffArray(101)) return 61; + else return 74; + } + else { + if (SearchBuffArray(107)) return 74; + if (SearchBuffArray(108)) return 61; + if (SearchBuffArray(109)) return 56; + return 74; + } + } + } + + // Replace Demolish with rear positional combo. + // During PB, Demo (with sub-max stacks) > Bootshine. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkRearCombo)) { + if (actionID == 66) { + if (SearchBuffArray(110)) { + MNKGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if ((gauge.NumGLStacks < 3 && level < 76) || SearchBuffArray(103)) { + return 66; + } + else if (gauge.NumGLStacks < 4 && level >= 76 && SearchBuffArray(105)) { + return 66; + } + else return 53; + } + else { + if (SearchBuffArray(107)) return 53; + if (SearchBuffArray(108)) return 54; + if (SearchBuffArray(109)) return 66; + return 53; + } + } + } + + // Replace Rockbreaker with AoE combo. + // During PB, RB (with sub-max stacks) > Twin Snakes (if not applied) > AotD. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkAoECombo)) { + if (actionID == 70) { + if (SearchBuffArray(110)) { + MNKGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if ((gauge.NumGLStacks < 3 && level < 76) || SearchBuffArray(103)) { + return 70; + } + else if (gauge.NumGLStacks < 4 && level >= 76 && SearchBuffArray(105)) { + return 70; + } + else if (!SearchBuffArray(101)) return 61; + else return 62; + } + else { + if (SearchBuffArray(107)) return 62; + if (SearchBuffArray(108)) { + if (!SearchBuffArray(101)) return 61; + return 16473; + } + if (SearchBuffArray(109)) return 70; + return 62; + } + } + } + + // RED MAGE + + // Replace Verstone with White Magic spells. Priority order: + // Scorch > Verholy > Verstone = Veraero (with Dualcast active) > opener Veraero > Jolt + // Impact is not the first available spell to allow for precast openers. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageWhiteMagicFeature)) { + if (actionID == 7511) { + if ((lastMove == 7526 || lastMove == 7525) && level == 80) return 16530; + if (lastMove == 7529) return 7526; + if (SearchBuffArray(1249) || SearchBuffArray(167)) return 7507; + if (SearchBuffArray(1235)) return 7511; + RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) return 7507; + if (level >= 62) return 7524; + return 7503; + } + } + + // Replace Verfire with Black Magic spells. Priority order: + // Scorch > Verflare> Verfire = Verthunder (with Dualcast active) > opener Verthunder > Jolt + // Impact is not the first available spell to allow for precast openers. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageBlackMagicFeature)) { + if (actionID == 7510) { + if ((lastMove == 7526 || lastMove == 7525) && level == 80) return 16530; + if (lastMove == 7529) return 7525; + if (SearchBuffArray(1249) || SearchBuffArray(167)) return 7505; + if (SearchBuffArray(1234)) return 7510; + RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) return 7505; + if (level >= 62) return 7524; + return 7503; + } + } + + // Replace Veraero 2 with Impact when Dualcast is active + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageWhiteAoECombo)) { + if (actionID == 16525) { + if (level >= 66 && (SearchBuffArray(1249) || SearchBuffArray(167))) return 16526; + return 16525; + } + } + + // Replace Verthunder 2 with Impact when Dualcast is active + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageBlackAoECombo)) { + if (actionID == 16524) { + if (level >= 66 && (SearchBuffArray(1249) || SearchBuffArray(167))) return 16526; + return 16524; + } + } + + // Replace Redoublement with Redoublement combo, Enchanted if possible. + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageMeleeCombo)) { + if (actionID == 7516) { + RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (lastMove == 7504 || lastMove == 7527) { + if (gauge.BlackGauge >= 25 && gauge.WhiteGauge >= 25) return 7528; + return 7512; + } + if (lastMove == 7512) { + if (gauge.BlackGauge >= 25 && gauge.WhiteGauge >= 25) return 7529; + return 7516; + } + if (gauge.BlackGauge >= 30 && gauge.WhiteGauge >= 30) return 7527; + return 7516; + } + } + return this.iconHook.Original(self, actionID); } - private unsafe bool SearchBuffArray(short needle) { + private bool SearchBuffArray(short needle) { for (int i = 0; i < 60; i++) { if (Marshal.ReadInt16(activeBuffArray + 4 * i) == needle) return true; }