public override bool Execute(float dt)
    {
        if (Entity.Target.Value != null)
        {
            var diff = Entity.Target.Value.Position - Entity.Position;
            if (_predictShots)
            {
                var targetHullData    = Entity.ItemManager.GetData(Entity.Target.Value.Hull) as HullData;
                var targetVelocity    = float3(Entity.Target.Value.Velocity.x, 0, Entity.Target.Value.Velocity.y);
                var predictedPosition = AetheriaMath.FirstOrderIntercept(
                    Entity.Position, float3.zero, _shotSpeed,
                    Entity.Target.Value.Position, targetVelocity
                    );
                predictedPosition.y  = Entity.Zone.GetHeight(predictedPosition.xz) + targetHullData.GridOffset;
                Entity.LookDirection = normalize(predictedPosition - Entity.Position);
            }
            else
            {
                Entity.LookDirection = normalize(diff);
            }
            var dist = length(diff);

            foreach (var x in _weapons)
            {
                var data = x.Data as WeaponData;
                var fire = dot(
                    x.Direction,
                    Entity.LookDirection) > .99f;
                if (x.Evaluate(data.Range) > dist && fire)
                {
                    x.Activate();
                }
                else if (x.Firing)
                {
                    x.Deactivate();
                }
            }
        }
        else
        {
            foreach (var x in _weapons)
            {
                if (x.Firing)
                {
                    x.Deactivate();
                }
            }
            Entity.Target.Value = Entity.VisibleEnemies.FirstOrDefault(e => e is Ship);
        }
        return(true);
    }
    void Update()
    {
        if (SourceEntity == null)
        {
            return;
        }

        var t = transform;

        if (_active)
        {
            if (TargetPosition == null && !Target)
            {
                StartCoroutine(FadeOut());
                return;
            }
            var position = (float3)t.position;

            var targetPosition = TargetPosition?.Invoke() ?? Target.position;
            _targetVelocity         = lerp(_targetVelocity, targetPosition - _previousTargetPosition, saturate(Time.deltaTime * 5));
            _previousTargetPosition = targetPosition;
            targetPosition          = AetheriaMath.FirstOrderIntercept(position, float3.zero, TopSpeed, targetPosition, _targetVelocity);

            var diff       = targetPosition - transform.position;
            var targetDist = diff.magnitude;
            var sourceDist = length(StartPosition.xz - position.xz);

            if (sourceDist > Range || dot(diff, Velocity) < 0)
            {
                StartCoroutine(FadeOut());
                if (HitEffect != null)
                {
                    var ht = HitEffect.Instantiate <Transform>();
                    ht.position = t.position;
                }
                return;
            }
            _prevDist = 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.transform.position = t.position;
                    child.StartPosition      = StartPosition;
                    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 / Children;
                    child.Penetration   = Penetration;
                    child.Spread        = Spread;
                    child.DamageType    = DamageType;
                    child.Source        = Source;
                    child.Target        = Target;
                    child.SourceEntity  = SourceEntity;
                    child.GuidanceCurve = GuidanceCurve;
                    child.LiftCurve     = LiftCurve;
                    child.ThrustCurve   = ThrustCurve;
                    child.Thrust        = Thrust;
                    child.TopSpeed      = TopSpeed;
                    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 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);
        }

        if (_alive)
        {
            var ray = new Ray(t.position, Velocity);
            foreach (var hit in Physics.RaycastAll(ray, Velocity.magnitude * Time.deltaTime, 1 | (1 << 17)))
            {
                var shield = hit.collider.GetComponent <ShieldManager>();
                if (shield)
                {
                    if (!(shield.Entity.Shield != null && shield.Entity.Shield.Item.Active.Value && shield.Entity.Shield.CanTakeHit(DamageType, Damage)))
                    {
                        continue;
                    }
                    if (shield.Entity != SourceEntity)
                    {
                        shield.Entity.Shield.TakeHit(DamageType, Damage);
                        shield.ShowHit(hit.point, sqrt(Damage));
                    }
                }
                var hull = hit.collider.GetComponent <HullCollider>();
                if (hull && !(hull.Entity.Shield != null && hull.Entity.Shield.Item.Active.Value && hull.Entity.Shield.CanTakeHit(DamageType, Damage)))
                {
                    if (hull.Entity != SourceEntity)
                    {
                        hull.SendHit(Damage, Penetration, Spread, DamageType, SourceEntity, hit.textureCoord, transform.forward);
                        transform.position = hit.point;
                        StartCoroutine(Kill());
                    }
                }
                else// if (hit.transform.gameObject.layer == 1)
                {
                    StartCoroutine(Kill());
                    return;
                }

                if (HitEffect != null)
                {
                    var ht = HitEffect.Instantiate <Transform>();
                    ht.SetParent(hit.collider.transform);
                    ht.position = hit.point;
                    return;
                }
            }

            t.position += Velocity * Time.deltaTime;
        }
    }
示例#3
0
 public override bool Execute(float dt)
 {
     Entity.Velocity = AetheriaMath.Damp(Entity.Velocity, Entity.Direction * length(Entity.Velocity), Evaluate(_data.Lambda), dt);
     return(true);
 }
示例#4
0
    public override void Update(float delta)
    {
        if (_active && !_exitingWormhole && !_enteringWormhole)
        {
            RecalculateThrust();
            foreach (var thruster in _allThrusters)
            {
                thruster.Axis = 0;
            }
            var rightThrusterTorqueCompensation = abs(RightStrafeTotalTorque) / RightStrafeTorqueThrusters.Count;
            foreach (var thruster in _rightThrusters)
            {
                var thrust = 0f;
                thrust += MovementDirection.x;
                if (RightStrafeTorqueThrusters.Contains(thruster))
                {
                    thrust -= MovementDirection.x * (rightThrusterTorqueCompensation / (abs(thruster.Torque) * thruster.Thrust));
                }
                thruster.Axis = thrust;
            }
            var leftThrusterTorqueCompensation = abs(LeftStrafeTotalTorque) / LeftStrafeTorqueThrusters.Count;
            foreach (var thruster in _leftThrusters)
            {
                var thrust = 0f;
                thrust += -MovementDirection.x;
                if (LeftStrafeTorqueThrusters.Contains(thruster))
                {
                    thrust += MovementDirection.x * (leftThrusterTorqueCompensation / (abs(thruster.Torque) * thruster.Thrust));
                }
                thruster.Axis = thrust;
            }
            foreach (var thruster in _forwardThrusters)
            {
                thruster.Axis += MovementDirection.y;
            }
            foreach (var thruster in _reverseThrusters)
            {
                thruster.Axis += -MovementDirection.y;
            }

            var look     = normalize(LookDirection.xz);
            var deltaRot = dot(look, normalize(Direction).Rotate(ItemRotation.Clockwise));
            if (abs(deltaRot) < .01f)
            {
                deltaRot  = 0;
                Direction = lerp(Direction, look, min(delta, 1));
            }
            deltaRot = pow(abs(deltaRot), .5f) * sign(deltaRot);

            foreach (var thruster in _clockwiseThrusters)
            {
                thruster.Axis += deltaRot;
            }
            foreach (var thruster in _counterClockwiseThrusters)
            {
                thruster.Axis += -deltaRot;
            }

            foreach (var drive in _aetherDrives)
            {
                drive.Axis = float3(MovementDirection.y, MovementDirection.x, deltaRot);
            }
        }

        var velocityMagnitude = length(Velocity);

        if (velocityMagnitude > .01f)
        {
            Velocity = normalize(Velocity) * AetheriaMath.Decay(velocityMagnitude, HullData.Drag, delta);
        }

        Position.xz += Velocity * delta;

        var normal         = Zone.GetNormal(Position.xz);
        var force          = new float2(normal.x, normal.z);
        var forceMagnitude = lengthsq(force);

        if (forceMagnitude > .001f)
        {
            var fa = 1 / (1 - forceMagnitude) - 1;
            Velocity += normalize(force) * Zone.Settings.GravityStrength * fa;
        }
        var shipRight = Direction.Rotate(ItemRotation.Clockwise);
        var forward   = cross(float3(shipRight.x, 0, shipRight.y), normal);

        Rotation = quaternion.LookRotation(forward, normal);

        base.Update(delta);

        if (_exitingWormhole)
        {
            _wormholeAnimationProgress += delta / ItemManager.GameplaySettings.WormholeAnimationDuration;
            if (_wormholeAnimationProgress < 1)
            {
                if (_wormholeAnimationProgress < ItemManager.GameplaySettings.WormholeExitCurveStart)
                {
                    Position.xz = _wormholePosition;
                    Rotation    = quaternion.LookRotation(float3(0, 1, 0), float3(-Direction.x, 0, -Direction.y));
                }
                else
                {
                    var exitLerp = (_wormholeAnimationProgress - ItemManager.GameplaySettings.WormholeExitCurveStart) /
                                   (1 - ItemManager.GameplaySettings.WormholeExitCurveStart);
                    exitLerp    = AetheriaMath.Smootherstep(exitLerp); // Square the interpolation variable to produce curve with zero slope at start
                    Position.xz = _wormholePosition + normalize(_wormholeExitVelocity) * exitLerp * ItemManager.GameplaySettings.WormholeExitRadius;
                    Rotation    = quaternion.LookRotation(
                        lerp(float3(0, 1, 0), forward, exitLerp),
                        lerp(float3(-Direction.x, 0, -Direction.y), normal, exitLerp));
                }

                Position.y = Position.y - lerp(ItemManager.GameplaySettings.WormholeDepth, 0, _wormholeAnimationProgress);
            }
            else
            {
                _exitingWormhole = false;
                OnExitedWormhole?.Invoke();
                OnExitedWormhole = null;
                Velocity         = _wormholeExitVelocity;
            }
        }

        if (_enteringWormhole)
        {
            _wormholeAnimationProgress += delta / ItemManager.GameplaySettings.WormholeAnimationDuration;
            if (_wormholeAnimationProgress < 1)
            {
                if (_wormholeAnimationProgress < 1 - ItemManager.GameplaySettings.WormholeExitCurveStart)
                {
                    var enterLerp = _wormholeAnimationProgress / (1 - ItemManager.GameplaySettings.WormholeExitCurveStart);
                    enterLerp   = AetheriaMath.Smootherstep(enterLerp); // Square the interpolation variable to produce curve with zero slope at vertical
                    Position.xz = lerp(_wormholeEntryPosition, _wormholePosition, enterLerp);
                    Rotation    = quaternion.LookRotation(
                        lerp(forward, float3(0, -1, 0), enterLerp),
                        lerp(normal, float3(-_wormholeEntryDirection.x, 0, -_wormholeEntryDirection.y), enterLerp));
                }
                else
                {
                    Position.xz = _wormholePosition;
                    Rotation    = quaternion.LookRotation(float3(0, -1, 0),
                                                          float3(-_wormholeEntryDirection.x, 0, -_wormholeEntryDirection.y));
                }

                Position.y = Position.y - lerp(0, ItemManager.GameplaySettings.WormholeDepth, _wormholeAnimationProgress);
            }
            else
            {
                _enteringWormhole = false;
                OnEnteredWormhole?.Invoke();
                OnEnteredWormhole = null;
            }
        }
    }