62 lines
2.0 KiB
C#
62 lines
2.0 KiB
C#
using MessagePack;
|
|
using OECS;
|
|
|
|
namespace Game.CardWars;
|
|
|
|
/// <summary>
|
|
/// Play a card from hand to the field, choosing a rank.
|
|
/// Resolves on-play effects via the CardEffectRegistry.
|
|
/// </summary>
|
|
[MessagePackObject]
|
|
public struct PlayCardCommand : ICommand
|
|
{
|
|
[Key(0)] public Entity CardEntity;
|
|
[Key(1)] public int Rank;
|
|
[Key(2)] public bool FaceDown;
|
|
[Key(3)] public Entity? TargetPlayer;
|
|
|
|
public void Execute(World world)
|
|
{
|
|
var state = world.ReadSingleton<GameState>();
|
|
if (state.Phase is not GamePhase.PlayPhase) return;
|
|
if (!world.IsAlive(CardEntity)) return;
|
|
|
|
Entity player = FindPlayerByIndex(world, state.CurrentPlayerIndex);
|
|
if (player == Entity.Null) return;
|
|
|
|
// Verify the card is in the player's hand.
|
|
if (!world.HasComponent<HeldBy>(CardEntity)) return;
|
|
var heldBy = world.ReadComponent<HeldBy>(CardEntity);
|
|
if (heldBy.Target != player) return;
|
|
|
|
var def = world.ReadComponent<CardDef>(CardEntity);
|
|
|
|
// Determine target: Witch/Thief are played to another player's field.
|
|
Entity fieldOwner = def.Effect is CardEffect.Witch or CardEffect.Thief
|
|
? (TargetPlayer ?? player)
|
|
: player;
|
|
|
|
// Move from hand to field.
|
|
world.RemoveComponent<HeldBy>(CardEntity);
|
|
world.AddComponent(CardEntity, new OnField { Target = fieldOwner });
|
|
world.AddComponent(CardEntity, new Card { Rank = Rank, FaceDown = FaceDown });
|
|
|
|
// Resolve on-play effects via registry.
|
|
if (!FaceDown)
|
|
CardEffectRegistry.Dispatch(world, def.Effect, CardEntity, player, fieldOwner);
|
|
|
|
world.MarkModified<GameState>(World.SingletonEntity);
|
|
}
|
|
|
|
public static Entity FindPlayerByIndex(World world, int index)
|
|
{
|
|
using var iter = world.Select<Player>();
|
|
while (iter.MoveNext())
|
|
{
|
|
if (iter.CurrentEntity == World.SingletonEntity) continue;
|
|
if (iter.Current1.Index == index)
|
|
return iter.CurrentEntity;
|
|
}
|
|
return Entity.Null;
|
|
}
|
|
} |