Череп ставится декором прямо из руки: 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>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8920ee01b8
commit
a902b44bdf
@@ -0,0 +1,116 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user