Урна: дух опускает руки из Т-позы (кости плеч и предплечий при появлении); necrogenie arms

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AlexCube
2026-10-16 19:53:43 +03:00
co-authored by Claude Opus 5.5
parent 49c7afe273
commit 23587d78e0
+84 -3
View File
@@ -35,6 +35,11 @@ namespace NecromancerTome
public static float BobHeight = 0.04f;
public static float BobPeriod = 4f;
public static float Alpha = 0.3f;
/// <summary>Руки (16.10: «Т-поза бесит»): плечо от вертикали вбок и вперёд, локоть согнут вперёд, градусы.
/// Модель в позе покоя, аниматора нет - кости ставятся один раз при появлении.</summary>
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<CinerariumGenieMotion>();
g.AddComponent<CinerariumGenieMotion>().Pose();
return g;
}
@@ -227,6 +232,65 @@ namespace NecromancerTome
public const float VisitSeconds = 2.2f;
/// <summary>Почернел и замер (готовое класть некуда, решение 06.10).</summary>
bool _stuck;
/// <summary>Кости рук (плечо, предплечье, кисть по сторонам) и их поворот в позе покоя.</summary>
Transform[] _arm;
Quaternion[] _armRest;
static bool _armLogged;
/// <summary>Опустить руки из позы покоя: направление плеча и предплечья задаётся в осях модели (вперёд - +Z),
/// поворот - от текущего направления кости к нужному, так что оси самих костей значения не имеют.</summary>
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<Transform>(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;
}
}
/// <summary>Светящиеся материалы рендереров - вернуть после почернения.</summary>
readonly Dictionary<Renderer, Material[]> _glowing = new Dictionary<Renderer, Material[]>();
@@ -348,7 +412,8 @@ namespace NecromancerTome
"necrogenie bob <m> <s> - 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 <r> <g> <b> - body colour";
"necrogenie tint <r> <g> <b> - body colour\n" +
"necrogenie arms <out> <fwd> <elbow> - arm pose, degrees: upper arm from vertical sideways and forward, elbow bend";
}
public override void Execute(List<string> _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);
}
}
}