2026-07-20 22:52:28 +08:00
|
|
|
using OECS;
|
|
|
|
|
|
|
|
|
|
namespace Game.CardWars;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// One-time setup: creates players, leaders, banners, decks, castles, and deals starting hands.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class GameSetupSystem : ISystem
|
|
|
|
|
{
|
|
|
|
|
private readonly int _playerCount;
|
|
|
|
|
private readonly string _cardDataCsv;
|
|
|
|
|
private bool _hasRun;
|
|
|
|
|
|
|
|
|
|
public GameSetupSystem(int playerCount, string cardDataCsv)
|
|
|
|
|
{
|
|
|
|
|
_playerCount = playerCount;
|
|
|
|
|
_cardDataCsv = cardDataCsv;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Run(World world)
|
|
|
|
|
{
|
|
|
|
|
if (_hasRun) return;
|
|
|
|
|
_hasRun = true;
|
|
|
|
|
|
|
|
|
|
var state = world.ReadSingleton<GameState>();
|
|
|
|
|
ref var mutable = ref world.GetSingleton<GameState>();
|
|
|
|
|
mutable.PlayerCount = _playerCount;
|
|
|
|
|
mutable.Phase = GamePhase.PlayPhase;
|
|
|
|
|
mutable.CurrentPlayerIndex = 0;
|
|
|
|
|
mutable.StartingPlayerIndex = 0;
|
|
|
|
|
mutable.RoundNumber = 1;
|
|
|
|
|
world.MarkModified<GameState>(World.SingletonEntity);
|
|
|
|
|
|
|
|
|
|
// Register card effects.
|
|
|
|
|
CardEffectRegistry.Add<WarriorEffect>();
|
|
|
|
|
CardEffectRegistry.Add<ArcherEffect>();
|
|
|
|
|
CardEffectRegistry.Add<MercenaryEffect>();
|
|
|
|
|
CardEffectRegistry.Add<MerchantEffect>();
|
|
|
|
|
CardEffectRegistry.Add<DancerEffect>();
|
|
|
|
|
CardEffectRegistry.Add<PaladinEffect>();
|
|
|
|
|
CardEffectRegistry.Add<PrincessEffect>();
|
|
|
|
|
CardEffectRegistry.Add<DuelistEffect>();
|
|
|
|
|
CardEffectRegistry.Add<NunEffect>();
|
|
|
|
|
CardEffectRegistry.Add<ScoutEffect>();
|
|
|
|
|
CardEffectRegistry.Add<WitchEffect>();
|
|
|
|
|
CardEffectRegistry.Add<ThiefEffect>();
|
|
|
|
|
CardEffectRegistry.Add<PegasusEffect>();
|
|
|
|
|
CardEffectRegistry.Add<CurseMasterEffect>();
|
|
|
|
|
CardEffectRegistry.Add<MageEffect>();
|
|
|
|
|
CardEffectRegistry.Freeze();
|
|
|
|
|
|
|
|
|
|
// Create public deck.
|
|
|
|
|
var publicDeck = world.CreateEntity();
|
|
|
|
|
world.AddComponent(publicDeck, new PublicDeck());
|
|
|
|
|
|
|
|
|
|
// Load card definitions and create card instances for the public deck.
|
|
|
|
|
var defs = CardDataLoader.LoadDefinitions(world, _cardDataCsv);
|
|
|
|
|
foreach (var (defEntity, _) in defs)
|
|
|
|
|
{
|
2026-07-20 22:59:27 +08:00
|
|
|
world.AddComponent(defEntity, new InDeck { Target = publicDeck });
|
2026-07-20 22:52:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Shuffle public deck.
|
|
|
|
|
var seed = state.Seed;
|
|
|
|
|
GameUtil.ShuffleDeck(world, publicDeck, ref seed);
|
|
|
|
|
|
|
|
|
|
// Create the first castle.
|
|
|
|
|
var castle = world.CreateEntity();
|
|
|
|
|
world.AddComponent(castle, new Castle { Color = CastleColor.Black });
|
|
|
|
|
|
|
|
|
|
// Create players.
|
|
|
|
|
for (int i = 0; i < _playerCount; i++)
|
|
|
|
|
{
|
|
|
|
|
var player = world.CreateEntity();
|
|
|
|
|
world.AddComponent(player, new Player { Index = i });
|
|
|
|
|
|
|
|
|
|
// Create leader card (always on field, rank 0 placeholder).
|
|
|
|
|
var leader = world.CreateEntity();
|
|
|
|
|
world.AddComponent(leader, new Leader());
|
|
|
|
|
world.AddComponent(leader, new CardDef { Name = $"领袖{i}", Ranks = new[] { 0 }, Effect = CardEffect.None, Kind = CardKind.Faction });
|
|
|
|
|
world.AddComponent(leader, new Card { Rank = 0, FaceDown = false });
|
2026-07-20 22:59:27 +08:00
|
|
|
world.AddComponent(leader, new OnField { Target = player });
|
2026-07-20 22:52:28 +08:00
|
|
|
|
|
|
|
|
// Create banner.
|
|
|
|
|
var banner = world.CreateEntity();
|
|
|
|
|
world.AddComponent(banner, new Banner());
|
2026-07-20 22:59:27 +08:00
|
|
|
world.AddComponent(banner, new OnField { Target = player });
|
2026-07-20 22:52:28 +08:00
|
|
|
|
|
|
|
|
// Create faction deck.
|
|
|
|
|
var factionDeck = world.CreateEntity();
|
|
|
|
|
world.AddComponent(factionDeck, new FactionDeck());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deal starting hands: 3 public cards per player.
|
|
|
|
|
foreach (var player in GameUtil.FindAllEntities<Player>(world))
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
GameUtil.DrawCard(world, publicDeck, player);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mutable.Seed = seed;
|
|
|
|
|
world.MarkModified<GameState>(World.SingletonEntity);
|
|
|
|
|
}
|
|
|
|
|
}
|