using System.Diagnostics; using FNAF_Server.Enemies; using FNAF_Server.Map; using GlobalClassLib; using PacketLib; namespace FNAF_Server; public class GameLogic { public const int START_CAMERA = 12; private static MovementOpportunity secondCycleTimer = new(1000); private static MovementOpportunity 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 int[] defaultSpawnPoints = [2, 22]; private static Random random = new(); private static bool unlimitedPower = false; // Debug // public const int POWER_MAX = 1000; // public static int P1Power{ get; set; } = Power.MAX_POWER_VALUE; // public static int P2Power{ get; set; } = Power.MAX_POWER_VALUE; // public static int[] PowerValues =>[P1Power, P2Power]; public static Dictionary PowerConsumers{ get; set; } = new(); public static void Init() { // Create map MapManager.InitMap(); P1Office = MapManager.Get(10); P2Office = MapManager.Get(14); // // foreach (var player in Server.Players.Values){ // player.state.power = Power.MAX_POWER_VALUE; // } //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)]]; Thread.Sleep(3000); secondCycleTimer.Start(); gamePhaseTimer.Start(); Server.SendUpdateToAll([GameEvent.GAME_START()]); // EnemyManager.AddEnemy(new SpotEnemy(10)).Spawn(MapManager.Get(12)); // EnemyManager.AddEnemy(new LurkEnemy(10)).Spawn(MapManager.Get(12)); // EnemyManager.AddEnemy(new NekoEnemy(10)).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(0)); } 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); } // Server.SendUpdateToAll([GameEvent.POWER_OUT(player.state.pid)]); } if (unlimitedPower){ // 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() { PhaseCounter++; Server.SendUpdateToAll([GameEvent.NEXT_PHASE()]); int roll = spawnOrder.Count > 0 ? random.Next(3) : random.Next(1,3); switch (roll){ case 0: int spawnRoll = random.Next(spawnOrder[0].Count); SpawnNext(spawnOrder[0][spawnRoll]); spawnOrder[0].RemoveAt(spawnRoll); if (spawnOrder[0].Count == 0){ spawnOrder.RemoveAt(0); } break; case 1: Enemy[] allEnemies = EnemyManager.GetAll(); for (int i = 0; i < 2; i++){ Enemy enemy = allEnemies[random.Next(allEnemies.Length)]; enemy.SetDifficulty(enemy.Difficulty + 2); } break; case 2: Enemy[] enemies = EnemyManager.GetAll(); for (int i = 0; i < enemies.Length; i++){ enemies[i].SetDifficulty(enemies[i].Difficulty + 1); } break; } } private static void SpawnNext(Enemy enemy) { if ((EnemyType)enemy.TypeId == EnemyType.NEKO || (EnemyType)enemy.TypeId == EnemyType.LURK || (EnemyType)enemy.TypeId == 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; } enemy.Spawn(spawnLocations[random.Next(spawnLocations.Length)]); } else if ((EnemyType)enemy.TypeId == EnemyType.SPOT || (EnemyType)enemy.TypeId == EnemyType.DASH){ enemy.Spawn(MapManager.Get(12)); } } }