diff --git a/NominaOcculta/Obscurer.cs b/NominaOcculta/Obscurer.cs index c5735cb..7a229cb 100755 --- a/NominaOcculta/Obscurer.cs +++ b/NominaOcculta/Obscurer.cs @@ -61,8 +61,65 @@ namespace NominaOcculta { } private void OnNamePlateUpdate(NamePlateUpdateEventArgs args) { - this.ChangeNames(args.Name); - this.ChangeNames(args.Title); // for minions + // only replace nameplates that have objects in the table + if (!this.Plugin.Config.Enabled || args.ObjectId == 0xE0000000) { + return; + } + + // find the object this nameplate references + var obj = this.Plugin.ObjectTable.FirstOrDefault(o => o.ObjectId == args.ObjectId); + if (obj == null) { + return; + } + + // handle owners + if (obj.OwnerId != 0xE0000000) { + if (this.Plugin.ObjectTable.FirstOrDefault(o => o.ObjectId == obj.OwnerId) is not { } owner) { + return; + } + + obj = owner; + } + + // only work for characters + if (obj.ObjectKind != ObjectKind.Player || obj is not Character chara) { + return; + } + + var info = GetInfo(chara); + + void Change(string name) { + this.ChangeName(args.Name, name, info); + this.ChangeName(args.Title, name, info); + } + + var name = chara.Name.TextValue; + var playerId = this.Plugin.ClientState.LocalPlayer?.ObjectId; + var party = this.Plugin.PartyList.Select(member => member.ObjectId).ToArray(); + if ((this.Plugin.Config.SelfFull || this.Plugin.Config.SelfFirst || this.Plugin.Config.SelfLast) && chara.ObjectId == playerId) { + if (this.Plugin.Config.SelfFull) { + Change(name); + } + + if ((this.Plugin.Config.SelfFirst || this.Plugin.Config.SelfLast) && this.Plugin.NameRepository.GetReplacement(name, info) is { } replacement) { + var parts = name.Split(' ', 2); + var replacementParts = replacement.Split(' ', 2); + + if (this.Plugin.Config.SelfFirst) { + args.Name.ReplacePlayerName(parts[0], replacementParts[0]); + args.Title.ReplacePlayerName(parts[0], replacementParts[0]); + } + + if (this.Plugin.Config.SelfLast) { + args.Name.ReplacePlayerName(parts[1], replacementParts[1]); + args.Title.ReplacePlayerName(parts[1], replacementParts[1]); + } + } + } else if (this.Plugin.Config.Party && party.Contains(chara.ObjectId) && (!this.Plugin.Config.ExcludeFriends || !this.Friends.Contains(name))) { + Change(name); + } else if (this.Plugin.Config.Others && chara.ObjectId != playerId && !party.Contains(chara.ObjectId) && (!this.Plugin.Config.ExcludeFriends || !this.Friends.Contains(name))) { + Change(chara.Name.TextValue); + } } private void OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) { @@ -70,6 +127,21 @@ namespace NominaOcculta { this.ChangeNames(message); } + private void ChangeName(SeString text, string name, (byte, byte, byte) info) { + if (this.Plugin.NameRepository.GetReplacement(name, info) is not { } replacement) { + return; + } + + if (!text.ContainsPlayerName(name)) { + return; + } + + text.ReplacePlayerName(name, replacement); + } + + // PERFORMANCE NOTE: This potentially loops over the party list twice and the object + // table once entirely. Should be avoided if being used in a + // position where the player to replace is known. private bool ChangeNames(SeString text) { if (!this.Plugin.Config.Enabled || !this.Plugin.NameRepository.Initialised) { return false;