diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index 251dc8796f2..5950f124f0f 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -229,12 +229,12 @@ public class GameCopier { private static final boolean USE_FROM_PAPER_CARD = true; private Card createCardCopy(Game newGame, Player newOwner, Card c) { - if (c.isToken() && !c.isEmblem()) { + if (c.isToken() && !c.isImmutable()) { Card result = new TokenInfo(c).makeOneToken(newOwner); CardFactory.copyCopiableCharacteristics(c, result); return result; } - if (USE_FROM_PAPER_CARD && !c.isEmblem() && c.getPaperCard() != null) { + if (USE_FROM_PAPER_CARD && !c.isImmutable() && c.getPaperCard() != null) { Card newCard = Card.fromPaperCard(c.getPaperCard(), newOwner); newCard.setCommander(c.isCommander()); return newCard; diff --git a/forge-core/src/main/java/forge/card/CardType.java b/forge-core/src/main/java/forge/card/CardType.java index 3941b990124..257230a184a 100644 --- a/forge-core/src/main/java/forge/card/CardType.java +++ b/forge-core/src/main/java/forge/card/CardType.java @@ -58,7 +58,6 @@ public final class CardType implements Comparable, CardTypeView { Conspiracy(false, "conspiracies"), Creature(true, "creatures"), Dungeon(false, "dungeons"), - Emblem(false, "emblems"), Enchantment(true, "enchantments"), Instant(false, "instants"), Land(true, "lands"), @@ -437,11 +436,6 @@ public final class CardType implements Comparable, CardTypeView { return coreTypes.contains(CoreType.Phenomenon); } - @Override - public boolean isEmblem() { - return coreTypes.contains(CoreType.Emblem); - } - @Override public boolean isTribal() { return coreTypes.contains(CoreType.Tribal); @@ -547,7 +541,7 @@ public final class CardType implements Comparable, CardTypeView { if (!isInstant() && !isSorcery()) { Iterables.removeIf(subtypes, Predicates.IS_SPELL_TYPE); } - if (!isPlaneswalker() && !isEmblem()) { + if (!isPlaneswalker()) { Iterables.removeIf(subtypes, Predicates.IS_WALKER_TYPE); } } diff --git a/forge-core/src/main/java/forge/card/CardTypeView.java b/forge-core/src/main/java/forge/card/CardTypeView.java index cfecf57a752..f89452baac8 100644 --- a/forge-core/src/main/java/forge/card/CardTypeView.java +++ b/forge-core/src/main/java/forge/card/CardTypeView.java @@ -42,7 +42,6 @@ public interface CardTypeView extends Iterable, Serializable { boolean isBasicLand(); boolean isPlane(); boolean isPhenomenon(); - boolean isEmblem(); boolean isTribal(); boolean isDungeon(); CardTypeView getTypeWithChanges(Iterable changedCardTypes); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 95f447942bf..c78e34e62c7 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -153,8 +153,7 @@ public final class GameActionUtil { final StringBuilder sb = new StringBuilder(sa.getDescription()); if (!source.equals(host)) { sb.append(" by "); - if ((host.isEmblem() || host.getType().hasSubtype("Effect")) - && host.getEffectSource() != null) { + if ((host.isImmutable()) && host.getEffectSource() != null) { sb.append(host.getEffectSource()); } else { sb.append(host); @@ -542,7 +541,6 @@ public final class GameActionUtil { final Card eff = new Card(game.nextCardId(), game); eff.setTimestamp(game.getNextTimestamp()); eff.setName(sourceCard.getName() + "'s Effect"); - eff.addType("Effect"); eff.setOwner(controller); eff.setImageKey(sourceCard.getImageKey()); diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 11dd1ada434..89c895d6173 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -112,9 +112,9 @@ public class AbilityUtils { // Probably will move to One function solution sometime in the future public static CardCollection getDefinedCards(final Card hostCard, final String def, final CardTraitBase sa) { CardCollection cards = new CardCollection(); - String defined = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self - final String[] incR = defined.split("\\.", 2); - defined = incR[0]; + String changedDef = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self + final String[] incR = changedDef.split("\\.", 2); + String defined = incR[0]; final Game game = hostCard.getGame(); Card c = null; @@ -132,7 +132,7 @@ public class AbilityUtils { } } else if (defined.equals("EffectSource")) { - if (hostCard.isEmblem() || hostCard.getType().hasSubtype("Effect")) { + if (hostCard.isImmutable()) { c = findEffectRoot(hostCard); } } @@ -346,6 +346,23 @@ public class AbilityUtils { cards.add(game.getCardState(cardByID)); } } + } else if (defined.startsWith("Valid")) { + Iterable candidates; + String validDefined; + if (defined.startsWith("Valid ")) { + candidates = game.getCardsIn(ZoneType.Battlefield); + validDefined = changedDef.substring("Valid ".length()); + } else if (defined.startsWith("ValidAll ")) { + candidates = game.getCardsInGame(); + validDefined = changedDef.substring("ValidAll ".length()); + } else { + String[] s = changedDef.split(" ", 2); + String zone = s[0].substring("Valid".length()); + candidates = game.getCardsIn(ZoneType.smartValueOf(zone)); + validDefined = s[1]; + } + cards.addAll(CardLists.getValidCards(candidates, validDefined.split(","), hostCard.getController(), hostCard, sa)); + return cards; } else { CardCollection list = null; if (sa instanceof SpellAbility) { @@ -377,19 +394,6 @@ public class AbilityUtils { } } - if (defined.startsWith("Valid ")) { - String validDefined = defined.substring("Valid ".length()); - list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), validDefined.split(","), hostCard.getController(), hostCard, sa); - } else if (defined.startsWith("ValidAll ")) { - String validDefined = defined.substring("ValidAll ".length()); - list = CardLists.getValidCards(game.getCardsInGame(), validDefined.split(","), hostCard.getController(), hostCard, sa); - } else if (defined.startsWith("Valid")) { - String[] s = defined.split(" "); - String zone = s[0].substring("Valid".length()); - String validDefined = s[1]; - list = CardLists.getValidCards(game.getCardsIn(ZoneType.smartValueOf(zone)), validDefined.split(","), hostCard.getController(), hostCard, sa); - } - if (list != null) { cards.addAll(list); } @@ -421,7 +425,7 @@ public class AbilityUtils { private static Card findEffectRoot(Card startCard) { Card cc = startCard.getEffectSource(); if (cc != null) { - if (cc.isEmblem() || cc.getType().hasSubtype("Effect")) { + if (cc.isImmutable()) { return findEffectRoot(cc); } return cc; diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 4c29e29dbb9..c84d0c0eb1a 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -13,7 +13,6 @@ import com.google.common.collect.Maps; import com.google.common.collect.Table; import forge.GameCommand; -import forge.card.CardType; import forge.card.MagicColor; import forge.game.Game; import forge.game.GameEntity; @@ -457,25 +456,19 @@ public abstract class SpellAbilityEffect { final Card eff = new Card(game.nextCardId(), game); eff.setTimestamp(game.getNextTimestamp()); eff.setName(name); + eff.setColor(hostCard.determineColor().getColor()); // if name includes emblem then it should be one - eff.addType(name.startsWith("Emblem") ? "Emblem" : "Effect"); - // add Planeswalker types into Emblem for fun - if (name.startsWith("Emblem") && hostCard.isPlaneswalker()) { - for (final String type : hostCard.getType().getSubtypes()) { - if (CardType.isAPlaneswalkerType(type)) { - eff.addType(type); - } - } + if (name.startsWith("Emblem")) { + eff.setEmblem(true); + // Emblem needs to be colorless + eff.setColor(MagicColor.COLORLESS); } + eff.setOwner(controller); eff.setSVars(sa.getSVars()); eff.setImageKey(image); - if (eff.getType().hasType(CardType.CoreType.Emblem)) { - eff.setColor(MagicColor.COLORLESS); - } else { - eff.setColor(hostCard.determineColor().getColor()); - } + eff.setImmutable(true); eff.setEffectSource(sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java index 9b09ca23032..63f36f6a89e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java @@ -190,11 +190,6 @@ public class AnimateEffect extends AnimateEffectBase { } } - // Restore immutable to effect - if (sa.hasParam("Immutable")) { - c.setImmutable(true); - } - game.fireEvent(new GameEventCardStatsChanged(c)); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DetachedCardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DetachedCardEffect.java index 0d62a05104b..56a1a46081d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DetachedCardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DetachedCardEffect.java @@ -12,7 +12,6 @@ public class DetachedCardEffect extends Card { card = card0; setName(name0); - addType("Effect"); setOwner(card0.getOwner()); setImmutable(true); diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java index 04471bed67a..445d03088ed 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java @@ -140,10 +140,6 @@ public class EffectEffect extends SpellAbilityEffect { final Card eff = createEffect(sa, controller, name, image); eff.setSetCode(sa.getHostCard().getSetCode()); eff.setRarity(sa.getHostCard().getRarity()); - // For Raging River effect to add attacker "left" or "right" pile later - if (sa.hasParam("Mutable")) { - eff.setImmutable(false); - } // Abilities and triggers work the same as they do for Token // Grant abilities diff --git a/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java index 7d42e9c5988..f96ad2a2ead 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RegenerationEffect.java @@ -37,7 +37,7 @@ public class RegenerationEffect extends SpellAbilityEffect { // Play the Regen sound game.fireEvent(new GameEventCardRegenerated()); - if (host.getType().hasStringType("Effect")) { + if (host.isImmutable()) { c.subtractShield(host); host.removeRemembered(c); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ReplaceDamageEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ReplaceDamageEffect.java index cb59a12eb10..3a19bb05c42 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ReplaceDamageEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ReplaceDamageEffect.java @@ -47,7 +47,7 @@ public class ReplaceDamageEffect extends SpellAbilityEffect { prevent -= n; if (!StringUtils.isNumeric(varValue) && card.getSVar(varValue).startsWith("Number$")) { - if (card.getType().hasStringType("Effect") && prevent <= 0) { + if (card.isImmutable() && prevent <= 0) { game.getAction().exile(card, null); } else { card.setSVar(varValue, "Number$" + prevent); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ReplaceSplitDamageEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ReplaceSplitDamageEffect.java index 1f462099afe..65fce9f796d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ReplaceSplitDamageEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ReplaceSplitDamageEffect.java @@ -45,7 +45,7 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect { dmg -= n; prevent -= n; - if (card.getType().hasStringType("Effect") && prevent <= 0) { + if (card.isImmutable() && prevent <= 0) { game.getAction().exile(card, null); } else if (!StringUtils.isNumeric(varValue)) { sa.setSVar(varValue, "Number$" + prevent); diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 24e466b381c..9c660f472f5 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -264,6 +264,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // for Vanguard / Manapool / Emblems etc. private boolean isImmutable = false; + private boolean isEmblem = false; private int exertThisTurn = 0; private PlayerCollection exertedByPlayer = new PlayerCollection(); @@ -4598,15 +4599,13 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final boolean isPermanent() { - return !isImmutable && (isInZone(ZoneType.Battlefield) || getType().isPermanent()); + return !isImmutable() && (isInZone(ZoneType.Battlefield) || getType().isPermanent()); } public final boolean isSpell() { return (isInstant() || isSorcery() || (isAura() && !isInZone((ZoneType.Battlefield)))); } - public final boolean isEmblem() { return getType().isEmblem(); } - public final boolean isLand() { return getType().isLand(); } public final boolean isBasicLand() { return getType().isBasicLand(); } public final boolean isSnow() { return getType().isSnow(); } @@ -4865,11 +4864,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // Takes one argument like Permanent.Blue+withFlying @Override public final boolean isValid(final String restriction, final Player sourceController, final Card source, CardTraitBase spellAbility) { - if (isImmutable() && source != null && !source.isRemembered(this) && - !(restriction.startsWith("Emblem") || restriction.startsWith("Effect"))) { // special case exclusion - return false; - } - // Inclusive restrictions are Card types final String[] incR = restriction.split("\\.", 2); @@ -4879,14 +4873,27 @@ public class Card extends GameEntity implements Comparable, IHasSVars { incR[0] = incR[0].substring(1); // consume negation sign } - if (incR[0].equals("Spell") && !isSpell()) { - return testFailed; - } - if (incR[0].equals("Permanent") && !isPermanent()) { - return testFailed; - } - if (!incR[0].equals("card") && !incR[0].equals("Card") && !incR[0].equals("Spell") - && !incR[0].equals("Permanent") && !getType().hasStringType(incR[0])) { + if (incR[0].equals("Spell")) { + if (!isSpell()) { + return testFailed; + } + } else if (incR[0].equals("Permanent")) { + if (!isPermanent()) { + return testFailed; + } + } else if (incR[0].equals("Effect")) { + if (!isImmutable()) { + return testFailed; + } + } else if (incR[0].equals("Emblem")) { + if (!isEmblem()) { + return testFailed; + } + } else if (incR[0].equals("card") || incR[0].equals("Card")) { + if (isImmutable()) { + return testFailed; + } + } else if (!getType().hasStringType(incR[0])) { return testFailed; // Check for wrong type } @@ -4916,6 +4923,15 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final void setImmutable(final boolean isImmutable0) { isImmutable = isImmutable0; + view.updateImmutable(this); + } + + public final boolean isEmblem() { + return isEmblem; + } + public final void setEmblem(final boolean isEmblem0) { + isEmblem = isEmblem0; + view.updateEmblem(this); } /* diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index 60bab6f6645..57fd52794ec 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -357,7 +357,7 @@ public class CardProperty { return false; } } else if (property.equals("EffectSource")) { - if (!source.isEmblem() && !source.getType().hasSubtype("Effect")) { + if (!source.isImmutable()) { return false; } diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index 18984d40709..99106c77f09 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -242,6 +242,7 @@ public final class CardUtil { newCopy.setToken(in.isToken()); newCopy.setCopiedSpell(in.isCopiedSpell()); newCopy.setImmutable(in.isImmutable()); + newCopy.setEmblem(in.isEmblem()); // lock in the current P/T newCopy.setBasePower(in.getCurrentPower()); diff --git a/forge-game/src/main/java/forge/game/card/CardView.java b/forge-game/src/main/java/forge/game/card/CardView.java index 4edc56438e9..7ad4251c635 100644 --- a/forge-game/src/main/java/forge/game/card/CardView.java +++ b/forge-game/src/main/java/forge/game/card/CardView.java @@ -233,6 +233,20 @@ public class CardView extends GameEntityView { set(TrackableProperty.Token, c.isToken()); } + public boolean isImmutable() { + return get(TrackableProperty.IsImmutable); + } + public void updateImmutable(Card c) { + set(TrackableProperty.IsImmutable, c.isImmutable()); + } + + public boolean isEmblem() { + return get(TrackableProperty.IsEmblem); + } + public void updateEmblem(Card c) { + set(TrackableProperty.IsEmblem, c.isEmblem()); + } + public boolean isTokenCard() { return get(TrackableProperty.TokenCard); } void updateTokenCard(Card c) { set(TrackableProperty.TokenCard, c.isTokenCard()); } diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 3792241e456..0e219e8ee56 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -3176,6 +3176,7 @@ public class Player extends GameEntity implements Comparable { if (monarchEffect == null) { monarchEffect = new Card(game.nextCardId(), null, game); monarchEffect.setOwner(this); + monarchEffect.setImmutable(true); if (set != null) { monarchEffect.setImageKey("t:monarch_" + set.toLowerCase()); monarchEffect.setSetCode(set); @@ -3183,7 +3184,6 @@ public class Player extends GameEntity implements Comparable { monarchEffect.setImageKey("t:monarch"); } monarchEffect.setName("The Monarch"); - monarchEffect.addType("Effect"); { final String drawTrig = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Command | " + @@ -3280,8 +3280,7 @@ public class Player extends GameEntity implements Comparable { blessingEffect.setOwner(this); blessingEffect.setImageKey("t:blessing"); blessingEffect.setName("City's Blessing"); - blessingEffect.addType("Effect"); - + blessingEffect.setImmutable(true); blessingEffect.updateStateForView(); @@ -3353,7 +3352,6 @@ public class Player extends GameEntity implements Comparable { keywordEffect.setOwner(this); keywordEffect.setName("Keyword Effects"); keywordEffect.setImageKey(ImageKeys.HIDDEN_CARD); - keywordEffect.addType("Effect"); keywordEffect.updateStateForView(); diff --git a/forge-game/src/main/java/forge/game/spellability/LandAbility.java b/forge-game/src/main/java/forge/game/spellability/LandAbility.java index 0e2bcdde8f4..5def083a3b1 100644 --- a/forge-game/src/main/java/forge/game/spellability/LandAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/LandAbility.java @@ -95,8 +95,7 @@ public class LandAbility extends Ability { Card source = sta.getHostCard(); if (!source.equals(getHostCard())) { sb.append(" by "); - if ((source.isEmblem() || source.getType().hasSubtype("Effect")) - && source.getEffectSource() != null) { + if (source.isImmutable() && source.getEffectSource() != null) { sb.append(source.getEffectSource()); } else { sb.append(source); diff --git a/forge-game/src/main/java/forge/trackable/TrackableProperty.java b/forge-game/src/main/java/forge/trackable/TrackableProperty.java index 93a3e81cd8e..50ace8e3e31 100644 --- a/forge-game/src/main/java/forge/trackable/TrackableProperty.java +++ b/forge-game/src/main/java/forge/trackable/TrackableProperty.java @@ -24,6 +24,9 @@ public enum TrackableProperty { Controller(TrackableTypes.PlayerViewType), Zone(TrackableTypes.EnumType(ZoneType.class)), + IsImmutable(TrackableTypes.BooleanType), + IsEmblem(TrackableTypes.BooleanType), + Flipped(TrackableTypes.BooleanType), Facedown(TrackableTypes.BooleanType), Foretold(TrackableTypes.BooleanType), diff --git a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java index e1839f48113..e6b682751c9 100644 --- a/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java +++ b/forge-gui-desktop/src/main/java/forge/view/arcane/CardPanel.java @@ -311,7 +311,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl final CardStateView state = getCard().getCurrentState(); final CardEdition ed = FModel.getMagicDb().getEditions().get(state.getSetCode()); boolean colorIsSet = false; - if (state.getType().isEmblem() || state.getType().hasStringType("Effect")) { + if (getCard().isImmutable()) { // Effects are drawn with orange border g2d.setColor(Color.ORANGE); colorIsSet = true; diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 8076308b240..70ca2dbe0d2 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -362,8 +362,7 @@ public class CardImageRenderer { drawDetails(g, card, gameView, altState, x, y, w, h); return; } - if(card.isToken() && card.getCurrentState().getType().hasSubtype("Effect") - && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_IMAGES_EFFECT_CARDS)){ + if(card.isImmutable() && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_IMAGES_EFFECT_CARDS)){ drawDetails(g, card, gameView, altState, x, y, w, h); return; } diff --git a/forge-gui/res/cardsfolder/d/dread_wight.txt b/forge-gui/res/cardsfolder/d/dread_wight.txt index e2373ef98d3..aef6b05482e 100644 --- a/forge-gui/res/cardsfolder/d/dread_wight.txt +++ b/forge-gui/res/cardsfolder/d/dread_wight.txt @@ -5,7 +5,7 @@ PT:3/4 T:Mode$ Phase | Phase$ EndCombat | Execute$ TrigCounter | TriggerZones$ Battlefield | TriggerDescription$ At end of combat, put a paralyzation counter on each creature blocking or blocked by CARDNAME and tap those creatures. Each of those creatures doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it. Each of those creatures gains "{4}: Remove a paralyzation counter from this creature." SVar:TrigCounter:DB$ PutCounterAll | CounterType$ PARALYZATION | CounterNum$ 1 | ValidCards$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBTap SVar:DBTap:DB$ TapAll | ValidCards$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBEffect -SVar:DBEffect:DB$ Effect | RememberObjects$ Valid Creature.blockedBySource,Valid Creature.blockingSource | StaticAbilities$ DontUntap | Duration$ Permanent | ConditionPresent$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBAnimate | ForgetOnMoved$ Battlefield | ForgetCounter$ PARALYZATION +SVar:DBEffect:DB$ Effect | RememberObjects$ Valid Creature.blockedBySource,Creature.blockingSource | StaticAbilities$ DontUntap | Duration$ Permanent | ConditionPresent$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBAnimate | ForgetOnMoved$ Battlefield | ForgetCounter$ PARALYZATION SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.blockedBySource,Creature.blockingSource | Abilities$ ABRemoveCounter | Duration$ Permanent SVar:ABRemoveCounter:AB$ RemoveCounter | Defined$ Self | Cost$ 4 | CounterType$ PARALYZATION | CounterNum$ 1 | SpellDescription$ Remove a paralyzation counter from this creature. SVar:DontUntap:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Card.IsRemembered | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. | Description$ Each of those creatures doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it. diff --git a/forge-gui/res/cardsfolder/g/gerrard_weatherlight_hero.txt b/forge-gui/res/cardsfolder/g/gerrard_weatherlight_hero.txt index 9f017a9d46d..c0aa968ae90 100644 --- a/forge-gui/res/cardsfolder/g/gerrard_weatherlight_hero.txt +++ b/forge-gui/res/cardsfolder/g/gerrard_weatherlight_hero.txt @@ -5,5 +5,5 @@ PT:3/3 K:First Strike T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, exile it and return to the battlefield all artifact and creature cards in your graveyard that were put there from the battlefield this turn. SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBReturn -SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact,Creature.YouOwn+ThisTurnEnteredFrom_Battlefield +SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact.YouOwn+ThisTurnEnteredFrom_Battlefield,Creature.YouOwn+ThisTurnEnteredFrom_Battlefield Oracle:First strike\nWhen Gerrard, Weatherlight Hero dies, exile it and return to the battlefield all artifact and creature cards in your graveyard that were put there from the battlefield this turn. diff --git a/forge-gui/res/cardsfolder/p/plague_of_vermin.txt b/forge-gui/res/cardsfolder/p/plague_of_vermin.txt index c124f930313..4e8e3870c91 100644 --- a/forge-gui/res/cardsfolder/p/plague_of_vermin.txt +++ b/forge-gui/res/cardsfolder/p/plague_of_vermin.txt @@ -1,17 +1,16 @@ Name:Plague of Vermin ManaCost:6 B Types:Sorcery -A:SP$ Effect | Cost$ 6 B | Name$ Plague of Vermin Life Paid | EffectOwner$ Player | ImprintOnHost$ True | Mutable$ True | Duration$ Permanent | SubAbility$ DBRepeat | StackDescription$ SpellDescription | SpellDescription$ Starting with you, each player may pay any amount of life. Repeat this process until no one pays life. Each player creates a 1/1 black Rat creature token for each 1 life they paid this way. +A:SP$ Effect | Cost$ 6 B | Name$ Plague of Vermin Life Paid | EffectOwner$ Player | ImprintOnHost$ True | Duration$ Permanent | SubAbility$ DBRepeat | StackDescription$ SpellDescription | SpellDescription$ Starting with you, each player may pay any amount of life. Repeat this process until no one pays life. Each player creates a 1/1 black Rat creature token for each 1 life they paid this way. SVar:DBRepeat:DB$ Repeat | RepeatSubAbility$ DBResetCheck | RepeatCheckSVar$ NumPlayerGiveup | RepeatSVarCompare$ LTTotalPlayer | SubAbility$ DBRepeatToken SVar:DBResetCheck:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ Number | Expression$ 0 | SubAbility$ DBRepeatChoice SVar:DBRepeatChoice:DB$ RepeatEach | StartingWithActivator$ True | RepeatSubAbility$ DBChoice | RepeatPlayers$ Player SVar:DBChoice:DB$ ChooseNumber | Defined$ Player.IsRemembered | Max$ LifeTotal | AILogic$ Vermin | ListTitle$ Pay Any Amount of Life | SubAbility$ DBCheckPaid SVar:DBCheckPaid:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ CountSVar | Expression$ NumPlayerGiveup/Plus.1 | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ0 | SubAbility$ DBStore -SVar:DBStore:DB$ PutCounter | Defined$ Imprinted.namedPlague of Vermin Life Paid+OwnedBy Player.IsRemembered | CounterNum$ X | Placer$ Player.IsRemembered | CounterType$ PLAGUE | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | UnlessCost$ PayLife | UnlessPayer$ Player.IsRemembered | UnlessSwitched$ True | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DBGiveUp | SpellDescription$ You may pay any amount of life. +SVar:DBStore:DB$ PutCounter | Defined$ ValidCommand Effect.namedPlague of Vermin Life Paid+OwnedBy Player.IsRemembered | CounterNum$ X | Placer$ Player.IsRemembered | CounterType$ PLAGUE | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | UnlessCost$ PayLife | UnlessPayer$ Player.IsRemembered | UnlessSwitched$ True | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DBGiveUp | SpellDescription$ You may pay any amount of life. SVar:DBGiveUp:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ CountSVar | Expression$ NumPlayerGiveup/Plus.1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 SVar:DBRepeatToken:DB$ RepeatEach | StartingWithActivator$ True | RepeatSubAbility$ DBToken | RepeatPlayers$ Player | SubAbility$ DBFinalReset -SVar:DBToken:DB$ Token | TokenAmount$ LifePaidAmount | TokenScript$ b_1_1_rat | TokenOwner$ Player.IsRemembered | StackDescription$ None | SubAbility$ DBRestoreImmutable -SVar:DBRestoreImmutable:DB$ Animate | Defined$ Imprinted.namedPlague of Vermin Life Paid+OwnedBy Player.IsRemembered | Duration$ Permanent | Immutable$ True +SVar:DBToken:DB$ Token | TokenAmount$ LifePaidAmount | TokenScript$ b_1_1_rat | TokenOwner$ Player.IsRemembered | StackDescription$ None SVar:DBFinalReset:DB$ StoreSVar | SVar$ NumPlayerGiveup | Type$ Number | Expression$ 0 | SubAbility$ DBExileEffect SVar:DBExileEffect:DB$ ChangeZone | Defined$ Imprinted | Origin$ Command | Destination$ Exile | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True diff --git a/forge-gui/res/cardsfolder/r/raging_river.txt b/forge-gui/res/cardsfolder/r/raging_river.txt index 4091cb62b91..ad6e1dafcfb 100644 --- a/forge-gui/res/cardsfolder/r/raging_river.txt +++ b/forge-gui/res/cardsfolder/r/raging_river.txt @@ -3,16 +3,16 @@ ManaCost:R R Types:Enchantment T:Mode$ AttackersDeclared | AttackingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigRepeatDefender | TriggerDescription$ Whenever one or more creatures you control attack, each defending player divides all creatures without flying they control into a "left" pile and a "right" pile. Then, for each attacking creature you control, choose "left" or "right." That creature can't be blocked this combat except by creatures with flying and creatures in a pile with the chosen label. SVar:TrigRepeatDefender:DB$ RepeatEach | RepeatPlayers$ TriggeredAttackedTarget | RepeatSubAbility$ DBDefLeftEffect | SubAbility$ DBAtkLeftRight -SVar:DBDefLeftEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Left | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Mutable$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefRightEffect -SVar:DBDefRightEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Right | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Mutable$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefLeftRight +SVar:DBDefLeftEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Left | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefRightEffect +SVar:DBDefRightEffect:DB$ Effect | EffectOwner$ Remembered | Name$ Raging River Right | StaticAbilities$ DBCantBlock | ImprintOnHost$ True | Duration$ UntilEndOfCombat | SubAbility$ DBDefLeftRight SVar:DBCantBlock:Mode$ CantBlockBy | ValidAttacker$ Creature.IsRemembered | ValidBlocker$ Creature.withoutFlying+IsNotImprinted+YouCtrl | EffectZone$ Command SVar:DBDefLeftRight:DB$ TwoPiles | Defined$ Remembered | Separator$ Remembered | ValidCards$ Creature.withoutFlying+RememberedPlayerCtrl | Zone$ Battlefield | LeftRightPile$ True | ChosenPile$ DBDefLeftPile | UnchosenPile$ DBDefRightPile | AILogic$ Random | SubAbility$ DBClearImprinted -SVar:DBDefLeftPile:DB$ Animate | Defined$ Imprinted.namedRaging River Left | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBLeftPump -SVar:DBDefRightPile:DB$ Animate | Defined$ Imprinted.namedRaging River Right | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBRightPump +SVar:DBDefLeftPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Left+IsImprinted | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBLeftPump +SVar:DBDefRightPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Right+IsImprinted | ImprintCards$ Remembered | Duration$ Permanent | SubAbility$ DBRightPump SVar:DBClearImprinted:DB$ Cleanup | ClearImprinted$ True SVar:DBAtkLeftRight:DB$ TwoPiles | Defined$ You | Separator$ You | ValidCards$ Creature.attacking+YouCtrl | Zone$ Battlefield | LeftRightPile$ True | ChosenPile$ DBAtkLeftPile | UnchosenPile$ DBAtkRightPile | AILogic$ Random | SubAbility$ DBCleanup -SVar:DBAtkLeftPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Left | RememberObjects$ RememberedCard | Duration$ Permanent | Immutable$ True | SubAbility$ DBLeftPump -SVar:DBAtkRightPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Right | RememberObjects$ RememberedCard | Duration$ Permanent | Immutable$ True | SubAbility$ DBRightPump +SVar:DBAtkLeftPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Left | RememberObjects$ RememberedCard | Duration$ Permanent | SubAbility$ DBLeftPump +SVar:DBAtkRightPile:DB$ Animate | Defined$ ValidCommand Effect.namedRaging River Right | RememberObjects$ RememberedCard | Duration$ Permanent | SubAbility$ DBRightPump SVar:DBLeftPump:DB$ Pump | Defined$ Remembered | KW$ "Left" pile | Duration$ UntilEndOfCombat SVar:DBRightPump:DB$ Pump | Defined$ Remembered | KW$ "Right" pile | Duration$ UntilEndOfCombat SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/s/second_sunrise.txt b/forge-gui/res/cardsfolder/s/second_sunrise.txt index 20a3a92b110..e05814dbb39 100644 --- a/forge-gui/res/cardsfolder/s/second_sunrise.txt +++ b/forge-gui/res/cardsfolder/s/second_sunrise.txt @@ -1,5 +1,5 @@ Name:Second Sunrise ManaCost:1 W W Types:Instant -A:SP$ChangeZone | Cost$ 1 W W | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact,Creature,Enchantment,Land.ThisTurnEnteredFrom_Battlefield | SpellDescription$ Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn. +A:SP$ChangeZone | Cost$ 1 W W | Origin$ Graveyard | Destination$ Battlefield | Defined$ ValidGraveyard Artifact.ThisTurnEnteredFrom_Battlefield,Creature.ThisTurnEnteredFrom_Battlefield,Enchantment.ThisTurnEnteredFrom_Battlefield,Land.ThisTurnEnteredFrom_Battlefield | SpellDescription$ Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn. Oracle:Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn. diff --git a/forge-gui/src/main/java/forge/gamemodes/puzzle/Puzzle.java b/forge-gui/src/main/java/forge/gamemodes/puzzle/Puzzle.java index 82c6ee6dc32..d4b34e04c56 100644 --- a/forge-gui/src/main/java/forge/gamemodes/puzzle/Puzzle.java +++ b/forge-gui/src/main/java/forge/gamemodes/puzzle/Puzzle.java @@ -121,7 +121,7 @@ public class Puzzle extends GameState implements InventoryItem, Comparable