Example #1
0
        public void UpdateProjectiles(GameRoom room, GameRound round)
        {
            foreach (var tower in room.Towers.Values)
            {
                if (tower.Damage > 0 && tower.ReadyAt <= DateTime.UtcNow)
                {
                    foreach (Mob mob in round.Mobs)
                    {
                        if (Point.IsNear(tower.Location, mob.CurrentLocation, tower.Range))
                        {
                            round.Projectiles.Add(new Projectile(tower, mob));
                            tower.ReadyAt = DateTime.UtcNow.AddMilliseconds(tower.Speed); // TODO: Should have a Game constant scale modifier here
                            break;
                        }
                    }
                }
            }

            foreach (Projectile projectile in round.Projectiles.Reverse())
            {
                var span = DateTime.UtcNow.Subtract(projectile.LastUpdated);
                projectile.Location = Point.TrackTo(projectile.Location, projectile.Target.CurrentLocation, (span.Milliseconds * (projectile.Speed / Constants.GameSpeed)));
                if (Point.IsNear(projectile.Location, projectile.Target.CurrentLocation, 0.1))  // projectile.Location.X == projectile.Target.CurrentLocation)
                {
                    TowerType towerType;
                    switch (projectile.TowerType)
                    {
                    case Constants.TowerList.Slowing:
                        towerType = GameDataUtils.GetTowerTypeFromTowerList(projectile.TowerType);
                        projectile.Target.Status.slow           = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(towerType.Effects.slow));
                        projectile.Target.Status.slow.remaining = DateTime.UtcNow.AddMilliseconds((int)towerType.Effects.slow.duration);
                        break;

                    case Constants.TowerList.Dot:
                        towerType = GameDataUtils.GetTowerTypeFromTowerList(projectile.TowerType);
                        projectile.Target.Status.dot = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(towerType.Effects.dot));
                        if (!((projectile.Target.Status.dot as IDictionary <string, object>)?.ContainsKey("lastUpdated") ?? false))
                        {
                            projectile.Target.Status.dot.lastUpdated = DateTime.UtcNow;
                        }
                        projectile.Target.Status.dot.remaining = DateTime.UtcNow.AddMilliseconds((int)towerType.Effects.dot.duration);
                        break;

                    default:
                        // No-op
                        break;
                    }

                    var abilities = projectile.Target.Type.Abilities;
                    var damage    = projectile.Damage;

                    // Stoneskin game mechanic
                    if (abilities?.Stoneskin.HasValue == true)
                    {
                        damage -= abilities.Stoneskin.Value;
                    }

                    // Evasion game mechanic
                    if (abilities?.Evasion.HasValue == true)
                    {
                        var roll = random.Value.Next(100);
                        if (roll < abilities.Evasion.Value)
                        {
                            damage = 0;
                        }
                    }

                    projectile.Target.Health -= Math.Max(damage, 0);
                    round.Projectiles.Remove(projectile);

                    if (projectile.Target.Health <= 0)
                    {
                        // Fracture game mechanic
                        if (abilities?.Fracture != null)
                        {
                            for (var i = 0; i < abilities.Fracture.Count; i++)
                            {
                                round.Mobs.Add(new Mob()
                                {
                                    Type            = projectile.Target.Type.Abilities.Fracture.Shard,
                                    CurrentLocation = new Point(projectile.Target.CurrentLocation),
                                    EndingLocation  = new Point(projectile.Target.EndingLocation),
                                    Health          = projectile.Target.Type.Abilities.Fracture.Shard.StartingHealth,
                                    CurrentSpeed    = projectile.Target.Type.Abilities.Fracture.Shard.MoveSpeed
                                });
                            }
                        }

                        // Avenger game mechanic
                        if (abilities?.Avenger != null)
                        {
                            var range = projectile.Target.Type.Abilities.Avenger.Range;
                            foreach (var mob in round.Mobs.Reverse())
                            {
                                if (Point.IsNear(projectile.Target.CurrentLocation, mob.CurrentLocation, range))
                                {
                                    mob.CurrentSpeed *= (1 + projectile.Target.Type.Abilities.Avenger.Bonus);
                                }
                            }
                        }

                        round.Mobs.Remove(projectile.Target);
                    }
                }

                projectile.LastUpdated = DateTime.UtcNow;
            }
        }