From 23587d78e035d8bc10d780b1c7a5b4d75e81f328 Mon Sep 17 00:00:00 2001 From: AlexCube Date: Fri, 16 Oct 2026 19:53:43 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D1=80=D0=BD=D0=B0:=20=D0=B4=D1=83=D1=85?= =?UTF-8?q?=20=D0=BE=D0=BF=D1=83=D1=81=D0=BA=D0=B0=D0=B5=D1=82=20=D1=80?= =?UTF-8?q?=D1=83=D0=BA=D0=B8=20=D0=B8=D0=B7=20=D0=A2-=D0=BF=D0=BE=D0=B7?= =?UTF-8?q?=D1=8B=20(=D0=BA=D0=BE=D1=81=D1=82=D0=B8=20=D0=BF=D0=BB=D0=B5?= =?UTF-8?q?=D1=87=20=D0=B8=20=D0=BF=D1=80=D0=B5=D0=B4=D0=BF=D0=BB=D0=B5?= =?UTF-8?q?=D1=87=D0=B8=D0=B9=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D1=8F?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B8);=20necrogenie=20arms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- HarmonySrc/CinerariumGenie.cs | 87 +++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) diff --git a/HarmonySrc/CinerariumGenie.cs b/HarmonySrc/CinerariumGenie.cs index 1648402..9f3c447 100644 --- a/HarmonySrc/CinerariumGenie.cs +++ b/HarmonySrc/CinerariumGenie.cs @@ -35,6 +35,11 @@ namespace NecromancerTome public static float BobHeight = 0.04f; public static float BobPeriod = 4f; public static float Alpha = 0.3f; + /// Руки (16.10: «Т-поза бесит»): плечо от вертикали вбок и вперёд, локоть согнут вперёд, градусы. + /// Модель в позе покоя, аниматора нет - кости ставятся один раз при появлении. + public static float ArmOut = 12f; + public static float ArmFwd = 15f; + public static float Elbow = 35f; static GameObject _prefab; static bool _tried; @@ -84,7 +89,7 @@ namespace NecromancerTome { Object.Destroy(c); } - g.AddComponent(); + g.AddComponent().Pose(); return g; } @@ -227,6 +232,65 @@ namespace NecromancerTome public const float VisitSeconds = 2.2f; /// Почернел и замер (готовое класть некуда, решение 06.10). bool _stuck; + /// Кости рук (плечо, предплечье, кисть по сторонам) и их поворот в позе покоя. + Transform[] _arm; + Quaternion[] _armRest; + static bool _armLogged; + + /// Опустить руки из позы покоя: направление плеча и предплечья задаётся в осях модели (вперёд - +Z), + /// поворот - от текущего направления кости к нужному, так что оси самих костей значения не имеют. + public void Pose() + { + if (_arm == null) + { + string[] names = { "LeftArm", "LeftForeArm", "LeftHand", "RightArm", "RightForeArm", "RightHand" }; + _arm = new Transform[names.Length]; + _armRest = new Quaternion[names.Length]; + foreach (Transform t in GetComponentsInChildren(true)) + { + for (int i = 0; i < names.Length; i++) + { + if (_arm[i] == null && t.name.EndsWith(names[i])) + { + _arm[i] = t; + _armRest[i] = t.localRotation; + } + } + } + if (!_armLogged) + { + _armLogged = true; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + for (int i = 0; i < names.Length; i++) + { + sb.Append(names[i]).Append('=').Append(_arm[i] != null ? "ok" : "НЕТ").Append(' '); + } + Debug.Log("[NecromancerTome] CinerariumGenie: кости рук " + sb); + } + } + for (int i = 0; i < _arm.Length; i++) + { + if (_arm[i] != null) + { + _arm[i].localRotation = _armRest[i]; + } + } + for (int side = 0; side < 2; side++) + { + Transform up = _arm[side * 3], fore = _arm[side * 3 + 1], hand = _arm[side * 3 + 2]; + if (up == null || fore == null || hand == null) + { + continue; + } + float sign = Mathf.Sign(transform.InverseTransformPoint(up.position).x); + float o = CinerariumGenie.ArmOut * Mathf.Deg2Rad, f = CinerariumGenie.ArmFwd * Mathf.Deg2Rad; + Vector3 upDir = new Vector3(sign * Mathf.Sin(o), -Mathf.Cos(o) * Mathf.Cos(f), Mathf.Sin(f)).normalized; + Vector3 foreDir = Vector3.RotateTowards(upDir, Vector3.forward, CinerariumGenie.Elbow * Mathf.Deg2Rad, 0f); + up.rotation = Quaternion.FromToRotation(fore.position - up.position, transform.TransformDirection(upDir)) * up.rotation; + fore.rotation = Quaternion.FromToRotation(hand.position - fore.position, transform.TransformDirection(foreDir)) * fore.rotation; + } + } + /// Светящиеся материалы рендереров - вернуть после почернения. readonly Dictionary _glowing = new Dictionary(); @@ -348,7 +412,8 @@ namespace NecromancerTome "necrogenie bob - bobbing height and period\n" + "necrogenie alpha <0-1> - body brightness (the body adds light, it is not alpha-blended)\n" + "necrogenie glow <0-1> - body's own glow (visible at night)\n" + - "necrogenie tint - body colour"; + "necrogenie tint - body colour\n" + + "necrogenie arms - arm pose, degrees: upper arm from vertical sideways and forward, elbow bend"; } public override void Execute(List _params, CommandSenderInfo _senderInfo) @@ -382,6 +447,21 @@ namespace NecromancerTome CinerariumGenie.Glow = Mathf.Clamp01(v); CinerariumGenie.ApplyAlpha(); break; + case "arms": + CinerariumGenie.ArmOut = v; + if (_params.Count >= 3 && float.TryParse(_params[2], System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out float af)) + { + CinerariumGenie.ArmFwd = af; + } + if (_params.Count >= 4 && float.TryParse(_params[3], System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out float ae)) + { + CinerariumGenie.Elbow = ae; + } + foreach (CinerariumGenieMotion m in CinerariumGenie.Live) + { + m.Pose(); + } + break; case "tint": if (_params.Count >= 4 && float.TryParse(_params[2], System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out float g) && @@ -399,7 +479,8 @@ namespace NecromancerTome 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") + ", glow " + CinerariumGenie.Glow.ToString("F2") + ", tint " + - CinerariumGenie.Tint.r.ToString("F2") + " " + CinerariumGenie.Tint.g.ToString("F2") + " " + CinerariumGenie.Tint.b.ToString("F2") + "; spirits on screen: " + CinerariumGenie.Live.Count); + CinerariumGenie.Tint.r.ToString("F2") + " " + CinerariumGenie.Tint.g.ToString("F2") + " " + CinerariumGenie.Tint.b.ToString("F2") + ", arms " + CinerariumGenie.ArmOut.ToString("F0") + " " + + CinerariumGenie.ArmFwd.ToString("F0") + " " + CinerariumGenie.Elbow.ToString("F0") + "; spirits on screen: " + CinerariumGenie.Live.Count); } } }