diff --git a/NominaOcculta/GameFunctions.cs b/NominaOcculta/GameFunctions.cs index dc45116..13f7b17 100755 --- a/NominaOcculta/GameFunctions.cs +++ b/NominaOcculta/GameFunctions.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Runtime.InteropServices; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Hooking; @@ -58,6 +60,8 @@ internal class GameFunctions : IDisposable { private LoadExdDelegate LoadExd { get; init; } = null!; #endregion + + #region Hooks [Signature(Signatures.AtkTextNodeSetText, DetourName = nameof(AtkTextNodeSetTextDetour))] private Hook AtkTextNodeSetTextHook { get; init; } = null!; @@ -70,6 +74,8 @@ internal class GameFunctions : IDisposable { [Signature(Signatures.FlagSlotUpdate, DetourName = nameof(FlagSlotUpdateDetour))] private Hook FlagSlotUpdateHook { get; init; } = null!; + + #endregion #region Events @@ -92,6 +98,8 @@ internal class GameFunctions : IDisposable { private IntPtr First { get; } private IntPtr Last { get; } + private Dictionary HumansToIds { get; } = new(); + internal GameFunctions(Plugin plugin) { this.Plugin = plugin; @@ -107,9 +115,12 @@ internal class GameFunctions : IDisposable { this.Utf8StringCtor(this.First); this.Utf8StringCtor(this.Last); + + this.Plugin.ClientState.TerritoryChanged += this.OnTerritoryChange; } public void Dispose() { + this.Plugin.ClientState.TerritoryChanged -= this.OnTerritoryChange; this.Utf8StringDtor(this.Last); this.Utf8StringDtor(this.First); Marshal.FreeHGlobal(this.Last); @@ -120,6 +131,10 @@ internal class GameFunctions : IDisposable { this.FlagSlotUpdateHook.Dispose(); } + private void OnTerritoryChange(object? sender, ushort e) { + this.HumansToIds.Clear(); + } + private unsafe void AtkTextNodeSetTextDetour(IntPtr node, IntPtr text) { SeString? overwrite = null; this.AtkTextNodeSetText?.Invoke(node, text, ref overwrite); @@ -151,6 +166,16 @@ internal class GameFunctions : IDisposable { private unsafe char CharacterInitialiseDetour(IntPtr actorPtr, IntPtr customizeDataPtr) { if (this._lastActor != IntPtr.Zero) { try { + var id = ((GameObject*) this._lastActor)->ObjectID; + + // remove other humans that may have had this object id + foreach (var (human, objId) in this.HumansToIds.ToList()) { + if (objId == id) { + this.HumansToIds.Remove(human); + } + } + + this.HumansToIds[actorPtr] = id; this.CharacterInitialise?.Invoke((GameObject*) this._lastActor, actorPtr, customizeDataPtr); } catch (Exception e) { PluginLog.LogError(e, "yeet"); @@ -167,6 +192,15 @@ internal class GameFunctions : IDisposable { } catch (Exception e) { PluginLog.LogError(e, "yeet2"); } + } else if (this.HumansToIds.TryGetValue(actorPtr, out var objId)) { + var obj = this.Plugin.ObjectTable.FirstOrDefault(obj => obj.ObjectId == objId); + if (obj != null) { + try { + this.FlagSlotUpdate?.Invoke((GameObject*) obj.Address, slot, (EquipData*) equipDataPtr); + } catch (Exception e) { + PluginLog.LogError(e, "yeet3"); + } + } } return this.FlagSlotUpdateHook.Original(actorPtr, slot, equipDataPtr);