Aetheria/Assets/Scripts/Gameplay/MineInstance.cs

74 lines
2.6 KiB
C#
Raw Normal View History

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;
public float GridOffset;
// 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 Mine _mine;
private Material _material;
private float _timeOffset;
private float _pulse;
private float _emission;
public void Bind(Zone zone, Mine mine)
{
_zone = zone;
_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 p = _mine.Body.Position;
transform.position = new Vector3(p.x, _zone.GetHeight(p) + GridOffset, 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);
}
}