/// <summary> /// Plays a card /// </summary> /// <param name="card">The card to play</param> /// <param name="subTarget">The sub target for this card, usually for targeting batlle cry spells</param> /// <param name="cardEffect">The card effect to use</param> /// <param name="gameboardPos">The position on the gameboard to place the card (if applicable). A value of -1 means play it in the next available slot</param> public void PlayCard(BaseCard card, IDamageableEntity subTarget, int gameboardPos = -1, CardEffect cardEffect = CardEffect.NONE) { // Is it even our turn to play? var gameState = GameEngine.GameState; if (gameState.CurrentPlayer != this) { throw new InvalidOperationException(string.Format("You can't play out of turn! It is currently {0}'s turn", gameState.CurrentPlayer)); } // Check if it exists in the player's hand BaseCard cardInHand = this.Hand.FirstOrDefault(c => c.Equals(card)); if (cardInHand == null) { throw new InvalidOperationException(string.Format("You can't play a card that's not in hand (or deck if force summoned from there)! {0}", card)); } // Check if we have enough mana to make the play if (this.Mana < cardInHand.CurrentManaCost) { throw new InvalidOperationException(string.Format("Not enough mana {0} to play that card {1}!", this.Mana, card.CurrentManaCost)); } var minionCard = cardInHand as BaseMinion; if (minionCard != null) { this.SummonMinion(minionCard, subTarget, gameboardPos, cardEffect, forceSummoned: false, cardSource: this.hand); } var spellCard = cardInHand as BaseSpell; if (spellCard != null) { this.PlaySpell(spellCard, subTarget, cardEffect); } var weaponCard = cardInHand as BaseWeapon; if (weaponCard != null) { this.PlayWeapon(weaponCard, subTarget); } // Register any triggered effects var triggeredEffectCard = cardInHand as ITriggeredEffectOwner; if (triggeredEffectCard != null) { triggeredEffectCard.RegisterEffect(); } // Trigger any deathrattles GameEngine.TriggerDeathrattles(); GameEngine.CheckForGameEnd(); }
/// <summary> /// Triggers death rattles after damage has been calculated. /// </summary> public static void TriggerDeathrattles() { // Before we fire trigger any deathrattles, we need to check if the game is over if (GameEngine.CheckForGameEnd()) { return; } // Remove dead minions from the board so the deathrattle doesn't trigger on itself GameEngine.DeadCardsThisTurn.ForEach(card => GameEngine.GameState.Board.RemoveCard(card)); // Deathrattles trigger by TimePlayed first. var sortedDeadCards = GameEngine.DeadCardsThisTurn.OrderBy(card => card.TimePlayed).ToList(); bool deathrattleTriggered = false; foreach (var card in sortedDeadCards) { if (GameEngine.Deathrattles.ContainsKey(card)) { GameEngine.Deathrattles[card].ForEach(deathrattle => deathrattle.Deathrattle()); // If the triggering card's player has a Baron Rivendare on the board, trigger again List <BaseCard> cardPlayZone; if (card.Owner == GameEngine.GameState.CurrentPlayer) { cardPlayZone = GameEngine.GameState.CurrentPlayerPlayZone; } else { cardPlayZone = GameEngine.GameState.WaitingPlayerPlayZone; } if (cardPlayZone.Any(minion => minion is BaronRivendare && !((BaseMinion)minion).IsSilenced)) { GameEngine.Deathrattles[card].ForEach(deathrattle => deathrattle.Deathrattle()); } deathrattleTriggered = true; GameEngine.Deathrattles.Remove(card); } } // We may have actually triggered yet more deathrattles with this so we need to check for it if (deathrattleTriggered) { GameEngine.TriggerDeathrattles(); } }
/// <summary> /// Draws n cards from the player's deck and puts it into his hand /// </summary> /// <param name="n"></param> public void DrawCards(int n = 1) { var drawnCards = this.Deck.DrawCards(n); foreach (var drawnCard in drawnCards) { drawnCard.Owner = this; if (drawnCard is FatigueCard) { // Oh noes! this.TakeDamage(((FatigueCard)drawnCard).FatigueDamage); GameEngine.CheckForGameEnd(); } else { Logger.Instance.Info(string.Format("{0}: Drew {1}", this.LogString(), drawnCard)); this.AddCardToHand(drawnCard); } } }