using System.Collections.Generic; using Babushka.scripts.CSharp.Common.Fight.Actions; using Babushka.scripts.CSharp.Common.Util; using Godot; namespace Babushka.scripts.CSharp.Common.Fight; public partial class FightWorld : Node { public class World { public required List rooms; } public class Room { public enum Special { None, EndOfNight } public required Dictionary paths; public required List enemyGroups; public Special specialRoom = Special.None; } public class FighterGroup { public required List fighters; } public class FightHappeningData { public required FighterGroup enemyGroup; public FightHappening.FightState fightState = FightHappening.FightState.None; public readonly FighterTurn fighterTurn = new(); public readonly FighterFormation allyFighterFormation = new(); public readonly FighterFormation enemyFighterFormation = new(); public FightHappening.FightersEnterStaging? fightersEnterStaging; public FighterAction? actionStaging; } public class Fighter { public enum Type { Blob, BigBlob, Mavka, YourMom, Vesna, Chuha } public required Type type; public required int maxHealth; public required List availableActions; public const int MaxActionPoints = 1; public int? health = null; // null => initialize to full health on spawn public int actionPointsLeft; public FighterAction AutoSelectAction() { return availableActions.Random() ?? new FighterAction.Skip(); } } #region AutoLoad ( Contains _EnterTree() ) public static FightWorld Instance { get; private set; } = null!; public override void _EnterTree() { Instance = this; MyEnterTree(); } #endregion public World? world = null; public Room? currentRoom = null; public FightHappeningData? fightHappeningData = null; public AllyFighters allyFighters = new(); public void MyEnterTree() { Generate(); currentRoom = world!.rooms[0]; } public void Generate() { world = new Generator().GenerateWorld(); } private class Generator { public World GenerateWorld() { var world = new World { rooms = GenerateRooms() }; return world; } private List GenerateRooms() { var rooms = new List(); var roomCount = 2; for (var i = 0; i < roomCount; i++) { rooms.Add(GenerateDisconnectedRoom()); } rooms.Add(new Room { paths = [], enemyGroups = [], specialRoom = Room.Special.EndOfNight }); // Connect rooms linearly for (var i = 0; i < rooms.Count - 1; i++) { rooms[i].paths[0] = rooms[i + 1]; rooms[i + 1].paths[1] = rooms[i]; } return rooms; } private Room GenerateDisconnectedRoom() { var room = new Room { paths = new Dictionary(), enemyGroups = GenerateEnemyGroups() }; return room; } private List GenerateEnemyGroups() { var enemyGroups = new List(); var enemyGroupCount = GD.RandRange(1, 2); for (var i = 0; i < enemyGroupCount; i++) { enemyGroups.Add(GenerateSingleEnemyGroup()); } return enemyGroups; } private FighterGroup GenerateSingleEnemyGroup() { var enemyGroup = new FighterGroup { fighters = [] }; var enemyCount = GD.RandRange(2, 3); for (var i = 0; i < enemyCount; i++) { enemyGroup.fighters.Add(GenerateSingleEnemy()); } return enemyGroup; } private Fighter GenerateSingleEnemy() { var typeRoll = GD.RandRange(0, 99); // Disabled generating different types due to lack of fighter visual type implementation //var type = typeRoll switch //{ // < 50 => Fighter.Type.Blob, // < 75 => Fighter.Type.BigBlob, // < 90 => Fighter.Type.Mavka, // _ => Fighter.Type.YourMom //}; var type = Fighter.Type.Blob; var enemy = new Fighter { type = type, health = null, maxHealth = GD.RandRange(8, 20), availableActions = [ new BlobAttackAction(GD.RandRange(2, 5)) ] }; return enemy; } } }