mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
[DSK] Implement Unable to Scream (#13234)
* Introduced LoseAllAbilitiesAttachedEffect * Added unit tests for Unable to Scream
This commit is contained in:
parent
02599fbaa4
commit
0bcf5f9e03
4 changed files with 301 additions and 0 deletions
95
Mage.Sets/src/mage/cards/u/UnableToScream.java
Normal file
95
Mage.Sets/src/mage/cards/u/UnableToScream.java
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
package mage.cards.u;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.continuous.AddCardSubtypeAttachedEffect;
|
||||
import mage.abilities.effects.common.continuous.AddCardTypeAttachedEffect;
|
||||
import mage.abilities.effects.common.continuous.LoseAllAbilitiesAttachedEffect;
|
||||
import mage.abilities.effects.common.continuous.SetBasePowerToughnessEnchantedEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author markort147
|
||||
*/
|
||||
public final class UnableToScream extends CardImpl {
|
||||
|
||||
public UnableToScream(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}");
|
||||
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// Enchanted creature loses all abilities and is a Toy artifact creature with base power and toughness 0/2 in addition to its other types.
|
||||
Ability ability = new SimpleStaticAbility(new LoseAllAbilitiesAttachedEffect(AttachmentType.AURA));
|
||||
ability.addEffect(new AddCardSubtypeAttachedEffect(SubType.TOY, AttachmentType.AURA).setText(" and is a Toy"));
|
||||
ability.addEffect(new AddCardTypeAttachedEffect(CardType.ARTIFACT, AttachmentType.AURA).setText(" artifact creature"));
|
||||
ability.addEffect(new SetBasePowerToughnessEnchantedEffect(0, 2).setText(" with base power and toughness 0/2 in addition to its other types."));
|
||||
this.addAbility(ability);
|
||||
|
||||
// As long as enchanted creature is face down, it can't be turned face up.
|
||||
this.addAbility(new SimpleStaticAbility(new UnableToScreamPreventingEffect()));
|
||||
}
|
||||
|
||||
private UnableToScream(final UnableToScream card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnableToScream copy() {
|
||||
return new UnableToScream(this);
|
||||
}
|
||||
}
|
||||
|
||||
class UnableToScreamPreventingEffect extends ContinuousRuleModifyingEffectImpl {
|
||||
|
||||
UnableToScreamPreventingEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
setText("As long as enchanted creature is face down, it can't be turned face up.");
|
||||
}
|
||||
|
||||
private UnableToScreamPreventingEffect(final UnableToScreamPreventingEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType().equals(GameEvent.EventType.TURN_FACE_UP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
Permanent aura = game.getPermanent(source.getSourceId());
|
||||
if (aura == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Permanent creature = game.getPermanent(aura.getAttachedTo());
|
||||
if (creature == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return creature.isFaceDown(game) && event.getTargetId().equals(creature.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnableToScreamPreventingEffect copy() {
|
||||
return new UnableToScreamPreventingEffect(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -241,6 +241,7 @@ public final class DuskmournHouseOfHorror extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Twist Reality", 77, Rarity.COMMON, mage.cards.t.TwistReality.class));
|
||||
cards.add(new SetCardInfo("Twitching Doll", 201, Rarity.RARE, mage.cards.t.TwitchingDoll.class));
|
||||
cards.add(new SetCardInfo("Tyvar, the Pummeler", 202, Rarity.MYTHIC, mage.cards.t.TyvarThePummeler.class));
|
||||
cards.add(new SetCardInfo("Unable to Scream", 78, Rarity.COMMON, mage.cards.u.UnableToScream.class));
|
||||
cards.add(new SetCardInfo("Under the Skin", 203, Rarity.UNCOMMON, mage.cards.u.UnderTheSkin.class));
|
||||
cards.add(new SetCardInfo("Unidentified Hovership", 37, Rarity.RARE, mage.cards.u.UnidentifiedHovership.class));
|
||||
cards.add(new SetCardInfo("Unnerving Grasp", 80, Rarity.UNCOMMON, mage.cards.u.UnnervingGrasp.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,154 @@
|
|||
package org.mage.test.cards.single.dsk;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.mana.GreenManaAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.*;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author markort147
|
||||
*/
|
||||
public class UnableToScreamTest extends CardTestPlayerBase {
|
||||
|
||||
/*
|
||||
* Unable to Scream {U}
|
||||
* Enchantment - Aura
|
||||
* Enchant creature
|
||||
* Enchanted creature loses all abilities and is a Toy artifact creature with base power and toughness 0/2 in addition to its other types.
|
||||
* As long as enchanted creature is face down, it can't be turned face up.
|
||||
*/
|
||||
public static final String UNABLE_TO_SCREAM = "Unable to Scream";
|
||||
|
||||
/*
|
||||
* Appetite for the Unnatural {2}{G}
|
||||
* Instant
|
||||
* Destroy target artifact or enchantment. You gain 2 life.
|
||||
*/
|
||||
public static final String APPETITE_FOR_THE_UNNATURAL = "Appetite for the Unnatural";
|
||||
|
||||
|
||||
// Cast a spell that would turn the creature face up, but Unable to Scream negates the effect.
|
||||
// After removing Unable to Scream, cast the spell again and the effect applies correctly.
|
||||
@Test
|
||||
public void preventFromTurningFaceUpTest() {
|
||||
/*
|
||||
* Akroma, Angel of Fury {5}{R}{R}{R}
|
||||
* Creature - Legendary Angel
|
||||
* 6/6
|
||||
* Akroma, Angel of Fury can't be countered.
|
||||
* Flying
|
||||
* Trample
|
||||
* Protection from white and from blue.
|
||||
* {R}: Akroma, Angel of Fury gets +1/+0 until end of turn.
|
||||
* Morph {3}{R}{R}{R}
|
||||
*/
|
||||
final String akromaAngelOfFury = "Akroma, Angel of Fury";
|
||||
|
||||
/*
|
||||
* Break Open {1}{R}
|
||||
* Instant
|
||||
* Turn target face-down creature an opponent controls face up.
|
||||
*/
|
||||
final String breakOpen = "Break Open";
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerB, akromaAngelOfFury);
|
||||
addCard(Zone.HAND, playerB, APPETITE_FOR_THE_UNNATURAL);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 6);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
|
||||
|
||||
addCard(Zone.HAND, playerA, UNABLE_TO_SCREAM);
|
||||
addCard(Zone.HAND, playerA, breakOpen, 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
|
||||
// prepare the face down creature
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, akromaAngelOfFury + " using Morph");
|
||||
// attach Unable to Scream to it
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, UNABLE_TO_SCREAM, EmptyNames.FACE_DOWN_CREATURE.getTestCommand(), true);
|
||||
// cast a spell that would turn the creature face up
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, breakOpen, EmptyNames.FACE_DOWN_CREATURE.getTestCommand());
|
||||
|
||||
// the creature is still face down
|
||||
checkPermanentCount("Face down creature is on the battlefield", 3, PhaseStep.BEGIN_COMBAT, playerB, EmptyNames.FACE_DOWN_CREATURE.getTestCommand(), 1);
|
||||
checkPermanentCount("Akroma is not on the battlefield", 3, PhaseStep.BEGIN_COMBAT, playerB, akromaAngelOfFury, 0);
|
||||
|
||||
// destroy Unable to Scream
|
||||
castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, APPETITE_FOR_THE_UNNATURAL, UNABLE_TO_SCREAM);
|
||||
// cast a spell that would turn the creature face up
|
||||
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, breakOpen, EmptyNames.FACE_DOWN_CREATURE.getTestCommand());
|
||||
|
||||
// now the creature is turned face up
|
||||
checkPermanentCount("Face down creature is not on the battlefield", 5, PhaseStep.BEGIN_COMBAT, playerB, EmptyNames.FACE_DOWN_CREATURE.getTestCommand(), 0);
|
||||
checkPermanentCount("Akroma is on the battlefield", 5, PhaseStep.BEGIN_COMBAT, playerB, akromaAngelOfFury, 1);
|
||||
|
||||
setStopAt(5, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
}
|
||||
|
||||
// Unable to Scream changes type, subtype and base stats of a creature.
|
||||
// After removing Unable to Scream, the creature restores its type, subtype, and base stats.
|
||||
@Test
|
||||
public void becomesEffectTest() {
|
||||
/*
|
||||
* Llanowar Elves {G}
|
||||
* Creature - Elf Druid
|
||||
* 1/1
|
||||
* {T}: Add {G}.
|
||||
*/
|
||||
final String llanowarElves = "Llanowar Elves";
|
||||
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.HAND, playerB, APPETITE_FOR_THE_UNNATURAL);
|
||||
addCard(Zone.BATTLEFIELD, playerB, llanowarElves);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Forest", 3);
|
||||
|
||||
addCard(Zone.HAND, playerA, UNABLE_TO_SCREAM);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
|
||||
// attach Unable to Scream to the creature
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, UNABLE_TO_SCREAM, llanowarElves);
|
||||
|
||||
// the creature is an artifact creature, toy elf druid with base stats 0/2
|
||||
runCode("The creature is an artifact creature, toy elf druid with base stats 0/2", 1, PhaseStep.BEGIN_COMBAT, playerB,
|
||||
(info, player, game) -> {
|
||||
Card elves = game.getBattlefield().getAllActivePermanents().stream().filter(p -> p.getName().equals(llanowarElves)).findAny().orElse(null);
|
||||
Assert.assertNotNull("The creature must be on the battlefield", elves);
|
||||
Assert.assertEquals("The creature must have base power 0", 0, elves.getPower().getValue());
|
||||
Assert.assertEquals("The creature must have base toughness 2", 2, elves.getToughness().getValue());
|
||||
Assert.assertTrue("The creature must have lost its abilities", elves.getAbilities(game).isEmpty());
|
||||
Assert.assertEquals("The creature must be an artifact creature", new HashSet<>(Arrays.asList(CardType.ARTIFACT, CardType.CREATURE)), new HashSet<>(elves.getCardType(game)));
|
||||
Assert.assertEquals("The creature must be a Toy Elf Druid", new HashSet<>(Arrays.asList(SubType.TOY, SubType.ELF, SubType.DRUID)), new HashSet<>(elves.getSubtype(game)));
|
||||
}
|
||||
);
|
||||
|
||||
// destroy Unable to Scream
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, APPETITE_FOR_THE_UNNATURAL, UNABLE_TO_SCREAM);
|
||||
|
||||
// the creature is a creature, elf druid with base stats 1/1
|
||||
runCode("The creature is creature, toy elf druid with base stats 1/1", 2, PhaseStep.BEGIN_COMBAT, playerB,
|
||||
(info, player, game) -> {
|
||||
Card elves = game.getBattlefield().getAllActivePermanents().stream().filter(p -> p.getName().equals(llanowarElves)).findAny().orElse(null);
|
||||
Assert.assertNotNull("The creature must be on the battlefield", elves);
|
||||
Assert.assertEquals("The creature must have base power 1", 1, elves.getPower().getValue());
|
||||
Assert.assertEquals("The creature must have base toughness 1", 1, elves.getToughness().getValue());
|
||||
Assert.assertTrue("The creature must have restored its abilities", elves.getAbilities(game).stream().map(Ability::getClass).collect(Collectors.toList()).contains(GreenManaAbility.class));
|
||||
Assert.assertEquals("The creature must be just a creature", Collections.singleton(CardType.CREATURE), new HashSet<>(elves.getCardType(game)));
|
||||
Assert.assertEquals("The creature must be an Elf Druid", new HashSet<>(Arrays.asList(SubType.ELF, SubType.DRUID)), new HashSet<>(elves.getSubtype(game)));
|
||||
}
|
||||
);
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
/**
|
||||
* @author markort147
|
||||
*/
|
||||
public class LoseAllAbilitiesAttachedEffect extends ContinuousEffectImpl {
|
||||
|
||||
protected AttachmentType attachmentType;
|
||||
|
||||
public LoseAllAbilitiesAttachedEffect(AttachmentType attachmentType) {
|
||||
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.LoseAbility);
|
||||
this.attachmentType = attachmentType;
|
||||
setText();
|
||||
}
|
||||
|
||||
protected LoseAllAbilitiesAttachedEffect(final LoseAllAbilitiesAttachedEffect effect) {
|
||||
super(effect);
|
||||
this.attachmentType = effect.attachmentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LoseAllAbilitiesAttachedEffect copy() {
|
||||
return new LoseAllAbilitiesAttachedEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent equipment = game.getPermanent(source.getSourceId());
|
||||
if (equipment != null && equipment.getAttachedTo() != null) {
|
||||
Permanent creature = game.getPermanent(equipment.getAttachedTo());
|
||||
if (creature != null) {
|
||||
creature.removeAllAbilities(source.getSourceId(), game);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void setText() {
|
||||
staticText = attachmentType.verb() + " creature loses all abilities";
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue