diff --git a/NominaOcculta/AppearanceRepository.cs b/NominaOcculta/AppearanceRepository.cs index 3827695..be85101 100755 --- a/NominaOcculta/AppearanceRepository.cs +++ b/NominaOcculta/AppearanceRepository.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; +using System.Reflection; +using Dalamud; using Dalamud.Logging; using Lumina.Excel.GeneratedSheets; @@ -42,6 +45,9 @@ internal class AppearanceRepository { "Hildibrand", "Godbert", }; + + internal IReadOnlyDictionary> JobMainHands { get; } + internal IReadOnlyDictionary> JobOffHands { get; } internal AppearanceRepository(Plugin plugin) { this.Plugin = plugin; @@ -56,6 +62,62 @@ internal class AppearanceRepository { .ToList(); this.RefilterPersonal(); PluginLog.Log($"npcs: {this.Npcs.Count}"); + + var jobMainHands = new Dictionary>(); + var jobOffHands = new Dictionary>(); + var allMainHands = this.Plugin.DataManager.GetExcelSheet()! + .Where(row => row.EquipSlotCategory.Value!.MainHand != 0) + // let's not give people ultimate weapons and shit + .Where(row => !row.IsUnique && !row.IsUntradable) + .ToList(); + var allOffHands = this.Plugin.DataManager.GetExcelSheet()! + .Where(row => row.EquipSlotCategory.Value!.OffHand != 0) + .Where(row => !row.IsUnique && !row.IsUntradable) + .ToList(); + foreach (var job in this.Plugin.DataManager.GetExcelSheet(ClientLanguage.English)!) { + if (job.RowId == 0) { + continue; + } + + if (!jobMainHands.ContainsKey(job.RowId)) { + jobMainHands[job.RowId] = new List(); + } + + if (!jobOffHands.ContainsKey(job.RowId)) { + jobOffHands[job.RowId] = new List(); + } + + var engAbbr = job.Abbreviation.RawString; + + foreach (var mainHand in allMainHands) { + var mainHandCategory = mainHand.ClassJobCategory.Value!; + var canUseMainHand = (bool?) mainHandCategory.GetType() + .GetProperty(engAbbr, BindingFlags.Instance | BindingFlags.Public)! + .GetValue(mainHandCategory); + + if (canUseMainHand == true) { + jobMainHands[job.RowId].Add(mainHand); + } + } + + foreach (var offHand in allOffHands) { + var offHandCategory = offHand.ClassJobCategory.Value!; + var canUseOffHand = (bool?) offHandCategory.GetType() + .GetProperty(engAbbr, BindingFlags.Instance | BindingFlags.Public)! + .GetValue(offHandCategory); + + if (canUseOffHand == true) { + jobOffHands[job.RowId].Add(offHand); + } + } + } + + this.JobMainHands = jobMainHands + .Select(entry => (entry.Key, (IReadOnlyList) entry.Value.ToImmutableList())) + .ToImmutableDictionary(entry => entry.Key, entry => entry.Item2); + this.JobOffHands = jobOffHands + .Select(entry => (entry.Key, (IReadOnlyList) entry.Value.ToImmutableList())) + .ToImmutableDictionary(entry => entry.Key, entry => entry.Item2); } internal void Reset() { @@ -94,4 +156,21 @@ internal class AppearanceRepository { return this.Npcs[this.GetNpcIndex(objectId)]; } + + internal (Item, Item?) GetHands(uint jobId, uint objectId) { + var random = new Random((int) (objectId + this.Salt)); + + var usesOffHand = this.JobOffHands[jobId].Count > 0; + + var mainHand = this.JobMainHands[jobId][random.Next(0, this.JobMainHands[jobId].Count)]; + var mainEquipCategory = mainHand.EquipSlotCategory.Value!; + var offHand = + mainEquipCategory.MainHand != 0 && mainEquipCategory.OffHand != 0 + ? null + : usesOffHand + ? this.JobOffHands[jobId][random.Next(0, this.JobOffHands[jobId].Count)] + : null; + + return (mainHand, offHand); + } } diff --git a/NominaOcculta/Obscurer.cs b/NominaOcculta/Obscurer.cs index 0e0689a..df626f3 100755 --- a/NominaOcculta/Obscurer.cs +++ b/NominaOcculta/Obscurer.cs @@ -175,6 +175,9 @@ internal class Obscurer : IDisposable { if (!this.ShouldObscureAppearance(gameObj)) { return; } + + var chara = (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*) gameObj; + var (mainHand, offHand) = this.Plugin.AppearanceRepository.GetHands(chara->ClassJob, gameObj->ObjectID); var npc = this.Plugin.AppearanceRepository.GetNpc(gameObj->ObjectID); var itemSlot = (EquipSlot) slot; @@ -189,6 +192,8 @@ internal class Obscurer : IDisposable { EquipSlot.Wrists => (npc.ModelWrists, npc.DyeWrists.Row), EquipSlot.RightRing => (npc.ModelRightRing, npc.DyeRightRing.Row), EquipSlot.LeftRing => (npc.ModelLeftRing, npc.DyeLeftRing.Row), + EquipSlot.MainHand => (mainHand.ModelMain, npc.DyeMainHand.Row), + EquipSlot.OffHand => (mainHand.ModelSub != 0 ? mainHand.ModelSub : offHand?.ModelMain ?? 0, npc.DyeOffHand.Row), _ => (uint.MaxValue, uint.MaxValue), };