public static void FlipCoinIfHeadsParalyzed(GameLog log, PokemonCard target) { if (CoinFlipper.FlipCoin()) { log.AddMessage("Coin flipped heads defending pokemon is now Paralyzed"); target.ApplyStatusEffect(StatusEffect.Paralyze, new GameField()); } else { log.AddMessage("Coin flipped tails, nothing happened"); } }
public void StartGame() { GameLog.AddMessage("Game starting"); ActivePlayerIndex = new Random().Next(2); GameLog.AddMessage($"{ActivePlayer.NetworkPlayer?.Name} goes first"); foreach (Player player in Players) { do { foreach (Card card in player.Hand) { player.Deck.Cards.Push(card); } player.Hand.Clear(); player.Deck.Shuffle(); player.DrawCards(StartingHandsize); } while (!player.Hand.OfType <PokemonCard>().Any(p => p.Stage == 0)); //TODO: Actual mulligan rules } GameState = GameFieldState.BothSelectingActive; ActivePlayer.OnCardsDrawn += PlayerDrewCards; ActivePlayer.OnCardsDiscarded += PlayerDiscardedCards; NonActivePlayer.OnCardsDrawn += PlayerDrewCards; NonActivePlayer.OnCardsDiscarded += PlayerDiscardedCards; PushGameLogUpdatesToPlayers(); }
public int FlipCoinsUntilTails() { int heads = 0; while (true) { if (CoinFlipper.FlipCoin() == CoinFlipper.TAILS) { break; } heads++; } GameLog?.AddMessage($"Flips {heads + 1} coins and gets {heads} heads"); var results = new List <bool>(); for (int i = 0; i < heads; i++) { results.Add(true); } results.Add(false); SendEventToPlayers(new CoinsFlippedEvent(results)); LastCoinFlipResult = heads > 0; LastCoinFlipHeadCount = heads; return(heads); }
private void DealDamageWithAttack(Attack attack) { Damage damage = attack.GetDamage(ActivePlayer, NonActivePlayer, this); damage.NormalDamage = DamageCalculator.GetDamageAfterWeaknessAndResistance(damage.NormalDamage, ActivePlayer.ActivePokemonCard, NonActivePlayer.ActivePokemonCard, attack, FindResistanceModifier()); if (DamageStoppers.Any(x => x.IsDamageIgnored(damage.NormalDamage + damage.DamageWithoutResistAndWeakness))) { GameLog.AddMessage("Damage ignored because of effect"); if (!IgnorePostAttack) { PostAttack(); } return; } var dealtDamage = NonActivePlayer.ActivePokemonCard.DealDamage(damage, this, ActivePlayer.ActivePokemonCard, !attack.IgnoreEffects); attack.OnDamageDealt(dealtDamage, ActivePlayer, this); if (!damage.IsZero()) { TriggerAbilityOfType(TriggerType.TakesDamage, NonActivePlayer.ActivePokemonCard, damage.NormalDamage + damage.DamageWithoutResistAndWeakness); TriggerAbilityOfType(TriggerType.DealsDamage, ActivePlayer.ActivePokemonCard, damage.NormalDamage + damage.DamageWithoutResistAndWeakness); } }
public void EvolvePokemon(PokemonCard basePokemon, PokemonCard evolution, bool ignoreAllChecks = false) { if (!ignoreAllChecks && !ActivePlayer.Id.Equals(basePokemon.Owner.Id) || !ActivePlayer.Id.Equals(evolution.Owner.Id)) { GameLog.AddMessage("Evolution stopped by epic 1337 anti-cheat"); return; } if (!ignoreAllChecks && GetAllPassiveAbilities().Any(ability => ability.ModifierType == PassiveModifierType.StopEvolutions)) { GameLog.AddMessage("Evolution stopped by ability"); return; } if (!ignoreAllChecks && (!basePokemon.CanEvolve() || !basePokemon.CanEvolveTo(evolution))) { return; } GameLog.AddMessage($"Evolving {basePokemon.GetName()} to {evolution.GetName()}"); if (ActivePlayer.ActivePokemonCard.Id.Equals(basePokemon.Id)) { basePokemon.Evolve(evolution); ActivePlayer.ActivePokemonCard = evolution; evolution.EvolvedThisTurn = true; } else { basePokemon.Evolve(evolution); evolution.EvolvedThisTurn = true; ActivePlayer.BenchedPokemon.ReplaceWith(basePokemon, evolution); } bool triggerEnterPlay = false; if (ActivePlayer.Hand.Contains(evolution)) { ActivePlayer.Hand.Remove(evolution); triggerEnterPlay = true; } evolution.RevealToAll(); SendEventToPlayers(new PokemonEvolvedEvent { TargetPokemonId = basePokemon.Id, NewPokemonCard = evolution }); if (triggerEnterPlay) { TriggerAbilityOfType(TriggerType.EnterPlay, evolution); } PushGameLogUpdatesToPlayers(); }
private void HitItselfInConfusion() { GameLog.AddMessage($"{ActivePlayer.ActivePokemonCard.GetName()} hurt itself in its confusion"); ActivePlayer.ActivePokemonCard.DealDamage(new Damage(0, ConfusedDamage), this, ActivePlayer.ActivePokemonCard, false); if (ActivePlayer.ActivePokemonCard.Ability?.TriggerType == TriggerType.DealsDamage) { ActivePlayer.ActivePokemonCard.Ability.SetTarget(ActivePlayer.ActivePokemonCard); ActivePlayer.ActivePokemonCard.Ability.Trigger(ActivePlayer, NonActivePlayer, ConfusedDamage, this); ActivePlayer.ActivePokemonCard.Ability.SetTarget(null); } }
public void PlayPokemon(PokemonCard pokemon) { if (!pokemon.Owner.Id.Equals(ActivePlayer.Id)) { GameLog.AddMessage($"{NonActivePlayer?.NetworkPlayer?.Name} Tried to play a pokemon on his opponents turn"); return; } ActivePlayer.PlayCard(pokemon); TriggerAbilityOfType(TriggerType.EnterPlay, pokemon); }
public void AddPokemonToBench(Player owner, List <PokemonCard> selectedPokemons) { if (GameState != GameFieldState.BothSelectingBench) { if (!ActivePlayer.Id.Equals(owner.Id)) { GameLog.AddMessage($"{owner?.NetworkPlayer?.Name} tried to play a pokemon when not allowed"); return; } } foreach (PokemonCard pokemon in selectedPokemons) { if (owner.BenchedPokemon.Count < BenchMaxSize && pokemon.Stage == 0) { int index = owner.BenchedPokemon.GetNextFreeIndex(); owner.SetBenchedPokemon(pokemon); pokemon.RevealToAll(); SendEventToPlayers(new PokemonAddedToBenchEvent() { Pokemon = pokemon, Player = owner.Id, Index = index }); } } if (GameState == GameFieldState.BothSelectingBench) { lock (lockObject) { playersSetStartBench.Add(owner.Id); if (playersSetStartBench.Count == 2) { foreach (var player in Players) { player.SetPrizeCards(PrizeCardCount); } GameState = GameFieldState.InTurn; SendEventToPlayers(new GameSyncEvent { Game = this }); } else { SendEventMessage(new GameSyncEvent { Game = this, Info = "Opponent is still selecting Pokémons" }, owner); } } } }
private void PostAttack() { if (AbilityTriggeredByDeath()) { GameLog.AddMessage(NonActivePlayer.ActivePokemonCard.Ability.Name + "triggered by dying"); NonActivePlayer.ActivePokemonCard.KnockedOutBy = ActivePlayer.ActivePokemonCard; TriggerAbilityOfType(TriggerType.KilledByAttack, NonActivePlayer.ActivePokemonCard, 0, NonActivePlayer.ActivePokemonCard); } DamageStoppers.ForEach(damageStopper => damageStopper.TurnsLeft--); DamageStoppers = DamageStoppers.Where(damageStopper => damageStopper.TurnsLeft > 0).ToList(); CheckDeadPokemon(); EndTurn(); }
public void PlayEnergyCard(EnergyCard energyCard, PokemonCard target) { if (!EnergyRule.CanPlayEnergyCard(energyCard, target)) { GameLog.AddMessage("Energy-rule disallowed playing the energy"); return; } if (!ActivePlayer.Hand.Contains(energyCard) || ActivePlayer.Hand.Contains(target)) { GameLog.AddMessage($"{ActivePlayer.NetworkPlayer?.Name} tried something wierd"); return; } foreach (var ability in target.TemporaryAbilities) { if (ability is DisableEnergyAttachmentAbility) { GameLog.AddMessage($"Ability {ability.Name} stops attaching energy to {target.Name}"); return; } } GameLog.AddMessage($"Attaching {energyCard.GetName()} to {target.Name}"); EnergyRule.CardPlayed(energyCard, target); energyCard.RevealToAll(); target.AttachedEnergy.Add(energyCard); bool fromHand = false; if (ActivePlayer.Hand.Contains(energyCard)) { fromHand = true; ActivePlayer.Hand.Remove(energyCard); } SendEventToPlayers(new EnergyCardsAttachedEvent() { AttachedTo = target, EnergyCard = energyCard }); energyCard.OnAttached(target, fromHand, this); PushGameLogUpdatesToPlayers(); }
public void TriggerAbilityOfType(TriggerType triggerType, PokemonCard pokemon, int damage = 0, PokemonCard target = null) { if (GetAllPassiveAbilities().Any(x => x.ModifierType == PassiveModifierType.StopAbilities)) { return; } if (StadiumCard != null && StadiumCard.Ability != null && StadiumCard.Ability.TriggerType == triggerType) { StadiumCard.Ability.Trigger(ActivePlayer, NonActivePlayer, damage, this); } var abilities = new List <Ability>(); abilities.AddRange(pokemon.TemporaryAbilities); if (pokemon.Ability != null) { abilities.Add(pokemon.Ability); } foreach (var ability in abilities) { if (ability is IAttackStoppingAbility) { continue; } var activator = ability.GetActivator(ActivePlayer); var other = GetOpponentOf(activator); if (ability.TriggerType == triggerType && ability.CanActivate(this, activator, other)) { GameLog.AddMessage($"Ability {ability.Name} from {ability.PokemonOwner.Name} triggers..."); SendEventToPlayers(new AbilityActivatedEvent { PokemonId = pokemon.Id }); ability.SetTarget(target); ability.Trigger(pokemon.Owner, GetOpponentOf(pokemon.Owner), damage, this); ability.SetTarget(null); } PushGameLogUpdatesToPlayers(); } }
public void ActivateAbility(Ability ability) { if (GetAllPassiveAbilities().Any(x => x.ModifierType == PassiveModifierType.StopAbilities)) { GameLog.AddMessage($"{ability.Name} stopped by ability"); return; } GameLog.AddMessage($"{ActivePlayer.NetworkPlayer?.Name} activates ability {ability.Name}"); var activatorId = ability.PokemonOwner != null ? ability.PokemonOwner.Id : StadiumCard.Id; SendEventToPlayers(new AbilityActivatedEvent() { PokemonId = activatorId }); ability.Trigger(ActivePlayer, NonActivePlayer, 0, this); SendEventToPlayers(new GameInfoEvent { }); CheckDeadPokemon(); if (GameState == GameFieldState.GameOver) { if (IsDraw()) { GameLog.AddMessage("It's a draw!"); EndGame(Id); } if (ActivePlayer.PrizeCards.Count == 0) { GameLog.AddMessage(ActivePlayer.NetworkPlayer?.Name + " wins the game"); EndGame(ActivePlayer.Id); } else if (NonActivePlayer.PrizeCards.Count == 0) { GameLog.AddMessage(NonActivePlayer.NetworkPlayer?.Name + " wins the game"); EndGame(NonActivePlayer.Id); } } PushGameLogUpdatesToPlayers(); }
private void StartNextTurn() { ActivePlayer.ResetTurn(); NonActivePlayer.ResetTurn(); ActivePlayer.DrawCards(1); if (ActivePlayer.IsDead) { GameLog.AddMessage($"{ActivePlayer.NetworkPlayer?.Name} loses because they drew to many cards"); EndGame(NonActivePlayer.Id); return; } if (ActivePlayer.ActivePokemonCard != null) { ActivePlayer.ActivePokemonCard.DamageTakenLastTurn = 0; } GameState = GameFieldState.InTurn; }
public void PokemonRetreated(PokemonCard replacementCard, List <EnergyCard> payedEnergy) { if (!ActivePlayer.Id.Equals(replacementCard.Owner.Id)) { return; } if (!CanRetreat(ActivePlayer.ActivePokemonCard)) { GameLog.AddMessage("Tried to retreat but did not have enough energy"); return; } foreach (var pokemon in NonActivePlayer.GetAllPokemonCards()) { TriggerAbilityOfType(TriggerType.OpponentRetreats, pokemon, 0, ActivePlayer.ActivePokemonCard); } ActivePlayer.RetreatActivePokemon(replacementCard, new List <EnergyCard>(payedEnergy), this); CheckDeadPokemon(); }
public int FlipCoins(int coins) { int heads; if (forcedFlips.Count > 0) { heads = 0; while (forcedFlips.Count > 0) { if (forcedFlips.Dequeue()) { heads++; } } } else { heads = CoinFlipper.FlipCoins(coins); } GameLog?.AddMessage($"Flips {coins} coins and gets {heads} heads"); var results = new List <bool>(); for (int i = 0; i < heads; i++) { results.Add(true); } for (int i = 0; i < coins - heads; i++) { results.Add(false); } SendEventToPlayers(new CoinsFlippedEvent(results)); LastCoinFlipResult = heads > 0; LastCoinFlipHeadCount = heads; return(heads); }
private void PlayStadiumCard(TrainerCard trainerCard) { trainerCard.RevealToAll(); CurrentTrainerCard = trainerCard; TriggerAllAbilitiesOfType(TriggerType.TrainerCardPlayed); GameLog.AddMessage(ActivePlayer.NetworkPlayer?.Name + " Plays " + trainerCard.GetName()); PushGameLogUpdatesToPlayers(); ActivePlayer.Hand.Remove(trainerCard); var trainerEvent = new StadiumCardPlayedEvent() { Card = trainerCard, Player = ActivePlayer.Id }; SendEventToPlayers(trainerEvent); trainerCard.Process(this, ActivePlayer, NonActivePlayer); if (StadiumCard != null) { StadiumCard.Owner.DiscardPile.Add(StadiumCard); } StadiumCard = trainerCard; CurrentTrainerCard = null; if (ActivePlayer.IsDead) { GameLog.AddMessage($"{ActivePlayer.NetworkPlayer?.Name} loses because they drew to many cards"); EndGame(NonActivePlayer.Id); } SendEventToPlayers(new GameInfoEvent { }); }
private void CheckDeadBenchedPokemon(Player player) { var opponent = GetOpponentOf(player); var killedPokemons = new List <PokemonCard>(); foreach (PokemonCard pokemon in player.BenchedPokemon.ValidPokemonCards) { if (pokemon == null || !pokemon.IsDead()) { continue; } SendEventToPlayers(new PokemonDiedEvent { Pokemon = pokemon }); killedPokemons.Add(pokemon); TriggerAbilityOfType(TriggerType.Dies, pokemon); if (opponent.PrizeCards.Count <= 1 && pokemon.PrizeCards > 0) { GameLog.AddMessage(opponent.NetworkPlayer?.Name + " wins the game"); EndGame(opponent.Id); return; } else { PushInfoToPlayer("Opponent is selecting a prize card", player); opponent.SelectPrizeCard(pokemon.PrizeCards, this); } } foreach (var pokemon in killedPokemons) { player.KillBenchedPokemon(pokemon); } }
private void CheckDeadPokemon() { if (IsDraw()) { GameLog.AddMessage("It's a draw!"); EndGame(Id); return; } CheckDeadBenchedPokemon(NonActivePlayer); CheckDeadBenchedPokemon(ActivePlayer); if (NonActivePlayer.ActivePokemonCard != null && NonActivePlayer.ActivePokemonCard.IsDead()) { GameLog.AddMessage(NonActivePlayer.ActivePokemonCard.GetName() + " Dies"); NonActivePlayer.ActivePokemonCard.KnockedOutBy = ActivePlayer.ActivePokemonCard; SendEventToPlayers(new PokemonDiedEvent { Pokemon = NonActivePlayer.ActivePokemonCard }); TriggerAbilityOfType(TriggerType.Dies, NonActivePlayer.ActivePokemonCard); TriggerAbilityOfType(TriggerType.Kills, ActivePlayer.ActivePokemonCard); NonActivePlayer.ActivePokemonCard.KnockedOutBy = ActivePlayer.ActivePokemonCard; PushGameLogUpdatesToPlayers(); if (ActivePlayer.PrizeCards.Count == 1 && NonActivePlayer.ActivePokemonCard.PrizeCards > 0) { GameLog.AddMessage(NonActivePlayer.NetworkPlayer?.Name + $" has no pokémon left, {ActivePlayer.NetworkPlayer?.Name} wins the game"); EndGame(ActivePlayer.Id); return; } else if (NonActivePlayer.BenchedPokemon.Count == 0) { GameLog.AddMessage(ActivePlayer.NetworkPlayer?.Name + " wins the game"); EndGame(ActivePlayer.Id); return; } else { PushInfoToPlayer("Opponent is selecting a prize card", NonActivePlayer); ActivePlayer.SelectPrizeCard(NonActivePlayer.ActivePokemonCard.PrizeCards, this); } NonActivePlayer.KillActivePokemon(); if (NonActivePlayer.BenchedPokemon.Count > 0) { PushInfoToPlayer("Opponent is selecting a new active Pokémon", ActivePlayer); NonActivePlayer.SelectActiveFromBench(this); } else { GameLog.AddMessage(NonActivePlayer.NetworkPlayer?.Name + $" has no pokémon left, {ActivePlayer.NetworkPlayer?.Name} wins the game"); EndGame(ActivePlayer.Id); return; } } PushGameLogUpdatesToPlayers(); if (ActivePlayer.ActivePokemonCard != null && ActivePlayer.ActivePokemonCard.IsDead()) { GameLog.AddMessage(ActivePlayer.ActivePokemonCard.GetName() + "Dies"); SendEventToPlayers(new PokemonDiedEvent { Pokemon = ActivePlayer.ActivePokemonCard }); TriggerAbilityOfType(TriggerType.Dies, ActivePlayer.ActivePokemonCard); var prizeCardValue = ActivePlayer.ActivePokemonCard.PrizeCards; ActivePlayer.ActivePokemonCard.KnockedOutBy = NonActivePlayer.ActivePokemonCard; ActivePlayer.KillActivePokemon(); if (ActivePlayer.BenchedPokemon.Count > 0) { PushInfoToPlayer("Opponent is selecting a prize card", ActivePlayer); NonActivePlayer.SelectPrizeCard(prizeCardValue, this); PushInfoToPlayer("Opponent is selecting a new active Pokémon", NonActivePlayer); ActivePlayer.SelectActiveFromBench(this); } else { GameLog.AddMessage(ActivePlayer.NetworkPlayer?.Name + $" has no pokémon left, {NonActivePlayer.NetworkPlayer?.Name} wins the game"); EndGame(NonActivePlayer.Id); return; } } PushGameLogUpdatesToPlayers(); }
public void PlayTrainerCard(TrainerCard trainerCard, Player asPlayer = null) { var caster = asPlayer == null ? ActivePlayer : asPlayer; var opponent = GetOpponentOf(caster); if (asPlayer == null && !caster.Hand.Contains(trainerCard)) { GameLog.AddMessage($"{ActivePlayer?.NetworkPlayer?.Name} Tried to play a trainer ({trainerCard.Name}) card not in his hand"); return; } if (GetAllPassiveAbilities().Any(ability => ability.ModifierType == PassiveModifierType.StopTrainerCast)) { GameLog.AddMessage($"{trainerCard.Name} stopped by ability"); return; } else if (!trainerCard.CanCast(this, caster, opponent)) { GameLog.AddMessage($"{trainerCard.Name} could not be cast because something is missing"); return; } if (trainerCard.IsStadium()) { PlayStadiumCard(trainerCard); return; } trainerCard.RevealToAll(); CurrentTrainerCard = trainerCard; TriggerAllAbilitiesOfType(TriggerType.TrainerCardPlayed); GameLog.AddMessage(caster.NetworkPlayer?.Name + " Plays " + trainerCard.GetName()); PushGameLogUpdatesToPlayers(); caster.Hand.Remove(trainerCard); var trainerEvent = new TrainerCardPlayed() { Card = trainerCard, Player = caster.Id }; SendEventToPlayers(trainerEvent); trainerCard.Process(this, caster, opponent); if (trainerCard.AddToDiscardWhenCasting) { trainerCard.Owner.DiscardPile.Add(trainerCard); } CurrentTrainerCard = null; if (caster.IsDead) { GameLog.AddMessage($"{caster.NetworkPlayer?.Name} loses because they drew to many cards"); EndGame(opponent.Id); } SendEventToPlayers(new GameInfoEvent { }); }
public void OnActivePokemonSelected(NetworkId ownerId, PokemonCard activePokemon) { Player owner = Players.First(p => p.Id.Equals(ownerId)); if (GameState != GameFieldState.BothSelectingActive) { if (!ActivePlayer.Id.Equals(ownerId)) { GameLog.AddMessage($"{owner?.NetworkPlayer?.Name} tried to play a pokemon when not allowed"); return; } } if (activePokemon.Stage == 0) { GameLog.AddMessage($"{owner.NetworkPlayer?.Name} is setting {activePokemon.GetName()} as active"); owner.SetActivePokemon(activePokemon); if (GameState != GameFieldState.BothSelectingActive) { SendEventToPlayers(new PokemonBecameActiveEvent { NewActivePokemon = activePokemon }); } } else { return; } lock (lockObject) { if (GameState == GameFieldState.BothSelectingActive) { if (!owner.Hand.OfType <PokemonCard>().Any(card => card.Stage == 0)) { playersSetStartBench.Add(owner.Id); } if (Players.All(p => p.ActivePokemonCard != null)) { if (playersSetStartBench.Count == 2) { foreach (var player in Players) { player.SetPrizeCards(PrizeCardCount); } GameState = GameFieldState.InTurn; SendEventToPlayers(new GameSyncEvent { Game = this }); } else { GameState = GameFieldState.BothSelectingBench; SendEventToPlayers(new GameSyncEvent { Game = this, Info = "Select Pokémons to add to your starting bench" }); return; } } else { PushInfoToPlayer("Opponent is selecting active...", owner); } SendEventMessage(new GameSyncEvent { Game = this }, Players.First(x => x.Id.Equals(ownerId))); } } PushGameLogUpdatesToPlayers(); }
public void Attack(Attack attack) { if (attack.Disabled || !attack.CanBeUsed(this, ActivePlayer, NonActivePlayer) || !ActivePlayer.ActivePokemonCard.CanAttack() || !ActivePlayer.ActivePokemonCard.Attacks.Contains(attack)) { GameLog.AddMessage($"Attack not used because FirstTurn: {FirstTurn} or Disabled: {attack.Disabled} or CanBeUsed:{attack.CanBeUsed(this, ActivePlayer, NonActivePlayer)}"); PushGameLogUpdatesToPlayers(); return; } GameState = GameFieldState.Attacking; GameLog.AddMessage($"{ActivePlayer.NetworkPlayer?.Name} activates attack {attack.Name}"); attack.PayExtraCosts(this, ActivePlayer, NonActivePlayer); CurrentDefender = NonActivePlayer.ActivePokemonCard; if (ActivePlayer.ActivePokemonCard.IsConfused && FlipCoins(1) == 0) { HitItselfInConfusion(); if (!IgnorePostAttack) { PostAttack(); } return; } SendEventToPlayers(new PokemonAttackedEvent() { Player = ActivePlayer.Id }); ActivePlayer.ActivePokemonCard.LastAttackUsed = attack; TriggerAbilityOfType(TriggerType.Attacks, ActivePlayer.ActivePokemonCard); TriggerAbilityOfType(TriggerType.Attacked, NonActivePlayer.ActivePokemonCard); var abilities = new List <Ability>(); abilities.AddRange(NonActivePlayer.ActivePokemonCard.GetAllActiveAbilities(this, NonActivePlayer, ActivePlayer)); abilities.AddRange(ActivePlayer.ActivePokemonCard.GetAllActiveAbilities(this, NonActivePlayer, ActivePlayer)); foreach (var ability in abilities.OfType <IAttackStoppingAbility>()) { if (ability.IsStopped(this, ActivePlayer.ActivePokemonCard, NonActivePlayer.ActivePokemonCard)) { if (!IgnorePostAttack) { PostAttack(); } return; } } DealDamageWithAttack(attack); attack.ProcessEffects(this, ActivePlayer, NonActivePlayer); CurrentDefender = null; GameState = GameFieldState.PostAttack; if (!IgnorePostAttack) { PostAttack(); } }