Ejemplo n.º 1
0
        public override void Tick(double Delta)
        {
            if (!Active)
            {
                return;
            }

            isLeader = Unit == null || Unit.Formation == null || this == Unit.Leader;

            if (!isLeader)
            {
                leader    = Unit.Leader;
                Stance    = leader.Stance;
                Objective = leader.Objective;
                Goal      = leader.Goal;
                Behavior  = leader.Behavior;
            }

            if (isLeader || Behavior == Behaviors.Attacking)
            {
                if (Behavior == Behaviors.Idle)
                {
                    Throttle = 0;
                    if (Velocity.Length() > 0)
                    {
                        Velocity = Velocity.Length() * 0.95f * Vector2.Normalize(Velocity);
                    }
                    AngularAcceleration = 0;

                    if (Shield <= 0 && RNG.Next(100 * 60) < ShieldRebootProbability)
                    {
                        Shield += 1;
                    }

                    if (Stance == Stances.Defend)
                    {
                        if (CombatRange <= 0)
                        {
                            CombatRange = MathF.Min(Texture.Texture.width, Texture.Texture.height) * 10;
                        }

                        if (Hardpoints == null) // If I've got hardpoints, let them deal with it.
                        {
                            SpaceObject[] nearTargets = GetTargets(Location, CombatRange);
                            if (nearTargets.Length > 0)
                            {
                                if (RandomOffset >= nearTargets.Length || RandomOffset < 0 || RNG.NextDouble() < 0.001)
                                {
                                    RandomOffset = RandomOffset = (int)Math.Floor(RNG.NextDouble() * nearTargets.Length);
                                }

                                Objective = nearTargets[RandomOffset];

                                float distance = Vector2.Distance(Objective.Location, Location);
                                if (RNG.Next(100) <= 200 / distance)
                                {
                                    attackOffset = new Vector2(RNG.Next((int)(distance / 50)) - RNG.Next((int)(distance / 50)), RNG.Next((int)(distance / 50)) - RNG.Next((int)(distance / 50)));
                                }
                                Goal = (Objective as SpaceShip).GetLead(1 + distance / 50) + attackOffset;

                                double angleOffset = (AngleToPoint(this.Location, Goal) - Angle) + 90;
                                if (angleOffset > 180)
                                {
                                    angleOffset -= 360;
                                }
                                if (angleOffset < -180)
                                {
                                    angleOffset += 360;
                                }

                                if (angleOffset > 1)
                                {
                                    AngularAcceleration = TurnSpeed * Delta;
                                }
                                else if (angleOffset < -1)
                                {
                                    AngularAcceleration = -TurnSpeed * Delta;
                                }
                                else
                                {
                                    AngularAcceleration = TurnSpeed * Math.Abs(Math.Pow(angleOffset, 2)) * angleOffset * Delta;
                                    if (shotCooldown <= 0)
                                    {
                                        Shoot();
                                    }
                                }
                            }
                        }
                    }
                }
                else if (Behavior == Behaviors.Attacking)
                {
                    if (Objective == this || Objective.Active == false)
                    {
                        Behavior = Behaviors.Idle;
                    }

                    float distance = Vector2.Distance(Objective.Location, Location);
                    if (RNG.Next(100) <= 200 / distance)
                    {
                        attackOffset = new Vector2(RNG.Next((int)(distance / 50)) - RNG.Next((int)(distance / 50)), RNG.Next((int)(distance / 50)) - RNG.Next((int)(distance / 50)));
                    }

                    if (Objective is SpaceShip)
                    {
                        Goal = (Objective as SpaceShip).GetLead(1 + distance / 50) + attackOffset;
                    }
                    else
                    {
                        Goal = Objective.Location + attackOffset;
                    }

                    double angleOffset = (AngleToPoint(this.Location, Goal) - Angle) + 90;
                    if (angleOffset > 180)
                    {
                        angleOffset -= 360;
                    }
                    if (angleOffset < -180)
                    {
                        angleOffset += 360;
                    }

                    if (angleOffset > 1)
                    {
                        AngularAcceleration = TurnSpeed * Delta;
                    }
                    else if (angleOffset < -1)
                    {
                        AngularAcceleration = -TurnSpeed * Delta;
                    }
                    else
                    {
                        AngularAcceleration = TurnSpeed * Math.Abs(Math.Pow(angleOffset, 2)) * angleOffset * Delta;
                        if (shotCooldown <= 0 && distance < CombatRange)
                        {
                            Shoot();
                        }
                    }

                    Throttle = Math.Pow(Math.Clamp((180 - angleOffset) / 180, 0.0, 1.0), 2);
                }
                else if (Behavior == Behaviors.Going)
                {
                    Vector2 goal = Goal;

                    /*if (Unit != null && Unit.Formation != null && this != Unit.Units[0])
                     * {
                     *  goal = Unit.Formation.GetLocation(this, Texture.Texture.width * 0.5f);
                     * }*/

                    double angleOffset = (AngleToPoint(this.Location, goal) - Angle) + 90;
                    if (angleOffset > 180)
                    {
                        angleOffset -= 360;
                    }
                    if (angleOffset < -180)
                    {
                        angleOffset += 360;
                    }

                    if (angleOffset > 1)
                    {
                        AngularAcceleration = TurnSpeed * Delta;
                    }
                    else if (angleOffset < -1)
                    {
                        AngularAcceleration = -TurnSpeed * Delta;
                    }
                    else
                    {
                        AngularAcceleration = TurnSpeed * Math.Abs(Math.Pow(angleOffset, 2)) * angleOffset * Delta;
                    }

                    Throttle = Math.Pow(Math.Clamp((180 - angleOffset) / 180, 0.0, 1.0), 2);

                    if (Vector2.Distance(Location, goal) < Velocity.Length() * 60 * 10)
                    {
                        if (Vector2.Distance(Location, goal) < Texture.Texture.height)
                        {
                            Behavior = Behaviors.Idle;
                        }
                        else
                        {
                            Throttle *= (Vector2.Distance(Location, goal) / ((Velocity.Length() * 120) + 1)) * 0.75;
                        }
                    }

                    if (Stance == Stances.Defend)
                    {
                        if (CombatRange <= 0)
                        {
                            CombatRange = MathF.Min(Texture.Texture.width, Texture.Texture.height) * 10;
                        }

                        if (Hardpoints == null) // If I've got hardpoints, let them deal with it.
                        {
                            SpaceObject[] nearTargets = GetTargets(Location, MathF.Sqrt(Velocity.Length()) * 0.75f * CombatRange);
                            if (nearTargets.Length > 0)
                            {
                                if (RandomOffset >= nearTargets.Length || RandomOffset < 0 || RNG.NextDouble() < 0.001)
                                {
                                    RandomOffset = RandomOffset = (int)Math.Floor(RNG.NextDouble() * nearTargets.Length);
                                }

                                float distance = Vector2.Distance(nearTargets[RandomOffset].Location, Location);
                                if (RNG.Next(100) <= 200 / distance)
                                {
                                    attackOffset = new Vector2(RNG.Next((int)(distance / 50)) - RNG.Next((int)(distance / 50)), RNG.Next((int)(distance / 50)) - RNG.Next((int)(distance / 50)));
                                }
                                Vector2 incidentalGoal = (nearTargets[RandomOffset] as SpaceShip).GetLead(1 + distance / 50) + attackOffset;

                                angleOffset = (AngleToPoint(this.Location, incidentalGoal) - Angle) + 90;
                                if (angleOffset > 180)
                                {
                                    angleOffset -= 360;
                                }
                                if (angleOffset < -180)
                                {
                                    angleOffset += 360;
                                }

                                if (Math.Abs(angleOffset) < 5)
                                {
                                    //AngularAcceleration = TurnSpeed * Math.Abs(Math.Pow(angleOffset, 2)) * angleOffset * Delta;
                                    if (shotCooldown <= 0)
                                    {
                                        Shoot();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                Vector2 goal           = Unit.Formation.GetLocation(this, Texture.Texture.width * 0.5f);
                Vector2 screenGoal     = UiManager.WorldToScreen(goal);
                Vector2 screenLocation = UiManager.WorldToScreen(Location);
                Debug.DrawLine((int)screenGoal.X, (int)screenGoal.Y, (int)screenLocation.X, (int)screenLocation.Y, new Color(255, 255, 255, 64));

                if (Vector2.Distance(Location, goal) > Texture.Texture.width)
                {
                    double angleOffset = (AngleToPoint(this.Location, goal) - Angle) + 90;
                    if (angleOffset > 180)
                    {
                        angleOffset -= 360;
                    }
                    if (angleOffset < -180)
                    {
                        angleOffset += 360;
                    }

                    if (angleOffset > 1)
                    {
                        AngularAcceleration = TurnSpeed * Delta;
                    }
                    else if (angleOffset < -1)
                    {
                        AngularAcceleration = -TurnSpeed * Delta;
                    }
                    else
                    {
                        AngularAcceleration = TurnSpeed * Math.Abs(Math.Pow(angleOffset, 2)) * angleOffset * Delta;
                    }

                    Throttle = Math.Pow(Math.Clamp((180 - angleOffset) / 180, 0.0, 1.0), 2);

                    if (Vector2.Distance(Location, goal) < Velocity.Length() * 60 * 10)
                    {
                        Throttle *= (Vector2.Distance(Location, goal) / ((Velocity.Length() * 120) + 1)) * 0.75;
                    }

                    //if (Behavior == Behaviors.Idle)
                    //{ Throttle = Throttle * 0.1; }
                }
                else
                {
                    Throttle = 0;
                }
            }

            double  radians = (Angle - 90) * (Math.PI / 180);
            Vector2 thrust  = new Vector2((float)Math.Cos(radians), (float)Math.Sin(radians));

            thrust       = thrust * (float)(MaxThrust * Throttle);
            Acceleration = thrust * (float)Delta / (float)Mass;

            // Nudge away from other ships
            SpaceObject[] neighbors = GetNeighbors(Location, Texture.Texture.width);
            if (neighbors.Length > 0)
            {
                for (int i = 0; i < neighbors.Length; i++)
                {
                    Vector2 nudge = Location - neighbors[i].Location;
                    nudge = (Vector2.Normalize(nudge) * (Velocity.Length() + 0.1f)) / (Vector2.Distance(neighbors[i].Location, Location) * 2.0f + 0.001f);
                    //nudge += new Vector2((float)RNG.NextDouble(), (float)RNG.NextDouble()) / (Vector2.Distance(neighbors[i].Location, Location) + 0.1f) ;
                    Acceleration += nudge / (float)Mass;
                }
            }

            /*
             * if (!isLeader)
             * {
             *  Vector2 nudge = Unit.Formation.GetLocation(this, Texture.Texture.width * 0.5f);
             *  nudge = nudge - Location;
             *  if (nudge.X != 0 || nudge.Y != 0)
             *  {
             *      if (nudge.Length() < Texture.Texture.width)
             *      {
             *          double angleOffset = leader.Angle - Angle;
             *          if (angleOffset > 180) { angleOffset -= 360; }
             *          if (angleOffset < -180) { angleOffset += 360; }
             *
             *          if (angleOffset > 1) { AngularAcceleration = TurnSpeed * Delta; }
             *          else if (angleOffset < -1) { AngularAcceleration = -TurnSpeed * Delta; }
             *          else
             *          {
             *              AngularAcceleration += TurnSpeed * Math.Pow(angleOffset, 5) * 0.1f;
             *          }
             *      }
             *      if (false)//Behavior == Behaviors.Idle)
             *      {
             *          nudge = Vector2.Normalize(nudge) * 0.01f;
             *      }
             *      else
             *      {
             *          nudge = Vector2.Normalize(nudge) * (Velocity.Length() * 0.1f + 1f) * 0.1f;
             *      }
             *
             *      Velocity += (nudge * 1f) / (float)Mass;
             *  }
             * }*/

            if (shotCooldown > 0)
            {
                shotCooldown -= 1 * Delta * (RNG.NextDouble() + RNG.NextDouble() + RNG.NextDouble());
            }
            if (shotHeat > 0)
            {
                shotHeat -= 0.1 * Delta;
            }

            if (Shield > 0 && Shield < MaxShield)
            {
                Shield += ShieldRegen;
            }

            base.Tick(Delta);
        }