Finished job gauge structs. Added a few gauge-related enums. Finished adding default icon replacers.

This commit is contained in:
attick 2019-10-24 01:43:22 -04:00
parent dc960c5f6f
commit 3776edb5b4
22 changed files with 480 additions and 103 deletions

View file

@ -6,6 +6,8 @@ using System.Threading.Tasks;
namespace XIVLauncher.Dalamud namespace XIVLauncher.Dalamud
{ {
//CURRENT HIGHEST FLAG IS 45
[Flags] [Flags]
public enum CustomComboPreset 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)] [CustomComboInfo("Dreadwyrm Combiner", "Now comes with Dreadwyrm Trance, Deathflare, Summon Bahamut, Enkindle Bahamut, FBT, and Enkindle Phoenix.", 27)]
SummonerDwtCombo = 1 << 28, 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 // SCHOLAR
[CustomComboInfo("Seraph Fey Blessing/Consolation", "Change Fey Blessing into Consolation when Seraph is out.", 28)] [CustomComboInfo("Seraph Fey Blessing/Consolation", "Change Fey Blessing into Consolation when Seraph is out.", 28)]
ScholarSeraphConsolationFeature = 1 << 29, ScholarSeraphConsolationFeature = 1 << 29,
[CustomComboInfo("ED Aetherflow", "Change Energy Drain into Aetherflow when you have no more Aetherflow stacks.", 28)]
ScholarEnergyDrainFeature = 1 << 37,
// DANCER // DANCER
[CustomComboInfo("Standard Step Combo", "Standard Step on one button.", 38)] [CustomComboInfo("Standard Step Combo", "Standard Step on one button.", 38)]
DancerStandardStepCombo = 1 << 30, DancerStandardStepCombo = 1 << 30,
@ -128,7 +142,48 @@ namespace XIVLauncher.Dalamud
DancerFanDanceCombo = 1 << 33, DancerFanDanceCombo = 1 << 33,
[CustomComboInfo("Fountain Combos", "Fountain changes into Fountain combo, prioritizing procs over combo, and Fountainfall over Reverse Cascade.", 38)] [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 public class CustomComboInfoAttribute : Attribute

View file

@ -15,7 +15,7 @@ namespace Dalamud.Game.ClientState
protected override void Setup64Bit(SigScanner sig) { protected override void Setup64Bit(SigScanner sig) {
ActorTable = sig.Module.BaseAddress + 0x1B29B40; ActorTable = sig.Module.BaseAddress + 0x1B29B40;
LocalContentId = sig.Module.BaseAddress + 0x1B58B60; LocalContentId = sig.Module.BaseAddress + 0x1B58B60;
JobGaugeData = sig.Module.BaseAddress + 0x1B2D4B4; JobGaugeData = sig.Module.BaseAddress + 0x1B2D4C0;
} }
} }
} }

View file

@ -9,5 +9,18 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct ASTGauge { 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;
}
} }
} }

View file

@ -9,12 +9,12 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct BLMGauge { public struct BLMGauge {
[FieldOffset(0xc)] public short TimeUntilNextPolyglot; //eno timer (ms) [FieldOffset(0)] public short TimeUntilNextPolyglot; //eno timer (ms)
[FieldOffset(0xe)] public short ElementTimeRemaining; //ui/af timer [FieldOffset(2)] public short ElementTimeRemaining; //ui/af timer
[FieldOffset(0x10)] private byte ElementStance; //ui/af [FieldOffset(4)] private byte ElementStance; //ui/af
[FieldOffset(0x11)] public byte NumUmbralHearts; //number of umbral hearts [FieldOffset(5)] public byte NumUmbralHearts; //number of umbral hearts
[FieldOffset(0x12)] public byte NumPolyglotStacks; //number of polyglot stacks [FieldOffset(6)] public byte NumPolyglotStacks; //number of polyglot stacks
[FieldOffset(0x13)] public bool IsEnoActive; //eno active? [FieldOffset(7)] public bool IsEnoActive; //eno active?
public bool InUmbralIce() { public bool InUmbralIce() {
return ElementStance > 4; return ElementStance > 4;

View file

@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct BRDGauge { public struct BRDGauge {
[FieldOffset(0)] public short SongTimer;
[FieldOffset(2)] public byte NumSongStacks;
[FieldOffset(4)] public CurrentSong ActiveSong;
} }
} }

View file

@ -9,13 +9,17 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public unsafe struct DNCGauge { public unsafe struct DNCGauge {
[FieldOffset(0xc)] public byte NumFeathers; [FieldOffset(0)] public byte NumFeathers;
[FieldOffset(0xd)] public byte Esprit; [FieldOffset(1)] public byte Esprit;
[FieldOffset(0xe)] public fixed byte StepOrder[4]; [FieldOffset(2)] private fixed byte StepOrder[4];
[FieldOffset(0x12)] public byte NumCompleteSteps; [FieldOffset(6)] public byte NumCompleteSteps;
public bool IsDancing() { public bool IsDancing() {
return StepOrder[0] != 0; return StepOrder[0] != 0;
} }
public ulong NextStep() {
return (ulong)(15999 + StepOrder[NumCompleteSteps] - 1);
}
} }
} }

View file

@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct DRGGauge { public struct DRGGauge {
[FieldOffset(0)] public short BOTDTimer;
[FieldOffset(2)] public BOTDState BOTDState;
[FieldOffset(3)] public byte EyeCount;
} }
} }

View file

@ -8,9 +8,9 @@ using System.Threading.Tasks;
namespace Dalamud.Game.ClientState.Structs.JobGauge { namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct DRKGauge { public struct DRKGauge {
[FieldOffset(0xc)] public short Blood; [FieldOffset(0)] public short Blood;
[FieldOffset(0xe)] public short DarksideTimeRemaining; [FieldOffset(2)] public short DarksideTimeRemaining;
[FieldOffset(0x10)] public bool HasDarkArts; [FieldOffset(4)] public bool HasDarkArts;
[FieldOffset(0x12)] public short ShadowTimeRemaining; [FieldOffset(6)] public short ShadowTimeRemaining;
} }
} }

View file

@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct GNBGauge { public struct GNBGauge {
[FieldOffset(0)] public byte NumAmmo;
[FieldOffset(2)] public short MaxTimerDuration;
[FieldOffset(4)] public byte AmmoComboStepNumber;
} }
} }

View file

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

View file

@ -10,12 +10,12 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct MCHGauge{ public struct MCHGauge{
[FieldOffset(0xc)] public short OverheatTimeRemaining; [FieldOffset(0)] public short OverheatTimeRemaining;
[FieldOffset(0xe)] public short RobotTimeRemaining; [FieldOffset(2)] public short RobotTimeRemaining;
[FieldOffset(0x10)] public byte Heat; [FieldOffset(4)] public byte Heat;
[FieldOffset(0x11)] public byte Battery; [FieldOffset(5)] public byte Battery;
[FieldOffset(0x12)] public byte LastRobotBatteryPower; [FieldOffset(6)] public byte LastRobotBatteryPower;
[FieldOffset(0x13)] private byte TimerActive; [FieldOffset(7)] private byte TimerActive;
public bool IsOverheated() { public bool IsOverheated() {
return (TimerActive & 1) != 0; return (TimerActive & 1) != 0;

View file

@ -9,5 +9,9 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct MNKGauge { public struct MNKGauge {
[FieldOffset(0)] public byte GLTimer;
[FieldOffset(2)] public byte NumGLStacks;
[FieldOffset(3)] public byte NumChakra;
[FieldOffset(4)] public bool IsGLTimerFrozen;
} }
} }

View file

@ -9,5 +9,9 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct NINGauge { 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
} }
} }

View file

@ -9,5 +9,6 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct PLDGauge { public struct PLDGauge {
[FieldOffset(0)] public byte GaugeAmount;
} }
} }

View file

@ -9,5 +9,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct RDMGauge { public struct RDMGauge {
[FieldOffset(0)] public byte WhiteGauge;
[FieldOffset(1)] public byte BlackGauge;
} }
} }

View file

@ -10,7 +10,7 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct SAMGauge { public struct SAMGauge {
[FieldOffset(0xf)] public byte Kenki; [FieldOffset(3)] public byte Kenki;
[FieldOffset(0x10)] public byte Sen; [FieldOffset(4)] public Sen Sen;
} }
} }

View file

@ -9,5 +9,9 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct SCHGauge { public struct SCHGauge {
[FieldOffset(2)] public byte NumAetherflowStacks;
[FieldOffset(3)] public byte FairyGaugeAmount;
[FieldOffset(4)] public short SeraphTimer;
[FieldOffset(6)] public DismissedFairy DismissedFairy;
} }
} }

View file

@ -11,8 +11,21 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
public struct SMNGauge { public struct SMNGauge {
//Unfinished //Unfinished
[FieldOffset(0xc)] public short TimerRemaining; [FieldOffset(0)] public short TimerRemaining;
[FieldOffset(0xf)] public bool IsDemiActive; [FieldOffset(2)] public byte ReturnSummon;
[FieldOffset(0x10)] public byte NumStacks; [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;
}
} }
} }

View file

@ -9,5 +9,6 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct WARGauge { public struct WARGauge {
[FieldOffset(0)] public byte BeastGaugeAmount;
} }
} }

View file

@ -9,5 +9,8 @@ namespace Dalamud.Game.ClientState.Structs.JobGauge {
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
public struct WHMGauge { public struct WHMGauge {
[FieldOffset(2)] public short LilyTimer; //Counts to 30k = 30s
[FieldOffset(4)] public byte NumLilies;
[FieldOffset(5)] public byte NumBloodLily;
} }
} }

View file

@ -99,7 +99,7 @@ namespace Dalamud.Game.Internal {
} catch (Exception ex) { } catch (Exception ex) {
Log.Error(ex, "Exception while dispatching Framework::Update event."); Log.Error(ex, "Exception while dispatching Framework::Update event.");
} }
return this.updateHook.Original(framework); return this.updateHook.Original(framework);
} }
} }

View file

@ -32,7 +32,6 @@ namespace Dalamud.Game.Internal.Gui {
this.Address.Setup(scanner); this.Address.Setup(scanner);
this.byteBase = scanner.Module.BaseAddress; this.byteBase = scanner.Module.BaseAddress;
this.jobInfo = byteBase + 0x1b2d4b4;
this.comboTimer = byteBase + 0x1AE1B10; this.comboTimer = byteBase + 0x1AE1B10;
this.lastComboMove = byteBase + 0x1AE1B14; this.lastComboMove = byteBase + 0x1AE1B14;
@ -71,14 +70,14 @@ namespace Dalamud.Game.Internal.Gui {
/// </summary> /// </summary>
private unsafe ulong GetIconDetour(byte self, uint actionID) { 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. // 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 not, skip everything until we are (game will crash cause I'm lazy).
if (activeBuffArray == IntPtr.Zero) { if (activeBuffArray == IntPtr.Zero) {
try { try {
activeBuffArray = FindBuffAddress(); activeBuffArray = FindBuffAddress();
localCharacter = dalamud.ClientState.LocalPlayer; Log.Verbose("ActiveBuffArray address: {ActiveBuffArray}", activeBuffArray);
} }
catch (Exception e) { catch (Exception e) {
activeBuffArray = IntPtr.Zero; 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. // Don't clutter the spaghetti any worse than it already is.
int lastMove = Marshal.ReadInt32(lastComboMove); int lastMove = Marshal.ReadInt32(lastComboMove);
float comboTime = (float)Marshal.ReadInt32(comboTimer); float comboTime = (float)Marshal.ReadInt32(comboTimer);
@ -98,8 +109,8 @@ namespace Dalamud.Game.Internal.Gui {
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonCoerthanTormentCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DragoonCoerthanTormentCombo)) {
if (actionID == 16477) { if (actionID == 16477) {
if (comboTime > 0) { if (comboTime > 0) {
if (Marshal.ReadInt32(lastComboMove) == 86) return 7397; if (lastMove == 86) return 7397;
if (Marshal.ReadInt32(lastComboMove) == 7397) return 16477; if (lastMove == 7397) return 16477;
} }
return 86; return 86;
} }
@ -112,13 +123,11 @@ namespace Dalamud.Game.Internal.Gui {
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 75 || lastMove == 16479) return 87; if (lastMove == 75 || lastMove == 16479) return 87;
if (lastMove == 87) return 88; 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; return 75;
} }
} }
@ -130,14 +139,10 @@ namespace Dalamud.Game.Internal.Gui {
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 75 || lastMove == 16479) return 78; if (lastMove == 75 || lastMove == 16479) return 78;
if (lastMove == 78) return 84; 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; return 75;
} }
@ -245,9 +250,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Yukikaze with Yukikaze combo // Replace Yukikaze with Yukikaze combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiYukikazeCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiYukikazeCombo)) {
if (actionID == 7480) { if (actionID == 7480) {
if (activeBuffArray != IntPtr.Zero) { if (SearchBuffArray(1233)) return 7480;
if (SearchBuffArray(1233)) return 7480;
}
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 7477) return 7480; if (lastMove == 7477) return 7480;
} }
@ -258,9 +261,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Gekko with Gekko combo // Replace Gekko with Gekko combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiGekkoCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiGekkoCombo)) {
if (actionID == 7481) { if (actionID == 7481) {
if (activeBuffArray != IntPtr.Zero) { if (SearchBuffArray(1233)) return 7481;
if (SearchBuffArray(1233)) return 7481;
}
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 7477) return 7478; if (lastMove == 7477) return 7478;
if (lastMove == 7478) return 7481; if (lastMove == 7478) return 7481;
@ -272,9 +273,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Kasha with Kasha combo // Replace Kasha with Kasha combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiKashaCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiKashaCombo)) {
if (actionID == 7482) { if (actionID == 7482) {
if (activeBuffArray != null) { if (SearchBuffArray(1233)) return 7482;
if (SearchBuffArray(1233)) return 7482;
}
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 7477) return 7479; if (lastMove == 7477) return 7479;
if (lastMove == 7479) return 7482; if (lastMove == 7479) return 7482;
@ -286,9 +285,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Mangetsu with Mangetsu combo // Replace Mangetsu with Mangetsu combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiMangetsuCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiMangetsuCombo)) {
if (actionID == 7484) { if (actionID == 7484) {
if (activeBuffArray != null) { if (SearchBuffArray(1233)) return 7484;
if (SearchBuffArray(1233)) return 7484;
}
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 7483) return 7484; if (lastMove == 7483) return 7484;
} }
@ -299,9 +296,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Oka with Oka combo // Replace Oka with Oka combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiOkaCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SamuraiOkaCombo)) {
if (actionID == 7485) { if (actionID == 7485) {
if (activeBuffArray != null) { if (SearchBuffArray(1233)) return 7485;
if (SearchBuffArray(1233)) return 7485;
}
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 7483) return 7485; if (lastMove == 7483) return 7485;
} }
@ -323,7 +318,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Armor Crush with Armor Crush combo // Replace Armor Crush with Armor Crush combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaArmorCrushCombo)) {
if (actionID == 2257) { if (actionID == 3563) {
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 2240) return 2242; if (lastMove == 2240) return 2242;
if (lastMove == 2242) return 3563; if (lastMove == 2242) return 3563;
@ -334,7 +329,7 @@ namespace Dalamud.Game.Internal.Gui {
// Replace Aeolian Edge with Aeolian Edge combo // Replace Aeolian Edge with Aeolian Edge combo
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAeolianEdgeCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.NinjaAeolianEdgeCombo)) {
if (actionID == 2257) { if (actionID == 2255) {
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 2240) return 2242; if (lastMove == 2240) return 2242;
if (lastMove == 2242) return 2255; if (lastMove == 2242) return 2255;
@ -370,7 +365,7 @@ namespace Dalamud.Game.Internal.Gui {
// TODO: Potentially add Contuation moves as well? // TODO: Potentially add Contuation moves as well?
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerGnashingFangCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.GunbreakerGnashingFangCombo)) {
if (actionID == 16146) { if (actionID == 16146) {
byte ammoComboState = Marshal.ReadByte(jobInfo, 0x10); byte ammoComboState = this.dalamud.ClientState.JobGauges.Get<GNBGauge>().AmmoComboStepNumber;
if (ammoComboState == 1) return 16147; if (ammoComboState == 1) return 16147;
if (ammoComboState == 2) return 16150; if (ammoComboState == 2) return 16150;
return 16146; return 16146;
@ -414,6 +409,7 @@ namespace Dalamud.Game.Internal.Gui {
// BLACK MAGE // BLACK MAGE
// Enochian changes to B4 or F4 depending on stance. // 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 (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.BlackEnochianFeature)) {
if (actionID == 3575) { if (actionID == 3575) {
BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get<BLMGauge>(); BLMGauge jobInfo = this.dalamud.ClientState.JobGauges.Get<BLMGauge>();
@ -435,26 +431,26 @@ namespace Dalamud.Game.Internal.Gui {
// ASTROLOGIAN // 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 (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.AstrologianCardsOnDrawFeature)) {
if (actionID == 17055) { if (actionID == 17055) {
byte x = Marshal.ReadByte(jobInfo, 0x10); ASTGauge gauge = this.dalamud.ClientState.JobGauges.Get<ASTGauge>();
switch (x) { switch (gauge.DrawnCard()) {
case 1: case CardType.BALANCE:
return 4401; return 4401;
case 2: case CardType.BOLE:
return 4404; return 4404;
case 3: case CardType.ARROW:
return 4402; return 4402;
case 4: case CardType.SPEAR:
return 4403; return 4403;
case 5: case CardType.EWER:
return 4405; return 4405;
case 6: case CardType.SPIRE:
return 4406; return 4406;
case 0x70: case CardType.LORD:
return 7444; return 7444;
case 0x80: case CardType.LADY:
return 7445; return 7445;
default: default:
return 3590; return 3590;
@ -469,35 +465,77 @@ namespace Dalamud.Game.Internal.Gui {
// What a monster of a button. // What a monster of a button.
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDwtCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.SummonerDwtCombo)) {
if (actionID == 3581) { if (actionID == 3581) {
byte stackState = Marshal.ReadByte(jobInfo, 0x10); SMNGauge gauge = this.dalamud.ClientState.JobGauges.Get<SMNGauge>();
if (Marshal.ReadInt16(jobInfo, 0xc) > 0) { if (gauge.TimerRemaining > 0) {
if (Marshal.ReadInt16(jobInfo, 0xe) > 0) { if (gauge.ReturnSummon > 0) {
if (stackState > 0) return 16516; if (gauge.IsPhoenixReady()) return 16516;
return 7429; return 7429;
} }
return 3582; return 3582;
} }
else { else {
if (stackState == 0) return 3581; if (gauge.IsBahamutReady()) return 7427;
if (stackState == 8) return 7427; if (gauge.IsPhoenixReady()) return 16513;
if (stackState == 0x10) return 16513;
return 3581; 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<SMNGauge>();
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<SMNGauge>().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<SMNGauge>().HasAetherflowStacks())
if(level >= 52) return 3578;
return 16510;
}
}
// SCHOLAR // SCHOLAR
// Change Fey Blessing into Consolation when Seraph is out. // Change Fey Blessing into Consolation when Seraph is out.
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarSeraphConsolationFeature)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.ScholarSeraphConsolationFeature)) {
if (actionID == 16543) { if (actionID == 16543) {
if (Marshal.ReadInt16(jobInfo, 0x10) > 0) return 16546; if (this.dalamud.ClientState.JobGauges.Get<SCHGauge>().SeraphTimer > 0) return 16546;
return 16543; 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<SCHGauge>().NumAetherflowStacks == 0) return 166;
return 167;
}
}
// DANCER // DANCER
// Standard Step is one button. // Standard Step is one button.
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerStandardStepCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerStandardStepCombo)) {
if (actionID == 15997) { if (actionID == 15997) {
@ -508,7 +546,7 @@ namespace Dalamud.Game.Internal.Gui {
} }
else { else {
// C# can't implicitly cast from int to ulong. // C# can't implicitly cast from int to ulong.
return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); return gauge.NextStep();
} }
} }
return 15997; return 15997;
@ -525,7 +563,7 @@ namespace Dalamud.Game.Internal.Gui {
} }
else { else {
// C# can't implicitly cast from int to ulong. // C# can't implicitly cast from int to ulong.
return (ulong)(15999 + gauge.StepOrder[gauge.NumCompleteSteps] - 1); return gauge.NextStep();
} }
} }
return 15998; return 15998;
@ -536,10 +574,9 @@ namespace Dalamud.Game.Internal.Gui {
// and Fountainfall over Reverse Cascade. // and Fountainfall over Reverse Cascade.
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFountainCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFountainCombo)) {
if (actionID == 15990) { if (actionID == 15990) {
if (activeBuffArray != null) { if (this.dalamud.ClientState.JobGauges.Get<DNCGauge>().IsDancing()) return 15999;
if (SearchBuffArray(1815)) return 15992; if (SearchBuffArray(1815)) return 15992;
if (SearchBuffArray(1814)) return 15991; if (SearchBuffArray(1814)) return 15991;
}
if (comboTime > 0) { if (comboTime > 0) {
if (lastMove == 15989) return 15990; if (lastMove == 15989) return 15990;
} }
@ -552,16 +589,12 @@ namespace Dalamud.Game.Internal.Gui {
// Replaces each GCD with its procced version. // Replaces each GCD with its procced version.
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerAoeGcdFeature)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerAoeGcdFeature)) {
if (actionID == 15994) { if (actionID == 15994) {
if (activeBuffArray != null) { if (SearchBuffArray(1817)) return 15996;
if (SearchBuffArray(1817)) return 15996;
}
return 15994; return 15994;
} }
if (actionID == 15993) { if (actionID == 15993) {
if (activeBuffArray != null) { if (SearchBuffArray(1816)) return 15995;
if (SearchBuffArray(1816)) return 15995;
}
return 15993; return 15993;
} }
} }
@ -570,26 +603,209 @@ namespace Dalamud.Game.Internal.Gui {
if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFanDanceCombo)) { if (this.dalamud.Configuration.ComboPresets.HasFlag(CustomComboPreset.DancerFanDanceCombo)) {
// Fan Dance changes into Fan Dance 3 while flourishing. // Fan Dance changes into Fan Dance 3 while flourishing.
if (actionID == 16007) { if (actionID == 16007) {
if (activeBuffArray != null) { if (SearchBuffArray(1820)) return 16009;
if (SearchBuffArray(1820)) return 16009;
}
return 16007; return 16007;
} }
// Fan Dance 2 changes into Fan Dance 3 while flourishing. // Fan Dance 2 changes into Fan Dance 3 while flourishing.
if (actionID == 16008) { if (actionID == 16008) {
if (activeBuffArray != null) { if (SearchBuffArray(1820)) return 16009;
if (SearchBuffArray(1820)) return 16009;
}
return 16008; 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<WHMGauge>().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<WHMGauge>().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<BRDGauge>().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<MNKGauge>();
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<MNKGauge>();
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<MNKGauge>();
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<RDMGauge>();
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<RDMGauge>();
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<RDMGauge>();
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); return this.iconHook.Original(self, actionID);
} }
private unsafe bool SearchBuffArray(short needle) { private bool SearchBuffArray(short needle) {
for (int i = 0; i < 60; i++) { for (int i = 0; i < 60; i++) {
if (Marshal.ReadInt16(activeBuffArray + 4 * i) == needle) return true; if (Marshal.ReadInt16(activeBuffArray + 4 * i) == needle) return true;
} }