mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-13 12:14:18 +01:00
Handle ItemOffhand and fix weapon plugin load order dependency.
This commit is contained in:
parent
4618e73c25
commit
bdcc6cb4de
4 changed files with 51 additions and 30 deletions
|
|
@ -164,8 +164,9 @@ public class PenumbraChangedItemTooltip : IDisposable
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
case ChangedItemType.ItemOffhand:
|
||||||
case ChangedItemType.Item:
|
case ChangedItemType.Item:
|
||||||
if (!_items.ItemService.AwaitedService.TryGetValue(id, EquipSlot.MainHand, out var item))
|
if (!_items.ItemService.AwaitedService.TryGetValue(id, type is ChangedItemType.Item ? EquipSlot.MainHand : EquipSlot.OffHand, out var item))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CreateTooltip(item, "[Glamourer] ", false);
|
CreateTooltip(item, "[Glamourer] ", false);
|
||||||
|
|
@ -189,13 +190,14 @@ public class PenumbraChangedItemTooltip : IDisposable
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ChangedItemType.Item:
|
case ChangedItemType.Item:
|
||||||
|
case ChangedItemType.ItemOffhand:
|
||||||
if (button is not MouseButton.Right)
|
if (button is not MouseButton.Right)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!Player(out var state))
|
if (!Player(out var state))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!_items.ItemService.AwaitedService.TryGetValue(id, EquipSlot.MainHand, out var item))
|
if (!_items.ItemService.AwaitedService.TryGetValue(id, type is ChangedItemType.Item ? EquipSlot.MainHand : EquipSlot.OffHand, out var item))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ApplyItem(state, item);
|
ApplyItem(state, item);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility.Signatures;
|
|
||||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||||
using Glamourer.Events;
|
using Glamourer.Events;
|
||||||
using Glamourer.Interop.Structs;
|
using Glamourer.Interop.Structs;
|
||||||
|
|
@ -13,19 +13,26 @@ namespace Glamourer.Interop;
|
||||||
public unsafe class WeaponService : IDisposable
|
public unsafe class WeaponService : IDisposable
|
||||||
{
|
{
|
||||||
private readonly WeaponLoading _event;
|
private readonly WeaponLoading _event;
|
||||||
|
private readonly ThreadLocal<bool> _inUpdate = new(() => false);
|
||||||
|
|
||||||
|
|
||||||
|
private readonly delegate* unmanaged[Stdcall]<DrawDataContainer*, uint, ulong, byte, byte, byte, byte, void>
|
||||||
|
_original;
|
||||||
|
|
||||||
|
|
||||||
public WeaponService(WeaponLoading @event, IGameInteropProvider interop)
|
public WeaponService(WeaponLoading @event, IGameInteropProvider interop)
|
||||||
{
|
{
|
||||||
_event = @event;
|
_event = @event;
|
||||||
_loadWeaponHook =
|
_loadWeaponHook =
|
||||||
interop.HookFromAddress<LoadWeaponDelegate>((nint)DrawDataContainer.MemberFunctionPointers.LoadWeapon, LoadWeaponDetour);
|
interop.HookFromAddress<LoadWeaponDelegate>((nint)DrawDataContainer.MemberFunctionPointers.LoadWeapon, LoadWeaponDetour);
|
||||||
|
_original =
|
||||||
|
(delegate* unmanaged[Stdcall] < DrawDataContainer*, uint, ulong, byte, byte, byte, byte, void >)
|
||||||
|
DrawDataContainer.MemberFunctionPointers.LoadWeapon;
|
||||||
_loadWeaponHook.Enable();
|
_loadWeaponHook.Enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
=> _loadWeaponHook.Dispose();
|
||||||
_loadWeaponHook.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Weapons for a specific character are reloaded with this function.
|
// Weapons for a specific character are reloaded with this function.
|
||||||
// slot is 0 for main hand, 1 for offhand, 2 for combat effects.
|
// slot is 0 for main hand, 1 for offhand, 2 for combat effects.
|
||||||
|
|
@ -41,6 +48,8 @@ public unsafe class WeaponService : IDisposable
|
||||||
|
|
||||||
private void LoadWeaponDetour(DrawDataContainer* drawData, uint slot, ulong weaponValue, byte redrawOnEquality, byte unk2,
|
private void LoadWeaponDetour(DrawDataContainer* drawData, uint slot, ulong weaponValue, byte redrawOnEquality, byte unk2,
|
||||||
byte skipGameObject, byte unk4)
|
byte skipGameObject, byte unk4)
|
||||||
|
{
|
||||||
|
if (!_inUpdate.Value)
|
||||||
{
|
{
|
||||||
var actor = (Actor)((nint*)drawData)[1];
|
var actor = (Actor)((nint*)drawData)[1];
|
||||||
var weapon = new CharacterWeapon(weaponValue);
|
var weapon = new CharacterWeapon(weaponValue);
|
||||||
|
|
@ -67,6 +76,11 @@ public unsafe class WeaponService : IDisposable
|
||||||
Glamourer.Log.Excessive(
|
Glamourer.Log.Excessive(
|
||||||
$"Weapon reloaded for 0x{actor.Address:X} ({actor.Utf8Name}) with attributes {slot} {weapon.Value:X14}, {redrawOnEquality}, {unk2}, {skipGameObject}, {unk4}");
|
$"Weapon reloaded for 0x{actor.Address:X} ({actor.Utf8Name}) with attributes {slot} {weapon.Value:X14}, {redrawOnEquality}, {unk2}, {skipGameObject}, {unk4}");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_original(drawData, slot, weaponValue, redrawOnEquality, unk2, skipGameObject, unk4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Load a specific weapon for a character by its data and slot.
|
// Load a specific weapon for a character by its data and slot.
|
||||||
public void LoadWeapon(Actor character, EquipSlot slot, CharacterWeapon weapon)
|
public void LoadWeapon(Actor character, EquipSlot slot, CharacterWeapon weapon)
|
||||||
|
|
@ -74,16 +88,21 @@ public unsafe class WeaponService : IDisposable
|
||||||
switch (slot)
|
switch (slot)
|
||||||
{
|
{
|
||||||
case EquipSlot.MainHand:
|
case EquipSlot.MainHand:
|
||||||
|
_inUpdate.Value = true;
|
||||||
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 1, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 1, 0, 1, 0);
|
||||||
|
_inUpdate.Value = false;
|
||||||
return;
|
return;
|
||||||
case EquipSlot.OffHand:
|
case EquipSlot.OffHand:
|
||||||
|
_inUpdate.Value = true;
|
||||||
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, weapon.Value, 1, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, weapon.Value, 1, 0, 1, 0);
|
||||||
|
_inUpdate.Value = false;
|
||||||
return;
|
return;
|
||||||
case EquipSlot.BothHand:
|
case EquipSlot.BothHand:
|
||||||
|
_inUpdate.Value = true;
|
||||||
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 1, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 1, 0, 1, 0);
|
||||||
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, CharacterWeapon.Empty.Value, 1, 0, 1, 0);
|
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, CharacterWeapon.Empty.Value, 1, 0, 1, 0);
|
||||||
|
_inUpdate.Value = false;
|
||||||
return;
|
return;
|
||||||
// function can also be called with '2', but does not seem to ever be.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit f9069dfdf1f0a7011c3b0ea7c0be5330c42959dd
|
Subproject commit 80f9793ef2ddaa50246b7112fde4d9b2098d8823
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4dd261fe837bbe4b799b3ca3c0c8c178197bc48f
|
Subproject commit e1a62d8e6b4e1d8c482253ad14850fd3dc372d86
|
||||||
Loading…
Add table
Add a link
Reference in a new issue