fix cost reduction not controller specific for [MH3] It That Heralds the End and [MH3] Ral, Leyline Prodify

fix #12503
This commit is contained in:
Susucre 2024-06-22 14:47:47 +02:00
parent 073637257f
commit 64e08b49b1
7 changed files with 93 additions and 40 deletions

View file

@ -3,7 +3,7 @@ package mage.cards.i;
import mage.MageInt; import mage.MageInt;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
@ -40,7 +40,7 @@ public final class ItThatHeraldsTheEnd extends CardImpl {
this.toughness = new MageInt(2); this.toughness = new MageInt(2);
// Colorless spells you cast with mana value 7 or greater cost {1} less to cast. // Colorless spells you cast with mana value 7 or greater cost {1} less to cast.
this.addAbility(new SimpleStaticAbility(new SpellsCostReductionAllEffect(filter, 1))); this.addAbility(new SimpleStaticAbility(new SpellsCostReductionControllerEffect(filter, 1)));
// Other colorless creatures you control get +1/+1. // Other colorless creatures you control get +1/+1.
this.addAbility(new SimpleStaticAbility(new BoostControlledEffect( this.addAbility(new SimpleStaticAbility(new BoostControlledEffect(

View file

@ -1,33 +1,19 @@
package mage.cards.m; package mage.cards.m;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.RemoveAllCountersSourceCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CastSourceTriggeredAbility; import mage.abilities.effects.common.CastSourceTriggeredAbility;
import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.effects.common.cost.CostModificationEffectImpl;
import mage.abilities.effects.common.cost.SpellCostReductionForEachSourceEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect;
import mage.constants.*;
import mage.abilities.keyword.DevoidAbility;
import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.DeathtouchAbility;
import mage.abilities.keyword.DevoidAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.counters.CounterType; import mage.constants.*;
import mage.filter.FilterOpponent; import mage.filter.FilterOpponent;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterPlayer;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterPermanentOrPlayer; import mage.filter.common.FilterPermanentOrPlayer;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.filter.predicate.permanent.CounterAnyPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
@ -35,8 +21,9 @@ import mage.target.common.TargetPermanentOrPlayer;
import mage.util.CardUtil; import mage.util.CardUtil;
import mage.watchers.common.CastSpellLastTurnWatcher; import mage.watchers.common.CastSpellLastTurnWatcher;
import java.util.UUID;
/** /**
*
* @author grimreap124 * @author grimreap124
*/ */
public final class MutatedCultist extends CardImpl { public final class MutatedCultist extends CardImpl {
@ -49,7 +36,7 @@ public final class MutatedCultist extends CardImpl {
public MutatedCultist(UUID ownerId, CardSetInfo setInfo) { public MutatedCultist(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{B}");
this.subtype.add(SubType.ELDRAZI); this.subtype.add(SubType.ELDRAZI);
this.subtype.add(SubType.HORROR); this.subtype.add(SubType.HORROR);
this.power = new MageInt(1); this.power = new MageInt(1);
@ -119,7 +106,7 @@ class MutatedCultistSpellsCostReductionEffect extends CostModificationEffectImpl
int spellsCast; int spellsCast;
int reductionAmount; int reductionAmount;
public MutatedCultistSpellsCostReductionEffect(int reductionAmount) { public MutatedCultistSpellsCostReductionEffect(int reductionAmount) {
super(Duration.EndOfTurn, Outcome.Benefit, CostModificationType.REDUCE_COST); super(Duration.EndOfTurn, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.reductionAmount = reductionAmount; this.reductionAmount = reductionAmount;
@ -136,7 +123,7 @@ class MutatedCultistSpellsCostReductionEffect extends CostModificationEffectImpl
super.init(source, game); super.init(source, game);
CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class); CastSpellLastTurnWatcher watcher = game.getState().getWatcher(CastSpellLastTurnWatcher.class);
if (watcher != null) { if (watcher != null) {
spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId()); spellsCast = watcher.getAmountOfSpellsPlayerCastOnCurrentTurn(source.getControllerId());
} }
} }
@ -154,7 +141,7 @@ class MutatedCultistSpellsCostReductionEffect extends CostModificationEffectImpl
discard(); // only one use discard(); // only one use
return false; return false;
} }
} }
if (abilityToModify instanceof SpellAbility) { if (abilityToModify instanceof SpellAbility) {
return abilityToModify.isControlledBy(source.getControllerId()); return abilityToModify.isControlledBy(source.getControllerId());
} }

View file

@ -16,7 +16,7 @@ import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DamageMultiEffect; import mage.abilities.effects.common.DamageMultiEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.hint.ConditionHint; import mage.abilities.hint.ConditionHint;
import mage.abilities.hint.Hint; import mage.abilities.hint.Hint;
@ -119,7 +119,7 @@ class RalLeylineProdigyCostReductionEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
SpellsCostReductionAllEffect effect = new SpellsCostReductionAllEffect(filter, 1); SpellsCostReductionControllerEffect effect = new SpellsCostReductionControllerEffect(filter, 1);
effect.setDuration(Duration.UntilYourNextTurn); effect.setDuration(Duration.UntilYourNextTurn);
game.addEffect(effect, source); game.addEffect(effect, source);
return true; return true;

View file

@ -0,0 +1,46 @@
package org.mage.test.cards.single.mh3;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class ItThatHeraldsTheEndTest extends CardTestPlayerBase {
/**
* {@link mage.cards.i.ItThatHeraldsTheEnd It That Heralds the End} {1}{C}
* Creature Eldrazi Drone
* Colorless spells you cast with mana value 7 or greater cost {1} less to cast.
* Other colorless creatures you control get +1/+1.
* 2/2
*/
private static final String it = "It That Heralds the End";
@Test
public void test_Simple() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerA, it);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
addCard(Zone.BATTLEFIELD, playerB, "Forest", 7);
addCard(Zone.HAND, playerA, "Ebony Rhino");
addCard(Zone.HAND, playerB, "Ebony Rhino");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ebony Rhino");
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Ebony Rhino");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertTappedCount("Swamp", true, 6);
assertTappedCount("Forest", true, 7);
assertPermanentCount(playerA, "Ebony Rhino", 1);
assertPowerToughness(playerA, "Ebony Rhino", 5, 6);
assertPermanentCount(playerB, "Ebony Rhino", 1);
assertPowerToughness(playerB, "Ebony Rhino", 4, 5);
}
}

View file

@ -11,7 +11,7 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.common.*; import mage.abilities.effects.common.*;
import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect; import mage.abilities.effects.common.cost.SpellsCostIncreasingAllEffect;
import mage.abilities.effects.common.cost.SpellsCostReductionAllEffect; import mage.abilities.effects.common.cost.SpellsCostReductionControllerEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.cards.CardImpl; import mage.cards.CardImpl;
@ -31,7 +31,6 @@ import mage.server.managers.ConfigSettings;
import mage.server.util.ConfigFactory; import mage.server.util.ConfigFactory;
import mage.server.util.ConfigWrapper; import mage.server.util.ConfigWrapper;
import mage.server.util.PluginClassLoader; import mage.server.util.PluginClassLoader;
import mage.utils.SystemUtil;
import mage.server.util.config.GamePlugin; import mage.server.util.config.GamePlugin;
import mage.server.util.config.Plugin; import mage.server.util.config.Plugin;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
@ -40,6 +39,7 @@ import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import mage.util.Copier; import mage.util.Copier;
import mage.utils.SystemUtil;
import org.apache.log4j.Level; import org.apache.log4j.Level;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.junit.Assert; import org.junit.Assert;
@ -241,10 +241,18 @@ public abstract class MageTestPlayerBase {
* @param enable * @param enable
*/ */
protected void setStrictChooseMode(boolean enable) { protected void setStrictChooseMode(boolean enable) {
if (playerA != null) playerA.setChooseStrictMode(enable); if (playerA != null) {
if (playerB != null) playerB.setChooseStrictMode(enable); playerA.setChooseStrictMode(enable);
if (playerC != null) playerC.setChooseStrictMode(enable); }
if (playerD != null) playerD.setChooseStrictMode(enable); if (playerB != null) {
playerB.setChooseStrictMode(enable);
}
if (playerC != null) {
playerC.setChooseStrictMode(enable);
}
if (playerD != null) {
playerD.setChooseStrictMode(enable);
}
} }
protected void addCustomCardWithSpell(TestPlayer controllerPlayer, SpellAbility spellAbility, Ability extraAbility, CardType cardType) { protected void addCustomCardWithSpell(TestPlayer controllerPlayer, SpellAbility spellAbility, Ability extraAbility, CardType cardType) {
@ -319,7 +327,7 @@ public abstract class MageTestPlayerBase {
if (modificationAmount >= 0) { if (modificationAmount >= 0) {
effect = new SpellsCostIncreasingAllEffect(modificationAmount, StaticFilters.FILTER_CARD, TargetController.YOU); effect = new SpellsCostIncreasingAllEffect(modificationAmount, StaticFilters.FILTER_CARD, TargetController.YOU);
} else { } else {
effect = new SpellsCostReductionAllEffect(StaticFilters.FILTER_CARD, -1 * modificationAmount, false, true); effect = new SpellsCostReductionControllerEffect(StaticFilters.FILTER_CARD, -1 * modificationAmount, false);
} }
addCustomCardWithAbility( addCustomCardWithAbility(
@ -439,7 +447,9 @@ class CustomTestCard extends CardImpl {
abilitiesList.put(cardName, new AbilitiesImpl<>()); abilitiesList.put(cardName, new AbilitiesImpl<>());
} }
Abilities<Ability> oldAbilities = abilitiesList.get(cardName); Abilities<Ability> oldAbilities = abilitiesList.get(cardName);
if (ability != null) oldAbilities.add(ability); if (ability != null) {
oldAbilities.add(ability);
}
spellAbilitiesList.put(cardName, spellAbility); spellAbilitiesList.put(cardName, spellAbility);
} }

View file

@ -1,8 +1,5 @@
package mage.abilities.effects.common.cost; package mage.abilities.effects.common.cost;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
@ -16,11 +13,18 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* Reduce cost of spells from any controller.
*
* @author LevelX2 * @author LevelX2
*/ */
public class SpellsCostReductionAllEffect extends CostModificationEffectImpl { public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
private static final FilterCard defaultFilter = new FilterCard("Spells");
private final FilterCard filter; private final FilterCard filter;
private final int amount; private final int amount;
private final boolean upTo; private final boolean upTo;
@ -28,7 +32,7 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
private UUID controllerId; private UUID controllerId;
public SpellsCostReductionAllEffect(int amount) { public SpellsCostReductionAllEffect(int amount) {
this(new FilterCard("Spells"), amount); this(defaultFilter, amount);
} }
public SpellsCostReductionAllEffect(FilterCard filter, int amount) { public SpellsCostReductionAllEffect(FilterCard filter, int amount) {
@ -39,7 +43,10 @@ public class SpellsCostReductionAllEffect extends CostModificationEffectImpl {
this(filter, amount, upTo, false); this(filter, amount, upTo, false);
} }
public SpellsCostReductionAllEffect(FilterCard filter, int amount, boolean upTo, boolean onlyControlled) { /**
* Note to devs: If you need onlyControlled at true, use SpellsCostReductionControllerEffect instead.
*/
protected SpellsCostReductionAllEffect(FilterCard filter, int amount, boolean upTo, boolean onlyControlled) {
super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST); super(Duration.WhileOnBattlefield, Outcome.Benefit, CostModificationType.REDUCE_COST);
this.filter = filter; this.filter = filter;
this.amount = amount; this.amount = amount;

View file

@ -1,7 +1,5 @@
package mage.abilities.effects.common.cost; package mage.abilities.effects.common.cost;
import java.util.LinkedHashSet;
import java.util.Set;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -20,7 +18,12 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.LinkedHashSet;
import java.util.Set;
/** /**
* Reduces cost of spell for the controller of the effect.
*
* @author North * @author North
*/ */
public class SpellsCostReductionControllerEffect extends CostModificationEffectImpl { public class SpellsCostReductionControllerEffect extends CostModificationEffectImpl {