Files
necromants-tome-7d2d-3-2/HarmonySrc/SkullDecorPlace.cs
T
AlexCubeandClaude Opus 5.5 a902b44bdf Череп ставится декором прямо из руки: R - меню вида (просто череп / по центру / у стены), ПКМ - поставить
Предмет necroSkull остаётся ItemClass, добавлено Action1 PlaceAsBlock (в ItemValue не пишется -
сейвы целы). R для черепа ловится постфиксом PlayerMoveController.Update, выбор - cvar
necroSkullDecorMode. Поднятый и разрушенный блок - снова череп. Помощник necroSkullDecor спрятан
(CreativeMode None), рецепт «череп -> декор» убран, обратный оставлен для уже сделанных помощников.
Описание черепа дополнено (13 языков), подсказка и пункт меню «Просто череп».

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

117 lines
5.4 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 с черепом в руке - круговое меню: «Просто череп» / «Декор: по центру» / «Декор: у стены».
/// ПКМ - ставит блок выбранного вида (Action1 = PlaceAsBlock у necroSkull в items.xml); в «Просто череп» - ничего.
/// Поднятый блок (E) и разрушенный - снова череп-предмет (CanPickup param1 / drop в blocks.xml).
/// Предмет остаётся ItemClass: действие в ItemValue не пишется (ItemValue.Write: тип, износ, качество, Meta,
/// метаданные, статы, моды) - старые стаки черепа читаются как прежде.
/// R для черепа игра сама не обрабатывает (PlayerMoveController открывает меню только оружию, ближнему бою и
/// блокам) - поэтому нажатие ловится постфиксом к PlayerMoveController.Update. Выбор - cvar игрока
/// (necroSkullDecorMode, без точки - пишется в сейв).
/// </summary>
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);
}
}
/// <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.OpenMenu(__instance, pl);
}
}
/// <summary>ПКМ с черепом: ставит выбранный вид; в «Просто череп» не ставит (и подсказывает про R).</summary>
[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;
}
}
}