mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
* Fixed some problems if a creature has multiple madness abilities.
This commit is contained in:
parent
c563d6f701
commit
c31bf97440
4 changed files with 100 additions and 10 deletions
|
@ -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 Gorger’s ability only applies while it’s on the
|
||||||
|
* battlefield. If you discard it, it won’t 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, you’ll 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue