From 84c66ddc6ec14571f4f6e62143c21fc9f6ea6acd Mon Sep 17 00:00:00 2001 From: attick Date: Tue, 15 Oct 2019 11:21:59 -0400 Subject: [PATCH 01/19] Initial icon replacement commit --- Dalamud/Dalamud.cs | 17 + .../Game/Internal/Gui/IconReplaceChecker.cs | 38 ++ .../Gui/IconReplaceCheckerAddressResolver.cs | 17 + Dalamud/Game/Internal/Gui/IconReplacer.cs | 461 ++++++++++++++++++ .../Gui/IconReplacerAddressResolver.cs | 16 + 5 files changed, 549 insertions(+) create mode 100644 Dalamud/Game/Internal/Gui/IconReplaceChecker.cs create mode 100644 Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs create mode 100644 Dalamud/Game/Internal/Gui/IconReplacer.cs create mode 100644 Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index ac2c028f1..0797ccb62 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -11,6 +11,7 @@ using Dalamud.Game.ClientState.Actors.Types; using Dalamud.Game.ClientState.Actors.Types.NonPlayer; using Dalamud.Game.Command; using Dalamud.Game.Internal; +using Dalamud.Game.Internal.Gui; using Dalamud.Game.Network; using Dalamud.Plugin; using Dalamud.Settings; @@ -39,6 +40,10 @@ namespace Dalamud { public readonly DalamudStartInfo StartInfo; + public readonly IconReplacer IconReplacer; + + public readonly IconReplaceChecker IconReplaceChecker; + public Dalamud(DalamudStartInfo info) { this.StartInfo = info; @@ -66,6 +71,10 @@ namespace Dalamud { this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory); + this.IconReplaceChecker = new IconReplaceChecker(this.targetModule, this.sigScanner); + + this.IconReplacer = new IconReplacer(this, this.targetModule, this.sigScanner); + try { this.PluginManager.LoadPlugins(); } catch (Exception ex) { @@ -79,6 +88,10 @@ namespace Dalamud { Framework.Enable(); this.BotManager.Start(); + + this.IconReplaceChecker.Enable(); + + this.IconReplacer.Enable(); } public void Unload() { @@ -95,6 +108,10 @@ namespace Dalamud { this.BotManager.Dispose(); this.unloadSignal.Dispose(); + + this.IconReplaceChecker.Dispose(); + + this.IconReplacer.Dispose(); } private void SetupCommands() { diff --git a/Dalamud/Game/Internal/Gui/IconReplaceChecker.cs b/Dalamud/Game/Internal/Gui/IconReplaceChecker.cs new file mode 100644 index 000000000..48eb7f553 --- /dev/null +++ b/Dalamud/Game/Internal/Gui/IconReplaceChecker.cs @@ -0,0 +1,38 @@ +using System; +using System.Diagnostics; +using Dalamud.Hooking; + +namespace Dalamud.Game.Internal.Gui { + public class IconReplaceChecker { + private IconReplaceCheckerAddressResolver address; + private Hook checkerHook; + + public IconReplaceChecker(ProcessModule module, SigScanner scanner) { + this.address = new IconReplaceCheckerAddressResolver(); + this.address.Setup(scanner); + hookChecker(); + } + + private void hookChecker() { + this.checkerHook = new Hook(this.address.BaseAddress, (Delegate)new OnCheckDetour(this.HandleChecker), (object)this); + } + + public void Enable() { + this.checkerHook.Enable(); + } + + public void Dispose() { + this.checkerHook.Dispose(); + } + + // I hate this function. This is the dumbest function to exist in the game. Just return 1. + // Determines which abilities are allowed to have their icons updated. + private ulong HandleChecker(int actionID) { + return 1; + } + + private delegate ulong OnCheckDetour(int actionID); + + public delegate ulong OnCheckDelegate(int actionID); + } +} diff --git a/Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs b/Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs new file mode 100644 index 000000000..28ce04bc3 --- /dev/null +++ b/Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.Internal.Gui { + class IconReplaceCheckerAddressResolver : BaseAddressResolver { + public IntPtr BaseAddress { get; private set; } + protected bool IsResolved { get; set; } + + protected override void Setup64Bit(SigScanner sig) + { + this.BaseAddress = sig.ScanText("81 f9 d4 08 00 00 7f 33 0f 84 fa 01 00 00 83 c1 eb 81 f9 a3 00 00 00"); + } + } +} diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs new file mode 100644 index 000000000..bd40830b1 --- /dev/null +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -0,0 +1,461 @@ +using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Hooking; +using Serilog; +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Dalamud.Game.Internal.Gui { + public class IconReplacer { + private IconReplacerAddressResolver address; + private Hook iconHook; + private IntPtr comboTimer; + private IntPtr lastComboMove; + private IntPtr activeBuffArray = IntPtr.Zero; + private IntPtr jobInfo; + private IntPtr byteBase; + private Dalamud dalamud; + private PlayerCharacter localCharacter = null; + + public unsafe IconReplacer(Dalamud dalamud, ProcessModule module, SigScanner scanner) { + this.dalamud = dalamud; + this.address = new IconReplacerAddressResolver(); + this.address.Setup(scanner); + + this.byteBase = scanner.Module.BaseAddress; + this.jobInfo = byteBase + 0x1b2d4b4; + this.comboTimer = byteBase + 0x1AE1B10; + this.lastComboMove = byteBase + 0x1AE1B14; + + this.iconHook = new Hook(this.address.BaseAddress, (Delegate)new OnIconDetour(this.HandleIconUpdate), (object)this); + + } + + public void Enable() { + this.iconHook.Enable(); + } + + public void Dispose() { + this.iconHook.Dispose(); + } + + + /// + /// Replace an ability with another ability + /// actionID is the original ability to be "used" + /// Return either actionID (itself) or a new Action table ID as the + /// ability to take its place. + /// I tend to make the "combo chain" button be the last move in the combo + /// For example, Souleater combo on DRK happens by dragging Souleater + /// onto your bar and mashing it. + /// + private unsafe ulong HandleIconUpdate(byte self, uint actionID) { + + // TODO: BRD, RDM, 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; + } + catch (Exception e) { + activeBuffArray = IntPtr.Zero; + 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); + byte level = localCharacter.Level; + + // DRAGOON + // TODO: Jump/High Jump into Mirage Dive + + // Replace Coerthan Torment with Coerthan Torment combo chain + if (actionID == 16477) { + if (comboTime > 0) { + if (Marshal.ReadInt32(lastComboMove) == 86) return 7397; + if (Marshal.ReadInt32(lastComboMove) == 7397) return 16477; + } + return 86; + } + + // Replace Chaos Thrust with the Chaos Thrust combo chain + if (actionID == 88) { + if (comboTime > 0) { + if (lastMove == 75 || lastMove == 16479) return 87; + if (lastMove == 87) return 88; + + } + if (activeBuffArray != IntPtr.Zero) { + if (SearchBuffArray(802)) return 3554; + if (SearchBuffArray(803)) return 3556; + if (SearchBuffArray(1863)) return 16479; + } + return 75; + } + + // Replace Full Thrust with the Full Thrust combo chain + if (actionID == 84) { + 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; + } + return 75; + } + + // DARK KNIGHT + + // Replace Souleater with Souleater combo chain + if (actionID == 3632) { + if (comboTime > 0) { + if (lastMove == 3617) return 3623; + if (lastMove == 3623) return 3632; + } + return 3617; + } + + // Replace Stalwart Soul with Stalwart Soul combo chain + if (actionID == 16468) { + if (comboTime > 0) { + if (lastMove == 3621) return 16468; + } + return 3621; + } + + // PALADIN + + // Replace Goring Blade with Goring Blade combo + if (actionID == 3538) { + if (comboTime > 0) { + if (lastMove == 9) return 15; + if (lastMove == 15) return 3538; + } + return 9; + } + + // Replace Royal Authority with Royal Authority combo + if (actionID == 3539) { + if (comboTime > 0) { + if (lastMove == 9) return 15; + if (lastMove == 15) return 3539; + } + return 9; + } + + // Replace Prominence with Prominence combo + if (actionID == 16457) { + if (comboTime > 0) { + if (lastMove == 7381) return 16457; + } + return 7381; + } + + // WARRIOR + + // Replace Storm's Path with Storm's Path combo + if (actionID == 42) { + if (comboTime > 0) { + if (lastMove == 31) return 37; + if (lastMove == 37) return 42; + } + return 31; + } + + // Replace Storm's Eye with Storm's Eye combo + if (actionID == 45) { + if (comboTime > 0) { + if (lastMove == 31) return 37; + if (lastMove == 37) return 45; + } + return 31; + } + + // Replace Mythril Tempest with Mythril Tempest combo + if (actionID == 16462) { + if (comboTime > 0) { + if (lastMove == 41) return 16462; + } + return 41; + } + + // SAMURAI + + // Replace Yukikaze with Yukikaze combo + if (actionID == 7480) { + if (activeBuffArray != IntPtr.Zero) { + if (SearchBuffArray(1233)) return 7480; + } + if (comboTime > 0) { + if (lastMove == 7477) return 7480; + } + return 7477; + } + + // Replace Gekko with Gekko combo + if (actionID == 7481) { + if (activeBuffArray != IntPtr.Zero) { + if (SearchBuffArray(1233)) return 7481; + } + if (comboTime > 0) { + if (lastMove == 7477) return 7478; + if (lastMove == 7478) return 7481; + } + return 7477; + } + + // Replace Kasha with Kasha combo + if (actionID == 7482) { + if (activeBuffArray != null) { + if (SearchBuffArray(1233)) return 7482; + } + if (comboTime > 0) { + if (lastMove == 7477) return 7479; + if (lastMove == 7479) return 7482; + } + return 7477; + } + + // Replace Mangetsu with Mangetsu combo + if (actionID == 7484) { + if (comboTime > 0) { + if (lastMove == 7483) return 7484; + } + return 7483; + } + + // Replace Yukikaze with Yukikaze combo + if (actionID == 7485) { + if (comboTime > 0) { + if (lastMove == 7483) return 7485; + } + return 7483; + } + + // NINJA + + // Replace Shadow Fang with Shadow Fang combo + if (actionID == 2257) { + if (comboTime > 0) { + if (lastMove == 2240) return 2257; + } + return 2240; + } + + // Replace Armor Crush with Armor Crush combo + if (actionID == 2257) { + if (comboTime > 0) { + if (lastMove == 2240) return 2242; + if (lastMove == 2242) return 3563; + } + return 2240; + } + + // Replace Aeolian Edge with Aeolian Edge combo + if (actionID == 2257) { + if (comboTime > 0) { + if (lastMove == 2240) return 2242; + if (lastMove == 2242) return 2255; + } + return 2240; + } + + // Replace Hakke Mujinsatsu with Hakke Mujinsatsu combo + if (actionID == 16488) { + if (comboTime > 0) { + if (lastMove == 2254) return 16488; + } + return 2254; + } + + // GUNBREAKER + + // Replace Solid Barrel with Solid Barrel combo + if (actionID == 16145) { + if (comboTime > 0) { + if (lastMove == 16137) return 16139; + if (lastMove == 16139) return 16145; + } + return 16137; + } + + // Replace Gnashing Fang with Gnashing Fang combo + // TODO: Potentially add Contuation moves as well? + if (actionID == 16146) { + byte ammoComboState = Marshal.ReadByte(jobInfo, 0x10); + if (ammoComboState == 1) return 16147; + if (ammoComboState == 2) return 16150; + return 16146; + } + + // Replace Demon Slaughter with Demon Slaughter combo + if (actionID == 16149) { + if (comboTime > 0) { + if (lastMove == 16141) return 16149; + } + return 16141; + } + + // MACHINIST + + // Replace Heated Clean Shot with Heated Clean Shot combo + // Or with Heat Blast when overheated. + // For some reason the shots use their unheated IDs as combo moves + if (actionID == 7413) { + if (Marshal.ReadInt16(jobInfo, 0xc) > 0) return 7410; + if (comboTime > 0) { + if (lastMove == 2866) return 7412; + if (lastMove == 2868) return 7413; + } + return 7411; + } + + // Replace Spread Shot with Auto Crossbow when overheated. + if (actionID == 2870) { + if (Marshal.ReadInt16(jobInfo, 0xc) > 0) return 16497; + return 2870; + } + + // BLACK MAGE + + // Enochian changes to B4 or F4 depending on stance. + if (actionID == 3575) { + if (Marshal.ReadByte(jobInfo, 0x13) == 1) { + if (Marshal.ReadByte(jobInfo, 0x10) > 3) return 3576; + if (Marshal.ReadByte(jobInfo, 0x10) > 0) return 3577; + } + return 3575; + } + + // Umbral Soul and Transpose + if (actionID == 16506) { + if (Marshal.ReadByte(jobInfo, 0x10) > 3) return 16506; + return 149; + } + + // ASTROLOGIAN + + // Make cards on the same button as draw + if (actionID == 17055) { + byte x = Marshal.ReadByte(jobInfo, 0x10); + switch (x) { + case 1: + return 4401; + case 2: + return 4404; + case 3: + return 4402; + case 4: + return 4403; + case 5: + return 4405; + case 6: + return 4406; + case 0x70: + return 7444; + case 0x80: + return 7445; + default: + return 3590; + } + } + + // SUMMONER + + // DWT changes. + // Now contains DWT, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix. + // What a monster of a button. + 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; + return 7429; + } + return 3582; + } + else { + if (stackState == 0) return 3581; + if (stackState == 8) return 7427; + if (stackState == 0x10) return 16513; + return 3581; + } + } + + // SCHOLAR + + // Change Fey Blessing into Consolation when Seraph is out. + if (actionID == 16543) { + if (Marshal.ReadInt16(jobInfo, 0x10) > 0) return 16546; + return 16543; + } + + // DANCER + // TODO: Single-target. This needs to be done alongside 1-button dances. + + // Handle AoE GCDs on one button. Procs take priority over combo. + + if (actionID == 15994) { + if (activeBuffArray != null) { + if (SearchBuffArray(1816)) return 15995; + if (SearchBuffArray(1817)) return 15996; + } + if (comboTime > 0) { + if (lastMove == 15993) return 15994; + } + return 15993; + } + + // Fan Dance changes into Fan Dance 3 while flourishing. + if (actionID == 16007) { + if (activeBuffArray != null) { + 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; + } + return 16008; + } + + + return this.iconHook.Original(self, actionID); + } + + private unsafe bool SearchBuffArray(short needle) { + for (int i = 0; i < 60; i++) { + if (Marshal.ReadInt16(activeBuffArray + 4 * i) == needle) return true; + } + return false; + } + + private delegate ulong OnIconDetour(byte param1, uint param2); + + public delegate ulong OnIconDelegate(byte param1, uint param2); + + private unsafe delegate int* getArray(long* address); + + private unsafe IntPtr FindBuffAddress() { + IntPtr randomAddress = byteBase + 0x1b2c970; + IntPtr num = Marshal.ReadIntPtr(randomAddress); + IntPtr step2 = (IntPtr)(Marshal.ReadInt64(num) + 0x248); + IntPtr step3 = Marshal.ReadIntPtr(step2); + var callback = Marshal.GetDelegateForFunctionPointer(step3); + return (IntPtr)callback((long*)num); + } + } +} diff --git a/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs b/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs new file mode 100644 index 000000000..e8c37533d --- /dev/null +++ b/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.Internal.Gui { + class IconReplacerAddressResolver : BaseAddressResolver { + public IntPtr BaseAddress { get; private set; } + protected bool IsResolved { get; set; } + + protected override void Setup64Bit(SigScanner sig) { + this.BaseAddress = sig.ScanText("81 fa d4 08 00 00 7f 4b 74 44 8d 42 eb 3d a3 00 00 00"); + } + } +} From 8d02c977d211ce09db1a8c552dcae32ef3e922c1 Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 17 Oct 2019 22:27:56 -0400 Subject: [PATCH 02/19] Update to C# 7.3. Some job gauge abstraction added. Mid-work push. --- Dalamud/Dalamud.csproj | 2 +- Dalamud/Game/ClientState/JobGauge.cs | 25 ++++++ .../ClientState/Structs/JobGauge/ASTGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/BLMGauge.cs | 30 +++++++ .../ClientState/Structs/JobGauge/BRDGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/DNCGauge.cs | 21 +++++ .../ClientState/Structs/JobGauge/DRGGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/DRKGauge.cs | 16 ++++ .../ClientState/Structs/JobGauge/GNBGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/MCHGauge.cs | 27 ++++++ .../ClientState/Structs/JobGauge/MNKGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/NINGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/PLDGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/RDMGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/SAMGauge.cs | 16 ++++ .../ClientState/Structs/JobGauge/SCHGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/SMNGauge.cs | 18 ++++ .../ClientState/Structs/JobGauge/WARGauge.cs | 13 +++ .../ClientState/Structs/JobGauge/WHMGauge.cs | 13 +++ Dalamud/Game/Internal/Gui/IconReplacer.cs | 83 ++++++++++++++++--- 20 files changed, 367 insertions(+), 14 deletions(-) create mode 100644 Dalamud/Game/ClientState/JobGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs create mode 100644 Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 966984ad6..99f9eca5e 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -2,7 +2,7 @@ AnyCPU net471 - 7.2 + 7.3 AnyCPU;x64 diff --git a/Dalamud/Game/ClientState/JobGauge.cs b/Dalamud/Game/ClientState/JobGauge.cs new file mode 100644 index 000000000..e91b342fe --- /dev/null +++ b/Dalamud/Game/ClientState/JobGauge.cs @@ -0,0 +1,25 @@ +using Dalamud.Game.ClientState.Structs.JobGauge; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState { + public static class JobGauge { + + private static IntPtr gaugeStart; + + public static void Init(ProcessModule module) { + gaugeStart = module.BaseAddress + 0x1b2d4b4; + } + + // Should only be called with the gauge types in + // ClientState.Structs.JobGauge + public static T Gauge() { + return Marshal.PtrToStructure(gaugeStart); + } + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs new file mode 100644 index 000000000..3372da7d2 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class ASTGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs new file mode 100644 index 000000000..89f2df857 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +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? + + public bool InUmbralIce() { + return ElementStance > 4; + } + + public bool InAstralFire() { + return ElementStance > 0 && ElementStance < 4; + } + + } + + +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs new file mode 100644 index 000000000..b5d408a70 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class BRDGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs new file mode 100644 index 000000000..0302015f2 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +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; + + public bool IsDancing() { + return StepOrder[0] != 0; + } + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs new file mode 100644 index 000000000..1e6293be7 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class DRGGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs new file mode 100644 index 000000000..bb4cdf455 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +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; + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs new file mode 100644 index 000000000..772ffb18a --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class GNBGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs new file mode 100644 index 000000000..73f43f3dd --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +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; + + public bool IsOverheated() { + return (TimerActive & 1) != 0; + } + public bool IsRobotActive() { + return (TimerActive & 2) != 0; + } + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs new file mode 100644 index 000000000..0ba90975e --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class MNKGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs new file mode 100644 index 000000000..a70d77d18 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class NINGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs new file mode 100644 index 000000000..7042ffc08 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class PLDGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs new file mode 100644 index 000000000..c2919a924 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + public struct RDMGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs new file mode 100644 index 000000000..2b0a6d532 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + public struct SAMGauge { + + [FieldOffset(0xf)] public byte Kenki; + [FieldOffset(0x10)] public byte Sen; + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs new file mode 100644 index 000000000..ed241b46a --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class SCHGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs new file mode 100644 index 000000000..0c76138f5 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + public struct SMNGauge { + + //Unfinished + [FieldOffset(0xc)] public short TimerRemaining; + [FieldOffset(0xf)] public bool IsDemiActive; + [FieldOffset(0x10)] public byte NumStacks; + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs new file mode 100644 index 000000000..78387efb5 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class WARGauge { + } +} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs new file mode 100644 index 000000000..4ae079e00 --- /dev/null +++ b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.ClientState.Structs.JobGauge { + + [StructLayout(LayoutKind.Explicit)] + class WHMGauge { + } +} diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index bd40830b1..869ac04f6 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -1,4 +1,6 @@ +using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Structs.JobGauge; using Dalamud.Hooking; using Serilog; using System; @@ -22,6 +24,8 @@ namespace Dalamud.Game.Internal.Gui { this.address = new IconReplacerAddressResolver(); this.address.Setup(scanner); + JobGauge.Init(module); + this.byteBase = scanner.Module.BaseAddress; this.jobInfo = byteBase + 0x1b2d4b4; this.comboTimer = byteBase + 0x1AE1B10; @@ -227,6 +231,9 @@ namespace Dalamud.Game.Internal.Gui { // Replace Mangetsu with Mangetsu combo if (actionID == 7484) { + if (activeBuffArray != null) { + if (SearchBuffArray(1233)) return 7484; + } if (comboTime > 0) { if (lastMove == 7483) return 7484; } @@ -235,6 +242,9 @@ namespace Dalamud.Game.Internal.Gui { // Replace Yukikaze with Yukikaze combo if (actionID == 7485) { + if (activeBuffArray != null) { + if (SearchBuffArray(1233)) return 7485; + } if (comboTime > 0) { if (lastMove == 7483) return 7485; } @@ -311,7 +321,7 @@ namespace Dalamud.Game.Internal.Gui { // Or with Heat Blast when overheated. // For some reason the shots use their unheated IDs as combo moves if (actionID == 7413) { - if (Marshal.ReadInt16(jobInfo, 0xc) > 0) return 7410; + if (JobGauge.Gauge().IsOverheated() && level >= 35) return 7410; if (comboTime > 0) { if (lastMove == 2866) return 7412; if (lastMove == 2868) return 7413; @@ -321,7 +331,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Spread Shot with Auto Crossbow when overheated. if (actionID == 2870) { - if (Marshal.ReadInt16(jobInfo, 0xc) > 0) return 16497; + if (JobGauge.Gauge().IsOverheated() && level >= 52) return 16497; return 2870; } @@ -329,16 +339,17 @@ namespace Dalamud.Game.Internal.Gui { // Enochian changes to B4 or F4 depending on stance. if (actionID == 3575) { - if (Marshal.ReadByte(jobInfo, 0x13) == 1) { - if (Marshal.ReadByte(jobInfo, 0x10) > 3) return 3576; - if (Marshal.ReadByte(jobInfo, 0x10) > 0) return 3577; + BLMGauge jobInfo = JobGauge.Gauge(); + if (jobInfo.IsEnoActive) { + if (jobInfo.InUmbralIce()) return 3576; + return 3577; } return 3575; } // Umbral Soul and Transpose - if (actionID == 16506) { - if (Marshal.ReadByte(jobInfo, 0x10) > 3) return 16506; + if (actionID == 149) { + if (JobGauge.Gauge().InUmbralIce() && level >= 76) return 16506; return 149; } @@ -400,17 +411,63 @@ namespace Dalamud.Game.Internal.Gui { } // DANCER - // TODO: Single-target. This needs to be done alongside 1-button dances. + + // Standard Step is one button. + if (actionID == 15997) { + DNCGauge gauge = JobGauge.Gauge(); + if (gauge.IsDancing()) { + if (gauge.NumCompleteSteps == 2) { + return 16192; + } + else { + // C# can't implicitly cast from int to ulong. + return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + } + } + return 15997; + } - // Handle AoE GCDs on one button. Procs take priority over combo. + // Technical Step is one button. + if (actionID == 15998) { + DNCGauge gauge = JobGauge.Gauge(); + if (gauge.IsDancing()) { + if (gauge.NumCompleteSteps == 4) { + return 16196; + } + else { + // C# can't implicitly cast from int to ulong. + return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + } + } + return 15998; + } - if (actionID == 15994) { + // Fountain changes into Fountain combo, prioritizing procs over combo, + // and Fountainfall over Reverse Cascade. + if (actionID == 15990) { if (activeBuffArray != null) { - if (SearchBuffArray(1816)) return 15995; - if (SearchBuffArray(1817)) return 15996; + if (SearchBuffArray(1815)) return 15992; + if (SearchBuffArray(1814)) return 15991; } if (comboTime > 0) { - if (lastMove == 15993) return 15994; + if (lastMove == 15989) return 15990; + } + return 15989; + } + + // AoE GCDs are split into two buttons, because priority matters + // differently in different single-target moments. Thanks yoship. + // Replaces each GCD with its procced version. + if (actionID == 15994) { + if (activeBuffArray != null) { + if (SearchBuffArray(1817)) return 15996; + } + return 15994; + } + + if (actionID == 15993) { + if (activeBuffArray != null) { + if (SearchBuffArray(1816)) return 15995; } return 15993; } From 78a7795a8424652a9cb11192464c8b65b307e519 Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 17 Oct 2019 22:35:42 -0400 Subject: [PATCH 03/19] All the structs are actually structs now. --- Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs | 2 +- Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs index 3372da7d2..ed10f470b 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class ASTGauge { + public struct ASTGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs index b5d408a70..6bd8941d2 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class BRDGauge { + public struct BRDGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs index 1e6293be7..f06c09bea 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class DRGGauge { + public struct DRGGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs index 772ffb18a..08aba0ed1 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class GNBGauge { + public struct GNBGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs index 0ba90975e..f7cf053d7 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class MNKGauge { + public struct MNKGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs index a70d77d18..8c9c12a38 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class NINGauge { + public struct NINGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs index 7042ffc08..33ae0e4e3 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class PLDGauge { + public struct PLDGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs index ed241b46a..3dc6d8ad1 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class SCHGauge { + public struct SCHGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs index 78387efb5..c97db4e51 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class WARGauge { + public struct WARGauge { } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs index 4ae079e00..4ab7d1ffb 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs @@ -8,6 +8,6 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] - class WHMGauge { + public struct WHMGauge { } } From a3fe81d31018402044c74c81263a972e970ba101 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 18 Oct 2019 21:26:11 +0900 Subject: [PATCH 04/19] Move job gauge access to ClientState and ClientStateAddressResolver --- Dalamud/Game/ClientState/ClientState.cs | 7 +++++++ .../Game/ClientState/ClientStateAddressResolver.cs | 2 ++ Dalamud/Game/ClientState/JobGauge.cs | 13 ++++++------- Dalamud/Game/Internal/Gui/IconReplacer.cs | 14 ++++++-------- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index 4af069e36..e12d542b1 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -38,6 +38,11 @@ namespace Dalamud.Game.ClientState /// public ulong LocalContentId => (ulong) Marshal.ReadInt64(Address.LocalContentId); + /// + /// The class facilitating Job Gauge data access + /// + public JobGauges JobGauges; + /// /// Set up client state access. /// @@ -52,6 +57,8 @@ namespace Dalamud.Game.ClientState this.ClientLanguage = startInfo.Language; this.Actors = new ActorTable(Address); + + this.JobGauges = new JobGauges(Address); } } } diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index 37d1fde18..afa5ef597 100644 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs @@ -10,10 +10,12 @@ namespace Dalamud.Game.ClientState public sealed class ClientStateAddressResolver : BaseAddressResolver { public IntPtr ActorTable { get; private set; } public IntPtr LocalContentId { get; private set; } + public IntPtr JobGaugeData { get; set; } protected override void Setup64Bit(SigScanner sig) { ActorTable = sig.Module.BaseAddress + 0x1B29B40; LocalContentId = sig.Module.BaseAddress + 0x1B58B60; + JobGaugeData = sig.Module.BaseAddress + 0x1B2D4B4; } } } diff --git a/Dalamud/Game/ClientState/JobGauge.cs b/Dalamud/Game/ClientState/JobGauge.cs index e91b342fe..3e458fffc 100644 --- a/Dalamud/Game/ClientState/JobGauge.cs +++ b/Dalamud/Game/ClientState/JobGauge.cs @@ -8,18 +8,17 @@ using System.Text; using System.Threading.Tasks; namespace Dalamud.Game.ClientState { - public static class JobGauge { + public class JobGauges { + private ClientStateAddressResolver Address { get; } - private static IntPtr gaugeStart; - - public static void Init(ProcessModule module) { - gaugeStart = module.BaseAddress + 0x1b2d4b4; + public JobGauges(ClientStateAddressResolver addressResolver) { + Address = addressResolver; } // Should only be called with the gauge types in // ClientState.Structs.JobGauge - public static T Gauge() { - return Marshal.PtrToStructure(gaugeStart); + public T Get() { + return Marshal.PtrToStructure(Address.ActorTable); } } } diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 869ac04f6..9de2c94b3 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -24,8 +24,6 @@ namespace Dalamud.Game.Internal.Gui { this.address = new IconReplacerAddressResolver(); this.address.Setup(scanner); - JobGauge.Init(module); - this.byteBase = scanner.Module.BaseAddress; this.jobInfo = byteBase + 0x1b2d4b4; this.comboTimer = byteBase + 0x1AE1B10; @@ -321,7 +319,7 @@ namespace Dalamud.Game.Internal.Gui { // Or with Heat Blast when overheated. // For some reason the shots use their unheated IDs as combo moves if (actionID == 7413) { - if (JobGauge.Gauge().IsOverheated() && level >= 35) return 7410; + if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 35) return 7410; if (comboTime > 0) { if (lastMove == 2866) return 7412; if (lastMove == 2868) return 7413; @@ -331,7 +329,7 @@ namespace Dalamud.Game.Internal.Gui { // Replace Spread Shot with Auto Crossbow when overheated. if (actionID == 2870) { - if (JobGauge.Gauge().IsOverheated() && level >= 52) return 16497; + if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 52) return 16497; return 2870; } @@ -339,7 +337,7 @@ namespace Dalamud.Game.Internal.Gui { // Enochian changes to B4 or F4 depending on stance. if (actionID == 3575) { - BLMGauge jobInfo = JobGauge.Gauge(); + BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get(); if (jobInfo.IsEnoActive) { if (jobInfo.InUmbralIce()) return 3576; return 3577; @@ -349,7 +347,7 @@ namespace Dalamud.Game.Internal.Gui { // Umbral Soul and Transpose if (actionID == 149) { - if (JobGauge.Gauge().InUmbralIce() && level >= 76) return 16506; + if (this.dalamud.ClientState.JobGauges.Get().InUmbralIce() && level >= 76) return 16506; return 149; } @@ -414,7 +412,7 @@ namespace Dalamud.Game.Internal.Gui { // Standard Step is one button. if (actionID == 15997) { - DNCGauge gauge = JobGauge.Gauge(); + DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get(); if (gauge.IsDancing()) { if (gauge.NumCompleteSteps == 2) { return 16192; @@ -429,7 +427,7 @@ namespace Dalamud.Game.Internal.Gui { // Technical Step is one button. if (actionID == 15998) { - DNCGauge gauge = JobGauge.Gauge(); + DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get(); if (gauge.IsDancing()) { if (gauge.NumCompleteSteps == 4) { return 16196; From 1bd4eed72c1dfa616a3cba21a4d04b522ad0fe81 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 18 Oct 2019 22:01:35 +0900 Subject: [PATCH 05/19] Unify IconReplacer and IconReplaceChecker, cleanup --- Dalamud/Dalamud.cs | 10 +---- .../Game/Internal/Gui/IconReplaceChecker.cs | 38 ------------------- .../Gui/IconReplaceCheckerAddressResolver.cs | 17 --------- Dalamud/Game/Internal/Gui/IconReplacer.cs | 35 +++++++++++------ .../Gui/IconReplacerAddressResolver.cs | 7 ++-- 5 files changed, 29 insertions(+), 78 deletions(-) delete mode 100644 Dalamud/Game/Internal/Gui/IconReplaceChecker.cs delete mode 100644 Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 0797ccb62..c5ecdf65f 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -42,8 +42,6 @@ namespace Dalamud { public readonly IconReplacer IconReplacer; - public readonly IconReplaceChecker IconReplaceChecker; - public Dalamud(DalamudStartInfo info) { this.StartInfo = info; @@ -71,9 +69,7 @@ namespace Dalamud { this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory); - this.IconReplaceChecker = new IconReplaceChecker(this.targetModule, this.sigScanner); - - this.IconReplacer = new IconReplacer(this, this.targetModule, this.sigScanner); + this.IconReplacer = new IconReplacer(this, this.sigScanner); try { this.PluginManager.LoadPlugins(); @@ -89,8 +85,6 @@ namespace Dalamud { this.BotManager.Start(); - this.IconReplaceChecker.Enable(); - this.IconReplacer.Enable(); } @@ -109,8 +103,6 @@ namespace Dalamud { this.unloadSignal.Dispose(); - this.IconReplaceChecker.Dispose(); - this.IconReplacer.Dispose(); } diff --git a/Dalamud/Game/Internal/Gui/IconReplaceChecker.cs b/Dalamud/Game/Internal/Gui/IconReplaceChecker.cs deleted file mode 100644 index 48eb7f553..000000000 --- a/Dalamud/Game/Internal/Gui/IconReplaceChecker.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Diagnostics; -using Dalamud.Hooking; - -namespace Dalamud.Game.Internal.Gui { - public class IconReplaceChecker { - private IconReplaceCheckerAddressResolver address; - private Hook checkerHook; - - public IconReplaceChecker(ProcessModule module, SigScanner scanner) { - this.address = new IconReplaceCheckerAddressResolver(); - this.address.Setup(scanner); - hookChecker(); - } - - private void hookChecker() { - this.checkerHook = new Hook(this.address.BaseAddress, (Delegate)new OnCheckDetour(this.HandleChecker), (object)this); - } - - public void Enable() { - this.checkerHook.Enable(); - } - - public void Dispose() { - this.checkerHook.Dispose(); - } - - // I hate this function. This is the dumbest function to exist in the game. Just return 1. - // Determines which abilities are allowed to have their icons updated. - private ulong HandleChecker(int actionID) { - return 1; - } - - private delegate ulong OnCheckDetour(int actionID); - - public delegate ulong OnCheckDelegate(int actionID); - } -} diff --git a/Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs b/Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs deleted file mode 100644 index 28ce04bc3..000000000 --- a/Dalamud/Game/Internal/Gui/IconReplaceCheckerAddressResolver.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Internal.Gui { - class IconReplaceCheckerAddressResolver : BaseAddressResolver { - public IntPtr BaseAddress { get; private set; } - protected bool IsResolved { get; set; } - - protected override void Setup64Bit(SigScanner sig) - { - this.BaseAddress = sig.ScanText("81 f9 d4 08 00 00 7f 33 0f 84 fa 01 00 00 83 c1 eb 81 f9 a3 00 00 00"); - } - } -} diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 9de2c94b3..a248378c5 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -9,8 +9,14 @@ using System.Runtime.InteropServices; namespace Dalamud.Game.Internal.Gui { public class IconReplacer { - private IconReplacerAddressResolver address; - private Hook iconHook; + public delegate ulong OnGetIconDelegate(byte param1, uint param2); + public delegate ulong OnCheckIsIconReplaceableDelegate(int actionID); + + private Hook iconHook; + private Hook checkerHook; + + private IconReplacerAddressResolver Address; + private IntPtr comboTimer; private IntPtr lastComboMove; private IntPtr activeBuffArray = IntPtr.Zero; @@ -19,28 +25,39 @@ namespace Dalamud.Game.Internal.Gui { private Dalamud dalamud; private PlayerCharacter localCharacter = null; - public unsafe IconReplacer(Dalamud dalamud, ProcessModule module, SigScanner scanner) { + public unsafe IconReplacer(Dalamud dalamud, SigScanner scanner) { this.dalamud = dalamud; - this.address = new IconReplacerAddressResolver(); - this.address.Setup(scanner); + this.Address = new IconReplacerAddressResolver(); + this.Address.Setup(scanner); this.byteBase = scanner.Module.BaseAddress; this.jobInfo = byteBase + 0x1b2d4b4; this.comboTimer = byteBase + 0x1AE1B10; this.lastComboMove = byteBase + 0x1AE1B14; - this.iconHook = new Hook(this.address.BaseAddress, (Delegate)new OnIconDetour(this.HandleIconUpdate), (object)this); + Log.Verbose("===== H O T B A R S ====="); + Log.Verbose("IsIconReplaceable address {IsIconReplaceable}", Address.IsIconReplaceable); + Log.Verbose("GetIcon address {GetIcon}", Address.GetIcon); + this.iconHook = new Hook(this.Address.GetIcon, new OnGetIconDelegate(GetIconDetour), this); + this.checkerHook = new Hook(this.Address.IsIconReplaceable, new OnCheckIsIconReplaceableDelegate(CheckIsIconReplaceableDetour), this); } public void Enable() { this.iconHook.Enable(); + this.checkerHook.Enable(); } public void Dispose() { this.iconHook.Dispose(); + this.checkerHook.Dispose(); } + // I hate this function. This is the dumbest function to exist in the game. Just return 1. + // Determines which abilities are allowed to have their icons updated. + private ulong CheckIsIconReplaceableDetour(int actionID) { + return 1; + } /// /// Replace an ability with another ability @@ -51,7 +68,7 @@ namespace Dalamud.Game.Internal.Gui { /// For example, Souleater combo on DRK happens by dragging Souleater /// onto your bar and mashing it. /// - private unsafe ulong HandleIconUpdate(byte self, uint actionID) { + private unsafe ulong GetIconDetour(byte self, uint actionID) { // TODO: BRD, RDM, level checking for everything. @@ -498,10 +515,6 @@ namespace Dalamud.Game.Internal.Gui { return false; } - private delegate ulong OnIconDetour(byte param1, uint param2); - - public delegate ulong OnIconDelegate(byte param1, uint param2); - private unsafe delegate int* getArray(long* address); private unsafe IntPtr FindBuffAddress() { diff --git a/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs b/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs index e8c37533d..77e8a5859 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs @@ -6,11 +6,12 @@ using System.Threading.Tasks; namespace Dalamud.Game.Internal.Gui { class IconReplacerAddressResolver : BaseAddressResolver { - public IntPtr BaseAddress { get; private set; } - protected bool IsResolved { get; set; } + public IntPtr GetIcon { get; private set; } + public IntPtr IsIconReplaceable { get; private set; } protected override void Setup64Bit(SigScanner sig) { - this.BaseAddress = sig.ScanText("81 fa d4 08 00 00 7f 4b 74 44 8d 42 eb 3d a3 00 00 00"); + this.GetIcon = sig.ScanText("81 fa d4 08 00 00 7f 4b 74 44 8d 42 eb 3d a3 00 00 00"); + this.IsIconReplaceable = sig.ScanText("81 f9 d4 08 00 00 7f 33 0f 84 fa 01 00 00 83 c1 eb 81 f9 a3 00 00 00"); } } } From 16a5788695af8df1d54df952fc53434849db0270 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 18 Oct 2019 23:50:02 +0900 Subject: [PATCH 06/19] New config system, config flags for combos, commands for combos --- Dalamud/Configuration/CustomComboPreset.cs | 147 +++++ Dalamud/Configuration/DalamudConfiguration.cs | 29 + Dalamud/Dalamud.cs | 61 +- Dalamud/Dalamud.csproj | 3 + Dalamud/DalamudStartInfo.cs | 9 +- Dalamud/Game/ClientState/ClientState.cs | 3 + Dalamud/Game/ClientState/JobGauge.cs | 12 +- Dalamud/Game/Internal/Framework.cs | 2 +- Dalamud/Game/Internal/Gui/IconReplacer.cs | 563 ++++++++++-------- 9 files changed, 572 insertions(+), 257 deletions(-) create mode 100644 Dalamud/Configuration/CustomComboPreset.cs create mode 100644 Dalamud/Configuration/DalamudConfiguration.cs diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs new file mode 100644 index 000000000..965a8574d --- /dev/null +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace XIVLauncher.Dalamud +{ + [Flags] + public enum CustomComboPreset + { + None = 0, + + // DRAGOON + [CustomComboInfo("Coerthan Torment Combo", "Replace Coearthan Torment with its combo chain", 22)] + DragoonCoerthanTormentCombo = 1 << 0, + + [CustomComboInfo("Chaos Thrust Combo", "Replace Chaos Thrust with its combo chain", 22)] + DragoonChaosThrustCombo = 1 << 1, + + [CustomComboInfo("Full Thrust Combo", "Replace Full Thrust with its combo chain", 22)] + DragoonFullThrustCombo = 1 << 2, + + // DARK KNIGHT + [CustomComboInfo("Souleater Combo", "Replace Souleater with its combo chain", 32)] + DarkSouleaterCombo = 1 << 3, + + [CustomComboInfo("Stalwart Soul Combo", "Replace Stalwart Soul with its combo chain", 32)] + DarkStalwartSoulCombo = 1 << 4, + + // PALADIN + [CustomComboInfo("Goring Blade Combo", "Replace Goring Blade with its combo chain", 19)] + PaladinGoringBladeCombo = 1 << 5, + + [CustomComboInfo("Royal Authority Combo", "Replace Royal Authority with its combo chain", 19)] + PaladinRoyalAuthorityCombo = 1 << 6, + + [CustomComboInfo("Prominence Combo", "Replace Prominence with its combo chain", 19)] + PaladinProminenceCombo = 1 << 7, + + // WARRIOR + [CustomComboInfo("Storms Path Combo", "Replace Storms Path with its combo chain", 21)] + WarriorStormsPathCombo = 1 << 8, + + [CustomComboInfo("Storms Eye Combo", "Replace Storms Eye with its combo chain", 21)] + WarriorStormsEyeCombo = 1 << 9, + + [CustomComboInfo("Mythril Tempest Combo", "Replace Mythril Tempest with its combo chain", 21)] + WarriorMythrilTempestCombo = 1 << 10, + + // SAMURAI + [CustomComboInfo("Yukikaze Combo", "Replace Yukikaze with its combo chain", 34)] + SamuraiYukikazeCombo = 1 << 11, + + [CustomComboInfo("Gekko Combo", "Replace Gekko with its combo chain", 34)] + SamuraiGekkoCombo = 1 << 12, + + [CustomComboInfo("Kasha Combo", "Replace Kasha with its combo chain", 34)] + SamuraiKashaCombo = 1 << 13, + + [CustomComboInfo("Mangetsu Combo", "Replace Mangetsu with its combo chain", 34)] + SamuraiMangetsuCombo = 1 << 14, + + [CustomComboInfo("Oka Combo", "Replace Oka with its combo chain", 34)] + SamuraiOkaCombo = 1 << 15, + + + // NINJA + [CustomComboInfo("Shadow Fang Combo", "Replace Shadow Fang with its combo chain", 30)] + NinjaShadowFangCombo = 1 << 16, + + [CustomComboInfo("Armor Crush Combo", "Replace Armor Crush with its combo chain", 30)] + NinjaArmorCrushCombo = 1 << 17, + + [CustomComboInfo("Aeolian Edge Combo", "Replace Aeolian Edge with its combo chain", 30)] + NinjaAeolianEdgeCombo = 1 << 18, + + [CustomComboInfo("Hakke Mujinsatsu Combo", "Replace Hakke Mujinsatsu with its combo chain", 30)] + NinjaHakkeMujinsatsuCombo = 1 << 19, + + // GUNBREAKER + [CustomComboInfo("Solid Barrel Combo", "Replace Solid Barrel with its combo chain", 37)] + GunbreakerSolidBarrelCombo = 1 << 20, + + [CustomComboInfo("Gnashing Fang Combo", "Replace Gnashing Fang with its combo chain", 37)] + GunbreakerGnashingFangCombo = 1 << 21, + + [CustomComboInfo("Demon Slaughter Combo", "Replace Demon Slaughter with its combo chain", 37)] + GunbreakerDemonSlaughterCombo = 1 << 22, + + // MACHINIST + [CustomComboInfo("Heated Clan Shot Combo/Heat", "Replace Heated Clan Shot with its combo chain or with Heat Blast when overheated.", 31)] + MachinistHeatedClanShotFeature = 1 << 23, + + [CustomComboInfo("Spread Shot Heat", "Replace Spread Shot with Heat Blast when overheated.", 31)] + MachinistSpreadShotFeature = 1 << 24, + + // BLACK MAGE + [CustomComboInfo("Enochian Stance Switcher", "Change Enochian to Fire 4 or Blizzard 4 depending on stance.", 25)] + BlackEnochianFeature = 1 << 25, + + [CustomComboInfo("Umbral Soul/Transpose Switcher", "Change between Umbral Soul and Transpose automatically.", 25)] + BlackManaFeature = 1 << 26, + + // ASTROLOGIAN + [CustomComboInfo("Cards on Draw", "Play your Astrologian Cards on Draw.", 33)] + AstrologianCardsOnDrawFeature = 1 << 27, + + // SUMMONER + [CustomComboInfo("Dreadwyrm Combiner", "Now comes with Dreadwyrm Trance, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix.", 27)] + SummonerDwtCombo = 1 << 28, + + // SCHOLAR + [CustomComboInfo("Seraph Fey Blessing/Consolation", "Change Fey Blessing into Consolation when Seraph is out.", 28)] + ScholarSeraphConsolationFeature = 1 << 29, + + // DANCER + [CustomComboInfo("Standard Step Combo", "Standard Step on one button.", 38)] + DancerStandardStepCombo = 1 << 30, + + [CustomComboInfo("Technical Step Combo", "Technical Step on one button.", 38)] + DancerTechnicalStepCombo = 1 << 31, + + [CustomComboInfo("AoE GCD procs", "Replaces all AoE GCDs with their procced version when available.", 38)] + DancerAoeGcdFeature = 1 << 32, + + [CustomComboInfo("Fan Dance Combos", "Change Fan Dance and Fan Dance 2 into Fan Dance 3 while flourishing.", 38)] + DancerFanDanceCombo = 1 << 33, + + [CustomComboInfo("Fountain Combos", "Fountain changes into Fountain combo, prioritizing procs over combo, and Fountainfall over Reverse Cascade.", 38)] + DancerFountainCombo = 1 << 34 + } + + public class CustomComboInfoAttribute : Attribute + { + internal CustomComboInfoAttribute(string fancyName, string description, byte classJob) + { + FancyName = fancyName; + Description = description; + ClassJob = classJob; + } + + public string FancyName { get; } + public string Description { get; } + public byte ClassJob { get; } + } +} diff --git a/Dalamud/Configuration/DalamudConfiguration.cs b/Dalamud/Configuration/DalamudConfiguration.cs new file mode 100644 index 000000000..32f2c0bd9 --- /dev/null +++ b/Dalamud/Configuration/DalamudConfiguration.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Dalamud.DiscordBot; +using Newtonsoft.Json; +using XIVLauncher.Dalamud; + +namespace Dalamud +{ + [Serializable] + public class DalamudConfiguration + { + public DiscordFeatureConfiguration DiscordFeatureConfig { get; set; } + + public bool OptOutMbCollection { get; set; } = false; + + public CustomComboPreset ComboPresets { get; set; } + + public List BadWords { get; set; } + + public static DalamudConfiguration Load(string path) { + return JsonConvert.DeserializeObject(File.ReadAllText(path)); + } + + public void Save(string path) { + File.WriteAllText(path, JsonConvert.SerializeObject(this)); + } + } +} diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index c5ecdf65f..b93033c92 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -16,6 +16,7 @@ using Dalamud.Game.Network; using Dalamud.Plugin; using Dalamud.Settings; using Serilog; +using XIVLauncher.Dalamud; namespace Dalamud { public sealed class Dalamud : IDisposable { @@ -42,8 +43,11 @@ namespace Dalamud { public readonly IconReplacer IconReplacer; + public readonly DalamudConfiguration Configuration; + public Dalamud(DalamudStartInfo info) { this.StartInfo = info; + this.Configuration = DalamudConfiguration.Load(info.ConfigurationPath); this.baseDirectory = info.WorkingDirectory; @@ -61,11 +65,11 @@ namespace Dalamud { SetupCommands(); ChatHandlers = new ChatHandlers(this); - NetworkHandlers = new NetworkHandlers(this, info.OptOutMbCollection); + NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection); this.ClientState = new ClientState(this, info, this.sigScanner, this.targetModule); - this.BotManager = new DiscordBotManager(this, info.DiscordFeatureConfig); + this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig); this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory); @@ -122,6 +126,11 @@ namespace Dalamud { ShowInHelp = false }); + CommandManager.AddHandler("/xldcombo", new CommandInfo(OnCommandDebugCombo) { + HelpMessage = "COMBO debug", + ShowInHelp = false + }); + CommandManager.AddHandler("/xlhelp", new CommandInfo(OnCommandHelp) { HelpMessage = "Shows list of commands available." }); @@ -320,6 +329,54 @@ namespace Dalamud { } } + private void OnCommandDebugCombo(string command, string arguments) { + var argumentsParts = arguments.Split(); + + switch (argumentsParts[0]) { + case "setall": { + foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { + if (value == CustomComboPreset.None) + continue; + + this.Configuration.ComboPresets |= value; + } + + Framework.Gui.Chat.Print("all SET"); + } + break; + case "unsetall": { + foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { + this.Configuration.ComboPresets &= value; + } + + Framework.Gui.Chat.Print("all UNSET"); + } + break; + case "set": { + foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { + if (value.ToString().ToLower() != argumentsParts[1].ToLower()) + continue; + + this.Configuration.ComboPresets |= value; + Framework.Gui.Chat.Print(argumentsParts[1] + " SET"); + } + } + break; + case "list": { + foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { + if (this.Configuration.ComboPresets.HasFlag(value)) + Framework.Gui.Chat.Print(value.ToString()); + } + } + break; + + default: Framework.Gui.Chat.Print("Unknown"); + break; + } + + this.Configuration.Save(this.StartInfo.ConfigurationPath); + } + private void OnBotJoinCommand(string command, string arguments) { if (this.BotManager != null && this.BotManager.IsConnected) Process.Start( diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 99f9eca5e..b14a0da76 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -64,4 +64,7 @@ Resources.Designer.cs + + + \ No newline at end of file diff --git a/Dalamud/DalamudStartInfo.cs b/Dalamud/DalamudStartInfo.cs index b0cac09b2..16d43e5fa 100644 --- a/Dalamud/DalamudStartInfo.cs +++ b/Dalamud/DalamudStartInfo.cs @@ -3,15 +3,14 @@ using Dalamud.DiscordBot; namespace Dalamud { [Serializable] - public sealed class DalamudStartInfo { + public sealed class DalamudStartInfo + { public string WorkingDirectory; + public string ConfigurationPath; + public string PluginDirectory; public string DefaultPluginDirectory; public ClientLanguage Language; - - public DiscordFeatureConfiguration DiscordFeatureConfig { get; set; } - - public bool OptOutMbCollection { get; set; } = false; } public enum ClientLanguage diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index e12d542b1..98e1c2e29 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Dalamud.Game.ClientState.Actors; using Dalamud.Game.ClientState.Actors.Types; using Dalamud.Game.Internal; +using Serilog; namespace Dalamud.Game.ClientState { @@ -54,6 +55,8 @@ namespace Dalamud.Game.ClientState Address = new ClientStateAddressResolver(); Address.Setup(scanner); + Log.Verbose("===== C L I E N T S T A T E ====="); + this.ClientLanguage = startInfo.Language; this.Actors = new ActorTable(Address); diff --git a/Dalamud/Game/ClientState/JobGauge.cs b/Dalamud/Game/ClientState/JobGauge.cs index 3e458fffc..916921af7 100644 --- a/Dalamud/Game/ClientState/JobGauge.cs +++ b/Dalamud/Game/ClientState/JobGauge.cs @@ -1,11 +1,5 @@ -using Dalamud.Game.ClientState.Structs.JobGauge; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; +using Serilog; namespace Dalamud.Game.ClientState { public class JobGauges { @@ -13,12 +7,14 @@ namespace Dalamud.Game.ClientState { public JobGauges(ClientStateAddressResolver addressResolver) { Address = addressResolver; + + Log.Verbose("JobGaugeData address {JobGaugeData}", Address.ActorTable); } // Should only be called with the gauge types in // ClientState.Structs.JobGauge public T Get() { - return Marshal.PtrToStructure(Address.ActorTable); + return Marshal.PtrToStructure(Address.JobGaugeData); } } } diff --git a/Dalamud/Game/Internal/Framework.cs b/Dalamud/Game/Internal/Framework.cs index 487ff699a..547753157 100644 --- a/Dalamud/Game/Internal/Framework.cs +++ b/Dalamud/Game/Internal/Framework.cs @@ -56,7 +56,7 @@ namespace Dalamud.Game.Internal { Network = new GameNetwork(dalamud, scanner); - Resource = new ResourceManager(dalamud, scanner); + //Resource = new ResourceManager(dalamud, scanner); } private void HookVTable() { diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index a248378c5..234426564 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -6,6 +6,7 @@ using Serilog; using System; using System.Diagnostics; using System.Runtime.InteropServices; +using XIVLauncher.Dalamud; namespace Dalamud.Game.Internal.Gui { public class IconReplacer { @@ -94,240 +95,296 @@ namespace Dalamud.Game.Internal.Gui { // TODO: Jump/High Jump into Mirage Dive // Replace Coerthan Torment with Coerthan Torment combo chain - if (actionID == 16477) { - if (comboTime > 0) { - if (Marshal.ReadInt32(lastComboMove) == 86) return 7397; - if (Marshal.ReadInt32(lastComboMove) == 7397) return 16477; + 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; + } + return 86; } - return 86; } + // Replace Chaos Thrust with the Chaos Thrust combo chain - if (actionID == 88) { - if (comboTime > 0) { - if (lastMove == 75 || lastMove == 16479) return 87; - if (lastMove == 87) return 88; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonChaosThrustCombo)) { + if (actionID == 88) { + if (comboTime > 0) { + if (lastMove == 75 || lastMove == 16479) return 87; + if (lastMove == 87) return 88; + } + if (activeBuffArray != IntPtr.Zero) { + if (SearchBuffArray(802)) return 3554; + if (SearchBuffArray(803)) return 3556; + if (SearchBuffArray(1863)) return 16479; + } + return 75; } - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(802)) return 3554; - if (SearchBuffArray(803)) return 3556; - if (SearchBuffArray(1863)) return 16479; - } - return 75; } + // Replace Full Thrust with the Full Thrust combo chain - if (actionID == 84) { - if (comboTime > 0) { - if (lastMove == 75 || lastMove == 16479) return 78; - if (lastMove == 78) return 84; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonFullThrustCombo)) { + if (actionID == 84) { + 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; + } + + return 75; } - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(802)) return 3554; - if (SearchBuffArray(803)) return 3556; - if (SearchBuffArray(1863)) return 16479; - } - return 75; } // DARK KNIGHT // Replace Souleater with Souleater combo chain - if (actionID == 3632) { - if (comboTime > 0) { - if (lastMove == 3617) return 3623; - if (lastMove == 3623) return 3632; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DarkSouleaterCombo)) { + if (actionID == 3632) { + if (comboTime > 0) { + if (lastMove == 3617) return 3623; + if (lastMove == 3623) return 3632; + } + + return 3617; } - return 3617; } // Replace Stalwart Soul with Stalwart Soul combo chain - if (actionID == 16468) { - if (comboTime > 0) { - if (lastMove == 3621) return 16468; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DarkStalwartSoulCombo)) { + if (actionID == 16468) { + if (comboTime > 0) { + if (lastMove == 3621) return 16468; + } + + return 3621; } - return 3621; } // PALADIN // Replace Goring Blade with Goring Blade combo - if (actionID == 3538) { - if (comboTime > 0) { - if (lastMove == 9) return 15; - if (lastMove == 15) return 3538; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinGoringBladeCombo)) { + if (actionID == 3538) { + if (comboTime > 0) { + if (lastMove == 9) return 15; + if (lastMove == 15) return 3538; + } + + return 9; } - return 9; } // Replace Royal Authority with Royal Authority combo - if (actionID == 3539) { - if (comboTime > 0) { - if (lastMove == 9) return 15; - if (lastMove == 15) return 3539; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinRoyalAuthorityCombo)) { + if (actionID == 3539) { + if (comboTime > 0) { + if (lastMove == 9) return 15; + if (lastMove == 15) return 3539; + } + + return 9; } - return 9; } // Replace Prominence with Prominence combo - if (actionID == 16457) { - if (comboTime > 0) { - if (lastMove == 7381) return 16457; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinProminenceCombo)) { + if (actionID == 16457) { + if (comboTime > 0) { + if (lastMove == 7381) return 16457; + } + + return 7381; } - return 7381; } // WARRIOR // Replace Storm's Path with Storm's Path combo - if (actionID == 42) { - if (comboTime > 0) { - if (lastMove == 31) return 37; - if (lastMove == 37) return 42; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorStormsPathCombo)) { + if (actionID == 42) { + if (comboTime > 0) { + if (lastMove == 31) return 37; + if (lastMove == 37) return 42; + } + + return 31; } - return 31; } // Replace Storm's Eye with Storm's Eye combo - if (actionID == 45) { - if (comboTime > 0) { - if (lastMove == 31) return 37; - if (lastMove == 37) return 45; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorStormsEyeCombo)) { + if (actionID == 45) { + if (comboTime > 0) { + if (lastMove == 31) return 37; + if (lastMove == 37) return 45; + } + return 31; } - return 31; } // Replace Mythril Tempest with Mythril Tempest combo - if (actionID == 16462) { - if (comboTime > 0) { - if (lastMove == 41) return 16462; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorMythrilTempestCombo)) { + if (actionID == 16462) { + if (comboTime > 0) { + if (lastMove == 41) return 16462; + } + return 41; } - return 41; } // SAMURAI // Replace Yukikaze with Yukikaze combo - if (actionID == 7480) { - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(1233)) return 7480; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiYukikazeCombo)) { + if (actionID == 7480) { + if (activeBuffArray != IntPtr.Zero) { + if (SearchBuffArray(1233)) return 7480; + } + if (comboTime > 0) { + if (lastMove == 7477) return 7480; + } + return 7477; } - if (comboTime > 0) { - if (lastMove == 7477) return 7480; - } - return 7477; } // Replace Gekko with Gekko combo - if (actionID == 7481) { - if (activeBuffArray != IntPtr.Zero) { - if (SearchBuffArray(1233)) return 7481; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiGekkoCombo)) { + if (actionID == 7481) { + if (activeBuffArray != IntPtr.Zero) { + if (SearchBuffArray(1233)) return 7481; + } + if (comboTime > 0) { + if (lastMove == 7477) return 7478; + if (lastMove == 7478) return 7481; + } + return 7477; } - if (comboTime > 0) { - if (lastMove == 7477) return 7478; - if (lastMove == 7478) return 7481; - } - return 7477; } // Replace Kasha with Kasha combo - if (actionID == 7482) { - if (activeBuffArray != null) { - if (SearchBuffArray(1233)) return 7482; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiKashaCombo)) { + if (actionID == 7482) { + if (activeBuffArray != null) { + if (SearchBuffArray(1233)) return 7482; + } + if (comboTime > 0) { + if (lastMove == 7477) return 7479; + if (lastMove == 7479) return 7482; + } + return 7477; } - if (comboTime > 0) { - if (lastMove == 7477) return 7479; - if (lastMove == 7479) return 7482; - } - return 7477; } // Replace Mangetsu with Mangetsu combo - if (actionID == 7484) { - if (activeBuffArray != null) { - if (SearchBuffArray(1233)) return 7484; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiMangetsuCombo)) { + if (actionID == 7484) { + if (activeBuffArray != null) { + if (SearchBuffArray(1233)) return 7484; + } + if (comboTime > 0) { + if (lastMove == 7483) return 7484; + } + return 7483; } - if (comboTime > 0) { - if (lastMove == 7483) return 7484; - } - return 7483; } - // Replace Yukikaze with Yukikaze combo - if (actionID == 7485) { - if (activeBuffArray != null) { - if (SearchBuffArray(1233)) return 7485; + // 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 (comboTime > 0) { + if (lastMove == 7483) return 7485; + } + return 7483; } - if (comboTime > 0) { - if (lastMove == 7483) return 7485; - } - return 7483; } // NINJA // Replace Shadow Fang with Shadow Fang combo - if (actionID == 2257) { - if (comboTime > 0) { - if (lastMove == 2240) return 2257; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaShadowFangCombo)) { + if (actionID == 2257) { + if (comboTime > 0) { + if (lastMove == 2240) return 2257; + } + return 2240; } - return 2240; } // Replace Armor Crush with Armor Crush combo - if (actionID == 2257) { - if (comboTime > 0) { - if (lastMove == 2240) return 2242; - if (lastMove == 2242) return 3563; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) { + if (actionID == 2257) { + if (comboTime > 0) { + if (lastMove == 2240) return 2242; + if (lastMove == 2242) return 3563; + } + return 2240; } - return 2240; } // Replace Aeolian Edge with Aeolian Edge combo - if (actionID == 2257) { - if (comboTime > 0) { - if (lastMove == 2240) return 2242; - if (lastMove == 2242) return 2255; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAeolianEdgeCombo)) { + if (actionID == 2257) { + if (comboTime > 0) { + if (lastMove == 2240) return 2242; + if (lastMove == 2242) return 2255; + } + return 2240; } - return 2240; } // Replace Hakke Mujinsatsu with Hakke Mujinsatsu combo - if (actionID == 16488) { - if (comboTime > 0) { - if (lastMove == 2254) return 16488; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaHakkeMujinsatsuCombo)) { + if (actionID == 16488) { + if (comboTime > 0) { + if (lastMove == 2254) return 16488; + } + return 2254; } - return 2254; } // GUNBREAKER // Replace Solid Barrel with Solid Barrel combo - if (actionID == 16145) { - if (comboTime > 0) { - if (lastMove == 16137) return 16139; - if (lastMove == 16139) return 16145; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerSolidBarrelCombo)) { + if (actionID == 16145) { + if (comboTime > 0) { + if (lastMove == 16137) return 16139; + if (lastMove == 16139) return 16145; + } + return 16137; } - return 16137; } // Replace Gnashing Fang with Gnashing Fang combo // TODO: Potentially add Contuation moves as well? - if (actionID == 16146) { - byte ammoComboState = Marshal.ReadByte(jobInfo, 0x10); - if (ammoComboState == 1) return 16147; - if (ammoComboState == 2) return 16150; - return 16146; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerGnashingFangCombo)) { + if (actionID == 16146) { + byte ammoComboState = Marshal.ReadByte(jobInfo, 0x10); + if (ammoComboState == 1) return 16147; + if (ammoComboState == 2) return 16150; + return 16146; + } } // Replace Demon Slaughter with Demon Slaughter combo - if (actionID == 16149) { - if (comboTime > 0) { - if (lastMove == 16141) return 16149; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerDemonSlaughterCombo)) { + if (actionID == 16149) { + if (comboTime > 0) { + if (lastMove == 16141) return 16149; + } + return 16141; } - return 16141; } // MACHINIST @@ -335,63 +392,73 @@ namespace Dalamud.Game.Internal.Gui { // Replace Heated Clean Shot with Heated Clean Shot combo // Or with Heat Blast when overheated. // For some reason the shots use their unheated IDs as combo moves - if (actionID == 7413) { - if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 35) return 7410; - if (comboTime > 0) { - if (lastMove == 2866) return 7412; - if (lastMove == 2868) return 7413; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MachinistHeatedClanShotFeature)) { + if (actionID == 7413) { + if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 35) return 7410; + if (comboTime > 0) { + if (lastMove == 2866) return 7412; + if (lastMove == 2868) return 7413; + } + return 7411; } - return 7411; } // Replace Spread Shot with Auto Crossbow when overheated. - if (actionID == 2870) { - if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 52) return 16497; - return 2870; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MachinistSpreadShotFeature)) { + if (actionID == 2870) { + if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 52) return 16497; + return 2870; + } } // BLACK MAGE // Enochian changes to B4 or F4 depending on stance. - if (actionID == 3575) { - BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get(); - if (jobInfo.IsEnoActive) { - if (jobInfo.InUmbralIce()) return 3576; - return 3577; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackEnochianFeature)) { + if (actionID == 3575) { + BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get(); + if (jobInfo.IsEnoActive) { + if (jobInfo.InUmbralIce()) return 3576; + return 3577; + } + return 3575; } - return 3575; } // Umbral Soul and Transpose - if (actionID == 149) { - if (this.dalamud.ClientState.JobGauges.Get().InUmbralIce() && level >= 76) return 16506; - return 149; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackManaFeature)) { + if (actionID == 149) { + if (this.dalamud.ClientState.JobGauges.Get().InUmbralIce() && level >= 76) return 16506; + return 149; + } } // ASTROLOGIAN // Make cards on the same button as draw - if (actionID == 17055) { - byte x = Marshal.ReadByte(jobInfo, 0x10); - switch (x) { - case 1: - return 4401; - case 2: - return 4404; - case 3: - return 4402; - case 4: - return 4403; - case 5: - return 4405; - case 6: - return 4406; - case 0x70: - return 7444; - case 0x80: - return 7445; - default: - return 3590; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.AstrologianCardsOnDrawFeature)) { + if (actionID == 17055) { + byte x = Marshal.ReadByte(jobInfo, 0x10); + switch (x) { + case 1: + return 4401; + case 2: + return 4404; + case 3: + return 4402; + case 4: + return 4403; + case 5: + return 4405; + case 6: + return 4406; + case 0x70: + return 7444; + case 0x80: + return 7445; + default: + return 3590; + } } } @@ -400,111 +467,125 @@ namespace Dalamud.Game.Internal.Gui { // DWT changes. // Now contains DWT, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix. // What a monster of a button. - 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; - return 7429; + 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; + return 7429; + } + return 3582; + } + else { + if (stackState == 0) return 3581; + if (stackState == 8) return 7427; + if (stackState == 0x10) return 16513; + return 3581; } - return 3582; - } - else { - if (stackState == 0) return 3581; - if (stackState == 8) return 7427; - if (stackState == 0x10) return 16513; - return 3581; } } // SCHOLAR // Change Fey Blessing into Consolation when Seraph is out. - if (actionID == 16543) { - if (Marshal.ReadInt16(jobInfo, 0x10) > 0) return 16546; - return 16543; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarSeraphConsolationFeature)) { + if (actionID == 16543) { + if (Marshal.ReadInt16(jobInfo, 0x10) > 0) return 16546; + return 16543; + } } // DANCER // Standard Step is one button. - if (actionID == 15997) { - DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get(); - if (gauge.IsDancing()) { - if (gauge.NumCompleteSteps == 2) { - return 16192; - } - else { - // C# can't implicitly cast from int to ulong. - return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerStandardStepCombo)) { + if (actionID == 15997) { + DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.IsDancing()) { + if (gauge.NumCompleteSteps == 2) { + return 16192; + } + else { + // C# can't implicitly cast from int to ulong. + return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + } } + return 15997; } - return 15997; } // Technical Step is one button. - if (actionID == 15998) { - DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get(); - if (gauge.IsDancing()) { - if (gauge.NumCompleteSteps == 4) { - return 16196; - } - else { - // C# can't implicitly cast from int to ulong. - return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerTechnicalStepCombo)) { + if (actionID == 15998) { + DNCGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.IsDancing()) { + if (gauge.NumCompleteSteps == 4) { + return 16196; + } + else { + // C# can't implicitly cast from int to ulong. + return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); + } } + return 15998; } - return 15998; } // Fountain changes into Fountain combo, prioritizing procs over combo, // and Fountainfall over Reverse Cascade. - if (actionID == 15990) { - if (activeBuffArray != null) { - if (SearchBuffArray(1815)) return 15992; - if (SearchBuffArray(1814)) return 15991; + 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 (comboTime > 0) { + if (lastMove == 15989) return 15990; + } + return 15989; } - if (comboTime > 0) { - if (lastMove == 15989) return 15990; - } - return 15989; } // AoE GCDs are split into two buttons, because priority matters // differently in different single-target moments. Thanks yoship. // Replaces each GCD with its procced version. - if (actionID == 15994) { - if (activeBuffArray != null) { - if (SearchBuffArray(1817)) return 15996; - } - return 15994; - } - - if (actionID == 15993) { - if (activeBuffArray != null) { - if (SearchBuffArray(1816)) return 15995; - } - return 15993; - } - - // Fan Dance changes into Fan Dance 3 while flourishing. - if (actionID == 16007) { - if (activeBuffArray != null) { - if (SearchBuffArray(1820)) return 16009; + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerAoeGcdFeature)) { + if (actionID == 15994) { + if (activeBuffArray != null) { + if (SearchBuffArray(1817)) return 15996; + } + return 15994; } - return 16007; - } - - // Fan Dance 2 changes into Fan Dance 3 while flourishing. - if (actionID == 16008) { - if (activeBuffArray != null) { - if (SearchBuffArray(1820)) return 16009; + if (actionID == 15993) { + if (activeBuffArray != null) { + if (SearchBuffArray(1816)) return 15995; + } + return 15993; } - return 16008; } + 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; + } + + return 16007; + } + + // Fan Dance 2 changes into Fan Dance 3 while flourishing. + if (actionID == 16008) { + if (activeBuffArray != null) { + if (SearchBuffArray(1820)) return 16009; + } + return 16008; + } + } + return this.iconHook.Original(self, actionID); } From 1ab43645f77f81be0bf8cd89e9ab538accf4c9c1 Mon Sep 17 00:00:00 2001 From: attick Date: Fri, 18 Oct 2019 12:33:42 -0400 Subject: [PATCH 07/19] Add "unset" and "toggle" commands for combos. --- Dalamud/Dalamud.cs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index b93033c92..b5013c1de 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -362,6 +362,27 @@ namespace Dalamud { } } break; + case "toggle": { + foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { + if (value.ToString().ToLower() != argumentsParts[1].ToLower()) + continue; + + this.Configuration.ComboPresets ^= value; + Framework.Gui.Chat.Print(argumentsParts[1] + " TOGGLE"); + } + } + break; + + case "unset": { + foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { + if (value.ToString().ToLower() != argumentsParts[1].ToLower()) + continue; + + this.Configuration.ComboPresets &= ~value; + Framework.Gui.Chat.Print(argumentsParts[1] + " UNSET"); + } + } + break; case "list": { foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { if (this.Configuration.ComboPresets.HasFlag(value)) From dc960c5f6f0b5152d143efc112cc53550a46b855 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 19 Oct 2019 02:27:23 +0900 Subject: [PATCH 08/19] Apply new configuration scheme to everything --- Dalamud/Configuration/DalamudConfiguration.cs | 8 +++ Dalamud/Dalamud.cs | 55 +++++++++++-------- Dalamud/Game/ChatHandlers.cs | 5 +- Dalamud/Game/Internal/Framework.cs | 1 - Dalamud/Game/Network/NetworkHandlers.cs | 5 +- Dalamud/Settings/PersistentSettings.cs | 50 ----------------- 6 files changed, 45 insertions(+), 79 deletions(-) delete mode 100644 Dalamud/Settings/PersistentSettings.cs diff --git a/Dalamud/Configuration/DalamudConfiguration.cs b/Dalamud/Configuration/DalamudConfiguration.cs index 32f2c0bd9..ebc5106c6 100644 --- a/Dalamud/Configuration/DalamudConfiguration.cs +++ b/Dalamud/Configuration/DalamudConfiguration.cs @@ -18,6 +18,14 @@ namespace Dalamud public List BadWords { get; set; } + public class FateInfo { + public string Name { get; set; } + public int Id { get; set; } + } + + public List Fates; + + public static DalamudConfiguration Load(string path) { return JsonConvert.DeserializeObject(File.ReadAllText(path)); } diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index b5013c1de..98708a4c5 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -14,7 +14,6 @@ using Dalamud.Game.Internal; using Dalamud.Game.Internal.Gui; using Dalamud.Game.Network; using Dalamud.Plugin; -using Dalamud.Settings; using Serilog; using XIVLauncher.Dalamud; @@ -218,8 +217,8 @@ namespace Dalamud { } private void OnFateWatchAdd(string command, string arguments) { - if (PersistentSettings.Instance.Fates == null) - PersistentSettings.Instance.Fates = new List(); + if (this.Configuration.Fates == null) + this.Configuration.Fates = new List(); dynamic candidates = XivApi.Search(arguments, "Fate").GetAwaiter().GetResult(); @@ -228,32 +227,36 @@ namespace Dalamud { return; } - var fateInfo = new PersistentSettings.FateInfo { + var fateInfo = new DalamudConfiguration.FateInfo { Id = candidates.Results[0].ID, Name = candidates.Results[0].Name }; - PersistentSettings.Instance.Fates.Add(fateInfo); + this.Configuration.Fates.Add(fateInfo); + + this.Configuration.Save(this.StartInfo.ConfigurationPath); Framework.Gui.Chat.Print($"Added fate \"{fateInfo.Name}\"."); } private void OnFateWatchList(string command, string arguments) { - if (PersistentSettings.Instance.Fates == null) - PersistentSettings.Instance.Fates = new List(); + if (this.Configuration.Fates == null) + this.Configuration.Fates = new List(); - if (PersistentSettings.Instance.Fates.Count == 0) { + if (this.Configuration.Fates.Count == 0) { Framework.Gui.Chat.Print("No fates on your watchlist."); return; } - foreach (var fate in PersistentSettings.Instance.Fates) + this.Configuration.Save(this.StartInfo.ConfigurationPath); + + foreach (var fate in this.Configuration.Fates) Framework.Gui.Chat.Print($"Fate {fate.Id}: {fate.Name}"); } private void OnFateWatchRemove(string command, string arguments) { - if (PersistentSettings.Instance.Fates == null) - PersistentSettings.Instance.Fates = new List(); + if (this.Configuration.Fates == null) + this.Configuration.Fates = new List(); dynamic candidates = XivApi.Search(arguments, "Fate").GetAwaiter().GetResult(); @@ -262,37 +265,45 @@ namespace Dalamud { return; } - PersistentSettings.Instance.Fates.RemoveAll(x => x.Id == candidates.Results[0].ID); + this.Configuration.Fates.RemoveAll(x => x.Id == candidates.Results[0].ID); + + this.Configuration.Save(this.StartInfo.ConfigurationPath); Framework.Gui.Chat.Print($"Removed fate \"{candidates.Results[0].Name}\"."); } private void OnBadWordsAdd(string command, string arguments) { - if (PersistentSettings.Instance.BadWords == null) - PersistentSettings.Instance.BadWords = new List(); + if (this.Configuration.BadWords == null) + this.Configuration.BadWords = new List(); - PersistentSettings.Instance.BadWords.Add(arguments); + this.Configuration.BadWords.Add(arguments); + + this.Configuration.Save(this.StartInfo.ConfigurationPath); Framework.Gui.Chat.Print($"Muted \"{arguments}\"."); } private void OnBadWordsList(string command, string arguments) { - if (PersistentSettings.Instance.BadWords == null) - PersistentSettings.Instance.BadWords = new List(); + if (this.Configuration.BadWords == null) + this.Configuration.BadWords = new List(); - if (PersistentSettings.Instance.BadWords.Count == 0) { + if (this.Configuration.BadWords.Count == 0) { Framework.Gui.Chat.Print("No muted words or sentences."); return; } - foreach (var word in PersistentSettings.Instance.BadWords) Framework.Gui.Chat.Print($"\"{word}\""); + this.Configuration.Save(this.StartInfo.ConfigurationPath); + + foreach (var word in this.Configuration.BadWords) Framework.Gui.Chat.Print($"\"{word}\""); } private void OnBadWordsRemove(string command, string arguments) { - if (PersistentSettings.Instance.BadWords == null) - PersistentSettings.Instance.BadWords = new List(); + if (this.Configuration.BadWords == null) + this.Configuration.BadWords = new List(); - PersistentSettings.Instance.BadWords.RemoveAll(x => x == arguments); + this.Configuration.BadWords.RemoveAll(x => x == arguments); + + this.Configuration.Save(this.StartInfo.ConfigurationPath); Framework.Gui.Chat.Print($"Unmuted \"{arguments}\"."); } diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index dab95d694..158527216 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -5,7 +5,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using Dalamud.Game.Chat; -using Dalamud.Settings; using Serilog; namespace Dalamud.Game { @@ -81,8 +80,8 @@ namespace Dalamud.Game { var originalMessage = string.Copy(message); - if (PersistentSettings.Instance.BadWords != null && - PersistentSettings.Instance.BadWords.Any(x => originalMessage.Contains(x))) { + if (this.dalamud.Configuration.BadWords != null && + this.dalamud.Configuration.BadWords.Any(x => originalMessage.Contains(x))) { // This seems to be in the user block list - let's not show it Log.Debug("Blocklist triggered"); isHandled = true; diff --git a/Dalamud/Game/Internal/Framework.cs b/Dalamud/Game/Internal/Framework.cs index 547753157..72c41fd3f 100644 --- a/Dalamud/Game/Internal/Framework.cs +++ b/Dalamud/Game/Internal/Framework.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; -using Dalamud.Settings; using Dalamud.Game.Internal.Gui; using Dalamud.Game.Internal.Libc; using Dalamud.Game.Internal.Network; diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs index 02d5c0e2b..eea77eb4c 100644 --- a/Dalamud/Game/Network/NetworkHandlers.cs +++ b/Dalamud/Game/Network/NetworkHandlers.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Dalamud.Game.Network.MarketBoardUploaders; using Dalamud.Game.Network.Structures; using Dalamud.Game.Network.Universalis.MarketBoardUploaders; -using Dalamud.Settings; using Serilog; namespace Dalamud.Game.Network { @@ -46,14 +45,14 @@ namespace Dalamud.Game.Network { } if (opCode == ZoneOpCode.FateSpawn) { - if (PersistentSettings.Instance.Fates == null) + if (this.dalamud.Configuration.Fates == null) return; var data = new byte[64]; Marshal.Copy(dataPtr, data, 0, 64); var fateId = data[16]; - if (PersistentSettings.Instance.Fates.Any(x => x.Id == fateId) && + if (this.dalamud.Configuration.Fates.Any(x => x.Id == fateId) && this.dalamud.BotManager.IsConnected) Task.Run(() => this.dalamud.BotManager.ProcessFate(fateId)); diff --git a/Dalamud/Settings/PersistentSettings.cs b/Dalamud/Settings/PersistentSettings.cs deleted file mode 100644 index 243202586..000000000 --- a/Dalamud/Settings/PersistentSettings.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace Dalamud.Settings -{ - public class PersistentSettings { - private static PersistentSettings _instance = null; - - private static readonly string ConfigPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "settings.json"); - - public static PersistentSettings Instance { - get { - if (_instance == null) { - if (!File.Exists(ConfigPath)) { - _instance = new PersistentSettings(); - return _instance; - } - - _instance = JsonConvert.DeserializeObject(File.ReadAllText(ConfigPath)); - } - - return _instance; - } - } - - public class FateInfo { - public string Name { get; set; } - public int Id { get; set; } - } - - public List Fates; - - public List BadWords; - - public void Save() { - File.WriteAllText(ConfigPath, JsonConvert.SerializeObject(this)); - } - - public static void Reset() { - _instance = new PersistentSettings(); - Instance.Save(); - } - } -} From 3776edb5b4eb308904e68d41bf8178db7896fdd1 Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 24 Oct 2019 01:43:22 -0400 Subject: [PATCH 09/19] 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; } From 4ea27ef1c549cbd591e08f302de278cd3e2b549c Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 24 Oct 2019 02:16:19 -0400 Subject: [PATCH 10/19] Disable debug message to update local player every call of icon replacement without instantly destroying log file. --- Dalamud/Game/ClientState/Actors/ActorTable.cs | 4 ++-- Dalamud/Game/Internal/Gui/IconReplacer.cs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Dalamud/Game/ClientState/Actors/ActorTable.cs b/Dalamud/Game/ClientState/Actors/ActorTable.cs index 3fea9625f..d1dd88a92 100644 --- a/Dalamud/Game/ClientState/Actors/ActorTable.cs +++ b/Dalamud/Game/ClientState/Actors/ActorTable.cs @@ -37,8 +37,8 @@ namespace Dalamud.Game.ClientState.Actors { var actorStruct = Marshal.PtrToStructure(offset); - Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"), - actorStruct.ObjectKind.ToString()); + //Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"), + // actorStruct.ObjectKind.ToString()); switch (actorStruct.ObjectKind) { case ObjectKind.Player: return new PlayerCharacter(actorStruct); diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 38ef4df91..8c5f23a67 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -100,6 +100,7 @@ namespace Dalamud.Game.Internal.Gui { // Don't clutter the spaghetti any worse than it already is. int lastMove = Marshal.ReadInt32(lastComboMove); float comboTime = (float)Marshal.ReadInt32(comboTimer); + localCharacter = dalamud.ClientState.LocalPlayer; byte level = localCharacter.Level; // DRAGOON From 42c325cb4d250373c6e76fb3f5a67bb7c4a972d6 Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 24 Oct 2019 02:59:41 -0400 Subject: [PATCH 11/19] Add proper level checking to everything. --- Dalamud/Configuration/CustomComboPreset.cs | 9 +- Dalamud/Game/Internal/Gui/IconReplacer.cs | 143 ++++++++++----------- 2 files changed, 73 insertions(+), 79 deletions(-) diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs index 1de3fe52d..42402a6ac 100644 --- a/Dalamud/Configuration/CustomComboPreset.cs +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -175,14 +175,11 @@ namespace XIVLauncher.Dalamud [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("Red Mage AoE Combo", "Replaces Veraero/thunder 2 with Impact when Dualcast or Swiftcast are active.", 35)] + RedMageAoECombo = 1 << 48, [CustomComboInfo("Redoublement combo", "Replaces Redoublement with its combo chain, following enchantment rules.", 35)] - RedMageMeleeCombo = 1 << 50 + RedMageMeleeCombo = 1 << 49 } diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 8c5f23a67..2deb6528a 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -110,8 +110,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonCoerthanTormentCombo)) { if (actionID == 16477) { if (comboTime > 0) { - if (lastMove == 86) return 7397; - if (lastMove == 7397) return 16477; + if (lastMove == 86 && level >= 62) return 7397; + if (lastMove == 7397 && level >= 72) return 16477; } return 86; } @@ -122,12 +122,12 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonChaosThrustCombo)) { if (actionID == 88) { if (comboTime > 0) { - if (lastMove == 75 || lastMove == 16479) return 87; - if (lastMove == 87) return 88; + if ((lastMove == 75 || lastMove == 16479) && level >= 18) return 87; + if (lastMove == 87 && level >= 50) return 88; } - if (SearchBuffArray(802)) return 3554; - if (SearchBuffArray(803)) return 3556; - if (SearchBuffArray(1863)) return 16479; + if (SearchBuffArray(802) && level >= 56) return 3554; + if (SearchBuffArray(803) && level >= 58) return 3556; + if (SearchBuffArray(1863) && level >= 76) return 16479; return 75; } @@ -138,12 +138,12 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonFullThrustCombo)) { if (actionID == 84) { if (comboTime > 0) { - if (lastMove == 75 || lastMove == 16479) return 78; - if (lastMove == 78) return 84; + if ((lastMove == 75 || lastMove == 16479) && level >= 4) return 78; + if (lastMove == 78 && level >= 26) return 84; } - if (SearchBuffArray(802)) return 3554; - if (SearchBuffArray(803)) return 3556; - if (SearchBuffArray(1863)) return 16479; + if (SearchBuffArray(802) && level >= 56) return 3554; + if (SearchBuffArray(803) && level >= 58) return 3556; + if (SearchBuffArray(1863) && level >= 76) return 16479; return 75; } @@ -155,8 +155,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DarkSouleaterCombo)) { if (actionID == 3632) { if (comboTime > 0) { - if (lastMove == 3617) return 3623; - if (lastMove == 3623) return 3632; + if (lastMove == 3617 && level >= 2) return 3623; + if (lastMove == 3623 && level >= 26) return 3632; } return 3617; @@ -167,7 +167,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DarkStalwartSoulCombo)) { if (actionID == 16468) { if (comboTime > 0) { - if (lastMove == 3621) return 16468; + if (lastMove == 3621 && level >= 72) return 16468; } return 3621; @@ -180,8 +180,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinGoringBladeCombo)) { if (actionID == 3538) { if (comboTime > 0) { - if (lastMove == 9) return 15; - if (lastMove == 15) return 3538; + if (lastMove == 9 && level >= 4) return 15; + if (lastMove == 15 && level >= 54) return 3538; } return 9; @@ -192,8 +192,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinRoyalAuthorityCombo)) { if (actionID == 3539) { if (comboTime > 0) { - if (lastMove == 9) return 15; - if (lastMove == 15) return 3539; + if (lastMove == 9 && level >= 4) return 15; + if (lastMove == 15 && level >= 60) return 3539; } return 9; @@ -204,7 +204,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.PaladinProminenceCombo)) { if (actionID == 16457) { if (comboTime > 0) { - if (lastMove == 7381) return 16457; + if (lastMove == 7381 && level >= 40) return 16457; } return 7381; @@ -217,8 +217,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorStormsPathCombo)) { if (actionID == 42) { if (comboTime > 0) { - if (lastMove == 31) return 37; - if (lastMove == 37) return 42; + if (lastMove == 31 && level >= 4) return 37; + if (lastMove == 37 && level >= 26) return 42; } return 31; @@ -229,8 +229,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorStormsEyeCombo)) { if (actionID == 45) { if (comboTime > 0) { - if (lastMove == 31) return 37; - if (lastMove == 37) return 45; + if (lastMove == 31 && level >= 4) return 37; + if (lastMove == 37 && level >= 50) return 45; } return 31; } @@ -240,7 +240,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.WarriorMythrilTempestCombo)) { if (actionID == 16462) { if (comboTime > 0) { - if (lastMove == 41) return 16462; + if (lastMove == 41 && level >= 40) return 16462; } return 41; } @@ -253,7 +253,7 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7480) { if (SearchBuffArray(1233)) return 7480; if (comboTime > 0) { - if (lastMove == 7477) return 7480; + if (lastMove == 7477 && level >= 50) return 7480; } return 7477; } @@ -264,8 +264,8 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7481) { if (SearchBuffArray(1233)) return 7481; if (comboTime > 0) { - if (lastMove == 7477) return 7478; - if (lastMove == 7478) return 7481; + if (lastMove == 7477 && level >= 4) return 7478; + if (lastMove == 7478 && level >= 30) return 7481; } return 7477; } @@ -276,8 +276,8 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7482) { if (SearchBuffArray(1233)) return 7482; if (comboTime > 0) { - if (lastMove == 7477) return 7479; - if (lastMove == 7479) return 7482; + if (lastMove == 7477 && level >= 18) return 7479; + if (lastMove == 7479 && level >= 40) return 7482; } return 7477; } @@ -288,7 +288,7 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7484) { if (SearchBuffArray(1233)) return 7484; if (comboTime > 0) { - if (lastMove == 7483) return 7484; + if (lastMove == 7483 && level >= 35) return 7484; } return 7483; } @@ -299,7 +299,7 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7485) { if (SearchBuffArray(1233)) return 7485; if (comboTime > 0) { - if (lastMove == 7483) return 7485; + if (lastMove == 7483 && level >= 45) return 7485; } return 7483; } @@ -311,7 +311,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaShadowFangCombo)) { if (actionID == 2257) { if (comboTime > 0) { - if (lastMove == 2240) return 2257; + if (lastMove == 2240 && level >= 30) return 2257; } return 2240; } @@ -321,8 +321,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) { if (actionID == 3563) { if (comboTime > 0) { - if (lastMove == 2240) return 2242; - if (lastMove == 2242) return 3563; + if (lastMove == 2240 && level >= 4) return 2242; + if (lastMove == 2242 && level >= 54) return 3563; } return 2240; } @@ -332,8 +332,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAeolianEdgeCombo)) { if (actionID == 2255) { if (comboTime > 0) { - if (lastMove == 2240) return 2242; - if (lastMove == 2242) return 2255; + if (lastMove == 2240 && level >= 4) return 2242; + if (lastMove == 2242 && level >= 26) return 2255; } return 2240; } @@ -343,7 +343,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaHakkeMujinsatsuCombo)) { if (actionID == 16488) { if (comboTime > 0) { - if (lastMove == 2254) return 16488; + if (lastMove == 2254 && level >= 52) return 16488; } return 2254; } @@ -355,8 +355,8 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerSolidBarrelCombo)) { if (actionID == 16145) { if (comboTime > 0) { - if (lastMove == 16137) return 16139; - if (lastMove == 16139) return 16145; + if (lastMove == 16137 && level >= 4) return 16139; + if (lastMove == 16139 && level >= 26) return 16145; } return 16137; } @@ -377,7 +377,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerDemonSlaughterCombo)) { if (actionID == 16149) { if (comboTime > 0) { - if (lastMove == 16141) return 16149; + if (lastMove == 16141 && level >= 40) return 16149; } return 16141; } @@ -392,8 +392,8 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7413) { if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 35) return 7410; if (comboTime > 0) { - if (lastMove == 2866) return 7412; - if (lastMove == 2868) return 7413; + if (lastMove == 2866 && level >= 2) return 7412; + if (lastMove == 2868 && level >= 26) return 7413; } return 7411; } @@ -415,8 +415,8 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 3575) { BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get(); if (jobInfo.IsEnoActive) { - if (jobInfo.InUmbralIce()) return 3576; - return 3577; + if (jobInfo.InUmbralIce() && level >= 58) return 3576; + if (level >= 60) return 3577; } return 3575; } @@ -472,7 +472,7 @@ namespace Dalamud.Game.Internal.Gui { if (gauge.IsPhoenixReady()) return 16516; return 7429; } - return 3582; + if (level >= 60) return 3582; } else { if (gauge.IsBahamutReady()) return 7427; @@ -512,7 +512,7 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerESPainflareCombo)) { if (actionID == 16510) { if (this.dalamud.ClientState.JobGauges.Get().HasAetherflowStacks()) - if(level >= 52) return 3578; + if (level >= 52) return 3578; return 16510; } } @@ -579,7 +579,7 @@ namespace Dalamud.Game.Internal.Gui { if (SearchBuffArray(1815)) return 15992; if (SearchBuffArray(1814)) return 15991; if (comboTime > 0) { - if (lastMove == 15989) return 15990; + if (lastMove == 15989 && level >= 2) return 15990; } return 15989; } @@ -655,7 +655,7 @@ namespace Dalamud.Game.Internal.Gui { if (level >= 70) return 7409; return 98; } - if (level > 76) return 16495; + if (level >= 76) return 16495; return 97; } } @@ -678,9 +678,9 @@ namespace Dalamud.Game.Internal.Gui { else return 74; } else { - if (SearchBuffArray(107)) return 74; - if (SearchBuffArray(108)) return 61; - if (SearchBuffArray(109)) return 56; + if (SearchBuffArray(107) && level >= 50) return 74; + if (SearchBuffArray(108) && level >= 18) return 61; + if (SearchBuffArray(109) && level >= 6) return 56; return 74; } } @@ -702,8 +702,8 @@ namespace Dalamud.Game.Internal.Gui { } else { if (SearchBuffArray(107)) return 53; - if (SearchBuffArray(108)) return 54; - if (SearchBuffArray(109)) return 66; + if (SearchBuffArray(108) && level >= 4) return 54; + if (SearchBuffArray(109) && level >= 30) return 66; return 53; } } @@ -728,9 +728,9 @@ namespace Dalamud.Game.Internal.Gui { if (SearchBuffArray(107)) return 62; if (SearchBuffArray(108)) { if (!SearchBuffArray(101)) return 61; - return 16473; + if (level >= 45) return 16473; } - if (SearchBuffArray(109)) return 70; + if (SearchBuffArray(109) && level >= 30) return 70; return 62; } } @@ -743,12 +743,12 @@ namespace Dalamud.Game.Internal.Gui { // 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; + if ((lastMove == 7526 || lastMove == 7525) && level >= 80) return 16530; + if (lastMove == 7529 && level >= 70) return 7526; + if ((SearchBuffArray(1249) || SearchBuffArray(167)) && level >= 10) return 7507; + if (SearchBuffArray(1235) && level >= 30) return 7511; RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); - if (gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) return 7507; + if ((gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) && level >= 10) return 7507; if (level >= 62) return 7524; return 7503; } @@ -759,27 +759,24 @@ namespace Dalamud.Game.Internal.Gui { // 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; + if ((lastMove == 7526 || lastMove == 7525) && level >= 80) return 16530; + if (lastMove == 7529 && level >= 68) return 7525; + if ((SearchBuffArray(1249) || SearchBuffArray(167)) && level >= 4) return 7505; + if (SearchBuffArray(1234) && level >= 26) return 7510; RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); - if (gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) return 7505; + if ((gauge.BlackGauge == 0 && gauge.WhiteGauge == 0) && level >= 4) 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)) { + // Replace Veraero/thunder 2 with Impact when Dualcast is active + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageAoECombo)) { 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; @@ -790,11 +787,11 @@ namespace Dalamud.Game.Internal.Gui { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageMeleeCombo)) { if (actionID == 7516) { RDMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); - if (lastMove == 7504 || lastMove == 7527) { + if ((lastMove == 7504 || lastMove == 7527) && level >= 35) { if (gauge.BlackGauge >= 25 && gauge.WhiteGauge >= 25) return 7528; return 7512; } - if (lastMove == 7512) { + if (lastMove == 7512 && level >= 50) { if (gauge.BlackGauge >= 25 && gauge.WhiteGauge >= 25) return 7529; return 7516; } From 09c5f0841de62c5c7a349256d48cf089a9d3739c Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 26 Oct 2019 02:11:51 +0900 Subject: [PATCH 12/19] Use 64bit bitmask for CustomComboPreset --- Dalamud/Configuration/CustomComboPreset.cs | 103 +++++++++--------- .../ClientState/Structs/JobGauge/JobEnums.cs | 48 +++++--- 2 files changed, 84 insertions(+), 67 deletions(-) diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs index 42402a6ac..132906fd1 100644 --- a/Dalamud/Configuration/CustomComboPreset.cs +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -9,178 +9,177 @@ namespace XIVLauncher.Dalamud //CURRENT HIGHEST FLAG IS 45 [Flags] - public enum CustomComboPreset + public enum CustomComboPreset : long { None = 0, // DRAGOON [CustomComboInfo("Coerthan Torment Combo", "Replace Coearthan Torment with its combo chain", 22)] - DragoonCoerthanTormentCombo = 1 << 0, + DragoonCoerthanTormentCombo = 1L << 0, [CustomComboInfo("Chaos Thrust Combo", "Replace Chaos Thrust with its combo chain", 22)] - DragoonChaosThrustCombo = 1 << 1, + DragoonChaosThrustCombo = 1L << 1, [CustomComboInfo("Full Thrust Combo", "Replace Full Thrust with its combo chain", 22)] - DragoonFullThrustCombo = 1 << 2, + DragoonFullThrustCombo = 1L << 2, // DARK KNIGHT [CustomComboInfo("Souleater Combo", "Replace Souleater with its combo chain", 32)] - DarkSouleaterCombo = 1 << 3, + DarkSouleaterCombo = 1L << 3, [CustomComboInfo("Stalwart Soul Combo", "Replace Stalwart Soul with its combo chain", 32)] - DarkStalwartSoulCombo = 1 << 4, + DarkStalwartSoulCombo = 1L << 4, // PALADIN [CustomComboInfo("Goring Blade Combo", "Replace Goring Blade with its combo chain", 19)] - PaladinGoringBladeCombo = 1 << 5, + PaladinGoringBladeCombo = 1L << 5, [CustomComboInfo("Royal Authority Combo", "Replace Royal Authority with its combo chain", 19)] - PaladinRoyalAuthorityCombo = 1 << 6, + PaladinRoyalAuthorityCombo = 1L << 6, [CustomComboInfo("Prominence Combo", "Replace Prominence with its combo chain", 19)] - PaladinProminenceCombo = 1 << 7, + PaladinProminenceCombo = 1L << 7, // WARRIOR [CustomComboInfo("Storms Path Combo", "Replace Storms Path with its combo chain", 21)] - WarriorStormsPathCombo = 1 << 8, + WarriorStormsPathCombo = 1L << 8, [CustomComboInfo("Storms Eye Combo", "Replace Storms Eye with its combo chain", 21)] - WarriorStormsEyeCombo = 1 << 9, + WarriorStormsEyeCombo = 1L << 9, [CustomComboInfo("Mythril Tempest Combo", "Replace Mythril Tempest with its combo chain", 21)] - WarriorMythrilTempestCombo = 1 << 10, + WarriorMythrilTempestCombo = 1L << 10, // SAMURAI [CustomComboInfo("Yukikaze Combo", "Replace Yukikaze with its combo chain", 34)] - SamuraiYukikazeCombo = 1 << 11, + SamuraiYukikazeCombo = 1L << 11, [CustomComboInfo("Gekko Combo", "Replace Gekko with its combo chain", 34)] - SamuraiGekkoCombo = 1 << 12, + SamuraiGekkoCombo = 1L << 12, [CustomComboInfo("Kasha Combo", "Replace Kasha with its combo chain", 34)] - SamuraiKashaCombo = 1 << 13, + SamuraiKashaCombo = 1L << 13, [CustomComboInfo("Mangetsu Combo", "Replace Mangetsu with its combo chain", 34)] - SamuraiMangetsuCombo = 1 << 14, + SamuraiMangetsuCombo = 1L << 14, [CustomComboInfo("Oka Combo", "Replace Oka with its combo chain", 34)] - SamuraiOkaCombo = 1 << 15, + SamuraiOkaCombo = 1L << 15, // NINJA [CustomComboInfo("Shadow Fang Combo", "Replace Shadow Fang with its combo chain", 30)] - NinjaShadowFangCombo = 1 << 16, + NinjaShadowFangCombo = 1L << 16, [CustomComboInfo("Armor Crush Combo", "Replace Armor Crush with its combo chain", 30)] - NinjaArmorCrushCombo = 1 << 17, + NinjaArmorCrushCombo = 1L << 17, [CustomComboInfo("Aeolian Edge Combo", "Replace Aeolian Edge with its combo chain", 30)] - NinjaAeolianEdgeCombo = 1 << 18, + NinjaAeolianEdgeCombo = 1L << 18, [CustomComboInfo("Hakke Mujinsatsu Combo", "Replace Hakke Mujinsatsu with its combo chain", 30)] - NinjaHakkeMujinsatsuCombo = 1 << 19, + NinjaHakkeMujinsatsuCombo = 1L << 19, // GUNBREAKER [CustomComboInfo("Solid Barrel Combo", "Replace Solid Barrel with its combo chain", 37)] - GunbreakerSolidBarrelCombo = 1 << 20, + GunbreakerSolidBarrelCombo = 1L << 20, [CustomComboInfo("Gnashing Fang Combo", "Replace Gnashing Fang with its combo chain", 37)] - GunbreakerGnashingFangCombo = 1 << 21, + GunbreakerGnashingFangCombo = 1L << 21, [CustomComboInfo("Demon Slaughter Combo", "Replace Demon Slaughter with its combo chain", 37)] - GunbreakerDemonSlaughterCombo = 1 << 22, + GunbreakerDemonSlaughterCombo = 1L << 22, // MACHINIST [CustomComboInfo("Heated Clan Shot Combo/Heat", "Replace Heated Clan Shot with its combo chain or with Heat Blast when overheated.", 31)] - MachinistHeatedClanShotFeature = 1 << 23, + MachinistHeatedClanShotFeature = 1L << 23, [CustomComboInfo("Spread Shot Heat", "Replace Spread Shot with Heat Blast when overheated.", 31)] - MachinistSpreadShotFeature = 1 << 24, + MachinistSpreadShotFeature = 1L << 24, // BLACK MAGE [CustomComboInfo("Enochian Stance Switcher", "Change Enochian to Fire 4 or Blizzard 4 depending on stance.", 25)] - BlackEnochianFeature = 1 << 25, + BlackEnochianFeature = 1L << 25, [CustomComboInfo("Umbral Soul/Transpose Switcher", "Change between Umbral Soul and Transpose automatically.", 25)] - BlackManaFeature = 1 << 26, + BlackManaFeature = 1L << 26, // ASTROLOGIAN [CustomComboInfo("Cards on Draw", "Play your Astrologian Cards on Draw.", 33)] - AstrologianCardsOnDrawFeature = 1 << 27, + AstrologianCardsOnDrawFeature = 1L << 27, // SUMMONER [CustomComboInfo("Dreadwyrm Combiner", "Now comes with Dreadwyrm Trance, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix.", 27)] - SummonerDwtCombo = 1 << 28, + SummonerDwtCombo = 1L << 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, + SummonerBoPCombo = 1L << 38, [CustomComboInfo("ED Fester", "Change Energy Drain into Fester while you have Aetherflow stacks.", 27)] - SummonerEDFesterCombo = 1 << 39, + SummonerEDFesterCombo = 1L << 39, [CustomComboInfo("ES Painflare", "Change Energy Siphon into Painflare while you have Aetherflow stacks.", 27)] - SummonerESPainflareCombo = 1 << 40, + SummonerESPainflareCombo = 1L << 40, // SCHOLAR [CustomComboInfo("Seraph Fey Blessing/Consolation", "Change Fey Blessing into Consolation when Seraph is out.", 28)] - ScholarSeraphConsolationFeature = 1 << 29, + ScholarSeraphConsolationFeature = 1L << 29, [CustomComboInfo("ED Aetherflow", "Change Energy Drain into Aetherflow when you have no more Aetherflow stacks.", 28)] - ScholarEnergyDrainFeature = 1 << 37, + ScholarEnergyDrainFeature = 1L << 37, // DANCER [CustomComboInfo("Standard Step Combo", "Standard Step on one button.", 38)] - DancerStandardStepCombo = 1 << 30, + DancerStandardStepCombo = 1L << 30, [CustomComboInfo("Technical Step Combo", "Technical Step on one button.", 38)] - DancerTechnicalStepCombo = 1 << 31, + DancerTechnicalStepCombo = 1L << 31, [CustomComboInfo("AoE GCD procs", "Replaces all AoE GCDs with their procced version when available.", 38)] - DancerAoeGcdFeature = 1 << 32, + DancerAoeGcdFeature = 1L << 32, [CustomComboInfo("Fan Dance Combos", "Change Fan Dance and Fan Dance 2 into Fan Dance 3 while flourishing.", 38)] - DancerFanDanceCombo = 1 << 33, + DancerFanDanceCombo = 1L << 33, [CustomComboInfo("Fountain Combos", "Fountain changes into Fountain combo, prioritizing procs over combo, and Fountainfall over Reverse Cascade.", 38)] - DancerFountainCombo = 1 << 34, + DancerFountainCombo = 1L << 34, // WHITE MAGE [CustomComboInfo("Solace into Misery", "Replaces Afflatus Solace with Afflatus Misery when Misery is ready to be used.", 24)] - WhiteMageSolaceMiseryFeature = 1 << 35, + WhiteMageSolaceMiseryFeature = 1L << 35, [CustomComboInfo("Rapture into Misery", "Replaces Afflatus Rapture with Afflatus Misery when Misery is ready to be used.", 24)] - WhiteMageRaptureMiseryFeature = 1 << 36, + WhiteMageRaptureMiseryFeature = 1L << 36, // BARD [CustomComboInfo("Wanderer's into Pitch Perfect", "Replaces Wanderer's Minuet with Pitch Perfect while in WM.", 23)] - BardWandererPPFeature = 1 << 41, + BardWandererPPFeature = 1L << 41, [CustomComboInfo("Heavy Shot into Straight Shot", "Replaces Heavy Shot/Burst Shot with Straight Shot/Refulgent Arrow when procced.", 23)] - BardStraightShotUpgradeFeature = 1 << 42, + BardStraightShotUpgradeFeature = 1L << 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, + MonkFlankCombo = 1L << 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, + MonkRearCombo = 1L << 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, + MonkAoECombo = 1L << 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, + RedMageWhiteMagicFeature = 1L << 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, + RedMageBlackMagicFeature = 1L << 47, [CustomComboInfo("Red Mage AoE Combo", "Replaces Veraero/thunder 2 with Impact when Dualcast or Swiftcast are active.", 35)] - RedMageAoECombo = 1 << 48, + RedMageAoECombo = 1L << 48, [CustomComboInfo("Redoublement combo", "Replaces Redoublement with its combo chain, following enchantment rules.", 35)] - RedMageMeleeCombo = 1 << 49 - + RedMageMeleeCombo = 1L << 49 } public class CustomComboInfoAttribute : Attribute diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs index a411b367e..c2252c8b3 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs @@ -1,25 +1,36 @@ 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 + NONE = 0, + SUN, + MOON, + CELESTIAL } + public enum CardType : byte { - NONE = 0, BALANCE, BOLE, ARROW, SPEAR, EWER, SPIRE, - LORD = 0x70, LADY = 0x80 + NONE = 0, + BALANCE, + BOLE, + ARROW, + SPEAR, + EWER, + SPIRE, + LORD = 0x70, + LADY = 0x80 } public enum SummonPet : byte { - IFRIT = 3, TITAN, GARUDA + IFRIT = 3, + TITAN, + GARUDA } public enum PetGlam : byte { - NONE = 0, EMERALD, TOPAZ, RUBY + NONE = 0, + EMERALD, + TOPAZ, + RUBY } [Flags] @@ -27,22 +38,29 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { NONE = 0, SETSU = 1 << 0, GETSU = 1 << 1, - KA = 1 << 2, + KA = 1 << 2 } public enum BOTDState : byte { - NONE = 0, BOTD, LOTD + NONE = 0, + BOTD, + LOTD } public enum CurrentSong : byte { - MAGE = 5, ARMY = 0xA, WANDERER = 0xF + MAGE = 5, + ARMY = 0xA, + WANDERER = 0xF } public enum DismissedFairy : byte { - EOS = 6, SELENE + EOS = 6, + SELENE } public enum Mudras : byte { - TEN = 1, CHI = 2, JIN = 3 + TEN = 1, + CHI = 2, + JIN = 3 } } From 58b5401e90268cac0cbfdde9d9092bbc8802dff6 Mon Sep 17 00:00:00 2001 From: attick Date: Fri, 25 Oct 2019 20:35:53 -0400 Subject: [PATCH 13/19] Fix Enochian, prep for 5.1 changes. --- Dalamud/Configuration/CustomComboPreset.cs | 8 ++-- .../ClientState/Structs/JobGauge/BLMGauge.cs | 6 ++- .../ClientState/Structs/JobGauge/DRKGauge.cs | 6 ++- .../ClientState/Structs/JobGauge/MNKGauge.cs | 6 ++- Dalamud/Game/Internal/Gui/IconReplacer.cs | 37 ++++++++++--------- 5 files changed, 37 insertions(+), 26 deletions(-) diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs index 132906fd1..c4b0ca053 100644 --- a/Dalamud/Configuration/CustomComboPreset.cs +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -7,14 +7,14 @@ using System.Threading.Tasks; namespace XIVLauncher.Dalamud { - //CURRENT HIGHEST FLAG IS 45 + //CURRENT HIGHEST FLAG IS 44 [Flags] public enum CustomComboPreset : long { None = 0, // DRAGOON - [CustomComboInfo("Coerthan Torment Combo", "Replace Coearthan Torment with its combo chain", 22)] + [CustomComboInfo("Coerthan Torment Combo", "Replace Coerthan Torment with its combo chain", 22)] DragoonCoerthanTormentCombo = 1L << 0, [CustomComboInfo("Chaos Thrust Combo", "Replace Chaos Thrust with its combo chain", 22)] @@ -68,8 +68,6 @@ namespace XIVLauncher.Dalamud // NINJA - [CustomComboInfo("Shadow Fang Combo", "Replace Shadow Fang with its combo chain", 30)] - NinjaShadowFangCombo = 1L << 16, [CustomComboInfo("Armor Crush Combo", "Replace Armor Crush with its combo chain", 30)] NinjaArmorCrushCombo = 1L << 17, @@ -166,7 +164,7 @@ namespace XIVLauncher.Dalamud MonkRearCombo = 1L << 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 = 1L << 45, + MonkAoECombo = 1L << 16, // RED MAGE [CustomComboInfo("One-button White Magic", "Replaces Verstone with the following priority: Scorch > Verholy > Dual/Swiftcast Veraero > Verstone proc > Opener Veraero > Jolt.", 35)] diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs index a46a03553..8bbb74610 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs @@ -14,7 +14,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [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? + [FieldOffset(7)] private byte EnoState; //eno active? public bool InUmbralIce() { return ElementStance > 4; @@ -24,6 +24,10 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { return ElementStance > 0 && ElementStance < 4; } + public bool IsEnoActive() { + return EnoState > 0; + } + } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs index 0d160713a..052b4e8ed 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs @@ -10,7 +10,11 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { public struct DRKGauge { [FieldOffset(0)] public short Blood; [FieldOffset(2)] public short DarksideTimeRemaining; - [FieldOffset(4)] public bool HasDarkArts; + [FieldOffset(4)] private byte DarkArtsState; [FieldOffset(6)] public short ShadowTimeRemaining; + + public bool HasDarkArts() { + return DarkArtsState > 0; + } } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs index 5741f3d7c..0d40ee780 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs @@ -12,6 +12,10 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { [FieldOffset(0)] public byte GLTimer; [FieldOffset(2)] public byte NumGLStacks; [FieldOffset(3)] public byte NumChakra; - [FieldOffset(4)] public bool IsGLTimerFrozen; + [FieldOffset(4)] private byte GLTimerFreezeState; + + public bool IsGLTimerFroze() { + return GLTimerFreezeState > 0; + } } } diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 2deb6528a..032c021d4 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -193,7 +193,10 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 3539) { if (comboTime > 0) { if (lastMove == 9 && level >= 4) return 15; - if (lastMove == 15 && level >= 60) return 3539; + if (lastMove == 15) { + if (level >= 60) return 3539; + if (level >= 26) return 21; + } } return 9; @@ -307,16 +310,6 @@ namespace Dalamud.Game.Internal.Gui { // NINJA - // Replace Shadow Fang with Shadow Fang combo - if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaShadowFangCombo)) { - if (actionID == 2257) { - if (comboTime > 0) { - if (lastMove == 2240 && level >= 30) return 2257; - } - return 2240; - } - } - // Replace Armor Crush with Armor Crush combo if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) { if (actionID == 3563) { @@ -392,8 +385,14 @@ namespace Dalamud.Game.Internal.Gui { if (actionID == 7413) { if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 35) return 7410; if (comboTime > 0) { - if (lastMove == 2866 && level >= 2) return 7412; - if (lastMove == 2868 && level >= 26) return 7413; + if (lastMove == 2866) { + if (level >= 60) return 7412; + if (level >= 2) return 2868; + } + if (lastMove == 2868) { + if (level >= 64) return 7413; + if (level >= 26) return 2873; + } } return 7411; } @@ -410,11 +409,10 @@ 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(); - if (jobInfo.IsEnoActive) { + if (jobInfo.IsEnoActive()) { if (jobInfo.InUmbralIce() && level >= 58) return 3576; if (level >= 60) return 3577; } @@ -425,7 +423,8 @@ namespace Dalamud.Game.Internal.Gui { // Umbral Soul and Transpose if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackManaFeature)) { if (actionID == 149) { - if (this.dalamud.ClientState.JobGauges.Get().InUmbralIce() && level >= 76) return 16506; + BLMGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.InUmbralIce() && gauge.IsEnoActive() && level >= 76) return 16506; return 149; } } @@ -449,10 +448,12 @@ namespace Dalamud.Game.Internal.Gui { return 4405; case CardType.SPIRE: return 4406; + /* case CardType.LORD: return 7444; case CardType.LADY: return 7445; + */ default: return 3590; } @@ -710,7 +711,7 @@ namespace Dalamud.Game.Internal.Gui { } // Replace Rockbreaker with AoE combo. - // During PB, RB (with sub-max stacks) > Twin Snakes (if not applied) > AotD. + // During PB, RB (with sub-max stacks) > Twin Snakes (if not applied) > RB. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MonkAoECombo)) { if (actionID == 70) { if (SearchBuffArray(110)) { @@ -722,7 +723,7 @@ namespace Dalamud.Game.Internal.Gui { return 70; } else if (!SearchBuffArray(101)) return 61; - else return 62; + else return 70; } else { if (SearchBuffArray(107)) return 62; From 70ddb95f529016d8a8d8f24a0e57cc9a8473801d Mon Sep 17 00:00:00 2001 From: attick Date: Fri, 25 Oct 2019 20:44:29 -0400 Subject: [PATCH 14/19] Wiki message --- Dalamud/Configuration/CustomComboPreset.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs index c4b0ca053..af5b010b8 100644 --- a/Dalamud/Configuration/CustomComboPreset.cs +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -163,7 +163,7 @@ namespace XIVLauncher.Dalamud [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 = 1L << 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)] + [CustomComboInfo("Rockbreaker Combo", "Replaces Rockbreaker according to stance. When PB is active, prefer RB (with non-max GL) > Twin Snakes (with no TS active) > RB.", 20)] MonkAoECombo = 1L << 16, // RED MAGE From 2828d096a7e6b69525fb11ea77855fcc46f79205 Mon Sep 17 00:00:00 2001 From: attick Date: Mon, 28 Oct 2019 16:30:09 -0400 Subject: [PATCH 15/19] Separate SMN a bit. Ready for 5.1 release. --- Dalamud/Configuration/CustomComboPreset.cs | 34 +++------------ .../ClientState/Structs/JobGauge/JobEnums.cs | 1 + .../ClientState/Structs/JobGauge/SMNGauge.cs | 4 +- Dalamud/Game/Internal/Gui/IconReplacer.cs | 42 +++++++++++++++++-- 4 files changed, 46 insertions(+), 35 deletions(-) diff --git a/Dalamud/Configuration/CustomComboPreset.cs b/Dalamud/Configuration/CustomComboPreset.cs index af5b010b8..903563642 100644 --- a/Dalamud/Configuration/CustomComboPreset.cs +++ b/Dalamud/Configuration/CustomComboPreset.cs @@ -68,7 +68,6 @@ namespace XIVLauncher.Dalamud // NINJA - [CustomComboInfo("Armor Crush Combo", "Replace Armor Crush with its combo chain", 30)] NinjaArmorCrushCombo = 1L << 17, @@ -92,7 +91,7 @@ namespace XIVLauncher.Dalamud [CustomComboInfo("Heated Clan Shot Combo/Heat", "Replace Heated Clan Shot with its combo chain or with Heat Blast when overheated.", 31)] MachinistHeatedClanShotFeature = 1L << 23, - [CustomComboInfo("Spread Shot Heat", "Replace Spread Shot with Heat Blast when overheated.", 31)] + [CustomComboInfo("Spread Shot Heat", "Replace Spread Shot with Auto Crossbow when overheated.", 31)] MachinistSpreadShotFeature = 1L << 24, // BLACK MAGE @@ -103,12 +102,12 @@ namespace XIVLauncher.Dalamud BlackManaFeature = 1L << 26, // ASTROLOGIAN - [CustomComboInfo("Cards on Draw", "Play your Astrologian Cards on Draw.", 33)] + [CustomComboInfo("Draw on Play", "Play turns into Draw when no card is drawn, as well as the usual Play behavior.", 33)] AstrologianCardsOnDrawFeature = 1L << 27, // SUMMONER - [CustomComboInfo("Dreadwyrm Combiner", "Now comes with Dreadwyrm Trance, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix.", 27)] - SummonerDwtCombo = 1L << 28, + [CustomComboInfo("Demi-summon combiners", "Dreadwyrm Trance, Summon Bahamut, and Firebird Trance are now one button. Deathflare, Enkindle Bahamut, and Enkindle Phoenix are now one button.", 27)] + SummonerDemiCombo = 1L << 28, [CustomComboInfo("Brand of Purgatory Combo", "Replaces Fountain of Fire with Brand of Purgatory when under the affect of Hellish Conduit.", 27)] SummonerBoPCombo = 1L << 38, @@ -127,21 +126,12 @@ namespace XIVLauncher.Dalamud ScholarEnergyDrainFeature = 1L << 37, // DANCER - [CustomComboInfo("Standard Step Combo", "Standard Step on one button.", 38)] - DancerStandardStepCombo = 1L << 30, - - [CustomComboInfo("Technical Step Combo", "Technical Step on one button.", 38)] - DancerTechnicalStepCombo = 1L << 31, - [CustomComboInfo("AoE GCD procs", "Replaces all AoE GCDs with their procced version when available.", 38)] DancerAoeGcdFeature = 1L << 32, [CustomComboInfo("Fan Dance Combos", "Change Fan Dance and Fan Dance 2 into Fan Dance 3 while flourishing.", 38)] DancerFanDanceCombo = 1L << 33, - [CustomComboInfo("Fountain Combos", "Fountain changes into Fountain combo, prioritizing procs over combo, and Fountainfall over Reverse Cascade.", 38)] - DancerFountainCombo = 1L << 34, - // WHITE MAGE [CustomComboInfo("Solace into Misery", "Replaces Afflatus Solace with Afflatus Misery when Misery is ready to be used.", 24)] WhiteMageSolaceMiseryFeature = 1L << 35, @@ -157,22 +147,8 @@ namespace XIVLauncher.Dalamud BardStraightShotUpgradeFeature = 1L << 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 = 1L << 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 = 1L << 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) > RB.", 20)] - MonkAoECombo = 1L << 16, - + // 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 = 1L << 46, - - [CustomComboInfo("One-button Black Magic", "Replaces Verfire with the following priority: Scorch > Verflare > Dual/Swiftcast Verthunder > Verfire proc > Opener Verthunder > Jolt.", 35)] - RedMageBlackMagicFeature = 1L << 47, - [CustomComboInfo("Red Mage AoE Combo", "Replaces Veraero/thunder 2 with Impact when Dualcast or Swiftcast are active.", 35)] RedMageAoECombo = 1L << 48, diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs index c2252c8b3..69762e295 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs @@ -21,6 +21,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { } public enum SummonPet : byte { + NONE = 0, IFRIT = 3, TITAN, GARUDA diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs index 89f22fe9c..1742f4d97 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs @@ -12,8 +12,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge { //Unfinished [FieldOffset(0)] public short TimerRemaining; - [FieldOffset(2)] public byte ReturnSummon; - [FieldOffset(3)] public byte ReturnSummonGlam; + [FieldOffset(2)] public SummonPet ReturnSummon; + [FieldOffset(3)] public PetGlam ReturnSummonGlam; [FieldOffset(4)] public byte NumStacks; public bool IsPhoenixReady() { diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 032c021d4..751a811ac 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -383,7 +383,9 @@ namespace Dalamud.Game.Internal.Gui { // For some reason the shots use their unheated IDs as combo moves if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.MachinistHeatedClanShotFeature)) { if (actionID == 7413) { - if (this.dalamud.ClientState.JobGauges.Get().IsOverheated() && level >= 35) return 7410; + MCHGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + // End overheat slightly early to prevent eager button mashing clipping your gcd with a fake 6th HB. + if (gauge.IsOverheated() && level >= 35 && gauge.OverheatTimeRemaining > 30) return 7410; if (comboTime > 0) { if (lastMove == 2866) { if (level >= 60) return 7412; @@ -465,6 +467,7 @@ namespace Dalamud.Game.Internal.Gui { // DWT changes. // Now contains DWT, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix. // What a monster of a button. + /* if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDwtCombo)) { if (actionID == 3581) { SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get(); @@ -482,6 +485,26 @@ namespace Dalamud.Game.Internal.Gui { } } } + */ + + if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDemiCombo)) { + // Replace Deathflare with demi enkindles + if (actionID == 3582) { + SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.IsPhoenixReady()) return 16516; + if (gauge.TimerRemaining > 0 && gauge.ReturnSummon != SummonPet.NONE) return 7429; + return 3582; + } + + //Replace DWT with demi summons + if (actionID == 3581) { + SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get(); + if (gauge.IsBahamutReady()) return 7427; + if (gauge.IsPhoenixReady() || + (gauge.TimerRemaining > 0 && gauge.ReturnSummon != SummonPet.NONE)) 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)) { @@ -538,6 +561,8 @@ namespace Dalamud.Game.Internal.Gui { // DANCER + /* + // Standard Step is one button. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerStandardStepCombo)) { if (actionID == 15997) { @@ -586,6 +611,8 @@ namespace Dalamud.Game.Internal.Gui { } } + */ + // AoE GCDs are split into two buttons, because priority matters // differently in different single-target moments. Thanks yoship. // Replaces each GCD with its procced version. @@ -601,9 +628,8 @@ namespace Dalamud.Game.Internal.Gui { } } - + // Fan Dance changes into Fan Dance 3 while flourishing. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFanDanceCombo)) { - // Fan Dance changes into Fan Dance 3 while flourishing. if (actionID == 16007) { if (SearchBuffArray(1820)) return 16009; @@ -663,6 +689,8 @@ namespace Dalamud.Game.Internal.Gui { // 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)) { @@ -737,8 +765,12 @@ namespace Dalamud.Game.Internal.Gui { } } + */ + // 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. @@ -770,7 +802,7 @@ namespace Dalamud.Game.Internal.Gui { return 7503; } } - + */ // Replace Veraero/thunder 2 with Impact when Dualcast is active if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageAoECombo)) { if (actionID == 16525) { @@ -784,6 +816,8 @@ namespace Dalamud.Game.Internal.Gui { } } + + // Replace Redoublement with Redoublement combo, Enchanted if possible. if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.RedMageMeleeCombo)) { if (actionID == 7516) { From 4ad5bee0c62128315b0a247466d28f42264c3069 Mon Sep 17 00:00:00 2001 From: attick Date: Tue, 29 Oct 2019 20:08:29 -0400 Subject: [PATCH 16/19] Update addresses and signatures for 5.1. --- Dalamud/Dalamud.cs | 2 +- .../ClientState/ClientStateAddressResolver.cs | 2 +- .../Game/ClientState/Structs/JobGauge/DRKGauge.cs | 2 +- Dalamud/Game/Internal/Gui/IconReplacer.cs | 15 +++++++++------ .../Internal/Gui/IconReplacerAddressResolver.cs | 4 ++-- 5 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 98708a4c5..589b5093e 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -73,7 +73,7 @@ namespace Dalamud { this.PluginManager = new PluginManager(this, info.PluginDirectory, info.DefaultPluginDirectory); this.IconReplacer = new IconReplacer(this, this.sigScanner); - + try { this.PluginManager.LoadPlugins(); } catch (Exception ex) { diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index 01a54a7c8..afe8ef25d 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 + 0x1B2D4C0; + JobGaugeData = sig.Module.BaseAddress + 0x1BFD110; } } } diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs index 052b4e8ed..5c711cf57 100644 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs +++ b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace Dalamud.Game.ClientState.Structs.JobGauge { [StructLayout(LayoutKind.Explicit)] public struct DRKGauge { - [FieldOffset(0)] public short Blood; + [FieldOffset(0)] public byte Blood; [FieldOffset(2)] public short DarksideTimeRemaining; [FieldOffset(4)] private byte DarkArtsState; [FieldOffset(6)] public short ShadowTimeRemaining; diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 751a811ac..7f89b401c 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -32,8 +32,8 @@ namespace Dalamud.Game.Internal.Gui { this.Address.Setup(scanner); this.byteBase = scanner.Module.BaseAddress; - this.comboTimer = byteBase + 0x1AE1B10; - this.lastComboMove = byteBase + 0x1AE1B14; + this.comboTimer = byteBase + 0x1BB5B50; + this.lastComboMove = byteBase + 0x1BB5B54; Log.Verbose("===== H O T B A R S ====="); Log.Verbose("IsIconReplaceable address {IsIconReplaceable}", Address.IsIconReplaceable); @@ -85,8 +85,9 @@ namespace Dalamud.Game.Internal.Gui { } } - // TODO: Update localCharacter without destroying the log with debug messages + // TODO: this is currently broken // As it stands, don't rely on localCharacter.level for anything. + /* if (localCharacter == null) { try { localCharacter = dalamud.ClientState.LocalPlayer; @@ -96,12 +97,14 @@ namespace Dalamud.Game.Internal.Gui { 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); - localCharacter = dalamud.ClientState.LocalPlayer; - byte level = localCharacter.Level; + //localCharacter = dalamud.ClientState.LocalPlayer; + //byte level = localCharacter.Level; + byte level = 80; // DRAGOON // TODO: Jump/High Jump into Mirage Dive @@ -848,7 +851,7 @@ namespace Dalamud.Game.Internal.Gui { private unsafe delegate int* getArray(long* address); private unsafe IntPtr FindBuffAddress() { - IntPtr randomAddress = byteBase + 0x1b2c970; + IntPtr randomAddress = byteBase + 0x1c04be0; IntPtr num = Marshal.ReadIntPtr(randomAddress); IntPtr step2 = (IntPtr)(Marshal.ReadInt64(num) + 0x248); IntPtr step3 = Marshal.ReadIntPtr(step2); diff --git a/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs b/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs index 77e8a5859..dd84a7bfb 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacerAddressResolver.cs @@ -10,8 +10,8 @@ namespace Dalamud.Game.Internal.Gui { public IntPtr IsIconReplaceable { get; private set; } protected override void Setup64Bit(SigScanner sig) { - this.GetIcon = sig.ScanText("81 fa d4 08 00 00 7f 4b 74 44 8d 42 eb 3d a3 00 00 00"); - this.IsIconReplaceable = sig.ScanText("81 f9 d4 08 00 00 7f 33 0f 84 fa 01 00 00 83 c1 eb 81 f9 a3 00 00 00"); + this.GetIcon = sig.ScanText("48 89 5c 24 08 48 89 6c 24 10 48 89 74 24 18 57 48 83 ec 30 8b da be dd 1c 00 00 bd d3 0d 00 00"); + this.IsIconReplaceable = sig.ScanText("81 f9 2e 01 00 00 7f 39 81 f9 2d 01 00 00 0f 8d 11 02 00 00 83 c1 eb"); } } } From 545757d40657746c2a825b4e0bbbc6fc58623e02 Mon Sep 17 00:00:00 2001 From: goat Date: Fri, 1 Nov 2019 16:30:53 +0900 Subject: [PATCH 17/19] Update for 5.1 --- Dalamud/Dalamud.cs | 11 ++-- Dalamud/Dalamud.csproj | 2 +- .../ClientState/ClientStateAddressResolver.cs | 4 +- Dalamud/Game/ClientState/Structs/Actor.cs | 16 +++--- .../Internal/Gui/ChatGuiAddressResolver.cs | 11 +++- Dalamud/Game/Internal/Gui/IconReplacer.cs | 11 ++-- Dalamud/Game/Internal/Gui/TargetManager.cs | 55 +++++++++++++++++++ .../Gui/TargetManagerAddressResolver.cs | 15 +++++ .../Network/GameNetworkAddressResolver.cs | 3 +- 9 files changed, 100 insertions(+), 28 deletions(-) create mode 100644 Dalamud/Game/Internal/Gui/TargetManager.cs create mode 100644 Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 589b5093e..52ec31e1c 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -158,8 +158,8 @@ namespace Dalamud { HelpMessage = "Unmute a word or sentence. Usage: /fatewatchremove " }); - CommandManager.AddHandler("/xldactortable", new CommandInfo(OnDebugActorTable) { - HelpMessage = "Actor table operations", + CommandManager.AddHandler("/xldstate", new CommandInfo(OnDebugPrintGameState) { + HelpMessage = "Print parsed game state", ShowInHelp = false }); @@ -318,11 +318,13 @@ namespace Dalamud { Process.Start(ChatHandlers.LastLink); } - private void OnDebugActorTable(string command, string arguments) { + private void OnDebugPrintGameState(string command, string arguments) { Framework.Gui.Chat.Print(this.ClientState.Actors.Length + " entries"); Framework.Gui.Chat.Print(this.ClientState.LocalPlayer.Name); Framework.Gui.Chat.Print(this.ClientState.LocalPlayer.CurrentWorld.Name); + Framework.Gui.Chat.Print(this.ClientState.LocalPlayer.HomeWorld.Name); Framework.Gui.Chat.Print(this.ClientState.LocalContentId.ToString("X")); + Framework.Gui.Chat.Print(Framework.Gui.Chat.LastLinkedItemId.ToString()); for (var i = 0; i < this.ClientState.Actors.Length; i++) { var actor = this.ClientState.Actors[i]; @@ -369,7 +371,6 @@ namespace Dalamud { continue; this.Configuration.ComboPresets |= value; - Framework.Gui.Chat.Print(argumentsParts[1] + " SET"); } } break; @@ -379,7 +380,6 @@ namespace Dalamud { continue; this.Configuration.ComboPresets ^= value; - Framework.Gui.Chat.Print(argumentsParts[1] + " TOGGLE"); } } break; @@ -390,7 +390,6 @@ namespace Dalamud { continue; this.Configuration.ComboPresets &= ~value; - Framework.Gui.Chat.Print(argumentsParts[1] + " UNSET"); } } break; diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index b14a0da76..d96583d65 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -21,7 +21,7 @@ - E:\Sapphire\recorder\FFXIV.Recorder\/bin\Dalamud.xml + E:\Sapphire\recorder\FFXIV.Recorder\/bin\Dalamud.xml diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs index afe8ef25d..885f0b31e 100644 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs @@ -13,8 +13,8 @@ namespace Dalamud.Game.ClientState public IntPtr JobGaugeData { get; set; } protected override void Setup64Bit(SigScanner sig) { - ActorTable = sig.Module.BaseAddress + 0x1B29B40; - LocalContentId = sig.Module.BaseAddress + 0x1B58B60; + ActorTable = sig.Module.BaseAddress + 0x1C01D90; + LocalContentId = sig.Module.BaseAddress + 0x1C2E000; JobGaugeData = sig.Module.BaseAddress + 0x1BFD110; } } diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs index 3e1d9ac7c..4dff763c7 100644 --- a/Dalamud/Game/ClientState/Structs/Actor.cs +++ b/Dalamud/Game/ClientState/Structs/Actor.cs @@ -20,13 +20,13 @@ namespace Dalamud.Game.ClientState.Structs [FieldOffset(140)] public ObjectKind ObjectKind; [FieldOffset(141)] public byte SubKind; [FieldOffset(160)] public Position3 Position; - [FieldOffset(6296)] public byte CurrentWorld; - [FieldOffset(6298)] public byte HomeWorld; - [FieldOffset(6308)] public int CurrentHp; - [FieldOffset(6312)] public int MaxHp; - [FieldOffset(6316)] public int CurrentMp; - [FieldOffset(6320)] public int MaxMp; - [FieldOffset(6364)] public byte ClassJob; - [FieldOffset(6366)] public byte Level; + [FieldOffset(6308)] public byte CurrentWorld; + [FieldOffset(6310)] public byte HomeWorld; + [FieldOffset(6328)] public int CurrentHp; + [FieldOffset(6332)] public int MaxHp; + [FieldOffset(6336)] public int CurrentMp; + [FieldOffset(6340)] public int MaxMp; + [FieldOffset(6388)] public byte ClassJob; + [FieldOffset(6390)] public byte Level; } } diff --git a/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs index 67478e423..0516fce54 100644 --- a/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs +++ b/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs @@ -76,13 +76,18 @@ namespace Dalamud.Game.Internal.Gui { */ protected override void Setup64Bit(SigScanner sig) { - PrintMessage = sig.ScanText("4055 57 41 ?? 41 ?? 488DAC24D8FEFFFF 4881EC28020000 488B05???????? 4833C4 488985F0000000 4532D2 48894C2448"); + //PrintMessage = sig.ScanText("4055 57 41 ?? 41 ?? 488DAC24D8FEFFFF 4881EC28020000 488B05???????? 4833C4 488985F0000000 4532D2 48894C2448"); LAST PART FOR 5.1??? + PrintMessage = + sig.ScanText( + "4055 57 41 ?? 41 ?? 4157488DAC24E0FE FFFF4881EC2002 0000488B05???? ????48 33C4488985F000 000045 32D248894C2448"); //PrintMessage = sig.ScanText("4055 57 41 ?? 41 ?? 488DAC24E8FEFFFF 4881EC18020000 488B05???????? 4833C4 488985E0000000 4532D2 48894C2438"); old - + //PrintMessage = sig.ScanText("40 55 57 41 56 41 57 48 8D AC 24 D8 FE FF FF 48 81 EC 28 02 00 00 48 8B 05 63 47 4A 01 48 33 C4 48 89 85 F0 00 00 00 45 32 D2 48 89 4C 24 48 33"); //PopulateItemLinkObject = sig.ScanText("48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 FA F2 B0 FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); - PopulateItemLinkObject = sig.ScanText("48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 ?? ?? B0 FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); + + //PopulateItemLinkObject = sig.ScanText("48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 ?? ?? B0 FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); 5.0 + PopulateItemLinkObject = sig.ScanText("48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 7A 12 AF FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); } } } diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 7f89b401c..069af81a8 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -87,7 +87,6 @@ namespace Dalamud.Game.Internal.Gui { // TODO: this is currently broken // As it stands, don't rely on localCharacter.level for anything. - /* if (localCharacter == null) { try { localCharacter = dalamud.ClientState.LocalPlayer; @@ -97,14 +96,12 @@ namespace Dalamud.Game.Internal.Gui { 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); - //localCharacter = dalamud.ClientState.LocalPlayer; - //byte level = localCharacter.Level; - byte level = 80; + var lastMove = Marshal.ReadInt32(this.lastComboMove); + var comboTime = Marshal.ReadInt32(this.comboTimer); + this.localCharacter = this.dalamud.ClientState.LocalPlayer; + var level = this.localCharacter.Level; // DRAGOON // TODO: Jump/High Jump into Mirage Dive diff --git a/Dalamud/Game/Internal/Gui/TargetManager.cs b/Dalamud/Game/Internal/Gui/TargetManager.cs new file mode 100644 index 000000000..a6a1c45ee --- /dev/null +++ b/Dalamud/Game/Internal/Gui/TargetManager.cs @@ -0,0 +1,55 @@ +using Dalamud.Game.ClientState; +using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Structs.JobGauge; +using Dalamud.Hooking; +using Serilog; +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using XIVLauncher.Dalamud; + +namespace Dalamud.Game.Internal.Gui { + public class TargetManager { + public delegate IntPtr GetTargetDelegate(IntPtr manager); + + private Hook getTargetHook; + + private TargetManagerAddressResolver Address; + + public unsafe TargetManager(Dalamud dalamud, SigScanner scanner) { + this.Address = new TargetManagerAddressResolver(); + this.Address.Setup(scanner); + + Log.Verbose("===== T A R G E T M A N A G E R ====="); + Log.Verbose("GetTarget address {GetTarget}", Address.GetTarget); + + this.getTargetHook = new Hook(this.Address.GetTarget, new GetTargetDelegate(GetTargetDetour), this); + } + + public void Enable() { + this.getTargetHook.Enable(); + } + + public void Dispose() { + this.getTargetHook.Dispose(); + } + + private IntPtr GetTargetDetour(IntPtr manager) + { + try { + var res = this.getTargetHook.Original(manager); + + var test = Marshal.ReadInt32(res); + + Log.Debug($"GetTargetDetour {manager.ToInt64():X} -> RET: {res:X}"); + + return res; + } + catch (Exception ex) + { + Log.Error(ex, "Exception GetTargetDetour hook."); + return this.getTargetHook.Original(manager); + } + } + } +} diff --git a/Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs b/Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs new file mode 100644 index 000000000..137742bc0 --- /dev/null +++ b/Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Dalamud.Game.Internal.Gui { + class TargetManagerAddressResolver : BaseAddressResolver { + public IntPtr GetTarget { get; private set; } + + protected override void Setup64Bit(SigScanner sig) { + this.GetTarget = sig.ScanText("40 57 48 83 EC 40 48 8B F9 48 8B 49 08 48 8B 01 FF 50 40 66 83 B8 CA 81 00 00 00 74 33 48 8B 4F 08 48 8B 01 FF 50 40 66 83 B8 CA 81 00 00 04 74"); + } + } +} diff --git a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs index 08868c3a4..02f76e865 100644 --- a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs +++ b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs @@ -5,7 +5,8 @@ namespace Dalamud.Game.Internal.Network { public IntPtr ProcessZonePacket { get; private set; } protected override void Setup64Bit(SigScanner sig) { - ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05"); + //ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05"); + ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 73 FF 0F B7 57 02 8D 42 ?? 3D ?? ?? 00 00 0F 87 60 01 00 00 4C 8D 05"); } } } From 6b5f8e6bed3f6c112f3297f11c06283a15b2daf9 Mon Sep 17 00:00:00 2001 From: goat Date: Sat, 2 Nov 2019 14:35:48 +0900 Subject: [PATCH 18/19] Don't try to do italics on messages with SE opcodes --- Dalamud.Injector/Program.cs | 2 +- Dalamud/Game/ChatHandlers.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dalamud.Injector/Program.cs b/Dalamud.Injector/Program.cs index dfa91a07f..75c0a8a75 100644 --- a/Dalamud.Injector/Program.cs +++ b/Dalamud.Injector/Program.cs @@ -19,7 +19,7 @@ namespace Dalamud.Injector { Process.GetCurrentProcess().Kill(); }; - int pid = int.Parse(args[0]); + var pid = int.Parse(args[0]); Process process = null; diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs index 158527216..4005107a4 100644 --- a/Dalamud/Game/ChatHandlers.cs +++ b/Dalamud/Game/ChatHandlers.cs @@ -92,8 +92,8 @@ namespace Dalamud.Game { .GetResult()); - if (this.HandledChatTypeColors.ContainsKey(type) || type == XivChatType.Say || type == XivChatType.Shout || - type == XivChatType.Alliance || type == XivChatType.TellOutgoing || type == XivChatType.Yell) { + if ((this.HandledChatTypeColors.ContainsKey(type) || type == XivChatType.Say || type == XivChatType.Shout || + type == XivChatType.Alliance || type == XivChatType.TellOutgoing || type == XivChatType.Yell) && !message.Contains((char)0x02)) { var italicsStart = message.IndexOf("*"); var italicsEnd = message.IndexOf("*", italicsStart + 1); From 75ed54117ccaf52ca0effb2644dd584620cdf716 Mon Sep 17 00:00:00 2001 From: goat Date: Sun, 3 Nov 2019 21:17:47 +0900 Subject: [PATCH 19/19] Some changes to Actor Table handling --- Dalamud/Dalamud.cs | 2 ++ Dalamud/Dalamud.csproj | 9 ++++---- Dalamud/Game/Chat/XivChatType.cs | 5 +++++ Dalamud/Game/ClientState/Actors/ActorTable.cs | 13 +++++++++--- Dalamud/Game/ClientState/ClientState.cs | 9 +++++++- Dalamud/Game/Internal/Gui/IconReplacer.cs | 21 +++++++------------ Dalamud/Game/Network/NetworkHandlers.cs | 14 ++++++------- Dalamud/XivApi.cs | 3 +++ 8 files changed, 46 insertions(+), 30 deletions(-) diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs index 52ec31e1c..3f756922a 100644 --- a/Dalamud/Dalamud.cs +++ b/Dalamud/Dalamud.cs @@ -346,6 +346,7 @@ namespace Dalamud { var argumentsParts = arguments.Split(); switch (argumentsParts[0]) { + /* Sorry! case "setall": { foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { if (value == CustomComboPreset.None) @@ -393,6 +394,7 @@ namespace Dalamud { } } break; + */ case "list": { foreach (var value in Enum.GetValues(typeof(CustomComboPreset)).Cast()) { if (this.Configuration.ComboPresets.HasFlag(value)) diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index d96583d65..9a99ab4ff 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -7,15 +7,16 @@ Library - $(SolutionDir)/bin + D:\Sapphire\recorder\FFXIV.Recorder\/bin false true Portable true - 2.1.0.0 - 2.1.0 + 2.2.0.0 + 2.2.0 + 2.2.0.0 @@ -27,7 +28,7 @@ E:\Sapphire\recorder\FFXIV.Recorder\/bin\Dalamud.xml - E:\Sapphire\recorder\FFXIV.Recorder\/bin\Dalamud.xml + D:\Sapphire\recorder\FFXIV.Recorder\/bin\Dalamud.xml E:\Sapphire\recorder\FFXIV.Recorder\/bin\Dalamud.xml diff --git a/Dalamud/Game/Chat/XivChatType.cs b/Dalamud/Game/Chat/XivChatType.cs index d909947cb..a52584153 100644 --- a/Dalamud/Game/Chat/XivChatType.cs +++ b/Dalamud/Game/Chat/XivChatType.cs @@ -61,6 +61,11 @@ namespace Dalamud.Game.Chat { [XivChatTypeInfo("Novice Network", "nn", 0xFF8B4513)] NoviceNetwork = 27, + [XivChatTypeInfo("Custom Emotes", "nn", 0xFF8B4513)] + CustomEmote = 28, + [XivChatTypeInfo("Standard Emotes", null, 0xFF8B4513)] + StandardEmote = 29, + [XivChatTypeInfo("Yell", "y", 0xFFFFFF00)] Yell = 30, diff --git a/Dalamud/Game/ClientState/Actors/ActorTable.cs b/Dalamud/Game/ClientState/Actors/ActorTable.cs index d1dd88a92..2dd497bc4 100644 --- a/Dalamud/Game/ClientState/Actors/ActorTable.cs +++ b/Dalamud/Game/ClientState/Actors/ActorTable.cs @@ -9,7 +9,7 @@ namespace Dalamud.Game.ClientState.Actors { /// /// This collection represents the currently spawned FFXIV actors. /// - public unsafe class ActorTable : ICollection { + public class ActorTable : ICollection { private ClientStateAddressResolver Address { get; } /// @@ -29,8 +29,15 @@ namespace Dalamud.Game.ClientState.Actors { /// at the specified spawn index. public Actor this[int index] { get { + if (index > Length) + return null; + + Log.Information("Trying to get actor at {0}", index); var tblIndex = Address.ActorTable + 8 + index * 8; - var offset = *(IntPtr*) tblIndex; + + var offset = Marshal.ReadIntPtr(tblIndex); + + Log.Information("Actor at {0}", offset.ToString()); if (offset == IntPtr.Zero) throw new Exception($"Actor slot at index {index} is invalid"); @@ -76,7 +83,7 @@ namespace Dalamud.Game.ClientState.Actors { /// /// The amount of currently spawned actors. /// - public int Length => *(int*) Address.ActorTable; + public int Length => Marshal.ReadInt32(Address.ActorTable); int ICollection.Count => Length; diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs index 98e1c2e29..e0e038382 100644 --- a/Dalamud/Game/ClientState/ClientState.cs +++ b/Dalamud/Game/ClientState/ClientState.cs @@ -32,7 +32,7 @@ namespace Dalamud.Game.ClientState /// /// The local player character, if one is present. /// - public PlayerCharacter LocalPlayer => (PlayerCharacter) this.Actors[0]; + public PlayerCharacter LocalPlayer { get; private set; } /// /// The content ID of the local character. @@ -62,6 +62,13 @@ namespace Dalamud.Game.ClientState this.Actors = new ActorTable(Address); this.JobGauges = new JobGauges(Address); + + dalamud.Framework.OnUpdateEvent += FrameworkOnOnUpdateEvent; + } + + private void FrameworkOnOnUpdateEvent(Framework framework) { + LocalPlayer = (PlayerCharacter) this.Actors[0]; + Log.Verbose("FRAMEWORK UPDATE"); } } } diff --git a/Dalamud/Game/Internal/Gui/IconReplacer.cs b/Dalamud/Game/Internal/Gui/IconReplacer.cs index 069af81a8..40630cab0 100644 --- a/Dalamud/Game/Internal/Gui/IconReplacer.cs +++ b/Dalamud/Game/Internal/Gui/IconReplacer.cs @@ -24,7 +24,6 @@ namespace Dalamud.Game.Internal.Gui { private IntPtr jobInfo; private IntPtr byteBase; private Dalamud dalamud; - private PlayerCharacter localCharacter = null; public unsafe IconReplacer(Dalamud dalamud, SigScanner scanner) { this.dalamud = dalamud; @@ -68,12 +67,13 @@ namespace Dalamud.Game.Internal.Gui { /// For example, Souleater combo on DRK happens by dragging Souleater /// onto your bar and mashing it. /// - private unsafe ulong GetIconDetour(byte self, uint actionID) { + private ulong GetIconDetour(byte self, uint actionID) { // 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(); @@ -84,24 +84,16 @@ namespace Dalamud.Game.Internal.Gui { return this.iconHook.Original(self, actionID); } } + */ // TODO: this is currently broken // 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); - } - } + var localPlayer = this.dalamud.ClientState.LocalPlayer; // Don't clutter the spaghetti any worse than it already is. var lastMove = Marshal.ReadInt32(this.lastComboMove); var comboTime = Marshal.ReadInt32(this.comboTimer); - this.localCharacter = this.dalamud.ClientState.LocalPlayer; - var level = this.localCharacter.Level; + var level = 80; // DRAGOON // TODO: Jump/High Jump into Mirage Dive @@ -838,10 +830,11 @@ namespace Dalamud.Game.Internal.Gui { return this.iconHook.Original(self, actionID); } - private 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; } + */ return false; } diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs index eea77eb4c..ba3a636ac 100644 --- a/Dalamud/Game/Network/NetworkHandlers.cs +++ b/Dalamud/Game/Network/NetworkHandlers.cs @@ -64,18 +64,16 @@ namespace Dalamud.Game.Network { Marshal.Copy(dataPtr, data, 0, 64); var notifyType = data[16]; - var contentFinderConditionId = BitConverter.ToInt16(data, 38); + var contentFinderConditionId = BitConverter.ToInt16(data, 28); Task.Run(async () => { - if (notifyType != 4) + if (notifyType != 2 || contentFinderConditionId == 0) return; var contentFinderCondition = await XivApi.GetContentFinderCondition(contentFinderConditionId); - this.dalamud.Framework.Gui.Chat.Print("Duty Finder pop: " + contentFinderCondition["Name"]); - if (this.dalamud.BotManager.IsConnected) await this.dalamud.BotManager.ProcessCfPop(contentFinderCondition); }); @@ -179,13 +177,13 @@ namespace Dalamud.Game.Network { } private enum ZoneOpCode { - CfNotify = 0x78, + CfNotify = 0x8F, RetainerSaleItemId = 0x13F, // TODO these are probably not accurate RetainerSaleFinish = 0x138, FateSpawn = 0x226, - MarketBoardItemRequestStart = 0x13B, - MarketBoardOfferings = 0x13C, - MarketBoardHistory = 0x140 + MarketBoardItemRequestStart = 0x39D, + MarketBoardOfferings = 0x36A, + MarketBoardHistory = 0x194 } } } diff --git a/Dalamud/XivApi.cs b/Dalamud/XivApi.cs index 6515541a5..dc5e5fa8b 100644 --- a/Dalamud/XivApi.cs +++ b/Dalamud/XivApi.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Microsoft.CSharp.RuntimeBinder; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using Serilog; namespace Dalamud { @@ -68,6 +69,8 @@ namespace Dalamud public static async Task Get(string endpoint, bool noCache = false) { + Log.Verbose("XIVAPI FETCH: {0}", endpoint); + if (cachedResponses.ContainsKey(endpoint) && !noCache) return cachedResponses[endpoint];