You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.7 KiB
223 lines
5.7 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using Babushka.scripts.CSharp.Common.Fight.Actions;
|
|
using Babushka.scripts.CSharp.Common.Inventory;
|
|
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<Room> rooms;
|
|
}
|
|
|
|
public class Room
|
|
{
|
|
public enum Special
|
|
{
|
|
None,
|
|
EndOfNight
|
|
}
|
|
|
|
public required Dictionary<int, Room> paths;
|
|
public required List<FighterGroup> enemyGroups;
|
|
public Special specialRoom = Special.None;
|
|
}
|
|
|
|
public class FighterGroup
|
|
{
|
|
public required List<Fighter> fighters;
|
|
public ItemInstance? lootToDrop = null;
|
|
}
|
|
|
|
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<FighterAction> availableActions;
|
|
public const int MaxActionPoints = 1;
|
|
public int actionPointsLeft;
|
|
|
|
private int? _healthBacking = null;
|
|
|
|
public int Health
|
|
{
|
|
get => _healthBacking ?? maxHealth;
|
|
set => _healthBacking = Math.Clamp(value, 0, maxHealth);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public World? world = null;
|
|
public Room? currentRoom = null;
|
|
public FightHappeningData? fightHappeningData = null;
|
|
public AllyFighters allyFighters = new();
|
|
|
|
// settings
|
|
[Export] private ItemResource? _itemToDropByEnemyGroup;
|
|
[Export] public ItemResource? itemBeetrootToEatForHealth;
|
|
|
|
public void ResetFightWorld()
|
|
{
|
|
Generate();
|
|
currentRoom = world!.rooms[0];
|
|
}
|
|
|
|
public void Generate()
|
|
{
|
|
world = new Generator(this).GenerateWorld();
|
|
}
|
|
|
|
private class Generator(FightWorld fightWorld)
|
|
{
|
|
public World GenerateWorld()
|
|
{
|
|
var world = new World
|
|
{
|
|
rooms = GenerateRooms()
|
|
};
|
|
return world;
|
|
}
|
|
|
|
private List<Room> GenerateRooms()
|
|
{
|
|
var rooms = new List<Room>();
|
|
|
|
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<int, Room>(),
|
|
enemyGroups = GenerateEnemyGroups()
|
|
};
|
|
return room;
|
|
}
|
|
|
|
private List<FighterGroup> GenerateEnemyGroups()
|
|
{
|
|
var enemyGroups = new List<FighterGroup>();
|
|
|
|
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 = []
|
|
};
|
|
|
|
if (fightWorld._itemToDropByEnemyGroup != null)
|
|
{
|
|
enemyGroup.lootToDrop = new ItemInstance { blueprint = fightWorld._itemToDropByEnemyGroup };
|
|
}
|
|
|
|
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,
|
|
maxHealth = GD.RandRange(8, 20),
|
|
availableActions =
|
|
[
|
|
new BlobAttackAction(GD.RandRange(2, 5))
|
|
]
|
|
};
|
|
|
|
return enemy;
|
|
}
|
|
}
|
|
} |