v1.0.7.0: Hotbar charge count on slots; fix WndProc restore on unload (left-click after disable)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -50,8 +50,12 @@ namespace HSUI.Helpers
|
||||
public RaptureHotbarModule.HotbarSlotType SlotType { get; }
|
||||
/// <summary>Keybind hint from game (user's keybind settings). Empty if unavailable.</summary>
|
||||
public string KeybindHint { get; }
|
||||
/// <summary>Current charges for charge-based actions; 0 when not applicable.</summary>
|
||||
public int CurrentCharges { get; }
|
||||
/// <summary>Max charges for charge-based actions; >1 only for actions with charges.</summary>
|
||||
public int MaxCharges { get; }
|
||||
|
||||
public SlotInfo(uint iconId, bool isEmpty, bool usable, int cooldownPct, int cooldownSecs, uint actionId = 0, RaptureHotbarModule.HotbarSlotType slotType = 0, string keybindHint = "")
|
||||
public SlotInfo(uint iconId, bool isEmpty, bool usable, int cooldownPct, int cooldownSecs, uint actionId = 0, RaptureHotbarModule.HotbarSlotType slotType = 0, string keybindHint = "", int currentCharges = 0, int maxCharges = 0)
|
||||
{
|
||||
IconId = iconId;
|
||||
IsEmpty = isEmpty;
|
||||
@@ -61,6 +65,8 @@ namespace HSUI.Helpers
|
||||
ActionId = actionId;
|
||||
SlotType = slotType;
|
||||
KeybindHint = keybindHint ?? "";
|
||||
CurrentCharges = currentCharges;
|
||||
MaxCharges = maxCharges;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,13 +112,13 @@ namespace HSUI.Helpers
|
||||
|
||||
if (slot == null)
|
||||
{
|
||||
list.Add(new SlotInfo(0, true, false, 0, 0, 0, 0, keybind));
|
||||
list.Add(new SlotInfo(0, true, false, 0, 0, 0, 0, keybind, 0, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (slot->IsEmpty)
|
||||
{
|
||||
list.Add(new SlotInfo(0, true, false, 0, 0, 0, 0, keybind));
|
||||
list.Add(new SlotInfo(0, true, false, 0, 0, 0, 0, keybind, 0, 0));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -122,7 +128,8 @@ namespace HSUI.Helpers
|
||||
var slotType = slot->ApparentSlotType;
|
||||
|
||||
(int pct, int secsLeft) = GetSlotCooldown(slot);
|
||||
list.Add(new SlotInfo(iconId, false, usable, pct, secsLeft, actionId, slotType, keybind));
|
||||
(int currentCharges, int maxCharges) = GetSlotCharges(slotType, actionId);
|
||||
list.Add(new SlotInfo(iconId, false, usable, pct, secsLeft, actionId, slotType, keybind, currentCharges, maxCharges));
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -132,6 +139,27 @@ namespace HSUI.Helpers
|
||||
/// Gets cooldown for a hotbar slot. For Action/GeneralAction/PetAction, uses ActionManager recast API
|
||||
/// (more accurate for adjusted IDs, recast groups). Falls back to slot's GetSlotActionCooldownPercentage for Items/Macros.
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets current and max charges for a slot. Only applies to Action type; returns (0,0) otherwise.
|
||||
/// </summary>
|
||||
private static unsafe (int CurrentCharges, int MaxCharges) GetSlotCharges(RaptureHotbarModule.HotbarSlotType slotType, uint actionId)
|
||||
{
|
||||
if (slotType != RaptureHotbarModule.HotbarSlotType.Action || actionId == 0)
|
||||
return (0, 0);
|
||||
|
||||
var actionManager = ActionManager.Instance();
|
||||
if (actionManager == null)
|
||||
return (0, 0);
|
||||
|
||||
uint effectiveId = actionManager->GetAdjustedActionId(actionId);
|
||||
ushort maxCh = ActionManager.GetMaxCharges(effectiveId, 0);
|
||||
if (maxCh <= 1)
|
||||
return (0, 0);
|
||||
|
||||
uint currentCh = actionManager->GetCurrentCharges(effectiveId);
|
||||
return ((int)currentCh, (int)maxCh);
|
||||
}
|
||||
|
||||
private static unsafe (int CooldownPercent, int SecondsLeft) GetSlotCooldown(RaptureHotbarModule.HotbarSlot* slot)
|
||||
{
|
||||
if (slot == null) return (0, 0);
|
||||
|
||||
+28
-11
@@ -142,8 +142,22 @@ namespace HSUI.Helpers
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigurationManager.Instance.ResetEvent -= OnConfigReset;
|
||||
Plugin.Framework.Update -= OnFrameworkUpdate;
|
||||
// Restore WndProc first so left-click works again immediately after unload.
|
||||
// After a game/Dalamud patch, other singletons may be disposed before us;
|
||||
// if we unsub or touch config first and that throws, we would never restore and LButton stays broken.
|
||||
RestoreWndProc();
|
||||
|
||||
try
|
||||
{
|
||||
ConfigurationManager.Instance.ResetEvent -= OnConfigReset;
|
||||
}
|
||||
catch { /* Instance may already be disposed */ }
|
||||
|
||||
try
|
||||
{
|
||||
Plugin.Framework.Update -= OnFrameworkUpdate;
|
||||
}
|
||||
catch { /* Framework may already be disposed */ }
|
||||
|
||||
Plugin.Logger.Info("\t\tDisposing _requestActionHook: " + (_requestActionHook?.Address.ToString("X") ?? "null"));
|
||||
_requestActionHook?.Disable();
|
||||
@@ -151,9 +165,6 @@ namespace HSUI.Helpers
|
||||
_executeSlotByIdHook?.Disable();
|
||||
_executeSlotByIdHook?.Dispose();
|
||||
|
||||
// give imgui the control of inputs again
|
||||
RestoreWndProc();
|
||||
|
||||
Instance = null!;
|
||||
}
|
||||
#endregion
|
||||
@@ -556,15 +567,21 @@ namespace HSUI.Helpers
|
||||
|
||||
private void RestoreWndProc()
|
||||
{
|
||||
if (_wndHandle != IntPtr.Zero && _imguiWndProcPtr != IntPtr.Zero)
|
||||
if (_wndHandle == IntPtr.Zero || _imguiWndProcPtr == IntPtr.Zero)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Plugin.Logger.Info("\t\tRestoring WndProc");
|
||||
Plugin.Logger.Info("\t\t\tOld _wndHandle = " + _wndHandle.ToString("X"));
|
||||
Plugin.Logger.Info("\t\t\tOld _imguiWndProcPtr = " + _imguiWndProcPtr.ToString("X"));
|
||||
|
||||
SetWindowLongPtr(_wndHandle, GWL_WNDPROC, _imguiWndProcPtr);
|
||||
Plugin.Logger.Info("\t\t\tDone!");
|
||||
|
||||
Plugin.Logger.Info("\t\t\tWndProc restored.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Plugin.Logger.Warning($"\t\tRestoreWndProc failed: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_wndHandle = IntPtr.Zero;
|
||||
_imguiWndProcPtr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user