forked from External/mage
implement [MH3] Detective's Phoenix
This commit is contained in:
parent
a3b7bb785d
commit
faa868aa16
4 changed files with 243 additions and 1 deletions
104
Mage.Sets/src/mage/cards/d/DetectivesPhoenix.java
Normal file
104
Mage.Sets/src/mage/cards/d/DetectivesPhoenix.java
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.common.CollectEvidenceCost;
|
||||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
|
||||
import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect;
|
||||
import mage.abilities.keyword.BestowAbility;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.abilities.keyword.HasteAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public final class DetectivesPhoenix extends CardImpl {
|
||||
|
||||
public DetectivesPhoenix(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT, CardType.CREATURE}, "{2}{R}");
|
||||
|
||||
this.subtype.add(SubType.PHOENIX);
|
||||
this.power = new MageInt(2);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// Bestow--{R}, Collect evidence 6
|
||||
Ability ability = new BestowAbility(this, "{R}");
|
||||
ability.addCost(new CollectEvidenceCost(6));
|
||||
this.addAbility(ability);
|
||||
|
||||
// Flying
|
||||
this.addAbility(FlyingAbility.getInstance());
|
||||
|
||||
// Haste
|
||||
this.addAbility(HasteAbility.getInstance());
|
||||
|
||||
// Enchanted creature gets +2/+2 and has flying and haste.
|
||||
ability = new SimpleStaticAbility(new BoostEnchantedEffect(2, 2));
|
||||
ability.addEffect(
|
||||
new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA)
|
||||
.setText("and has flying")
|
||||
);
|
||||
ability.addEffect(
|
||||
new GainAbilityAttachedEffect(HasteAbility.getInstance(), AttachmentType.AURA)
|
||||
.setText("and haste")
|
||||
);
|
||||
this.addAbility(ability);
|
||||
|
||||
// You may cast Detective's Phoenix from your graveyard using its bestow ability.
|
||||
this.addAbility(new SimpleStaticAbility(Zone.ALL, new DetectivesPhoenixEffect()));
|
||||
}
|
||||
|
||||
private DetectivesPhoenix(final DetectivesPhoenix card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetectivesPhoenix copy() {
|
||||
return new DetectivesPhoenix(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to Tenacious Underdog
|
||||
class DetectivesPhoenixEffect extends AsThoughEffectImpl {
|
||||
|
||||
DetectivesPhoenixEffect() {
|
||||
super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfGame, Outcome.PutCreatureInPlay);
|
||||
staticText = "You may cast {this} from your graveyard using its bestow ability";
|
||||
}
|
||||
|
||||
private DetectivesPhoenixEffect(final DetectivesPhoenixEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetectivesPhoenixEffect copy() {
|
||||
return new DetectivesPhoenixEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID objectId, Ability affectedAbility, Ability source, Game game, UUID playerId) {
|
||||
return objectId.equals(source.getSourceId())
|
||||
&& source.isControlledBy(playerId)
|
||||
&& affectedAbility instanceof BestowAbility
|
||||
&& game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD
|
||||
&& game.getCard(source.getSourceId()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ public final class ModernHorizons3 extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Cursed Mirror", 279, Rarity.RARE, mage.cards.c.CursedMirror.class));
|
||||
cards.add(new SetCardInfo("Deep Analysis", 268, Rarity.UNCOMMON, mage.cards.d.DeepAnalysis.class));
|
||||
cards.add(new SetCardInfo("Deserted Temple", 301, Rarity.RARE, mage.cards.d.DesertedTemple.class));
|
||||
cards.add(new SetCardInfo("Detective's Phoenix", 116, Rarity.RARE, mage.cards.d.DetectivesPhoenix.class));
|
||||
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("Dreadmobile", 87, Rarity.UNCOMMON, mage.cards.d.Dreadmobile.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,126 @@
|
|||
package org.mage.test.cards.single.mh3;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author Susucr
|
||||
*/
|
||||
public class DetectivesPhoenixTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* {@link mage.cards.d.DetectivesPhoenix Detective's Phoenix} {2}{R}
|
||||
* Enchantment Creature — Phoenix
|
||||
* Bestow—{R}, Collect evidence 6. (To pay this bestow cost, pay {R} and exile cards with total mana value 6 or greater from your graveyard.)
|
||||
* Flying, haste
|
||||
* Enchanted creature gets +2/+2 and has flying and haste.
|
||||
* You may cast Detective's Phoenix from your graveyard using its bestow ability.
|
||||
* 2/2
|
||||
*/
|
||||
private static final String phoenix = "Detective's Phoenix";
|
||||
|
||||
@Test
|
||||
public void test_Cast_FromHand_Normal() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.HAND, playerA, phoenix);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix, true);
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix + " using bestow", false);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phoenix);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertTappedCount("Mountain", true, 3);
|
||||
assertPowerToughness(playerA, phoenix, 2, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Cast_FromHand_Bestow() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.HAND, playerA, phoenix);
|
||||
addCard(Zone.GRAVEYARD, playerA, "Grave Titan");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix, true);
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix + " using bestow", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phoenix + " using bestow", "Memnite");
|
||||
setChoice(playerA, "Grave Titan"); // pay for Collect Evidence.
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertTappedCount("Mountain", true, 1);
|
||||
assertExileCount("Grave Titan", 1);
|
||||
assertPowerToughness(playerA, "Memnite", 1 + 2, 1 + 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Cast_FromGraveyard_Normal_NotPossible() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.GRAVEYARD, playerA, phoenix);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix, false);
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix + " using bestow", false);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Cast_FromGraveyard_Bestow() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.GRAVEYARD, playerA, phoenix);
|
||||
addCard(Zone.GRAVEYARD, playerA, "Grave Titan");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix, true); // It is a prefix check, so sadly can not check that can't cast using non-bestow
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix + " using bestow", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phoenix + " using bestow", "Memnite");
|
||||
setChoice(playerA, "Grave Titan"); // pay for Collect Evidence.
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertTappedCount("Mountain", true, 1);
|
||||
assertExileCount("Grave Titan", 1);
|
||||
assertPowerToughness(playerA, "Memnite", 1 + 2, 1 + 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Cast_FromGraveyard_BestowPossible_NotRegular() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Memnite");
|
||||
addCard(Zone.GRAVEYARD, playerA, phoenix);
|
||||
addCard(Zone.GRAVEYARD, playerA, "Grave Titan");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix, true); // It is a prefix check, so sadly can not check that can't cast using non-bestow
|
||||
checkPlayableAbility("Can cast normal way", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast " + phoenix + " using bestow", true);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, phoenix, "Memnite");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
try {
|
||||
execute();
|
||||
Assert.fail("should have failed");
|
||||
} catch (Throwable e) {
|
||||
if (!e.getMessage().contains("Cast " + phoenix)) {
|
||||
Assert.fail("Should have thrown error about not being able to cast the Phoenix, but got:\n" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import mage.MageObject;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.abilities.effects.common.AttachEffect;
|
||||
|
|
@ -15,6 +16,7 @@ import mage.game.events.GameEvent.EventType;
|
|||
import mage.game.permanent.Permanent;
|
||||
import mage.target.TargetPermanent;
|
||||
import mage.target.common.TargetCreaturePermanent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
* 702.102. Bestow
|
||||
|
|
@ -109,7 +111,16 @@ public class BestowAbility extends SpellAbility {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Bestow " + getManaCostsToPay().getText() + " <i>(If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)</i>";
|
||||
StringBuilder sb = new StringBuilder("Bestow");
|
||||
Costs costs = getCosts();
|
||||
if (costs.size() > 0) {
|
||||
sb.append("—").append(getManaCostsToPay().getText()).append(", ");
|
||||
sb.append(CardUtil.getTextWithFirstCharUpperCase(costs.getText())).append('.');
|
||||
} else {
|
||||
sb.append(" ").append(getManaCostsToPay().getText());
|
||||
}
|
||||
sb.append(" <i>(If you cast this card for its bestow cost, it's an Aura spell with enchant creature. It becomes a creature again if it's not attached to a creature.)</i>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void becomeCreature(Permanent permanent, Game game) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue