diff --git a/Glamourer/GameData/CustomizeSet.cs b/Glamourer/GameData/CustomizeSet.cs index 7fcf1d2..178ef07 100644 --- a/Glamourer/GameData/CustomizeSet.cs +++ b/Glamourer/GameData/CustomizeSet.cs @@ -11,12 +11,15 @@ namespace Glamourer.GameData; /// public class CustomizeSet { - internal CustomizeSet(SubRace clan, Gender gender) + private NpcCustomizeSet _npcCustomizations; + + internal CustomizeSet(NpcCustomizeSet npcCustomizations, SubRace clan, Gender gender) { - Gender = gender; - Clan = clan; - Race = clan.ToRace(); - SettingAvailable = 0; + _npcCustomizations = npcCustomizations; + Gender = gender; + Clan = clan; + Race = clan.ToRace(); + SettingAvailable = 0; } public Gender Gender { get; } @@ -85,6 +88,7 @@ public class CustomizeSet { if (IsAvailable(index)) return DataByValue(index, value, out custom, face) >= 0 + || _npcCustomizations.CheckColor(index, value) || NpcOptions.Any(t => t.Type == index && t.Value == value); custom = null; diff --git a/Glamourer/GameData/CustomizeSetFactory.cs b/Glamourer/GameData/CustomizeSetFactory.cs index e2291d4..13a9865 100644 --- a/Glamourer/GameData/CustomizeSetFactory.cs +++ b/Glamourer/GameData/CustomizeSetFactory.cs @@ -1,6 +1,5 @@ using Dalamud.Game; using Dalamud.Plugin.Services; -using Dalamud.Utility; using Lumina.Excel; using Lumina.Excel.Sheets; using OtterGui.Classes; @@ -29,7 +28,7 @@ internal class CustomizeSetFactory( var row = _charaMakeSheet.GetRow(((uint)race - 1) * 2 - 1 + (uint)gender)!; var hrothgar = race.ToRace() == Race.Hrothgar; // Create the initial set with all the easily accessible parameters available for anyone. - var set = new CustomizeSet(race, gender) + var set = new CustomizeSet(_npcCustomizeSet, race, gender) { Name = GetName(race, gender), Voices = row.VoiceStruct, @@ -77,13 +76,7 @@ internal class CustomizeSetFactory( CustomizeIndex.Hairstyle, CustomizeIndex.LipColor, CustomizeIndex.SkinColor, - CustomizeIndex.FacePaintColor, - CustomizeIndex.HighlightsColor, - CustomizeIndex.HairColor, CustomizeIndex.FacePaint, - CustomizeIndex.TattooColor, - CustomizeIndex.EyeColorLeft, - CustomizeIndex.EyeColorRight, CustomizeIndex.TailShape, }; diff --git a/Glamourer/GameData/NpcCustomizeSet.cs b/Glamourer/GameData/NpcCustomizeSet.cs index 72ed4b4..4dbfd83 100644 --- a/Glamourer/GameData/NpcCustomizeSet.cs +++ b/Glamourer/GameData/NpcCustomizeSet.cs @@ -4,6 +4,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object; using Lumina.Excel.Sheets; using OtterGui.Services; using Penumbra.GameData.DataContainers; +using Penumbra.GameData.Enums; using Penumbra.GameData.Structs; namespace Glamourer.GameData; @@ -35,6 +36,23 @@ public class NpcCustomizeSet : IAsyncDataContainer, IReadOnlyList /// The list of data. private readonly List _data = []; + private readonly BitArray _hairColors = new(256); + private readonly BitArray _eyeColors = new(256); + private readonly BitArray _facepaintColors = new(256); + private readonly BitArray _tattooColors = new(256); + + public bool CheckColor(CustomizeIndex type, CustomizeValue value) + => type switch + { + CustomizeIndex.HairColor => _hairColors[value.Value], + CustomizeIndex.HighlightsColor => _hairColors[value.Value], + CustomizeIndex.EyeColorLeft => _eyeColors[value.Value], + CustomizeIndex.EyeColorRight => _eyeColors[value.Value], + CustomizeIndex.FacePaintColor => _facepaintColors[value.Value], + CustomizeIndex.TattooColor => _tattooColors[value.Value], + _ => false, + }; + /// Create the data when ready. public NpcCustomizeSet(IDataManager data, DictENpc eNpcs, DictBNpc bNpcs, DictBNpcNames bNpcNames) { @@ -147,6 +165,12 @@ public class NpcCustomizeSet : IAsyncDataContainer, IReadOnlyList for (var i = 0; i < duplicates.Count; ++i) { var current = duplicates[i]; + _hairColors[current.Customize[CustomizeIndex.HairColor].Value] = true; + _hairColors[current.Customize[CustomizeIndex.HighlightsColor].Value] = true; + _eyeColors[current.Customize[CustomizeIndex.EyeColorLeft].Value] = true; + _eyeColors[current.Customize[CustomizeIndex.EyeColorRight].Value] = true; + _facepaintColors[current.Customize[CustomizeIndex.FacePaintColor].Value] = true; + _tattooColors[current.Customize[CustomizeIndex.TattooColor].Value] = true; for (var j = 0; j < i; ++j) { if (current.DataEquals(duplicates[j])) @@ -195,8 +219,8 @@ public class NpcCustomizeSet : IAsyncDataContainer, IReadOnlyList data.Set(7, row.ModelWrists | (row.DyeWrists.RowId << 24) | ((ulong)row.Dye2Wrists.RowId << 32)); data.Set(8, row.ModelRightRing | (row.DyeRightRing.RowId << 24) | ((ulong)row.Dye2RightRing.RowId << 32)); data.Set(9, row.ModelLeftRing | (row.DyeLeftRing.RowId << 24) | ((ulong)row.Dye2LeftRing.RowId << 32)); - data.Mainhand = new CharacterWeapon(row.ModelMainHand | ((ulong)row.DyeMainHand.RowId << 48) | ((ulong)row.Dye2MainHand.RowId << 56)); - data.Offhand = new CharacterWeapon(row.ModelOffHand | ((ulong)row.DyeOffHand.RowId << 48) | ((ulong)row.Dye2OffHand.RowId << 56)); + data.Mainhand = new CharacterWeapon(row.ModelMainHand | ((ulong)row.DyeMainHand.RowId << 48) | ((ulong)row.Dye2MainHand.RowId << 56)); + data.Offhand = new CharacterWeapon(row.ModelOffHand | ((ulong)row.DyeOffHand.RowId << 48) | ((ulong)row.Dye2OffHand.RowId << 56)); data.VisorToggled = row.Visor; } @@ -213,8 +237,8 @@ public class NpcCustomizeSet : IAsyncDataContainer, IReadOnlyList data.Set(7, row.ModelWrists | (row.DyeWrists.RowId << 24) | ((ulong)row.Dye2Wrists.RowId << 32)); data.Set(8, row.ModelRightRing | (row.DyeRightRing.RowId << 24) | ((ulong)row.Dye2RightRing.RowId << 32)); data.Set(9, row.ModelLeftRing | (row.DyeLeftRing.RowId << 24) | ((ulong)row.Dye2LeftRing.RowId << 32)); - data.Mainhand = new CharacterWeapon(row.ModelMainHand | ((ulong)row.DyeMainHand.RowId << 48) | ((ulong)row.Dye2MainHand.RowId << 56)); - data.Offhand = new CharacterWeapon(row.ModelOffHand | ((ulong)row.DyeOffHand.RowId << 48) | ((ulong)row.Dye2OffHand.RowId << 56)); + data.Mainhand = new CharacterWeapon(row.ModelMainHand | ((ulong)row.DyeMainHand.RowId << 48) | ((ulong)row.Dye2MainHand.RowId << 56)); + data.Offhand = new CharacterWeapon(row.ModelOffHand | ((ulong)row.DyeOffHand.RowId << 48) | ((ulong)row.Dye2OffHand.RowId << 56)); data.VisorToggled = row.Visor; } diff --git a/Glamourer/Gui/Tabs/DebugTab/CustomizationServicePanel.cs b/Glamourer/Gui/Tabs/DebugTab/CustomizationServicePanel.cs index 17e180e..afc7d56 100644 --- a/Glamourer/Gui/Tabs/DebugTab/CustomizationServicePanel.cs +++ b/Glamourer/Gui/Tabs/DebugTab/CustomizationServicePanel.cs @@ -1,10 +1,13 @@ -using Glamourer.GameData; +using Dalamud.Interface; +using Glamourer.GameData; using Glamourer.Services; using ImGuiNET; using OtterGui; using OtterGui.Raii; +using OtterGui.Text; using Penumbra.GameData.Enums; using Penumbra.GameData.Gui.Debug; +using Penumbra.GameData.Structs; namespace Glamourer.Gui.Tabs.DebugTab; @@ -24,6 +27,49 @@ public class CustomizationServicePanel(CustomizeService customize) : IGameDataDr DrawCustomizationInfo(set); DrawNpcCustomizationInfo(set); } + + DrawColorInfo(); + } + + private void DrawColorInfo() + { + using var tree = ImUtf8.TreeNode("NPC Colors"u8); + if (!tree) + return; + + using var table = ImUtf8.Table("data"u8, 5, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.RowBg); + if (!table) + return; + + ImGui.TableNextColumn(); + ImUtf8.TableHeader("Id"u8); + ImGui.TableNextColumn(); + ImUtf8.TableHeader("Hair"u8); + ImGui.TableNextColumn(); + ImUtf8.TableHeader("Eyes"u8); + ImGui.TableNextColumn(); + ImUtf8.TableHeader("Facepaint"u8); + ImGui.TableNextColumn(); + ImUtf8.TableHeader("Tattoos"u8); + + for (var i = 192; i < 256; ++i) + { + var index = new CustomizeValue((byte)i); + ImUtf8.DrawTableColumn($"{i:D3}"); + using var font = ImRaii.PushFont(UiBuilder.IconFont); + ImUtf8.DrawTableColumn(customize.NpcCustomizeSet.CheckColor(CustomizeIndex.HairColor, index) + ? FontAwesomeIcon.Check.ToIconString() + : FontAwesomeIcon.Times.ToIconString()); + ImUtf8.DrawTableColumn(customize.NpcCustomizeSet.CheckColor(CustomizeIndex.EyeColorLeft, index) + ? FontAwesomeIcon.Check.ToIconString() + : FontAwesomeIcon.Times.ToIconString()); + ImUtf8.DrawTableColumn(customize.NpcCustomizeSet.CheckColor(CustomizeIndex.FacePaintColor, index) + ? FontAwesomeIcon.Check.ToIconString() + : FontAwesomeIcon.Times.ToIconString()); + ImUtf8.DrawTableColumn(customize.NpcCustomizeSet.CheckColor(CustomizeIndex.TattooColor, index) + ? FontAwesomeIcon.Check.ToIconString() + : FontAwesomeIcon.Times.ToIconString()); + } } private void DrawCustomizationInfo(CustomizeSet set)