Aetheria/Assets/Scripts/Gameplay/MineInstance.cs
Meta Vens be7f2b0787 Layers: one owner puts orbitals above the ship plane and floaters below; per-hull GridOffset is deleted
GameplaySettings carries ShipLayerHeight 3, OrbitalLayerHeight 15, FloaterLayerHeight 0 (authored in Settings.asset).
Entity.LayerHeight (Ship, OrbitalEntity) is the one offset RideHeight adds; DrawAhead.FloaterHeight is the floater
height ItemPickup and MineInstance draw at. HullData.GridOffset (Key 26) and the pickup/mine/prefab GridOffset fields
are gone with every reader. Fixtures (DrawnPose, FireControl*, ImpactFeedback) take heights from the layer owner;
LayerTests pin each kind's layer. FloatingItemsDrawnSmoke follows. ItemPickup/MineInstance.Bind take the settings from
ZoneRenderer. Builds as one commit with its tests; not compile-verified until the cut's head run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 02:35:07 +02:00

76 lines
2.8 KiB
C#

using CultMath;
using CultMath.UnityBridge;
using UnityEngine;
using static CultMath.math;
using Random = UnityEngine.Random;
// How one laid mine looks. Zone owns the mine's every fact (position, arming, trigger, end); this reads them and
// draws, and writes nothing back. The pose is the latest sim body, spun for show; the pulse runs in real time
// (rulings unity-presents-only-r3 and sim-speed-presentation).
public class MineInstance : MonoBehaviour
{
public MeshRenderer MeshRenderer;
public int EmissionSubmesh = 2;
public AnimationCurve EmissionCurve;
public float ActiveCycleDuration = 1f;
public float ArmedCycleDuration = .25f;
public float ActiveEmission = 100f;
public float ArmedEmission = 1000f;
public float RotationSpeed = 1f;
// The blast's particles; the effect prefab destroys itself when its particle system stops.
public GameObject HitEffect;
public float HitEffectScale = 10f;
private Zone _zone;
private GameplaySettings _settings;
private Mine _mine;
private Material _material;
private float _timeOffset;
private float _pulse;
private float _emission;
public void Bind(Zone zone, Mine mine, GameplaySettings settings)
{
_zone = zone;
_settings = settings;
_mine = mine;
_material = MeshRenderer.materials[EmissionSubmesh];
_timeOffset = Random.value * 100;
Place();
}
private void Update()
{
Place();
transform.localRotation = Quaternion.Euler(
sin(Time.time - _timeOffset * RotationSpeed) * 90, 0, cos(Time.time - _timeOffset * RotationSpeed) * 90);
// None before the mine arms, then slow while it waits and fast once its fuse is lit.
var armed = _mine.Armed(_zone.Time);
var counting = _mine.TriggeredAt != null;
var target = !armed ? 0f : counting ? ArmedEmission : ActiveEmission;
_emission = lerp(_emission, target, Time.deltaTime * 10);
_pulse = (_pulse + Time.deltaTime / (counting ? ArmedCycleDuration : ActiveCycleDuration)) % 1;
_material.SetFloat("_Emission", _emission * EmissionCurve.Evaluate(_pulse));
}
private void Place()
{
var lead = ActionGameManager.Clock.Lead;
var p = DrawAhead.Position(_mine.Body, lead);
transform.position = new Vector3(p.x, DrawAhead.FloaterHeight(_zone, _settings, p, lead), p.y);
}
// The mine left Zone.Mines, which only its blast does: show it where it was drawn last.
public void Blast()
{
var effect = Instantiate(HitEffect, transform.position, Quaternion.identity);
effect.transform.localScale = Vector3.one * HitEffectScale;
Destroy(gameObject);
}
private void OnDestroy()
{
if (_material) Destroy(_material);
}
}