2022-08-08 22:43:55 +01:00
|
|
|
using System;
|
2026-08-10 14:57:50 +01:00
|
|
|
using System.Collections;
|
2022-08-08 22:43:55 +01:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using UnityEngine;
|
2026-08-10 14:57:50 +01:00
|
|
|
using UnityEngine.InputSystem;
|
2026-09-14 17:39:12 +02:00
|
|
|
using CultMath;
|
Convert engine types through CultMath.UnityBridge
CultMath has no implicit conversions to or from Vector*, Quaternion or
Color, so Assembly-CSharp converts explicitly with ToCultMath/ToUnity at
each engine boundary: FieldDriver, GuidedProjectile(Manager),
EntityInstance, ActionGameManager, HullCollider, GridObject, ShipInstance,
ShieldManager, ItemPickup, FieldTester, PlaceUIElementWorldspace,
MapMenuInput, MapRenderer, SectorRenderer and ZoneRenderer. CultMath math
calls that were handed Unity vectors now take converted values;
Vector3.Scale in FieldDriver becomes a float3 product, and ItemPickup's
Vector3.Dot on float3s becomes dot. packages-lock.json records the
cultmath git package at f0605367 and demotes com.unity.mathematics to a
transitive dependency.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:47:33 +02:00
|
|
|
using CultMath.UnityBridge;
|
2026-09-14 17:39:12 +02:00
|
|
|
using static CultMath.math;
|
2022-08-08 22:43:55 +01:00
|
|
|
|
2026-09-17 14:36:40 +02:00
|
|
|
// Implements the capability presenter interfaces (Assets/Scripts/Gameplay/CapabilityPresenters.cs) by
|
|
|
|
|
// delegating to its own pre-existing methods/fields; it decides nothing about capability rules,
|
|
|
|
|
// per docs/headless-playground-cut.md fork L. CapabilityPresentationBinder is what actually
|
|
|
|
|
// subscribes these methods to a CapabilityEvents source -- FieldDriver has no reference to one.
|
|
|
|
|
public class FieldDriver : MonoBehaviour, IAbsorbPresenter, IGrabPresenter, IMeleePresenter, IThrustPresenter
|
2022-08-08 22:43:55 +01:00
|
|
|
{
|
2025-01-30 01:58:05 +00:00
|
|
|
public Camera Camera;
|
2026-08-10 14:57:50 +01:00
|
|
|
public float2 Push;
|
2025-01-30 01:58:05 +00:00
|
|
|
public float FrontTwist;
|
|
|
|
|
public float RearTwist;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float TestMagnitude;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float FlowSpeed;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float FlowSpeedThrottleExponent;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2025-01-30 01:58:05 +00:00
|
|
|
public float WaveThrottleExponent;
|
|
|
|
|
|
2022-08-08 22:43:55 +01:00
|
|
|
public int MaxHits;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public ExponentialCurve MagnitudeTimeScaling;
|
2025-01-30 01:58:05 +00:00
|
|
|
|
Replace the Database Tools with the Studio and cut Unity over
Cut 8b. The Unity project compiles with 0 errors in 6000.3.24f1 batchmode.
Packages: manifest.json pins org.gamecult.cultlib at cultlib-unity-v1.0.57
and org.gamecult.caching.unity at caching-unity-v1.2.0, next to the 8a
CultMath tag. Aetheria.Shared.Unity references GameCult.CultLib and keeps
noEngineReferences.
The Database Tools (Assets/Scripts/CultCache/Editor) are deleted in this
commit, alongside their five ported drawers in
Assets/Scripts/Editor/CultCacheDrawers.cs, each an
[CultInspectorDrawer] ICultInspectorDrawer:
- InspectableType: popup of the attribute type's [Union] member names,
writing the string.
- InspectableColor: float3 and float4 through ColorField.
- InspectableAnimationCurve: float4[] and BezierCurve through CurveField.
- InspectableTemperature: Kelvin, Celsius and Fahrenheit fields over one
value.
- InspectableSchematicShape: size and cell toggles. The old drawer also
drew the item's schematic texture and tinted hull hardpoints, which need
the parent document. The tagged Studio hands a drawer only the value, so
those wait on the Studio exposing the open record.
Unity call sites:
- ActionGameManager opens the catalog through AetheriaStores; Cut 10 adds
the run and player stores.
- Refs resolve through ItemManager.GetData or Get(ref); orbit, planet and
belt maps key by CultRecordKey; identity is compared by reference or key.
- The PlayerSettings.msgpack reader and writer, which Cut 10 deletes, pass
CultDocumentMessagePackSerialization.OptionsFor, since the embedded run
reaches CultMath values and refs. Keyboard layouts need no resolver and
keep MessagePack's defaults until Cut 10.
- The input map uses the nested action to binding shape.
- PropertiesPanel reads CultInspectorRangeAttribute.
- NameTools loses its legacy name-file writer.
- Slime compares serialized settings instead of the deleted SHA1 helper.
- FieldDriver drops InspectorHeader.
- .gitignore covers the test project's build output.
Builds: Aetheria.Shared, AetherDb, Aetheria.Shared.Tests (6/6), Unity
batchmode (0 errors).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 19:15:20 +02:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeRange;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeRangeExponent;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeFlatness;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeShaping;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeDuration;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeAngle;
|
2026-08-10 14:57:50 +01:00
|
|
|
[Inspectable]
|
2022-08-08 22:43:55 +01:00
|
|
|
public float MeleeAngleExponent;
|
2025-01-30 01:58:05 +00:00
|
|
|
|
Replace the Database Tools with the Studio and cut Unity over
Cut 8b. The Unity project compiles with 0 errors in 6000.3.24f1 batchmode.
Packages: manifest.json pins org.gamecult.cultlib at cultlib-unity-v1.0.57
and org.gamecult.caching.unity at caching-unity-v1.2.0, next to the 8a
CultMath tag. Aetheria.Shared.Unity references GameCult.CultLib and keeps
noEngineReferences.
The Database Tools (Assets/Scripts/CultCache/Editor) are deleted in this
commit, alongside their five ported drawers in
Assets/Scripts/Editor/CultCacheDrawers.cs, each an
[CultInspectorDrawer] ICultInspectorDrawer:
- InspectableType: popup of the attribute type's [Union] member names,
writing the string.
- InspectableColor: float3 and float4 through ColorField.
- InspectableAnimationCurve: float4[] and BezierCurve through CurveField.
- InspectableTemperature: Kelvin, Celsius and Fahrenheit fields over one
value.
- InspectableSchematicShape: size and cell toggles. The old drawer also
drew the item's schematic texture and tinted hull hardpoints, which need
the parent document. The tagged Studio hands a drawer only the value, so
those wait on the Studio exposing the open record.
Unity call sites:
- ActionGameManager opens the catalog through AetheriaStores; Cut 10 adds
the run and player stores.
- Refs resolve through ItemManager.GetData or Get(ref); orbit, planet and
belt maps key by CultRecordKey; identity is compared by reference or key.
- The PlayerSettings.msgpack reader and writer, which Cut 10 deletes, pass
CultDocumentMessagePackSerialization.OptionsFor, since the embedded run
reaches CultMath values and refs. Keyboard layouts need no resolver and
keep MessagePack's defaults until Cut 10.
- The input map uses the nested action to binding shape.
- PropertiesPanel reads CultInspectorRangeAttribute.
- NameTools loses its legacy name-file writer.
- Slime compares serialized settings instead of the deleted SHA1 helper.
- FieldDriver drops InspectorHeader.
- .gitignore covers the test project's build output.
Builds: Aetheria.Shared, AetherDb, Aetheria.Shared.Tests (6/6), Unity
batchmode (0 errors).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 19:15:20 +02:00
|
|
|
[Inspectable]
|
2026-08-10 14:57:50 +01:00
|
|
|
public float TendrilBaseRadius = 3;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float TendrilTipRadius = .1f;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float TendrilExtensionExponent = .75f;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float TendrilExtendBaseAnimationExponent = .5f;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float TendrilBaseDamping = 2;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float TendrilTipRadiusAnimationExponent = 2f;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float TendrilFadeExponent = 2;
|
|
|
|
|
// [Inspectable]
|
|
|
|
|
// public float GrabScaleAnimationExponent = .5f;
|
|
|
|
|
|
Replace the Database Tools with the Studio and cut Unity over
Cut 8b. The Unity project compiles with 0 errors in 6000.3.24f1 batchmode.
Packages: manifest.json pins org.gamecult.cultlib at cultlib-unity-v1.0.57
and org.gamecult.caching.unity at caching-unity-v1.2.0, next to the 8a
CultMath tag. Aetheria.Shared.Unity references GameCult.CultLib and keeps
noEngineReferences.
The Database Tools (Assets/Scripts/CultCache/Editor) are deleted in this
commit, alongside their five ported drawers in
Assets/Scripts/Editor/CultCacheDrawers.cs, each an
[CultInspectorDrawer] ICultInspectorDrawer:
- InspectableType: popup of the attribute type's [Union] member names,
writing the string.
- InspectableColor: float3 and float4 through ColorField.
- InspectableAnimationCurve: float4[] and BezierCurve through CurveField.
- InspectableTemperature: Kelvin, Celsius and Fahrenheit fields over one
value.
- InspectableSchematicShape: size and cell toggles. The old drawer also
drew the item's schematic texture and tinted hull hardpoints, which need
the parent document. The tagged Studio hands a drawer only the value, so
those wait on the Studio exposing the open record.
Unity call sites:
- ActionGameManager opens the catalog through AetheriaStores; Cut 10 adds
the run and player stores.
- Refs resolve through ItemManager.GetData or Get(ref); orbit, planet and
belt maps key by CultRecordKey; identity is compared by reference or key.
- The PlayerSettings.msgpack reader and writer, which Cut 10 deletes, pass
CultDocumentMessagePackSerialization.OptionsFor, since the embedded run
reaches CultMath values and refs. Keyboard layouts need no resolver and
keep MessagePack's defaults until Cut 10.
- The input map uses the nested action to binding shape.
- PropertiesPanel reads CultInspectorRangeAttribute.
- NameTools loses its legacy name-file writer.
- Slime compares serialized settings instead of the deleted SHA1 helper.
- FieldDriver drops InspectorHeader.
- .gitignore covers the test project's build output.
Builds: Aetheria.Shared, AetherDb, Aetheria.Shared.Tests (6/6), Unity
batchmode (0 errors).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 19:15:20 +02:00
|
|
|
[Inspectable]
|
2026-08-10 14:57:50 +01:00
|
|
|
public float GrabExtendTime;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float GrabEnvelopTime;
|
|
|
|
|
[Inspectable]
|
|
|
|
|
public float GrabPullTime;
|
|
|
|
|
|
|
|
|
|
[Inspectable]
|
2025-01-30 01:58:05 +00:00
|
|
|
public RectTransform.Axis RefractionAxis = RectTransform.Axis.Horizontal;
|
2022-08-08 22:43:55 +01:00
|
|
|
|
|
|
|
|
private Material _field;
|
|
|
|
|
private ComputeBuffer _hitBuffer;
|
|
|
|
|
private List<FieldHit> _hits = new List<FieldHit>();
|
2025-01-30 01:58:05 +00:00
|
|
|
private float _waveOffset;
|
2022-08-08 22:43:55 +01:00
|
|
|
private float _meleeTime;
|
|
|
|
|
private bool _meleeActive;
|
2026-08-10 14:57:50 +01:00
|
|
|
private MeshCollider _collider;
|
|
|
|
|
private Transform _grabObject;
|
|
|
|
|
private Vector3 _grabObjectStartPos;
|
|
|
|
|
private Vector3 _grabObjectStartTendrilBasePos;
|
|
|
|
|
private Vector3 _grabObjectEndPos;
|
|
|
|
|
private Vector3 _grabObjectVelocity;
|
|
|
|
|
private float _grabObjectScale;
|
|
|
|
|
private float _grabTime;
|
2026-09-17 14:36:40 +02:00
|
|
|
private TendrilPhase _grabPhase;
|
2026-08-10 14:57:50 +01:00
|
|
|
private Vector3 _tendrilBasePos;
|
|
|
|
|
private Vector3 _tendrilBendTarget;
|
|
|
|
|
private Vector3 _tendrilTargetPos;
|
|
|
|
|
private float _fadePoint;
|
|
|
|
|
|
2026-09-17 14:36:40 +02:00
|
|
|
// Named distinctly from the global GrabPhase (CapabilityEvents.cs): this is FieldDriver's own
|
|
|
|
|
// internal tendril-animation timing, still owned here until a real pickup capability exists to
|
|
|
|
|
// publish per-phase GrabEvent transitions (see Grab(GrabEvent, Transform, Vector3) below).
|
|
|
|
|
private enum TendrilPhase
|
2026-08-10 14:57:50 +01:00
|
|
|
{
|
|
|
|
|
Extend,
|
|
|
|
|
Envelop,
|
|
|
|
|
Pull
|
|
|
|
|
}
|
2022-08-08 22:43:55 +01:00
|
|
|
|
|
|
|
|
private struct FieldHit
|
|
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
public float3 Position;
|
|
|
|
|
public float3 Direction;
|
2022-08-08 22:43:55 +01:00
|
|
|
public float Magnitude;
|
|
|
|
|
public float Time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Start()
|
|
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_collider = GetComponent<MeshCollider>();
|
2022-08-08 22:43:55 +01:00
|
|
|
_field = GetComponent<MeshRenderer>().material;
|
|
|
|
|
_hitBuffer = new ComputeBuffer(MaxHits, 32);
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
public void AddHit(float3 position, float3 direction, float magnitude)
|
2022-08-08 22:43:55 +01:00
|
|
|
{
|
|
|
|
|
if (_hits.Count >= MaxHits) return;
|
|
|
|
|
var hit = new FieldHit
|
|
|
|
|
{
|
Convert engine types through CultMath.UnityBridge
CultMath has no implicit conversions to or from Vector*, Quaternion or
Color, so Assembly-CSharp converts explicitly with ToCultMath/ToUnity at
each engine boundary: FieldDriver, GuidedProjectile(Manager),
EntityInstance, ActionGameManager, HullCollider, GridObject, ShipInstance,
ShieldManager, ItemPickup, FieldTester, PlaceUIElementWorldspace,
MapMenuInput, MapRenderer, SectorRenderer and ZoneRenderer. CultMath math
calls that were handed Unity vectors now take converted values;
Vector3.Scale in FieldDriver becomes a float3 product, and ItemPickup's
Vector3.Dot on float3s becomes dot. packages-lock.json records the
cultmath git package at f0605367 and demotes com.unity.mathematics to a
transitive dependency.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:47:33 +02:00
|
|
|
Position = normalize(transform.InverseTransformPoint(position.ToUnity()).ToCultMath()) * transform.localScale.ToCultMath(),
|
|
|
|
|
Direction = normalize((transform.rotation * direction.ToUnity()).ToCultMath()),
|
2022-08-08 22:43:55 +01:00
|
|
|
Magnitude = magnitude,
|
|
|
|
|
Time = 0
|
|
|
|
|
};
|
2025-01-30 01:58:05 +00:00
|
|
|
//Debug.Log($"Received hit: Position={hit.Position}, Direction={hit.Direction}");
|
2022-08-08 22:43:55 +01:00
|
|
|
_hits.Add(hit);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int HitCount => _hits.Count;
|
|
|
|
|
|
|
|
|
|
public void Melee()
|
|
|
|
|
{
|
|
|
|
|
_meleeActive = true;
|
|
|
|
|
_meleeTime = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
public bool CanGrab => _grabObject == null;
|
|
|
|
|
|
|
|
|
|
public void GrabObject(Transform t, Vector3 v)
|
|
|
|
|
{
|
2026-09-17 14:36:40 +02:00
|
|
|
_grabPhase = TendrilPhase.Extend;
|
2026-08-10 14:57:50 +01:00
|
|
|
_grabObject = t;
|
|
|
|
|
_grabObjectStartPos = t.position;
|
|
|
|
|
_grabObjectVelocity = v;
|
|
|
|
|
_grabObjectScale = t.localScale.x;
|
|
|
|
|
_tendrilBasePos = _grabObjectStartTendrilBasePos = _collider.ClosestPoint(_grabObjectStartPos);
|
|
|
|
|
_fadePoint = .999f;
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-17 14:36:40 +02:00
|
|
|
// IAbsorbPresenter: delegates straight to the existing hit-buffer mechanism. e.DamageType is not
|
|
|
|
|
// read -- the field shield has no per-damage-type visual today; it rides along in the event for
|
|
|
|
|
// presentations that do vary by type (the mask itself is absorb-capability data, out of scope here).
|
|
|
|
|
public void Absorb(AbsorbEvent e) => AddHit(e.Position, e.Direction, e.Magnitude);
|
|
|
|
|
|
|
|
|
|
// IGrabPresenter: only the Started phase does anything today. FieldDriver still times the
|
|
|
|
|
// extend/envelop/pull animation itself (TendrilPhase above, driven by GrabExtendTime/
|
|
|
|
|
// GrabEnvelopTime/GrabPullTime) because no capability yet publishes those phase transitions;
|
|
|
|
|
// once one does, this is where FieldDriver would react to Envelop/Pull/Completed/Cancelled too.
|
|
|
|
|
public void Grab(GrabEvent e, Transform target, Vector3 initialVelocity)
|
|
|
|
|
{
|
|
|
|
|
if (e.Phase == GrabPhase.Started && target != null)
|
|
|
|
|
GrabObject(target, initialVelocity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// IMeleePresenter: the field shield's swing shape comes from its own authored curves
|
|
|
|
|
// (MeleeRange/MeleeAngle/MeleeDuration/etc, tuned in the inspector), not from the event's
|
|
|
|
|
// direction/range/arc/duration -- those exist for presentations that do read them.
|
|
|
|
|
public void Melee(MeleeEvent e) => Melee();
|
|
|
|
|
|
|
|
|
|
// IThrustPresenter: Throttle is not read; pushMag is derived from PlanarThrust in Update() below,
|
|
|
|
|
// matching the field shield's existing behaviour.
|
|
|
|
|
public void Thrust(ThrustEvent e)
|
|
|
|
|
{
|
|
|
|
|
Push = e.PlanarThrust;
|
|
|
|
|
FrontTwist = e.Twist.x;
|
|
|
|
|
RearTwist = e.Twist.y;
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-08 22:43:55 +01:00
|
|
|
void Update()
|
|
|
|
|
{
|
2025-01-30 01:58:05 +00:00
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
var pushMag = min(length(Push), 1);
|
2025-01-30 01:58:05 +00:00
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
_waveOffset = frac(_waveOffset + Time.deltaTime * FlowSpeed * pow(max(pushMag, max(abs(FrontTwist), abs(RearTwist))), FlowSpeedThrottleExponent));
|
2025-01-30 01:58:05 +00:00
|
|
|
|
|
|
|
|
var refractionRotation = Matrix4x4.Rotate(Camera.transform.rotation).inverse;
|
|
|
|
|
if (RefractionAxis == RectTransform.Axis.Vertical) refractionRotation =
|
|
|
|
|
Matrix4x4.Rotate(Quaternion.Euler(90, 0, 0)) * refractionRotation;
|
|
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
_field.SetFloat("_WaveOffset", _waveOffset * PI * 2);
|
2025-01-30 01:58:05 +00:00
|
|
|
_field.SetFloat("_Push", pushMag);
|
|
|
|
|
_field.SetVector("_PushDirection", new Vector4(-Push.x, 0, -Push.y));
|
|
|
|
|
_field.SetFloat("_TwistFront", FrontTwist);
|
|
|
|
|
_field.SetFloat("_TwistRear", RearTwist);
|
|
|
|
|
|
|
|
|
|
_field.SetVector("_InverseScale", new Vector4(1/transform.localScale.x,1/transform.localScale.y,1/transform.localScale.z));
|
|
|
|
|
_field.SetMatrix("_ReflRotate", refractionRotation);
|
|
|
|
|
|
2022-08-08 22:43:55 +01:00
|
|
|
for (int i = 0; i < _hits.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var hit = _hits[i];
|
|
|
|
|
hit.Time += Time.deltaTime / MagnitudeTimeScaling.Evaluate(_hits[i].Magnitude);
|
|
|
|
|
_hits[i] = hit;
|
|
|
|
|
if (hit.Time > 1)
|
|
|
|
|
{
|
|
|
|
|
_hits.RemoveAt(i);
|
|
|
|
|
i--;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-30 01:58:05 +00:00
|
|
|
_hitBuffer.SetData(_hits);
|
|
|
|
|
_field.SetBuffer("_Hits", _hitBuffer);
|
|
|
|
|
_field.SetInt("_HitCount", _hits.Count);
|
2022-08-08 22:43:55 +01:00
|
|
|
|
|
|
|
|
if (_meleeActive)
|
|
|
|
|
{
|
|
|
|
|
_meleeTime += Time.deltaTime / MeleeDuration;
|
2025-01-30 01:58:05 +00:00
|
|
|
if (_meleeTime < 1)
|
|
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
_field.SetVector("_MeleeDirection", Quaternion.AngleAxis(sign(_meleeTime*2-1) * MeleeAngle * pow(abs(_meleeTime * 2 - 1), MeleeAngleExponent), Vector3.up) * -Vector3.forward);
|
|
|
|
|
_field.SetFloat("_MeleeDisplacement", pow(1 - 2 * abs(_meleeTime - .5f), MeleeRangeExponent) * MeleeRange);
|
2025-01-30 01:58:05 +00:00
|
|
|
_field.SetFloat("_MeleeShape", MeleeShaping);
|
|
|
|
|
_field.SetFloat("_MeleeFlattening", MeleeFlatness);
|
|
|
|
|
}
|
|
|
|
|
else
|
2022-08-08 22:43:55 +01:00
|
|
|
{
|
|
|
|
|
_meleeActive = false;
|
2025-01-30 01:58:05 +00:00
|
|
|
_field.SetFloat("_MeleeDisplacement", 0);
|
2022-08-08 22:43:55 +01:00
|
|
|
}
|
|
|
|
|
}
|
2026-08-10 14:57:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if(_grabObject != null)
|
|
|
|
|
{
|
|
|
|
|
_grabTime += Time.deltaTime / _grabPhase switch
|
|
|
|
|
{
|
2026-09-17 14:36:40 +02:00
|
|
|
TendrilPhase.Extend => GrabExtendTime,
|
|
|
|
|
TendrilPhase.Envelop => GrabEnvelopTime,
|
|
|
|
|
TendrilPhase.Pull => GrabPullTime,
|
2026-08-10 14:57:50 +01:00
|
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
|
|
|
};
|
|
|
|
|
if (_grabTime > 1)
|
|
|
|
|
{
|
|
|
|
|
_grabTime = 0;
|
2026-09-17 14:36:40 +02:00
|
|
|
if (_grabPhase == TendrilPhase.Envelop)
|
2026-08-10 14:57:50 +01:00
|
|
|
{
|
|
|
|
|
_grabObjectEndPos = _grabObject.position;
|
|
|
|
|
}
|
2026-09-17 14:36:40 +02:00
|
|
|
if (_grabPhase == TendrilPhase.Pull)
|
2026-08-10 14:57:50 +01:00
|
|
|
{
|
|
|
|
|
Destroy(_grabObject.gameObject);
|
|
|
|
|
_grabObject = null;
|
|
|
|
|
_field.SetFloat("_TendrilInfluence", 0);
|
|
|
|
|
}
|
|
|
|
|
else _grabPhase++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_grabObject != null)
|
|
|
|
|
{
|
Delete AetheriaMath in favour of CultMath
AetheriaMath predates the CultMath swap and re-implemented helpers CultMath
now owns. Callers use CultMath directly: decay (Ship, AetherDrive, Entity),
damp (VelocityConversion, FieldTester, FieldDriver), first_order_intercept
(TurretController, Combat, GuidedProjectile), quadratic_bezier (FieldDriver)
and smootherstep (Ship). Parameter order matches in every case, and those
formulas have the same float evaluation order, so behaviour is unchanged.
Galaxy's commented-out segment check names distance_to_segment.
The other overloads had no callers and are dropped without a CultMath
counterpart being needed: the double Damp overloads, FindDistanceToSegment,
GetCatmullRomPosition, GetCubicSplinePosition, Smoothstep(x), and the
Deg2Rad/Rad2Deg constants.
AetherDb census, factions and hardpoint-fit are byte-identical to the
pre-cut captures.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 18:02:41 +02:00
|
|
|
_tendrilBasePos = damp(_tendrilBasePos.ToCultMath(), _grabObject.position.ToCultMath(), TendrilBaseDamping, Time.deltaTime).ToUnity();
|
2026-08-10 14:57:50 +01:00
|
|
|
switch (_grabPhase)
|
|
|
|
|
{
|
2026-09-17 14:36:40 +02:00
|
|
|
case TendrilPhase.Extend:
|
2026-08-10 14:57:50 +01:00
|
|
|
_tendrilBendTarget = _grabObjectStartPos;
|
|
|
|
|
_grabObject.position += _grabObjectVelocity * Time.deltaTime;
|
|
|
|
|
_tendrilTargetPos = lerp(
|
Convert engine types through CultMath.UnityBridge
CultMath has no implicit conversions to or from Vector*, Quaternion or
Color, so Assembly-CSharp converts explicitly with ToCultMath/ToUnity at
each engine boundary: FieldDriver, GuidedProjectile(Manager),
EntityInstance, ActionGameManager, HullCollider, GridObject, ShipInstance,
ShieldManager, ItemPickup, FieldTester, PlaceUIElementWorldspace,
MapMenuInput, MapRenderer, SectorRenderer and ZoneRenderer. CultMath math
calls that were handed Unity vectors now take converted values;
Vector3.Scale in FieldDriver becomes a float3 product, and ItemPickup's
Vector3.Dot on float3s becomes dot. packages-lock.json records the
cultmath git package at f0605367 and demotes com.unity.mathematics to a
transitive dependency.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:47:33 +02:00
|
|
|
lerp(_grabObjectStartTendrilBasePos.ToCultMath(), _grabObjectStartPos.ToCultMath(), _grabTime),
|
|
|
|
|
lerp(_grabObjectStartPos.ToCultMath(), _grabObject.position.ToCultMath(), _grabTime),
|
|
|
|
|
pow(_grabTime, TendrilExtensionExponent)).ToUnity();
|
2026-08-10 14:57:50 +01:00
|
|
|
_field.SetFloat("_TendrilInfluence", pow(_grabTime, TendrilExtendBaseAnimationExponent));
|
|
|
|
|
_field.SetFloat("_TendrilSize", lerp(TendrilBaseRadius/2,TendrilBaseRadius,pow(_grabTime, TendrilExtendBaseAnimationExponent)));
|
|
|
|
|
_field.SetFloat("_TendrilRadius", _grabObjectScale * pow(_grabTime, TendrilTipRadiusAnimationExponent) * TendrilTipRadius);
|
|
|
|
|
break;
|
2026-09-17 14:36:40 +02:00
|
|
|
case TendrilPhase.Envelop:
|
2026-08-10 14:57:50 +01:00
|
|
|
_tendrilBendTarget = _grabObjectStartPos;
|
|
|
|
|
_tendrilTargetPos = _grabObject.position += _grabObjectVelocity * Time.deltaTime * (1-_grabTime);
|
|
|
|
|
_field.SetFloat("_TendrilInfluence", 1);
|
|
|
|
|
_field.SetFloat("_TendrilSize", TendrilBaseRadius);
|
|
|
|
|
_field.SetFloat("_TendrilRadius", _grabObjectScale * TendrilTipRadius);
|
|
|
|
|
break;
|
2026-09-17 14:36:40 +02:00
|
|
|
case TendrilPhase.Pull:
|
Convert engine types through CultMath.UnityBridge
CultMath has no implicit conversions to or from Vector*, Quaternion or
Color, so Assembly-CSharp converts explicitly with ToCultMath/ToUnity at
each engine boundary: FieldDriver, GuidedProjectile(Manager),
EntityInstance, ActionGameManager, HullCollider, GridObject, ShipInstance,
ShieldManager, ItemPickup, FieldTester, PlaceUIElementWorldspace,
MapMenuInput, MapRenderer, SectorRenderer and ZoneRenderer. CultMath math
calls that were handed Unity vectors now take converted values;
Vector3.Scale in FieldDriver becomes a float3 product, and ItemPickup's
Vector3.Dot on float3s becomes dot. packages-lock.json records the
cultmath git package at f0605367 and demotes com.unity.mathematics to a
transitive dependency.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 17:47:33 +02:00
|
|
|
_tendrilTargetPos = _grabObject.position = lerp(_grabObjectEndPos.ToCultMath(), transform.position.ToCultMath(), _grabTime*_grabTime).ToUnity();
|
|
|
|
|
_tendrilBendTarget = lerp(_grabObjectStartPos.ToCultMath(), _grabObjectEndPos.ToCultMath(), _grabTime*_grabTime).ToUnity();
|
2026-08-10 14:57:50 +01:00
|
|
|
if (_fadePoint > .99 && transform.InverseTransformPoint(_grabObject.position).sqrMagnitude < 1)
|
|
|
|
|
_fadePoint = _grabTime;
|
|
|
|
|
_field.SetFloat("_TendrilInfluence", pow(smoothstep(1, _fadePoint, _grabTime), TendrilFadeExponent));
|
|
|
|
|
_field.SetFloat("_TendrilSize", TendrilBaseRadius);
|
|
|
|
|
_field.SetFloat("_TendrilRadius", _grabObjectScale * TendrilTipRadius);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
}
|
|
|
|
|
_field.SetVector("_TendrilBase", Vector3.Scale(transform.InverseTransformPoint(_tendrilBasePos).normalized, transform.localScale));
|
|
|
|
|
_field.SetVector("_TendrilBend", Vector3.Scale(transform.InverseTransformPoint(_tendrilBendTarget), transform.localScale));
|
|
|
|
|
_field.SetVector("_TendrilTarget", Vector3.Scale(transform.InverseTransformPoint(_tendrilTargetPos), transform.localScale));
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-30 01:58:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private float almostIdentity( float x )
|
|
|
|
|
{
|
|
|
|
|
return x*x*(2.0f-x);
|
|
|
|
|
}
|
2022-08-08 22:43:55 +01:00
|
|
|
|
2025-01-30 01:58:05 +00:00
|
|
|
private float smooth(float t)
|
|
|
|
|
{
|
|
|
|
|
return t * t * (3.0f - 2.0f * t);
|
|
|
|
|
}
|
2022-08-08 22:43:55 +01:00
|
|
|
|
2026-08-10 14:57:50 +01:00
|
|
|
private const int GIZMO_STEPS = 16;
|
|
|
|
|
private void OnDrawGizmosSelected()
|
2025-01-30 01:58:05 +00:00
|
|
|
{
|
2026-08-10 14:57:50 +01:00
|
|
|
if (_grabObject != null)
|
|
|
|
|
{
|
|
|
|
|
Vector3 previous = _tendrilBasePos;
|
|
|
|
|
for (int i = 1; i <= GIZMO_STEPS; i++)
|
|
|
|
|
{
|
|
|
|
|
var l = (float)i / GIZMO_STEPS;
|
Delete AetheriaMath in favour of CultMath
AetheriaMath predates the CultMath swap and re-implemented helpers CultMath
now owns. Callers use CultMath directly: decay (Ship, AetherDrive, Entity),
damp (VelocityConversion, FieldTester, FieldDriver), first_order_intercept
(TurretController, Combat, GuidedProjectile), quadratic_bezier (FieldDriver)
and smootherstep (Ship). Parameter order matches in every case, and those
formulas have the same float evaluation order, so behaviour is unchanged.
Galaxy's commented-out segment check names distance_to_segment.
The other overloads had no callers and are dropped without a CultMath
counterpart being needed: the double Damp overloads, FindDistanceToSegment,
GetCatmullRomPosition, GetCubicSplinePosition, Smoothstep(x), and the
Deg2Rad/Rad2Deg constants.
AetherDb census, factions and hardpoint-fit are byte-identical to the
pre-cut captures.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 18:02:41 +02:00
|
|
|
var next = quadratic_bezier(_tendrilBasePos.ToCultMath(), _tendrilBendTarget.ToCultMath(), _tendrilTargetPos.ToCultMath(), l).ToUnity();
|
2026-08-10 14:57:50 +01:00
|
|
|
Gizmos.DrawLine(previous, next);
|
|
|
|
|
previous = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-30 01:58:05 +00:00
|
|
|
}
|
2022-08-08 22:43:55 +01:00
|
|
|
|
2025-01-30 01:58:05 +00:00
|
|
|
private void OnDestroy()
|
|
|
|
|
{
|
|
|
|
|
_hitBuffer.Dispose();
|
2022-08-08 22:43:55 +01:00
|
|
|
}
|
|
|
|
|
}
|