forked from External/mage
[LTR] Implement Forge Anew (#10777)
* implements Forge Anew with unit tests * fixes equip effect and adjusts test * fixes effect to only apply on controller's turns * changed test location to set * fixes comparison, fixes wording of text to match oracle text
This commit is contained in:
parent
178e408ac5
commit
040a9779b5
3 changed files with 192 additions and 0 deletions
147
Mage.Sets/src/mage/cards/f/ForgeAnew.java
Normal file
147
Mage.Sets/src/mage/cards/f/ForgeAnew.java
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
package mage.cards.f;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.MyTurnCondition;
|
||||
import mage.abilities.decorator.ConditionalAsThoughEffect;
|
||||
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
|
||||
import mage.abilities.effects.common.continuous.ActivateAbilitiesAnyTimeYouCouldCastInstantEffect;
|
||||
import mage.abilities.effects.common.cost.CostModificationEffectImpl;
|
||||
import mage.abilities.keyword.EquipAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xanderhall
|
||||
*/
|
||||
public class ForgeAnew extends CardImpl {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("Equipment card from your graveyard");
|
||||
|
||||
static {
|
||||
filter.add(SubType.EQUIPMENT.getPredicate());
|
||||
}
|
||||
|
||||
public ForgeAnew(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}");
|
||||
|
||||
// When Forge Anew enters the battlefield, return target Equipment card from your graveyard to the battlefield.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ReturnFromGraveyardToBattlefieldTargetEffect());
|
||||
ability.addTarget(new TargetCardInYourGraveyard(filter));
|
||||
this.addAbility(ability);
|
||||
|
||||
//As long as it’s your turn, you may activate equip abilities any time you could cast an instant.
|
||||
this.addAbility(new SimpleStaticAbility(new ConditionalAsThoughEffect(
|
||||
new ActivateAbilitiesAnyTimeYouCouldCastInstantEffect(EquipAbility.class, "equip abilities"), MyTurnCondition.instance
|
||||
).setText("as long as it's your turn, you may activate equip abilities any time you could cast an instant."))
|
||||
);
|
||||
|
||||
//You may pay {0} rather than pay the equip cost of the first equip ability you activate during each of your turns.
|
||||
this.addAbility(new SimpleStaticAbility(new ForgeAnewCostEffect()), new ForgeAnewWatcher());
|
||||
}
|
||||
private ForgeAnew(final ForgeAnew card) {
|
||||
super(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeAnew copy() {
|
||||
return new ForgeAnew(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ForgeAnewCostEffect extends CostModificationEffectImpl {
|
||||
|
||||
ForgeAnewCostEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.SET_COST);
|
||||
this.staticText = "you may pay {0} rather than pay the equip cost of the first equip ability you activate during each of your turns.";
|
||||
}
|
||||
|
||||
ForgeAnewCostEffect(final ForgeAnewCostEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
return abilityToModify instanceof EquipAbility
|
||||
&& source.isControlledBy(abilityToModify.getControllerId())
|
||||
&& game.getActivePlayerId().equals(source.getControllerId())
|
||||
&& !ForgeAnewWatcher.checkPlayer(abilityToModify.getControllerId(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source, Ability abilityToModify) {
|
||||
boolean applyReduce = false;
|
||||
if (game.inCheckPlayableState()) {
|
||||
// getPlayable use - apply all the time
|
||||
applyReduce = true;
|
||||
} else {
|
||||
// real use - ask the player
|
||||
Player controller = game.getPlayer(abilityToModify.getControllerId());
|
||||
if (controller != null
|
||||
&& controller.chooseUse(Outcome.PlayForFree,
|
||||
String.format("Pay {0} to equip instead %s?", abilityToModify.getManaCostsToPay().getText()), source, game)) {
|
||||
applyReduce = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (applyReduce) {
|
||||
abilityToModify.getCosts().clear();
|
||||
abilityToModify.getManaCostsToPay().clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForgeAnewCostEffect copy() {
|
||||
return new ForgeAnewCostEffect(this);
|
||||
}
|
||||
}
|
||||
|
||||
class ForgeAnewWatcher extends Watcher {
|
||||
|
||||
private final Set<UUID> equippedThisTurn = new HashSet<>();
|
||||
|
||||
ForgeAnewWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() != GameEvent.EventType.ACTIVATED_ABILITY) {
|
||||
return;
|
||||
}
|
||||
|
||||
StackObject object = game.getStack().getStackObject(event.getSourceId());
|
||||
|
||||
if (object != null && object.getStackAbility() instanceof EquipAbility) {
|
||||
equippedThisTurn.add(event.getPlayerId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
equippedThisTurn.clear();
|
||||
}
|
||||
|
||||
static boolean checkPlayer(UUID playerId, Game game) {
|
||||
ForgeAnewWatcher watcher = game.getState().getWatcher(ForgeAnewWatcher.class);
|
||||
return watcher != null && watcher.equippedThisTurn.contains(playerId);
|
||||
}
|
||||
}
|
||||
|
|
@ -99,6 +99,7 @@ public final class TheLordOfTheRingsTalesOfMiddleEarth extends ExpansionSet {
|
|||
cards.add(new SetCardInfo("Flowering of the White Tree", 15, Rarity.RARE, mage.cards.f.FloweringOfTheWhiteTree.class));
|
||||
cards.add(new SetCardInfo("Fog on the Barrow-Downs", 16, Rarity.COMMON, mage.cards.f.FogOnTheBarrowDowns.class));
|
||||
cards.add(new SetCardInfo("Foray of Orcs", 128, Rarity.UNCOMMON, mage.cards.f.ForayOfOrcs.class));
|
||||
cards.add(new SetCardInfo("Forge Anew", 17, Rarity.RARE, mage.cards.f.ForgeAnew.class));
|
||||
cards.add(new SetCardInfo("Forest", 270, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS));
|
||||
cards.add(new SetCardInfo("Friendly Rivalry", 204, Rarity.UNCOMMON, mage.cards.f.FriendlyRivalry.class));
|
||||
cards.add(new SetCardInfo("Frodo Baggins", 205, Rarity.UNCOMMON, mage.cards.f.FrodoBaggins.class));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package org.mage.test.cards.single.ltr;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
|
||||
/**
|
||||
* @author Xanderhall
|
||||
*/
|
||||
public class ForgeAnewTest extends CardTestPlayerBase {
|
||||
|
||||
static final String FORGE_ANEW = "Forge Anew";
|
||||
static final String EQUIPMENT = "Bronze Sword";
|
||||
static final String CREATURE = "Silvercoat Lion";
|
||||
|
||||
/**
|
||||
* Test implementation of card
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testForgeAnew() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, CREATURE, 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
|
||||
addCard(Zone.HAND, playerA, FORGE_ANEW, 1);
|
||||
addCard(Zone.GRAVEYARD, playerA, EQUIPMENT, 1);
|
||||
|
||||
// Test return from graveyard
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, FORGE_ANEW);
|
||||
addTarget(playerA, EQUIPMENT, 1);
|
||||
|
||||
// Test can equip at instant speed for 0 (all mana tapped)
|
||||
activateAbility(1, PhaseStep.END_COMBAT, playerA, "Equip {3}", CREATURE);
|
||||
setChoice(playerA, true); // Choose to equip for free
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
// Make sure it is attached
|
||||
assertIsAttachedTo(playerA, EQUIPMENT, CREATURE);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue