implement [MH3] Dog Umbra ; fix [BRO] Mishra's Domination

This commit is contained in:
Susucre 2024-06-01 00:44:30 +02:00
parent f5c8fb1a4e
commit 81ef8da46e
7 changed files with 251 additions and 82 deletions

View file

@ -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);
}
}
}

View 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);
}
}

View file

@ -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)

View file

@ -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);
}
}
}

View file

@ -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));

View file

@ -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 cant 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);
}
}

View file

@ -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 cant 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);
}
}