diff --git a/Config/XUi_InGame/windows.xml b/Config/XUi_InGame/windows.xml index 673a8ab..1f688c4 100644 --- a/Config/XUi_InGame/windows.xml +++ b/Config/XUi_InGame/windows.xml @@ -208,21 +208,4 @@ - - - - - - - - - - - - - - diff --git a/Config/XUi_InGame/xui.xml b/Config/XUi_InGame/xui.xml index 13caeb2..e6ac8a7 100644 --- a/Config/XUi_InGame/xui.xml +++ b/Config/XUi_InGame/xui.xml @@ -59,10 +59,4 @@ - - - - - - diff --git a/HarmonySrc/Cinerarium.cs b/HarmonySrc/Cinerarium.cs index 0f0113a..ab2cf98 100644 --- a/HarmonySrc/Cinerarium.cs +++ b/HarmonySrc/Cinerarium.cs @@ -70,7 +70,7 @@ namespace NecromancerTome base.OnRemove(_world); RemoveBounds(); RemoveGenie(false); - XUiC_NecroCinerariumSkullGrid.CloseIfShowing(this); + CinerariumContents.CloseIfShowing(this); if (!ConnectionManager.Instance.IsServer) { return; @@ -96,7 +96,7 @@ namespace NecromancerTome base.OnUnload(_world); RemoveBounds(); RemoveGenie(false); - XUiC_NecroCinerariumSkullGrid.CloseIfShowing(this); + CinerariumContents.CloseIfShowing(this); } public override void Write(PooledBinaryWriter _bw, StreamModeWrite _eStreamMode) @@ -602,7 +602,7 @@ namespace NecromancerTome } if (skull) { - XUiC_NecroCinerariumSkullGrid.Open(_player, urn); + CinerariumContents.Open(_player, urn); } else if (repair) { diff --git a/HarmonySrc/CinerariumTrunk.cs b/HarmonySrc/CinerariumTrunk.cs index d7f9633..eaa0136 100644 --- a/HarmonySrc/CinerariumTrunk.cs +++ b/HarmonySrc/CinerariumTrunk.cs @@ -3,83 +3,116 @@ using UnityEngine; namespace NecromancerTome { /// - /// «Багажник» урны-цинерария (решение 16.10: «урна как транспорт» - на E круговое меню, как у велосипеда: - /// багажник с ячейкой черепа и сумка духа). Окно necroCinerariumTrunk (Config/XUi_InGame) - панель с одной - /// ячейкой игры для обязательного предмета (XUiC_RequiredItemStack, как в панели модификаций коллектора - /// росы), рядом рюкзак (open_backpack_on_open). Ячейка принимает только череп и не больше одного - /// (override_stack_count="1" в XML). Череп - обычный предмет (ItemClass): в сейвах он уже есть, менять ему - /// класс на модификацию нельзя (см. память про сейвы), поэтому ячейка, а не сборка как у робомолота. + /// «Содержимое» урны-цинерария - ячейка черепа (решение 16.10: «урна как транспорт»; переименовано из «Багажника»). + /// Окно - родное окно хранилища игры (XUiC_BagStorageWindowGroup, как сумка транспорта и сумка волка) с сумкой на одну + /// ячейку: перетаскивание, Shift+клик и правый клик - кодом игры (16.10: «Сумки, ящики в игре есть» - своё окно с + /// ячейкой коллектора не принимало череп ни перетаскиванием, ни Shift+кликом). Своё здесь одно: после каждого изменения + /// в ячейке остаётся один череп, всё остальное (лишние черепа, чужие предметы) - назад в рюкзак, и урна узнаёт, есть ли + /// в ней череп. Череп - обычный предмет (ItemClass): он уже в сейвах, менять ему класс на модификацию нельзя. /// - public class XUiC_NecroCinerariumSkullGrid : XUiC_ItemStackGrid + public static class CinerariumContents { - public const string WindowGroup = "necroCinerariumTrunk"; + public const string LootTemplate = "roboticDrone"; // звуки и время открытия, как у сумки волка - /// Урна, чей багажник открыт (ставится перед открытием окна). - public static TEFeatureCinerarium Urn; + static TEFeatureCinerarium _urn; + static Bag _bag; + static EntityPlayerLocal _player; - public static void Open(EntityPlayerLocal _player, TEFeatureCinerarium _urn) + public static void Open(EntityPlayerLocal _p, TEFeatureCinerarium _u) { - LocalPlayerUI ui = _player?.PlayerUI; - if (ui == null || _urn == null) + LocalPlayerUI ui = _p != null ? LocalPlayerUI.GetUIForPlayer(_p) : null; + ItemValue skull = ItemClass.GetItem(TEFeatureCinerarium.SkullItemName); + if (ui == null || _u == null) { return; } - Urn = _urn; - ui.windowManager.Open(WindowGroup, true); + _urn = _u; + _player = _p; + _bag = new Bag(new Vector2i(1, 1), XUiC_ItemStack.StackLocationTypes.LootContainer, null); + if (_u.HasSkull && skull != null && skull.type > 0) + { + _bag.SetSlot(0, new ItemStack(skull, 1)); + } + XUiC_BagStorageWindowGroup.Open(ui.xui, _p, _bag, LootContainer.GetLootContainer(LootTemplate), + Localization.Get("necroCinerariumTrunk"), Check, () => + { + Check(); + _urn = null; + _bag = null; + _player = null; + }); + Debug.Log("[NecromancerTome] Cinerarium: «Содержимое» урны " + _u.ToWorldPos() + " открыто, череп " + (_u.HasSkull ? "есть" : "нет")); } - public override void OnOpen() + /// Оставить в ячейке один череп, остальное - игроку; отметить в урне. + static void Check() { - base.OnOpen(); - ItemValue skull = ItemClass.GetItem(TEFeatureCinerarium.SkullItemName); - for (int i = 0; i < itemControllers.Length; i++) + if (_bag == null || _urn == null) { - if (itemControllers[i] is XUiC_RequiredItemStack slot) + return; + } + ItemStack s = _bag.ItemGrid.items[0]; + bool has = false; + if (s != null && !s.IsEmpty()) + { + ItemStack back = null; + if (s.itemValue.ItemClass?.GetItemName() != TEFeatureCinerarium.SkullItemName) { - slot.SetAllowedItemClassSingle(TEFeatureCinerarium.SkullItemName); - slot.RequiredItemOnly = true; - slot.StackLocation = XUiC_ItemStack.StackLocationTypes.Workstation; + back = s.Clone(); + _bag.SetSlot(0, ItemStack.Empty.Clone()); + } + else + { + has = true; + if (s.count > 1) + { + back = s.Clone(); + back.count = s.count - 1; + ItemStack one = s.Clone(); + one.count = 1; + _bag.SetSlot(0, one); + } + } + if (back != null) + { + GiveBack(back); } } - ItemStack[] stacks = new ItemStack[itemControllers.Length]; - for (int i = 0; i < stacks.Length; i++) - { - stacks[i] = ItemStack.Empty.Clone(); - } - if (stacks.Length > 0 && Urn != null && Urn.HasSkull && skull != null && skull.type > 0) - { - stacks[0] = new ItemStack(skull, 1); - } - SetStacks(stacks); + _urn.SetSkull(has); } - public override void OnClose() + static void GiveBack(ItemStack _s) { - base.OnClose(); - Urn = null; - } - - public override void UpdateBackend(ItemStack[] stackList) - { - base.UpdateBackend(stackList); - bool has = stackList != null && stackList.Length > 0 && stackList[0] != null && !stackList[0].IsEmpty(); - Urn?.SetSkull(has); - } - - /// Урна убрана или выгружена, пока открыт её багажник, - закрыть окно (иначе череп в ячейке - /// уже ни к чему не привязан). - public static void CloseIfShowing(TEFeatureCinerarium _urn) - { - if (Urn == null || Urn != _urn) + if (_player == null) { return; } - LocalPlayerUI ui = GameManager.Instance?.World?.GetPrimaryPlayer()?.PlayerUI; - if (ui != null && ui.windowManager.IsWindowOpen(WindowGroup)) + if (_player.bag != null && _player.bag.AddItem(_s)) { - ui.windowManager.Close(WindowGroup); + return; + } + if (_player.inventory != null && _player.inventory.AddItem(_s)) + { + return; + } + _player.world.gameManager.ItemDropServer(_s, _player.GetPosition(), Vector3.zero); + } + + /// Урна убрана или выгружена, пока открыто её «Содержимое», - закрыть окно (череп из ячейки не потеряется: + /// Check успеет отметить его в урне, а урна при разрушении роняет череп). + public static void CloseIfShowing(TEFeatureCinerarium _u) + { + if (_urn == null || _urn != _u) + { + return; + } + Check(); + LocalPlayerUI ui = _player != null ? LocalPlayerUI.GetUIForPlayer(_player) : null; + _urn = null; + if (ui != null && ui.windowManager.IsWindowOpen(XUiC_BagStorageWindowGroup.ID)) + { + ui.windowManager.Close(XUiC_BagStorageWindowGroup.ID); } - Urn = null; } } } diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index b0de7d9..faeacb3 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ