mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
implement [MH3] Arena of Glory and usage of ManaSpentDelayedTriggeredAbility (#12404)
This commit is contained in:
parent
0cd2fda764
commit
3e18b58cac
6 changed files with 200 additions and 3 deletions
117
Mage.Sets/src/mage/cards/a/ArenaOfGlory.java
Normal file
117
Mage.Sets/src/mage/cards/a/ArenaOfGlory.java
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
package mage.cards.a;
|
||||||
|
|
||||||
|
import mage.Mana;
|
||||||
|
import mage.abilities.common.EntersBattlefieldAbility;
|
||||||
|
import mage.abilities.common.delayed.ManaSpentDelayedTriggeredAbility;
|
||||||
|
import mage.abilities.condition.Condition;
|
||||||
|
import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition;
|
||||||
|
import mage.abilities.costs.common.ExertSourceCost;
|
||||||
|
import mage.abilities.costs.common.TapSourceCost;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.decorator.ConditionalOneShotEffect;
|
||||||
|
import mage.abilities.effects.common.AddContinuousEffectToGame;
|
||||||
|
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
||||||
|
import mage.abilities.effects.common.TapSourceEffect;
|
||||||
|
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
|
||||||
|
import mage.abilities.effects.mana.BasicManaEffect;
|
||||||
|
import mage.abilities.keyword.HasteAbility;
|
||||||
|
import mage.abilities.mana.RedManaAbility;
|
||||||
|
import mage.abilities.mana.SimpleManaAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.ComparisonType;
|
||||||
|
import mage.constants.Duration;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.filter.FilterPermanent;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.filter.common.FilterControlledPermanent;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.stack.Spell;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public final class ArenaOfGlory extends CardImpl {
|
||||||
|
|
||||||
|
private static final FilterPermanent filter = new FilterControlledPermanent(SubType.MOUNTAIN);
|
||||||
|
private static final Condition condition
|
||||||
|
= new PermanentsOnTheBattlefieldCondition(filter, ComparisonType.EQUAL_TO, 0);
|
||||||
|
|
||||||
|
public ArenaOfGlory(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.LAND}, "");
|
||||||
|
|
||||||
|
// Arena of Glory enters the battlefield tapped unless you control a Mountain.
|
||||||
|
this.addAbility(new EntersBattlefieldAbility(new ConditionalOneShotEffect(
|
||||||
|
new TapSourceEffect(), condition
|
||||||
|
), "tapped unless you control a Mountain"));
|
||||||
|
|
||||||
|
// {T}: Add {R}.
|
||||||
|
this.addAbility(new RedManaAbility());
|
||||||
|
|
||||||
|
// {R}, {T}, Exert Arena of Glory: Add {R}{R}. If that mana is spent on a creature spell, it gains haste until end of turn.
|
||||||
|
SimpleManaAbility ability = new SimpleManaAbility(
|
||||||
|
new BasicManaEffect(Mana.RedMana(2)),
|
||||||
|
new ManaCostsImpl<>("{R}")
|
||||||
|
);
|
||||||
|
ability.addEffect(new CreateDelayedTriggeredAbilityEffect(
|
||||||
|
new ArenaOfGloryDelayedTriggeredAbility()
|
||||||
|
));
|
||||||
|
ability.addCost(new TapSourceCost());
|
||||||
|
ability.addCost(new ExertSourceCost());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArenaOfGlory(final ArenaOfGlory card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArenaOfGlory copy() {
|
||||||
|
return new ArenaOfGlory(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ArenaOfGloryDelayedTriggeredAbility extends ManaSpentDelayedTriggeredAbility {
|
||||||
|
|
||||||
|
ArenaOfGloryDelayedTriggeredAbility() {
|
||||||
|
super(
|
||||||
|
new AddContinuousEffectToGame(
|
||||||
|
new GainAbilityTargetEffect(
|
||||||
|
HasteAbility.getInstance(), Duration.EndOfTurn,
|
||||||
|
"it gains haste until end of turn", true
|
||||||
|
)
|
||||||
|
),
|
||||||
|
StaticFilters.FILTER_SPELL_CREATURE
|
||||||
|
);
|
||||||
|
this.usesStack = false;
|
||||||
|
this.triggerOnlyOnce = false;
|
||||||
|
setTriggerPhrase("If that mana is spent on a creature spell, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArenaOfGloryDelayedTriggeredAbility(final ArenaOfGloryDelayedTriggeredAbility effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArenaOfGloryDelayedTriggeredAbility copy() {
|
||||||
|
return new ArenaOfGloryDelayedTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
if (!super.checkTrigger(event, game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||||
|
if (spell == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
getEffects().setTargetPointer(new FixedTarget(spell.getCard(), game));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -35,6 +35,7 @@ public final class ModernHorizons3 extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Annoyed Altisaur", 284, Rarity.UNCOMMON, mage.cards.a.AnnoyedAltisaur.class));
|
cards.add(new SetCardInfo("Annoyed Altisaur", 284, Rarity.UNCOMMON, mage.cards.a.AnnoyedAltisaur.class));
|
||||||
cards.add(new SetCardInfo("Arcbound Condor", 81, Rarity.UNCOMMON, mage.cards.a.ArcboundCondor.class));
|
cards.add(new SetCardInfo("Arcbound Condor", 81, Rarity.UNCOMMON, mage.cards.a.ArcboundCondor.class));
|
||||||
cards.add(new SetCardInfo("Archway of Innovation", 214, Rarity.RARE, mage.cards.a.ArchwayOfInnovation.class));
|
cards.add(new SetCardInfo("Archway of Innovation", 214, Rarity.RARE, mage.cards.a.ArchwayOfInnovation.class));
|
||||||
|
cards.add(new SetCardInfo("Arena of Glory", 215, Rarity.RARE, mage.cards.a.ArenaOfGlory.class));
|
||||||
cards.add(new SetCardInfo("Argent Dais", 20, Rarity.RARE, mage.cards.a.ArgentDais.class));
|
cards.add(new SetCardInfo("Argent Dais", 20, Rarity.RARE, mage.cards.a.ArgentDais.class));
|
||||||
cards.add(new SetCardInfo("Arna Kennerud, Skycaptain", 178, Rarity.MYTHIC, mage.cards.a.ArnaKennerudSkycaptain.class));
|
cards.add(new SetCardInfo("Arna Kennerud, Skycaptain", 178, Rarity.MYTHIC, mage.cards.a.ArnaKennerudSkycaptain.class));
|
||||||
cards.add(new SetCardInfo("Ashling, Flame Dancer", 115, Rarity.MYTHIC, mage.cards.a.AshlingFlameDancer.class));
|
cards.add(new SetCardInfo("Ashling, Flame Dancer", 115, Rarity.MYTHIC, mage.cards.a.AshlingFlameDancer.class));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.mage.test.cards.single.mh3;
|
||||||
|
|
||||||
|
import mage.abilities.keyword.HasteAbility;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class ArenaOfGloryTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.a.ArenaOfGlory Arena of Glory}
|
||||||
|
* Land
|
||||||
|
* Arena of Glory enters the battlefield tapped unless you control a Mountain.
|
||||||
|
* {T}: Add {R}.
|
||||||
|
* {R}, {T}, Exert Arena of Glory: Add {R}{R}. If that mana is spent on a creature spell, it gains haste until end of turn. (An exerted permanent won’t untap during your next untap step.)
|
||||||
|
*/
|
||||||
|
private static final String arena = "Arena of Glory";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_NormalManaNoHaste() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, "Dwarven Trader"); // vanilla for {R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, arena);
|
||||||
|
|
||||||
|
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", true);
|
||||||
|
checkAbility("Dwarven Trader doesn't have haste", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", HasteAbility.class, false);
|
||||||
|
|
||||||
|
setStopAt(5, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertTapped(arena, false);
|
||||||
|
assertPermanentCount(playerA, "Dwarven Trader", 1);
|
||||||
|
assertAbility(playerA, "Dwarven Trader", HasteAbility.getInstance(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_TwoCreatureHaste() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.HAND, playerA, "Dwarven Trader"); // vanilla for {R}
|
||||||
|
addCard(Zone.HAND, playerA, "Mons's Goblin Raiders"); // vanilla for {R}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, arena);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Mountain");
|
||||||
|
|
||||||
|
activateManaAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}");
|
||||||
|
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", true);
|
||||||
|
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mons's Goblin Raiders", true);
|
||||||
|
checkAbility("Dwarven Trader has haste", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader", HasteAbility.class, true);
|
||||||
|
checkAbility("Mons's Goblin Raiders has haste", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mons's Goblin Raiders", HasteAbility.class, true);
|
||||||
|
|
||||||
|
attack(3, playerA, "Dwarven Trader", playerB);
|
||||||
|
attack(3, playerA, "Mons's Goblin Raiders", playerB);
|
||||||
|
|
||||||
|
setStopAt(5, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertTapped(arena, true); // exerted
|
||||||
|
assertLife(playerB, 20 - 2);
|
||||||
|
assertPermanentCount(playerA, "Dwarven Trader", 1);
|
||||||
|
assertAbility(playerA, "Dwarven Trader", HasteAbility.getInstance(), false);
|
||||||
|
assertPermanentCount(playerA, "Mons's Goblin Raiders", 1);
|
||||||
|
assertAbility(playerA, "Mons's Goblin Raiders", HasteAbility.getInstance(), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -103,9 +103,10 @@ public class MageObjectReference implements Comparable<MageObjectReference>, Ser
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString() {
|
||||||
return "("+zoneChangeCounter+"|"+sourceId.toString().substring(0,3)+")";
|
return "(" + zoneChangeCounter + "|" + sourceId.toString().substring(0, 3) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getSourceId() {
|
public UUID getSourceId() {
|
||||||
return sourceId;
|
return sourceId;
|
||||||
}
|
}
|
||||||
|
|
@ -185,6 +186,14 @@ public class MageObjectReference implements Comparable<MageObjectReference>, Ser
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Spell getSpell(Game game) {
|
||||||
|
Spell spell = game.getSpell(sourceId);
|
||||||
|
if (spell != null && spell.getZoneChangeCounter(game) == zoneChangeCounter) {
|
||||||
|
return spell;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean zoneCounterIsCurrent(Game game) {
|
public boolean zoneCounterIsCurrent(Game game) {
|
||||||
return game.getState().getZoneChangeCounter(sourceId) == zoneChangeCounter;
|
return game.getState().getZoneChangeCounter(sourceId) == zoneChangeCounter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ public class ManaSpentDelayedTriggeredAbility extends DelayedTriggeredAbility {
|
||||||
setTriggerPhrase("When you spend this mana to cast " + filter.getMessage() + ", ");
|
setTriggerPhrase("When you spend this mana to cast " + filter.getMessage() + ", ");
|
||||||
}
|
}
|
||||||
|
|
||||||
private ManaSpentDelayedTriggeredAbility(final ManaSpentDelayedTriggeredAbility ability) {
|
protected ManaSpentDelayedTriggeredAbility(final ManaSpentDelayedTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.filter = ability.filter;
|
this.filter = ability.filter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ public class AddContinuousEffectToGame extends OneShotEffect {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
for (Effect effect : this.effects) {
|
for (Effect effect : this.effects) {
|
||||||
|
effect.setTargetPointer(this.getTargetPointer().copy());
|
||||||
game.addEffect((ContinuousEffect) effect, source);
|
game.addEffect((ContinuousEffect) effect, source);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue