using GUI_2; using HarmonyLib; using UnityEngine; namespace NecromancerTome { /// /// Череп ставится декором прямо из руки (15.10.2026, указание: «Сейчас держу в руках именно череп. И он нормальный. /// Но его нельзя поставить как декор. Может сделать возможность через R переключаться в режим декора и сразу /// выбирать центральный или у стены?»; «А при поднятии снова делать просто черепом»). /// Удержание R с черепом в руке - круговое меню: «Просто череп» / «Декор: по центру» / «Декор: у стены». /// ПКМ - ставит блок выбранного вида (Action1 = PlaceAsBlock у necroSkull в items.xml); в «Просто череп» - ничего. /// Поднятый блок (E) и разрушенный - снова череп-предмет (CanPickup param1 / drop в blocks.xml). /// Предмет остаётся ItemClass: действие в ItemValue не пишется (ItemValue.Write: тип, износ, качество, Meta, /// метаданные, статы, моды) - старые стаки черепа читаются как прежде. /// R для черепа игра сама не обрабатывает (PlayerMoveController открывает меню только оружию, ближнему бою и /// блокам) - поэтому нажатие ловится постфиксом к PlayerMoveController.Update. Выбор - cvar игрока /// (necroSkullDecorMode, без точки - пишется в сейв). /// public static class SkullDecorPlace { public const string ModeCVar = "necroSkullDecorMode"; public const int Off = 0, Center = 1, Back = 2; public const string CenterBlock = "necroSkullDecorCenter"; public const string BackBlock = "necroSkullDecorBack"; public static bool IsSkull(ItemClass _item) => _item != null && _item.Name == NecroSkull.ItemName; public static int Mode(EntityAlive _e) { if (_e == null) return Off; int m = Mathf.RoundToInt(_e.GetCVar(ModeCVar)); return m >= Off && m <= Back ? m : Off; } public static void OnRadialCommand(XUiC_Radial _sender, int _commandIndex, XUiC_Radial.RadialContextAbs _context) { EntityPlayerLocal pl = _sender?.xui?.playerUI?.entityPlayer; if (pl != null && _commandIndex >= Off && _commandIndex <= Back) { pl.SetCVar(ModeCVar, _commandIndex); } } public static void OpenMenu(PlayerMoveController _pmc, EntityPlayerLocal _pl) { XUiC_Radial r = _pmc.playerUI?.xui?.RadialWindow; if (r == null) return; int cur = Mode(_pl); r.Open(); r.ResetRadialEntries(); r.CreateRadialEntry(Off, "ui_game_symbol_hand", "UIAtlas", "", Localization.Get("necroSkullModeOff"), cur == Off); r.CreateRadialEntry(Center, "ui_game_symbol_skull", "UIAtlas", "", Localization.Get("necroSkullDecorCenter"), cur == Center); r.CreateRadialEntry(Back, "ui_game_symbol_skull", "UIAtlas", "", Localization.Get("necroSkullDecorBack"), cur == Back); r.SetCommonData(UIUtils.GetButtonIconForAction(_pmc.playerInput.Reload), OnRadialCommand, new XUiC_Radial.RadialContextHoldingSlotIndex(_pl.inventory.holdingItemIdx), cur, false, XUiC_Radial.RadialValidSameHoldingSlotIndex); } } /// R с черепом в руке - меню вида декора. [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.OpenMenu(__instance, pl); } } /// ПКМ с черепом: ставит выбранный вид; в «Просто череп» не ставит (и подсказывает про R). [HarmonyPatch(typeof(ItemActionPlaceAsBlock), nameof(ItemActionPlaceAsBlock.ExecuteAction))] public static class Patch_ItemActionPlaceAsBlock_ExecuteAction_SkullDecor { static float _hintAt; public static bool Prefix(ItemActionPlaceAsBlock __instance, ItemActionData _actionData, bool _bReleased) { if (!SkullDecorPlace.IsSkull(__instance.item)) { return true; } EntityAlive e = _actionData?.invData?.holdingEntity; int mode = SkullDecorPlace.Mode(e); if (mode == SkullDecorPlace.Off) { if (_bReleased && e is EntityPlayerLocal pl && Time.time - _hintAt > 2f) { _hintAt = Time.time; GameManager.ShowTooltip(pl, Localization.Get("necroSkullDecorHint")); } return false; } BlockValue bv = Block.GetBlockValue(mode == SkullDecorPlace.Back ? SkullDecorPlace.BackBlock : SkullDecorPlace.CenterBlock); if (!bv.isair) { __instance.blockToPlace = bv; } return true; } } }