* Fixed some problems if a creature has multiple madness abilities.

This commit is contained in:
LevelX2 2016-08-09 13:14:29 +02:00
parent c563d6f701
commit c31bf97440
4 changed files with 100 additions and 10 deletions

View file

@ -27,6 +27,7 @@
*/ */
package mage.sets.shadowsoverinnistrad; package mage.sets.shadowsoverinnistrad;
import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -60,7 +61,18 @@ public class FalkenrathGorger extends CardImpl {
this.subtype.add("Berserker"); this.subtype.add("Berserker");
this.power = new MageInt(2); this.power = new MageInt(2);
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
/**
* 4/8/2016 Falkenrath Gorgers ability only applies while its on the
* battlefield. If you discard it, it wont give itself madness.
* 4/8/2016 If Falkenrath Gorger leaves the battlefield before the
* madness trigger has resolved for a Vampire card that gained madness
* with its ability, the madness ability will still let you cast that
* Vampire card for the appropriate cost even though it no longer has
* madness. 4/8/2016 If you discard a Vampire creature card that already
* has a madness ability, youll choose which madness ability exiles it.
* You may choose either the one it normally has or the one it gains
* from Falkenrath Gorger.
*/
// Each Vampire creature card you own that isn't on the battlefield has madness. Its madness cost is equal to its mana cost. // Each Vampire creature card you own that isn't on the battlefield has madness. Its madness cost is equal to its mana cost.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new FalkenrathGorgerEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new FalkenrathGorgerEffect()));
} }
@ -84,6 +96,8 @@ class FalkenrathGorgerEffect extends ContinuousEffectImpl {
} }
HashMap<UUID, MadnessAbility> madnessAbilities = new HashMap<>(); // reuse the same ability for the same object
public FalkenrathGorgerEffect() { public FalkenrathGorgerEffect() {
super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility); super(Duration.WhileOnBattlefield, Layer.AbilityAddingRemovingEffects_6, SubLayer.NA, Outcome.AddAbility);
this.staticText = "Each Vampire creature card you own that isn't on the battlefield has madness. Its madness cost is equal to its mana cost"; this.staticText = "Each Vampire creature card you own that isn't on the battlefield has madness. Its madness cost is equal to its mana cost";
@ -91,6 +105,7 @@ class FalkenrathGorgerEffect extends ContinuousEffectImpl {
public FalkenrathGorgerEffect(final FalkenrathGorgerEffect effect) { public FalkenrathGorgerEffect(final FalkenrathGorgerEffect effect) {
super(effect); super(effect);
this.madnessAbilities.putAll(effect.madnessAbilities);
} }
@Override @Override
@ -102,25 +117,37 @@ class FalkenrathGorgerEffect extends ContinuousEffectImpl {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
HashMap<UUID, MadnessAbility> usedMadnessAbilities = new HashMap<>();
// hand // hand
for (Card card : controller.getHand().getCards(filter, game)) { for (Card card : controller.getHand().getCards(filter, game)) {
game.getState().addOtherAbility(card, new MadnessAbility(card, card.getSpellAbility().getManaCosts())); addMadnessToCard(game, card, usedMadnessAbilities);
} }
// graveyard // graveyard
for (Card card : controller.getGraveyard().getCards(filter, game)) { for (Card card : controller.getGraveyard().getCards(filter, game)) {
game.getState().addOtherAbility(card, new MadnessAbility(card, card.getSpellAbility().getManaCosts())); addMadnessToCard(game, card, usedMadnessAbilities);
} }
// Exile // Exile
for (Card card : game.getExile().getAllCards(game)) { for (Card card : game.getExile().getAllCards(game)) {
if (filter.match(card, source.getSourceId(), controller.getId(), game)) { if (filter.match(card, source.getSourceId(), controller.getId(), game)) {
if (card.getOwnerId().equals(controller.getId())) { if (card.getOwnerId().equals(controller.getId())) {
game.getState().addOtherAbility(card, new MadnessAbility(card, card.getSpellAbility().getManaCosts())); addMadnessToCard(game, card, usedMadnessAbilities);
} }
} }
} }
madnessAbilities.clear();
madnessAbilities.putAll(usedMadnessAbilities);
return true; return true;
} }
return false; return false;
} }
private void addMadnessToCard(Game game, Card card, HashMap<UUID, MadnessAbility> usedMadnessAbilities) {
MadnessAbility ability = madnessAbilities.get(card.getId());
if (ability == null) {
ability = new MadnessAbility(card, card.getSpellAbility().getManaCosts());
}
game.getState().addOtherAbility(card, ability, false);
usedMadnessAbilities.put(card.getId(), ability);
}
} }

View file

@ -27,6 +27,7 @@
*/ */
package org.mage.test.cards.abilities.keywords; package org.mage.test.cards.abilities.keywords;
import mage.abilities.keyword.HasteAbility;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Test; import org.junit.Test;
@ -111,7 +112,7 @@ public class MadnessTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Falkenrath Gorger", 1); addCard(Zone.BATTLEFIELD, playerA, "Falkenrath Gorger", 1);
// Sacrifice a creature: Vampire Aristocrat gets +2/+2 until end of turn. // Sacrifice a creature: Vampire Aristocrat gets +2/+2 until end of turn.
addCard(Zone.HAND, playerA, "Vampire Aristocrat"); addCard(Zone.HAND, playerA, "Vampire Aristocrat"); // {2}{B}
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 6); addCard(Zone.BATTLEFIELD, playerB, "Swamp", 6);
// Target player discards two cards. If you cast this spell during your main phase, that player discards four cards instead. // Target player discards two cards. If you cast this spell during your main phase, that player discards four cards instead.
@ -157,4 +158,63 @@ public class MadnessTest extends CardTestPlayerBase {
} }
/**
* Falkenrath Gorger + Asylum Visitor (& probably any Vampire with printed
* Madness) + Olivia, Mobilized for War - Haste part of the triggered effect
* may not affect entering Vampire properly, please read further for more
* details.
*
* When I cast Falkenrath Gorger and then discarded Asylum Visitor with
* Olivia, Mobilized for War 's triggered ability, two Madness pop-ups
* appeared, I have used the first one, Asylum Visitor entered the
* battlefield, Olivia triggered again and I used the ability to give Asylum
* Visitor Haste and +1/+1. Then the second Madness trigger resolved for the
* Visitor and I have cancelled it (by choosing "No" at first pop-up, but
* from what I have tested, the choice at this point does not matter).
* Asylum Visitor lost Haste and was both visually and functionally affected
* by Summoning Sickness.
*
* I was able to avoid this issue by cancelling the first Madness pop-up and
* then using only the second one.
*/
@Test
public void testFalkenrathGorgerWithAsylumVisitor() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// Flying
// Whenever another creature enters the battlefield under your control, you may discard a card. If you do, put a +1/+1 counter on that creature,
// it gains haste until end of turn, and it becomes a Vampire in addition to its other types.
addCard(Zone.BATTLEFIELD, playerA, "Olivia, Mobilized for War", 1);
// Each Vampire creature card you own that isn't on the battlefield has madness. Its madness cost is equal to its mana cost.
addCard(Zone.HAND, playerA, "Falkenrath Gorger", 1); // Creature Vampire 2/1 {R}
// At the beginning of each player's upkeep, if that player has no cards in hand, you draw a card and you lose 1 life.
// Madness {1}{B}
addCard(Zone.HAND, playerA, "Asylum Visitor"); // Creature Vampire 3/1 {1}{B}
addCard(Zone.HAND, playerA, "Forest");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Falkenrath Gorger");
setChoice(playerA, "Yes"); // Discard a card and put a +1/+1 counter on that creature, it gains haste until end of turn, and it becomes a Vampire in addition to its other types?
setChoice(playerA, "Asylum Visitor");
setChoice(playerA, "Yes"); // When this card is exiled this way, you may cast it by paying {1}{B} instead of putting it into your graveyard.
setChoice(playerA, "Yes"); // Cast Asylum Visitor by madness?
setChoice(playerA, "Yes"); // Discard a card and put a +1/+1 counter on that creature, it gains haste until end of turn, and it becomes a Vampire in addition to its other types?
setChoice(playerA, "Forest");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Falkenrath Gorger", 1);
assertPermanentCount(playerA, "Asylum Visitor", 1);
assertPowerToughness(playerA, "Falkenrath Gorger", 3, 2);
assertAbility(playerA, "Falkenrath Gorger", HasteAbility.getInstance(), true);
assertPowerToughness(playerA, "Asylum Visitor", 4, 2);
assertAbility(playerA, "Asylum Visitor", HasteAbility.getInstance(), true);
assertGraveyardCount(playerA, "Forest", 1);
}
} }

View file

@ -54,6 +54,5 @@ public class GainControlAllEffect extends ContinuousEffectImpl {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Gain control of ").append(filter.getMessage()); sb.append("Gain control of ").append(filter.getMessage());
return sb.toString(); return sb.toString();
//return "Gain control of " + filter;
} }
} }

View file

@ -52,7 +52,7 @@ public class MadnessAbility extends StaticAbility {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public MadnessAbility(Card card, ManaCosts madnessCost) { public MadnessAbility(Card card, ManaCosts madnessCost) {
super(Zone.HAND, new MadnessReplacementEffect((ManaCosts<ManaCost>) madnessCost)); super(Zone.HAND, new MadnessReplacementEffect((ManaCosts<ManaCost>) madnessCost));
addSubAbility(new MadnessTriggeredAbility((ManaCosts<ManaCost>) madnessCost)); addSubAbility(new MadnessTriggeredAbility((ManaCosts<ManaCost>) madnessCost, getOriginalId()));
rule = "Madness " + madnessCost.getText() + " <i>(If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)</i>"; rule = "Madness " + madnessCost.getText() + " <i>(If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.)</i>";
} }
@ -105,7 +105,8 @@ class MadnessReplacementEffect extends ReplacementEffectImpl {
if (card != null) { if (card != null) {
if (controller.moveCardToExileWithInfo(card, source.getSourceId(), "Madness", source.getSourceId(), game, ((ZoneChangeEvent) event).getFromZone(), true)) { if (controller.moveCardToExileWithInfo(card, source.getSourceId(), "Madness", source.getSourceId(), game, ((ZoneChangeEvent) event).getFromZone(), true)) {
game.applyEffects(); // needed to add Madness ability to cards (e.g. by Falkenrath Gorger) game.applyEffects(); // needed to add Madness ability to cards (e.g. by Falkenrath Gorger)
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.MADNESS_CARD_EXILED, card.getId(), card.getId(), controller.getId())); GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.MADNESS_CARD_EXILED, card.getId(), source.getOriginalId(), controller.getId());
game.fireEvent(gameEvent);
} }
return true; return true;
} }
@ -134,14 +135,17 @@ class MadnessTriggeredAbility extends TriggeredAbilityImpl {
//This array holds the Id's of all of the cards that activated madness //This array holds the Id's of all of the cards that activated madness
private static ArrayList<UUID> activatedIds = new ArrayList<>(); private static ArrayList<UUID> activatedIds = new ArrayList<>();
private final UUID madnessOriginalId;
MadnessTriggeredAbility(ManaCosts<ManaCost> madnessCost) { MadnessTriggeredAbility(ManaCosts<ManaCost> madnessCost, UUID madnessOriginalId) {
super(Zone.EXILED, new MadnessCastEffect(madnessCost), true); super(Zone.EXILED, new MadnessCastEffect(madnessCost), true);
this.madnessOriginalId = madnessOriginalId;
this.setRuleVisible(false); this.setRuleVisible(false);
} }
MadnessTriggeredAbility(final MadnessTriggeredAbility ability) { MadnessTriggeredAbility(final MadnessTriggeredAbility ability) {
super(ability); super(ability);
this.madnessOriginalId = ability.madnessOriginalId;
} }
@Override @Override
@ -156,7 +160,7 @@ class MadnessTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
return event.getTargetId().equals(getSourceId()); return event.getSourceId().equals(madnessOriginalId); // Check that the event was from the connected replacement effect
} }
@Override @Override