using DominionBase.Enums; using DominionBase.Players; using DominionBase.Properties; using System.Collections.Generic; using System.Diagnostics.Contracts; namespace DominionBase.Cards.Menagerie { public class VillageGreen : Card { private CardsDiscardingEventHandler _CardsDiscardingEventHandler; private IPlayer _turnStartedPlayer; public VillageGreen() : base(Categories.Action | Categories.Duration | Categories.Reaction, Source.Menagerie, Location.Kingdom, Traits.MultiType | Traits.PlusAction | Traits.PlusCard | Traits.PlusMultipleActions | Traits.ReactToDiscard) { BaseCost = new Cost(4); OwnerChanged += new OwnerChangedEventHandler(VillageGreen_OwnerChanged); } public override void TearDown(IGame game) { Contract.Requires(game != null, "game cannot be null"); VillageGreen_OwnerChanged(this, new OwnerChangedEventArgs(Owner, null)); base.TearDown(game); OwnerChanged -= new OwnerChangedEventHandler(VillageGreen_OwnerChanged); foreach (var player in game.Players) { player.TurnEnded -= Player_TurnEnded; player.TurnStarted -= Player_TurnStarted; } } private void VillageGreen_OwnerChanged(object sender, OwnerChangedEventArgs e) { if (_CardsDiscardingEventHandler != null && e.OldOwner != null) { e.OldOwner.CardsDiscarding -= _CardsDiscardingEventHandler; _CardsDiscardingEventHandler = null; } if (e.NewOwner != null) { _CardsDiscardingEventHandler = new CardsDiscardingEventHandler(Player_CardsDiscarding); e.NewOwner.CardsDiscarding += _CardsDiscardingEventHandler; } } private void Player_CardsDiscarding(object sender, CardsDiscardEventArgs e) { var player = sender as IPlayer; // Already being processed or been handled -- don't need to process this one if (e.GetResolver(TypeClass.VillageGreen) != null || e.HandledBy.Contains(this)) return; if (e.Cards.Contains(PhysicalCard) && player.Phase != PhaseEnum.Cleanup) e.AddResolver(TypeClass.VillageGreen, new CardsDiscardResolver(Owner, this, Resource.PlayCard.Replace("{card}", PhysicalCard.ToString()), Player_PlayVillageGreen)); } internal void Player_PlayVillageGreen(IPlayer player, ref CardsDiscardEventArgs e) { if (e.FromLocation == DeckLocation.PlayerMat) player.RetrieveCardFrom(e.FromMatType, this); else player.RetrieveCardFrom(e.FromLocation == DeckLocation.Deck ? DeckLocation.Revealed : e.FromLocation, this); e.Cards.Remove(this); // Reveal the card immediately before playing it player.AddCardInto(DeckLocation.Revealed, this); player.PlayCard(PhysicalCard, DeckLocation.InPlay); e.HandledBy.Add(this); } public override void FollowInstructions(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.FollowInstructions(player); var choiceTurn = new Choice(Resource.ChooseOne, this, this, new List { Resource.Now, Resource.NextTurn }, player); var resultTurn = player.MakeChoice(choiceTurn); if (resultTurn.Options.Count > 0) { if (resultTurn.Options[0] == Resource.Now) { TakeBenefit(player); CanCleanUpPlayed.Add(true); } else { CanCleanUpPlayed.Add(false); _turnStartedPlayer = player; player._Game.ActivePlayer.TurnEnded += Player_TurnEnded; } } } private void Player_TurnEnded(object sender, TurnEndedEventArgs e) { e.Player.TurnEnded -= Player_TurnEnded; _turnStartedPlayer.TurnStarted += Player_TurnStarted; } 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; } public override void ResolveDuration(IPlayer player) { Contract.Requires(player != null, "player cannot be null"); base.ResolveDuration(player); TakeBenefit(player); } private void TakeBenefit(IPlayer player) { player.ReceiveBenefit(this, new CardBenefit { Cards = 1, Actions = 2 }); } } }