diff --git a/Glamourer/Api/StateApi.cs b/Glamourer/Api/StateApi.cs index 331942b..ce7d226 100644 --- a/Glamourer/Api/StateApi.cs +++ b/Glamourer/Api/StateApi.cs @@ -333,6 +333,8 @@ public sealed class StateApi : IGlamourerApiState, IApiService, IDisposable private void OnStateChanged(StateChangeType type, StateSource _2, ActorState _3, ActorData actors, ITransaction? _5) { + Glamourer.Log.Error($"[OnStateChanged API CALL] Sending out OnStateChanged with type {type}."); + if (StateChanged != null) foreach (var actor in actors.Objects) StateChanged.Invoke(actor.Address); diff --git a/Glamourer/Automation/AutoDesignApplier.cs b/Glamourer/Automation/AutoDesignApplier.cs index 660acf4..d49864f 100644 --- a/Glamourer/Automation/AutoDesignApplier.cs +++ b/Glamourer/Automation/AutoDesignApplier.cs @@ -1,4 +1,5 @@ using Dalamud.Plugin.Services; +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.UI.Misc; using Glamourer.Designs; using Glamourer.Designs.Links; @@ -201,11 +202,22 @@ public sealed class AutoDesignApplier : IDisposable } } + /// + /// JOB CHANGE IS CALLED UPON HERE. + /// private void OnJobChange(Actor actor, Job oldJob, Job newJob) { + unsafe + { + var drawObject = actor.AsCharacter->DrawObject; + Glamourer.Log.Information($"[AutoDesignApplier][OnJobChange] 0x{(nint)drawObject:X} changed job from {oldJob} ({oldJob.Id}) to {newJob} ({newJob.Id})."); + } + if (!_config.EnableAutoDesigns || !actor.Identifier(_actors, out var id)) return; + Glamourer.Log.Information($"[AutoDesignApplier][OnJobChange] We had EnableAutoDesigns active, and are a valid actor!"); + if (!GetPlayerSet(id, out var set)) { if (_state.TryGetValue(id, out var s)) diff --git a/Glamourer/Interop/ChangeCustomizeService.cs b/Glamourer/Interop/ChangeCustomizeService.cs index 495d69c..032412e 100644 --- a/Glamourer/Interop/ChangeCustomizeService.cs +++ b/Glamourer/Interop/ChangeCustomizeService.cs @@ -64,12 +64,13 @@ public unsafe class ChangeCustomizeService : EventWrapperRef2 _changeCustomizeHook; + // manual invoke by calling the detours _original call to `execute to` instead of `listen to`. public bool UpdateCustomize(Model model, CustomizeArray customize) { if (!model.IsHuman) return false; - Glamourer.Log.Verbose($"[ChangeCustomize] Invoked on 0x{model.Address:X} with {customize}."); + Glamourer.Log.Information($"[ChangeCustomize] Glamour-Invoked on 0x{model.Address:X} with {customize}."); using var _ = InUpdate.EnterMethod(); var ret = _original(model.AsHuman, customize.Data, true); return ret; @@ -78,16 +79,20 @@ public unsafe class ChangeCustomizeService : EventWrapperRef2 UpdateCustomize(actor.Model, customize); + // detoured method. private bool ChangeCustomizeDetour(Human* human, byte* data, byte skipEquipment) { if (!InUpdate.InMethod) Invoke(human, ref *(CustomizeArray*)data); var ret = _changeCustomizeHook.Original(human, data, skipEquipment); + + Glamourer.Log.Information($"[ChangeCustomize] Called on with {*(CustomizeArray*)data} ({ret})."); _postEvent.Invoke(human); return ret; } + public void Subscribe(Action action, Post.Priority priority) => _postEvent.Subscribe(action, priority); diff --git a/Glamourer/Interop/InventoryService.cs b/Glamourer/Interop/InventoryService.cs index 6d8e58b..605ca15 100644 --- a/Glamourer/Interop/InventoryService.cs +++ b/Glamourer/Interop/InventoryService.cs @@ -1,9 +1,11 @@ using Dalamud.Hooking; using Dalamud.Plugin.Services; +using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.UI.Misc; using Glamourer.Events; using OtterGui.Services; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; using Penumbra.String; @@ -16,39 +18,48 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService private readonly EquippedGearset _gearsetEvent; private readonly List<(EquipSlot, uint, StainIds)> _itemList = new(12); + // This can be moved into client structs or penumbra.gamedata when needed. + public const string EquipGearsetInternal = "40 55 53 56 57 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 4C 63 FA"; + private delegate nint ChangeGearsetInternalDelegate(RaptureGearsetModule* module, uint gearsetId, byte glamourPlateId); + + [Signature(EquipGearsetInternal, DetourName = nameof(EquipGearSetInternalDetour))] + private readonly Hook _equipGearsetInternalHook = null!; + public InventoryService(MovedEquipment movedItemsEvent, IGameInteropProvider interop, EquippedGearset gearsetEvent) { _movedItemsEvent = movedItemsEvent; _gearsetEvent = gearsetEvent; _moveItemHook = interop.HookFromAddress((nint)InventoryManager.MemberFunctionPointers.MoveItemSlot, MoveItemDetour); - _equipGearsetHook = - interop.HookFromAddress((nint)RaptureGearsetModule.MemberFunctionPointers.EquipGearset, EquipGearSetDetour); + _equipGearsetHook = interop.HookFromAddress((nint)RaptureGearsetModule.MemberFunctionPointers.EquipGearset, EquipGearSetDetour); + interop.InitializeFromAttributes(this); _moveItemHook.Enable(); _equipGearsetHook.Enable(); + _equipGearsetInternalHook.Enable(); } public void Dispose() { _moveItemHook.Dispose(); _equipGearsetHook.Dispose(); + _equipGearsetInternalHook.Dispose(); } private delegate int EquipGearsetDelegate(RaptureGearsetModule* module, int gearsetId, byte glamourPlateId); private readonly Hook _equipGearsetHook; - private int EquipGearSetDetour(RaptureGearsetModule* module, int gearsetId, byte glamourPlateId) + private nint EquipGearSetInternalDetour(RaptureGearsetModule* module, uint gearsetId, byte glamourPlateId) { var prior = module->CurrentGearsetIndex; - var ret = _equipGearsetHook.Original(module, gearsetId, glamourPlateId); - var set = module->GetGearset(gearsetId); - _gearsetEvent.Invoke(new ByteString(set->Name).ToString(), gearsetId, prior, glamourPlateId, set->ClassJob); - Glamourer.Log.Excessive($"[InventoryService] Applied gear set {gearsetId} with glamour plate {glamourPlateId} (Returned {ret})"); + var ret = _equipGearsetInternalHook.Original(module, gearsetId, glamourPlateId); + var set = module->GetGearset((int)gearsetId); + _gearsetEvent.Invoke(new ByteString(set->Name).ToString(), (int)gearsetId, prior, glamourPlateId, set->ClassJob); + Glamourer.Log.Warning($"[InventoryService] [EquipInternal] Applied gear set {gearsetId} with glamour plate {glamourPlateId} (Returned {ret})"); if (ret == 0) { - var entry = module->GetGearset(gearsetId); + var entry = module->GetGearset((int)gearsetId); if (entry == null) return ret; @@ -73,18 +84,18 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService } var plate = MirageManager.Instance()->GlamourPlates[glamourPlateId - 1]; - Add(EquipSlot.MainHand, plate.ItemIds[0], StainIds.FromGlamourPlate(plate, 0), ref entry->Items[0]); - Add(EquipSlot.OffHand, plate.ItemIds[1], StainIds.FromGlamourPlate(plate, 1), ref entry->Items[1]); - Add(EquipSlot.Head, plate.ItemIds[2], StainIds.FromGlamourPlate(plate, 2), ref entry->Items[2]); - Add(EquipSlot.Body, plate.ItemIds[3], StainIds.FromGlamourPlate(plate, 3), ref entry->Items[3]); - Add(EquipSlot.Hands, plate.ItemIds[4], StainIds.FromGlamourPlate(plate, 4), ref entry->Items[5]); - Add(EquipSlot.Legs, plate.ItemIds[5], StainIds.FromGlamourPlate(plate, 5), ref entry->Items[6]); - Add(EquipSlot.Feet, plate.ItemIds[6], StainIds.FromGlamourPlate(plate, 6), ref entry->Items[7]); - Add(EquipSlot.Ears, plate.ItemIds[7], StainIds.FromGlamourPlate(plate, 7), ref entry->Items[8]); - Add(EquipSlot.Neck, plate.ItemIds[8], StainIds.FromGlamourPlate(plate, 8), ref entry->Items[9]); - Add(EquipSlot.Wrists, plate.ItemIds[9], StainIds.FromGlamourPlate(plate, 9), ref entry->Items[10]); - Add(EquipSlot.RFinger, plate.ItemIds[10], StainIds.FromGlamourPlate(plate, 10), ref entry->Items[11]); - Add(EquipSlot.LFinger, plate.ItemIds[11], StainIds.FromGlamourPlate(plate, 11), ref entry->Items[12]); + Add(EquipSlot.MainHand, plate.ItemIds[0], StainIds.FromGlamourPlate(plate, 0), ref entry->Items[0]); + Add(EquipSlot.OffHand, plate.ItemIds[1], StainIds.FromGlamourPlate(plate, 1), ref entry->Items[1]); + Add(EquipSlot.Head, plate.ItemIds[2], StainIds.FromGlamourPlate(plate, 2), ref entry->Items[2]); + Add(EquipSlot.Body, plate.ItemIds[3], StainIds.FromGlamourPlate(plate, 3), ref entry->Items[3]); + Add(EquipSlot.Hands, plate.ItemIds[4], StainIds.FromGlamourPlate(plate, 4), ref entry->Items[5]); + Add(EquipSlot.Legs, plate.ItemIds[5], StainIds.FromGlamourPlate(plate, 5), ref entry->Items[6]); + Add(EquipSlot.Feet, plate.ItemIds[6], StainIds.FromGlamourPlate(plate, 6), ref entry->Items[7]); + Add(EquipSlot.Ears, plate.ItemIds[7], StainIds.FromGlamourPlate(plate, 7), ref entry->Items[8]); + Add(EquipSlot.Neck, plate.ItemIds[8], StainIds.FromGlamourPlate(plate, 8), ref entry->Items[9]); + Add(EquipSlot.Wrists, plate.ItemIds[9], StainIds.FromGlamourPlate(plate, 9), ref entry->Items[10]); + Add(EquipSlot.RFinger, plate.ItemIds[10], StainIds.FromGlamourPlate(plate, 10), ref entry->Items[11]); + Add(EquipSlot.LFinger, plate.ItemIds[11], StainIds.FromGlamourPlate(plate, 11), ref entry->Items[12]); } else { @@ -99,17 +110,17 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService } Add(EquipSlot.MainHand, ref entry->Items[0]); - Add(EquipSlot.OffHand, ref entry->Items[1]); - Add(EquipSlot.Head, ref entry->Items[2]); - Add(EquipSlot.Body, ref entry->Items[3]); - Add(EquipSlot.Hands, ref entry->Items[5]); - Add(EquipSlot.Legs, ref entry->Items[6]); - Add(EquipSlot.Feet, ref entry->Items[7]); - Add(EquipSlot.Ears, ref entry->Items[8]); - Add(EquipSlot.Neck, ref entry->Items[9]); - Add(EquipSlot.Wrists, ref entry->Items[10]); - Add(EquipSlot.RFinger, ref entry->Items[11]); - Add(EquipSlot.LFinger, ref entry->Items[12]); + Add(EquipSlot.OffHand, ref entry->Items[1]); + Add(EquipSlot.Head, ref entry->Items[2]); + Add(EquipSlot.Body, ref entry->Items[3]); + Add(EquipSlot.Hands, ref entry->Items[5]); + Add(EquipSlot.Legs, ref entry->Items[6]); + Add(EquipSlot.Feet, ref entry->Items[7]); + Add(EquipSlot.Ears, ref entry->Items[8]); + Add(EquipSlot.Neck, ref entry->Items[9]); + Add(EquipSlot.Wrists, ref entry->Items[10]); + Add(EquipSlot.RFinger, ref entry->Items[11]); + Add(EquipSlot.LFinger, ref entry->Items[12]); } _movedItemsEvent.Invoke(_itemList.ToArray()); @@ -118,6 +129,13 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService return ret; } + private int EquipGearSetDetour(RaptureGearsetModule* module, int gearsetId, byte glamourPlateId) + { + var ret = _equipGearsetHook.Original(module, gearsetId, glamourPlateId); + Glamourer.Log.Verbose($"[InventoryService] Applied gear set {gearsetId} with glamour plate {glamourPlateId} (Returned {ret})"); + return ret; + } + private static uint FixId(uint itemId) => itemId % 50000; @@ -130,7 +148,7 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService InventoryType targetContainer, ushort targetSlot, byte unk) { var ret = _moveItemHook.Original(manager, sourceContainer, sourceSlot, targetContainer, targetSlot, unk); - Glamourer.Log.Excessive($"[InventoryService] Moved {sourceContainer} {sourceSlot} {targetContainer} {targetSlot} (Returned {ret})"); + Glamourer.Log.Verbose($"[InventoryService] Moved {sourceContainer} {sourceSlot} {targetContainer} {targetSlot} (Returned {ret})"); if (ret == 0) { if (InvokeSource(sourceContainer, sourceSlot, out var source)) diff --git a/Glamourer/Interop/JobService.cs b/Glamourer/Interop/JobService.cs index 1797809..f687715 100644 --- a/Glamourer/Interop/JobService.cs +++ b/Glamourer/Interop/JobService.cs @@ -50,7 +50,7 @@ public class JobService : IDisposable var newJob = Jobs.TryGetValue(newJobIndex, out var j) ? j : Jobs[0]; var oldJob = Jobs.TryGetValue(oldJobIndex, out var o) ? o : Jobs[0]; - Glamourer.Log.Excessive($"{actor} changed job from {oldJob} to {newJob}."); + Glamourer.Log.Error($"{actor} changed job from {oldJob} to {newJob}."); JobChanged?.Invoke(actor, oldJob, newJob); } } diff --git a/Glamourer/Interop/UpdateSlotService.cs b/Glamourer/Interop/UpdateSlotService.cs index d1004e6..e43dc74 100644 --- a/Glamourer/Interop/UpdateSlotService.cs +++ b/Glamourer/Interop/UpdateSlotService.cs @@ -1,36 +1,124 @@ using Dalamud.Hooking; using Dalamud.Plugin.Services; using Dalamud.Utility.Signatures; +using FFXIVClientStructs.FFXIV.Client.Game.Character; using Glamourer.Events; using Penumbra.GameData; using Penumbra.GameData.DataContainers; using Penumbra.GameData.Enums; using Penumbra.GameData.Interop; using Penumbra.GameData.Structs; - namespace Glamourer.Interop; +/// +/// This struct is the struct that loadallequipment passes in as its gearsetData container. +/// +[StructLayout(LayoutKind.Explicit)] // Size of 70 bytes maybe? +public readonly struct GearsetItemDataStruct +{ + // Stores the weapon data. Includes both dyes in the data. + [FieldOffset(0)] public readonly WeaponModelId MainhandWeaponData; + [FieldOffset(8)] public readonly WeaponModelId OffhandWeaponData; + + [FieldOffset(16)] public readonly byte CrestBitField; // A Bitfield:: ShieldCrest == 1, HeadCrest == 2, Chest Crest == 4 + [FieldOffset(17)] public readonly byte JobId; // Job ID associated with the gearset change. + + // Flicks from 0 to 128 (anywhere inbetween), have yet to associate what it is linked to. Remains the same when flicking between gearsets of the same job. + [FieldOffset(18)] public readonly byte UNK_18; + [FieldOffset(19)] public readonly byte UNK_19; // I have never seen this be anything other than 0. + + // Legacy helmet equip slot armor for a character. + [FieldOffset(20)] public readonly LegacyCharacterArmor HeadSlotArmor; + [FieldOffset(24)] public readonly LegacyCharacterArmor TopSlotArmor; + [FieldOffset(28)] public readonly LegacyCharacterArmor ArmsSlotArmor; + [FieldOffset(32)] public readonly LegacyCharacterArmor LegsSlotArmor; + [FieldOffset(26)] public readonly LegacyCharacterArmor FeetSlotArmor; + [FieldOffset(40)] public readonly LegacyCharacterArmor EarSlotArmor; + [FieldOffset(44)] public readonly LegacyCharacterArmor NeckSlotArmor; + [FieldOffset(48)] public readonly LegacyCharacterArmor WristSlotArmor; + [FieldOffset(52)] public readonly LegacyCharacterArmor RFingerSlotArmor; + [FieldOffset(56)] public readonly LegacyCharacterArmor LFingerSlotArmor; + + // Byte array of all slot's secondary dyes. + [FieldOffset(60)] public readonly byte HeadSlotSecondaryDye; + [FieldOffset(61)] public readonly byte TopSlotSecondaryDye; + [FieldOffset(62)] public readonly byte ArmsSlotSecondaryDye; + [FieldOffset(63)] public readonly byte LegsSlotSecondaryDye; + [FieldOffset(64)] public readonly byte FeetSlotSecondaryDye; + [FieldOffset(65)] public readonly byte EarSlotSecondaryDye; + [FieldOffset(66)] public readonly byte NeckSlotSecondaryDye; + [FieldOffset(67)] public readonly byte WristSlotSecondaryDye; + [FieldOffset(68)] public readonly byte RFingerSlotSecondaryDye; + [FieldOffset(69)] public readonly byte LFingerSlotSecondaryDye; +} + public unsafe class UpdateSlotService : IDisposable { - public readonly EquipSlotUpdating EquipSlotUpdatingEvent; - public readonly BonusSlotUpdating BonusSlotUpdatingEvent; - private readonly DictBonusItems _bonusItems; + public readonly EquipSlotUpdating EquipSlotUpdatingEvent; + public readonly BonusSlotUpdating BonusSlotUpdatingEvent; + private readonly DictBonusItems _bonusItems; + + #region LoadAllEquipData + /////////////////////////////////////////////////// + // This is a currently undocumented signature that loads all equipment after changing a gearset. + // :: Signature Maintainers Note: + // To obtain this signature, get the stacktrace from FlagSlotForUpdate for human, and find func `sub_140842F50`. + // This function is what calls the weapon/equipment/crest loads, which call FlagSlotForUpdate if different. + // + // By detouring this function, and executing the original, then logic after, we have a consistant point in time where we know all + // slots have been flagged, meaning a consistant point in time that glamourer has processed all of its updates. + public const string LoadAllEquipmentSig = "48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 44 0F B6 B9"; + private delegate Int64 LoadAllEquipmentDelegate(DrawDataContainer* drawDataContainer, GearsetItemDataStruct* gearsetData); + private Int64 LoadAllEquipmentDetour(DrawDataContainer* drawDataContainer, GearsetItemDataStruct* gearsetData) + { + // return original first so we can log the changes after + var ret = _loadAllEquipmentHook.Original(drawDataContainer, gearsetData); + + // perform logic stuff. + var owner = drawDataContainer->OwnerObject; + Glamourer.Log.Warning($"[LoadAllEquipmentDetour] Owner: 0x{(nint)owner->DrawObject:X} Finished Applying its GameState!"); + Glamourer.Log.Warning($"[LoadAllEquipmentDetour] GearsetItemData: {FormatGearsetItemDataStruct(*gearsetData)}"); + + // return original. + return ret; + } + + private string FormatWeaponModelId(WeaponModelId weaponModelId) => $"Id: {weaponModelId.Id}, Type: {weaponModelId.Type}, Variant: {weaponModelId.Variant}, Stain0: {weaponModelId.Stain0}, Stain1: {weaponModelId.Stain1}"; + + private string FormatGearsetItemDataStruct(GearsetItemDataStruct gearsetItemData) + { + string ret = $"\nMainhandWeaponData: {FormatWeaponModelId(gearsetItemData.MainhandWeaponData)}," + + $"\nOffhandWeaponData: {FormatWeaponModelId(gearsetItemData.OffhandWeaponData)}," + + $"\nCrestBitField: {gearsetItemData.CrestBitField} | JobId: {gearsetItemData.JobId} | UNK_18: {gearsetItemData.UNK_18} | UNK_19: {gearsetItemData.UNK_19}"; + // Iterate through offsets from 20 to 60 and format the CharacterArmor data + for (int offset = 20; offset <= 56; offset += sizeof(LegacyCharacterArmor)) + { + LegacyCharacterArmor* equipSlotPtr = (LegacyCharacterArmor*)((byte*)&gearsetItemData + offset); + int dyeOffset = (offset - 20) / sizeof(LegacyCharacterArmor) + 60; // Calculate the corresponding dye offset + byte* dyePtr = (byte*)&gearsetItemData + dyeOffset; + ret += $"\nEquipSlot {((EquipSlot)(dyeOffset-60)).ToString()}:: Id: {(*equipSlotPtr).Set}, Variant: {(*equipSlotPtr).Variant}, Stain0: {(*equipSlotPtr).Stain.Id}, Stain1: {*dyePtr}"; + } + return ret; + } +#endregion LoadAllEquipData public UpdateSlotService(EquipSlotUpdating equipSlotUpdating, BonusSlotUpdating bonusSlotUpdating, IGameInteropProvider interop, DictBonusItems bonusItems) { EquipSlotUpdatingEvent = equipSlotUpdating; BonusSlotUpdatingEvent = bonusSlotUpdating; - _bonusItems = bonusItems; + _bonusItems = bonusItems; interop.InitializeFromAttributes(this); _flagSlotForUpdateHook.Enable(); _flagBonusSlotForUpdateHook.Enable(); + _loadAllEquipmentHook.Enable(); } public void Dispose() { _flagSlotForUpdateHook.Dispose(); _flagBonusSlotForUpdateHook.Dispose(); + _loadAllEquipmentHook.Dispose(); } public void UpdateEquipSlot(Model drawObject, EquipSlot slot, CharacterArmor data) @@ -79,24 +167,36 @@ public unsafe class UpdateSlotService : IDisposable [Signature(Sigs.FlagBonusSlotForUpdate, DetourName = nameof(FlagBonusSlotForUpdateDetour))] private readonly Hook _flagBonusSlotForUpdateHook = null!; + [Signature(LoadAllEquipmentSig, DetourName = nameof(LoadAllEquipmentDetour))] + private readonly Hook _loadAllEquipmentHook = null!; + private ulong FlagSlotForUpdateDetour(nint drawObject, uint slotIdx, CharacterArmor* data) { - var slot = slotIdx.ToEquipSlot(); + var slot = slotIdx.ToEquipSlot(); var returnValue = ulong.MaxValue; + EquipSlotUpdatingEvent.Invoke(drawObject, slot, ref *data, ref returnValue); - Glamourer.Log.Excessive($"[FlagSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X})."); - return returnValue == ulong.MaxValue ? _flagSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue; + Glamourer.Log.Information($"[FlagSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X})."); + returnValue = returnValue == ulong.MaxValue ? _flagSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue; + + return returnValue; } private ulong FlagBonusSlotForUpdateDetour(nint drawObject, uint slotIdx, CharacterArmor* data) { - var slot = slotIdx.ToBonusSlot(); + var slot = slotIdx.ToBonusSlot(); var returnValue = ulong.MaxValue; + BonusSlotUpdatingEvent.Invoke(drawObject, slot, ref *data, ref returnValue); - Glamourer.Log.Excessive($"[FlagBonusSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X})."); - return returnValue == ulong.MaxValue ? _flagBonusSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue; + Glamourer.Log.Information($"[FlagBonusSlotForUpdate] Called with 0x{drawObject:X} for slot {slot} with {*data} ({returnValue:X})."); + returnValue = returnValue == ulong.MaxValue ? _flagBonusSlotForUpdateHook.Original(drawObject, slotIdx, data) : returnValue; + + return returnValue; } private ulong FlagSlotForUpdateInterop(Model drawObject, EquipSlot slot, CharacterArmor armor) - => _flagSlotForUpdateHook.Original(drawObject.Address, slot.ToIndex(), &armor); + { + Glamourer.Log.Warning($"Glamour-Invoked Equip Slot update for 0x{drawObject.Address:X} with {slot} and {armor}."); + return _flagSlotForUpdateHook.Original(drawObject.Address, slot.ToIndex(), &armor); + } } diff --git a/Glamourer/State/StateEditor.cs b/Glamourer/State/StateEditor.cs index f9ddb89..b592b65 100644 --- a/Glamourer/State/StateEditor.cs +++ b/Glamourer/State/StateEditor.cs @@ -51,7 +51,7 @@ public class StateEditor( return; var actors = Applier.ChangeCustomize(state, settings.Source.RequiresChange()); - Glamourer.Log.Verbose( + Glamourer.Log.Information( $"Set {idx.ToDefaultName()} customizations in state {state.Identifier.Incognito(null)} from {old.Value} to {value.Value}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Customize, settings.Source, state, actors, new CustomizeTransaction(idx, old, value)); } @@ -64,7 +64,7 @@ public class StateEditor( return; var actors = Applier.ChangeCustomize(state, settings.Source.RequiresChange()); - Glamourer.Log.Verbose( + Glamourer.Log.Information( $"Set {applied} customizations in state {state.Identifier.Incognito(null)} from {old} to {customizeInput}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.EntireCustomize, settings.Source, state, actors, new EntireCustomizeTransaction(applied, old, customizeInput)); @@ -75,7 +75,10 @@ public class StateEditor( { var state = (ActorState)data; if (!Editor.ChangeItem(state, slot, item, settings.Source, out var old, settings.Key)) + { + Glamourer.Log.Information("Not Setting State or invoking, Editor requested us not to change it!"); return; + } var type = slot.ToIndex() < 10 ? StateChangeType.Equip : StateChangeType.Weapon; var actors = type is StateChangeType.Equip @@ -86,8 +89,8 @@ public class StateEditor( if (slot is EquipSlot.MainHand) ApplyMainhandPeriphery(state, item, null, settings); - Glamourer.Log.Verbose( - $"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}). [Affecting {actors.ToLazyString("nothing")}.]"); + Glamourer.Log.Debug( + $"[ChangeItem] Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item.Name} ({item.ItemId}). [Affecting {actors.ToLazyString("nothing")}.]"); if (type is StateChangeType.Equip) { @@ -116,8 +119,8 @@ public class StateEditor( return; var actors = Applier.ChangeBonusItem(state, slot, settings.Source.RequiresChange()); - Glamourer.Log.Verbose( - $"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.Id}) to {item.Name} ({item.Id}). [Affecting {actors.ToLazyString("nothing")}.]"); + Glamourer.Log.Debug( + $"[ChangeBonus] Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.Id}) to {item.Name} ({item.Id}). [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.BonusItem, settings.Source, state, actors, new BonusItemTransaction(slot, old, item)); } @@ -149,8 +152,8 @@ public class StateEditor( if (slot is EquipSlot.MainHand) ApplyMainhandPeriphery(state, item, stains, settings); - Glamourer.Log.Verbose( - $"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item!.Value.Name} ({item.Value.ItemId}) and its stain from {oldStains} to {stains!.Value}. [Affecting {actors.ToLazyString("nothing")}.]"); + Glamourer.Log.Debug( + $"[ChangeEquip] Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item!.Value.Name} ({item.Value.ItemId}) and its stain from {oldStains} to {stains!.Value}. [Affecting {actors.ToLazyString("nothing")}.]"); if (type is StateChangeType.Equip) { StateChanged.Invoke(type, settings.Source, state, actors, new EquipTransaction(slot, old, item!.Value)); @@ -181,7 +184,7 @@ public class StateEditor( return; var actors = Applier.ChangeStain(state, slot, settings.Source.RequiresChange()); - Glamourer.Log.Verbose( + Glamourer.Log.Debug( $"Set {slot.ToName()} stain in state {state.Identifier.Incognito(null)} from {old} to {stains}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Stains, settings.Source, state, actors, new StainTransaction(slot, old, stains)); } @@ -250,7 +253,7 @@ public class StateEditor( return; var actors = Applier.ChangeMetaState(state, index, settings.Source.RequiresChange()); - Glamourer.Log.Verbose( + Glamourer.Log.Debug( $"Set {index.ToName()} in state {state.Identifier.Incognito(null)} from {old} to {value}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Other, settings.Source, state, actors, new MetaTransaction(index, old, value)); } @@ -414,8 +417,7 @@ public class StateEditor( ? Applier.ApplyAll(state, requiresRedraw, false) : ActorData.Invalid; - Glamourer.Log.Verbose( - $"Applied design to {state.Identifier.Incognito(null)}. [Affecting {actors.ToLazyString("nothing")}.]"); + Glamourer.Log.Debug($"Applied design to {state.Identifier.Incognito(null)}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Design, state.Sources[MetaIndex.Wetness], state, actors, null); // FIXME: maybe later return; diff --git a/Glamourer/State/StateListener.cs b/Glamourer/State/StateListener.cs index d054a25..382e488 100644 --- a/Glamourer/State/StateListener.cs +++ b/Glamourer/State/StateListener.cs @@ -216,8 +216,7 @@ public class StateListener : IDisposable // then we do not want to use our restricted gear protection // since we assume the player has that gear modded to availability. var locked = false; - if (actor.Identifier(_actors, out var identifier) - && _manager.TryGetValue(identifier, out var state)) + if (actor.Identifier(_actors, out var identifier) && _manager.TryGetValue(identifier, out var state)) { HandleEquipSlot(actor, state, slot, ref armor); locked = state.Sources[slot, false] is StateSource.IpcFixed; @@ -383,7 +382,7 @@ public class StateListener : IDisposable lastFistOffhand = new CharacterWeapon((PrimaryId)(weapon.Skeleton.Id + 50), weapon.Weapon, weapon.Variant, weapon.Stains); _fistOffhands[actor] = lastFistOffhand; - Glamourer.Log.Excessive($"Storing fist weapon offhand {lastFistOffhand} for 0x{actor.Address:X}."); + Glamourer.Log.Verbose($"Storing fist weapon offhand {lastFistOffhand} for 0x{actor.Address:X}."); } _funModule.ApplyFunToWeapon(actor, ref weapon, slot); diff --git a/Glamourer/State/StateManager.cs b/Glamourer/State/StateManager.cs index eabaf2f..736dd6e 100644 --- a/Glamourer/State/StateManager.cs +++ b/Glamourer/State/StateManager.cs @@ -273,7 +273,7 @@ public sealed class StateManager( if (source is not StateSource.Game) actors = Applier.ApplyAll(state, redraw, true); - Glamourer.Log.Verbose( + Glamourer.Log.Debug( $"Reset entire state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Reset, source, state, actors, null); } @@ -298,7 +298,7 @@ public sealed class StateManager( state.Materials.Clear(); - Glamourer.Log.Verbose( + Glamourer.Log.Debug( $"Reset advanced customization and dye state of {state.Identifier.Incognito(null)} to game base. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Reset, source, state, actors, null); }