using DominionBase.Enums; using DominionBase.Players; using DominionBase.Properties; using System.Diagnostics.Contracts; namespace DominionBase.Cards.Nocturne { public class Guardian : Card { private IPlayer _turnStartedPlayer; public Guardian() : base(Categories.Night | Categories.Duration, Source.Nocturne, Location.Kingdom, Traits.Defense | Traits.PlusCoin | Traits.ReactToGain) { BaseCost = new Cost(2); DurationBenefit.Currency.Coin.Value = 1; } public override void SetupCard(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.SetupCard(game); foreach (var player in game.Players) player.CardGained += Player_CardGained; } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); base.TearDown(game); foreach (var player in game.Players) { player.CardGained -= Player_CardGained; player.Attacked -= Player_Attacked_InPlay; } if (_turnStartedPlayer != null) _turnStartedPlayer.TurnStarted -= Player_TurnStarted; _turnStartedPlayer = null; } private void Player_CardGained(object sender, CardGainEventArgs e) { var player = sender as IPlayer; var key = TypeClass.Guardian.ToString(); // This is not the card you are looking for if (e.Card != this || e.Resolvers.ContainsKey(key) || e.HandledBy.Contains(this)) return; e.Resolvers[key] = new CardGainResolver(player, this, "PutIntoHand", $"Put {PhysicalCard} into your hand", Player_GainGuardian, true); } internal void Player_GainGuardian(IPlayer player, ref Players.CardGainEventArgs e) { e.Cancelled = true; e.IsLostTrackOf = true; e.Location = DeckLocation.Hand; e.HandledBy.Add(this); } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); CanCleanUpPlayed.Add(false); player.Attacked -= Player_Attacked_InPlay; player.Attacked += Player_Attacked_InPlay; _turnStartedPlayer = player; _turnStartedPlayer.TurnStarted += Player_TurnStarted; } private void Player_Attacked_InPlay(object sender, AttackedEventArgs e) { // Already been cancelled -- don't need to process this one if (e.Cancelled) return; var player = sender as IPlayer; // Guardian only protects against other attackers (duh) if (player == e.Attacker) return; // Passively cancels any attack e.Cancelled = true; player._Game.SendMessage(player, this); } public override void RemovedFrom(DeckLocation location, IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.RemovedFrom(location, player); player.Attacked -= Player_Attacked_InPlay; } private void Player_TurnStarted(object sender, TurnStartedEventArgs e) { var key = ToString(); if (!e.Resolvers.ContainsKey(key)) e.Resolvers[key] = new TurnStartedResolver(e.Player, this, Resource.ResolveCard.Replace("{card}", PhysicalCard.ToString()), Player_Action, true); } internal void Player_Action(IPlayer player, ref TurnStartedEventArgs e) { ResolveDuration(e.Player); CanCleanUpPlayed.Remove(false); e.Player.TurnStarted -= Player_TurnStarted; _turnStartedPlayer = null; } } }