MIRV Missiles!

Implemented missiles that turn into more missiles
Guided projectile code is much more robust now
This commit is contained in:
Reinier Vens 2021-01-28 02:42:39 +00:00
commit 6130eca5f9
15 changed files with 20347 additions and 245 deletions

View file

@ -10,6 +10,12 @@ using static Noise1D;
public class GuidedProjectile : MonoBehaviour
{
public Prototype HitEffect;
public Prototype ChildProjectile;
public int Children;
public float SplitTime;
public float SplitSeparationForwardness;
public float SplitSeparationVelocity;
public ParticleSystem Particles;
public float FadeOutTime;
public AnimationCurve ThrustCurve;
@ -25,7 +31,10 @@ public class GuidedProjectile : MonoBehaviour
private float _prevDist;
private bool _active;
private bool _alive;
private List<GuidedProjectile> _children = new List<GuidedProjectile>();
public float3 StartPosition { get; set; }
public float Range { get; set; }
public Vector3 Velocity { get; set; }
public float Damage { get; set; }
public float Penetration { get; set; }
@ -33,10 +42,6 @@ public class GuidedProjectile : MonoBehaviour
public DamageType DamageType { get; set; }
public Entity SourceEntity { get; set; }
void Awake()
{
}
void OnEnable()
{
_active = _alive = true;
@ -65,39 +70,97 @@ public class GuidedProjectile : MonoBehaviour
}
var diff = Target.position - transform.position;
var targetDist = diff.Flatland().magnitude;
if (_prevDist < targetDist)
var targetDist = diff.magnitude;
var position = (float3) t.position;
var sourceDist = length(StartPosition.xz - position.xz);
if (sourceDist > Range || _prevDist < targetDist)
{
StartCoroutine(FadeOut());
if (HitEffect != null)
{
var ht = HitEffect.Instantiate<Transform>();
ht.position = t.position;
}
return;
}
_prevDist = targetDist;
var position = (float3) t.position;
var sourceDist = length(((float3) Source.position).xz - position.xz);
var curveLerp = 1 - targetDist / (sourceDist + targetDist);
var targetDistFlat = diff.Flatland().magnitude;
var curveLerp = 1 - targetDistFlat / (sourceDist + targetDistFlat);
var dir = diff.normalized;
var right = cross(dir, float3(0, 1, 0));
var up = cross(dir, right);
if (Children > 0 && SplitTime < curveLerp)
{
for (int i = 0; i < Children; i++)
{
var child = ChildProjectile.Instantiate<GuidedProjectile>();
child.StartPosition = child.transform.position = t.position;
_children.Add(child);
var randomDirection = normalize(Random.insideUnitCircle);
var perpendicularRandom = randomDirection.x * right + randomDirection.y * up;
child.Velocity = normalize(lerp(perpendicularRandom, dir, SplitSeparationForwardness)) * length(Velocity) * SplitSeparationVelocity;
child.Range = Range;
child.Damage = Damage;
child.Penetration = Penetration;
child.Spread = Spread;
child.DamageType = DamageType;
child.GuidanceCurve = GuidanceCurve;
child.LiftCurve = LiftCurve;
child.ThrustCurve = ThrustCurve;
child.Thrust = Thrust;
child.TopSpeed = TopSpeed;
child.Source = Source;
child.Target = Target;
child.SourceEntity = SourceEntity;
child.Frequency = Frequency;
child.Thrust = Thrust;
}
StartCoroutine(Kill());
if (HitEffect != null)
{
var ht = HitEffect.Instantiate<Transform>();
ht.position = t.position;
}
}
var dodge = normalize(lerp(
normalize(right * noise(Time.time * Frequency + _phase) + up * noise(Time.time * Frequency + (100 + _phase))),
Vector3.up, LiftCurve.Evaluate(curveLerp)));
var desired = Vector3.Slerp(dodge, dir, GuidanceCurve.Evaluate(curveLerp)).normalized * TopSpeed;
var thrust = Thrust * ThrustCurve.Evaluate(curveLerp);
Velocity += (desired-Velocity) * (thrust * Time.deltaTime);
var thrustCurve = ThrustCurve.Evaluate(curveLerp);
var thrust = Thrust * thrustCurve;
var c = Color.white * thrustCurve;
c.a = 1;
Particles.startColor = c;
Velocity += (desired-Velocity).normalized * (thrust * Time.deltaTime);
}
var ray = new Ray(t.position, Velocity);
if (Physics.Raycast(ray, out var hit, Velocity.magnitude * Time.deltaTime, 1))
if(_alive)
{
var hull = hit.collider.GetComponent<HullCollider>();
if (hull)
var ray = new Ray(t.position, Velocity);
if (Physics.Raycast(ray, out var hit, Velocity.magnitude * Time.deltaTime, 1))
{
hull.SendHit(Damage, Penetration, Spread, DamageType, SourceEntity, hit, Velocity.normalized);
var hull = hit.collider.GetComponent<HullCollider>();
if (hull)
{
hull.SendHit(Damage, Penetration, Spread, DamageType, SourceEntity, hit, Velocity.normalized);
}
StartCoroutine(Kill());
if (HitEffect != null)
{
var ht = HitEffect.Instantiate<Transform>();
ht.SetParent(hit.collider.transform);
ht.position = hit.point;
return;
}
}
StartCoroutine(Kill());
t.position += Velocity * Time.deltaTime;
}
t.position += Velocity * Time.deltaTime;
}
IEnumerator FadeOut()
@ -107,7 +170,9 @@ public class GuidedProjectile : MonoBehaviour
while (Time.time - startTime < FadeOutTime)
{
var lerp = 1 - (Time.time - startTime) / FadeOutTime;
Particles.startColor = Color.white * lerp;
var c = Color.white * lerp;
c.a = 1;
Particles.startColor = c;
//var main = Particles.main;
//main.startColor = new ParticleSystem.MinMaxGradient { mode = ParticleSystemGradientMode.Color, color = Color.white * lerp };
yield return null;
@ -118,12 +183,21 @@ public class GuidedProjectile : MonoBehaviour
IEnumerator Kill()
{
_active = false;
_alive = false;
Particles.Stop(true, ParticleSystemStopBehavior.StopEmitting);
var startTime = Time.time;
var lifetime = Particles.main.startLifetime.constant;
while (Time.time - startTime < lifetime)
while (Time.time - startTime < lifetime || _children.Count > 0)
{
for (var index = 0; index < _children.Count; index++)
{
if (!_children[index].gameObject.activeSelf)
_children.RemoveAt(index--);
}
yield return null;
}
GetComponent<Prototype>().ReturnToPool();
}
}

View file

@ -18,7 +18,8 @@ public class GuidedProjectileManager : InstantWeaponEffectManager
p.Thrust = source.Entity.ItemManager.Evaluate(launcher.Thrust, item.EquippableItem, source.Entity);
var hp = source.Entity.Hardpoints[item.Position.x, item.Position.y];
var barrel = source.GetBarrel(hp);
p.transform.position = barrel.position;
p.StartPosition = p.transform.position = barrel.position;
p.Range = source.Entity.ItemManager.Evaluate(data.Range, item.EquippableItem, source.Entity);
p.Velocity = barrel.forward * source.Entity.ItemManager.Evaluate(launcher.LaunchSpeed, item.EquippableItem, source.Entity);
p.Damage = source.Entity.ItemManager.Evaluate(data.Damage, item.EquippableItem, source.Entity);
p.Penetration = source.Entity.ItemManager.Evaluate(data.Penetration, item.EquippableItem, source.Entity);

View file

@ -289,18 +289,21 @@ public class InventoryPanel : MonoBehaviour
_firstRect = cell.GetComponent<RectTransform>();
if (!thermal)
{
cell.PointerClickTrigger.OnPointerClickAsObservable()
.Subscribe(data => _onClick?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.BeginDragTrigger.OnBeginDragAsObservable()
.Subscribe(data => _onBeginDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.DragTrigger.OnDragAsObservable()
.Subscribe(data => _onDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.EndDragTrigger.OnEndDragAsObservable()
.Subscribe(data => _onEndDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerEnterTrigger.OnPointerEnterAsObservable()
.Subscribe(data => _onPointerEnter?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerExitTrigger.OnPointerExitAsObservable()
.Subscribe(data => _onPointerExit?.OnNext(new InventoryEntityEventData(data, v, entity)));
if(cell.PointerClickTrigger)
{
cell.PointerClickTrigger.OnPointerClickAsObservable()
.Subscribe(data => _onClick?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.BeginDragTrigger.OnBeginDragAsObservable()
.Subscribe(data => _onBeginDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.DragTrigger.OnDragAsObservable()
.Subscribe(data => _onDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.EndDragTrigger.OnEndDragAsObservable()
.Subscribe(data => _onEndDrag?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerEnterTrigger.OnPointerEnterAsObservable()
.Subscribe(data => _onPointerEnter?.OnNext(new InventoryEntityEventData(data, v, entity)));
cell.PointerExitTrigger.OnPointerExitAsObservable()
.Subscribe(data => _onPointerExit?.OnNext(new InventoryEntityEventData(data, v, entity)));
}
}
else
{