mirror of
https://github.com/correl/mage.git
synced 2024-12-24 11:50:45 +00:00
Fixed that some AlternativeCostSourceAbilities had no sourceId set.
This commit is contained in:
parent
0a66f1fca0
commit
4050631807
9 changed files with 113 additions and 37 deletions
|
@ -70,7 +70,7 @@ class AlurenRuleEffect extends ContinuousEffectImpl {
|
|||
filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, 4));
|
||||
}
|
||||
|
||||
private static AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(null, SourceIsSpellCondition.instance, null, filter, true);
|
||||
private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(null, SourceIsSpellCondition.instance, null, filter, true);
|
||||
|
||||
public AlurenRuleEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
|
@ -86,6 +86,12 @@ class AlurenRuleEffect extends ContinuousEffectImpl {
|
|||
return new AlurenRuleEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||
super.init(source, game, activePlayerId);
|
||||
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
|
|
@ -83,17 +83,14 @@ class SpellWithManaCostLessThanOrEqualToCondition implements Condition {
|
|||
*/
|
||||
class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
|
||||
|
||||
private UUID sourceAsForetold;
|
||||
private boolean wasActivated;
|
||||
|
||||
AsForetoldAlternativeCost(UUID sourceAsForetold, int timeCounters) {
|
||||
AsForetoldAlternativeCost(int timeCounters) {
|
||||
super(new ManaCostsImpl("{0}"), new SpellWithManaCostLessThanOrEqualToCondition(timeCounters));
|
||||
this.sourceAsForetold = sourceAsForetold;
|
||||
}
|
||||
|
||||
private AsForetoldAlternativeCost(final AsForetoldAlternativeCost ability) {
|
||||
super(ability);
|
||||
this.sourceAsForetold = ability.sourceAsForetold;
|
||||
this.wasActivated = ability.wasActivated;
|
||||
}
|
||||
|
||||
|
@ -105,7 +102,7 @@ class AsForetoldAlternativeCost extends AlternativeCostSourceAbility {
|
|||
@Override
|
||||
public boolean askToActivateAlternativeCosts(Ability ability, Game game) {
|
||||
Player controller = game.getPlayer(ability.getControllerId());
|
||||
Permanent asForetold = game.getPermanent(sourceAsForetold);
|
||||
Permanent asForetold = game.getPermanent(getSourceId());
|
||||
if (controller != null
|
||||
&& asForetold != null) {
|
||||
if (controller.chooseUse(Outcome.Neutral, "Do you wish to use "
|
||||
|
@ -156,8 +153,9 @@ class AsForetoldAddAltCostEffect extends ContinuousEffectImpl {
|
|||
// If we haven't used it yet this turn, give the option of using the zero alternative cost
|
||||
if (wasItUsed == null) {
|
||||
int timeCounters = sourcePermanent.getCounters(game).getCount("time");
|
||||
controller.getAlternativeSourceCosts().add(
|
||||
new AsForetoldAlternativeCost(sourcePermanent.getId(), timeCounters));
|
||||
AsForetoldAlternativeCost alternateCostAbility = new AsForetoldAlternativeCost(timeCounters);
|
||||
alternateCostAbility.setSourceId(source.getSourceId());
|
||||
controller.getAlternativeSourceCosts().add(alternateCostAbility);
|
||||
}
|
||||
// Return true even if we didn't add the alt cost. We still applied the effect
|
||||
return true;
|
||||
|
|
|
@ -49,7 +49,7 @@ class DreamHallsEffect extends ContinuousEffectImpl {
|
|||
filter.add(new SharesColorWithSourcePredicate());
|
||||
}
|
||||
|
||||
static AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new DiscardCardCost(filter), SourceIsSpellCondition.instance);
|
||||
private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new DiscardCardCost(filter), SourceIsSpellCondition.instance);
|
||||
|
||||
public DreamHallsEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
|
@ -64,7 +64,13 @@ class DreamHallsEffect extends ContinuousEffectImpl {
|
|||
public DreamHallsEffect copy() {
|
||||
return new DreamHallsEffect(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||
super.init(source, game, activePlayerId);
|
||||
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
|
|
@ -60,7 +60,7 @@ class KentaroTheSmilingCatCastingEffect extends ContinuousEffectImpl {
|
|||
filterSamurai.add(SubType.SAMURAI.getPredicate());
|
||||
}
|
||||
|
||||
static final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(
|
||||
private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(
|
||||
SourceIsSpellCondition.instance, null, filterSamurai, true, new ColorlessConvertedManaCost());
|
||||
|
||||
public KentaroTheSmilingCatCastingEffect() {
|
||||
|
@ -77,6 +77,12 @@ class KentaroTheSmilingCatCastingEffect extends ContinuousEffectImpl {
|
|||
return new KentaroTheSmilingCatCastingEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||
super.init(source, game, activePlayerId);
|
||||
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
|
|
@ -48,7 +48,7 @@ class RooftopStormRuleEffect extends ContinuousEffectImpl {
|
|||
filter.add(CardType.CREATURE.getPredicate());
|
||||
}
|
||||
|
||||
static AlternativeCostSourceAbility alternativeCastingCostAbility
|
||||
private final AlternativeCostSourceAbility alternativeCastingCostAbility
|
||||
= new AlternativeCostSourceAbility(new ManaCostsImpl("{0}"), SourceIsSpellCondition.instance, null, filter, true);
|
||||
|
||||
public RooftopStormRuleEffect() {
|
||||
|
@ -65,6 +65,12 @@ class RooftopStormRuleEffect extends ContinuousEffectImpl {
|
|||
return new RooftopStormRuleEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||
super.init(source, game, activePlayerId);
|
||||
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
|
|
@ -192,16 +192,15 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
/**
|
||||
* Omniscience is not allowing me to cast spells for free. I'm playing a
|
||||
* Commander game against the Computer, if that helps.
|
||||
* <p>
|
||||
*
|
||||
* Edit: It's not letting me cast fused spells for free. Others seems to be
|
||||
* working.
|
||||
*/
|
||||
@Test
|
||||
@Ignore // targeting of fused/split spells not supported by testplayer
|
||||
public void testCastingFusedSpell() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||
|
@ -214,13 +213,18 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
*/
|
||||
addCard(Zone.HAND, playerA, "Far // Away");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "fused Far // Away", "Silvercoat Lion^targetPlayer=PlayerB");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "fused Far // Away");
|
||||
setChoice(playerA, "Yes"); // Cast without paying its mana cost?
|
||||
addTarget(playerA, "Silvercoat Lion");
|
||||
addTarget(playerA, playerB);
|
||||
playerB.addTarget("Pillarfield Ox");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertHandCount(playerA, 1);
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertHandCount(playerA, "Silvercoat Lion", 1);
|
||||
assertHandCount(playerB, 0);
|
||||
|
||||
assertGraveyardCount(playerA, "Far // Away", 1);
|
||||
|
@ -228,6 +232,7 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerB, "Pillarfield Ox", 0);
|
||||
assertGraveyardCount(playerB, "Pillarfield Ox", 1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If another effect (e.g. Future Sight) allows you to cast nonland cards
|
||||
|
@ -335,6 +340,47 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
assertLife(playerB, 20);
|
||||
}
|
||||
|
||||
// Not sure what the exact interaction is, but when Omniscience is on the field with Jodah,
|
||||
// if you say "no" to the Jodah cast option to get to the Omniscience option, then the game will initiate a rollback.
|
||||
|
||||
@Test
|
||||
public void test_OmniscienceAndJodah() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
|
||||
// Flying
|
||||
// You may pay WUBRG rather than pay the mana cost for spells that you cast.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Jodah, Archmage Eternal"); // Creature {1}{U}{R}{W} (4/3)
|
||||
|
||||
// You may cast nonland cards from your hand without paying their mana costs.
|
||||
addCard(Zone.HAND, playerA, "Omniscience"); // Enchantment {7}{U}{U}{U}
|
||||
|
||||
// Creature - 3/3 Swampwalk
|
||||
addCard(Zone.HAND, playerA, "Bog Wraith", 1); // Creature {3}{B} (3/3)
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Omniscience");
|
||||
setChoice(playerA, "Yes"); // Pay alternative costs? ({W}{U}{B}{R}{G})
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bog Wraith");
|
||||
// The order of the two alternate casting abilities is not fixed, so it's not clear which ability is asked for first
|
||||
setChoice(playerA, "No"); // Pay alternative costs? ({W}{U}{B}{R}{G})
|
||||
setChoice(playerA, "Yes"); // Cast without paying its mana cost?
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Omniscience", 1);
|
||||
assertPermanentCount(playerA, "Bog Wraith", 1);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJelevaCastingSavageBeatingFromExile() {
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import mage.players.Player;
|
|||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
import mage.MageObject;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
|
@ -135,7 +136,6 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
|
|||
} else {
|
||||
costChoiceText = alternativeCostsToCheck.isEmpty() ? "Cast without paying its mana cost?" : "Pay alternative costs? (" + alternativeCostsToCheck.getText() + ')';
|
||||
}
|
||||
|
||||
if (alternativeCostsToCheck.canPay(ability, ability.getSourceId(), ability.getControllerId(), game)
|
||||
&& player.chooseUse(Outcome.Benefit, costChoiceText, this, game)) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
|
|
|
@ -20,9 +20,8 @@ import java.util.UUID;
|
|||
|
||||
public class CastFromHandWithoutPayingManaCostEffect extends ContinuousEffectImpl {
|
||||
|
||||
private final FilterCard filter;
|
||||
private final boolean fromHand;
|
||||
|
||||
private final AlternativeCostSourceAbility alternativeCastingCostAbility;
|
||||
|
||||
public CastFromHandWithoutPayingManaCostEffect() {
|
||||
this(StaticFilters.FILTER_CARDS_NON_LAND, true);
|
||||
}
|
||||
|
@ -33,8 +32,13 @@ public class CastFromHandWithoutPayingManaCostEffect extends ContinuousEffectImp
|
|||
|
||||
public CastFromHandWithoutPayingManaCostEffect(FilterCard filter, boolean fromHand, Duration duration) {
|
||||
super(duration, Outcome.Detriment);
|
||||
this.filter = filter;
|
||||
this.fromHand = fromHand;
|
||||
Condition condition;
|
||||
if (fromHand) {
|
||||
condition = new CompoundCondition(SourceIsSpellCondition.instance, IsBeingCastFromHandCondition.instance);
|
||||
} else {
|
||||
condition = SourceIsSpellCondition.instance;
|
||||
}
|
||||
this.alternativeCastingCostAbility = new AlternativeCostSourceAbility(null, condition, null, filter, true);
|
||||
this.staticText = "You may cast " + filter.getMessage()
|
||||
+ (fromHand ? " from your hand" : "")
|
||||
+ " without paying their mana costs";
|
||||
|
@ -42,8 +46,7 @@ public class CastFromHandWithoutPayingManaCostEffect extends ContinuousEffectImp
|
|||
|
||||
private CastFromHandWithoutPayingManaCostEffect(final CastFromHandWithoutPayingManaCostEffect effect) {
|
||||
super(effect);
|
||||
this.filter = effect.filter;
|
||||
this.fromHand = effect.fromHand;
|
||||
this.alternativeCastingCostAbility = effect.alternativeCastingCostAbility;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,21 +54,19 @@ public class CastFromHandWithoutPayingManaCostEffect extends ContinuousEffectImp
|
|||
return new CastFromHandWithoutPayingManaCostEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||
super.init(source, game, activePlayerId);
|
||||
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Condition condition;
|
||||
if (fromHand) {
|
||||
condition = new CompoundCondition(SourceIsSpellCondition.instance, IsBeingCastFromHandCondition.instance);
|
||||
} else {
|
||||
condition = SourceIsSpellCondition.instance;
|
||||
}
|
||||
controller.getAlternativeSourceCosts().add(new AlternativeCostSourceAbility(
|
||||
null, condition, null, filter, true
|
||||
));
|
||||
controller.getAlternativeSourceCosts().add(alternativeCastingCostAbility);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,7 @@ enum IsBeingCastFromHandCondition implements Condition {
|
|||
}
|
||||
if (object instanceof Spell) { // needed to check if it can be cast by alternate cost
|
||||
Spell spell = (Spell) object;
|
||||
return spell.getFromZone() == Zone.HAND;
|
||||
return Zone.HAND.equals(spell.getFromZone());
|
||||
}
|
||||
if (object instanceof Card) { // needed for the check what's playable
|
||||
Card card = (Card) object;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
package mage.abilities.effects.common.continuous;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.common.SourceIsSpellCondition;
|
||||
import mage.abilities.costs.AlternativeCostSourceAbility;
|
||||
|
@ -19,7 +20,7 @@ import mage.players.Player;
|
|||
*/
|
||||
public class WUBRGInsteadEffect extends ContinuousEffectImpl {
|
||||
|
||||
static AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new ManaCostsImpl("{W}{U}{B}{R}{G}"), SourceIsSpellCondition.instance);
|
||||
private final AlternativeCostSourceAbility alternativeCastingCostAbility = new AlternativeCostSourceAbility(new ManaCostsImpl("{W}{U}{B}{R}{G}"), SourceIsSpellCondition.instance);
|
||||
|
||||
public WUBRGInsteadEffect() {
|
||||
super(Duration.WhileOnBattlefield, Outcome.Detriment);
|
||||
|
@ -35,6 +36,12 @@ public class WUBRGInsteadEffect extends ContinuousEffectImpl {
|
|||
return new WUBRGInsteadEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Ability source, Game game, UUID activePlayerId) {
|
||||
super.init(source, game, activePlayerId);
|
||||
alternativeCastingCostAbility.setSourceId(source.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
|
|
Loading…
Reference in a new issue