diff --git a/Glamourer/Designs/DesignBase.cs b/Glamourer/Designs/DesignBase.cs index 06e55d7..5c4996a 100644 --- a/Glamourer/Designs/DesignBase.cs +++ b/Glamourer/Designs/DesignBase.cs @@ -280,7 +280,7 @@ public class DesignBase var item = _designData.BonusItem(slot); ret[slot.ToString()] = new JObject() { - ["BonusId"] = item.Id.Id, + ["BonusId"] = item.CustomId.Id, ["Apply"] = DoApplyBonusItem(slot), }; } @@ -431,7 +431,7 @@ public class DesignBase protected static void LoadBonus(ItemManager items, DesignBase design, JToken? json) { - if (json is not JObject obj) + if (json is not JObject) { design.Application.BonusItem = 0; return; @@ -439,8 +439,7 @@ public class DesignBase foreach (var slot in BonusExtensions.AllFlags) { - var itemJson = json[slot.ToString()] as JObject; - if (itemJson == null) + if (json[slot.ToString()] is not JObject itemJson) { design.Application.BonusItem &= ~slot; design.GetDesignDataRef().SetBonusItem(slot, BonusItem.Empty(slot)); @@ -448,7 +447,7 @@ public class DesignBase } design.SetApplyBonusItem(slot, itemJson["Apply"]?.ToObject() ?? false); - var id = itemJson["BonusId"]?.ToObject() ?? 0; + var id = itemJson["BonusId"]?.ToObject() ?? 0; var item = items.Resolve(slot, id); design.GetDesignDataRef().SetBonusItem(slot, item); } diff --git a/Glamourer/Designs/DesignData.cs b/Glamourer/Designs/DesignData.cs index 0a52861..28944b9 100644 --- a/Glamourer/Designs/DesignData.cs +++ b/Glamourer/Designs/DesignData.cs @@ -112,7 +112,7 @@ public unsafe struct DesignData => slot switch { // @formatter:off - BonusItemFlag.Glasses => new BonusItem(_nameGlasses, _iconIds[12], _bonusIds[0], _bonusModelIds[0], _bonusVariants[0], BonusItemFlag.Glasses), + BonusItemFlag.Glasses => Penumbra.GameData.Structs.BonusItem.FromIds(_bonusIds[0], _iconIds[12], _bonusModelIds[0], _bonusVariants[0], BonusItemFlag.Glasses, _nameGlasses), _ => Penumbra.GameData.Structs.BonusItem.Empty(slot), // @formatter:on }; diff --git a/Glamourer/Designs/DesignEditor.cs b/Glamourer/Designs/DesignEditor.cs index 5328f03..a3e86a5 100644 --- a/Glamourer/Designs/DesignEditor.cs +++ b/Glamourer/Designs/DesignEditor.cs @@ -175,7 +175,7 @@ public class DesignEditor( public void ChangeBonusItem(object data, BonusItemFlag slot, BonusItem item, ApplySettings settings = default) { var design = (Design)data; - if (!Items.IsBonusItemValid(slot, item.Id, out item)) + if (item.Slot != slot) return; var oldItem = design.DesignData.BonusItem(slot); diff --git a/Glamourer/Gui/Materials/MaterialDrawer.cs b/Glamourer/Gui/Materials/MaterialDrawer.cs index dec1aae..1b5e65a 100644 --- a/Glamourer/Gui/Materials/MaterialDrawer.cs +++ b/Glamourer/Gui/Materials/MaterialDrawer.cs @@ -139,6 +139,8 @@ public class MaterialDrawer(DesignManager _designManager, Configuration _config) "If this is checked, Glamourer will try to revert the advanced dye row to its game state instead of applying a specific row."u8); } + public sealed class MaterialSlotCombo; + public void DrawNew(Design design) { if (EquipSlotCombo.Draw("##slot", "Choose a slot for an advanced dye row.", ref _newSlot)) diff --git a/Glamourer/Services/ItemManager.cs b/Glamourer/Services/ItemManager.cs index 7b83199..8cfd387 100644 --- a/Glamourer/Services/ItemManager.cs +++ b/Glamourer/Services/ItemManager.cs @@ -132,16 +132,48 @@ public class ItemManager if (index == uint.MaxValue) return new BonusItem($"Invalid ({id.Id}-{variant})", 0, 0, id, variant, slot); - if (id.Id == 0) - return BonusItem.Empty(slot); + var item = ObjectIdentification.Identify(id, variant, slot) + .FirstOrDefault(BonusItem.FromIds(BonusItemId.Invalid, 0, id, variant, slot)); + if (item.Id != BonusItemId.Invalid) + return item; - return ObjectIdentification.Identify(id, variant, slot) - .FirstOrDefault(new BonusItem($"Invalid ({id.Id}-{variant})", 0, 0, id, variant, slot)); + if (slot is BonusItemFlag.Glasses) + { + var headItem = ObjectIdentification.Identify(id, 0, variant, EquipSlot.Head).FirstOrDefault(); + if (headItem.Valid) + return BonusItem.FromIds(BonusItemId.Invalid, headItem.IconId, id, variant, slot, $"{headItem.Name} ({EquipSlot.Head.ToName()}: {id}-{variant})"); + } + + return item; } public BonusItem Resolve(BonusItemFlag slot, BonusItemId id) => IsBonusItemValid(slot, id, out var item) ? item : new BonusItem($"Invalid ({id.Id})", 0, id, 0, 0, slot); + public BonusItem Resolve(BonusItemFlag slot, CustomItemId id) + { + // Only from early designs as migration. + if (!id.IsBonusItem) + { + IsBonusItemValid(slot, (BonusItemId)id.Id, out var item); + return item; + } + + if (!id.IsCustom) + { + if (IsBonusItemValid(slot, id.BonusItem, out var item)) + return item; + + return BonusItem.Empty(slot); + } + + var (model, variant, slot2) = id.SplitBonus; + if (slot != slot2) + return BonusItem.Empty(slot); + + return Identify(slot, model, variant); + } + /// Return the default offhand for a given mainhand, that is for both handed weapons, return the correct offhand part, and for everything else Nothing. public EquipItem GetDefaultOffhand(EquipItem mainhand) { diff --git a/Penumbra.GameData b/Penumbra.GameData index 3a65ed1..d9d4b28 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit 3a65ed1c86a2d5fd5794ff5c0559b02fc25d7224 +Subproject commit d9d4b286d54ad4027a1e8a2bbf900ee79aefaa93