forked from External/mage
* Added logic to check if a card had a triggered ability in the graveyard if it was moved from graveyard to a hidden zone. Because if not, the ability does not trigger.
This commit is contained in:
parent
9110f70e2d
commit
ebdba3c57e
7 changed files with 173 additions and 32 deletions
|
|
@ -86,4 +86,79 @@ public class LoosingAbilitiesTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
assertPermanentCount(playerB, "Gravecrawler", 1);
|
assertPermanentCount(playerB, "Gravecrawler", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yixlid Jailer works incorrectly with reanimation spelss - I cast Unearth
|
||||||
|
* targeting Seasoned Pyromancer with a Yixlid Jailer in play, but didnt get
|
||||||
|
* the Pyromancer's ETB trigger. This is a bug as Jailer only affaects cards
|
||||||
|
* when they are on the battle field
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testYixlidJailerAndETBEffects() {
|
||||||
|
// Cards in graveyards lose all abilities.
|
||||||
|
addCard(Zone.HAND, playerA, "Yixlid Jailer"); // Creature 2/1 - {1}{B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
|
||||||
|
// When Seasoned Pyromancer enters the battlefield, discard two cards, then draw two cards. For each nonland card discarded this way, create a 1/1 red Elemental creature token.
|
||||||
|
// {3}{R}{R}, Exile Seasoned Pyromancer from your graveyard: Create two 1/1 red Elemental creature tokens.
|
||||||
|
addCard(Zone.GRAVEYARD, playerB, "Seasoned Pyromancer");
|
||||||
|
addCard(Zone.HAND, playerB, "Lightning Bolt", 2);
|
||||||
|
// Return target creature card with converted mana cost 3 or less from your graveyard to the battlefield.
|
||||||
|
// Cycling {2}
|
||||||
|
addCard(Zone.HAND, playerB, "Unearth", 1); // Sorcery {B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 1);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer");
|
||||||
|
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Unearth");
|
||||||
|
setChoice(playerB, "Lightning Bolt^Lightning Bolt");
|
||||||
|
|
||||||
|
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Yixlid Jailer", 1);
|
||||||
|
|
||||||
|
assertPermanentCount(playerB, "Seasoned Pyromancer", 1);
|
||||||
|
|
||||||
|
assertGraveyardCount(playerB, "Unearth", 1);
|
||||||
|
assertGraveyardCount(playerB, "Lightning Bolt", 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If an ability triggers when the object that has it is put into a hidden
|
||||||
|
* zone from a graveyard, that ability triggers from the graveyard, (such as
|
||||||
|
* Golgari Brownscale), Yixlid Jailer will prevent that ability from
|
||||||
|
* triggering. (2007-05-01)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testYixlidJailerAndPutIntoHandEffect() {
|
||||||
|
// Cards in graveyards lose all abilities.
|
||||||
|
addCard(Zone.HAND, playerA, "Yixlid Jailer"); // Creature 2/1 - {1}{B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||||
|
|
||||||
|
// When Golgari Brownscale is put into your hand from your graveyard, you gain 2 life.
|
||||||
|
// Dredge 2 (If you would draw a card, instead you may put exactly X cards from the top of
|
||||||
|
// your library into your graveyard. If you do, return this card from your
|
||||||
|
// graveyard to your hand. Otherwise, draw a card. )
|
||||||
|
addCard(Zone.GRAVEYARD, playerB, "Golgari Brownscale", 1); // Sorcery {B}
|
||||||
|
// Return target creature card from your graveyard to your hand. If it’s a Zombie card, draw a card.
|
||||||
|
addCard(Zone.HAND, playerB, "Cemetery Recruitment", 1); // Sorcery {1}{B}
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Yixlid Jailer");
|
||||||
|
|
||||||
|
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Cemetery Recruitment");
|
||||||
|
|
||||||
|
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, "Yixlid Jailer", 1);
|
||||||
|
assertHandCount(playerB, "Golgari Brownscale", 1);
|
||||||
|
assertGraveyardCount(playerB, "Cemetery Recruitment", 1);
|
||||||
|
|
||||||
|
assertLife(playerB, 20); // The trigger of Golgari Brownscale does not work because of Yixlid Jailer
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package mage.abilities;
|
package mage.abilities;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.effects.Effect;
|
import mage.abilities.effects.Effect;
|
||||||
import mage.constants.AbilityType;
|
import mage.constants.AbilityType;
|
||||||
|
|
@ -10,9 +12,7 @@ import mage.game.events.GameEvent;
|
||||||
import mage.game.events.GameEvent.EventType;
|
import mage.game.events.GameEvent.EventType;
|
||||||
import mage.game.events.ZoneChangeEvent;
|
import mage.game.events.ZoneChangeEvent;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.util.CardUtil;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author BetaSteward_at_googlemail.com
|
* @author BetaSteward_at_googlemail.com
|
||||||
|
|
@ -158,6 +158,17 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
||||||
if (event != null && event.getTargetId() != null && event.getTargetId().equals(getSourceId())) {
|
if (event != null && event.getTargetId() != null && event.getTargetId().equals(getSourceId())) {
|
||||||
switch (event.getType()) {
|
switch (event.getType()) {
|
||||||
case ZONE_CHANGE:
|
case ZONE_CHANGE:
|
||||||
|
ZoneChangeEvent zce = (ZoneChangeEvent) event;
|
||||||
|
if (event.getTargetId().equals(getSourceId()) && !zce.getToZone().isPublicZone()) {
|
||||||
|
// If an ability triggers when the object that has it is put into a hidden zone from a graveyard,
|
||||||
|
// that ability triggers from the graveyard, (such as Golgari Brownscale),
|
||||||
|
// Yixlid Jailer will prevent that ability from triggering.
|
||||||
|
if (zce.getFromZone().match(Zone.GRAVEYARD)) {
|
||||||
|
if (!CardUtil.cardHadAbility(this, game.getLastKnownInformationCard(getSourceId(), zce.getFromZone()), getSourceId(), game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
case DESTROYED_PERMANENT:
|
case DESTROYED_PERMANENT:
|
||||||
if (isLeavesTheBattlefieldTrigger()) {
|
if (isLeavesTheBattlefieldTrigger()) {
|
||||||
if (event.getType() == EventType.DESTROYED_PERMANENT) {
|
if (event.getType() == EventType.DESTROYED_PERMANENT) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
package mage.abilities.common;
|
package mage.abilities.common;
|
||||||
|
|
||||||
import mage.abilities.TriggeredAbilityImpl;
|
import mage.abilities.TriggeredAbilityImpl;
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ class DredgeEffect extends ReplacementEffectImpl {
|
||||||
public DredgeEffect(int value) {
|
public DredgeEffect(int value) {
|
||||||
super(Duration.WhileInGraveyard, Outcome.AIDontUseIt);
|
super(Duration.WhileInGraveyard, Outcome.AIDontUseIt);
|
||||||
this.amount = value;
|
this.amount = value;
|
||||||
this.staticText = new StringBuilder("Dredge ").append(Integer.toString(value)).append(" <i>(If you would draw a card, instead you may put exactly ").append(value).append(" card(s) from the top of your library into your graveyard. If you do, return this card from your graveyard to your hand. Otherwise, draw a card.)</i>").toString();
|
this.staticText = ("Dredge ") + Integer.toString(value) + " <i>(If you would draw a card, instead you may put exactly "
|
||||||
|
+ value + " card(s) from the top of your library into your graveyard. If you do, return this card from "
|
||||||
|
+ "your graveyard to your hand. Otherwise, draw a card.)</i>";
|
||||||
}
|
}
|
||||||
|
|
||||||
public DredgeEffect(final DredgeEffect effect) {
|
public DredgeEffect(final DredgeEffect effect) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
package mage.game;
|
package mage.game;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import mage.MageItem;
|
import mage.MageItem;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
|
@ -41,10 +44,6 @@ import mage.players.Players;
|
||||||
import mage.util.MessageToClient;
|
import mage.util.MessageToClient;
|
||||||
import mage.util.functions.ApplyToPermanent;
|
import mage.util.functions.ApplyToPermanent;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public interface Game extends MageItem, Serializable {
|
public interface Game extends MageItem, Serializable {
|
||||||
|
|
||||||
MatchType getGameType();
|
MatchType getGameType();
|
||||||
|
|
@ -208,6 +207,8 @@ public interface Game extends MageItem, Serializable {
|
||||||
|
|
||||||
MageObject getLastKnownInformation(UUID objectId, Zone zone);
|
MageObject getLastKnownInformation(UUID objectId, Zone zone);
|
||||||
|
|
||||||
|
CardState getLastKnownInformationCard(UUID objectId, Zone zone);
|
||||||
|
|
||||||
MageObject getLastKnownInformation(UUID objectId, Zone zone, int zoneChangeCounter);
|
MageObject getLastKnownInformation(UUID objectId, Zone zone, int zoneChangeCounter);
|
||||||
|
|
||||||
boolean getShortLivingLKI(UUID objectId, Zone zone);
|
boolean getShortLivingLKI(UUID objectId, Zone zone);
|
||||||
|
|
@ -298,9 +299,9 @@ public interface Game extends MageItem, Serializable {
|
||||||
/**
|
/**
|
||||||
* Creates and fires an damage prevention event
|
* Creates and fires an damage prevention event
|
||||||
*
|
*
|
||||||
* @param damageEvent damage event that will be replaced (instanceof check
|
* @param damageEvent damage event that will be replaced (instanceof check
|
||||||
* will be done)
|
* will be done)
|
||||||
* @param source ability that's the source of the prevention effect
|
* @param source ability that's the source of the prevention effect
|
||||||
* @param game
|
* @param game
|
||||||
* @param amountToPrevent max preventable amount
|
* @param amountToPrevent max preventable amount
|
||||||
* @return true prevention was successfull / false prevention was replaced
|
* @return true prevention was successfull / false prevention was replaced
|
||||||
|
|
@ -310,12 +311,12 @@ public interface Game extends MageItem, Serializable {
|
||||||
/**
|
/**
|
||||||
* Creates and fires an damage prevention event
|
* Creates and fires an damage prevention event
|
||||||
*
|
*
|
||||||
* @param event damage event that will be replaced (instanceof check will be
|
* @param event damage event that will be replaced (instanceof check will be
|
||||||
* done)
|
* done)
|
||||||
* @param source ability that's the source of the prevention effect
|
* @param source ability that's the source of the prevention effect
|
||||||
* @param game
|
* @param game
|
||||||
* @param preventAllDamage true if there is no limit to the damage that can
|
* @param preventAllDamage true if there is no limit to the damage that can
|
||||||
* be prevented
|
* be prevented
|
||||||
* @return true prevention was successfull / false prevention was replaced
|
* @return true prevention was successfull / false prevention was replaced
|
||||||
*/
|
*/
|
||||||
PreventionEffectData preventDamage(GameEvent event, Ability source, Game game, boolean preventAllDamage);
|
PreventionEffectData preventDamage(GameEvent event, Ability source, Game game, boolean preventAllDamage);
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
protected Map<UUID, MeldCard> meldCards = new HashMap<>(0);
|
protected Map<UUID, MeldCard> meldCards = new HashMap<>(0);
|
||||||
|
|
||||||
protected Map<Zone, HashMap<UUID, MageObject>> lki = new EnumMap<>(Zone.class);
|
protected Map<Zone, HashMap<UUID, MageObject>> lki = new EnumMap<>(Zone.class);
|
||||||
|
protected Map<Zone, HashMap<UUID, CardState>> lkiCardState = new EnumMap<>(Zone.class);
|
||||||
protected Map<UUID, Map<Integer, MageObject>> lkiExtended = new HashMap<>();
|
protected Map<UUID, Map<Integer, MageObject>> lkiExtended = new HashMap<>();
|
||||||
// Used to check if an object was moved by the current effect in resolution (so Wrath like effect can be handled correctly)
|
// Used to check if an object was moved by the current effect in resolution (so Wrath like effect can be handled correctly)
|
||||||
protected Map<Zone, Set<UUID>> shortLivingLKI = new EnumMap<>(Zone.class);
|
protected Map<Zone, Set<UUID>> shortLivingLKI = new EnumMap<>(Zone.class);
|
||||||
|
|
@ -168,6 +169,7 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
this.gameOptions = game.gameOptions;
|
this.gameOptions = game.gameOptions;
|
||||||
this.lki.putAll(game.lki);
|
this.lki.putAll(game.lki);
|
||||||
this.lkiExtended.putAll(game.lkiExtended);
|
this.lkiExtended.putAll(game.lkiExtended);
|
||||||
|
this.lkiCardState.putAll(game.lkiCardState);
|
||||||
this.shortLivingLKI.putAll(game.shortLivingLKI);
|
this.shortLivingLKI.putAll(game.shortLivingLKI);
|
||||||
this.permanentsEntering.putAll(game.permanentsEntering);
|
this.permanentsEntering.putAll(game.permanentsEntering);
|
||||||
|
|
||||||
|
|
@ -2773,6 +2775,20 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
return getLastKnownInformation(objectId, zone);
|
return getLastKnownInformation(objectId, zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CardState getLastKnownInformationCard(UUID objectId, Zone zone) {
|
||||||
|
if (zone == Zone.GRAVEYARD) {
|
||||||
|
Map<UUID, CardState> lkiCardStateMap = lkiCardState.get(zone);
|
||||||
|
if (lkiCardStateMap != null) {
|
||||||
|
CardState cardState = lkiCardStateMap.get(objectId);
|
||||||
|
if (cardState != null) {
|
||||||
|
return cardState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getShortLivingLKI(UUID objectId, Zone zone) {
|
public boolean getShortLivingLKI(UUID objectId, Zone zone) {
|
||||||
Set<UUID> idSet = shortLivingLKI.get(zone);
|
Set<UUID> idSet = shortLivingLKI.get(zone);
|
||||||
|
|
@ -2817,16 +2833,28 @@ public abstract class GameImpl implements Game, Serializable {
|
||||||
lkiExtended.put(objectId, lkiExtendedMap);
|
lkiExtended.put(objectId, lkiExtendedMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (Zone.GRAVEYARD.equals(zone)) {
|
||||||
|
// Remember card state in this public zone (mainly removed/gained abilities)
|
||||||
|
Map<UUID, CardState> lkiMap = lkiCardState.get(zone);
|
||||||
|
if (lkiMap != null) {
|
||||||
|
lkiMap.put(objectId, getState().getCardState(objectId));
|
||||||
|
} else {
|
||||||
|
HashMap<UUID, CardState> newMap = new HashMap<>();
|
||||||
|
newMap.put(objectId, getState().getCardState(objectId).copy());
|
||||||
|
lkiCardState.put(zone, newMap);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset objects stored for Last Known Information.
|
* Reset objects stored for Last Known Information. (Happens if all effects
|
||||||
|
* are applied und stack is empty)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resetLKI() {
|
public void resetLKI() {
|
||||||
lki.clear();
|
lki.clear();
|
||||||
lkiExtended.clear();
|
lkiExtended.clear();
|
||||||
|
lkiCardState.clear();
|
||||||
infiniteLoopCounter = 0;
|
infiniteLoopCounter = 0;
|
||||||
stackObjectsCheck.clear();
|
stackObjectsCheck.clear();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,11 @@
|
||||||
package mage.util;
|
package mage.util;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.Mana;
|
import mage.Mana;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
|
|
@ -9,18 +15,12 @@ import mage.abilities.costs.mana.*;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.constants.EmptyNames;
|
import mage.constants.EmptyNames;
|
||||||
import mage.filter.Filter;
|
import mage.filter.Filter;
|
||||||
|
import mage.game.CardState;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.permanent.Permanent;
|
import mage.game.permanent.Permanent;
|
||||||
import mage.game.permanent.token.Token;
|
import mage.game.permanent.token.Token;
|
||||||
import mage.util.functions.CopyTokenFunction;
|
import mage.util.functions.CopyTokenFunction;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author nantuko
|
* @author nantuko
|
||||||
*/
|
*/
|
||||||
|
|
@ -29,10 +29,10 @@ public final class CardUtil {
|
||||||
private static final String SOURCE_EXILE_ZONE_TEXT = "SourceExileZone";
|
private static final String SOURCE_EXILE_ZONE_TEXT = "SourceExileZone";
|
||||||
|
|
||||||
static final String[] numberStrings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
static final String[] numberStrings = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
|
||||||
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"};
|
"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty"};
|
||||||
|
|
||||||
static final String[] ordinalStrings = {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eightth", "ninth",
|
static final String[] ordinalStrings = {"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eightth", "ninth",
|
||||||
"tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth", "twentieth"};
|
"tenth", "eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth", "sixteenth", "seventeenth", "eighteenth", "nineteenth", "twentieth"};
|
||||||
|
|
||||||
public static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
|
public static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
|
||||||
|
|
||||||
|
|
@ -147,8 +147,8 @@ public final class CardUtil {
|
||||||
*
|
*
|
||||||
* @param spellAbility
|
* @param spellAbility
|
||||||
* @param manaCostsToReduce costs to reduce
|
* @param manaCostsToReduce costs to reduce
|
||||||
* @param convertToGeneric colored mana does reduce generic mana if no
|
* @param convertToGeneric colored mana does reduce generic mana if no
|
||||||
* appropriate colored mana is in the costs included
|
* appropriate colored mana is in the costs included
|
||||||
*/
|
*/
|
||||||
public static void adjustCost(SpellAbility spellAbility, ManaCosts<ManaCost> manaCostsToReduce, boolean convertToGeneric) {
|
public static void adjustCost(SpellAbility spellAbility, ManaCosts<ManaCost> manaCostsToReduce, boolean convertToGeneric) {
|
||||||
ManaCosts<ManaCost> previousCost = spellAbility.getManaCostsToPay();
|
ManaCosts<ManaCost> previousCost = spellAbility.getManaCostsToPay();
|
||||||
|
|
@ -333,7 +333,7 @@ public final class CardUtil {
|
||||||
*
|
*
|
||||||
* @param number number to convert to text
|
* @param number number to convert to text
|
||||||
* @param forOne if the number is 1, this string will be returnedinstead of
|
* @param forOne if the number is 1, this string will be returnedinstead of
|
||||||
* "one".
|
* "one".
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String numberToText(int number, String forOne) {
|
public static String numberToText(int number, String forOne) {
|
||||||
|
|
@ -418,7 +418,7 @@ public final class CardUtil {
|
||||||
/**
|
/**
|
||||||
* Creates and saves a (card + zoneChangeCounter) specific exileId.
|
* Creates and saves a (card + zoneChangeCounter) specific exileId.
|
||||||
*
|
*
|
||||||
* @param game the current game
|
* @param game the current game
|
||||||
* @param source source ability
|
* @param source source ability
|
||||||
* @return the specific UUID
|
* @return the specific UUID
|
||||||
*/
|
*/
|
||||||
|
|
@ -453,9 +453,9 @@ public final class CardUtil {
|
||||||
* be specific to a permanent instance. So they won't match, if a permanent
|
* be specific to a permanent instance. So they won't match, if a permanent
|
||||||
* was e.g. exiled and came back immediately.
|
* was e.g. exiled and came back immediately.
|
||||||
*
|
*
|
||||||
* @param text short value to describe the value
|
* @param text short value to describe the value
|
||||||
* @param cardId id of the card
|
* @param cardId id of the card
|
||||||
* @param game the game
|
* @param game the game
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getCardZoneString(String text, UUID cardId, Game game) {
|
public static String getCardZoneString(String text, UUID cardId, Game game) {
|
||||||
|
|
@ -605,4 +605,29 @@ public final class CardUtil {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a card had a given ability depending their historic cardState
|
||||||
|
*
|
||||||
|
* @param ability the ability that is checked
|
||||||
|
* @param cardState the historic cardState (from LKI)
|
||||||
|
* @param cardId the id of the card
|
||||||
|
* @param game
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean cardHadAbility(Ability ability, CardState cardState, UUID cardId, Game game) {
|
||||||
|
Card card = game.getCard(cardId);
|
||||||
|
if (card != null) {
|
||||||
|
if (cardState != null) {
|
||||||
|
if (cardState.getAbilities().contains(ability)) { // Check other abilities (possibly given after lost of abilities)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (cardState.hasLostAllAbilities()) {
|
||||||
|
return false; // Not allowed to check abilities of original card
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return card.getAbilities().contains(ability); // check if the original card has the ability
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue