This commit is contained in:
Ottermandias 2023-06-20 18:54:33 +02:00
parent d1d369a56b
commit 65ce391051
19 changed files with 757 additions and 158 deletions

View file

@ -113,6 +113,17 @@ public class ObjectManager : IReadOnlyDictionary<ActorIdentifier, ActorData>
public Actor Player
=> _objects.GetObjectAddress(0);
public (ActorIdentifier Identifier, ActorData Data) PlayerData
{
get
{
Update();
return Player.Identifier(_actors.AwaitedService, out var ident) && _identifiers.TryGetValue(ident, out var data)
? (ident, data)
: (ActorIdentifier.Invalid, ActorData.Invalid);
}
}
public IEnumerator<KeyValuePair<ActorIdentifier, ActorData>> GetEnumerator()
=> Identifiers.GetEnumerator();

View file

@ -10,11 +10,11 @@ namespace Glamourer.Interop;
public unsafe class UpdateSlotService : IDisposable
{
public readonly UpdatedSlot Event;
public readonly SlotUpdating Event;
public UpdateSlotService(UpdatedSlot updatedSlot)
public UpdateSlotService(SlotUpdating slotUpdating)
{
Event = updatedSlot;
Event = slotUpdating;
SignatureHelper.Initialise(this);
_flagSlotForUpdateHook.Enable();
}

View file

@ -23,13 +23,7 @@ public class VisorService : IDisposable
/// <summary> Obtain the current state of the Visor for the given draw object (true: toggled). </summary>
public unsafe bool GetVisorState(Model characterBase)
{
if (!characterBase.IsCharacterBase)
return false;
// TODO: use client structs.
return (characterBase.AsCharacterBase->UnkFlags_01 & Offsets.DrawObjectVisorStateFlag) != 0;
}
=> characterBase.IsCharacterBase && characterBase.AsCharacterBase->VisorToggled;
/// <summary> Manually set the state of the Visor for the given draw object. </summary>
/// <param name="human"> The draw object. </param>
@ -45,7 +39,6 @@ public class VisorService : IDisposable
if (oldState == on)
return false;
SetupVisorHook(human, (ushort)human.AsHuman->HeadSetID, on);
return true;
}

View file

@ -2,6 +2,7 @@
using Dalamud.Hooking;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using Glamourer.Events;
using Glamourer.Interop.Structs;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
@ -10,8 +11,11 @@ namespace Glamourer.Interop;
public unsafe class WeaponService : IDisposable
{
public WeaponService()
private readonly WeaponLoading _event;
public WeaponService(WeaponLoading @event)
{
_event = @event;
SignatureHelper.Initialise(this);
_loadWeaponHook = Hook<LoadWeaponDelegate>.FromAddress((nint)DrawDataContainer.MemberFunctionPointers.LoadWeapon, LoadWeaponDetour);
_loadWeaponHook.Enable();
@ -22,20 +26,38 @@ public unsafe class WeaponService : IDisposable
_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.
// weapon argument is the new weapon data.
// redrawOnEquality controls whether the game does anything if the new weapon is identical to the old one.
// skipGameObject seems to control whether the new weapons are written to the game object or just influence the draw object. (1 = skip, 0 = change)
// unk4 seemed to be the same as unk1.
private delegate void LoadWeaponDelegate(DrawDataContainer* drawData, uint slot, ulong weapon, byte redrawOnEquality, byte unk2,
byte skipGameObject, byte unk4);
private readonly Hook<LoadWeaponDelegate> _loadWeaponHook;
private void LoadWeaponDetour(DrawDataContainer* drawData, uint slot, ulong weapon, byte redrawOnEquality, byte unk2, byte skipGameObject,
private void LoadWeaponDetour(DrawDataContainer* drawData, uint slot, ulong weaponValue, byte redrawOnEquality, byte unk2,
byte skipGameObject,
byte unk4)
{
var actor = (Actor) (nint)(drawData + 1);
var actor = (Actor)((nint*)drawData)[1];
var weapon = new CharacterWeapon(weaponValue);
var equipSlot = slot switch
{
0 => EquipSlot.MainHand,
1 => EquipSlot.OffHand,
_ => EquipSlot.Unknown,
};
// First call the regular function.
_loadWeaponHook.Original(drawData, slot, weapon, redrawOnEquality, unk2, skipGameObject, unk4);
if (equipSlot is not EquipSlot.Unknown)
_event.Invoke(actor, equipSlot, ref weapon);
_loadWeaponHook.Original(drawData, slot, weapon.Value, redrawOnEquality, unk2, skipGameObject, unk4);
Glamourer.Log.Excessive(
$"Weapon reloaded for 0x{actor.Address:X} with attributes {slot} {weapon:X14}, {redrawOnEquality}, {unk2}, {skipGameObject}, {unk4}");
$"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.