forked from External/mage
implement [MH3] Dog Umbra ; fix [BRO] Mishra's Domination
This commit is contained in:
parent
f5c8fb1a4e
commit
81ef8da46e
7 changed files with 251 additions and 82 deletions
|
|
@ -4,15 +4,13 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.ReturnToHandSourceEffect;
|
||||
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
|
@ -36,10 +34,10 @@ public final class CageOfHands extends CardImpl {
|
|||
this.addAbility(ability);
|
||||
|
||||
// Enchanted creature can't attack or block.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CageOfHandsEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(new CantAttackBlockAttachedEffect(AttachmentType.AURA)));
|
||||
|
||||
// {1}{W}: Return Cage of Hands to its owner's hand.
|
||||
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandSourceEffect(true), new ManaCostsImpl<>("{1}{W}")));
|
||||
this.addAbility(new SimpleActivatedAbility(new ReturnToHandSourceEffect(true), new ManaCostsImpl<>("{1}{W}")));
|
||||
}
|
||||
|
||||
private CageOfHands(final CageOfHands card) {
|
||||
|
|
@ -50,37 +48,4 @@ public final class CageOfHands extends CardImpl {
|
|||
public CageOfHands copy() {
|
||||
return new CageOfHands(this);
|
||||
}
|
||||
}
|
||||
|
||||
class CageOfHandsEffect extends RestrictionEffect {
|
||||
|
||||
CageOfHandsEffect() {
|
||||
super(Duration.WhileOnBattlefield);
|
||||
staticText = "Enchanted creature can't attack or block";
|
||||
}
|
||||
|
||||
private CageOfHandsEffect(final CageOfHandsEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
return permanent.getAttachments().contains((source.getSourceId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttack(Game game, boolean canUseChooseDialogs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CageOfHandsEffect copy() {
|
||||
return new CageOfHandsEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
92
Mage.Sets/src/mage/cards/d/DogUmbra.java
Normal file
92
Mage.Sets/src/mage/cards/d/DogUmbra.java
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.decorator.ConditionalRestrictionEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilitySourceEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.abilities.keyword.FlashAbility;
|
||||
import mage.abilities.keyword.TotemArmorAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class DogUmbra extends CardImpl {
|
||||
|
||||
public DogUmbra(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}");
|
||||
|
||||
this.subtype.add(SubType.AURA);
|
||||
|
||||
// Flash
|
||||
this.addAbility(FlashAbility.getInstance());
|
||||
|
||||
// Enchant creature
|
||||
TargetPermanent auraTarget = new TargetCreaturePermanent();
|
||||
this.getSpellAbility().addTarget(auraTarget);
|
||||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
|
||||
this.addAbility(new EnchantAbility(auraTarget));
|
||||
|
||||
// As long as another player controls enchanted creature, it can't attack or block. Otherwise, Dog Umbra has umbra armor.
|
||||
Ability ability = new SimpleStaticAbility(new ConditionalRestrictionEffect(
|
||||
new CantAttackBlockAttachedEffect(AttachmentType.AURA),
|
||||
DogUmbraCondition.TRUE,
|
||||
"As long as another player controls enchanted creature, it can't attack or block."
|
||||
));
|
||||
ability.addEffect(new ConditionalContinuousEffect(
|
||||
new GainAbilitySourceEffect(new TotemArmorAbility()),
|
||||
DogUmbraCondition.FALSE,
|
||||
"Otherwise, Dog Umbra has umbra armor"
|
||||
));
|
||||
this.addAbility(ability);
|
||||
}
|
||||
|
||||
private DogUmbra(final DogUmbra card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DogUmbra copy() {
|
||||
return new DogUmbra(this);
|
||||
}
|
||||
}
|
||||
|
||||
enum DogUmbraCondition implements Condition {
|
||||
TRUE(true),
|
||||
FALSE(false);
|
||||
private final boolean value;
|
||||
|
||||
DogUmbraCondition(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return Optional
|
||||
.ofNullable(source.getSourcePermanentIfItStillExists(game))
|
||||
.map(Permanent::getAttachedTo)
|
||||
.map(game::getPermanentOrLKIBattlefield)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(source::isControlledBy)
|
||||
.orElse(false)
|
||||
.equals(!value);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,21 +6,21 @@ import mage.abilities.condition.Condition;
|
|||
import mage.abilities.decorator.ConditionalContinuousEffect;
|
||||
import mage.abilities.decorator.ConditionalRestrictionEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.combat.CantBlockSourceEffect;
|
||||
import mage.abilities.effects.common.combat.CantBlockAttachedEffect;
|
||||
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.AttachmentType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubType;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ public final class MishrasDomination extends CardImpl {
|
|||
"as long as you control enchanted creature, it gets +2/+2"
|
||||
));
|
||||
ability.addEffect(new ConditionalRestrictionEffect(
|
||||
new CantBlockSourceEffect(Duration.WhileOnBattlefield),
|
||||
new CantBlockAttachedEffect(AttachmentType.AURA),
|
||||
MishrasDominationCondition.FALSE, "otherwise, it can't block"
|
||||
));
|
||||
this.addAbility(ability);
|
||||
|
|
@ -75,7 +75,8 @@ enum MishrasDominationCondition implements Condition {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
return Optional
|
||||
.ofNullable(source.getSourcePermanentIfItStillExists(game))
|
||||
.filter(Objects::nonNull)
|
||||
.map(Permanent::getAttachedTo)
|
||||
.map(game::getPermanentOrLKIBattlefield)
|
||||
.map(Controllable::getControllerId)
|
||||
.map(source::isControlledBy)
|
||||
.orElse(false)
|
||||
|
|
|
|||
|
|
@ -3,15 +3,13 @@ package mage.cards.r;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.effects.RestrictionEffect;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.combat.CantAttackBlockAttachedEffect;
|
||||
import mage.abilities.keyword.EnchantAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
|
||||
|
|
@ -31,7 +29,7 @@ public final class RecumbentBliss extends CardImpl {
|
|||
this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment));
|
||||
Ability ability = new EnchantAbility(auraTarget);
|
||||
this.addAbility(ability);
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new RecumbentBlissEffect()));
|
||||
this.addAbility(new SimpleStaticAbility(new CantAttackBlockAttachedEffect(AttachmentType.AURA)));
|
||||
this.addAbility(new BeginningOfUpkeepTriggeredAbility(new GainLifeEffect(1), TargetController.YOU, true));
|
||||
}
|
||||
|
||||
|
|
@ -43,37 +41,4 @@ public final class RecumbentBliss extends CardImpl {
|
|||
public RecumbentBliss copy() {
|
||||
return new RecumbentBliss(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RecumbentBlissEffect extends RestrictionEffect {
|
||||
|
||||
RecumbentBlissEffect() {
|
||||
super(Duration.WhileOnBattlefield);
|
||||
staticText = "Enchanted creature can't attack or block";
|
||||
}
|
||||
|
||||
private RecumbentBlissEffect(final RecumbentBlissEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
return permanent.getAttachments().contains((source.getSourceId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAttack(Game game, boolean canUseChooseDialogs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBlock(Permanent attacker, Permanent blocker, Ability source, Game game, boolean canUseChooseDialogs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecumbentBlissEffect copy() {
|
||||
return new RecumbentBlissEffect(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -69,6 +69,7 @@ public final class ModernHorizons3 extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Devourer of Destiny", 2, Rarity.RARE, mage.cards.d.DevourerOfDestiny.class));
|
||||
cards.add(new SetCardInfo("Disciple of Freyalise", 250, Rarity.UNCOMMON, mage.cards.d.DiscipleOfFreyalise.class));
|
||||
cards.add(new SetCardInfo("Distinguished Conjurer", 264, Rarity.UNCOMMON, mage.cards.d.DistinguishedConjurer.class));
|
||||
cards.add(new SetCardInfo("Dog Umbra", 22, Rarity.COMMON, mage.cards.d.DogUmbra.class));
|
||||
cards.add(new SetCardInfo("Dreadmobile", 87, Rarity.UNCOMMON, mage.cards.d.Dreadmobile.class));
|
||||
cards.add(new SetCardInfo("Dreamdrinker Vampire", 88, Rarity.COMMON, mage.cards.d.DreamdrinkerVampire.class));
|
||||
cards.add(new SetCardInfo("Dreamtide Whale", 59, Rarity.RARE, mage.cards.d.DreamtideWhale.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
package org.mage.test.cards.single.bro;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class MishraDominationTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.m.MishrasDomination Mishra's Domination} {1}{R}
|
||||
* Enchantment — Aura
|
||||
* Enchant creature
|
||||
* As long as you control enchanted creature, it gets +2/+2. Otherwise, it can’t block.
|
||||
*/
|
||||
private static final String domination = "Mishra's Domination";
|
||||
|
||||
@Test
|
||||
public void test_Boost() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears");
|
||||
addCard(Zone.HAND, playerA, domination);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, domination, "Memnite");
|
||||
attack(2, playerB, "Grizzly Bears", playerA);
|
||||
block(2, playerA, "Memnite", "Grizzly Bears");
|
||||
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, "Memnite", 3, 3);
|
||||
assertGraveyardCount(playerB, "Grizzly Bears", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Threaten_Boosted() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears");
|
||||
addCard(Zone.HAND, playerA, domination);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||
addCard(Zone.HAND, playerA, "Threaten");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, domination, "Grizzly Bears", true);
|
||||
checkPT("no change in PT", 1, PhaseStep.BEGIN_COMBAT, playerB, "Grizzly Bears", 2, 2);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Threaten", "Grizzly Bears", true);
|
||||
checkPT("change in PT after control change", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", 4, 4);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CantBlock() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears");
|
||||
addCard(Zone.HAND, playerA, domination);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, domination, "Grizzly Bears");
|
||||
|
||||
checkPT("no change in PT", 1, PhaseStep.BEGIN_COMBAT, playerB, "Grizzly Bears", 2, 2);
|
||||
attack(1, playerA, "Memnite", playerB);
|
||||
block(1, playerB, "Grizzly Bears", "Memnite"); // invalid block
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertLife(playerB, 20 - 1);
|
||||
assertPowerToughness(playerA, "Memnite", 1, 1);
|
||||
assertPowerToughness(playerB, "Grizzly Bears", 2, 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package org.mage.test.cards.single.mh3;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class DogUmbraTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.d.DogUmbra Dog Umbra} {1}{W}
|
||||
* Flash
|
||||
* Enchant creature
|
||||
* As long as another player controls enchanted creature, it can’t attack or block. Otherwise, Dog Umbra has umbra armor.
|
||||
*/
|
||||
private static final String umbra = "Dog Umbra";
|
||||
|
||||
@Test
|
||||
public void test_Umbra() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.HAND, playerA, umbra);
|
||||
addCard(Zone.HAND, playerA, "Murder");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, umbra, "Memnite", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Murder", "Memnite");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Murder", 1);
|
||||
assertGraveyardCount(playerA, umbra, 1);
|
||||
assertGraveyardCount(playerA, "Memnite", 0);
|
||||
assertPermanentCount(playerA, "Memnite", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Not_Umbra() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Memnite");
|
||||
addCard(Zone.HAND, playerA, umbra);
|
||||
addCard(Zone.HAND, playerA, "Murder");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, umbra, "Memnite", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Murder", "Memnite");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Murder", 1);
|
||||
assertGraveyardCount(playerA, umbra, 1);
|
||||
assertGraveyardCount(playerB, "Memnite", 1);
|
||||
assertPermanentCount(playerB, "Memnite", 0);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue