Нити цинерария: нож «хватом для нитей» (R), нити урна-ящик как у стриппера, урна-логист перевозит по образцу, зелёные глазницы
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
fad57a3756
commit
d8e7c8c66a
@@ -227,15 +227,22 @@ namespace NecromancerTome
|
||||
float _yaw;
|
||||
float _phase;
|
||||
/// <summary>Полёт к месту работы и обратно (16.10: «возвращается задом», «делал действие не сразу, а хоть руками
|
||||
/// пошевелив»): туда - лицом к месту, над местом - жест руками (дело делается в его середине, см. ActDelay),
|
||||
/// пошевелив»): туда - лицом к месту, над местом - жест руками (дело делается в его середине, см. Visit),
|
||||
/// обратно - развернувшись лицом к урне. Точка - в координатах модели урны; _t - время с начала полёта, -1 - дома.</summary>
|
||||
Vector3 _visit;
|
||||
struct Stop
|
||||
{
|
||||
public Vector3 Hover, Look; // в осях модели урны
|
||||
public float Fly;
|
||||
}
|
||||
|
||||
readonly List<Stop> _stops = new List<Stop>();
|
||||
float _backFly;
|
||||
float _t = -1f;
|
||||
/// <summary>Скорость полёта, м/с: время перелёта - не меньше OutSeconds/BackSeconds, дальше - по расстоянию (нити до 15 м).</summary>
|
||||
public static float FlySpeed = 4f;
|
||||
public static float OutSeconds = 1.3f;
|
||||
public static float WorkSeconds = 1.6f;
|
||||
public static float BackSeconds = 1.3f;
|
||||
/// <summary>Через сколько после начала полёта дело выполняется - в середине жеста.</summary>
|
||||
public static float ActDelay => OutSeconds + WorkSeconds * 0.5f;
|
||||
/// <summary>Жест: плечи вперёд до GestureFwd градусов, локти ходят на ±GestureWave вразнобой.</summary>
|
||||
public static float GestureFwd = 55f;
|
||||
public static float GestureWave = 30f;
|
||||
@@ -309,21 +316,63 @@ namespace NecromancerTome
|
||||
/// <summary>Светящиеся материалы рендереров - вернуть после почернения.</summary>
|
||||
readonly Dictionary<Renderer, Material[]> _glowing = new Dictionary<Renderer, Material[]>();
|
||||
|
||||
/// <summary>Куда смотреть за работой (в координатах модели урны); _beside - дух стоит сбоку от места, а не над ним.</summary>
|
||||
Vector3 _look;
|
||||
bool _beside;
|
||||
|
||||
/// <summary>Точки - в координатах сцены (без Origin): _stand - где встать (низ клетки), _look - низ клетки места работы.</summary>
|
||||
public void Visit(Vector3 _stand, Vector3 _lookAt, bool _besideIt)
|
||||
/// <summary>Облёт мест работы по порядку (у перевозки по нити - ящик «откуда», потом «куда»), у каждого - жест, затем
|
||||
/// назад к урне. Точки - в координатах сцены (без Origin): stand - где встать (низ клетки), look - низ клетки места,
|
||||
/// beside - встал сбоку, а не над местом. Возвращает, через сколько секунд дело (середина последнего жеста).</summary>
|
||||
public float Visit(List<(Vector3 stand, Vector3 look, bool beside)> _list)
|
||||
{
|
||||
if (transform.parent == null)
|
||||
if (transform.parent == null || _list == null || _list.Count == 0)
|
||||
{
|
||||
return;
|
||||
return 0f;
|
||||
}
|
||||
_visit = transform.parent.InverseTransformPoint(_stand);
|
||||
_look = transform.parent.InverseTransformPoint(_lookAt);
|
||||
_beside = _besideIt;
|
||||
_stops.Clear();
|
||||
Vector3 home = Home();
|
||||
Vector3 prev = home;
|
||||
float delay = 0f;
|
||||
foreach ((Vector3 stand, Vector3 look, bool beside) in _list)
|
||||
{
|
||||
Stop st = new Stop
|
||||
{
|
||||
Hover = transform.parent.InverseTransformPoint(stand) + new Vector3(0f, CinerariumGenie.OffsetY + (beside ? 0.15f : 0.8f), 0f),
|
||||
Look = transform.parent.InverseTransformPoint(look)
|
||||
};
|
||||
st.Fly = Mathf.Max(OutSeconds, Vector3.Distance(prev, st.Hover) / FlySpeed);
|
||||
delay += st.Fly + WorkSeconds;
|
||||
prev = st.Hover;
|
||||
_stops.Add(st);
|
||||
}
|
||||
_backFly = Mathf.Max(BackSeconds, Vector3.Distance(prev, home) / FlySpeed);
|
||||
_t = 0f;
|
||||
return delay - WorkSeconds * 0.5f;
|
||||
}
|
||||
|
||||
Vector3 Home()
|
||||
{
|
||||
return new Vector3(0f, CinerariumGenie.OffsetY, 0f) + Quaternion.Euler(0f, _yaw, 0f) * new Vector3(0f, 0f, CinerariumGenie.Forward);
|
||||
}
|
||||
|
||||
/// <summary>Повернуться лицом по направлению _dir (горизонтально), не быстрее 300°/с.</summary>
|
||||
void Face(Vector3 _dir)
|
||||
{
|
||||
if (_dir.x * _dir.x + _dir.z * _dir.z > 0.01f)
|
||||
{
|
||||
_yaw = Mathf.MoveTowardsAngle(_yaw, Mathf.Atan2(_dir.x, _dir.z) * Mathf.Rad2Deg, 300f * Time.deltaTime) % 360f;
|
||||
}
|
||||
}
|
||||
|
||||
void Gesture(float _w)
|
||||
{
|
||||
if (_w > 0f)
|
||||
{
|
||||
float wave = Mathf.Sin(_t * Mathf.PI * 2f * 1.5f) * GestureWave * _w;
|
||||
Pose(Mathf.Lerp(CinerariumGenie.ArmFwd, GestureFwd, _w), CinerariumGenie.Elbow + 15f * _w + wave, CinerariumGenie.Elbow + 15f * _w - wave);
|
||||
_gesturing = true;
|
||||
}
|
||||
else if (_gesturing)
|
||||
{
|
||||
Pose();
|
||||
_gesturing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetStuck(bool _on)
|
||||
@@ -379,58 +428,44 @@ namespace NecromancerTome
|
||||
return; // замер как был
|
||||
}
|
||||
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 (_t >= 0f)
|
||||
Vector3 home = Home();
|
||||
if (_t >= 0f && _stops.Count > 0)
|
||||
{
|
||||
_t += Time.deltaTime;
|
||||
if (_t < OutSeconds + WorkSeconds + BackSeconds)
|
||||
float acc = 0f;
|
||||
Vector3 from = home;
|
||||
foreach (Stop st in _stops)
|
||||
{
|
||||
// Сбоку - на уровне места (тело вровень со станцией), над местом - выше него.
|
||||
Vector3 over = _visit + new Vector3(0f, CinerariumGenie.OffsetY + (_beside ? 0.15f : 0.8f), 0f) + Quaternion.Euler(0f, _yaw, 0f) * new Vector3(0f, 0f, CinerariumGenie.Forward);
|
||||
Vector3 d = _visit - new Vector3(0f, CinerariumGenie.OffsetY, 0f);
|
||||
bool far = d.x * d.x + d.z * d.z > 0.01f;
|
||||
float toPlace = far ? Mathf.Atan2(d.x, d.z) * Mathf.Rad2Deg : _yaw;
|
||||
Vector3 dl = _look - _visit;
|
||||
float toLook = dl.x * dl.x + dl.z * dl.z > 0.01f ? Mathf.Atan2(dl.x, dl.z) * Mathf.Rad2Deg : toPlace;
|
||||
float k, face, w = 0f;
|
||||
if (_t < OutSeconds)
|
||||
if (_t < acc + st.Fly)
|
||||
{
|
||||
k = Mathf.SmoothStep(0f, 1f, _t / OutSeconds);
|
||||
face = toPlace;
|
||||
transform.localPosition = Vector3.Lerp(from, st.Hover, Mathf.SmoothStep(0f, 1f, (_t - acc) / st.Fly));
|
||||
Face(st.Hover - from);
|
||||
Gesture(0f);
|
||||
transform.localRotation = Quaternion.Euler(0f, _yaw, 0f);
|
||||
return;
|
||||
}
|
||||
else if (_t < OutSeconds + WorkSeconds)
|
||||
acc += st.Fly;
|
||||
if (_t < acc + WorkSeconds)
|
||||
{
|
||||
k = 1f;
|
||||
face = toLook; // за работой - лицом к станции
|
||||
w = Mathf.Sin((_t - OutSeconds) / WorkSeconds * Mathf.PI);
|
||||
transform.localPosition = st.Hover;
|
||||
Face(st.Look - st.Hover); // за работой - лицом к месту
|
||||
Gesture(Mathf.Sin((_t - acc) / WorkSeconds * Mathf.PI));
|
||||
transform.localRotation = Quaternion.Euler(0f, _yaw, 0f);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
k = 1f - Mathf.SmoothStep(0f, 1f, (_t - OutSeconds - WorkSeconds) / BackSeconds);
|
||||
face = far ? toPlace + 180f : _yaw; // назад - лицом к урне
|
||||
}
|
||||
_yaw = Mathf.MoveTowardsAngle(_yaw, face, 300f * Time.deltaTime) % 360f;
|
||||
transform.localPosition = Vector3.Lerp(home, over, k);
|
||||
acc += WorkSeconds;
|
||||
from = st.Hover;
|
||||
}
|
||||
if (_t < acc + _backFly)
|
||||
{
|
||||
transform.localPosition = Vector3.Lerp(from, home, Mathf.SmoothStep(0f, 1f, (_t - acc) / _backFly));
|
||||
Face(home - from); // назад - лицом к урне
|
||||
Gesture(0f);
|
||||
transform.localRotation = Quaternion.Euler(0f, _yaw, 0f);
|
||||
if (w > 0f)
|
||||
{
|
||||
float wave = Mathf.Sin(_t * Mathf.PI * 2f * 1.5f) * GestureWave * w;
|
||||
Pose(Mathf.Lerp(CinerariumGenie.ArmFwd, GestureFwd, w), CinerariumGenie.Elbow + 15f * w + wave, CinerariumGenie.Elbow + 15f * w - wave);
|
||||
_gesturing = true;
|
||||
}
|
||||
else if (_gesturing)
|
||||
{
|
||||
Pose();
|
||||
_gesturing = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
_t = -1f;
|
||||
if (_gesturing)
|
||||
{
|
||||
Pose();
|
||||
_gesturing = false;
|
||||
}
|
||||
Gesture(0f);
|
||||
}
|
||||
_yaw = yawTarget % 360f;
|
||||
float bob = CinerariumGenie.BobPeriod > 0.01f
|
||||
|
||||
Reference in New Issue
Block a user