using System.Diagnostics; using GlobalClassLib; using ONDServer.Enemies; using ONDServer.Map; using ONDServer.Net; using PacketLib; namespace ONDServer; public static class GameLogic { public const int START_CAMERA = 12; private static readonly OpportunityTimer secondCycleTimer = new(1000); private static readonly OpportunityTimer gamePhaseTimer = new(60_000); public static bool NSecondUpdate{ get; private set; } = false; public static MapTile P1Office; public static MapTile P2Office; public static MapTile[] Offices =>[P1Office, P2Office]; public static int OfficeDoorUsage{ get; set; } = 10; public static int RemoteDoorUsage{ get; set; } = 3; public static int LightUsage{ get; set; } = 2; public static int PhaseCounter{ get; private set; } = 1; private static List> spawnOrder; private static readonly int[] defaultSpawnPoints = [2, 22]; private static readonly Random random = new(); private const bool UNLIMITED_POWER = false; // Debug private const bool NO_PHASES = false; // Debug public static Dictionary PowerConsumers{ get; set; } = new(); public static void Init() { // Create map MapManager.InitMap(); P1Office = MapManager.Get(10); P2Office = MapManager.Get(14); //Send map to client TileConnector[] connectors = MapManager.GetAllConnectors(); int[] connectorsConverted = new int[connectors.Length * 4]; for (int i = 0; i < connectors.Length; i++){ connectorsConverted[i * 4] = connectors[i].Tiles.tile1.Id; connectorsConverted[i * 4 + 1] = connectors[i].Tiles.tile2.Id; connectorsConverted[i * 4 + 2] = (int)connectors[i].Type; connectorsConverted[i * 4 + 3] = connectors[i].Owner == null ? -1 : connectors[i].Owner!.State.Pid; } List p1Tiles = new(); List p2Tiles = new(); List neutralTiles = new(); foreach (var tile in MapManager.GetAllTiles()){ if(tile.Owner == null) neutralTiles.Add(tile.Id); else if(tile.Owner == Server.P1) p1Tiles.Add(tile.Id); else if(tile.Owner == Server.P2) p2Tiles.Add(tile.Id); } Server.SendPacket(new MapInitPacket{Connectors = connectorsConverted, UpsideDown = false, YourTiles = p1Tiles.ToArray(), OpponentTiles = p2Tiles.ToArray(), LitTiles = neutralTiles.ToArray()}, Server.P1.Peer); Server.SendPacket(new MapInitPacket{Connectors = connectorsConverted, UpsideDown = true, YourTiles = p2Tiles.ToArray(), OpponentTiles = p1Tiles.ToArray(), LitTiles = neutralTiles.ToArray()}, Server.P2.Peer); spawnOrder = [[new SpotEnemy(3), new MareEnemy(3)], [new DashEnemy(6)], [new LurkEnemy(3), new NekoEnemy(3)]]; spawnOrder.ForEach(l => l.ForEach(e => EnemyManager.AddEnemy(e))); Thread.Sleep(3000); secondCycleTimer.Start(); gamePhaseTimer.Start(); Server.SendUpdateToAll([GameEvent.GAME_START()]); // debug // EnemyManager.AddEnemy(new SpotEnemy(10)).Spawn(MapManager.Get(12)); // EnemyManager.AddEnemy(new LurkEnemy(10)).Spawn(MapManager.Get(12)); // EnemyManager.AddEnemy(new NekoEnemy(7)).Spawn(MapManager.Get(2)); // EnemyManager.AddEnemy(new DashEnemy(10)).Spawn(MapManager.Get(12)); // EnemyManager.AddEnemy(new MareEnemy(10)).Spawn(MapManager.Get(22)); EnemyManager.AddEnemy(new LurkEnemy(4)).Spawn(MapManager.Get(2)); EnemyManager.AddEnemy(new NekoEnemy(4)).Spawn(MapManager.Get(22)); } public static void Update() { if(secondCycleTimer.Check()) NSecondUpdate = true; if (NSecondUpdate){ (int p1, int p2) powerUsage = CalculatePowerUsage(); Server.P1.State.Power -= powerUsage.p1; Server.P2.State.Power -= powerUsage.p2; foreach (var player in Server.Players.Values){ if (player.State.Power < 0){ player.State.PoweredOut = true; player.State.Power = 0; PowerOut(player); } } if (UNLIMITED_POWER){ // Debug Server.P1.State.Power = Power.MAX_POWER_VALUE; Server.P2.State.Power = Power.MAX_POWER_VALUE; } Server.SendUpdateToAll([GameEvent.POWER_TICK(Server.P1.State.Pid, Server.P1.State.Power), GameEvent.POWER_TICK(Server.P2.State.Pid, Server.P2.State.Power)]); if (gamePhaseTimer.Check()){ NextPhase(); } } EnemyManager.Update(); NSecondUpdate = false; } public static void DeclareWinner(ServerPlayer player) { if (Server.Players.Count == 2){ Server.SendUpdateToAll([GameEvent.PLAYER_WIN(player.State.Pid)]); Console.WriteLine("Player " + player.State.Pid + " won!"); } Thread.Sleep(1000); Server.Stop(); if (!Server.AutoStop){ Program.Restart(); } } private static (int p1Usage, int p2Usage) CalculatePowerUsage() { int p1Usage = 0; int p2Usage = 0; foreach (var consumer in PowerConsumers){ if (consumer.Value.pid == Server.P1.State.Pid){ p1Usage += consumer.Value.usage; } else if (consumer.Value.pid == Server.P2.State.Pid){ p2Usage += consumer.Value.usage; } } return (p1Usage, p2Usage); } private static void PowerOut(ServerPlayer player) { foreach (var door in MapManager.GetDoors(player)){ door.Blocked = false; } foreach (var tile in MapManager.GetAllTiles().Where(t => t.Owner == player)){ tile.Lit = false; } PowerConsumers.Where(c => c.Value.pid == player.State.Pid).ToList().ForEach(c => PowerConsumers.Remove(c.Key)); Server.SendUpdateToAll([GameEvent.POWER_OUT(player.State.Pid)]); } private static void NextPhase() { if(NO_PHASES) return; PhaseCounter++; Server.SendUpdateToAll([GameEvent.NEXT_PHASE()]); int roll = spawnOrder.Count == 0 ? random.Next(1, 3) : random.Next(3); if (roll == 0){ int spawnRoll = random.Next(spawnOrder[0].Count); if (SpawnNext(spawnOrder[0][spawnRoll])){ spawnOrder[0].RemoveAt(spawnRoll); if (spawnOrder[0].Count == 0){ spawnOrder.RemoveAt(0); } } else{ roll = random.Next(1, 3); } } if (roll == 1){ Enemy[] allEnemies = EnemyManager.GetAll().Where(e => e.Difficulty <= 10).ToArray(); if (allEnemies.Length == 0) return; for (int i = 0; i < 2; i++){ Enemy enemy = allEnemies[random.Next(allEnemies.Length)]; enemy.SetDifficulty(enemy.Difficulty + 2); } } else if (roll == 2){ Enemy[] enemies = EnemyManager.GetAll(); for (int i = 0; i < enemies.Length; i++){ enemies[i].SetDifficulty(enemies[i].Difficulty + 1); } } } private static bool SpawnNext(Enemy enemy) { if (enemy.Type == EnemyType.NEKO || enemy.Type == EnemyType.LURK || enemy.Type == EnemyType.MARE){ MapTile[] spawnLocations = defaultSpawnPoints.Select(i => MapManager.Get(i)).Where(t => EnemyManager.GetByLocation(t).All(e => !e.BlocksTile)).ToArray(); if (spawnLocations.Length == 0){ return false; } enemy.Spawn(spawnLocations[random.Next(spawnLocations.Length)]); return true; } if (enemy.Type == EnemyType.SPOT || enemy.Type == EnemyType.DASH){ enemy.Spawn(MapManager.Get(12)); return true; } return false; } }