mirror of
https://github.com/magefree/mage.git
synced 2026-01-23 11:49:56 -08:00
Merge branch 'master' into refactor/multiple-names
This commit is contained in:
commit
f4c55dfc45
67 changed files with 1228 additions and 169 deletions
|
|
@ -1,6 +1,7 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -14,14 +15,21 @@ import mage.util.CardUtil;
|
|||
*/
|
||||
public class PayMoreToCastAsThoughtItHadFlashAbility extends SpellAbility {
|
||||
|
||||
private final ManaCosts costsToAdd;
|
||||
private final Cost costsToAdd;
|
||||
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility(Card card, ManaCosts<ManaCost> costsToAdd) {
|
||||
super(card.getSpellAbility().getManaCosts().copy(), card.getName() + " as though it had flash", Zone.HAND, SpellAbilityType.BASE_ALTERNATE);
|
||||
public PayMoreToCastAsThoughtItHadFlashAbility(Card card, Cost costsToAdd) {
|
||||
super(card.getSpellAbility().getManaCosts().copy(), card.getName(), Zone.HAND, SpellAbilityType.BASE_ALTERNATE);
|
||||
this.costsToAdd = costsToAdd;
|
||||
this.timing = TimingRule.INSTANT;
|
||||
this.setRuleAtTheTop(true);
|
||||
CardUtil.increaseCost(this, costsToAdd);
|
||||
|
||||
if(costsToAdd instanceof ManaCosts<?>) {
|
||||
ManaCosts<ManaCost> manaCosts = (ManaCosts<ManaCost>) costsToAdd;
|
||||
CardUtil.increaseCost(this, manaCosts);
|
||||
}
|
||||
else {
|
||||
this.addCost(costsToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
protected PayMoreToCastAsThoughtItHadFlashAbility(final PayMoreToCastAsThoughtItHadFlashAbility ability) {
|
||||
|
|
@ -38,10 +46,13 @@ public class PayMoreToCastAsThoughtItHadFlashAbility extends SpellAbility {
|
|||
public String getRule(boolean all) {
|
||||
return getRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "You may cast {this} as though it had flash if you pay " + costsToAdd.getText() + " more to cast it. <i>(You may cast it any time you could cast an instant.)</i>";
|
||||
if (costsToAdd instanceof ManaCosts) {
|
||||
return "You may cast {this} as though it had flash if you pay " + costsToAdd.getText() + " more to cast it. <i>(You may cast it any time you could cast an instant.)</i>";
|
||||
} else {
|
||||
return "You may cast {this} as though it had flash by " + costsToAdd.getText() + " in addition to paying its other costs.";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,8 @@ public class SpellCastAllTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (!filter.match(spell, getControllerId(), this, game)) {
|
||||
if (!filter.match(spell, getControllerId(), this, game)
|
||||
|| !game.getState().getPlayersInRange(getControllerId(), game, false).contains(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
getEffects().setValue("spellCast", spell);
|
||||
|
|
|
|||
|
|
@ -74,6 +74,8 @@ public interface ContinuousEffect extends Effect {
|
|||
|
||||
boolean isYourNextEndStep(Game game);
|
||||
|
||||
boolean isTheNextEndStep(Game game);
|
||||
|
||||
boolean isYourNextUpkeepStep(Game game);
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -56,9 +56,11 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
|
||||
// until your next turn or until end of your next turn
|
||||
private UUID startingControllerId; // player to check for turn duration (can't different with real controller ability)
|
||||
private UUID activePlayerId; // Player whose turn the effect started on
|
||||
private boolean startingTurnWasActive; // effect started during related players turn and related players turn was already active
|
||||
private int effectStartingOnTurn = 0; // turn the effect started
|
||||
private int effectStartingEndStep = 0;
|
||||
private int effectControllerStartingEndStep = 0;
|
||||
private int effectActivePlayerStartingEndStep = 0;
|
||||
private int nextTurnNumber = Integer.MAX_VALUE; // effect is waiting for a step during your next turn, we store it if found.
|
||||
// set to the turn number on your next turn.
|
||||
private int effectStartingStepNum = 0; // Some continuous are waiting for the next step of a kind.
|
||||
|
|
@ -93,7 +95,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
this.startingControllerId = effect.startingControllerId;
|
||||
this.startingTurnWasActive = effect.startingTurnWasActive;
|
||||
this.effectStartingOnTurn = effect.effectStartingOnTurn;
|
||||
this.effectStartingEndStep = effect.effectStartingEndStep;
|
||||
this.effectControllerStartingEndStep = effect.effectControllerStartingEndStep;
|
||||
this.dependencyTypes = effect.dependencyTypes;
|
||||
this.dependendToTypes = effect.dependendToTypes;
|
||||
this.characterDefining = effect.characterDefining;
|
||||
|
|
@ -251,10 +253,12 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
@Override
|
||||
public void setStartingControllerAndTurnNum(Game game, UUID startingController, UUID activePlayerId) {
|
||||
this.startingControllerId = startingController;
|
||||
this.activePlayerId = activePlayerId;
|
||||
this.startingTurnWasActive = activePlayerId != null
|
||||
&& activePlayerId.equals(startingController); // you can't use "game" for active player cause it's called from tests/cheat too
|
||||
this.effectStartingOnTurn = game.getTurnNum();
|
||||
this.effectStartingEndStep = EndStepCountWatcher.getCount(startingController, game);
|
||||
this.effectControllerStartingEndStep = EndStepCountWatcher.getCount(startingController, game);
|
||||
this.effectActivePlayerStartingEndStep = EndStepCountWatcher.getCount(activePlayerId, game);
|
||||
this.effectStartingStepNum = game.getState().getStepNum();
|
||||
}
|
||||
|
||||
|
|
@ -266,7 +270,12 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
|
||||
@Override
|
||||
public boolean isYourNextEndStep(Game game) {
|
||||
return EndStepCountWatcher.getCount(startingControllerId, game) > effectStartingEndStep;
|
||||
return EndStepCountWatcher.getCount(startingControllerId, game) > effectControllerStartingEndStep;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTheNextEndStep(Game game) {
|
||||
return EndStepCountWatcher.getCount(activePlayerId, game) > effectActivePlayerStartingEndStep;
|
||||
}
|
||||
|
||||
public boolean isEndCombatOfYourNextTurn(Game game) {
|
||||
|
|
@ -298,6 +307,7 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
case UntilYourNextTurn:
|
||||
case UntilEndOfYourNextTurn:
|
||||
case UntilYourNextEndStep:
|
||||
case UntilTheNextEndStep:
|
||||
case UntilEndCombatOfYourNextTurn:
|
||||
case UntilYourNextUpkeepStep:
|
||||
break;
|
||||
|
|
@ -342,6 +352,10 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
return this.isYourNextEndStep(game);
|
||||
}
|
||||
break;
|
||||
case UntilTheNextEndStep:
|
||||
if (player != null && player.isInGame()) {
|
||||
return this.isTheNextEndStep(game);
|
||||
}
|
||||
case UntilEndCombatOfYourNextTurn:
|
||||
if (player != null && player.isInGame()) {
|
||||
return this.isEndCombatOfYourNextTurn(game);
|
||||
|
|
|
|||
|
|
@ -156,6 +156,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
|
|||
case UntilEndOfYourNextTurn:
|
||||
case UntilEndCombatOfYourNextTurn:
|
||||
case UntilYourNextEndStep:
|
||||
case UntilTheNextEndStep:
|
||||
case UntilYourNextUpkeepStep:
|
||||
// until your turn effects continue until real turn reached, their used it's own inactive method
|
||||
// 514.2 Second, the following actions happen simultaneously: all damage marked on permanents
|
||||
|
|
|
|||
|
|
@ -18,21 +18,28 @@ public class IfAbilityHasResolvedXTimesEffect extends OneShotEffect {
|
|||
|
||||
private final int resolutionNumber;
|
||||
private final Effects effects;
|
||||
private final boolean orMore;
|
||||
|
||||
public IfAbilityHasResolvedXTimesEffect(int resolutionNumber, Effect effect) {
|
||||
this(effect.getOutcome(), resolutionNumber, effect);
|
||||
}
|
||||
|
||||
public IfAbilityHasResolvedXTimesEffect(Outcome outcome, int resolutionNumber, Effect... effects) {
|
||||
this(outcome, resolutionNumber, false, effects);
|
||||
}
|
||||
|
||||
public IfAbilityHasResolvedXTimesEffect(Outcome outcome, int resolutionNumber, boolean orMore, Effect... effects) {
|
||||
super(outcome);
|
||||
this.resolutionNumber = resolutionNumber;
|
||||
this.effects = new Effects(effects);
|
||||
this.orMore = orMore;
|
||||
}
|
||||
|
||||
private IfAbilityHasResolvedXTimesEffect(final IfAbilityHasResolvedXTimesEffect effect) {
|
||||
super(effect);
|
||||
this.resolutionNumber = effect.resolutionNumber;
|
||||
this.effects = effect.effects.copy();
|
||||
this.orMore = effect.orMore;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -42,7 +49,8 @@ public class IfAbilityHasResolvedXTimesEffect extends OneShotEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
if (AbilityResolvedWatcher.getResolutionCount(game, source) != resolutionNumber) {
|
||||
int resolutionCount = AbilityResolvedWatcher.getResolutionCount(game, source);
|
||||
if (resolutionCount < resolutionNumber || (!orMore && resolutionCount > resolutionNumber)) {
|
||||
return false;
|
||||
}
|
||||
boolean result = false;
|
||||
|
|
@ -62,6 +70,9 @@ public class IfAbilityHasResolvedXTimesEffect extends OneShotEffect {
|
|||
if (staticText != null && !staticText.isEmpty()) {
|
||||
return staticText;
|
||||
}
|
||||
if (orMore) {
|
||||
return "otherwise, " + effects.getText(mode);
|
||||
}
|
||||
return "if this is the " + CardUtil.numberToOrdinalText(resolutionNumber) +
|
||||
" time this ability has resolved this turn, " + effects.getText(mode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ public class EmergeAbility extends SpellAbility {
|
|||
Permanent creature = game.getPermanent(target.getFirstTarget());
|
||||
if (creature != null) {
|
||||
CardUtil.reduceCost(this, creature.getManaValue());
|
||||
if (super.activate(game, allowedIdentifiers, false)) {
|
||||
boolean reducedToZero = this.getManaCostsToPay().isEmpty();
|
||||
if (super.activate(game, allowedIdentifiers, reducedToZero)) {
|
||||
MageObjectReference mor = new MageObjectReference(creature, game);
|
||||
if (creature.sacrifice(this, game)) {
|
||||
this.setCostsTag(EMERGE_ACTIVATION_CREATURE_REFERENCE, mor); //Can access with LKI afterwards
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public class CardNameUtil {
|
|||
.replace("û", "u")
|
||||
.replace("í", "i")
|
||||
.replace("ï", "i")
|
||||
.replace("î", "i")
|
||||
.replace("â", "a")
|
||||
.replace("á", "a")
|
||||
.replace("à", "a")
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ public enum TokenRepository {
|
|||
public static final String XMAGE_IMAGE_NAME_NIGHT = "Night";
|
||||
public static final String XMAGE_IMAGE_NAME_THE_MONARCH = "The Monarch";
|
||||
public static final String XMAGE_IMAGE_NAME_RADIATION = "Radiation";
|
||||
public static final String XMAGE_IMAGE_NAME_THE_RING = "The Ring";
|
||||
public static final String XMAGE_IMAGE_NAME_HELPER_EMBLEM = "Helper Emblem";
|
||||
|
||||
private static final Logger logger = Logger.getLogger(TokenRepository.class);
|
||||
|
|
@ -306,6 +307,9 @@ public enum TokenRepository {
|
|||
// Radiation (for trigger)
|
||||
res.add(createXmageToken(XMAGE_IMAGE_NAME_RADIATION, 1, "https://api.scryfall.com/cards/tpip/22/en?format=image"));
|
||||
|
||||
// The Ring
|
||||
res.add(createXmageToken(XMAGE_IMAGE_NAME_THE_RING, 1, "https://api.scryfall.com/cards/tltr/H13/en?format=image"));
|
||||
|
||||
// Helper emblem (for global card hints)
|
||||
// use backface for it
|
||||
res.add(createXmageToken(XMAGE_IMAGE_NAME_HELPER_EMBLEM, 1, "https://upload.wikimedia.org/wikipedia/en/a/aa/Magic_the_gathering-card_back.jpg"));
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ public enum Duration {
|
|||
EndOfTurn("until end of turn", true, true),
|
||||
UntilYourNextTurn("until your next turn", true, true),
|
||||
UntilYourNextEndStep("until your next end step", true, true),
|
||||
UntilTheNextEndStep("until your next end step", true, true),
|
||||
UntilEndCombatOfYourNextTurn("until end of combat on your next turn", true, true),
|
||||
UntilYourNextUpkeepStep("until your next upkeep", true, true),
|
||||
UntilEndOfYourNextTurn("until the end of your next turn", true, true),
|
||||
|
|
|
|||
|
|
@ -583,11 +583,10 @@ public abstract class GameImpl implements Game {
|
|||
if (emblem != null) {
|
||||
return emblem;
|
||||
}
|
||||
|
||||
TheRingEmblem newEmblem = new TheRingEmblem(playerId);
|
||||
|
||||
// TODO: add image info
|
||||
|
||||
state.addCommandObject(newEmblem);
|
||||
|
||||
return newEmblem;
|
||||
}
|
||||
|
||||
|
|
@ -1966,16 +1965,13 @@ public abstract class GameImpl implements Game {
|
|||
@Override
|
||||
public void addEmblem(Emblem emblem, MageObject sourceObject, UUID toPlayerId) {
|
||||
Emblem newEmblem = emblem.copy();
|
||||
newEmblem.setSourceObject(sourceObject);
|
||||
newEmblem.setSourceObjectAndInitImage(sourceObject);
|
||||
newEmblem.setControllerId(toPlayerId);
|
||||
newEmblem.assignNewId();
|
||||
newEmblem.getAbilities().newId();
|
||||
for (Ability ability : newEmblem.getAbilities()) {
|
||||
ability.setSourceId(newEmblem.getId());
|
||||
}
|
||||
|
||||
// image info setup in setSourceObject
|
||||
|
||||
state.addCommandObject(newEmblem);
|
||||
}
|
||||
|
||||
|
|
@ -1997,17 +1993,15 @@ public abstract class GameImpl implements Game {
|
|||
}
|
||||
}
|
||||
Plane newPlane = plane.copy();
|
||||
newPlane.setSourceObject();
|
||||
newPlane.setSourceObjectAndInitImage();
|
||||
newPlane.setControllerId(toPlayerId);
|
||||
newPlane.assignNewId();
|
||||
newPlane.getAbilities().newId();
|
||||
for (Ability ability : newPlane.getAbilities()) {
|
||||
ability.setSourceId(newPlane.getId());
|
||||
}
|
||||
|
||||
// image info setup in setSourceObject
|
||||
|
||||
state.addCommandObject(newPlane);
|
||||
|
||||
informPlayers("You have planeswalked to " + newPlane.getLogName());
|
||||
|
||||
// Fire off the planeswalked event
|
||||
|
|
@ -2028,7 +2022,6 @@ public abstract class GameImpl implements Game {
|
|||
@Override
|
||||
public Dungeon addDungeon(Dungeon dungeon, UUID playerId) {
|
||||
dungeon.setControllerId(playerId);
|
||||
dungeon.setSourceObject();
|
||||
state.addCommandObject(dungeon);
|
||||
return dungeon;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1239,6 +1239,11 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.isPlaneChase = isPlaneChase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add object to command zone.
|
||||
* <p>
|
||||
* Warning, all object data must be initialized before adding, including image info
|
||||
*/
|
||||
public void addCommandObject(CommandObject commandObject) {
|
||||
getCommand().add(commandObject);
|
||||
setZone(commandObject.getId(), Zone.COMMAND);
|
||||
|
|
|
|||
|
|
@ -154,24 +154,35 @@ public class Dungeon extends CommandObjectImpl {
|
|||
}
|
||||
|
||||
public static Dungeon createDungeon(String name, boolean isNameMustExists) {
|
||||
Dungeon res;
|
||||
switch (name) {
|
||||
case "Tomb of Annihilation":
|
||||
return new TombOfAnnihilationDungeon();
|
||||
res = new TombOfAnnihilationDungeon();
|
||||
break;
|
||||
case "Lost Mine of Phandelver":
|
||||
return new LostMineOfPhandelverDungeon();
|
||||
res = new LostMineOfPhandelverDungeon();
|
||||
break;
|
||||
case "Dungeon of the Mad Mage":
|
||||
return new DungeonOfTheMadMageDungeon();
|
||||
res = new DungeonOfTheMadMageDungeon();
|
||||
break;
|
||||
default:
|
||||
if (isNameMustExists) {
|
||||
throw new UnsupportedOperationException("A dungeon should have been chosen");
|
||||
} else {
|
||||
return null;
|
||||
res = null;
|
||||
}
|
||||
}
|
||||
|
||||
// dungeon don't have source, so image data can be initialized immediately
|
||||
if (res != null) {
|
||||
res.setSourceObjectAndInitImage();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void setSourceObject() {
|
||||
// choose set code due source
|
||||
public void setSourceObjectAndInitImage() {
|
||||
// image
|
||||
TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForClass(this.getClass().getName(), null);
|
||||
if (foundInfo != null) {
|
||||
this.setExpansionSetCode(foundInfo.getSetCode());
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public abstract class Emblem extends CommandObjectImpl {
|
|||
return frameStyle;
|
||||
}
|
||||
|
||||
public void setSourceObject(MageObject sourceObject) {
|
||||
public void setSourceObjectAndInitImage(MageObject sourceObject) {
|
||||
this.sourceObject = sourceObject;
|
||||
|
||||
// choose set code due source
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public abstract class Plane extends CommandObjectImpl {
|
|||
return frameStyle;
|
||||
}
|
||||
|
||||
public void setSourceObject() {
|
||||
public void setSourceObjectAndInitImage() {
|
||||
this.sourceObject = null;
|
||||
|
||||
// choose set code due source
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public final class EmblemOfCard extends Emblem {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setSourceObject(MageObject sourceObject) {
|
||||
public void setSourceObjectAndInitImage(MageObject sourceObject) {
|
||||
this.sourceObject = sourceObject;
|
||||
// super method would try and fail to find the emblem image here
|
||||
// (not sure why that would be setSoureObject's job; we get our image during construction)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ public class RadiationEmblem extends Emblem {
|
|||
this.setImageFileName(""); // use default
|
||||
this.setImageNumber(foundInfo.getImageNumber());
|
||||
} else {
|
||||
// how-to fix: add emblem to the tokens-database TokenRepository->loadXmageTokens
|
||||
// how-to fix: add image to the tokens-database TokenRepository->loadXmageTokens
|
||||
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_RADIATION);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
|
|||
import mage.abilities.effects.common.DrawDiscardControllerEffect;
|
||||
import mage.abilities.effects.common.LoseLifeOpponentsEffect;
|
||||
import mage.abilities.effects.common.SacrificeTargetEffect;
|
||||
import mage.cards.repository.TokenInfo;
|
||||
import mage.cards.repository.TokenRepository;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
|
|
@ -41,6 +43,19 @@ public final class TheRingEmblem extends Emblem {
|
|||
public TheRingEmblem(UUID controllerId) {
|
||||
super("The Ring");
|
||||
this.setControllerId(controllerId);
|
||||
|
||||
// ring don't have source, so image can be initialized immediately
|
||||
TokenInfo foundInfo = TokenRepository.instance.findPreferredTokenInfoForXmage(TokenRepository.XMAGE_IMAGE_NAME_THE_RING, null);
|
||||
if (foundInfo != null) {
|
||||
this.setExpansionSetCode(foundInfo.getSetCode());
|
||||
this.setUsesVariousArt(false);
|
||||
this.setCardNumber("");
|
||||
this.setImageFileName(""); // use default
|
||||
this.setImageNumber(foundInfo.getImageNumber());
|
||||
} else {
|
||||
// how-to fix: add image to the tokens-database TokenRepository->loadXmageTokens
|
||||
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_THE_RING);
|
||||
}
|
||||
}
|
||||
|
||||
private TheRingEmblem(final TheRingEmblem card) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public class XmageHelperEmblem extends Emblem {
|
|||
this.setImageFileName(""); // use default
|
||||
this.setImageNumber(foundInfo.getImageNumber());
|
||||
} else {
|
||||
// how-to fix: add emblem to the tokens-database TokenRepository->loadXmageTokens
|
||||
// how-to fix: add image to the tokens-database TokenRepository->loadXmageTokens
|
||||
throw new IllegalArgumentException("Wrong code usage: can't find xmage token info for: " + TokenRepository.XMAGE_IMAGE_NAME_HELPER_EMBLEM);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,9 @@ public class SpellStack extends ArrayDeque<StackObject> {
|
|||
counteredObjectName = "Ability (" + stackObject.getStackAbility().getRule(targetSourceName) + ") of " + targetSourceName;
|
||||
}
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER, objectId, source, stackObject.getControllerId()))) {
|
||||
if (!(stackObject instanceof Spell)) { // spells are removed from stack by the card movement
|
||||
// spells are removed from stack by the card movement
|
||||
if (!(stackObject instanceof Spell)
|
||||
|| stackObject.isCopy()) { // !ensure that copies of stackobjects have their history recorded ie: Swan Song
|
||||
this.remove(stackObject, game);
|
||||
game.rememberLKI(Zone.STACK, stackObject);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1035,6 +1035,7 @@ public final class CardUtil {
|
|||
|| text.startsWith("any ")
|
||||
|| text.startsWith("{this} ")
|
||||
|| text.startsWith("your ")
|
||||
|| text.startsWith("their ")
|
||||
|| text.startsWith("one ")) {
|
||||
return text;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue