void UpdateStructures(double dt) { Match.Structures.ForEach(s => { s.Update(TimeSpan.FromSeconds(dt)); if (s.GetHealthChangedAndClearFlag()) // the health of the structure changed { Console.WriteLine(s.Team + " " + s.Type + " - " + s.Health + " / " + s.MaxHealth); AddRemarkableEvent(ServerCommand.StructureStatsChanged, (msg) => { bool left = s.Team == Teams.Left; byte type = (byte)s.Type; float health = s.Health; msg.Write(left); msg.Write(type); msg.Write(health); }); if (!s.Alive) // the structure is destroyed { AddRemarkableEvent(ServerCommand.StructureDestroyed, (msg) => { bool left = s.Team == Teams.Left; byte type = (byte)s.Type; msg.Write(left); msg.Write(type); }); if (s.Type == StructureTypes.Base) { AddRemarkableEvent(ServerCommand.EndOfGame, (msg) => { bool winnerIsLeft = TeamsHelper.Opposite(s.Team) == Teams.Left; msg.Write(winnerIsLeft); }); Timer t = new Timer(3000); t.Elapsed += (sender, e) => Server.Exit = true; t.Start(); } } } // Check to hit entities if (StructureHelper.IsTower(s.Type) && s.Alive) { Tower t = (Tower)s; float now = (float)Server.Instance.GetTime().TotalSeconds; Vec2 towerCenter = t.SpellSpawnPosition; foreach (ServerClient client in Clients.Values) { var clientRect = client.Champion.CreateCollisionRectangle(); Vec2 clientCenter = Rect.Center(clientRect); if (t.CanPrepare(now) && // not on cooldown s.Team == TeamsHelper.Opposite(client.Champion.Team) && // is enemy client.ChampStats.Alive && // is alive Utilities.InRange(towerCenter, clientCenter, Tower.RANGE)) // in range { if (!t.IsPreparing()) { t.StartPreparation(); PrepareTower(s.Team, s.Type); } else if (t.CanShoot(now)) { CastTowerSpell(s.Team, towerCenter, clientCenter); t.OnShot(now); } } } } }); }