diff --git a/Config/blocks.xml b/Config/blocks.xml index 7de1efe..4c7ace6 100644 --- a/Config/blocks.xml +++ b/Config/blocks.xml @@ -518,7 +518,9 @@ Составной блок, как земельный камень: TEFeatureStorage - сумка духа (окно хранилища 6x2, «Открыть»), TEFeatureCinerarium (HarmonySrc/Cinerarium.cs) - череп (положить/забрать), показ зоны 5x5, -1..+4, лимит ceil(убийств / 500) и запрет пересечения зон при постановке. Всё - в радиальном меню на E (решение 16.10). - Модель и иконка ВРЕМЕННЫЕ - кастрюля игры; своя урна будет из Blender. --> + Модель (16.10) - своя: бандл necrocinerarium (BlenderWork/necroCinerarium, make_urn.py): чёрная глазурь, черепа по + четырём сторонам, руны футарка кровью «SERVU ĜIS LA LASTA CINDRO», меандр, бусины; свечение рун и глазниц + включает TEFeatureCinerarium по черепу. Иконка - рендер той же модели (make_icon.py). --> @@ -536,8 +538,9 @@ - - + + + diff --git a/Config/recipes.xml b/Config/recipes.xml index fe285b7..681f293 100644 --- a/Config/recipes.xml +++ b/Config/recipes.xml @@ -606,12 +606,20 @@ - + + + + + + + + + diff --git a/HarmonySrc/Cinerarium.cs b/HarmonySrc/Cinerarium.cs index 7511c83..6311ef4 100644 --- a/HarmonySrc/Cinerarium.cs +++ b/HarmonySrc/Cinerarium.cs @@ -245,6 +245,7 @@ namespace NecromancerTome /// _sound - череп только что положили или вынули (порыв); при загрузке чанка дух появляется молча. public void SyncGenie(bool _sound) { + SyncGlow(); if (HasSkull && _genie == null) { _genie = CinerariumGenie.Spawn(ModelTransform()); @@ -259,6 +260,37 @@ namespace NecromancerTome } } + /// Руны кровью и глазницы черепов светятся, только когда в урне череп (16.10): _EmissionColor через + /// MaterialPropertyBlock на рендерерах модели урны (материал общий не трогается), духа не задевает. + public static Color GlowColor = new Color(2.2f, 2.2f, 2.2f, 1f); + static readonly MaterialPropertyBlock _glowBlock = new MaterialPropertyBlock(); + static readonly int EmissionColorId = Shader.PropertyToID("_EmissionColor"); + int _glowState = -1; // -1 - не ставили на эту модель + + void SyncGlow() + { + Transform t = ModelTransform(); + int want = HasSkull ? 1 : 0; + if (t == null || (_glowState == want && _glowModel == t)) + { + return; + } + foreach (Renderer r in t.GetComponentsInChildren(true)) + { + if (_genie != null && r.transform.IsChildOf(_genie.transform) || _bounds != null && r.transform.IsChildOf(_bounds.transform)) + { + continue; + } + r.GetPropertyBlock(_glowBlock); + _glowBlock.SetColor(EmissionColorId, HasSkull ? GlowColor : Color.black); + r.SetPropertyBlock(_glowBlock); + } + _glowState = want; + _glowModel = t; + } + + Transform _glowModel; + void RemoveGenie(bool _sound) { if (_genie == null) diff --git a/HarmonySrc/CinerariumGenie.cs b/HarmonySrc/CinerariumGenie.cs index e8761d5..83124f7 100644 --- a/HarmonySrc/CinerariumGenie.cs +++ b/HarmonySrc/CinerariumGenie.cs @@ -22,8 +22,13 @@ namespace NecromancerTome { public const string ModelPath = "#@modfolder(NecromancerTome):Resources/necrotechnologist?necroTechnologistPrefab.prefab"; - /// Высота корня модели над низом блока урны, м (кончик хвоста в модели - на 0.45 м). Подгоняется командой necrogenie. - public static float OffsetY = -0.25f; + /// Высота корня модели над низом блока урны, м. 16.10 в Blender по модели урны: -0.15 («духа чуть приподними»). + /// Подгоняется командой necrogenie. + public static float OffsetY = -0.15f; + /// Сдвиг вперёд в системе самого духа, м (16.10: «чуть вперёд, чтобы хвост не просвечивал сквозь урну сзади» + /// - загнутый назад кончик хвоста; в Blender 0.06 - ни одной вершины за стенкой, взято 0.07). Поворачивается вместе + /// с духом, поэтому хвост всегда в горлышке. Знак проверить в игре: necrogenie fwd. + public static float Forward = 0.07f; /// Поворот без работы, градусов в секунду. public static float TurnSpeed = 6f; /// Покачивание: размах (м) и период (с). @@ -203,14 +208,14 @@ namespace NecromancerTome { return; // замер как был } - Vector3 home = new Vector3(0f, CinerariumGenie.OffsetY, 0f); float yawTarget = _yaw + CinerariumGenie.TurnSpeed * Time.deltaTime; + Vector3 home = new Vector3(0f, CinerariumGenie.OffsetY, 0f) + Quaternion.Euler(0f, _yaw, 0f) * new Vector3(0f, 0f, CinerariumGenie.Forward); if (_visitLeft > 0f) { // Туда и обратно по синусу: на полпути - над местом работы, лицом к нему. _visitLeft -= Time.deltaTime; float k = Mathf.Sin(Mathf.Clamp01(1f - _visitLeft / VisitSeconds) * Mathf.PI); - Vector3 over = _visit + new Vector3(0f, CinerariumGenie.OffsetY + 0.6f, 0f); + Vector3 over = _visit + new Vector3(0f, CinerariumGenie.OffsetY + 0.6f, 0f) + Quaternion.Euler(0f, _yaw, 0f) * new Vector3(0f, 0f, CinerariumGenie.Forward); transform.localPosition = Vector3.Lerp(home, over, k); Vector3 d = _visit - home; if (d.x * d.x + d.z * d.z > 0.01f) @@ -252,7 +257,8 @@ namespace NecromancerTome public override string getHelp() { return "necrogenie - show the current values and how many spirits are on screen\n" + - "necrogenie y - model root height above the urn block's bottom (tail tip is 0.45 m above the root)\n" + + "necrogenie y - model root height above the urn block's bottom (tail tip is 0.47 m above the root)\n" + + "necrogenie fwd - shift along the spirit's own forward (keeps the curled tail inside the neck)\n" + "necrogenie turn - idle turning speed\n" + "necrogenie bob - bobbing height and period\n" + "necrogenie alpha <0-1> - body opacity"; @@ -268,6 +274,9 @@ namespace NecromancerTome case "y": CinerariumGenie.OffsetY = v; break; + case "fwd": + CinerariumGenie.Forward = v; + break; case "turn": CinerariumGenie.TurnSpeed = v; break; @@ -287,7 +296,7 @@ namespace NecromancerTome return; } } - con.Output("necrogenie: y " + CinerariumGenie.OffsetY.ToString("F2") + ", turn " + CinerariumGenie.TurnSpeed.ToString("F1") + + con.Output("necrogenie: y " + CinerariumGenie.OffsetY.ToString("F2") + ", fwd " + CinerariumGenie.Forward.ToString("F2") + ", turn " + CinerariumGenie.TurnSpeed.ToString("F1") + ", bob " + CinerariumGenie.BobHeight.ToString("F2") + " / " + CinerariumGenie.BobPeriod.ToString("F1") + " s, alpha " + CinerariumGenie.Alpha.ToString("F2") + "; spirits on screen: " + CinerariumGenie.Live.Count); } diff --git a/HarmonySrc/DecorColliderTagPatch.cs b/HarmonySrc/DecorColliderTagPatch.cs index cc4d901..2ff82e1 100644 --- a/HarmonySrc/DecorColliderTagPatch.cs +++ b/HarmonySrc/DecorColliderTagPatch.cs @@ -20,7 +20,7 @@ namespace NecromancerTome static bool Ours(string _name) { - return _name == "necroBookMindPrefab" || _name == "necroKnifeDecorPrefab" || _name == "necroMortarPrefab" || _name.StartsWith("necroBloodRose") || _name.StartsWith("necroPoster") || _name == "necroBookDoorPrefab" || _name.StartsWith("necroSkullDecor"); + return _name == "necroBookMindPrefab" || _name == "necroKnifeDecorPrefab" || _name == "necroMortarPrefab" || _name.StartsWith("necroBloodRose") || _name.StartsWith("necroPoster") || _name == "necroBookDoorPrefab" || _name.StartsWith("necroSkullDecor") || _name == "necroCinerariumPrefab"; } public static void Postfix(Transform __result) diff --git a/NecromancerHarmony.dll b/NecromancerHarmony.dll index 6c23567..beba47c 100644 Binary files a/NecromancerHarmony.dll and b/NecromancerHarmony.dll differ diff --git a/Resources/necrocinerarium b/Resources/necrocinerarium new file mode 100644 index 0000000..b73eab6 Binary files /dev/null and b/Resources/necrocinerarium differ diff --git a/UIAtlases/ItemIconAtlas/necroCinerarium.png b/UIAtlases/ItemIconAtlas/necroCinerarium.png new file mode 100644 index 0000000..ce19455 Binary files /dev/null and b/UIAtlases/ItemIconAtlas/necroCinerarium.png differ