Update to C# 7.3. Some job gauge abstraction added. Mid-work push.

This commit is contained in:
attick 2019-10-17 22:27:56 -04:00
parent 84c66ddc6e
commit 8d02c977d2
20 changed files with 367 additions and 14 deletions

View file

@ -2,7 +2,7 @@
<PropertyGroup Label="Target">
<PlatformTarget>AnyCPU</PlatformTarget>
<TargetFramework>net471</TargetFramework>
<LangVersion>7.2</LangVersion>
<LangVersion>7.3</LangVersion>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>
<PropertyGroup Label="Build">

View file

@ -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<T>() {
return Marshal.PtrToStructure<T>(gaugeStart);
}
}
}

View file

@ -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 {
}
}

View file

@ -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;
}
}
}

View file

@ -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 {
}
}

View file

@ -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;
}
}
}

View file

@ -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 {
}
}

View file

@ -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;
}
}

View file

@ -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 {
}
}

View file

@ -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;
}
}
}

View file

@ -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 {
}
}

View file

@ -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 {
}
}

View file

@ -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 {
}
}

View file

@ -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 {
}
}

View file

@ -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;
}
}

View file

@ -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 {
}
}

View file

@ -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;
}
}

View file

@ -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 {
}
}

View file

@ -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 {
}
}

View file

@ -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<MCHGauge>().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<MCHGauge>().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<BLMGauge>();
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<BLMGauge>().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.
// Handle AoE GCDs on one button. Procs take priority over combo.
// Standard Step is one button.
if (actionID == 15997) {
DNCGauge gauge = JobGauge.Gauge<DNCGauge>();
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;
}
if (actionID == 15994) {
// Technical Step is one button.
if (actionID == 15998) {
DNCGauge gauge = JobGauge.Gauge<DNCGauge>();
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;
}
// 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;
}