From 85d7f099bd2ef688cb6d90b68189327e1ebb0dd3 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 1 May 2015 17:37:57 +0200 Subject: [PATCH] * River Kelpie - Fixed that the first ability did not always trigger as intended. --- .../DragonlordsPrerogative.java | 2 +- .../src/mage/sets/shadowmoor/RiverKelpie.java | 26 +++++++------- .../src/mage/sets/theros/WhipOfErebos.java | 9 +++-- .../src/mage/sets/torment/ArrogantWurm.java | 3 +- .../cards/abilities/keywords/BestowTest.java | 16 +++++---- .../ZoneChangeReplacementTest.java | 36 ++++++++++++++++++- Mage/src/mage/abilities/AbilitiesImpl.java | 2 +- Mage/src/mage/game/GameTinyLeadersImpl.java | 2 +- Mage/src/mage/game/events/GameEvent.java | 1 + 9 files changed, 68 insertions(+), 29 deletions(-) diff --git a/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordsPrerogative.java b/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordsPrerogative.java index ffb2080d0b1..8f3a72b35e5 100644 --- a/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordsPrerogative.java +++ b/Mage.Sets/src/mage/sets/dragonsoftarkir/DragonlordsPrerogative.java @@ -114,7 +114,7 @@ class DragonlordsPrerogativeCondition implements Condition { public boolean apply(Game game, Ability source) { boolean applies = false; Spell spell = game.getStack().getSpell(source.getSourceId()); - if (spell != null) { + if (spell != null && spell.getSpellAbility() != null) { for(Cost cost: spell.getSpellAbility().getCosts()) { if (cost instanceof RevealTargetFromHandCost) { applies = !((RevealTargetFromHandCost)cost).getTargets().isEmpty(); diff --git a/Mage.Sets/src/mage/sets/shadowmoor/RiverKelpie.java b/Mage.Sets/src/mage/sets/shadowmoor/RiverKelpie.java index 08ac5c76c64..c90b5623244 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/RiverKelpie.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/RiverKelpie.java @@ -39,7 +39,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; /** * @@ -52,7 +51,6 @@ public class RiverKelpie extends CardImpl { this.expansionSetCode = "SHM"; this.subtype.add("Beast"); - this.color.setBlue(true); this.power = new MageInt(3); this.toughness = new MageInt(3); @@ -91,21 +89,20 @@ class RiverKelpieTriggeredAbility extends TriggeredAbilityImpl { super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), false); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.ZONE_CHANGE; + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE) { - ZoneChangeEvent zEvent = (ZoneChangeEvent) event; - if (zEvent.getFromZone() == Zone.GRAVEYARD && zEvent.getToZone() == Zone.BATTLEFIELD) { - Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD); - return permanent != null; - } - } - return false; + ZoneChangeEvent zEvent = (ZoneChangeEvent) event; + return zEvent.getFromZone() == Zone.GRAVEYARD && zEvent.getToZone() == Zone.BATTLEFIELD; } @Override public String getRule() { - return "Whenever River Kelpie or another permanent is put onto the battlefield from a graveyard, draw a card."; + return "Whenever {this} or another permanent is put onto the battlefield from a graveyard, draw a card."; } } @@ -124,9 +121,14 @@ class RiverKelpieTriggeredAbility2 extends TriggeredAbilityImpl { return new RiverKelpieTriggeredAbility2(this); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.SPELL_CAST; + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - return (event.getType() == GameEvent.EventType.SPELL_CAST && event.getZone() == Zone.GRAVEYARD); + return event.getZone() == Zone.GRAVEYARD; } @Override diff --git a/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java b/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java index 86126a1e408..8e4dfbcb939 100644 --- a/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java +++ b/Mage.Sets/src/mage/sets/theros/WhipOfErebos.java @@ -55,6 +55,7 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; import mage.target.targetpointer.FixedTarget; @@ -70,8 +71,6 @@ public class WhipOfErebos extends CardImpl { this.expansionSetCode = "THS"; this.supertype.add("Legendary"); - this.color.setBlack(true); - // Creatures you control have lifelink. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent("Creatures")))); // {2}{B}{B}, {T}: Return target creature card from your graveyard to the battlefield. @@ -154,10 +153,10 @@ class WhipOfErebosReplacementEffect extends ReplacementEffectImpl { @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Card card = game.getCard(source.getFirstTarget()); + Permanent permanent = game.getPermanent(source.getFirstTarget()); Player controller = game.getPlayer(source.getControllerId()); - if (card != null && controller != null) { - controller.moveCardToExileWithInfo(card, null, null, source.getSourceId(), game, Zone.BATTLEFIELD, true); + if (permanent != null && controller != null) { + controller.moveCardToExileWithInfo(permanent, null, null, source.getSourceId(), game, Zone.BATTLEFIELD, true); } return true; } diff --git a/Mage.Sets/src/mage/sets/torment/ArrogantWurm.java b/Mage.Sets/src/mage/sets/torment/ArrogantWurm.java index 390962c9929..5743ca061e5 100644 --- a/Mage.Sets/src/mage/sets/torment/ArrogantWurm.java +++ b/Mage.Sets/src/mage/sets/torment/ArrogantWurm.java @@ -48,7 +48,6 @@ public class ArrogantWurm extends CardImpl { this.expansionSetCode = "TOR"; this.subtype.add("Wurm"); - this.color.setGreen(true); this.power = new MageInt(4); this.toughness = new MageInt(4); @@ -56,7 +55,7 @@ public class ArrogantWurm extends CardImpl { this.addAbility(TrampleAbility.getInstance()); // Madness {2}{G} - this.addAbility(new MadnessAbility(this, new ManaCostsImpl("{2}{G}"))); + this.addAbility(new MadnessAbility(this, new ManaCostsImpl<>("{2}{G}"))); } public ArrogantWurm(final ArrogantWurm card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java index 62bc9f08089..b2a1690abd8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/BestowTest.java @@ -295,17 +295,21 @@ public class BestowTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Mogis's Warhound"); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mogis's Warhound using bestow", "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 4); + // Chandra's Outrage deals 4 damage to target creature and 2 damage to that creature's controller. + addCard(Zone.HAND, playerB, "Chandra's Outrage"); - setStopAt(3, PhaseStep.BEGIN_COMBAT); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Mogis's Warhound using bestow", "Silvercoat Lion"); + castSpell(1, PhaseStep.END_TURN, playerB, "Chandra's Outrage", "Silvercoat Lion"); + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); execute(); + assertLife(playerA, 18); // -2 from Chandra's Outrage + assertLife(playerB, 18); // -2 from attack of Mogis's Warhound // assertHandCount(playerA, "Mogis's Warhound", 0); - - // because cast with bestow, Boon Satyr may not be tapped - assertPermanentCount(playerA, "Silvercoat Lion", 1); - assertPowerToughness(playerA, "Silvercoat Lion", 4,4); + assertPermanentCount(playerA, "Mogis's Warhound", 1); + assertGraveyardCount(playerA, "Silvercoat Lion", 1); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java index cd71b3de778..adf0480d7d6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ZoneChangeReplacementTest.java @@ -30,7 +30,6 @@ package org.mage.test.cards.replacement; import mage.constants.PhaseStep; import mage.constants.Zone; -import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -324,6 +323,41 @@ public class ZoneChangeReplacementTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Legacy Weapon", 1); } + + /** + * Test that a returned creature of Whip of Erebos + * got exiled if it is destroyed by a spell + */ + @Test + public void testWhipOfErebos() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); + // Destroy target nonartifact, nonblack creature. It can't be regenerated. + addCard(Zone.HAND, playerA, "Terror"); + + // {2}{B}{B}, {T}: Return target creature card from your graveyard to the battlefield. + // It gains haste. Exile it at the beginning of the next end step. + // If it would leave the battlefield, exile it instead of putting it anywhere else. + // Activate this ability only any time you could cast a sorcery. + addCard(Zone.BATTLEFIELD, playerB, "Whip of Erebos"); + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 4); + addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion"); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{2}{B}{B},{T}: Return target creature", "Silvercoat Lion"); + + castSpell(2, PhaseStep.BEGIN_COMBAT, playerA, "Terror", "Silvercoat Lion"); + setStopAt(2, PhaseStep.END_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + assertGraveyardCount(playerA, "Terror", 1); + assertExileCount("Silvercoat Lion", 1); + + } + + + } diff --git a/Mage/src/mage/abilities/AbilitiesImpl.java b/Mage/src/mage/abilities/AbilitiesImpl.java index 199a795464d..fb34ffa59ee 100644 --- a/Mage/src/mage/abilities/AbilitiesImpl.java +++ b/Mage/src/mage/abilities/AbilitiesImpl.java @@ -76,7 +76,7 @@ public class AbilitiesImpl extends ArrayList implements Ab } if (!(ability instanceof SpellAbility || ability instanceof PlayLandAbility)) { String rule = ability.getRule(); - if (rule.length() > 3) { + if (rule != null && rule.length() > 3) { rule = Character.toUpperCase(rule.charAt(0)) + rule.substring(1); if (ability.getRuleAtTheTop()) { rules.add(0, rule); diff --git a/Mage/src/mage/game/GameTinyLeadersImpl.java b/Mage/src/mage/game/GameTinyLeadersImpl.java index 11c285982a2..d25f23cea01 100644 --- a/Mage/src/mage/game/GameTinyLeadersImpl.java +++ b/Mage/src/mage/game/GameTinyLeadersImpl.java @@ -95,7 +95,7 @@ public abstract class GameTinyLeadersImpl extends GameImpl{ getState().getWatchers().add(watcher); watcher.addCardInfoToCommander(this); } else { - throw new UnknownError("Commander card could not be created"); + throw new UnknownError("Commander card could not be created. Name: [" + player.getMatchPlayer().getDeck().getName() +"]"); } } diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 6b23fbc942e..b885db66466 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -118,6 +118,7 @@ public class GameEvent { playerId player that casts the spell amount not used for this event flag not used for this event + zone zone the spell is cast from */ SPELL_CAST,