From 60abca71bdc91bbb63a6782621dd07b41b4fec1b Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 30 Jun 2024 19:08:43 +0100 Subject: [PATCH 1/3] Fix cooldown data --- XIVSlothCombo/Combos/CustomComboPreset.cs | 25 +++++ XIVSlothCombo/Combos/JobHelpers/RDM.cs | 2 +- XIVSlothCombo/Combos/PvE/BRD.cs | 2 +- .../CustomCombo/Functions/Cooldown.cs | 2 +- XIVSlothCombo/Data/CooldownData.cs | 93 ++++--------------- XIVSlothCombo/Data/CustomComboCache.cs | 40 ++------ 6 files changed, 51 insertions(+), 113 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 66dcd648f..0da6479e3 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2179,6 +2179,31 @@ public enum CustomComboPreset #endregion + #region PICTOMANCER + [ReplaceSkill(PCT.FireInRed)] + [ConflictingCombos(CombinedAetherhues)] + [CustomComboInfo("Simple Mode - Single Target", $"Replaces Fire in Red with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", PCT.JobID)] + PCT_ST_SimpleMode = 20000, + + [ReplaceSkill(PCT.FireIIinRed)] + [ConflictingCombos(CombinedAetherhues)] + [CustomComboInfo("Simple Mode - AoE", $"Replaces Fire II in Red with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", PCT.JobID)] + PCT_AoE_SimpleMode = 20001, + + [ReplaceSkill(PCT.FireInRed, PCT.FireIIinRed)] + [CustomComboInfo("Combined Aetherhues Feature", "Combines aetherhue actions onto one button for their respective target types.", PCT.JobID)] + CombinedAetherhues = 20002, + + [ReplaceSkill(PCT.CreatureMotif, PCT.WeaponMotif, PCT.LandscapeMotif)] + [CustomComboInfo("One Button Motifs", "Combine Motifs and Muses into one button.", PCT.JobID)] + CombinedMotifs = 20003, + + [ReplaceSkill(PCT.HolyInWhite)] + [CustomComboInfo("One Button Paint", "Combines paint consuming actions into one button.", PCT.JobID)] + CombinedPaint = 20004, + + #endregion + #region PALADIN //// Last value = 11032 diff --git a/XIVSlothCombo/Combos/JobHelpers/RDM.cs b/XIVSlothCombo/Combos/JobHelpers/RDM.cs index d52550a74..fd47b8978 100644 --- a/XIVSlothCombo/Combos/JobHelpers/RDM.cs +++ b/XIVSlothCombo/Combos/JobHelpers/RDM.cs @@ -9,7 +9,7 @@ internal class RDM static float GetBuffRemainingTime(ushort effectid) => CustomComboFunctions.GetBuffRemainingTime(effectid); static bool LevelChecked(uint id) => CustomComboFunctions.LevelChecked(id); static float GetActionCastTime(uint actionID) => CustomComboFunctions.GetActionCastTime(actionID); - static ushort GetRemainingCharges(uint actionID) => CustomComboFunctions.GetRemainingCharges(actionID); + static uint GetRemainingCharges(uint actionID) => CustomComboFunctions.GetRemainingCharges(actionID); static float GetCooldownRemainingTime(uint actionID) => CustomComboFunctions.GetCooldownRemainingTime(actionID); static bool ActionReady(uint id) => CustomComboFunctions.ActionReady(id); static bool CanSpellWeave(uint id) => CustomComboFunctions.CanSpellWeave(id); diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 019867966..52d3df5af 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -654,7 +654,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Bloodletter) && ((!openerFinished && IsOnCooldown(RagingStrikes)) || openerFinished)) { - ushort bloodletterCharges = GetRemainingCharges(Bloodletter); + uint bloodletterCharges = GetRemainingCharges(Bloodletter); if (IsEnabled(CustomComboPreset.BRD_Simple_Pooling) && LevelChecked(WanderersMinuet)) { diff --git a/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs b/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs index 5debbfc13..728f9b843 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs @@ -50,7 +50,7 @@ internal abstract partial class CustomComboFunctions /// Get the current number of charges remaining for an action. /// Action ID to check. /// Number of charges. - public static ushort GetRemainingCharges(uint actionID) => GetCooldown(actionID).RemainingCharges; + public static uint GetRemainingCharges(uint actionID) => GetCooldown(actionID).RemainingCharges; /// Get the maximum number of charges for an action. /// Action ID to check. diff --git a/XIVSlothCombo/Data/CooldownData.cs b/XIVSlothCombo/Data/CooldownData.cs index 2e836f964..5e27d87a7 100644 --- a/XIVSlothCombo/Data/CooldownData.cs +++ b/XIVSlothCombo/Data/CooldownData.cs @@ -1,114 +1,55 @@ -using System.Runtime.InteropServices; +using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Services; namespace XIVSlothCombo.Data { - /// Internal cooldown data. - [StructLayout(LayoutKind.Explicit)] - internal struct CooldownData + internal class CooldownData { - [FieldOffset(0x0)] - private readonly bool isCooldown; - - [FieldOffset(0x4)] - private readonly uint actionID; - - [FieldOffset(0x8)] - private readonly float cooldownElapsed; - - [FieldOffset(0xC)] - private float cooldownTotal; - /// Gets a value indicating whether the action is on cooldown. - public readonly bool IsCooldown + public bool IsCooldown { get { - var (cur, max) = Service.ComboCache.GetMaxCharges(ActionID); - return cur == max - ? isCooldown - : cooldownElapsed < CooldownTotal; + return RemainingCharges == MaxCharges + ? false + : CooldownElapsed < CooldownTotal; } } /// Gets the action ID on cooldown. - public readonly uint ActionID => actionID; + public uint ActionID; /// Gets the elapsed cooldown time. - public readonly float CooldownElapsed - { - get - { - if (cooldownElapsed == 0) - return 0; - - if (cooldownElapsed > CooldownTotal) - return 0; - - return cooldownElapsed; - } - } + public unsafe float CooldownElapsed => ActionManager.Instance()->GetRecastGroupDetail(ActionManager.Instance()->GetRecastGroup(1, ActionID))->Elapsed; /// Gets the total cooldown time. - public float CooldownTotal - { - readonly get - { - if (cooldownTotal == 0) - return 0; - - var (cur, max) = Service.ComboCache.GetMaxCharges(ActionID); - - if (cur == max) - return cooldownTotal; - - // Rebase to the current charge count - float total = cooldownTotal / max * cur; - - return cooldownElapsed > total - ? 0 - : total; - } - set - { - cooldownTotal = value; - } - } + public unsafe float CooldownTotal => (ActionManager.GetAdjustedRecastTime(ActionType.Action, ActionID) / 1000f) * MaxCharges; /// Gets the cooldown time remaining. - public readonly float CooldownRemaining => IsCooldown ? CooldownTotal - CooldownElapsed : 0; + public unsafe float CooldownRemaining => CooldownTotal - CooldownElapsed; /// Gets the maximum number of charges for an action at the current level. /// Number of charges. - public readonly ushort MaxCharges => Service.ComboCache.GetMaxCharges(ActionID).Current; + public ushort MaxCharges => Service.ComboCache.GetMaxCharges(ActionID); /// Gets a value indicating whether the action has charges, not charges available. - public readonly bool HasCharges => MaxCharges > 1; + public bool HasCharges => MaxCharges > 1; /// Gets the remaining number of charges for an action. - public readonly ushort RemainingCharges - { - get - { - var (cur, _) = Service.ComboCache.GetMaxCharges(ActionID); - - return !IsCooldown - ? cur - : (ushort)(CooldownElapsed / (CooldownTotal / MaxCharges)); - } - } + public unsafe uint RemainingCharges => ActionManager.Instance()->GetCurrentCharges(ActionID); /// Gets the cooldown time remaining until the next charge. - public readonly float ChargeCooldownRemaining + public float ChargeCooldownRemaining { get { if (!IsCooldown) return 0; - var (cur, _) = Service.ComboCache.GetMaxCharges(ActionID); + var maxCharges = ActionManager.GetMaxCharges(ActionID, 100); + var timePerCharge = CooldownTotal / maxCharges; - return CooldownRemaining % (CooldownTotal / cur); + return CooldownRemaining % (CooldownTotal / MaxCharges); } } } diff --git a/XIVSlothCombo/Data/CustomComboCache.cs b/XIVSlothCombo/Data/CustomComboCache.cs index 7a3bb7aac..c49e564d4 100644 --- a/XIVSlothCombo/Data/CustomComboCache.cs +++ b/XIVSlothCombo/Data/CustomComboCache.cs @@ -81,46 +81,18 @@ internal unsafe CooldownData GetCooldown(uint actionID) if (actionManager == null) return cooldownCache[actionID] = default; - byte cooldownGroup = GetCooldownGroup(actionID); - - RecastDetail* cooldownPtr = actionManager->GetRecastGroupDetail(cooldownGroup - 1); - if (cooldownPtr is null) + CooldownData data = new() { - CooldownData data = new() - { - CooldownTotal = -1 - }; - - return cooldownCache[actionID] = data; - } + ActionID = actionID, + }; - cooldownPtr->ActionId = actionID; - - return cooldownCache[actionID] = *(CooldownData*)cooldownPtr; + return cooldownCache[actionID] = data; } /// Get the maximum number of charges for an action. /// Action ID to check. - /// Max number of charges at current and max level. - internal unsafe (ushort Current, ushort Max) GetMaxCharges(uint actionID) - { - IPlayerCharacter? player = Service.ClientState.LocalPlayer; - if (player == null) - return (0, 0); - - uint job = player.ClassJob.Id; - byte level = player.Level; - if (job == 0 || level == 0) - return (0, 0); - - var key = (actionID, job, level); - if (chargesCache.TryGetValue(key, out var found)) - return found; - - ushort cur = ActionManager.GetMaxCharges(actionID, 0); - ushort max = ActionManager.GetMaxCharges(actionID, 90); - return chargesCache[key] = (cur, max); - } + /// Max number of charges at current level. + internal unsafe ushort GetMaxCharges(uint actionID) => ActionManager.GetMaxCharges(actionID, 0); /// Get the resource cost of an action. /// Action ID to check. From ff4413ea6758c5c5d04ea70224dbded414470042 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 30 Jun 2024 19:10:31 +0100 Subject: [PATCH 2/3] Revert "Fix cooldown data" This reverts commit 60abca71bdc91bbb63a6782621dd07b41b4fec1b. --- XIVSlothCombo/Combos/CustomComboPreset.cs | 25 ----- XIVSlothCombo/Combos/JobHelpers/RDM.cs | 2 +- XIVSlothCombo/Combos/PvE/BRD.cs | 2 +- .../CustomCombo/Functions/Cooldown.cs | 2 +- XIVSlothCombo/Data/CooldownData.cs | 93 +++++++++++++++---- XIVSlothCombo/Data/CustomComboCache.cs | 40 ++++++-- 6 files changed, 113 insertions(+), 51 deletions(-) diff --git a/XIVSlothCombo/Combos/CustomComboPreset.cs b/XIVSlothCombo/Combos/CustomComboPreset.cs index 0da6479e3..66dcd648f 100644 --- a/XIVSlothCombo/Combos/CustomComboPreset.cs +++ b/XIVSlothCombo/Combos/CustomComboPreset.cs @@ -2179,31 +2179,6 @@ public enum CustomComboPreset #endregion - #region PICTOMANCER - [ReplaceSkill(PCT.FireInRed)] - [ConflictingCombos(CombinedAetherhues)] - [CustomComboInfo("Simple Mode - Single Target", $"Replaces Fire in Red with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", PCT.JobID)] - PCT_ST_SimpleMode = 20000, - - [ReplaceSkill(PCT.FireIIinRed)] - [ConflictingCombos(CombinedAetherhues)] - [CustomComboInfo("Simple Mode - AoE", $"Replaces Fire II in Red with a one-button full single target rotation.\nThis is ideal for newcomers to the job.", PCT.JobID)] - PCT_AoE_SimpleMode = 20001, - - [ReplaceSkill(PCT.FireInRed, PCT.FireIIinRed)] - [CustomComboInfo("Combined Aetherhues Feature", "Combines aetherhue actions onto one button for their respective target types.", PCT.JobID)] - CombinedAetherhues = 20002, - - [ReplaceSkill(PCT.CreatureMotif, PCT.WeaponMotif, PCT.LandscapeMotif)] - [CustomComboInfo("One Button Motifs", "Combine Motifs and Muses into one button.", PCT.JobID)] - CombinedMotifs = 20003, - - [ReplaceSkill(PCT.HolyInWhite)] - [CustomComboInfo("One Button Paint", "Combines paint consuming actions into one button.", PCT.JobID)] - CombinedPaint = 20004, - - #endregion - #region PALADIN //// Last value = 11032 diff --git a/XIVSlothCombo/Combos/JobHelpers/RDM.cs b/XIVSlothCombo/Combos/JobHelpers/RDM.cs index fd47b8978..d52550a74 100644 --- a/XIVSlothCombo/Combos/JobHelpers/RDM.cs +++ b/XIVSlothCombo/Combos/JobHelpers/RDM.cs @@ -9,7 +9,7 @@ internal class RDM static float GetBuffRemainingTime(ushort effectid) => CustomComboFunctions.GetBuffRemainingTime(effectid); static bool LevelChecked(uint id) => CustomComboFunctions.LevelChecked(id); static float GetActionCastTime(uint actionID) => CustomComboFunctions.GetActionCastTime(actionID); - static uint GetRemainingCharges(uint actionID) => CustomComboFunctions.GetRemainingCharges(actionID); + static ushort GetRemainingCharges(uint actionID) => CustomComboFunctions.GetRemainingCharges(actionID); static float GetCooldownRemainingTime(uint actionID) => CustomComboFunctions.GetCooldownRemainingTime(actionID); static bool ActionReady(uint id) => CustomComboFunctions.ActionReady(id); static bool CanSpellWeave(uint id) => CustomComboFunctions.CanSpellWeave(id); diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 52d3df5af..019867966 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -654,7 +654,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Bloodletter) && ((!openerFinished && IsOnCooldown(RagingStrikes)) || openerFinished)) { - uint bloodletterCharges = GetRemainingCharges(Bloodletter); + ushort bloodletterCharges = GetRemainingCharges(Bloodletter); if (IsEnabled(CustomComboPreset.BRD_Simple_Pooling) && LevelChecked(WanderersMinuet)) { diff --git a/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs b/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs index 728f9b843..5debbfc13 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs @@ -50,7 +50,7 @@ internal abstract partial class CustomComboFunctions /// Get the current number of charges remaining for an action. /// Action ID to check. /// Number of charges. - public static uint GetRemainingCharges(uint actionID) => GetCooldown(actionID).RemainingCharges; + public static ushort GetRemainingCharges(uint actionID) => GetCooldown(actionID).RemainingCharges; /// Get the maximum number of charges for an action. /// Action ID to check. diff --git a/XIVSlothCombo/Data/CooldownData.cs b/XIVSlothCombo/Data/CooldownData.cs index 5e27d87a7..2e836f964 100644 --- a/XIVSlothCombo/Data/CooldownData.cs +++ b/XIVSlothCombo/Data/CooldownData.cs @@ -1,55 +1,114 @@ -using FFXIVClientStructs.FFXIV.Client.Game; +using System.Runtime.InteropServices; using XIVSlothCombo.Services; namespace XIVSlothCombo.Data { - internal class CooldownData + /// Internal cooldown data. + [StructLayout(LayoutKind.Explicit)] + internal struct CooldownData { + [FieldOffset(0x0)] + private readonly bool isCooldown; + + [FieldOffset(0x4)] + private readonly uint actionID; + + [FieldOffset(0x8)] + private readonly float cooldownElapsed; + + [FieldOffset(0xC)] + private float cooldownTotal; + /// Gets a value indicating whether the action is on cooldown. - public bool IsCooldown + public readonly bool IsCooldown { get { - return RemainingCharges == MaxCharges - ? false - : CooldownElapsed < CooldownTotal; + var (cur, max) = Service.ComboCache.GetMaxCharges(ActionID); + return cur == max + ? isCooldown + : cooldownElapsed < CooldownTotal; } } /// Gets the action ID on cooldown. - public uint ActionID; + public readonly uint ActionID => actionID; /// Gets the elapsed cooldown time. - public unsafe float CooldownElapsed => ActionManager.Instance()->GetRecastGroupDetail(ActionManager.Instance()->GetRecastGroup(1, ActionID))->Elapsed; + public readonly float CooldownElapsed + { + get + { + if (cooldownElapsed == 0) + return 0; + + if (cooldownElapsed > CooldownTotal) + return 0; + + return cooldownElapsed; + } + } /// Gets the total cooldown time. - public unsafe float CooldownTotal => (ActionManager.GetAdjustedRecastTime(ActionType.Action, ActionID) / 1000f) * MaxCharges; + public float CooldownTotal + { + readonly get + { + if (cooldownTotal == 0) + return 0; + + var (cur, max) = Service.ComboCache.GetMaxCharges(ActionID); + + if (cur == max) + return cooldownTotal; + + // Rebase to the current charge count + float total = cooldownTotal / max * cur; + + return cooldownElapsed > total + ? 0 + : total; + } + set + { + cooldownTotal = value; + } + } /// Gets the cooldown time remaining. - public unsafe float CooldownRemaining => CooldownTotal - CooldownElapsed; + public readonly float CooldownRemaining => IsCooldown ? CooldownTotal - CooldownElapsed : 0; /// Gets the maximum number of charges for an action at the current level. /// Number of charges. - public ushort MaxCharges => Service.ComboCache.GetMaxCharges(ActionID); + public readonly ushort MaxCharges => Service.ComboCache.GetMaxCharges(ActionID).Current; /// Gets a value indicating whether the action has charges, not charges available. - public bool HasCharges => MaxCharges > 1; + public readonly bool HasCharges => MaxCharges > 1; /// Gets the remaining number of charges for an action. - public unsafe uint RemainingCharges => ActionManager.Instance()->GetCurrentCharges(ActionID); + public readonly ushort RemainingCharges + { + get + { + var (cur, _) = Service.ComboCache.GetMaxCharges(ActionID); + + return !IsCooldown + ? cur + : (ushort)(CooldownElapsed / (CooldownTotal / MaxCharges)); + } + } /// Gets the cooldown time remaining until the next charge. - public float ChargeCooldownRemaining + public readonly float ChargeCooldownRemaining { get { if (!IsCooldown) return 0; - var maxCharges = ActionManager.GetMaxCharges(ActionID, 100); - var timePerCharge = CooldownTotal / maxCharges; + var (cur, _) = Service.ComboCache.GetMaxCharges(ActionID); - return CooldownRemaining % (CooldownTotal / MaxCharges); + return CooldownRemaining % (CooldownTotal / cur); } } } diff --git a/XIVSlothCombo/Data/CustomComboCache.cs b/XIVSlothCombo/Data/CustomComboCache.cs index c49e564d4..7a3bb7aac 100644 --- a/XIVSlothCombo/Data/CustomComboCache.cs +++ b/XIVSlothCombo/Data/CustomComboCache.cs @@ -81,18 +81,46 @@ internal unsafe CooldownData GetCooldown(uint actionID) if (actionManager == null) return cooldownCache[actionID] = default; - CooldownData data = new() + byte cooldownGroup = GetCooldownGroup(actionID); + + RecastDetail* cooldownPtr = actionManager->GetRecastGroupDetail(cooldownGroup - 1); + if (cooldownPtr is null) { - ActionID = actionID, - }; + CooldownData data = new() + { + CooldownTotal = -1 + }; + + return cooldownCache[actionID] = data; + } - return cooldownCache[actionID] = data; + cooldownPtr->ActionId = actionID; + + return cooldownCache[actionID] = *(CooldownData*)cooldownPtr; } /// Get the maximum number of charges for an action. /// Action ID to check. - /// Max number of charges at current level. - internal unsafe ushort GetMaxCharges(uint actionID) => ActionManager.GetMaxCharges(actionID, 0); + /// Max number of charges at current and max level. + internal unsafe (ushort Current, ushort Max) GetMaxCharges(uint actionID) + { + IPlayerCharacter? player = Service.ClientState.LocalPlayer; + if (player == null) + return (0, 0); + + uint job = player.ClassJob.Id; + byte level = player.Level; + if (job == 0 || level == 0) + return (0, 0); + + var key = (actionID, job, level); + if (chargesCache.TryGetValue(key, out var found)) + return found; + + ushort cur = ActionManager.GetMaxCharges(actionID, 0); + ushort max = ActionManager.GetMaxCharges(actionID, 90); + return chargesCache[key] = (cur, max); + } /// Get the resource cost of an action. /// Action ID to check. From e1e226cc0ab56d332751369dc6e73aa801cd26c9 Mon Sep 17 00:00:00 2001 From: Taurenkey Date: Sun, 30 Jun 2024 19:11:02 +0100 Subject: [PATCH 3/3] Fix cooldown data --- XIVSlothCombo/Combos/JobHelpers/RDM.cs | 2 +- XIVSlothCombo/Combos/PvE/BRD.cs | 2 +- .../CustomCombo/Functions/Cooldown.cs | 2 +- XIVSlothCombo/Data/CooldownData.cs | 93 ++++--------------- XIVSlothCombo/Data/CustomComboCache.cs | 40 ++------ XIVSlothCombo/Window/Tabs/Debug.cs | 1 + 6 files changed, 27 insertions(+), 113 deletions(-) diff --git a/XIVSlothCombo/Combos/JobHelpers/RDM.cs b/XIVSlothCombo/Combos/JobHelpers/RDM.cs index d52550a74..fd47b8978 100644 --- a/XIVSlothCombo/Combos/JobHelpers/RDM.cs +++ b/XIVSlothCombo/Combos/JobHelpers/RDM.cs @@ -9,7 +9,7 @@ internal class RDM static float GetBuffRemainingTime(ushort effectid) => CustomComboFunctions.GetBuffRemainingTime(effectid); static bool LevelChecked(uint id) => CustomComboFunctions.LevelChecked(id); static float GetActionCastTime(uint actionID) => CustomComboFunctions.GetActionCastTime(actionID); - static ushort GetRemainingCharges(uint actionID) => CustomComboFunctions.GetRemainingCharges(actionID); + static uint GetRemainingCharges(uint actionID) => CustomComboFunctions.GetRemainingCharges(actionID); static float GetCooldownRemainingTime(uint actionID) => CustomComboFunctions.GetCooldownRemainingTime(actionID); static bool ActionReady(uint id) => CustomComboFunctions.ActionReady(id); static bool CanSpellWeave(uint id) => CustomComboFunctions.CanSpellWeave(id); diff --git a/XIVSlothCombo/Combos/PvE/BRD.cs b/XIVSlothCombo/Combos/PvE/BRD.cs index 019867966..52d3df5af 100644 --- a/XIVSlothCombo/Combos/PvE/BRD.cs +++ b/XIVSlothCombo/Combos/PvE/BRD.cs @@ -654,7 +654,7 @@ protected override uint Invoke(uint actionID, uint lastComboMove, float comboTim if (LevelChecked(Bloodletter) && ((!openerFinished && IsOnCooldown(RagingStrikes)) || openerFinished)) { - ushort bloodletterCharges = GetRemainingCharges(Bloodletter); + uint bloodletterCharges = GetRemainingCharges(Bloodletter); if (IsEnabled(CustomComboPreset.BRD_Simple_Pooling) && LevelChecked(WanderersMinuet)) { diff --git a/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs b/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs index 5debbfc13..728f9b843 100644 --- a/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs +++ b/XIVSlothCombo/CustomCombo/Functions/Cooldown.cs @@ -50,7 +50,7 @@ internal abstract partial class CustomComboFunctions /// Get the current number of charges remaining for an action. /// Action ID to check. /// Number of charges. - public static ushort GetRemainingCharges(uint actionID) => GetCooldown(actionID).RemainingCharges; + public static uint GetRemainingCharges(uint actionID) => GetCooldown(actionID).RemainingCharges; /// Get the maximum number of charges for an action. /// Action ID to check. diff --git a/XIVSlothCombo/Data/CooldownData.cs b/XIVSlothCombo/Data/CooldownData.cs index 2e836f964..5e27d87a7 100644 --- a/XIVSlothCombo/Data/CooldownData.cs +++ b/XIVSlothCombo/Data/CooldownData.cs @@ -1,114 +1,55 @@ -using System.Runtime.InteropServices; +using FFXIVClientStructs.FFXIV.Client.Game; using XIVSlothCombo.Services; namespace XIVSlothCombo.Data { - /// Internal cooldown data. - [StructLayout(LayoutKind.Explicit)] - internal struct CooldownData + internal class CooldownData { - [FieldOffset(0x0)] - private readonly bool isCooldown; - - [FieldOffset(0x4)] - private readonly uint actionID; - - [FieldOffset(0x8)] - private readonly float cooldownElapsed; - - [FieldOffset(0xC)] - private float cooldownTotal; - /// Gets a value indicating whether the action is on cooldown. - public readonly bool IsCooldown + public bool IsCooldown { get { - var (cur, max) = Service.ComboCache.GetMaxCharges(ActionID); - return cur == max - ? isCooldown - : cooldownElapsed < CooldownTotal; + return RemainingCharges == MaxCharges + ? false + : CooldownElapsed < CooldownTotal; } } /// Gets the action ID on cooldown. - public readonly uint ActionID => actionID; + public uint ActionID; /// Gets the elapsed cooldown time. - public readonly float CooldownElapsed - { - get - { - if (cooldownElapsed == 0) - return 0; - - if (cooldownElapsed > CooldownTotal) - return 0; - - return cooldownElapsed; - } - } + public unsafe float CooldownElapsed => ActionManager.Instance()->GetRecastGroupDetail(ActionManager.Instance()->GetRecastGroup(1, ActionID))->Elapsed; /// Gets the total cooldown time. - public float CooldownTotal - { - readonly get - { - if (cooldownTotal == 0) - return 0; - - var (cur, max) = Service.ComboCache.GetMaxCharges(ActionID); - - if (cur == max) - return cooldownTotal; - - // Rebase to the current charge count - float total = cooldownTotal / max * cur; - - return cooldownElapsed > total - ? 0 - : total; - } - set - { - cooldownTotal = value; - } - } + public unsafe float CooldownTotal => (ActionManager.GetAdjustedRecastTime(ActionType.Action, ActionID) / 1000f) * MaxCharges; /// Gets the cooldown time remaining. - public readonly float CooldownRemaining => IsCooldown ? CooldownTotal - CooldownElapsed : 0; + public unsafe float CooldownRemaining => CooldownTotal - CooldownElapsed; /// Gets the maximum number of charges for an action at the current level. /// Number of charges. - public readonly ushort MaxCharges => Service.ComboCache.GetMaxCharges(ActionID).Current; + public ushort MaxCharges => Service.ComboCache.GetMaxCharges(ActionID); /// Gets a value indicating whether the action has charges, not charges available. - public readonly bool HasCharges => MaxCharges > 1; + public bool HasCharges => MaxCharges > 1; /// Gets the remaining number of charges for an action. - public readonly ushort RemainingCharges - { - get - { - var (cur, _) = Service.ComboCache.GetMaxCharges(ActionID); - - return !IsCooldown - ? cur - : (ushort)(CooldownElapsed / (CooldownTotal / MaxCharges)); - } - } + public unsafe uint RemainingCharges => ActionManager.Instance()->GetCurrentCharges(ActionID); /// Gets the cooldown time remaining until the next charge. - public readonly float ChargeCooldownRemaining + public float ChargeCooldownRemaining { get { if (!IsCooldown) return 0; - var (cur, _) = Service.ComboCache.GetMaxCharges(ActionID); + var maxCharges = ActionManager.GetMaxCharges(ActionID, 100); + var timePerCharge = CooldownTotal / maxCharges; - return CooldownRemaining % (CooldownTotal / cur); + return CooldownRemaining % (CooldownTotal / MaxCharges); } } } diff --git a/XIVSlothCombo/Data/CustomComboCache.cs b/XIVSlothCombo/Data/CustomComboCache.cs index 7a3bb7aac..c49e564d4 100644 --- a/XIVSlothCombo/Data/CustomComboCache.cs +++ b/XIVSlothCombo/Data/CustomComboCache.cs @@ -81,46 +81,18 @@ internal unsafe CooldownData GetCooldown(uint actionID) if (actionManager == null) return cooldownCache[actionID] = default; - byte cooldownGroup = GetCooldownGroup(actionID); - - RecastDetail* cooldownPtr = actionManager->GetRecastGroupDetail(cooldownGroup - 1); - if (cooldownPtr is null) + CooldownData data = new() { - CooldownData data = new() - { - CooldownTotal = -1 - }; - - return cooldownCache[actionID] = data; - } + ActionID = actionID, + }; - cooldownPtr->ActionId = actionID; - - return cooldownCache[actionID] = *(CooldownData*)cooldownPtr; + return cooldownCache[actionID] = data; } /// Get the maximum number of charges for an action. /// Action ID to check. - /// Max number of charges at current and max level. - internal unsafe (ushort Current, ushort Max) GetMaxCharges(uint actionID) - { - IPlayerCharacter? player = Service.ClientState.LocalPlayer; - if (player == null) - return (0, 0); - - uint job = player.ClassJob.Id; - byte level = player.Level; - if (job == 0 || level == 0) - return (0, 0); - - var key = (actionID, job, level); - if (chargesCache.TryGetValue(key, out var found)) - return found; - - ushort cur = ActionManager.GetMaxCharges(actionID, 0); - ushort max = ActionManager.GetMaxCharges(actionID, 90); - return chargesCache[key] = (cur, max); - } + /// Max number of charges at current level. + internal unsafe ushort GetMaxCharges(uint actionID) => ActionManager.GetMaxCharges(actionID, 0); /// Get the resource cost of an action. /// Action ID to check. diff --git a/XIVSlothCombo/Window/Tabs/Debug.cs b/XIVSlothCombo/Window/Tabs/Debug.cs index 0af885d6d..d6daf94d1 100644 --- a/XIVSlothCombo/Window/Tabs/Debug.cs +++ b/XIVSlothCombo/Window/Tabs/Debug.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Numerics; using XIVSlothCombo.Combos; +using XIVSlothCombo.Combos.PvE; using XIVSlothCombo.CustomComboNS; using XIVSlothCombo.CustomComboNS.Functions; using XIVSlothCombo.Data;