Отдельный блок necroChalkboardPlayer (модель и надпись сюжетной доски): крафт с начала игры - краска 2, дерево 8, гвозди 4, волокна 3, кости 2; писать можно в обычной игре, записи свои у каждой доски; можно подобрать. Сюжетная necroChalkboard (чертоги) по-прежнему пишется только модом. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
123 lines
4.9 KiB
C#
123 lines
4.9 KiB
C#
using System;
|
||
using HarmonyLib;
|
||
using UnityEngine;
|
||
|
||
namespace NecromancerTome
|
||
{
|
||
/// <summary>
|
||
/// Грифельная доска (necroChalkboard, 09.10.2026): надписи мелом - как на табличках (TEFeatureSignable), но
|
||
/// «игрок этого делать не будет, а нам для сюжета пригодится». Поэтому команда «написать» у доски есть
|
||
/// только в редакторе префабов, в творческом режиме и в режиме отладки (так мы и подписываем её - текст
|
||
/// сохраняется в префабе локации, IFeatureSavedInPrefab). В обычной игре доску только читают: без команды
|
||
/// нет и подсказки «E - использовать».
|
||
/// </summary>
|
||
public static class Chalkboard
|
||
{
|
||
/// <summary>Сюжетная доска (чертоги, локации): пишет мод или автор префаба.</summary>
|
||
public const string BlockName = "necroChalkboard";
|
||
/// <summary>Доска игрока (10.10): крафтится, пишется в обычной игре - записи свои у каждой доски.</summary>
|
||
public const string PlayerBlockName = "necroChalkboardPlayer";
|
||
|
||
static string NameOf(TEFeatureSignable _sign)
|
||
{
|
||
return _sign?.Parent?.TeData?.Block?.GetBlockName();
|
||
}
|
||
|
||
/// <summary>Любая из досок - для материала надписи.</summary>
|
||
public static bool Is(TEFeatureSignable _sign)
|
||
{
|
||
string n = NameOf(_sign);
|
||
return n == BlockName || n == PlayerBlockName;
|
||
}
|
||
|
||
/// <summary>Сюжетная доска - писать только в редакторе, творческом режиме, отладке.</summary>
|
||
public static bool IsLocked(TEFeatureSignable _sign)
|
||
{
|
||
return NameOf(_sign) == BlockName && !CanWrite();
|
||
}
|
||
|
||
/// <summary>Кто может писать: редактор префабов, творческий режим, отладка.</summary>
|
||
public static bool CanWrite()
|
||
{
|
||
return GameManager.Instance != null && GameManager.Instance.IsEditMode() ||
|
||
GameStats.GetBool(EnumGameStats.IsCreativeMenuEnabled) ||
|
||
GamePrefs.GetBool(EnumGamePrefs.DebugMenuEnabled);
|
||
}
|
||
|
||
/// <summary>Материал надписи - из бандла, свой шейдер NecroTome/ChalkText с ZTest LEqual (тест 09.10: надпись
|
||
/// просвечивала сквозь стены - встроенный GUI/Text Shader берёт ZTest из глобального unity_GUIZTestMode, который
|
||
/// интерфейс держит «Always», и переопределение в материале не помогло). Шрифт динамический: его текстура
|
||
/// растёт и пересоздаётся при новых буквах - держим её в материале надписи (один материал на все доски).</summary>
|
||
static Material _mat;
|
||
static Font _font;
|
||
static bool _hooked;
|
||
|
||
public static void BindText(TextMesh _tm, MeshRenderer _r)
|
||
{
|
||
_mat = _r.sharedMaterial;
|
||
_font = _tm.font;
|
||
if (_mat == null || _font == null)
|
||
{
|
||
return;
|
||
}
|
||
_mat.mainTexture = _font.material.mainTexture;
|
||
if (!_hooked)
|
||
{
|
||
_hooked = true;
|
||
Font.textureRebuilt += _f =>
|
||
{
|
||
if (_mat != null && _f == _font)
|
||
{
|
||
_mat.mainTexture = _f.material.mainTexture;
|
||
}
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(TEFeatureSignable), nameof(TEFeatureSignable.SetBlockEntityData))]
|
||
public static class Patch_TEFeatureSignable_SetBlockEntityData_Chalkboard
|
||
{
|
||
public static void Postfix(TEFeatureSignable __instance, BlockEntityData _blockEntityData)
|
||
{
|
||
if (_blockEntityData == null || !_blockEntityData.bHasTransform || !Chalkboard.Is(__instance))
|
||
{
|
||
return;
|
||
}
|
||
foreach (TextMesh tm in _blockEntityData.transform.GetComponentsInChildren<TextMesh>())
|
||
{
|
||
MeshRenderer r = tm.GetComponent<MeshRenderer>();
|
||
if (r != null && tm.font != null)
|
||
{
|
||
Chalkboard.BindText(tm, r);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(TEFeatureSignable), nameof(TEFeatureSignable.AllowBlockActivationCommand))]
|
||
public static class Patch_TEFeatureSignable_AllowBlockActivationCommand_Chalkboard
|
||
{
|
||
public static void Postfix(TEFeatureSignable __instance, ITileEntityFeature _module, ReadOnlySpan<char> _commandName, ref bool __result)
|
||
{
|
||
if (__result && __instance.Equals(_module) && _commandName.SequenceEqual("edit".AsSpan()) &&
|
||
Chalkboard.IsLocked(__instance))
|
||
{
|
||
__result = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
[HarmonyPatch(typeof(TEFeatureSignable), nameof(TEFeatureSignable.GetActivationText))]
|
||
public static class Patch_TEFeatureSignable_GetActivationText_Chalkboard
|
||
{
|
||
public static void Postfix(TEFeatureSignable __instance, ref string __result)
|
||
{
|
||
if (Chalkboard.IsLocked(__instance))
|
||
{
|
||
__result = null;
|
||
}
|
||
}
|
||
}
|
||
}
|