Files
necromants-tome-7d2d-3-2/HarmonySrc/SkullDecorPlace.cs
T
AlexCubeandClaude Opus 5.5 99c2f183ad Череп: три режима как у мебели - предмет / декор по центру / декор у стены
R с черепом-предметом - меню; выбор декора превращает стопку в ячейке в блок (превью, повороты
блока). С декором в руке R - обычное меню блока плюс «Просто череп» и второй вид. Действие
PlaceAsBlock у предмета убрано (ПКМ из предмета больше не ставит). Стопка блоков 50, как у черепа.
Описания черепа и декора (13 языков) - под новую схему.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:37:39 +03:00

124 lines
7.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using GUI_2;
using HarmonyLib;
using UnityEngine;
namespace NecromancerTome
{
/// <summary>
/// Череп - предмет или декор (15.10.2026, вторая версия). Указание после теста: «Посмотри как ставится мебель. Например,
/// горшки с цветами... Три режима. Предмет, и два декора. Если выбран декор, хват меняется на тот который при установке
/// строительных блоков или мебели, и я начинаю видеть типа превью того как блок будет стоять»; поворот - как у блоков.
/// Череп-предмет в руке, удержание R - меню: «Просто череп» / «Череп: по центру» / «Череп: у стены». Выбор декора
/// превращает всю стопку в ячейке пояса в блок этого вида: в руке настоящий блок - превью, повороты блока.
/// Блок-декор в руке, R - обычное меню блока (короткое нажатие - поворот), к нему добавлены «Просто череп» (стопка
/// обратно в черепа) и второй вид декора.
/// Поднятый (E) и разрушенный декор - снова череп-предмет (blocks.xml: CanPickup param1 / drop).
/// Предмет necroSkull не меняется (ItemClass, без действий) - сейвы с черепом целы; блоки-декор - отдельные блоки.
/// R для предмета игра не обрабатывает (PlayerMoveController открывает меню только оружию, ближнему бою и блокам) -
/// нажатие ловится постфиксом к PlayerMoveController.Update.
/// </summary>
public static class SkullDecorPlace
{
public const int ItemIdx = 0, CenterIdx = 1, BackIdx = 2;
/// <summary>Номера наших пунктов в меню блока - вне занятых игрой (-2..10).</summary>
public const int BlockMenuItem = 40, BlockMenuCenter = 41, BlockMenuBack = 42;
public const string CenterBlock = "necroSkullDecorCenter";
public const string BackBlock = "necroSkullDecorBack";
public static bool IsSkull(ItemClass _item) => _item != null && _item.Name == NecroSkull.ItemName;
public static bool IsDecor(ItemClass _item) => _item != null && (_item.Name == CenterBlock || _item.Name == BackBlock);
/// <summary>Стопка в руке превращается в _name (тот же счёт).</summary>
public static void Convert(EntityPlayerLocal _pl, string _name)
{
if (_pl?.inventory == null) return;
ItemStack cur = _pl.inventory.holdingItemStack;
if (cur == null || cur.IsEmpty() || !(IsSkull(cur.itemValue.ItemClass) || IsDecor(cur.itemValue.ItemClass))) return;
if (cur.itemValue.ItemClass.Name == _name) return;
ItemValue iv = ItemClass.GetItem(_name);
if (iv == null || iv.IsEmpty()) return;
_pl.inventory.SetItem(_pl.inventory.holdingItemIdx, new ItemStack(iv, cur.count));
}
public static void OnItemMenu(XUiC_Radial _sender, int _commandIndex, XUiC_Radial.RadialContextAbs _context)
{
EntityPlayerLocal pl = _sender?.xui?.playerUI?.entityPlayer;
if (_commandIndex == CenterIdx) Convert(pl, CenterBlock);
else if (_commandIndex == BackIdx) Convert(pl, BackBlock);
}
public static void OpenItemMenu(PlayerMoveController _pmc, EntityPlayerLocal _pl)
{
XUiC_Radial r = _pmc.playerUI?.xui?.RadialWindow;
if (r == null) return;
r.Open();
r.ResetRadialEntries();
r.CreateRadialEntry(ItemIdx, "necroSkull", "ItemIconAtlas", "", Localization.Get("necroSkullModeOff"), true);
r.CreateRadialEntry(CenterIdx, "ui_game_symbol_skull", "UIAtlas", "", Localization.Get("necroSkullDecorCenter"));
r.CreateRadialEntry(BackIdx, "ui_game_symbol_skull", "UIAtlas", "", Localization.Get("necroSkullDecorBack"));
r.SetCommonData(UIUtils.GetButtonIconForAction(_pmc.playerInput.Reload), OnItemMenu,
new XUiC_Radial.RadialContextHoldingSlotIndex(_pl.inventory.holdingItemIdx), ItemIdx, false,
XUiC_Radial.RadialValidSameHoldingSlotIndex);
}
/// <summary>Меню блока с декором в руке: наши пункты - сами, остальное - игре.</summary>
public static void OnBlockMenu(XUiC_Radial _sender, int _commandIndex, XUiC_Radial.RadialContextAbs _context)
{
EntityPlayerLocal pl = _sender?.xui?.playerUI?.entityPlayer;
switch (_commandIndex)
{
case BlockMenuItem: Convert(pl, NecroSkull.ItemName); return;
case BlockMenuCenter: Convert(pl, CenterBlock); return;
case BlockMenuBack: Convert(pl, BackBlock); return;
}
_sender.handleBlockShapeCommand(_sender, _commandIndex, _context);
}
}
/// <summary>R с черепом-предметом в руке - меню «предмет / два декора».</summary>
[HarmonyPatch(typeof(PlayerMoveController), nameof(PlayerMoveController.Update))]
public static class Patch_PlayerMoveController_Update_SkullDecor
{
public static void Postfix(PlayerMoveController __instance)
{
EntityPlayerLocal pl = __instance.entityPlayerLocal;
if (pl == null || pl.inventory == null || !SkullDecorPlace.IsSkull(pl.inventory.holdingItem) || pl.IsDead())
{
return;
}
PlayerActionsLocal inp = __instance.playerInput;
if (inp == null || !(inp.Reload.WasPressed || inp.PermanentActions.Reload.WasPressed) || pl.inventory.IsHandSwitching())
{
return;
}
if (__instance.playerUI == null || __instance.playerUI.windowManager.IsModalWindowOpen())
{
return;
}
SkullDecorPlace.OpenItemMenu(__instance, pl);
}
}
/// <summary>Меню блока с черепом-декором в руке: к пунктам игры - «Просто череп» и второй вид.</summary>
[HarmonyPatch(typeof(XUiC_Radial), nameof(XUiC_Radial.SetupBlockShapeData))]
public static class Patch_XUiC_Radial_SetupBlockShapeData_SkullDecor
{
public static void Postfix(XUiC_Radial __instance)
{
EntityPlayerLocal pl = __instance.xui?.playerUI?.entityPlayer;
ItemClass held = pl?.inventory?.holdingItem;
if (!SkullDecorPlace.IsDecor(held))
{
return;
}
__instance.CreateRadialEntry(SkullDecorPlace.BlockMenuItem, "necroSkull", "ItemIconAtlas", "", Localization.Get("necroSkullModeOff"));
if (held.Name == SkullDecorPlace.CenterBlock)
__instance.CreateRadialEntry(SkullDecorPlace.BlockMenuBack, "ui_game_symbol_skull", "UIAtlas", "", Localization.Get("necroSkullDecorBack"));
else
__instance.CreateRadialEntry(SkullDecorPlace.BlockMenuCenter, "ui_game_symbol_skull", "UIAtlas", "", Localization.Get("necroSkullDecorCenter"));
__instance.SetCommonData(UIUtils.GetButtonIconForAction(__instance.xui.playerUI.playerInput.Activate), SkullDecorPlace.OnBlockMenu,
new XUiC_Radial.RadialContextHoldingSlotIndex(pl.inventory.holdingItemIdx), -1, true, XUiC_Radial.RadialValidSameHoldingSlotIndex);
}
}
}