Ejemplo n.º 1
0
        /// <summary>
        /// Trains a unit
        /// </summary>
        /// <param name="uid">The UID to build</param>
        /// <returns>The built unit</returns>
        public Unit TrainUnit(string uid)
        {
            Unit trained = UnitType.CreateUnit(uid, Position + Vector2.Transform(new Vector2(0f, 4f * Type.SelectionCircleSize), Matrix.CreateRotationZ(MathHelper.ToRadians(League.Random.Next(0, 360)))), Owner);

            if (RallyPoint != null && trained.Type.Moves)
            {
                // We have a rally point, so we might as well use it
                trained.State = UnitState.Moving;
                Engine.CurrentMap.FindPath(trained, Engine.CurrentMap.GetNode(RallyPoint ?? Vector2.Zero));
            }
            return(trained);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Updates the component - calculates pathing maps, moves, attacks, casts abilities,
        /// builds, trains
        /// </summary>
        /// <param name="gameTime">A snapshot of game timing values</param>
        public override void Update(GameTime gameTime)
        {
            float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;

            // Update times for everything
            AttackCooldown -= elapsed;

            if (CastTime != null)
            {
                CastTime -= elapsed;
            }

            string[] keys = new string[AbilityCooldown.Count];
            AbilityCooldown.Keys.CopyTo(keys, 0);
            for (int i = 0; i < AbilityCooldown.Count; i++)
            {
                AbilityCooldown[keys[i]] -= elapsed;
                if (AbilityCooldown[keys[i]] < 0)
                {
                    AbilityCooldown.Remove(keys[i]);
                }
            }

            if (TargetUnit != null && !Engine.Units.Contains(TargetUnit))
            {
                // The target unit is dead
                TargetUnit     = null;
                CastingAbility = null;
                Path           = null;
                State         &= ~(UnitState.Attacking | UnitState.Moving | UnitState.Casting);
            }

            if (CurrentlyBuilding)
            {
                // This is an incomplete building and should continue to build
                BuildTime += elapsed;
                Hp         = (int)(BuildTime / Type.BuildTime * Type.Hp);

                if (BuildTime >= Type.BuildTime)
                {
                    // The building is complete!
                    CurrentlyBuilding = false;
                    Builder.State    &= ~UnitState.Building;
                    Builder           = null;

                    if (Player.CurrentPlayer.Selected.Count != 0 && Player.CurrentPlayer.Selected[0] == this)
                    {
                        // If this is the selected object, refresh actions
                        Player.CurrentPlayer.RefreshActions();
                    }
                }
            }

            if (Hp <= 0 && !(CurrentlyBuilding && BuildTime < 0.5f))
            {
                // Time to DIE
                Die();

                return;
            }


            if (QueuedBuilding != null)
            {
                // There is a building to build
                if ((Position - TargetPoint).Length() <= 8 * UnitType.GetUnitType(QueuedBuilding).SelectionCircleSize)
                {
                    // We are in range to build it
                    if (Owner.MatchesResources(UnitType.GetUnitType(QueuedBuilding).Costs))
                    {
                        // We are able to build it
                        Path = null;
                        Unit u = UnitType.CreateUnit(QueuedBuilding, TargetPoint, Owner);
                        u.CurrentlyBuilding = true;
                        u.Builder           = this;
                        Owner.ChargeResources(u.Type.Costs);
                        QueuedBuilding = null;
                        State          = UnitState.Building;
                    }
                    else
                    {
                        // We can't build it :(
                        QueuedBuilding = null;
                        Path           = null;
                    }
                }
                else if (Path == null)
                {
                    // We are not moving but need to get to the build site
                    State = UnitState.Moving;
                    Engine.CurrentMap.FindPath(this, Engine.CurrentMap.GetNode(TargetPoint));
                }
            }

            if (CastingAbility == null)
            {
                if (TargetUnit != null && TargetUnit != this)
                {
                    // We have a target and it's not us and it's not an Ability target
                    if ((TargetUnit.Position - Position).Length() < Type.AttackRange)
                    {
                        // We're in range!
                        if (AttackCooldown <= 0)
                        {
                            DoAttack();
                        }
                    }
                    else if (Path == null)
                    {
                        // We're not in range so let's get there
                        Engine.CurrentMap.FindPath(this, Engine.CurrentMap.GetNode(TargetUnit.Position));
                        State = UnitState.Moving;
                    }
                }
            }
            else
            {
                // There's magic to be done
                if (!(TargetUnit == null && TargetPoint == Vector2.Zero) && Path == null && CastTime == null)
                {
                    // And we need to get there
                    Engine.CurrentMap.FindPath(this, Engine.CurrentMap.GetNode((CastingAbility.Target.Type == TargetType.Point ? TargetPoint : TargetUnit.Position)));
                    State = UnitState.Moving;
                }

                if ((TargetUnit == null && TargetPoint == Vector2.Zero) || (Position - (CastingAbility.Target.Type == TargetType.Point ? TargetPoint : TargetUnit.Position)).Length() <= CastingAbility.CastRange)
                {
                    // We're in range or there's no Target
                    if (CastTime == null)
                    {
                        // And we haven't started casting
                        CastTime = CastingAbility.CastTime;
                        // Start casting ;)
                        Path = null;
                    }
                    else if (CastTime <= 0)
                    {
                        if (TargetUnit == null && TargetPoint == Vector2.Zero)
                        {
                            // Cast against nothing
                            CastingAbility.Invoke(this, null);
                        }
                        else
                        {
                            // Cast against our target
                            CastingAbility.Invoke(this, (CastingAbility.Target.Type == TargetType.Point ? (object)TargetPoint : (object)TargetUnit));
                        }
                    }
                }
            }

            if (Path != null)
            {
                lock (Path) {
                    // Move along our path
                    Vector3 pos      = Engine.CurrentMap.GetNodePosition(Path[Node].X, Path[Node].Y);
                    Vector2 intended = new Vector2(pos.X, pos.Z);
                    Vector2 dif      = intended - Position;
                    float   angle    = (float)(Math.Atan2(-dif.Y, dif.X) + MathHelper.PiOver2);
                    if (Rotation.Yaw < angle)
                    {
                        Rotation.Yaw += elapsed * Type.TurnSpeed;
                    }
                    else if (Rotation.Yaw > angle)
                    {
                        Rotation.Yaw -= elapsed * Type.TurnSpeed;
                    }
                    float xdir = Math.Sign(dif.X);
                    float ydir = Math.Sign(dif.Y);
                    Position.X += Type.Speed * elapsed * xdir;
                    Position.Y += Type.Speed * elapsed * ydir;

                    if (TargetUnit != null)
                    {
                        if ((TargetUnit.Position - Position).Length() < Type.AttackRange)
                        {
                            // Our target is in range!
                            Path  = null;
                            State = UnitState.Attacking;
                            return;
                        }
                    }

                    if (Math.Abs(dif.X) < Type.Speed * elapsed * 2 && Math.Abs(dif.Y) < Type.Speed * elapsed * 2)
                    {
                        // We're through this node - on to the next!
                        Node++;
                        if (Node == Path.Count && State != UnitState.Patrolling)
                        {
                            Path = null;
                        }
                        else if (State == UnitState.Patrolling)
                        {
                            // If we're patrolling, repeat the path over and over
                            List <Point> newpath = new List <Point>();
                            for (int i = 1; i <= Path.Count; i++)
                            {
                                newpath.Add(Path[Path.Count - i]);
                            }
                            Path = newpath;
                            Node = 0;
                        }
                    }
                }
            }
            else if (Type.Attacks && TargetUnit == null && !CurrentlyBuilding)
            {
                foreach (Unit u in Engine.Units)
                {
                    if (u.Owner != Owner && (Position - u.Position).Length() <= Type.AttackEngage && u.Owner != Player.NeutralPlayer)
                    {
                        // We can attack and there are enemy units nearby
                        TargetUnit = u;
                    }
                }
            }

            if (Training.Count != 0)
            {
                // We're training units
                TrainTime -= elapsed;

                if (TrainTime <= 0f)
                {
                    // Training is complete, let's pop one out
                    TrainUnit(Training.Dequeue());
                    if (Training.Count != 0)
                    {
                        TrainTime = UnitType.GetUnitType(Training.Peek()).BuildTime;
                    }
                }
            }

            base.Update(gameTime);
        }