From 8b880bfd470d3cca1bbab77a01a2700b7ae03739 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 31 Jul 2017 20:41:31 +0200 Subject: [PATCH 1/4] * Avatar of Will - Fixed a bug of the cost reduction effect. --- Mage.Sets/src/mage/cards/a/AvatarOfWill.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfWill.java b/Mage.Sets/src/mage/cards/a/AvatarOfWill.java index c4e8b913944..04d35881df3 100644 --- a/Mage.Sets/src/mage/cards/a/AvatarOfWill.java +++ b/Mage.Sets/src/mage/cards/a/AvatarOfWill.java @@ -48,7 +48,7 @@ import mage.players.Player; public class AvatarOfWill extends CardImpl { public AvatarOfWill(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{6}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{U}{U}"); this.subtype.add(SubType.AVATAR); this.power = new MageInt(5); this.toughness = new MageInt(6); @@ -99,10 +99,12 @@ class AvatarOfWillCostReductionEffect extends CostModificationEffectImpl { @Override public boolean applies(Ability abilityToModify, Ability source, Game game) { - for (UUID playerId : game.getOpponents(source.getControllerId())) { - Player opponent = game.getPlayer(playerId); - if (opponent != null && opponent.getHand().isEmpty()) { - return true; + if (abilityToModify.getSourceId().equals(source.getSourceId())) { + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player opponent = game.getPlayer(playerId); + if (opponent != null && opponent.getHand().isEmpty()) { + return true; + } } } return false; From 7a1245e2fec2dc0d8b6d93c32303df1241f85277 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 31 Jul 2017 20:42:32 +0200 Subject: [PATCH 2/4] Fixed a problem of DiesTriggeredAbility that produced null pointer exception. --- .../common/DiesTriggeredAbility.java | 2 +- .../BoostAllOfChosenSubtypeEffect.java | 114 +++++++++--------- 2 files changed, 60 insertions(+), 56 deletions(-) diff --git a/Mage/src/main/java/mage/abilities/common/DiesTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DiesTriggeredAbility.java index 6496e8ade82..d7f880ce11a 100644 --- a/Mage/src/main/java/mage/abilities/common/DiesTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DiesTriggeredAbility.java @@ -64,7 +64,7 @@ public class DiesTriggeredAbility extends ZoneChangeTriggeredAbility { return false; } // check now it is in graveyard - if (before.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(source.getId())) { + if (before.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(sourceId)) { Zone after = game.getState().getZone(sourceId); return after != null && Zone.GRAVEYARD.match(after); } else { diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java index 08223c5779d..5420bd0cf5e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BoostAllOfChosenSubtypeEffect.java @@ -1,55 +1,59 @@ -/* - * 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.constants.Duration; -import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; - -/** - * - * @author LevelX2 - */ -public class BoostAllOfChosenSubtypeEffect extends BoostAllEffect { - - SubType subtype = null; - - public BoostAllOfChosenSubtypeEffect(int power, int toughness, Duration duration, boolean excludeSource) { - super(power, toughness, duration, new FilterCreaturePermanent("All creatures of the chosen type"), excludeSource); - } - - public BoostAllOfChosenSubtypeEffect(int power, int toughness, Duration duration, FilterCreaturePermanent filter, boolean excludeSource) { - super(power, toughness, duration, filter, excludeSource); - } - - public BoostAllOfChosenSubtypeEffect(final BoostAllOfChosenSubtypeEffect effect) { - super(effect); - this.subtype = effect.subtype; - } - - @Override - public BoostAllOfChosenSubtypeEffect copy() { - return new BoostAllOfChosenSubtypeEffect(this); - } - - @Override - protected boolean selectedByRuntimeData(Permanent permanent, Ability source, Game game) { - if (subtype != null) { - return permanent.hasSubtype(subtype, game); - } - return false; - } - - @Override - protected void setRuntimeData(Ability source, Game game) { - String s = (String) game.getState().getValue(source.getSourceId() + "_type"); - subtype = SubType.byDescription(s); - } - -} +/* + * 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.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author LevelX2 + */ +public class BoostAllOfChosenSubtypeEffect extends BoostAllEffect { + + SubType subtype = null; + + public BoostAllOfChosenSubtypeEffect(int power, int toughness, Duration duration, boolean excludeSource) { + super(power, toughness, duration, new FilterCreaturePermanent("All creatures of the chosen type"), excludeSource); + } + + public BoostAllOfChosenSubtypeEffect(int power, int toughness, Duration duration, FilterCreaturePermanent filter, boolean excludeSource) { + super(power, toughness, duration, filter, excludeSource); + } + + public BoostAllOfChosenSubtypeEffect(final BoostAllOfChosenSubtypeEffect effect) { + super(effect); + this.subtype = effect.subtype; + } + + @Override + public BoostAllOfChosenSubtypeEffect copy() { + return new BoostAllOfChosenSubtypeEffect(this); + } + + @Override + protected boolean selectedByRuntimeData(Permanent permanent, Ability source, Game game) { + if (subtype != null) { + return permanent.hasSubtype(subtype, game); + } + return false; + } + + @Override + protected void setRuntimeData(Ability source, Game game) { + String s = (String) game.getState().getValue(source.getSourceId() + "_type"); + if (subtype != null) { + subtype = SubType.byDescription(s); + } else { + discard(); + } + } + +} From ad12c75c20527736371550ce4a7b1f82e596c928 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 31 Jul 2017 20:55:29 +0200 Subject: [PATCH 3/4] * Cinder cloud - Fixed the check for "dies this way". --- Mage.Sets/src/mage/cards/c/CinderCloud.java | 25 +++++++++++-------- .../mage/game/permanent/PermanentImpl.java | 4 +-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Mage.Sets/src/mage/cards/c/CinderCloud.java b/Mage.Sets/src/mage/cards/c/CinderCloud.java index f1c18346504..dab5bca111d 100644 --- a/Mage.Sets/src/mage/cards/c/CinderCloud.java +++ b/Mage.Sets/src/mage/cards/c/CinderCloud.java @@ -27,6 +27,7 @@ */ package mage.cards.c; +import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -34,13 +35,12 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import java.util.UUID; - /** * * @author ciaccona007 @@ -49,7 +49,6 @@ public class CinderCloud extends CardImpl { public CinderCloud(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}{R}"); - // Destroy target creature. If a white creature dies this way, Cinder Cloud deals damage to that creature's controller equal to the creature's power. this.getSpellAbility().addEffect(new CinderCloudEffect()); @@ -85,13 +84,19 @@ class CinderCloudEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if(permanent != null && permanent.destroy(source.getSourceId(), game, false) && permanent.getColor(game).equals(ObjectColor.WHITE)) { - int damage = permanent.getPower().getValue(); - Player player = game.getPlayer(permanent.getControllerId()); - if(player != null) { - player.damage(damage, source.getSourceId(), game, false, true); + if (permanent != null && permanent.destroy(source.getSourceId(), game, false) && permanent.getColor(game).equals(ObjectColor.WHITE)) { + game.applyEffects(); + if (permanent.getZoneChangeCounter(game) + 1 == game.getState().getZoneChangeCounter(permanent.getId()) + && !game.getState().getZone(permanent.getId()).equals(Zone.GRAVEYARD)) { + // A replacement effect has moved the card to another zone as grvayard + return true; + } + Player permanentController = game.getPlayer(permanent.getControllerId()); + if (permanentController != null) { + int damage = permanent.getPower().getValue(); + permanentController.damage(damage, source.getSourceId(), game, false, true); } } - return false; + return true; } -} \ No newline at end of file +} diff --git a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java index 86ed0b59fdf..f6c67594c07 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentImpl.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentImpl.java @@ -953,8 +953,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent { } if (!game.replaceEvent(GameEvent.getEvent(EventType.DESTROY_PERMANENT, objectId, sourceId, controllerId, noRegen ? 1 : 0))) { - // this means destroy was successful, if object movement to graveyard will be replaced (e.g. commander to command zone) does not count for - // successful destroying. + // this means destroy was successful, if object movement to graveyard will be replaced (e.g. commander to command zone) its still + // is handled as successful destroying (but not as sucessful "dies this way" for destroying). if (moveToZone(Zone.GRAVEYARD, sourceId, game, false)) { if (!game.isSimulation()) { String logName; From 98671c1210551fa76f571345dd88fe083520cd92 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Mon, 31 Jul 2017 21:08:32 +0200 Subject: [PATCH 4/4] * Jevleva - Fixed a by the last commited fix introduced bug in second triggered ability. --- .../mage/cards/j/JelevaNephaliasScourge.java | 4 +-- ...CastFromHandWithoutPayingManaCostTest.java | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java b/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java index 3db1324d721..6a3417fa05d 100644 --- a/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java +++ b/Mage.Sets/src/mage/cards/j/JelevaNephaliasScourge.java @@ -44,7 +44,6 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SuperType; import mage.constants.WatcherScope; -import mage.constants.Zone; import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.ExileZone; import mage.game.Game; @@ -117,7 +116,8 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect { for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { - player.moveCards(player.getLibrary().getTopCards(game, xValue), Zone.EXILED, source, game); + // + player.moveCardsToExile(player.getLibrary().getTopCards(game, xValue), source, game, true, CardUtil.getCardExileZoneId(game, source), sourceObject.getIdName()); } } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java index 88d23b08ee0..0f51dac53d2 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/alternate/CastFromHandWithoutPayingManaCostTest.java @@ -327,20 +327,20 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20); } - + @Test public void testJelevaCastingSavageBeatingFromExile() { - + /* Jeleva, Nephalia's Scourge {1}{U}{B}{R} Legendary Creature - Vampire Wizard 1/3 Flying When Jeleva, Nephalia's Scourge enters the battlefield, each player exiles the top X cards of his or her library, where X is the amount of mana spent to cast Jeleva. Whenever Jeleva attacks, you may cast an instant or sorcery card exiled with it without paying its mana cost. - */ + */ String jeleva = "Jeleva, Nephalia's Scourge"; - - /* + + /* Savage Beating {3}{R}{R} Instant Cast Savage Beating only during your turn and only during combat. @@ -348,30 +348,31 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase { - Creatures you control gain double strike until end of turn. - Untap all creatures you control. After this phase, there is an additional combat phase. Entwine {1}{R} (Choose both if you pay the entwine cost.) - */ + */ String savageBeating = "Savage Beating"; - + skipInitShuffling(); - addCard(Zone.LIBRARY, playerA, savageBeating); + addCard(Zone.LIBRARY, playerA, savageBeating, 2); addCard(Zone.HAND, playerA, jeleva); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); addCard(Zone.BATTLEFIELD, playerA, "Island", 3); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, jeleva); - + attack(3, playerA, jeleva); setChoice(playerA, "Yes"); // opt to use Jeleva ability setChoice(playerA, savageBeating); // choose to cast Savage Beating for free setChoice(playerA, "No"); // opt not to pay entwine cost setModeChoice(playerA, "1"); // use first mode of Savage Beating granting double strike - + setStopAt(3, PhaseStep.END_COMBAT); execute(); - + + assertGraveyardCount(playerA, savageBeating, 1); assertTapped(jeleva, true); assertLife(playerB, 18); assertAbility(playerA, jeleva, DoubleStrikeAbility.getInstance(), true); - assertGraveyardCount(playerA, savageBeating, 1); + } }