oecs-sharp/Game.CardWars/Commands/PlayCardCommand.cs

62 lines
2.0 KiB
C#
Raw Normal View History

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;
}
}