MIRV Missiles!
Implemented missiles that turn into more missiles Guided projectile code is much more robust now
This commit is contained in:
parent
922c8ea460
commit
6130eca5f9
15 changed files with 20347 additions and 245 deletions
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue