From 8d02c977d211ce09db1a8c552dcae32ef3e922c1 Mon Sep 17 00:00:00 2001 From: attick Date: Thu, 17 Oct 2019 22:27:56 -0400 Subject: [PATCH] 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; }