Книга: главы ножа и Могильной крысы; плакат ножа, грифельная доска, дверь-шкаф; чертоги 25x8x25; плата силовой ножа 20/40

- Книга некроманта: главы «Нож некроманта» и «Могильная крыса» - лист-чертёж сверху (Textures/,
  три вида из Blender, подписи на эсперанто), управление и лор; окно книги непрозрачное, текст с контуром
- «Дух крысы» переименован в «Могильную крысу» на 13 языках (ключи прежние)
- Блоки (Dev): плакат-синька ножа (necroPosterKnife, 3:2 под полотно рамки), грифельная доска
  necroChalkboard (надписи - TEFeatureSignable, писать только в редакторе/творческом; шрифт Neucha OFL,
  свой шейдер текста с тестом глубины), дверь-книжный шкаф necroBookDoor (своя модель с аниматором,
  хитбокс створки через RootTransformRefParent)
- Чертоги: префаб 25x8x25 (промежуточный); открываются только межкомнатные двери; надписи на досках
  по дням игры: «Отомсти архимагу!», с 5-го дня «Берегись излучения красной луны»
- Нож: силовая атака стоит 20 здоровья, с «Мёртвой бурей» 40; не хватает - itembreak, «Недостаточно
  здоровья» и обычный удар; описания на 13 языках
- Консольная команда necromodel - устройство модели блока в лог

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-09 18:26:17 +03:00
co-authored by Claude Opus 5.5
parent e94e967b8e
commit 4e14a0562b
23 changed files with 609 additions and 41 deletions
+61 -3
View File
@@ -27,7 +27,9 @@ namespace NecromancerTome
/// (woodShapes:cube) -&gt; terrBedrock (в меню творчества его нет, рисовали деревом),
/// одиночная книга на столе -&gt; necroMemoryBook, на стол с реактивами - нож-декорация,
/// кровать (SleepingBag) -&gt; necroPalaceBed: иначе игра делает её точкой возрождения игрока.
/// Построены ли - по книге: нет её - ставим заново (самопочинка).
/// Построены ли - сверка с префабом каждой клетки (Mismatches: тип, плотность, покраска) при каждом входе:
/// расхождение - ставим заново (самопочинка; заодно новый, более широкий префаб сам перестраивает старые
/// чертоги в сейвах). Надписи на досках из префаба НЕ переносятся (указание 09.10: «текст будет добавлять мод по событиям»).
///
/// ОХРАНА. Внутри чертогов игра считает место «зоной торговца» (патч IsWithinTraderArea):
/// блоки не ломаются ни ударом, ни взрывом, строить нельзя. Чужие сущности в коробке чертогов
@@ -45,6 +47,8 @@ namespace NecromancerTome
public const string BedBlock = "necroPalaceBed";
public const string ShellFrom = "woodShapes:cube";
public const string ShellTo = "terrBedrock";
/// <summary>Межкомнатные двери - их чертоги открывают сами при входе (кроме входной).</summary>
public const string PassageDoor = "exteriorHouseDoorWhite";
/// <summary>Одиночная книга на обеденном столе (cntBookPile09 в префабе).</summary>
public static readonly Vector3i BookAt = new Vector3i(12, 2, 9);
/// <summary>Место ножа на столе с реактивами (указание пользователя).</summary>
@@ -408,8 +412,9 @@ namespace NecromancerTome
return Mismatches(_world, _o) == 0;
}
/// <summary>Все двери чертогов - открыты (в редакторе сохранились закрытыми, а дух дверей не
/// открывает). Состояние двери - в её TEFeatureDoor, не в блоке.</summary>
/// <summary>Межкомнатные двери чертогов (PassageDoor) - открыты (в редакторе сохранились закрытыми, а дух
/// дверей не открывает), входная - закрыта. Прочие двери (шкаф-тайник, стальная - указание 09.10: «закрыты
/// и откроются только по событию») не трогаем: их открывает событие. Состояние двери - в её TEFeatureDoor.</summary>
public static void OpenDoors(World _world, Vector3i _o)
{
Vector3i s = Size;
@@ -421,6 +426,10 @@ namespace NecromancerTome
if (_world.GetTileEntity(_o + new Vector3i(x, y, z)) is TileEntityComposite tec)
{
TEFeatureDoor door = tec.GetFeature<TEFeatureDoor>();
if (door == null || _world.GetBlock(_o + new Vector3i(x, y, z)).Block.GetBlockName() != PassageDoor)
{
continue;
}
// Входная - закрыть (могла остаться открытой от прежних входов), остальные - открыть.
bool wantOpen = new Vector3i(x, y, z) != EntranceDoorAt;
if (door != null && door.IsOpen() != wantOpen)
@@ -436,6 +445,54 @@ namespace NecromancerTome
}
}
/// <summary>Надписи на досках чертогов (указание 09.10). Лор: некроманта бросили в этот мир умирать - раздели,
/// лишили артефактов (и вживлённых тоже) и ментальной магией стёрли память, «закрыв знания, опасные для общества».
/// Доска - то, что он ещё помнит или успел себе написать; строки прибавляются по событиям игры. Пока событие -
/// только день: (с какого дня, ключ локализации). Остальные строки - позднее.</summary>
public static readonly (int day, string key)[] BoardLines =
{
(1, "necroPalaceBoardRevenge"),
(5, "necroPalaceBoardRedMoon"),
};
/// <summary>При каждом входе: на каждой доске (necroChalkboard) чертогов - все наступившие строки, на языке игрока.
/// Текст из префаба в чертоги не идёт (Stamp ставит только блоки) - пишет только мод.</summary>
public static void UpdateBoards(World _world, Vector3i _o)
{
int day = GameUtils.WorldTimeToDays(_world.worldTime);
var lines = new List<string>();
foreach (var l in BoardLines)
{
if (day >= l.day)
{
lines.Add(Localization.Get(l.key));
}
}
string text = string.Join("\n", lines);
Vector3i s = Size;
int n = 0;
for (int y = 0; y < s.y; y++)
for (int z = 0; z < s.z; z++)
for (int x = 0; x < s.x; x++)
{
Vector3i wp = _o + new Vector3i(x, y, z);
if (_world.GetBlock(wp).Block?.GetBlockName() != Chalkboard.BlockName ||
!(_world.GetTileEntity(wp) is TileEntityComposite tec) || !tec.TryGetSelfOrFeature(out TEFeatureSignable sign))
{
continue;
}
if ((sign.GetAuthoredText()?.Text ?? "") != text)
{
sign.SetText(text, true);
n++;
}
}
if (n > 0)
{
Debug.Log("[NecromancerTome] MindPalace: надпись на досках (день " + day + ", строк " + lines.Count + "), досок " + n);
}
}
public static void Stamp(World _world, Vector3i _o)
{
Prefab p = LoadPrefab();
@@ -707,6 +764,7 @@ namespace NecromancerTome
Debug.Log("[NecromancerTome] MindPalace: коллизии " + (world.IsChunkAreaCollidersLoaded(spawn) ? "готовы" : "НЕ готовы, пускаем по таймеру"));
_stage = Stage.Ready;
OpenDoors(world, _origin);
UpdateBoards(world, _origin);
LogCell(world, _origin + KnifeAt, "нож");
LogCell(world, _origin + BookAt, "книга");
MindControl.Begin(player, spawn, SpawnYaw);