mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
[DSK] Implement Nowhere to Run (#13208)
* [DSK] implemented Nowhere to Run * [DSK] implemented Nowhere to Run * NowhereToRun - fixed typo in static test * NowhereToRun - fixed hexproof effect
This commit is contained in:
parent
8772190c7b
commit
30dac5cc9f
3 changed files with 235 additions and 0 deletions
128
Mage.Sets/src/mage/cards/n/NowhereToRun.java
Normal file
128
Mage.Sets/src/mage/cards/n/NowhereToRun.java
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.AsThoughEffect;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.ContinuousEffect;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.common.continuous.BoostTargetEffect;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.abilities.keyword.WardAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.common.TargetOpponentsCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author markort147
|
||||
*/
|
||||
public final class NowhereToRun extends CardImpl {
|
||||
|
||||
public NowhereToRun(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}");
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// When Nowhere to Run enters, target creature an opponent controls gets -3/-3 until end of turn.
|
||||
Ability etbAbility = new EntersBattlefieldTriggeredAbility(new BoostTargetEffect(-3, -3, Duration.EndOfTurn));
|
||||
etbAbility.addTarget(new TargetOpponentsCreaturePermanent());
|
||||
this.addAbility(etbAbility);
|
||||
|
||||
// Creatures your opponents control can be the targets of spells and abilities as though they didn't have hexproof. Ward abilities of those creatures don't trigger.
|
||||
Ability staticAbility = new SimpleStaticAbility(new NowhereToRunHexproofEffect());
|
||||
staticAbility.addEffect(new NowhereToRunWardEffect());
|
||||
this.addAbility(staticAbility);
|
||||
}
|
||||
|
||||
private NowhereToRun(final NowhereToRun card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NowhereToRun copy() {
|
||||
return new NowhereToRun(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NowhereToRunHexproofEffect extends AsThoughEffectImpl {
|
||||
|
||||
NowhereToRunHexproofEffect() {
|
||||
super(AsThoughEffectType.HEXPROOF, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "Creatures your opponents control "
|
||||
+ "can be the targets of spells and "
|
||||
+ "abilities as though they didn't "
|
||||
+ "have hexproof.";
|
||||
}
|
||||
|
||||
private NowhereToRunHexproofEffect(final NowhereToRunHexproofEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
if (affectedControllerId.equals(source.getControllerId())) {
|
||||
Permanent creature = game.getPermanent(sourceId);
|
||||
return creature != null
|
||||
&& creature.isCreature(game)
|
||||
&& game.getOpponents(source.getControllerId()).contains(creature.getControllerId());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsThoughEffect copy() {
|
||||
return new NowhereToRunHexproofEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class NowhereToRunWardEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
|
||||
NowhereToRunWardEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||
staticText = "Ward abilities of those creatures don't trigger.";
|
||||
}
|
||||
|
||||
private NowhereToRunWardEffect(final NowhereToRunWardEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType().equals(GameEvent.EventType.NUMBER_OF_TRIGGERS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent == null || !permanent.isCreature(game)) {
|
||||
return false;
|
||||
}
|
||||
if (!game.getOpponents(source.getControllerId()).contains(permanent.getControllerId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return getValue("targetAbility") instanceof WardAbility;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContinuousEffect copy() {
|
||||
return new NowhereToRunWardEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -166,6 +166,7 @@ public final class DuskmournHouseOfHorror extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Neglected Manor", 264, Rarity.COMMON, mage.cards.n.NeglectedManor.class));
|
||||
cards.add(new SetCardInfo("Niko, Light of Hope", 224, Rarity.MYTHIC, mage.cards.n.NikoLightOfHope.class));
|
||||
cards.add(new SetCardInfo("Norin, Swift Survivalist", 145, Rarity.UNCOMMON, mage.cards.n.NorinSwiftSurvivalist.class));
|
||||
cards.add(new SetCardInfo("Nowhere to Run", 111, Rarity.UNCOMMON, mage.cards.n.NowhereToRun.class));
|
||||
cards.add(new SetCardInfo("Oblivious Bookworm", 225, Rarity.UNCOMMON, mage.cards.o.ObliviousBookworm.class));
|
||||
cards.add(new SetCardInfo("Omnivorous Flytrap", 192, Rarity.RARE, mage.cards.o.OmnivorousFlytrap.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Omnivorous Flytrap", 322, Rarity.RARE, mage.cards.o.OmnivorousFlytrap.class, NON_FULL_USE_VARIOUS));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
package org.mage.test.cards.enchantments;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author markort147
|
||||
*/
|
||||
public class NowhereToRunTest extends CardTestPlayerBase {
|
||||
|
||||
// Prevent ward from triggering on opponent's creatures
|
||||
@Test
|
||||
public void testWardPreventingOnOpponentsCreatures() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Waterfall Aerialist", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.HAND, playerA, "Nowhere to Run", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nowhere to Run");
|
||||
addTarget(playerA, "Waterfall Aerialist");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Waterfall Aerialist", 0);
|
||||
}
|
||||
|
||||
// Does not prevent ward from triggering on own creatures
|
||||
@Test
|
||||
public void testWardOnOwnCreatures() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Waterfall Aerialist", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Nowhere to Run", 1);
|
||||
addCard(Zone.HAND, playerB, "Swords to Plowshares", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Swords to Plowshares");
|
||||
addTarget(playerB, "Waterfall Aerialist");
|
||||
setChoice(playerB, false);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Waterfall Aerialist", 1);
|
||||
assertGraveyardCount(playerB, "Swords to Plowshares", 1);
|
||||
}
|
||||
|
||||
// Prevent hexproof on opponent's creatures
|
||||
@Test
|
||||
public void testHexproofOnCreatures() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Gladecover Scout", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Nowhere to Run", 1);
|
||||
addCard(Zone.HAND, playerA, "Go for the Throat", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Go for the Throat");
|
||||
addTarget(playerA, "Gladecover Scout");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerB, "Gladecover Scout", 0);
|
||||
}
|
||||
|
||||
// Does not prevent hexproof on non-creature permanents
|
||||
@Test
|
||||
public void testHexproofOnOtherPermanents() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Valgavoth's Lair", 1);
|
||||
setChoice(playerB, "Red");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Nowhere to Run", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.HAND, playerA, "Stone Rain", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stone Rain");
|
||||
addTarget(playerA, "Valgavoth's Lair");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
|
||||
try {
|
||||
execute();
|
||||
} catch (Throwable e) {
|
||||
if (!e.getMessage().contains("Targets list was setup by addTarget with [Valgavoth's Lair], but not used")) {
|
||||
Assert.fail("must throw error about bad targets, but got:\n" + e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
Assert.fail("must throw exception on execute");
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue