From 25ef57570d29ec65e3d0e7240a55404c76955415 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 10 May 2015 01:33:02 +0200 Subject: [PATCH] [MM2] Added Worldhear Phoneix. --- .../src/mage/player/human/HumanPlayer.java | 2 +- .../mage/sets/avacynrestored/StolenGoods.java | 2 +- .../mage/sets/conflux/WorldheartPhoenix.java | 54 ++++++ .../src/mage/sets/judgment/Spelljack.java | 2 +- .../khansoftarkir/KheruSpellsnatcher.java | 2 +- .../NarsetEnlightenedMaster.java | 2 +- .../modernmasters2015/WorldheartPhoenix.java | 158 ++++++++++++++++++ .../sets/planarchaos/IntetTheDreamer.java | 2 +- .../src/mage/sets/ravnica/SinsOfThePast.java | 2 +- .../mage/sets/vintagemasters/MindsDesire.java | 2 +- Mage/src/mage/abilities/SpellAbility.java | 2 +- .../abilities/costs/mana/ManaCostsImpl.java | 1 - .../mage/abilities/effects/EffectImpl.java | 7 +- .../CanBlockAdditionalCreatureEffect.java | 2 +- Mage/src/mage/players/Player.java | 7 +- Mage/src/mage/players/PlayerImpl.java | 56 ++++--- 16 files changed, 269 insertions(+), 34 deletions(-) create mode 100644 Mage.Sets/src/mage/sets/conflux/WorldheartPhoenix.java create mode 100644 Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 0a500b4440..456bfb651f 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -1032,7 +1032,7 @@ public class HumanPlayer extends PlayerImpl { if (ability instanceof PlayLandAbility) { return true; } - if (!ability.getSourceId().equals(getCastSourceIdWithoutMana()) && ability.getManaCostsToPay().convertedManaCost() > 0) { + if (!ability.getSourceId().equals(getCastSourceIdWithAlternateMana()) && ability.getManaCostsToPay().convertedManaCost() > 0) { return true; } if (ability instanceof ManaAbility) { diff --git a/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java b/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java index 494d65c852..4afe7ededf 100644 --- a/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java +++ b/Mage.Sets/src/mage/sets/avacynrestored/StolenGoods.java @@ -138,7 +138,7 @@ class StolenGoodsCastFromExileEffect extends AsThoughEffectImpl { Card card = game.getCard(sourceId); if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) { Player player = game.getPlayer(affectedControllerId); - player.setCastSourceIdWithoutMana(sourceId); + player.setCastSourceIdWithAlternateMana(sourceId, null); return true; } } diff --git a/Mage.Sets/src/mage/sets/conflux/WorldheartPhoenix.java b/Mage.Sets/src/mage/sets/conflux/WorldheartPhoenix.java new file mode 100644 index 0000000000..038f985008 --- /dev/null +++ b/Mage.Sets/src/mage/sets/conflux/WorldheartPhoenix.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.conflux; + +import java.util.UUID; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class WorldheartPhoenix extends mage.sets.modernmasters2015.WorldheartPhoenix { + + public WorldheartPhoenix(UUID ownerId) { + super(ownerId); + this.cardNumber = 77; + this.expansionSetCode = "CON"; + this.rarity = Rarity.RARE; + } + + public WorldheartPhoenix(final WorldheartPhoenix card) { + super(card); + } + + @Override + public WorldheartPhoenix copy() { + return new WorldheartPhoenix(this); + } +} diff --git a/Mage.Sets/src/mage/sets/judgment/Spelljack.java b/Mage.Sets/src/mage/sets/judgment/Spelljack.java index 00703ee289..69b3746899 100644 --- a/Mage.Sets/src/mage/sets/judgment/Spelljack.java +++ b/Mage.Sets/src/mage/sets/judgment/Spelljack.java @@ -148,7 +148,7 @@ class SpelljackCastFromExileEffect extends AsThoughEffectImpl { if (card != null) { if (game.getState().getZone(sourceId) == Zone.EXILED) { Player player = game.getPlayer(affectedControllerId); - player.setCastSourceIdWithoutMana(sourceId); + player.setCastSourceIdWithAlternateMana(sourceId, null); return true; } else { diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java b/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java index 0388436b26..7f5cbbb6df 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/KheruSpellsnatcher.java @@ -162,7 +162,7 @@ class KheruSpellsnatcherCastFromExileEffect extends AsThoughEffectImpl { if (card != null) { if (game.getState().getZone(sourceId) == Zone.EXILED) { Player player = game.getPlayer(affectedControllerId); - player.setCastSourceIdWithoutMana(sourceId); + player.setCastSourceIdWithAlternateMana(sourceId, null); return true; } else { diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java b/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java index b349e2286c..1e83454a4c 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/NarsetEnlightenedMaster.java @@ -155,7 +155,7 @@ class NarsetEnlightenedMasterCastFromExileEffect extends AsThoughEffectImpl { Card card = game.getCard(objectId); if (card != null && game.getState().getZone(objectId) == Zone.EXILED) { Player player = game.getPlayer(affectedControllerId); - player.setCastSourceIdWithoutMana(objectId); + player.setCastSourceIdWithAlternateMana(objectId, null); return true; } } diff --git a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java new file mode 100644 index 0000000000..18150d9a69 --- /dev/null +++ b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java @@ -0,0 +1,158 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets.modernmasters2015; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.EntersBattlefieldEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class WorldheartPhoenix extends CardImpl { + + public WorldheartPhoenix(UUID ownerId) { + super(ownerId, 135, "Worldheart Phoenix", Rarity.UNCOMMON, new CardType[]{CardType.CREATURE}, "{3}{R}"); + this.expansionSetCode = "MMB"; + this.subtype.add("Phoenix"); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // You may cast Worldheart Phoenix from your graveyard by paying {W}{U}{B}{R}{G} rather than paying its mana cost. + // If you do, it enters the battlefield with two +1/+1 counters on it. + Ability ability = new SimpleStaticAbility(Zone.ALL, new WorldheartPhoenixPlayEffect()); + ability.addEffect(new EntersBattlefieldEffect(new WorldheartPhoenixEntersBattlefieldEffect(), + "If you do, it enters the battlefield with two +1/+1 counters on it")); + this.addAbility(ability); + + } + + public WorldheartPhoenix(final WorldheartPhoenix card) { + super(card); + } + + @Override + public WorldheartPhoenix copy() { + return new WorldheartPhoenix(this); + } + + class WorldheartPhoenixPlayEffect extends AsThoughEffectImpl { + + public WorldheartPhoenixPlayEffect() { + super(AsThoughEffectType.PLAY_FROM_NON_HAND_ZONE, Duration.EndOfGame, Outcome.Benefit); + staticText = "You may cast {this} from your graveyard by paying {W}{U}{B}{R}{G} rather than paying its mana cost"; + } + + public WorldheartPhoenixPlayEffect(final WorldheartPhoenixPlayEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public WorldheartPhoenixPlayEffect copy() { + return new WorldheartPhoenixPlayEffect(this); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + if (sourceId.equals(source.getSourceId()) && source.getControllerId().equals(affectedControllerId)) { + if (game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) { + Player player = game.getPlayer(affectedControllerId); + if (player != null) { + player.setCastSourceIdWithAlternateMana(sourceId, new ManaCostsImpl<>("{W}{U}{B}{R}{G}")); + return true; + } + } + } + return false; + } + + } + + class WorldheartPhoenixEntersBattlefieldEffect extends OneShotEffect { + + public WorldheartPhoenixEntersBattlefieldEffect() { + super(Outcome.BoostCreature); + staticText = "If you do, it enters the battlefield with two +1/+1 counters on it"; + } + + public WorldheartPhoenixEntersBattlefieldEffect(final WorldheartPhoenixEntersBattlefieldEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(source.getSourceId()); + if (permanent != null) { + Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (obj != null && obj instanceof SpellAbility) { + // TODO: No perfect solution because there could be other effects that allow to cast the card for this mana cost + if (((SpellAbility) obj).getManaCosts().getText().equals("{W}{U}{B}{R}{G}")) { + permanent.addCounters(CounterType.P1P1.createInstance(2), game); + } + } + } + return true; + } + + @Override + public WorldheartPhoenixEntersBattlefieldEffect copy() { + return new WorldheartPhoenixEntersBattlefieldEffect(this); + } + + } + +} diff --git a/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java b/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java index 0bd95f4c0a..4e23186000 100644 --- a/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java +++ b/Mage.Sets/src/mage/sets/planarchaos/IntetTheDreamer.java @@ -154,7 +154,7 @@ class IntetTheDreamerEffect extends AsThoughEffectImpl { controller.lookAtCards(sourceObject.getName(), cards, game); return false; } - controller.setCastSourceIdWithoutMana(objectId); + controller.setCastSourceIdWithAlternateMana(objectId, null); return true; } } diff --git a/Mage.Sets/src/mage/sets/ravnica/SinsOfThePast.java b/Mage.Sets/src/mage/sets/ravnica/SinsOfThePast.java index adf2dbb7a1..66849d4525 100644 --- a/Mage.Sets/src/mage/sets/ravnica/SinsOfThePast.java +++ b/Mage.Sets/src/mage/sets/ravnica/SinsOfThePast.java @@ -136,7 +136,7 @@ class SinsOfThePastCastFromGraveyardEffect extends AsThoughEffectImpl { if (sourceId.equals(this.getTargetPointer().getFirst(game, source)) && affectedControllerId.equals(source.getControllerId())) { Player player = game.getPlayer(affectedControllerId); - player.setCastSourceIdWithoutMana(sourceId); + player.setCastSourceIdWithAlternateMana(sourceId, null); return true; } return false; diff --git a/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java b/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java index e95e0bdab0..4ea05dfb29 100644 --- a/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java +++ b/Mage.Sets/src/mage/sets/vintagemasters/MindsDesire.java @@ -139,7 +139,7 @@ class MindsDesireCastFromExileEffect extends AsThoughEffectImpl { Card card = game.getCard(sourceId); if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) { Player player = game.getPlayer(affectedControllerId); - player.setCastSourceIdWithoutMana(sourceId); + player.setCastSourceIdWithAlternateMana(sourceId, null); return true; } } diff --git a/Mage/src/mage/abilities/SpellAbility.java b/Mage/src/mage/abilities/SpellAbility.java index a6006d52b1..6deef056b0 100644 --- a/Mage/src/mage/abilities/SpellAbility.java +++ b/Mage/src/mage/abilities/SpellAbility.java @@ -113,7 +113,7 @@ public class SpellAbility extends ActivatedAbilityImpl { // Alternate spell abilities (Flashback, Overload) can't be cast with no mana to pay option if (getSpellAbilityType().equals(SpellAbilityType.BASE_ALTERNATE)) { Player player = game.getPlayer(playerId); - if (player != null && getSourceId().equals(player.getCastSourceIdWithoutMana())) { + if (player != null && getSourceId().equals(player.getCastSourceIdWithAlternateMana())) { return false; } } diff --git a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java index 290d942426..bfefe86b77 100644 --- a/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java +++ b/Mage/src/mage/abilities/costs/mana/ManaCostsImpl.java @@ -33,7 +33,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import mage.MageObject; import mage.Mana; import mage.abilities.Ability; import mage.abilities.costs.VariableCost; diff --git a/Mage/src/mage/abilities/effects/EffectImpl.java b/Mage/src/mage/abilities/effects/EffectImpl.java index d339672eae..89db5169f8 100644 --- a/Mage/src/mage/abilities/effects/EffectImpl.java +++ b/Mage/src/mage/abilities/effects/EffectImpl.java @@ -46,7 +46,7 @@ import java.util.UUID; public abstract class EffectImpl implements Effect { protected UUID id; - protected final Outcome outcome; + protected Outcome outcome; protected EffectType effectType; protected TargetPointer targetPointer = FirstTargetPointer.getInstance(); protected String staticText = ""; @@ -94,6 +94,11 @@ public abstract class EffectImpl implements Effect { return outcome; } + @Override + public void setOutcome(Outcome outcome) { + this.outcome = outcome; + } + @Override public EffectType getEffectType() { return effectType; diff --git a/Mage/src/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java b/Mage/src/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java index 0e6ce67726..efeb94f2f6 100644 --- a/Mage/src/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java +++ b/Mage/src/mage/abilities/effects/common/combat/CanBlockAdditionalCreatureEffect.java @@ -102,7 +102,7 @@ public class CanBlockAdditionalCreatureEffect extends ContinuousEffectImpl { sb.append("any number of creatures"); break; default: - sb.append(CardUtil.numberToText(amount, "an")).append(" additional creatures"); + sb.append(CardUtil.numberToText(amount, "an")).append(" additional creature").append(amount > 1 ? "s":""); } return sb.toString(); } diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 3c4f0d64fa..a3a13e4451 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -47,6 +47,7 @@ import mage.abilities.TriggeredAbility; import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.VariableCost; import mage.abilities.costs.mana.ManaCost; +import mage.abilities.costs.mana.ManaCosts; import mage.cards.Card; import mage.cards.Cards; import mage.cards.decks.Deck; @@ -569,9 +570,11 @@ public interface Player extends MageItem, Copyable { * be cast without mana. * * @param sourceId the source that can be cast without mana + * @param manaCosts alternate ManaCost, null if it can be cast without mana cost */ - void setCastSourceIdWithoutMana(UUID sourceId); - UUID getCastSourceIdWithoutMana(); + void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts); + UUID getCastSourceIdWithAlternateMana(); + ManaCosts getCastSourceIdManaCosts(); // permission handling to show hand cards void addPermissionToShowHandCards(UUID watcherUserId); diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 33092b77f9..6c3b0d77d5 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -63,6 +63,7 @@ import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.Cost; import mage.abilities.costs.OptionalAdditionalSourceCosts; import mage.abilities.costs.mana.ManaCost; +import mage.abilities.costs.mana.ManaCosts; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.RestrictionUntapNotMoreThanEffect; @@ -219,8 +220,10 @@ public abstract class PlayerImpl implements Player, Serializable { // They neither expire immediately nor last indefinitely. protected boolean reachedNextTurnAfterLeaving = false; - // indicates that a sourceId will be cast without paying mana - protected UUID castSourceIdWithoutMana; + // indicates that the spell with the set sourceId can be cast with an alternate mana costs (can also be no mana costs) + protected UUID castSourceIdWithAlternateMana; + protected ManaCosts castSourceIdManaCosts; + // indicates that the player is in mana payment phase protected boolean payManaMode = false; @@ -320,7 +323,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.priorityTimeLeft = player.getPriorityTimeLeft(); this.reachedNextTurnAfterLeaving = player.reachedNextTurnAfterLeaving; - this.castSourceIdWithoutMana = player.castSourceIdWithoutMana; + this.castSourceIdWithAlternateMana = player.castSourceIdWithAlternateMana; + this.castSourceIdManaCosts = player.castSourceIdManaCosts; this.payManaMode = player.payManaMode; } @@ -378,7 +382,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.passed = player.isPassed(); this.priorityTimeLeft = player.getPriorityTimeLeft(); this.reachedNextTurnAfterLeaving = player.hasReachedNextTurnAfterLeaving(); - this.castSourceIdWithoutMana = player.getCastSourceIdWithoutMana(); + this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana(); + this.castSourceIdManaCosts = player.getCastSourceIdManaCosts(); this.usersAllowedToSeeHandCards.addAll(player.getUsersAllowedToSeeHandCards()); } @@ -439,7 +444,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.setLife(game.getLife(), game); this.setReachedNextTurnAfterLeaving(false); game.getState().getWatchers().add(new BloodthirstWatcher(playerId)); - this.castSourceIdWithoutMana = null; + this.castSourceIdWithAlternateMana = null; + this.castSourceIdManaCosts = null; } /** @@ -461,7 +467,8 @@ public abstract class PlayerImpl implements Player, Serializable { this.canPlayCardsFromGraveyard = false; this.topCardRevealed = false; this.alternativeSourceCosts.clear(); - this.castSourceIdWithoutMana = null; + this.castSourceIdWithAlternateMana = null; + this.castSourceIdManaCosts = null; this.getManaPool().clearEmptyManaPoolRules(); } @@ -885,15 +892,22 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public void setCastSourceIdWithoutMana(UUID sourceId) { - castSourceIdWithoutMana = sourceId; + public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts) { + castSourceIdWithAlternateMana = sourceId; + castSourceIdManaCosts = manaCosts; } @Override - public UUID getCastSourceIdWithoutMana() { - return castSourceIdWithoutMana; + public UUID getCastSourceIdWithAlternateMana() { + return castSourceIdWithAlternateMana; } + @Override + public ManaCosts getCastSourceIdManaCosts() { + return castSourceIdManaCosts; + } + + @Override public boolean isInPayManaMode() { return payManaMode; @@ -913,16 +927,19 @@ public abstract class PlayerImpl implements Player, Serializable { card.cast(game, fromZone, ability, playerId); Spell spell = game.getStack().getSpell(ability.getId()); // some effects set sourceId to cast without paying mana costs - if (ability.getSourceId().equals(getCastSourceIdWithoutMana())) { - noMana = true; + if (ability.getSourceId().equals(getCastSourceIdWithAlternateMana())) { + ManaCosts alternateCosts = getCastSourceIdManaCosts(); + if (alternateCosts == null) { + noMana = true; + } else { + ability.getManaCosts().clear(); + ability.getManaCosts().add(alternateCosts.copy()); + ability.getManaCostsToPay().clear(); + ability.getManaCostsToPay().add(alternateCosts.copy()); + } } - setCastSourceIdWithoutMana(null); + setCastSourceIdWithAlternateMana(null, null); if (spell.activate(game, noMana)) { -// for (Ability spellAbility: spell.getSpellAbilities()) { -// for (Effect effect: spellAbility.getEffects()) { -// effect.getTargetPointer().init(game, ability); -// } -// } GameEvent event = GameEvent.getEvent(GameEvent.EventType.SPELL_CAST, spell.getSpellAbility().getId(), spell.getSpellAbility().getSourceId(), playerId); event.setZone(fromZone); game.fireEvent(event); @@ -2959,8 +2976,7 @@ public abstract class PlayerImpl implements Player, Serializable { card = game.getCard(card.getId()); } game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName() : "a card face down") + " " + - (fromZone != null ? new StringBuilder("from ") + fromZone.toString().toLowerCase(Locale.ENGLISH) + " " : "") + - "to the exile zone"); + (fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) + " " : "") + "to the exile zone"); } result = true; }