mirror of
https://github.com/Ottermandias/Glamourer.git
synced 2025-12-12 18:27:24 +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)
|
||||
{
|
||||
case ChangedItemType.ItemOffhand:
|
||||
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;
|
||||
|
||||
CreateTooltip(item, "[Glamourer] ", false);
|
||||
|
|
@ -189,13 +190,14 @@ public class PenumbraChangedItemTooltip : IDisposable
|
|||
switch (type)
|
||||
{
|
||||
case ChangedItemType.Item:
|
||||
case ChangedItemType.ItemOffhand:
|
||||
if (button is not MouseButton.Right)
|
||||
return;
|
||||
|
||||
if (!Player(out var state))
|
||||
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;
|
||||
|
||||
ApplyItem(state, item);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Dalamud.Utility.Signatures;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using Glamourer.Events;
|
||||
using Glamourer.Interop.Structs;
|
||||
|
|
@ -12,20 +12,27 @@ namespace Glamourer.Interop;
|
|||
|
||||
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)
|
||||
{
|
||||
_event = @event;
|
||||
_loadWeaponHook =
|
||||
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();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_loadWeaponHook.Dispose();
|
||||
}
|
||||
=> _loadWeaponHook.Dispose();
|
||||
|
||||
// Weapons for a specific character are reloaded with this function.
|
||||
// slot is 0 for main hand, 1 for offhand, 2 for combat effects.
|
||||
|
|
@ -42,30 +49,37 @@ public unsafe class WeaponService : IDisposable
|
|||
private void LoadWeaponDetour(DrawDataContainer* drawData, uint slot, ulong weaponValue, byte redrawOnEquality, byte unk2,
|
||||
byte skipGameObject, byte unk4)
|
||||
{
|
||||
var actor = (Actor)((nint*)drawData)[1];
|
||||
var weapon = new CharacterWeapon(weaponValue);
|
||||
var equipSlot = slot switch
|
||||
if (!_inUpdate.Value)
|
||||
{
|
||||
0 => EquipSlot.MainHand,
|
||||
1 => EquipSlot.OffHand,
|
||||
_ => EquipSlot.Unknown,
|
||||
};
|
||||
var actor = (Actor)((nint*)drawData)[1];
|
||||
var weapon = new CharacterWeapon(weaponValue);
|
||||
var equipSlot = slot switch
|
||||
{
|
||||
0 => EquipSlot.MainHand,
|
||||
1 => EquipSlot.OffHand,
|
||||
_ => EquipSlot.Unknown,
|
||||
};
|
||||
|
||||
var tmpWeapon = weapon;
|
||||
// First call the regular function.
|
||||
if (equipSlot is not EquipSlot.Unknown)
|
||||
_event.Invoke(actor, equipSlot, ref tmpWeapon);
|
||||
var tmpWeapon = weapon;
|
||||
// First call the regular function.
|
||||
if (equipSlot is not EquipSlot.Unknown)
|
||||
_event.Invoke(actor, equipSlot, ref tmpWeapon);
|
||||
|
||||
_loadWeaponHook.Original(drawData, slot, weapon.Value, redrawOnEquality, unk2, skipGameObject, unk4);
|
||||
if (tmpWeapon.Value != weapon.Value)
|
||||
{
|
||||
if (tmpWeapon.Set.Id == 0)
|
||||
tmpWeapon.Stain = 0;
|
||||
_loadWeaponHook.Original(drawData, slot, tmpWeapon.Value, 1, unk2, 1, unk4);
|
||||
_loadWeaponHook.Original(drawData, slot, weapon.Value, redrawOnEquality, unk2, skipGameObject, unk4);
|
||||
if (tmpWeapon.Value != weapon.Value)
|
||||
{
|
||||
if (tmpWeapon.Set.Id == 0)
|
||||
tmpWeapon.Stain = 0;
|
||||
_loadWeaponHook.Original(drawData, slot, tmpWeapon.Value, 1, unk2, 1, unk4);
|
||||
}
|
||||
|
||||
Glamourer.Log.Excessive(
|
||||
$"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);
|
||||
}
|
||||
|
||||
Glamourer.Log.Excessive(
|
||||
$"Weapon reloaded for 0x{actor.Address:X} ({actor.Utf8Name}) with attributes {slot} {weapon.Value:X14}, {redrawOnEquality}, {unk2}, {skipGameObject}, {unk4}");
|
||||
}
|
||||
|
||||
// Load a specific weapon for a character by its data and slot.
|
||||
|
|
@ -74,16 +88,21 @@ public unsafe class WeaponService : IDisposable
|
|||
switch (slot)
|
||||
{
|
||||
case EquipSlot.MainHand:
|
||||
_inUpdate.Value = true;
|
||||
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 0, weapon.Value, 1, 0, 1, 0);
|
||||
_inUpdate.Value = false;
|
||||
return;
|
||||
case EquipSlot.OffHand:
|
||||
_inUpdate.Value = true;
|
||||
_loadWeaponHook.Original(&character.AsCharacter->DrawData, 1, weapon.Value, 1, 0, 1, 0);
|
||||
_inUpdate.Value = false;
|
||||
return;
|
||||
case EquipSlot.BothHand:
|
||||
_inUpdate.Value = true;
|
||||
_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);
|
||||
_inUpdate.Value = false;
|
||||
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