diff --git a/Glamourer/Designs/DesignBase.cs b/Glamourer/Designs/DesignBase.cs index 8132f07..95b10f1 100644 --- a/Glamourer/Designs/DesignBase.cs +++ b/Glamourer/Designs/DesignBase.cs @@ -257,10 +257,10 @@ public class DesignBase foreach (var slot in EquipSlotExtensions.EqdpSlots.Prepend(EquipSlot.OffHand).Prepend(EquipSlot.MainHand)) { var item = _designData.Item(slot); - var stain = _designData.Stain(slot); + var stains = _designData.Stain(slot); var crestSlot = slot.ToCrestFlag(); var crest = _designData.Crest(crestSlot); - ret[slot.ToString()] = Serialize(item.Id, stain, crest, DoApplyEquip(slot), DoApplyStain(slot), DoApplyCrest(crestSlot)); + ret[slot.ToString()] = Serialize(item.Id, stains, crest, DoApplyEquip(slot), DoApplyStain(slot), DoApplyCrest(crestSlot)); } ret["Hat"] = new QuadBool(_designData.IsHatVisible(), DoApplyMeta(MetaIndex.HatState)).ToJObject("Show", "Apply"); @@ -274,11 +274,11 @@ public class DesignBase return ret; - static JObject Serialize(CustomItemId id, StainId stain, bool crest, bool apply, bool applyStain, bool applyCrest) + static JObject Serialize(CustomItemId id, StainIds stains, bool crest, bool apply, bool applyStain, bool applyCrest) => new() { ["ItemId"] = id.Id, - ["Stain"] = stain.Id, + ["Stain"] = stains.ToString(), ["Crest"] = crest, ["Apply"] = apply, ["ApplyStain"] = applyStain, @@ -522,15 +522,15 @@ public class DesignBase return; } - static (CustomItemId, StainId, bool, bool, bool, bool) ParseItem(EquipSlot slot, JToken? item) + static (CustomItemId, StainIds, bool, bool, bool, bool) ParseItem(EquipSlot slot, JToken? item) { var id = item?["ItemId"]?.ToObject() ?? ItemManager.NothingId(slot).Id; - var stain = (StainId)(item?["Stain"]?.ToObject() ?? 0); + var stains = (item?["Stain"]?.ToObject() ?? StainIds.None); var crest = item?["Crest"]?.ToObject() ?? false; var apply = item?["Apply"]?.ToObject() ?? false; var applyStain = item?["ApplyStain"]?.ToObject() ?? false; var applyCrest = item?["ApplyCrest"]?.ToObject() ?? false; - return (id, stain, crest, apply, applyStain, applyCrest); + return (id, stains, crest, apply, applyStain, applyCrest); } void PrintWarning(string msg) @@ -541,13 +541,13 @@ public class DesignBase foreach (var slot in EquipSlotExtensions.EqdpSlots) { - var (id, stain, crest, apply, applyStain, applyCrest) = ParseItem(slot, equip[slot.ToString()]); + var (id, stains, crest, apply, applyStain, applyCrest) = ParseItem(slot, equip[slot.ToString()]); PrintWarning(items.ValidateItem(slot, id, out var item, allowUnknown)); - PrintWarning(items.ValidateStain(stain, out stain, allowUnknown)); + PrintWarning(items.ValidateStain(stains, out stains, allowUnknown)); var crestSlot = slot.ToCrestFlag(); design._designData.SetItem(slot, item); - design._designData.SetStain(slot, stain); + design._designData.SetStain(slot, stains); design._designData.SetCrest(crestSlot, crest); design.SetApplyEquip(slot, apply); design.SetApplyStain(slot, applyStain); diff --git a/Glamourer/Designs/DesignData.cs b/Glamourer/Designs/DesignData.cs index 310c54a..f0d242b 100644 --- a/Glamourer/Designs/DesignData.cs +++ b/Glamourer/Designs/DesignData.cs @@ -52,10 +52,10 @@ public unsafe struct DesignData || name.IsContained(_nameMainhand) || name.IsContained(_nameOffhand); - public readonly StainId Stain(EquipSlot slot) + public readonly StainIds Stain(EquipSlot slot) { var index = slot.ToIndex(); - return index > 11 ? (StainId)0 : _equipmentBytes[4 * index + 3]; + return index > 11 ? StainIds.None : new(_equipmentBytes[4 * index + 3], _equipmentBytes[4 * index + 3]); } public readonly bool Crest(CrestFlag slot) diff --git a/Glamourer/Designs/DesignEditor.cs b/Glamourer/Designs/DesignEditor.cs index 91050ec..55a77b6 100644 --- a/Glamourer/Designs/DesignEditor.cs +++ b/Glamourer/Designs/DesignEditor.cs @@ -167,29 +167,29 @@ public class DesignEditor( } /// - public void ChangeStain(object data, EquipSlot slot, StainId stain, ApplySettings _ = default) + public void ChangeStain(object data, EquipSlot slot, StainIds stains, ApplySettings _ = default) { var design = (Design)data; - if (Items.ValidateStain(stain, out var _, false).Length > 0) + if (Items.ValidateStain(stains, out var _, false).Length > 0) return; var oldStain = design.DesignData.Stain(slot); - if (!design.GetDesignDataRef().SetStain(slot, stain)) + if (!design.GetDesignDataRef().SetStain(slot, stains)) return; design.LastEdit = DateTimeOffset.UtcNow; SaveService.QueueSave(design); - Glamourer.Log.Debug($"Set stain of {slot} equipment piece to {stain.Id}."); - DesignChanged.Invoke(DesignChanged.Type.Stain, design, (oldStain, stain, slot)); + Glamourer.Log.Debug($"Set stain of {slot} equipment piece to {stains}."); + DesignChanged.Invoke(DesignChanged.Type.Stain, design, (oldStain, stains, slot)); } /// - public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainId? stain, ApplySettings _ = default) + public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainIds? stains, ApplySettings _ = default) { if (item.HasValue) ChangeItem(data, slot, item.Value, _); - if (stain.HasValue) - ChangeStain(data, slot, stain.Value, _); + if (stains.HasValue) + ChangeStain(data, slot, stains.Value, _); } /// @@ -366,4 +366,9 @@ public class DesignEditor( return true; } + + public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainId? stain, ApplySettings settings = default) + { + throw new NotImplementedException(); + } } diff --git a/Glamourer/Designs/IDesignEditor.cs b/Glamourer/Designs/IDesignEditor.cs index a0aab84..e0ac3f8 100644 --- a/Glamourer/Designs/IDesignEditor.cs +++ b/Glamourer/Designs/IDesignEditor.cs @@ -65,11 +65,11 @@ public interface IDesignEditor => ChangeEquip(data, slot, item, null, settings); /// Change the stain for any equipment piece. - public void ChangeStain(object data, EquipSlot slot, StainId stain, ApplySettings settings = default) - => ChangeEquip(data, slot, null, stain, settings); + public void ChangeStain(object data, EquipSlot slot, StainIds stains, ApplySettings settings = default) + => ChangeEquip(data, slot, null, stains, settings); /// Change an equipment piece and its stain at the same time. - public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainId? stain, ApplySettings settings = default); + public void ChangeEquip(object data, EquipSlot slot, EquipItem? item, StainIds? stains, ApplySettings settings = default); /// Change the crest visibility for any equipment piece. public void ChangeCrest(object data, CrestFlag slot, bool crest, ApplySettings settings = default); diff --git a/Glamourer/Events/MovedEquipment.cs b/Glamourer/Events/MovedEquipment.cs index 53491f1..9d24a03 100644 --- a/Glamourer/Events/MovedEquipment.cs +++ b/Glamourer/Events/MovedEquipment.cs @@ -11,7 +11,7 @@ namespace Glamourer.Events; /// /// public sealed class MovedEquipment() - : EventWrapper<(EquipSlot, uint, StainId)[], MovedEquipment.Priority>(nameof(MovedEquipment)) + : EventWrapper<(EquipSlot, uint, StainIds)[], MovedEquipment.Priority>(nameof(MovedEquipment)) { public enum Priority { diff --git a/Glamourer/Gui/Equipment/EquipDrawData.cs b/Glamourer/Gui/Equipment/EquipDrawData.cs index e6b5d0d..99d3d26 100644 --- a/Glamourer/Gui/Equipment/EquipDrawData.cs +++ b/Glamourer/Gui/Equipment/EquipDrawData.cs @@ -23,8 +23,8 @@ public struct EquipDrawData(EquipSlot slot, in DesignData designData) public readonly void SetItem(EquipItem item) => _editor.ChangeItem(_object, Slot, item, ApplySettings.Manual); - public readonly void SetStain(StainId stain) - => _editor.ChangeStain(_object, Slot, stain, ApplySettings.Manual); + public readonly void SetStain(StainIds stains) + => _editor.ChangeStain(_object, Slot, stains, ApplySettings.Manual); public readonly void SetApplyItem(bool value) { @@ -41,9 +41,9 @@ public struct EquipDrawData(EquipSlot slot, in DesignData designData) } public EquipItem CurrentItem = designData.Item(slot); - public StainId CurrentStain = designData.Stain(slot); + public StainIds CurrentStain = designData.Stain(slot); public EquipItem GameItem = default; - public StainId GameStain = default; + public StainIds GameStain = default; public bool CurrentApply; public bool CurrentApplyStain; diff --git a/Glamourer/Gui/Tabs/DebugTab/ActiveStatePanel.cs b/Glamourer/Gui/Tabs/DebugTab/ActiveStatePanel.cs index 4aa0163..758f76c 100644 --- a/Glamourer/Gui/Tabs/DebugTab/ActiveStatePanel.cs +++ b/Glamourer/Gui/Tabs/DebugTab/ActiveStatePanel.cs @@ -87,8 +87,8 @@ public class ActiveStatePanel(StateManager _stateManager, ObjectManager _objectM foreach (var slot in EquipSlotExtensions.EqdpSlots.Prepend(EquipSlot.OffHand).Prepend(EquipSlot.MainHand)) { PrintRow(slot.ToName(), ItemString(state.BaseData, slot), ItemString(state.ModelData, slot), state.Sources[slot, false]); - ImGuiUtil.DrawTableColumn(state.BaseData.Stain(slot).Id.ToString()); - ImGuiUtil.DrawTableColumn(state.ModelData.Stain(slot).Id.ToString()); + ImGuiUtil.DrawTableColumn($"{state.BaseData.Stain(slot)[0]}, {state.BaseData.Stain(slot)[1]}"); + ImGuiUtil.DrawTableColumn($"{state.ModelData.Stain(slot)[0]}, {state.ModelData.Stain(slot)[1]}"); ImGuiUtil.DrawTableColumn(state.Sources[slot, true].ToString()); } diff --git a/Glamourer/Gui/Tabs/DebugTab/GlamourPlatePanel.cs b/Glamourer/Gui/Tabs/DebugTab/GlamourPlatePanel.cs index 2129c1f..d25f984 100644 --- a/Glamourer/Gui/Tabs/DebugTab/GlamourPlatePanel.cs +++ b/Glamourer/Gui/Tabs/DebugTab/GlamourPlatePanel.cs @@ -51,7 +51,7 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer using (ImRaii.Group()) { ImGuiUtil.CopyOnClickSelectable($"0x{(ulong)manager:X}"); - ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesSpan.Length.ToString()); + ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlates.Length.ToString()); ImGui.TextUnformatted(manager == null ? "-" : manager->GlamourPlatesRequested.ToString()); ImGui.SameLine(); if (ImGui.SmallButton("Request Update")) @@ -67,13 +67,13 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer var (identifier, data) = _objects.PlayerData; var enabled = data.Valid && _state.GetOrCreate(identifier, data.Objects[0], out state); - for (var i = 0; i < manager->GlamourPlatesSpan.Length; ++i) + for (var i = 0; i < manager->GlamourPlates.Length; ++i) { using var tree = ImRaii.TreeNode($"Plate #{i + 1:D2}"); if (!tree) continue; - ref var plate = ref manager->GlamourPlatesSpan[i]; + ref var plate = ref manager->GlamourPlates[i]; if (ImGuiUtil.DrawDisabledButton("Apply to Player", Vector2.Zero, string.Empty, !enabled)) { var design = CreateDesign(plate); @@ -90,7 +90,7 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer using (ImRaii.Group()) { foreach (var (_, index) in EquipSlotExtensions.FullSlots.WithIndex()) - ImGui.TextUnformatted($"{plate.ItemIds[index]:D6}, {plate.StainIds[index]:D3}"); + ImGui.TextUnformatted($"{plate.ItemIds[index]:D6}, {plate.Stain0Ids[index]:D3}, {plate.Stain1Ids[index]:D3}"); } } } @@ -126,7 +126,7 @@ public unsafe class GlamourPlatePanel : IGameDataDrawer continue; design.GetDesignDataRef().SetItem(slot, item); - design.GetDesignDataRef().SetStain(slot, plate.StainIds[index]); + design.GetDesignDataRef().SetStain(slot, new(plate.Stain0Ids[index], plate.Stain1Ids[index])); design.ApplyEquip |= slot.ToBothFlags(); } diff --git a/Glamourer/Gui/Tabs/DebugTab/InventoryPanel.cs b/Glamourer/Gui/Tabs/DebugTab/InventoryPanel.cs index bd447e7..b021656 100644 --- a/Glamourer/Gui/Tabs/DebugTab/InventoryPanel.cs +++ b/Glamourer/Gui/Tabs/DebugTab/InventoryPanel.cs @@ -43,8 +43,8 @@ public unsafe class InventoryPanel : IGameDataDrawer } else { - ImGuiUtil.DrawTableColumn(item->ItemID.ToString()); - ImGuiUtil.DrawTableColumn(item->GlamourID.ToString()); + ImGuiUtil.DrawTableColumn(item->ItemId.ToString()); + ImGuiUtil.DrawTableColumn(item->GlamourId.ToString()); ImGui.TableNextColumn(); ImGuiUtil.CopyOnClickSelectable($"0x{(ulong)item:X}"); } diff --git a/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs b/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs index 49b76b6..87b84cb 100644 --- a/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs +++ b/Glamourer/Gui/Tabs/DesignTab/DesignPanel.cs @@ -453,7 +453,7 @@ public class DesignPanel } private static unsafe string GetUserPath() - => Framework.Instance()->UserPath; + => Framework.Instance()->UserPathString; private sealed class LockButton(DesignPanel panel) : Button diff --git a/Glamourer/Gui/Tabs/UnlocksTab/UnlockOverview.cs b/Glamourer/Gui/Tabs/UnlocksTab/UnlockOverview.cs index aa67fb4..e0d4e1b 100644 --- a/Glamourer/Gui/Tabs/UnlocksTab/UnlockOverview.cs +++ b/Glamourer/Gui/Tabs/UnlocksTab/UnlockOverview.cs @@ -233,7 +233,7 @@ public class UnlockOverview ImGui.TextUnformatted($"For all {_jobs.AllJobGroups[item.JobRestrictions.Id].Name} of at least Level {item.Level}"); } - if (item.Flags.HasFlag(ItemFlags.IsDyable)) + if (item.Flags.HasFlag(ItemFlags.IsDyable1)) ImGui.TextUnformatted("Dyable"); if (item.Flags.HasFlag(ItemFlags.IsTradable)) ImGui.TextUnformatted("Tradable"); diff --git a/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs b/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs index d4fd4b0..57004cb 100644 --- a/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs +++ b/Glamourer/Gui/Tabs/UnlocksTab/UnlockTable.cs @@ -384,7 +384,7 @@ public class UnlockTable : Table, IDisposable => Tooltip = "Whether the item is dyable."; protected override bool GetValue(EquipItem item) - => item.Flags.HasFlag(ItemFlags.IsDyable); + => item.Flags.HasFlag(ItemFlags.IsDyable1); } private sealed class TradableColumn : YesNoColumn diff --git a/Glamourer/Interop/ChangeCustomizeService.cs b/Glamourer/Interop/ChangeCustomizeService.cs index cfff90f..c4317af 100644 --- a/Glamourer/Interop/ChangeCustomizeService.cs +++ b/Glamourer/Interop/ChangeCustomizeService.cs @@ -36,7 +36,7 @@ public unsafe class ChangeCustomizeService : EventWrapperRef2)Human.MemberFunctionPointers.UpdateDrawData; interop.InitializeFromAttributes(this); _penumbraReloaded.Subscribe(Restore, PenumbraReloaded.Priority.ChangeCustomizeService); } diff --git a/Glamourer/Interop/CharaFile/CharaFile.cs b/Glamourer/Interop/CharaFile/CharaFile.cs index 0613fb3..b55811b 100644 --- a/Glamourer/Interop/CharaFile/CharaFile.cs +++ b/Glamourer/Interop/CharaFile/CharaFile.cs @@ -60,7 +60,7 @@ public sealed class CharaFile return; data.SetItem(slot, item); - data.SetStain(slot, dye); + data.SetStain(slot, new(dye, dye)); flags |= slot.ToFlag(); flags |= slot.ToStainFlag(); } @@ -79,7 +79,7 @@ public sealed class CharaFile return; data.SetItem(slot, item); - data.SetStain(slot, dye); + data.SetStain(slot, new(dye, dye)); flags |= slot.ToFlag(); flags |= slot.ToStainFlag(); } diff --git a/Glamourer/Interop/CharaFile/CmaFile.cs b/Glamourer/Interop/CharaFile/CmaFile.cs index 45d1741..867e4d1 100644 --- a/Glamourer/Interop/CharaFile/CmaFile.cs +++ b/Glamourer/Interop/CharaFile/CmaFile.cs @@ -96,7 +96,7 @@ public sealed class CmaFile if (offhand == null) { data.SetItem(EquipSlot.MainHand, defaultOffhand); - data.SetStain(EquipSlot.MainHand, defaultOffhand.PrimaryId.Id == 0 ? 0 : data.Stain(EquipSlot.MainHand)); + data.SetStain(EquipSlot.MainHand, defaultOffhand.PrimaryId.Id == 0 ? StainIds.None : data.Stain(EquipSlot.MainHand)); return; } diff --git a/Glamourer/Interop/CrestService.cs b/Glamourer/Interop/CrestService.cs index 75e2a81..c10afd7 100644 --- a/Glamourer/Interop/CrestService.cs +++ b/Glamourer/Interop/CrestService.cs @@ -96,7 +96,7 @@ public sealed unsafe class CrestService : EventWrapperRef3)((nint*)model.AsCharacterBase->VTable)[95]; + var getter = (delegate* unmanaged)((nint*)model.AsCharacterBase->VirtualTable)[95]; return getter(model.AsHuman, index) != 0; } case CrestType.Offhand: @@ -105,7 +105,7 @@ public sealed unsafe class CrestService : EventWrapperRef3)((nint*)model.AsCharacterBase->VTable)[95]; + var getter = (delegate* unmanaged)((nint*)model.AsCharacterBase->VirtualTable)[95]; return getter(model.AsWeapon, index) != 0; } } diff --git a/Glamourer/Interop/InventoryService.cs b/Glamourer/Interop/InventoryService.cs index 9ad8737..2be7464 100644 --- a/Glamourer/Interop/InventoryService.cs +++ b/Glamourer/Interop/InventoryService.cs @@ -14,7 +14,7 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService { private readonly MovedEquipment _movedItemsEvent; private readonly EquippedGearset _gearsetEvent; - private readonly List<(EquipSlot, uint, StainId)> _itemList = new(12); + private readonly List<(EquipSlot, uint, StainIds)> _itemList = new(12); public InventoryService(MovedEquipment movedItemsEvent, IGameInteropProvider interop, EquippedGearset gearsetEvent) { @@ -60,56 +60,56 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService if (glamourPlateId != 0) { - void Add(EquipSlot slot, uint glamourId, StainId glamourStain, ref RaptureGearsetModule.GearsetItem item) + void Add(EquipSlot slot, uint glamourId, StainId glamourStain1, StainId glamourStain2, ref RaptureGearsetModule.GearsetItem item) { - if (item.ItemID == 0) - _itemList.Add((slot, 0, 0)); + if (item.ItemId == 0) + _itemList.Add((slot, 0, new(0, 0))); else if (glamourId != 0) - _itemList.Add((slot, glamourId, glamourStain)); + _itemList.Add((slot, glamourId, new(glamourStain1, glamourStain2))); else if (item.GlamourId != 0) - _itemList.Add((slot, item.GlamourId, item.Stain)); + _itemList.Add((slot, item.GlamourId, new(item.Stain0Id, item.Stain1Id))); else - _itemList.Add((slot, FixId(item.ItemID), item.Stain)); + _itemList.Add((slot, FixId(item.ItemId), new(item.Stain0Id, item.Stain1Id))); } - var plate = MirageManager.Instance()->GlamourPlatesSpan[glamourPlateId - 1]; - Add(EquipSlot.MainHand, plate.ItemIds[0], plate.StainIds[0], ref entry->ItemsSpan[0]); - Add(EquipSlot.OffHand, plate.ItemIds[1], plate.StainIds[1], ref entry->ItemsSpan[1]); - Add(EquipSlot.Head, plate.ItemIds[2], plate.StainIds[2], ref entry->ItemsSpan[2]); - Add(EquipSlot.Body, plate.ItemIds[3], plate.StainIds[3], ref entry->ItemsSpan[3]); - Add(EquipSlot.Hands, plate.ItemIds[4], plate.StainIds[4], ref entry->ItemsSpan[5]); - Add(EquipSlot.Legs, plate.ItemIds[5], plate.StainIds[5], ref entry->ItemsSpan[6]); - Add(EquipSlot.Feet, plate.ItemIds[6], plate.StainIds[6], ref entry->ItemsSpan[7]); - Add(EquipSlot.Ears, plate.ItemIds[7], plate.StainIds[7], ref entry->ItemsSpan[8]); - Add(EquipSlot.Neck, plate.ItemIds[8], plate.StainIds[8], ref entry->ItemsSpan[9]); - Add(EquipSlot.Wrists, plate.ItemIds[9], plate.StainIds[9], ref entry->ItemsSpan[10]); - Add(EquipSlot.RFinger, plate.ItemIds[10], plate.StainIds[10], ref entry->ItemsSpan[11]); - Add(EquipSlot.LFinger, plate.ItemIds[11], plate.StainIds[11], ref entry->ItemsSpan[12]); + var plate = MirageManager.Instance()->GlamourPlates[glamourPlateId - 1]; + Add(EquipSlot.MainHand, plate.ItemIds[0], plate.Stain0Ids[0], plate.Stain1Ids[0], ref entry->Items[0]); + Add(EquipSlot.OffHand, plate.ItemIds[1], plate.Stain0Ids[1], plate.Stain1Ids[1], ref entry->Items[1]); + Add(EquipSlot.Head, plate.ItemIds[2], plate.Stain0Ids[2], plate.Stain1Ids[2], ref entry->Items[2]); + Add(EquipSlot.Body, plate.ItemIds[3], plate.Stain0Ids[3], plate.Stain1Ids[3], ref entry->Items[3]); + Add(EquipSlot.Hands, plate.ItemIds[4], plate.Stain0Ids[4], plate.Stain1Ids[4], ref entry->Items[5]); + Add(EquipSlot.Legs, plate.ItemIds[5], plate.Stain0Ids[5], plate.Stain1Ids[5], ref entry->Items[6]); + Add(EquipSlot.Feet, plate.ItemIds[6], plate.Stain0Ids[6], plate.Stain1Ids[6], ref entry->Items[7]); + Add(EquipSlot.Ears, plate.ItemIds[7], plate.Stain0Ids[7], plate.Stain1Ids[7], ref entry->Items[8]); + Add(EquipSlot.Neck, plate.ItemIds[8], plate.Stain0Ids[8], plate.Stain1Ids[8], ref entry->Items[9]); + Add(EquipSlot.Wrists, plate.ItemIds[9], plate.Stain0Ids[9], plate.Stain1Ids[9], ref entry->Items[10]); + Add(EquipSlot.RFinger, plate.ItemIds[10], plate.Stain0Ids[10], plate.Stain1Ids[10], ref entry->Items[11]); + Add(EquipSlot.LFinger, plate.ItemIds[11], plate.Stain0Ids[11], plate.Stain1Ids[11], ref entry->Items[12]); } else { void Add(EquipSlot slot, ref RaptureGearsetModule.GearsetItem item) { - if (item.ItemID == 0) - _itemList.Add((slot, 0, 0)); + if (item.ItemId == 0) + _itemList.Add((slot, 0, new(0, 0))); else if (item.GlamourId != 0) - _itemList.Add((slot, item.GlamourId, item.Stain)); + _itemList.Add((slot, item.GlamourId, new(item.Stain0Id, item.Stain1Id))); else - _itemList.Add((slot, FixId(item.ItemID), item.Stain)); + _itemList.Add((slot, FixId(item.ItemId), new(item.Stain0Id, item.Stain1Id))); } - Add(EquipSlot.MainHand, ref entry->ItemsSpan[0]); - Add(EquipSlot.OffHand, ref entry->ItemsSpan[1]); - Add(EquipSlot.Head, ref entry->ItemsSpan[2]); - Add(EquipSlot.Body, ref entry->ItemsSpan[3]); - Add(EquipSlot.Hands, ref entry->ItemsSpan[5]); - Add(EquipSlot.Legs, ref entry->ItemsSpan[6]); - Add(EquipSlot.Feet, ref entry->ItemsSpan[7]); - Add(EquipSlot.Ears, ref entry->ItemsSpan[8]); - Add(EquipSlot.Neck, ref entry->ItemsSpan[9]); - Add(EquipSlot.Wrists, ref entry->ItemsSpan[10]); - Add(EquipSlot.RFinger, ref entry->ItemsSpan[11]); - Add(EquipSlot.LFinger, ref entry->ItemsSpan[12]); + 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]); } _movedItemsEvent.Invoke(_itemList.ToArray()); @@ -155,7 +155,7 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService return ret; } - private static bool InvokeSource(InventoryType sourceContainer, uint sourceSlot, out (EquipSlot, uint, StainId) tuple) + private static bool InvokeSource(InventoryType sourceContainer, uint sourceSlot, out (EquipSlot, uint, StainIds) tuple) { tuple = default; if (sourceContainer is not InventoryType.EquippedItems) @@ -165,12 +165,12 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService if (slot is EquipSlot.Unknown) return false; - tuple = (slot, 0u, 0); + tuple = (slot, 0u, StainIds.None); return true; } private static bool InvokeTarget(InventoryManager* manager, InventoryType targetContainer, uint targetSlot, - out (EquipSlot, uint, StainId) tuple) + out (EquipSlot, uint, StainIds) tuple) { tuple = default; if (targetContainer is not InventoryType.EquippedItems) @@ -189,7 +189,7 @@ public sealed unsafe class InventoryService : IDisposable, IRequiredService if (item == null) return false; - tuple = (slot, item->GlamourID != 0 ? item->GlamourID : item->ItemID, item->Stain); + tuple = (slot, item->GlamourId != 0 ? item->GlamourId : item->ItemId, new(item->Stains[0], item->Stains[1])); return true; } diff --git a/Glamourer/Interop/MetaService.cs b/Glamourer/Interop/MetaService.cs index 1bc7a32..d3c3c4e 100644 --- a/Glamourer/Interop/MetaService.cs +++ b/Glamourer/Interop/MetaService.cs @@ -48,12 +48,14 @@ public unsafe class MetaService : IDisposable if (!actor.IsCharacter) return; + actor.AsCharacter->DrawData.SetVisor(value); + // The function seems to not do anything if the head is 0, but also breaks for carbuncles turned human, sometimes? - var old = actor.AsCharacter->DrawData.Head.Id; + /* var old = actor.AsCharacter->DrawData.Head.Id; if (old == 0 && actor.AsCharacter->CharacterData.ModelCharaId == 0) actor.AsCharacter->DrawData.Head.Id = 1; _hideHatGearHook.Original(&actor.AsCharacter->DrawData, 0, (byte)(value ? 0 : 1)); - actor.AsCharacter->DrawData.Head.Id = old; + actor.AsCharacter->DrawData.Head.Id = old; */ } public void SetWeaponState(Actor actor, bool value) diff --git a/Glamourer/Services/CollectionOverrideService.cs b/Glamourer/Services/CollectionOverrideService.cs index 9069682..7481ff7 100644 --- a/Glamourer/Services/CollectionOverrideService.cs +++ b/Glamourer/Services/CollectionOverrideService.cs @@ -164,7 +164,7 @@ public sealed class CollectionOverrideService : IService, ISavable var collection = _penumbra.CollectionByIdentifier(collectionIdentifier); if (collection == null) { - Glamourer.Messager.AddMessage(new Notification( + Glamourer.Messager.AddMessage(new OtterGui.Classes.Notification( $"The overridden collection for identifier {identifier.Incognito(null)} with name {collectionIdentifier} could not be found by Penumbra for migration.", NotificationType.Warning)); continue; diff --git a/Glamourer/Services/ItemManager.cs b/Glamourer/Services/ItemManager.cs index 8f52815..318d9da 100644 --- a/Glamourer/Services/ItemManager.cs +++ b/Glamourer/Services/ItemManager.cs @@ -195,16 +195,16 @@ public class ItemManager /// The returned stain id is either the input or 0. /// The return value is an empty string if there was no problem and a warning otherwise. /// - public string ValidateStain(StainId stain, out StainId ret, bool allowUnknown) + public string ValidateStain(StainIds stains, out StainIds ret, bool allowUnknown) { - if (allowUnknown || IsStainValid(stain)) + if (allowUnknown || IsStainValid(stains[0]) && IsStainValid(stains[1])) { - ret = stain; + ret = stains; return string.Empty; } - ret = 0; - return $"The Stain {stain} does not exist, reset to unstained."; + ret = StainIds.None; + return $"The Stains {stains} does not exist, reset to unstained."; } /// Returns whether an offhand is valid given the required offhand type. diff --git a/Glamourer/State/InternalStateEditor.cs b/Glamourer/State/InternalStateEditor.cs index 19a16c8..4681c77 100644 --- a/Glamourer/State/InternalStateEditor.cs +++ b/Glamourer/State/InternalStateEditor.cs @@ -152,11 +152,11 @@ public class InternalStateEditor( } /// Change a single piece of equipment including stain. - public bool ChangeEquip(ActorState state, EquipSlot slot, EquipItem item, StainId stain, StateSource source, out EquipItem oldItem, - out StainId oldStain, uint key = 0) + public bool ChangeEquip(ActorState state, EquipSlot slot, EquipItem item, StainIds stains, StateSource source, out EquipItem oldItem, + out StainIds oldStains, uint key = 0) { oldItem = state.ModelData.Item(slot); - oldStain = state.ModelData.Stain(slot); + oldStains = state.ModelData.Stain(slot); if (!state.CanUnlock(key)) return false; @@ -168,7 +168,7 @@ public class InternalStateEditor( return false; var old = oldItem; - var oldS = oldStain; + var oldS = oldStains; gPose.AddActionOnLeave(() => { if (old.Type == state.BaseData.Item(slot).Type) @@ -177,16 +177,16 @@ public class InternalStateEditor( } state.ModelData.SetItem(slot, item); - state.ModelData.SetStain(slot, stain); + state.ModelData.SetStain(slot, stains); state.Sources[slot, false] = source; state.Sources[slot, true] = source; return true; } /// Change only the stain of an equipment piece. - public bool ChangeStain(ActorState state, EquipSlot slot, StainIds stains, StateSource source, out StainId oldStain, uint key = 0) + public bool ChangeStain(ActorState state, EquipSlot slot, StainIds stains, StateSource source, out StainIds oldStains, uint key = 0) { - oldStain = state.ModelData.Stain(slot); + oldStains = state.ModelData.Stain(slot); if (!state.CanUnlock(key)) return false; diff --git a/Glamourer/State/StateEditor.cs b/Glamourer/State/StateEditor.cs index 096d3ad..749039c 100644 --- a/Glamourer/State/StateEditor.cs +++ b/Glamourer/State/StateEditor.cs @@ -118,7 +118,7 @@ public class StateEditor( 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 {oldStain.Id} to {stain!.Value.Id}. [Affecting {actors.ToLazyString("nothing")}.]"); + $"Set {slot.ToName()} in state {state.Identifier.Incognito(null)} from {old.Name} ({old.ItemId}) to {item!.Value.Name} ({item.Value.ItemId}) and its stains from {oldStain[0]},{oldStain[1]} to {stains!.Value[0]}, {stains!.Value[1]}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(type, settings.Source, state, actors, (old, item!.Value, slot)); StateChanged.Invoke(StateChangeType.Stain, settings.Source, state, actors, (oldStain, stains!.Value, slot)); } @@ -132,7 +132,7 @@ public class StateEditor( var actors = Applier.ChangeStain(state, slot, settings.Source.RequiresChange()); Glamourer.Log.Verbose( - $"Set {slot.ToName()} stain in state {state.Identifier.Incognito(null)} from {old.Id} to {stains.ToString()}. [Affecting {actors.ToLazyString("nothing")}.]"); + $"Set {slot.ToName()} stain in state {state.Identifier.Incognito(null)} from {old[0]},{old[1]} to {stains.ToString()}. [Affecting {actors.ToLazyString("nothing")}.]"); StateChanged.Invoke(StateChangeType.Stain, settings.Source, state, actors, (old, stains, slot)); } diff --git a/Glamourer/State/StateListener.cs b/Glamourer/State/StateListener.cs index d3f6e1e..752fe82 100644 --- a/Glamourer/State/StateListener.cs +++ b/Glamourer/State/StateListener.cs @@ -227,14 +227,14 @@ public class StateListener : IDisposable (_, armor) = _items.RestrictedGear.ResolveRestricted(armor, slot, customize.Race, customize.Gender); } - private void OnMovedEquipment((EquipSlot, uint, StainId)[] items) + private void OnMovedEquipment((EquipSlot, uint, StainIds)[] items) { _objects.Update(); var (identifier, objects) = _objects.PlayerData; if (!identifier.IsValid || !_manager.TryGetValue(identifier, out var state)) return; - foreach (var (slot, item, stain) in items) + foreach (var (slot, item, stains) in items) { var currentItem = state.BaseData.Item(slot); var model = slot is EquipSlot.MainHand or EquipSlot.OffHand @@ -244,7 +244,7 @@ public class StateListener : IDisposable if (model.Value == current.Value || !_items.ItemData.TryGetValue(item, EquipSlot.MainHand, out var changedItem)) continue; - var changed = changedItem.Weapon(stain); + var changed = changedItem.Weapon(stains); var itemChanged = current.Skeleton == changed.Skeleton && current.Variant == changed.Variant && current.Weapon == changed.Weapon diff --git a/Glamourer/Unlocks/CustomizeUnlockManager.cs b/Glamourer/Unlocks/CustomizeUnlockManager.cs index b63a98e..3cb3d8a 100644 --- a/Glamourer/Unlocks/CustomizeUnlockManager.cs +++ b/Glamourer/Unlocks/CustomizeUnlockManager.cs @@ -174,7 +174,7 @@ public class CustomizeUnlockManager : IDisposable, ISavable IDataManager gameData) { var ret = new Dictionary(); - var sheet = gameData.GetExcelSheet(ClientLanguage.English)!; + var sheet = gameData.GetExcelSheet(Dalamud.Game.ClientLanguage.English)!; foreach (var (clan, gender) in CustomizeManager.AllSets()) { var list = customizations.Manager.GetSet(clan, gender); diff --git a/Glamourer/Unlocks/ItemUnlockManager.cs b/Glamourer/Unlocks/ItemUnlockManager.cs index de35335..856b767 100644 --- a/Glamourer/Unlocks/ItemUnlockManager.cs +++ b/Glamourer/Unlocks/ItemUnlockManager.cs @@ -154,7 +154,7 @@ public class ItemUnlockManager : ISavable, IDisposable, IReadOnlyDictionaryGlamourPlatesSpan) + foreach (var plate in mirageManager->GlamourPlates) { // TODO: Make independent from hardcoded value var span = new ReadOnlySpan(plate.ItemIds, 12); @@ -176,8 +176,8 @@ public class ItemUnlockManager : ISavable, IDisposable, IReadOnlyDictionaryGetInventorySlot(_currentInventoryIndex++); if (item != null) { - changes |= AddItem(item->ItemID, time); - changes |= AddItem(item->GlamourID, time); + changes |= AddItem(item->ItemId, time); + changes |= AddItem(item->GlamourId, time); } } else