Exemplo n.º 1
0
        public override bool Update(float deltaSeconds)
        {
            // If the missile has outlived its thing, delete it.
            lifetime -= deltaSeconds;
            if (lifetime < 0)
            {
                Runner.DelSimObject(this);
                return(false);
            }

            // ideas: have certain missiles acquire a new target from owner if it disappears? have certain missiles explode when lacking a target?
            if (seek && lifetime < munition_arch.Lifetime - 1)
            {
                SimObject target = Runner.FindObject(target_objid);
                if (target == null)
                {
                    target_objid    = 0;
                    target_subobjid = 0;
                    seek            = false;
                    if (broadcast)
                    {
                        Runner.NotifyOnSetTarget(Objid, 0, 0);
                        broadcast = false;
                    }
                }
                else if (target.Position.DistSqr(Position) > seeker_range * seeker_range)
                {
                    time_to_lock = munition_arch.TimeToLock;
                    if (broadcast)
                    {
                        Runner.NotifyOnSetTarget(Objid, 0, 0);
                        broadcast = false;
                    }
                }
                else
                {
                    Vector current_direction        = Orientation * -Vector.Z();
                    Vector current_target_vector    = target.ExtrapolatedPosition() - Position;
                    Vector current_target_direction = current_target_vector.Normalize();
                    double target_cosine            = current_target_direction.Dot(current_direction);
                    double solid_angle = 1 / Math.Sqrt(Math.Pow(target.Arch.Radius / current_target_vector.Length(), 2) + 1);

                    if (target_cosine < Math.Cos(seeker_fov / 2) - solid_angle)
                    {
                        time_to_lock = munition_arch.TimeToLock;
                        if (broadcast)
                        {
                            Runner.NotifyOnSetTarget(Objid, 0, 0);
                            broadcast = false;
                        }
                    }
                    else if (time_to_lock > 0)
                    {
                        time_to_lock -= deltaSeconds;
                    }
                    else
                    {
                        if (!broadcast)
                        {
                            Runner.NotifyOnSetTarget(Objid, target_objid, target_subobjid);
                            broadcast = true;
                        }

                        double max_cosine = Math.Cos(max_angular_velocity * deltaSeconds);
                        if (max_cosine < target_cosine)
                        {
                            Vector cross  = current_direction.Cross(current_target_direction);
                            Matrix rotate = Matrix.CreateRotationAboutAxis(cross, max_cosine);
                            Orientation *= rotate;
                            velocity     = rotate * velocity / 2 + velocity / 2; // need to ponder on this behavior
                        }
                        else
                        {
                            Orientation = Matrix.CreateLookAt(Position, target.ExtrapolatedPosition());
                            velocity    = current_target_direction * velocity.Length() / 2 + velocity / 2;
                        }
                    }
                }
            }

            // Calculate any velocity changes
            if (motor_delay > 0)
            {
                motor_delay -= deltaSeconds;
            }
            else if (motor_lifetime > 0)
            {
                var linear_acceleration = new Vector(0, 0, -(motor_accel * deltaSeconds));
                velocity       += Orientation * linear_acceleration;
                motor_lifetime -= deltaSeconds;
            }

            // Move the object
            Position   += velocity * deltaSeconds;
            UpdateTime += (float)deltaSeconds;
            Runner.NotifyOnObjUpdate(this);
            return(true);
        }