OneNightDuel/ONDServer/GameLogic.cs

206 lines
7.9 KiB
C#
Raw Normal View History

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<List<Enemy>> 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<object, (int usage, int pid)> 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<int> p1Tiles = new();
List<int> p2Tiles = new();
List<int> 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();
}
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;
}
}