From e0d9678b99243a2a4202202ff440ff4c16a30b4b Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 11:22:04 +0200 Subject: [PATCH 1/7] * Fixed split card handling in deck editor. --- Mage/src/mage/cards/mock/MockSplitCard.java | 4 +- .../mage/cards/mock/MockSplitCardHalf.java | 58 +++++++++++++++++++ Mage/src/mage/filter/FilterCard.java | 27 +++++---- 3 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 Mage/src/mage/cards/mock/MockSplitCardHalf.java diff --git a/Mage/src/mage/cards/mock/MockSplitCard.java b/Mage/src/mage/cards/mock/MockSplitCard.java index 3eb271bdad..e1c03601f4 100644 --- a/Mage/src/mage/cards/mock/MockSplitCard.java +++ b/Mage/src/mage/cards/mock/MockSplitCard.java @@ -51,12 +51,12 @@ public class MockSplitCard extends SplitCard { CardInfo leftHalf = CardRepository.instance.findCard(getLeftHalfName(card)); if (leftHalf != null) { - this.leftHalfCard = new MockCard(leftHalf); + this.leftHalfCard = new MockSplitCardHalf(leftHalf); } CardInfo rightHalf = CardRepository.instance.findCard(getRightHalfName(card)); if (rightHalf != null) { - this.rightHalfCard = new MockCard(rightHalf); + this.rightHalfCard = new MockSplitCardHalf(rightHalf); } } diff --git a/Mage/src/mage/cards/mock/MockSplitCardHalf.java b/Mage/src/mage/cards/mock/MockSplitCardHalf.java new file mode 100644 index 0000000000..4eefd3d0b1 --- /dev/null +++ b/Mage/src/mage/cards/mock/MockSplitCardHalf.java @@ -0,0 +1,58 @@ +/* + * 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.cards.mock; + +import mage.cards.SplitCard; +import mage.cards.SplitCardHalf; +import mage.cards.repository.CardInfo; + +/** + * + * @author LevelX2 + */ +public class MockSplitCardHalf extends MockCard implements SplitCardHalf { + + public MockSplitCardHalf(CardInfo card) { + super(card); + } + + public MockSplitCardHalf(final MockSplitCardHalf card) { + super(card); + } + + @Override + public MockSplitCardHalf copy() { + return new MockSplitCardHalf(this); + } + + @Override + public void setParentCard(SplitCard card) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + +} diff --git a/Mage/src/mage/filter/FilterCard.java b/Mage/src/mage/filter/FilterCard.java index 97cb529a05..2995a69318 100644 --- a/Mage/src/mage/filter/FilterCard.java +++ b/Mage/src/mage/filter/FilterCard.java @@ -64,30 +64,29 @@ public class FilterCard extends FilterObject { } //20130711 708.6c - /* If anything performs a comparison involving multiple characteristics or - * values of one or more split cards in any zone other than the stack or - * involving multiple characteristics or values of one or more fused split - * spells, each characteristic or value is compared separately. If each of - * the individual comparisons would return a “yes” answer, the whole + /* If anything performs a comparison involving multiple characteristics or + * values of one or more split cards in any zone other than the stack or + * involving multiple characteristics or values of one or more fused split + * spells, each characteristic or value is compared separately. If each of + * the individual comparisons would return a “yes” answer, the whole * comparison returns a “yes” answer. The individual comparisons may involve * different halves of the same split card. */ - @Override public boolean match(Card card, Game game) { - if(card.isSplitCard()){ - return super.match(((SplitCard)card).getLeftHalfCard(), game) || - super.match(((SplitCard)card).getRightHalfCard(), game); - } - else{ - return super.match(card, game); + if (card.isSplitCard()) { + return super.match(((SplitCard) card).getLeftHalfCard(), game) + || super.match(((SplitCard) card).getRightHalfCard(), game); + } else { + return super.match(card, game); } } + public boolean match(Card card, UUID playerId, Game game) { if (!this.match(card, game)) { return false; } - + return Predicates.and(extraPredicates).apply(new ObjectPlayer(card, playerId), game); } @@ -111,7 +110,7 @@ public class FilterCard extends FilterObject { } return filtered; } - + public boolean hasPredicates() { return predicates.size() > 0; } From 1213fd22c871bbe8ea7ebdce92b3383434740f25 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 17:34:21 +0200 Subject: [PATCH 2/7] * Followed Footsteps - Fixed that the token copy was not working correctly if the target was already copying something (e.g. a Cryptoplasm). --- .../mage/sets/ravnica/FollowedFootsteps.java | 14 ++++---- .../mage/test/cards/copy/CryptoplasmTest.java | 36 +++++++++++++++++++ .../util/functions/CopyTokenFunction.java | 18 +++++----- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/Mage.Sets/src/mage/sets/ravnica/FollowedFootsteps.java b/Mage.Sets/src/mage/sets/ravnica/FollowedFootsteps.java index 4ab45ecce4..76703050bb 100644 --- a/Mage.Sets/src/mage/sets/ravnica/FollowedFootsteps.java +++ b/Mage.Sets/src/mage/sets/ravnica/FollowedFootsteps.java @@ -30,8 +30,10 @@ package mage.sets.ravnica; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.OnEventTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.PutTokenOntoBattlefieldCopyTargetEffect; import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.constants.CardType; @@ -40,15 +42,14 @@ import mage.constants.Rarity; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.permanent.token.EmptyToken; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; -import mage.util.CardUtil; +import mage.target.targetpointer.FixedTarget; /** * * @author LoneFox - + * */ public class FollowedFootsteps extends CardImpl { @@ -99,10 +100,9 @@ class FollowedFootstepsEffect extends OneShotEffect { Permanent enchantment = game.getPermanentOrLKIBattlefield(source.getSourceId()); Permanent target = game.getPermanentOrLKIBattlefield(enchantment.getAttachedTo()); if (target != null) { - EmptyToken token = new EmptyToken(); - CardUtil.copyTo(token).from(target); - token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); - return true; + Effect effect = new PutTokenOntoBattlefieldCopyTargetEffect(); + effect.setTargetPointer(new FixedTarget(enchantment.getAttachedTo())); + return effect.apply(game, source); } return false; } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java index 1242402d45..1f8926e2cf 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java @@ -19,4 +19,40 @@ public class CryptoplasmTest extends CardTestPlayerBase { assertLife(playerB, 20); assertPermanentCount(playerA, "Craw Wurm", 2); } + + /** + * I have a Cryptoplasm in play, currently copying a Sigiled Paladin, and I + * enchant it with a Followed Footsteps. Next turn the aura triggers (the + * Crypto is still copying the same creature) and places a token on the + * battlefield, except the token is an untransformed Cryptoplasm, when it + * should be a Sigiled Paladin with Cryptoplasm's ability (as per rule + * 706.3), since that's what the enchanted creature currently is. + * + * 6/1/2011 If another creature becomes a copy of Cryptoplasm, it will + * become a copy of whatever Cryptoplasm is currently copying (if anything), + * plus it will have Cryptoplasm's triggered ability. + */ + @Test + public void testFollowedFootsteps() { + // First strike + // Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.) + addCard(Zone.BATTLEFIELD, playerA, "Sigiled Paladin", 1); // {W}{W} + + addCard(Zone.BATTLEFIELD, playerB, "Island", 5); + // Enchant creature + // At the beginning of your upkeep, put a token that's a copy of enchanted creature onto the battlefield. + addCard(Zone.HAND, playerB, "Followed Footsteps", 1); // {3}{U}{U} + // At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability. + addCard(Zone.BATTLEFIELD, playerB, "Cryptoplasm", 1); // {1}{U}{U} + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Followed Footsteps"); + addTarget(playerB, "Sigiled Paladin[only copy]"); + + setStopAt(4, PhaseStep.END_TURN); + execute(); + + assertPermanentCount(playerB, "Followed Footsteps", 1); + assertPermanentCount(playerB, "Cryptoplasm", 0); + assertPermanentCount(playerB, "Sigiled Paladin", 2); + } } diff --git a/Mage/src/mage/util/functions/CopyTokenFunction.java b/Mage/src/mage/util/functions/CopyTokenFunction.java index 001c818820..0c1e2957d0 100644 --- a/Mage/src/mage/util/functions/CopyTokenFunction.java +++ b/Mage/src/mage/util/functions/CopyTokenFunction.java @@ -61,24 +61,24 @@ public class CopyTokenFunction implements Function { if (source instanceof PermanentToken) { sourceObj = ((PermanentToken) source).getToken(); // to show the source image, the original values have to be used - target.setOriginalExpansionSetCode(((Token)sourceObj).getOriginalExpansionSetCode()); - target.setOriginalCardNumber(((Token)sourceObj).getOriginalCardNumber()); - target.setCopySourceCard(((PermanentToken)source).getToken().getCopySourceCard()); + target.setOriginalExpansionSetCode(((Token) sourceObj).getOriginalExpansionSetCode()); + target.setOriginalCardNumber(((Token) sourceObj).getOriginalCardNumber()); + target.setCopySourceCard(((PermanentToken) source).getToken().getCopySourceCard()); } else if (source instanceof PermanentCard) { - if (((PermanentCard)source).isMorphed() || ((PermanentCard)source).isManifested()) { + if (((PermanentCard) source).isMorphed() || ((PermanentCard) source).isManifested()) { MorphAbility.setPermanentToFaceDownCreature(target); return target; } else { - sourceObj = ((PermanentCard) source).getCard(); - target.setOriginalExpansionSetCode(source.getExpansionSetCode()); - target.setOriginalCardNumber(source.getCardNumber()); - target.setCopySourceCard((Card)sourceObj); + sourceObj = ((PermanentCard) source).getCard(); + target.setOriginalExpansionSetCode(source.getExpansionSetCode()); + target.setOriginalCardNumber(source.getCardNumber()); + target.setCopySourceCard((Card) sourceObj); } } else { target.setOriginalExpansionSetCode(source.getExpansionSetCode()); target.setOriginalCardNumber(source.getCardNumber()); if (source instanceof Card) { - target.setCopySourceCard((Card)source); + target.setCopySourceCard((Card) source); } } From df4dfc16d7ebc85439fbc474172d3f2a4dcc65ac Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 21:39:34 +0200 Subject: [PATCH 3/7] * Cipher - Fixed that the selection of the creature was handled targeted (e.g. checking for protection) fixes #1240). --- .../effects/common/CipherEffect.java | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/Mage/src/mage/abilities/effects/common/CipherEffect.java b/Mage/src/mage/abilities/effects/common/CipherEffect.java index d4bbdb20a2..89e6b39112 100644 --- a/Mage/src/mage/abilities/effects/common/CipherEffect.java +++ b/Mage/src/mage/abilities/effects/common/CipherEffect.java @@ -28,8 +28,6 @@ package mage.abilities.effects.common; import java.util.UUID; -import mage.constants.Duration; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; @@ -38,6 +36,9 @@ import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.cards.Card; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -46,37 +47,37 @@ import mage.target.targetpointer.FixedTarget; /** * FAQ 2013/01/11 - * + * * 702.97. Cipher * - * 702.97a Cipher appears on some instants and sorceries. It represents two static - * abilities, one that functions while the spell is on the stack and one that functions - * while the card with cipher is in the exile zone. "Cipher" means "If this spell is - * represented by a card, you may exile this card encoded on a creature you control" - * and "As long as this card is encoded on that creature, that creature has 'Whenever - * this creature deals combat damage to a player, you may copy this card and you may - * cast the copy without paying its mana cost.'" + * 702.97a Cipher appears on some instants and sorceries. It represents two + * static abilities, one that functions while the spell is on the stack and one + * that functions while the card with cipher is in the exile zone. "Cipher" + * means "If this spell is represented by a card, you may exile this card + * encoded on a creature you control" and "As long as this card is encoded on + * that creature, that creature has 'Whenever this creature deals combat damage + * to a player, you may copy this card and you may cast the copy without paying + * its mana cost.'" * - * 702.97b The term "encoded" describes the relationship between the card with cipher - * while in the exile zone and the creature chosen when the spell represented by that - * card resolves. + * 702.97b The term "encoded" describes the relationship between the card with + * cipher while in the exile zone and the creature chosen when the spell + * represented by that card resolves. * - * 702.97c The card with cipher remains encoded on the chosen creature as long as the - * card with cipher remains exiled and the creature remains on the battlefield. The - * card remains encoded on that object even if it changes controller or stops being - * a creature, as long as it remains on the battlefield. + * 702.97c The card with cipher remains encoded on the chosen creature as long + * as the card with cipher remains exiled and the creature remains on the + * battlefield. The card remains encoded on that object even if it changes + * controller or stops being a creature, as long as it remains on the + * battlefield. * * TODO: Implement Cipher as two static abilities concerning the rules. * * @author LevelX2 */ - - public class CipherEffect extends OneShotEffect { public CipherEffect() { super(Outcome.Copy); - staticText ="

Cipher (Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost.)"; + staticText = "

Cipher (Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost.)"; } public CipherEffect(final CipherEffect effect) { @@ -86,10 +87,11 @@ public class CipherEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); if (controller != null) { + TargetControlledCreaturePermanent target = new TargetControlledCreaturePermanent(); + target.setNotTarget(true); if (target.canChoose(source.getControllerId(), game) - && controller.chooseUse(outcome, "Cipher this spell to a creature?", source, game)) { + && controller.chooseUse(outcome, "Cipher this spell to a creature?", source, game)) { controller.chooseTarget(outcome, target, source, game); Card sourceCard = game.getCard(source.getSourceId()); Permanent targetCreature = game.getPermanent(target.getFirstTarget()); @@ -99,9 +101,10 @@ public class CipherEffect extends OneShotEffect { ContinuousEffect effect = new GainAbilityTargetEffect(ability, Duration.Custom); effect.setTargetPointer(new FixedTarget(target.getFirstTarget())); game.addEffect(effect, source); - if (!game.isSimulation()) + if (!game.isSimulation()) { game.informPlayers(new StringBuilder(sourceCard.getLogName()).append(": Spell ciphered to ").append(targetCreature.getLogName()).toString()); - return sourceCard.moveToExile(null, "", source.getSourceId(), game); + } + return controller.moveCards(sourceCard, null, Zone.EXILED, source, game); } else { return false; } @@ -119,7 +122,7 @@ public class CipherEffect extends OneShotEffect { class CipherStoreEffect extends OneShotEffect { - private UUID cipherCardId; + private final UUID cipherCardId; public CipherStoreEffect(UUID cipherCardId, String ruleText) { super(Outcome.Copy); @@ -141,13 +144,13 @@ class CipherStoreEffect extends OneShotEffect { SpellAbility ability = copyCard.getSpellAbility(); // remove the cipher effect from the copy Effect cipherEffect = null; - for (Effect effect :ability.getEffects()) { + for (Effect effect : ability.getEffects()) { if (effect instanceof CipherEffect) { cipherEffect = effect; } } ability.getEffects().remove(cipherEffect); - if (ability != null && ability instanceof SpellAbility) { + if (ability instanceof SpellAbility) { controller.cast(ability, game, true); } } From 5545aa02b54aba0174a2d1695c5c9195901c72a2 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 21:52:52 +0200 Subject: [PATCH 4/7] Added LoseAbilityAllEffect. --- .../continuous/LoseAbilityAllEffect.java | 57 +++++++++++++++++ .../continuous/LoseAllAbilitiesAllEffect.java | 64 +++++++++---------- 2 files changed, 88 insertions(+), 33 deletions(-) create mode 100644 Mage/src/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java diff --git a/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java new file mode 100644 index 0000000000..0ee881c377 --- /dev/null +++ b/Mage/src/mage/abilities/effects/common/continuous/LoseAbilityAllEffect.java @@ -0,0 +1,57 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.filter.FilterPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class LoseAbilityAllEffect extends ContinuousEffectImpl { + + protected final FilterPermanent filter; + protected final Ability ability; + + public LoseAbilityAllEffect(FilterPermanent filter, Ability ability, Duration duration) { + super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); + this.filter = filter; + this.ability = ability; + staticText = filter.getMessage() + " lose " + ability.toString() + (duration.toString().isEmpty() ? "" : " " + duration.toString()); + } + + public LoseAbilityAllEffect(final LoseAbilityAllEffect effect) { + super(effect); + this.filter = effect.filter.copy(); + this.ability = effect.ability; + } + + @Override + public LoseAbilityAllEffect copy() { + return new LoseAbilityAllEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + if (permanent != null) { + while (permanent.getAbilities().contains(ability)) { + permanent.getAbilities().remove(ability); + } + } + } + return true; + } + +} diff --git a/Mage/src/mage/abilities/effects/common/continuous/LoseAllAbilitiesAllEffect.java b/Mage/src/mage/abilities/effects/common/continuous/LoseAllAbilitiesAllEffect.java index 54115e932f..2e2020eda6 100644 --- a/Mage/src/mage/abilities/effects/common/continuous/LoseAllAbilitiesAllEffect.java +++ b/Mage/src/mage/abilities/effects/common/continuous/LoseAllAbilitiesAllEffect.java @@ -1,52 +1,50 @@ /* -* 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. -*/ - + * 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.abilities.effects.common.continuous; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.effects.ContinuousEffectImpl; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; -import mage.abilities.Ability; -import mage.abilities.Mode; -import mage.abilities.effects.ContinuousEffectImpl; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.permanent.Permanent; - /** * * @author LevelX2 */ public class LoseAllAbilitiesAllEffect extends ContinuousEffectImpl { - private FilterPermanent filter; + private final FilterPermanent filter; public LoseAllAbilitiesAllEffect(FilterPermanent filter, Duration duration) { super(duration, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); @@ -65,7 +63,7 @@ public class LoseAllAbilitiesAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { - for (Permanent permanent: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { if (permanent != null) { permanent.removeAllAbilities(source.getSourceId(), game); } From fa14128486604a32c9ff831edc09eb607327e078 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 22:52:00 +0200 Subject: [PATCH 5/7] * SOURCE_CAST_SPELL_ABILITY check for sourceId added. --- .../sets/bornofthegods/AstralCornucopia.java | 9 +-- .../championsofkamigawa/OrochiHatchery.java | 9 +-- .../sets/commander2014/LifebloodHydra.java | 9 +-- .../mage/sets/conflux/ApocalypseHydra.java | 9 +-- .../mage/sets/conspiracy/AcademyElite.java | 7 +- .../sets/conspiracy/GrenzoDungeonWarden.java | 10 +-- .../sets/dragonsmaze/SavagebornHydra.java | 12 ++-- .../mage/sets/gatecrash/NimbusSwimmer.java | 9 +-- .../sets/innistrad/MikaeusTheLunarch.java | 9 +-- .../mage/sets/khansoftarkir/BribersPurse.java | 9 +-- .../mage/sets/khansoftarkir/HoodedHydra.java | 9 +-- .../src/mage/sets/magic2010/ProteanHydra.java | 9 +-- .../mage/sets/magic2012/PrimordialHydra.java | 9 +-- .../mage/sets/magic2014/VastwoodHydra.java | 9 +-- .../src/mage/sets/magic2015/GenesisHydra.java | 8 +-- .../sets/magicorigins/HangarbackWalker.java | 9 +-- .../mage/sets/mirrodin/ChaliceOfTheVoid.java | 9 +-- .../modernmasters2015/WorldheartPhoenix.java | 9 +-- .../mage/sets/planechase/IvyElemental.java | 8 +-- .../src/mage/sets/planeshift/DralnusPet.java | 9 +-- .../mage/sets/returntoravnica/ManaBloom.java | 9 +-- .../MagaTraitorToMortals.java | 9 +-- .../sets/scarsofmirrodin/ChimericMass.java | 9 +-- .../mage/sets/shardsofalara/FeralHydra.java | 10 +-- .../shardsofalara/SigilOfDistinction.java | 9 +-- Mage.Sets/src/mage/sets/tempest/Krakilin.java | 10 +-- .../src/mage/sets/theros/MistcutterHydra.java | 10 +-- .../mage/sets/visions/PhyrexianMarauder.java | 9 +-- .../asthough/PlayFromNonHandZoneTest.java | 69 +++++++++++-------- 29 files changed, 183 insertions(+), 141 deletions(-) diff --git a/Mage.Sets/src/mage/sets/bornofthegods/AstralCornucopia.java b/Mage.Sets/src/mage/sets/bornofthegods/AstralCornucopia.java index def4ee17b9..d371e9adcc 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/AstralCornucopia.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/AstralCornucopia.java @@ -90,10 +90,11 @@ class AstralCornucopiaEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.CHARGE.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java index 56a0e0acb1..1e2e16c741 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/OrochiHatchery.java @@ -91,10 +91,11 @@ class OrochiHatcheryEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) {; - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.CHARGE.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/commander2014/LifebloodHydra.java b/Mage.Sets/src/mage/sets/commander2014/LifebloodHydra.java index fe68627ce7..8922851882 100644 --- a/Mage.Sets/src/mage/sets/commander2014/LifebloodHydra.java +++ b/Mage.Sets/src/mage/sets/commander2014/LifebloodHydra.java @@ -94,10 +94,11 @@ class LifebloodHydraComesIntoPlayEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && !permanent.isFaceDown(game)) { - Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/conflux/ApocalypseHydra.java b/Mage.Sets/src/mage/sets/conflux/ApocalypseHydra.java index 2996412edd..a195c86159 100644 --- a/Mage.Sets/src/mage/sets/conflux/ApocalypseHydra.java +++ b/Mage.Sets/src/mage/sets/conflux/ApocalypseHydra.java @@ -96,10 +96,11 @@ class ApocalypseHydraEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { if (amount < 5) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); diff --git a/Mage.Sets/src/mage/sets/conspiracy/AcademyElite.java b/Mage.Sets/src/mage/sets/conspiracy/AcademyElite.java index 9a249cfa5b..97809e2431 100644 --- a/Mage.Sets/src/mage/sets/conspiracy/AcademyElite.java +++ b/Mage.Sets/src/mage/sets/conspiracy/AcademyElite.java @@ -100,9 +100,10 @@ class AcademyEliteEffect1 extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { CardsInAllGraveyardsCount instantsAndSorceries = new CardsInAllGraveyardsCount(new FilterInstantOrSorceryCard("instant or sorcery cards")); int instantsAndSorceriesCount = instantsAndSorceries.calculate(game, source, this); if (instantsAndSorceriesCount > 0) { diff --git a/Mage.Sets/src/mage/sets/conspiracy/GrenzoDungeonWarden.java b/Mage.Sets/src/mage/sets/conspiracy/GrenzoDungeonWarden.java index 5195b3ef39..e583ec71ad 100644 --- a/Mage.Sets/src/mage/sets/conspiracy/GrenzoDungeonWarden.java +++ b/Mage.Sets/src/mage/sets/conspiracy/GrenzoDungeonWarden.java @@ -34,6 +34,7 @@ import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; @@ -94,10 +95,11 @@ class GrenzoDungeonWardenEtBEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((Ability) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java b/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java index 294084fe22..1ed4e842ea 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/SavagebornHydra.java @@ -34,6 +34,7 @@ import mage.abilities.SpellAbility; import mage.abilities.common.ActivateAsSorceryActivatedAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.DoubleStrikeAbility; @@ -95,12 +96,11 @@ class SavageBornHydraEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - // delete to prevent using it again if put into battlefield from other effect - setValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY, null); - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/gatecrash/NimbusSwimmer.java b/Mage.Sets/src/mage/sets/gatecrash/NimbusSwimmer.java index a47c15bc88..e7dbf68a9c 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/NimbusSwimmer.java +++ b/Mage.Sets/src/mage/sets/gatecrash/NimbusSwimmer.java @@ -87,10 +87,11 @@ class NimbusSwimmerEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/innistrad/MikaeusTheLunarch.java b/Mage.Sets/src/mage/sets/innistrad/MikaeusTheLunarch.java index b2e510508a..c87a6c44bc 100644 --- a/Mage.Sets/src/mage/sets/innistrad/MikaeusTheLunarch.java +++ b/Mage.Sets/src/mage/sets/innistrad/MikaeusTheLunarch.java @@ -110,10 +110,11 @@ class MikaeusTheLunarchEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/BribersPurse.java b/Mage.Sets/src/mage/sets/khansoftarkir/BribersPurse.java index ae267ccc25..ac166275b3 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/BribersPurse.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/BribersPurse.java @@ -94,10 +94,11 @@ class BribersPurseEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(new Counter("gem", amount), game); } diff --git a/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java b/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java index 701624c57f..9f577aba4d 100644 --- a/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java +++ b/Mage.Sets/src/mage/sets/khansoftarkir/HoodedHydra.java @@ -111,10 +111,11 @@ class HoodedHydraEffect1 extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && !permanent.isFaceDown(game)) { - Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/magic2010/ProteanHydra.java b/Mage.Sets/src/mage/sets/magic2010/ProteanHydra.java index 29285cf79c..e84b732672 100644 --- a/Mage.Sets/src/mage/sets/magic2010/ProteanHydra.java +++ b/Mage.Sets/src/mage/sets/magic2010/ProteanHydra.java @@ -102,10 +102,11 @@ public class ProteanHydra extends CardImpl { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/magic2012/PrimordialHydra.java b/Mage.Sets/src/mage/sets/magic2012/PrimordialHydra.java index 420d7def57..76a4fe38a7 100644 --- a/Mage.Sets/src/mage/sets/magic2012/PrimordialHydra.java +++ b/Mage.Sets/src/mage/sets/magic2012/PrimordialHydra.java @@ -98,10 +98,11 @@ class PrimordialHydraEntersEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java b/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java index 1face40591..128e2d989f 100644 --- a/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java +++ b/Mage.Sets/src/mage/sets/magic2014/VastwoodHydra.java @@ -102,10 +102,11 @@ class VastwoodHydraEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/magic2015/GenesisHydra.java b/Mage.Sets/src/mage/sets/magic2015/GenesisHydra.java index 39a891f900..af7a92c7e1 100644 --- a/Mage.Sets/src/mage/sets/magic2015/GenesisHydra.java +++ b/Mage.Sets/src/mage/sets/magic2015/GenesisHydra.java @@ -101,10 +101,10 @@ class GenesisHydraEntersBattlefieldEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - SpellAbility spellAbility = (SpellAbility) obj; + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { if (spellAbility.getSourceId().equals(source.getSourceId())) { // put into play by normal cast int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { diff --git a/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java b/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java index f438ef8f52..0b0a72bf05 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java +++ b/Mage.Sets/src/mage/sets/magicorigins/HangarbackWalker.java @@ -101,10 +101,11 @@ class HangarbackWalkerEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/mirrodin/ChaliceOfTheVoid.java b/Mage.Sets/src/mage/sets/mirrodin/ChaliceOfTheVoid.java index e36d852e5b..afab045802 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/ChaliceOfTheVoid.java +++ b/Mage.Sets/src/mage/sets/mirrodin/ChaliceOfTheVoid.java @@ -88,10 +88,11 @@ class ChaliceOfTheVoidEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.CHARGE.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java index 3eb2340d63..31277520f3 100644 --- a/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java +++ b/Mage.Sets/src/mage/sets/modernmasters2015/WorldheartPhoenix.java @@ -136,11 +136,12 @@ public class WorldheartPhoenix extends CardImpl { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { // 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}")) { + if (spellAbility.getManaCosts().getText().equals("{W}{U}{B}{R}{G}")) { permanent.addCounters(CounterType.P1P1.createInstance(2), game); } } diff --git a/Mage.Sets/src/mage/sets/planechase/IvyElemental.java b/Mage.Sets/src/mage/sets/planechase/IvyElemental.java index ab427c6c98..757482edb4 100644 --- a/Mage.Sets/src/mage/sets/planechase/IvyElemental.java +++ b/Mage.Sets/src/mage/sets/planechase/IvyElemental.java @@ -85,10 +85,10 @@ class IvyElementalEntersBattlefieldEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - SpellAbility spellAbility = (SpellAbility) obj; + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { if (spellAbility.getSourceId().equals(source.getSourceId())) { // put into play by normal cast int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { diff --git a/Mage.Sets/src/mage/sets/planeshift/DralnusPet.java b/Mage.Sets/src/mage/sets/planeshift/DralnusPet.java index c8c9218dbd..5a94ca0d4e 100644 --- a/Mage.Sets/src/mage/sets/planeshift/DralnusPet.java +++ b/Mage.Sets/src/mage/sets/planeshift/DralnusPet.java @@ -112,11 +112,12 @@ class DralnusPetEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getSourceId()); if (controller != null && permanent != null) { - Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { int cmc = 0; - for (Cost cost : ((SpellAbility) obj).getCosts()) { + for (Cost cost : spellAbility.getCosts()) { if (cost instanceof DiscardCardCost && ((DiscardCardCost) cost).getCards().size() > 0) { cmc = ((DiscardCardCost) cost).getCards().get(0).getManaCost().convertedManaCost(); } diff --git a/Mage.Sets/src/mage/sets/returntoravnica/ManaBloom.java b/Mage.Sets/src/mage/sets/returntoravnica/ManaBloom.java index 155244c026..f0d423cd6f 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/ManaBloom.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/ManaBloom.java @@ -100,12 +100,13 @@ class ManaBloomEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { // delete to prevent using it again if put into battlefield from other effect setValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY, null); - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.CHARGE.createInstance(amount), game); return true; diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java index fa2c2afda1..028f929959 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MagaTraitorToMortals.java @@ -97,10 +97,11 @@ class MagaTraitorToMortalsEnterBattlefieldEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java index e554b7b6c3..6ca59c6d7b 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/ChimericMass.java @@ -92,10 +92,11 @@ class ChimericMassEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.CHARGE.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/shardsofalara/FeralHydra.java b/Mage.Sets/src/mage/sets/shardsofalara/FeralHydra.java index c79740b735..a6d8eeda83 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/FeralHydra.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/FeralHydra.java @@ -34,6 +34,7 @@ import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -96,10 +97,11 @@ class FeralHydraEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java b/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java index a5c433e594..dc7aa39b6e 100644 --- a/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java +++ b/Mage.Sets/src/mage/sets/shardsofalara/SigilOfDistinction.java @@ -93,10 +93,11 @@ class SigilOfDistinctionEffect extends OneShotEffect { 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 - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.CHARGE.createInstance(amount), game); return true; diff --git a/Mage.Sets/src/mage/sets/tempest/Krakilin.java b/Mage.Sets/src/mage/sets/tempest/Krakilin.java index 5b7ee1a1c4..55ac185a0e 100644 --- a/Mage.Sets/src/mage/sets/tempest/Krakilin.java +++ b/Mage.Sets/src/mage/sets/tempest/Krakilin.java @@ -34,6 +34,7 @@ import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.RegenerateSourceEffect; import mage.cards.CardImpl; @@ -90,10 +91,11 @@ class KrakilinEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java b/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java index 501b8084e9..7fa563f676 100644 --- a/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java +++ b/Mage.Sets/src/mage/sets/theros/MistcutterHydra.java @@ -34,6 +34,7 @@ import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.CantBeCounteredAbility; import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.ProtectionAbility; @@ -102,10 +103,11 @@ class MistcutterHydraEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { - Object obj = getValue(mage.abilities.effects.EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((SpellAbility) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Sets/src/mage/sets/visions/PhyrexianMarauder.java b/Mage.Sets/src/mage/sets/visions/PhyrexianMarauder.java index 96c5998fc5..e06229d3ab 100644 --- a/Mage.Sets/src/mage/sets/visions/PhyrexianMarauder.java +++ b/Mage.Sets/src/mage/sets/visions/PhyrexianMarauder.java @@ -96,10 +96,11 @@ class PhyrexianMarauderEntersEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null && !permanent.isFaceDown(game)) { - Object obj = getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); - if (obj != null && obj instanceof SpellAbility - && permanent.getZoneChangeCounter(game) - 1 == ((SpellAbility) obj).getSourceObjectZoneChangeCounter()) { - int amount = ((Ability) obj).getManaCostsToPay().getX(); + SpellAbility spellAbility = (SpellAbility) getValue(EntersBattlefieldEffect.SOURCE_CAST_SPELL_ABILITY); + if (spellAbility != null + && spellAbility.getSourceId().equals(source.getSourceId()) + && permanent.getZoneChangeCounter(game) - 1 == spellAbility.getSourceObjectZoneChangeCounter()) { + int amount = spellAbility.getManaCostsToPay().getX(); if (amount > 0) { permanent.addCounters(CounterType.P1P1.createInstance(amount), game); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java index 0c2a691248..395b217c58 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/PlayFromNonHandZoneTest.java @@ -36,14 +36,31 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * * @author LevelX2 */ - public class PlayFromNonHandZoneTest extends CardTestPlayerBase { + @Test + public void testWorldheartPhoenixNormal() { + // Creature - Phoenix {3}{R} + // Flying + // 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. + addCard(Zone.HAND, playerA, "Worldheart Phoenix"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Worldheart Phoenix"); // can only be cast by {W}{U}{B}{R}{G} + + setStopAt(1, PhaseStep.END_COMBAT); + execute(); + + assertPowerToughness(playerA, "Worldheart Phoenix", 2, 2); + + } + @Test public void testWorldheartPhoenixNoMana() { // Creature - Phoenix {3}{R} - // Flying - // You may cast Worldheart Phoenix from your graveyard by paying {W}{U}{B}{R}{G} rather than paying its mana cost. + // Flying + // 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. addCard(Zone.GRAVEYARD, playerA, "Worldheart Phoenix"); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); @@ -53,16 +70,15 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase { setStopAt(1, PhaseStep.END_COMBAT); execute(); - assertPermanentCount(playerA, "Worldheart Phoenix", 0); - - } + assertPermanentCount(playerA, "Worldheart Phoenix", 0); + } @Test public void testWorldheartPhoenix() { // Creature - Phoenix {3}{R} - // Flying - // You may cast Worldheart Phoenix from your graveyard by paying {W}{U}{B}{R}{G} rather than paying its mana cost. + // Flying + // 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. addCard(Zone.GRAVEYARD, playerA, "Worldheart Phoenix"); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); @@ -76,11 +92,10 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase { setStopAt(1, PhaseStep.END_COMBAT); execute(); - assertPermanentCount(playerA, "Worldheart Phoenix", 1); - - } - - + assertPermanentCount(playerA, "Worldheart Phoenix", 1); + + } + @Test public void testNarsetEnlightenedMaster() { // First strike @@ -90,38 +105,36 @@ public class PlayFromNonHandZoneTest extends CardTestPlayerBase { skipInitShuffling(); addCard(Zone.LIBRARY, playerB, "Silvercoat Lion"); - addCard(Zone.LIBRARY, playerB, "Abzan Banner"); + addCard(Zone.LIBRARY, playerB, "Abzan Banner"); // Ferocious - If you control a creature with power 4 or greater, you may cast Dragon Grip as though it had flash. (You may cast it any time you could cast an instant.) // Enchant creature // Enchanted creature gets +2/+0 and has first strike. - addCard(Zone.LIBRARY, playerB, "Dragon Grip"); + addCard(Zone.LIBRARY, playerB, "Dragon Grip"); // You gain 2 life for each creature you control. - addCard(Zone.LIBRARY, playerB, "Peach Garden Oath"); - addCard(Zone.LIBRARY, playerB, "Plains"); - + addCard(Zone.LIBRARY, playerB, "Peach Garden Oath"); + addCard(Zone.LIBRARY, playerB, "Plains"); + attack(2, playerB, "Narset, Enlightened Master"); castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion"); // can't be cast from exile castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Abzan Banner"); // can be cast from exile castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Dragon Grip", "Narset, Enlightened Master"); // can be cast from exile castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Peach Garden Oath"); // can be cast from exile - + setStopAt(2, PhaseStep.END_TURN); execute(); assertExileCount("Silvercoat Lion", 1); - assertPermanentCount(playerB, "Abzan Banner", 1); - assertPermanentCount(playerB, "Dragon Grip", 1); + assertPermanentCount(playerB, "Abzan Banner", 1); + assertPermanentCount(playerB, "Dragon Grip", 1); assertGraveyardCount(playerB, "Peach Garden Oath", 1); - + assertPowerToughness(playerB, "Narset, Enlightened Master", 5, 2); - + assertHandCount(playerB, "Plains", 1); assertLife(playerA, 17); assertLife(playerB, 22); - - - } - - + + } + } From 774b7bdb0aa2f544debc1cf1a92365da28027eb0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 23:50:34 +0200 Subject: [PATCH 6/7] * Oloro, Ageless Ascetic - Fixe dthat the life loss was wrongly dealt as damage to the opponents. --- .../commander2013/OloroAgelessAscetic.java | 41 +++++-------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/Mage.Sets/src/mage/sets/commander2013/OloroAgelessAscetic.java b/Mage.Sets/src/mage/sets/commander2013/OloroAgelessAscetic.java index 569209b09f..766fb5bd62 100644 --- a/Mage.Sets/src/mage/sets/commander2013/OloroAgelessAscetic.java +++ b/Mage.Sets/src/mage/sets/commander2013/OloroAgelessAscetic.java @@ -29,23 +29,20 @@ package mage.sets.commander2013; import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.GainLifeControllerTriggeredAbility; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.DamagePlayersEffect; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeOpponentsEffect; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.TargetController; import mage.constants.Zone; -import mage.game.Game; /** * @@ -65,11 +62,17 @@ public class OloroAgelessAscetic extends CardImpl { // At the beginning of your upkeep, you gain 2 life. this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(2), TargetController.YOU, false)); + // Whenever you gain life, you may pay {1}. If you do, draw a card and each opponent loses 1 life. - this.addAbility(new GainLifeControllerTriggeredAbility(new DoIfCostPaid(new OloroAgelessAsceticEffect(), new GenericManaCost(1)),false)); + DoIfCostPaid effect = new DoIfCostPaid(new DrawCardSourceControllerEffect(1), new GenericManaCost(1)); + Effect effectToAdd = new LoseLifeOpponentsEffect(1); + effectToAdd.setText("and each opponent loses 1 life"); + effect.addEffect(effectToAdd); + this.addAbility(new GainLifeControllerTriggeredAbility(effect, false)); + // At the beginning of your upkeep, if Oloro, Ageless Ascetic is in the command zone, you gain 2 life. this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.COMMAND, - new GainLifeEffect(new StaticValue(2), "if Oloro, Ageless Ascetic is in the command zone, you gain 2 life"),TargetController.YOU, false)); + new GainLifeEffect(new StaticValue(2), "if {this} is in the command zone, you gain 2 life"), TargetController.YOU, false)); } public OloroAgelessAscetic(final OloroAgelessAscetic card) { @@ -81,27 +84,3 @@ public class OloroAgelessAscetic extends CardImpl { return new OloroAgelessAscetic(this); } } - -class OloroAgelessAsceticEffect extends OneShotEffect { - - public OloroAgelessAsceticEffect() { - super(Outcome.Benefit); - this.staticText = "draw a card and each opponent loses 1 life"; - } - - public OloroAgelessAsceticEffect(final OloroAgelessAsceticEffect effect) { - super(effect); - } - - @Override - public OloroAgelessAsceticEffect copy() { - return new OloroAgelessAsceticEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - new DrawCardSourceControllerEffect(1).apply(game, source); - new DamagePlayersEffect(1, TargetController.OPPONENT).apply(game, source); - return false; - } -} From bb1839f79bb03abe09aad16159939d1b9c6c22f5 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 1 Sep 2015 23:54:56 +0200 Subject: [PATCH 7/7] Added a test. --- .../mage/sets/eventide/DivinityOfPride.java | 21 +++--- .../sets/mirrodinbesieged/Cryptoplasm.java | 69 +++++++++---------- .../mage/test/AI/basic/CastCreaturesTest.java | 4 ++ .../mage/test/cards/copy/CryptoplasmTest.java | 59 ++++++++++++++++ 4 files changed, 108 insertions(+), 45 deletions(-) diff --git a/Mage.Sets/src/mage/sets/eventide/DivinityOfPride.java b/Mage.Sets/src/mage/sets/eventide/DivinityOfPride.java index 19558dcc7f..19190e1ec5 100644 --- a/Mage.Sets/src/mage/sets/eventide/DivinityOfPride.java +++ b/Mage.Sets/src/mage/sets/eventide/DivinityOfPride.java @@ -28,11 +28,6 @@ package mage.sets.eventide; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; @@ -42,6 +37,10 @@ import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -57,15 +56,19 @@ public class DivinityOfPride extends CardImpl { this.subtype.add("Spirit"); this.subtype.add("Avatar"); - this.power = new MageInt(4); this.toughness = new MageInt(4); + // Flying this.addAbility(FlyingAbility.getInstance()); + + // Lifelink this.addAbility(LifelinkAbility.getInstance()); + + // Divinity of Pride gets +4/+4 as long as you have 25 or more life. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new BoostSourceEffect(4, 4, Duration.WhileOnBattlefield), - new DivinityOfPrideCondition(), - "Divinity of Pride gets +4/+4 as long as you have 25 or more life"))); + new DivinityOfPrideCondition(), + "{this} gets +4/+4 as long as you have 25 or more life"))); } public DivinityOfPride(final DivinityOfPride card) { @@ -85,4 +88,4 @@ class DivinityOfPrideCondition implements Condition { Player player = game.getPlayer(source.getControllerId()); return player != null && player.getLife() >= 25; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java b/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java index 64202e88ca..3f02879da6 100644 --- a/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java +++ b/Mage.Sets/src/mage/sets/mirrodinbesieged/Cryptoplasm.java @@ -25,17 +25,19 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.mirrodinbesieged; -import mage.constants.CardType; -import mage.constants.Rarity; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CopyEffect; import mage.cards.CardImpl; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.TargetController; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.AnotherPredicate; import mage.game.Game; @@ -43,12 +45,11 @@ import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; import mage.util.functions.ApplyToPermanent; -import java.util.UUID; - /** * @author Loki */ public class Cryptoplasm extends CardImpl { + final static FilterCreaturePermanent filter = new FilterCreaturePermanent(); static { @@ -64,7 +65,7 @@ public class Cryptoplasm extends CardImpl { this.toughness = new MageInt(2); // At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability. - Ability ability = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmTransformEffect(), TargetController.YOU, true); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), TargetController.YOU, true); ability.addTarget(new TargetCreaturePermanent(filter)); this.addAbility(ability); } @@ -80,43 +81,39 @@ public class Cryptoplasm extends CardImpl { } -class CryptoplasmTransformEffect extends ContinuousEffectImpl { +class CryptoplasmEffect extends OneShotEffect { - CryptoplasmTransformEffect() { - super(Duration.WhileOnBattlefield, Layer.CopyEffects_1, SubLayer.NA, Outcome.Copy); - staticText = "you may have {this} become a copy of another target creature. If you do, {this} gains this ability"; + public CryptoplasmEffect() { + super(Outcome.Copy); + this.staticText = "you may have {this} become a copy of another target creature. If you do, {this} gains this ability"; } - CryptoplasmTransformEffect(final CryptoplasmTransformEffect effect) { + public CryptoplasmEffect(final CryptoplasmEffect effect) { super(effect); } @Override - public boolean apply(Game game, final Ability source) { - Permanent creature = game.getPermanent(targetPointer.getFirst(game, source)); - Permanent permanent = game.getPermanent(source.getSourceId()); - - if (creature == null || permanent == null) { - return false; - } - - game.copyPermanent(creature, permanent, source, new ApplyToPermanent() { - @Override - public Boolean apply(Game game, Permanent permanent) { - Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmTransformEffect(), TargetController.YOU, true); - upkeepAbility.addTarget(new TargetCreaturePermanent()); - permanent.addAbility(upkeepAbility, source.getSourceId(), game); - return true; - } - }); - - - return true; + public CryptoplasmEffect copy() { + return new CryptoplasmEffect(this); } @Override - public CryptoplasmTransformEffect copy() { - return new CryptoplasmTransformEffect(this); - } + public boolean apply(Game game, final Ability source) { + Permanent creatureToCopy = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (creatureToCopy != null) { + CopyEffect effect = new CopyEffect(creatureToCopy, source.getSourceId()); + effect.setApplier(new ApplyToPermanent() { + @Override + public Boolean apply(Game game, Permanent permanent) { + Ability upkeepAbility = new BeginningOfUpkeepTriggeredAbility(new CryptoplasmEffect(), TargetController.YOU, true); + upkeepAbility.addTarget(new TargetCreaturePermanent()); + permanent.addAbility(upkeepAbility, source.getSourceId(), game); + return true; + } + }); + game.addEffect(effect, source); + } + return true; + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java b/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java index 565fc57e36..7ec428cced 100644 --- a/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/AI/basic/CastCreaturesTest.java @@ -52,6 +52,10 @@ public class CastCreaturesTest extends CardTestPlayerBaseAI { assertPermanentCount(playerA, "Silvercoat Lion", 1); } + /** + * This test fails sometimes, probably because two plains are tapped for the + * first creature + */ @Test public void testSimpleCast2() { addCard(Zone.HAND, playerA, "Silvercoat Lion"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java index 1f8926e2cf..f57e5f9342 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java @@ -55,4 +55,63 @@ public class CryptoplasmTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Cryptoplasm", 0); assertPermanentCount(playerB, "Sigiled Paladin", 2); } + + /** + * I'm at 8 life, opponent (AI) is at 21. I have a Cryptoplasm currently + * copying my opponent's Divinity of Pride, the Crypto also has my Followed + * Footsteps attached to it. Additionally, I have another Cryptoplasm on the + * battlefield also copying the same Divinity, and a Clever Impersonator + * that ETB copying the first Cryptoplasm and is currently also a copy of + * the Divinity. + * + * Opponent attacks with his only Divinity of Pride (4/4) and a Serra + * Avenger (3/3). I block the Divinity with two of my Divinity copies (the + * Clever Impersonator and unenchanted Cryptoplasm) and the Avenger with the + * enchanted Divinity (originally a Cryptoplasm). My opponent's Divinity + * kills my two copies and dies, and then his Avenger dies and kills the + * Divinity blocking it, also sending my Followed Footsteps down with it. + * + * How does any of that add up? Not only should his Divinity only kill one + * of mine since it was a 4/4 and only becomes an 8/8 after dealing its + * damage (at which point it should be too late to go back and say the 4 + * damage are now 8, since it was that exact damage that put him at 25 + * life), but even more confusing is how the Serra Avenger, which is a 3/3, + * somehow kills my 4/4 that had suffered no other damage that turn. + * + * No other permanents in play at that moment had any influence in this + * either, they were only basic lands and a couple of creatures with no + * relevant abilities. + * + * I won't put aside me completely missing something here, but I really + * can't see any other explanation to this other than a game bug. + */ + @Test + public void testDamageLifelink() { + setLife(playerA, 21); + setLife(playerB, 8); + // First strike + // Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.) + addCard(Zone.BATTLEFIELD, playerA, "Divinity of Pride", 1); // {W}{W} + + addCard(Zone.BATTLEFIELD, playerB, "Island", 5); + // At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability. + addCard(Zone.BATTLEFIELD, playerB, "Cryptoplasm", 2); // {1}{U}{U} + addTarget(playerB, "Divinity of Pride"); + addTarget(playerB, "Divinity of Pride"); + + attack(3, playerA, "Divinity of Pride"); + block(3, playerB, "Divinity of Pride", "Divinity of Pride"); + block(3, playerB, "Divinity of Pride", "Divinity of Pride"); + + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerB, "Cryptoplasm", 0); + + assertPermanentCount(playerA, "Divinity of Pride", 0); + assertPermanentCount(playerB, "Divinity of Pride", 1); + + assertLife(playerB, 16); + assertLife(playerA, 25); + } }