diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index f2e6b62f67f..1eb2845064a 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -2430,7 +2430,7 @@ public class GameAction { } if (c.isPlaneswalker()) { int lethalPW = c.getCurrentLoyalty(); - // 120.10 + // CR 120.10 lethal = c.isCreature() ? Math.min(lethal, lethalPW) : lethalPW; } lethalDamage.put(c, lethal); @@ -2442,6 +2442,7 @@ public class GameAction { sourceLKI.getDamageHistory().registerDamage(e.getValue(), isCombat, sourceLKI, e.getKey(), lkiCache); } + // CR 702.15e if (sum > 0 && sourceLKI.hasKeyword(Keyword.LIFELINK)) { sourceLKI.getController().gainLife(sum, sourceLKI, cause); } diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index e0e59f1bc6d..710979e36a3 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -302,8 +302,7 @@ public final class AbilityFactory { } if (spellAbility instanceof SpellApiBased && hostCard.isPermanent()) { - String desc = mapParams.containsKey("SpellDescription") ? mapParams.get("SpellDescription") - : spellAbility.getHostCard().getName(); + String desc = mapParams.getOrDefault("SpellDescription", spellAbility.getHostCard().getName()); spellAbility.setDescription(desc); } else if (mapParams.containsKey("SpellDescription")) { spellAbility.rebuiltDescription(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index 1f5902bc90a..f6955394958 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -65,6 +65,10 @@ public class CharmEffect extends SpellAbilityEffect { // using getCardForUi game is not set, so can't guess max charm num = Integer.MAX_VALUE; } else { + // fallback needed while ability building + if (sa.getActivatingPlayer() == null) { + sa.setActivatingPlayer(source.getController()); + } num = Math.min(AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CharmNum", "1"), sa), list.size()); } final int min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParam("MinCharmNum"), sa) : num; diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamageDealEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DamageDealEffect.java index 0ea92400ad2..9f970957841 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamageDealEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamageDealEffect.java @@ -320,12 +320,9 @@ public class DamageDealEffect extends DamageBaseEffect { } else { if (sa.hasParam("ExcessDamage") && (!sa.hasParam("ExcessDamageCondition") || sourceLKI.isValid(sa.getParam("ExcessDamageCondition").split(","), activationPlayer, hostCard, sa))) { - damageMap.put(sourceLKI, c, dmgToTarget); - List list = Lists.newArrayList(); - list.addAll(AbilityUtils.getDefinedCards(hostCard, sa.getParam("ExcessDamage"), sa)); - list.addAll(AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("ExcessDamage"), sa)); + List list = AbilityUtils.getDefinedEntities(hostCard, sa.getParam("ExcessDamage"), sa); if (!list.isEmpty()) { damageMap.put(sourceLKI, list.get(0), excess); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java index cdecd9ce083..039ab8088aa 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java @@ -17,6 +17,7 @@ import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.CardTranslation; import forge.util.TextUtil; public abstract class DamagePreventEffectBase extends SpellAbilityEffect { @@ -24,7 +25,7 @@ public abstract class DamagePreventEffectBase extends SpellAbilityEffect { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); final Player player = hostCard.getController(); - final String name = hostCard.getName() + "'s Effect"; + final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect"; final String image = hostCard.getImageKey(); StringBuilder sb = new StringBuilder("Event$ DamageDone | ActiveZones$ Command | ValidTarget$ "); sb.append((o instanceof Card ? "Card.IsRemembered" : "Player.IsRemembered")); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java index 316885c6234..0770d40935c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java @@ -38,6 +38,7 @@ public class DelayedTriggerEffect extends SpellAbilityEffect { final Card host = sa.getHostCard(); final Game game = host.getGame(); Map mapParams = Maps.newHashMap(sa.getMapParams()); + mapParams.remove("Cost"); if (mapParams.containsKey("SpellDescription")) { 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 0665b7fbe55..b7607038afa 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 @@ -27,6 +27,7 @@ import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.CardTranslation; import forge.util.TextUtil; import forge.util.collect.FCollection; @@ -113,7 +114,7 @@ public class EffectEffect extends SpellAbilityEffect { String name = sa.getParam("Name"); if (name == null) { - name = hostCard.getName() + (sa.hasParam("Boon") ? "'s Boon" : "'s Effect"); + name = CardTranslation.getTranslatedName(hostCard.getName()) + (sa.hasParam("Boon") ? "'s Boon" : "'s Effect"); } // Unique Effects shouldn't be duplicated diff --git a/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java index 335e8eeb3b7..9f848b2f8d7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java @@ -10,6 +10,7 @@ import forge.game.replacement.ReplacementHandler; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.CardTranslation; public class FogEffect extends SpellAbilityEffect { @@ -22,7 +23,7 @@ public class FogEffect extends SpellAbilityEffect { public void resolve(SpellAbility sa) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); - final String name = hostCard.getName() + "'s Effect"; + final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect"; final String image = hostCard.getImageKey(); StringBuilder sb = new StringBuilder("Event$ DamageDone | ActiveZones$ Command | IsCombat$ True"); sb.append(" | Prevent$ True | Description$ Prevent all combat damage this turn."); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java index 2ed822bb1d4..68f3e7142ac 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java @@ -15,6 +15,7 @@ import forge.game.trigger.Trigger; import forge.game.trigger.TriggerHandler; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.CardTranslation; public abstract class RegenerateBaseEffect extends SpellAbilityEffect { @@ -24,44 +25,44 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect { // create Effect for Regeneration final Card eff = createEffect( - sa, sa.getActivatingPlayer(), hostCard.getName() + "'s Regeneration", hostCard.getImageKey()); - + sa, sa.getActivatingPlayer(), CardTranslation.getTranslatedName(hostCard.getName()) + "'s Regeneration", hostCard.getImageKey()); + eff.addRemembered(list); addForgetOnMovedTrigger(eff, "Battlefield"); - + // build ReplacementEffect String repeffstr = "Event$ Destroy | ActiveZones$ Command | ValidCard$ Card.IsRemembered | Regeneration$ True" + " | Description$ Regeneration (if creature would be destroyed, regenerate it instead)"; - + String effect = "DB$ Regeneration | Defined$ ReplacedCard"; String exileEff = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile" + " | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0"; ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true); - + SpellAbility saReg = AbilityFactory.getAbility(effect, eff); - AbilitySub saExile = (AbilitySub)AbilityFactory.getAbility(exileEff, eff); + AbilitySub saExile = (AbilitySub)AbilityFactory.getAbility(exileEff, eff); saReg.setSubAbility(saExile); re.setOverridingAbility(saReg); eff.addReplacementEffect(re); - + // add extra Remembered if (sa.hasParam("RememberObjects")) { eff.addRemembered(AbilityUtils.getDefinedObjects(hostCard, sa.getParam("RememberObjects"), sa)); } - + if (sa.hasParam("RegenerationTrigger")) { final String str = sa.getSVar(sa.getParam("RegenerationTrigger")); - + SpellAbility trigSA = AbilityFactory.getAbility(str, eff); - + final String trigStr = "Mode$ Regenerated | ValidCause$ Effect.Self | TriggerZones$ Command " + " | TriggerDescription$ " + trigSA.getDescription(); final Trigger trigger = TriggerHandler.parseTrigger(trigStr, eff, true); trigger.setOverridingAbility(trigSA); eff.addTrigger(trigger); } - + // Copy text changes if (sa.isIntrinsic()) { eff.copyChangedTextFrom(hostCard); @@ -75,7 +76,7 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect { game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); - + final GameCommand untilEOT = new GameCommand() { private static final long serialVersionUID = 259368227093961103L; diff --git a/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java index 4c4ddc1f9fd..2e25b4f5373 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java @@ -15,6 +15,7 @@ import forge.game.replacement.ReplacementLayer; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.CardTranslation; public class SkipPhaseEffect extends SpellAbilityEffect { @@ -58,7 +59,7 @@ public class SkipPhaseEffect extends SpellAbilityEffect { final String duration, final String phase, final String step) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); - final String name = hostCard.getName() + "'s Effect"; + final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect"; final String image = hostCard.getImageKey(); final boolean isNextThisTurn = duration != null && duration.equals("NextThisTurn"); diff --git a/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java index 0d81ed142ca..ec956b5e12f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java @@ -16,6 +16,7 @@ import forge.game.spellability.AbilitySub; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; import forge.game.zone.ZoneType; +import forge.util.CardTranslation; import forge.util.Lang; public class SkipTurnEffect extends SpellAbilityEffect { @@ -38,7 +39,7 @@ public class SkipTurnEffect extends SpellAbilityEffect { public void resolve(SpellAbility sa) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); - final String name = hostCard.getName() + "'s Effect"; + final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect"; final String image = hostCard.getImageKey(); final int numTurns = AbilityUtils.calculateAmount(hostCard, sa.getParam("NumTurns"), sa); String repeffstr = "Event$ BeginTurn | ActiveZones$ Command | ValidPlayer$ You " + 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 1c3fdb8f152..9c85906bd83 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -299,7 +299,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { private Map goad = Maps.newTreeMap(); private final List leavePlayCommandList = Lists.newArrayList(); - private final List etbCommandList = Lists.newArrayList(); private final List untapCommandList = Lists.newArrayList(); private final List changeControllerCommandList = Lists.newArrayList(); private final List unattachCommandList = Lists.newArrayList(); @@ -3265,20 +3264,24 @@ public class Card extends GameEntity implements Comparable, IHasSVars { return canCounter; } - public final void addComesIntoPlayCommand(final GameCommand c) { - etbCommandList.add(c); - } - - public final void runComesIntoPlayCommands() { - for (final GameCommand c : etbCommandList) { - c.run(); - } - etbCommandList.clear(); - } - public final void addLeavesPlayCommand(final GameCommand c) { leavePlayCommandList.add(c); } + public final void addUntapCommand(final GameCommand c) { + untapCommandList.add(c); + } + public final void addUnattachCommand(final GameCommand c) { + unattachCommandList.add(c); + } + public final void addFaceupCommand(final GameCommand c) { + faceupCommandList.add(c); + } + public final void addFacedownCommand(final GameCommand c) { + facedownCommandList.add(c); + } + public final void addChangeControllerCommand(final GameCommand c) { + changeControllerCommandList.add(c); + } public final void runLeavesPlayCommands() { for (final GameCommand c : leavePlayCommandList) { @@ -3286,22 +3289,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } leavePlayCommandList.clear(); } - - public final void addUntapCommand(final GameCommand c) { - untapCommandList.add(c); - } - - public final void addUnattachCommand(final GameCommand c) { - unattachCommandList.add(c); - } - - public final void addFaceupCommand(final GameCommand c) { - faceupCommandList.add(c); - } - - public final void addFacedownCommand(final GameCommand c) { - facedownCommandList.add(c); - } public final void runUntapCommands() { for (final GameCommand c : untapCommandList) { c.run(); @@ -3314,25 +3301,18 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } unattachCommandList.clear(); } - public final void runFaceupCommands() { for (final GameCommand c : faceupCommandList) { c.run(); } faceupCommandList.clear(); } - public final void runFacedownCommands() { for (final GameCommand c : facedownCommandList) { c.run(); } facedownCommandList.clear(); } - - public final void addChangeControllerCommand(final GameCommand c) { - changeControllerCommandList.add(c); - } - public final void runChangeControllerCommands() { for (final GameCommand c : changeControllerCommandList) { c.run(); @@ -3346,16 +3326,16 @@ public class Card extends GameEntity implements Comparable, IHasSVars { view.updateSickness(this); } - public final boolean isFirstTurnControlled() { - return sickness; - } - public final boolean hasSickness() { return sickness && !hasKeyword(Keyword.HASTE); } public final boolean isSick() { - return sickness && isCreature() && !hasKeyword(Keyword.HASTE); + return hasSickness() && isCreature(); + } + + public final boolean isFirstTurnControlled() { + return sickness; } public boolean hasBecomeTargetThisTurn() { @@ -5070,7 +5050,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false); // when it doesn't exist the game will no longer see it as tapped runUntapCommands(); - // TODO need to run UntilHostLeavesPlay commands but only when worded "for as long as" + // TODO CR 702.26f need to run LeavesPlay + changeController commands but only when worded "for as long as" } setPhasedOut(!phasedOut); @@ -5636,7 +5616,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { @Override public final int addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat, GameEntityCounterTable counterTable) { if (damageIn <= 0) { - return 0; // Rule 119.8 + return 0; // 120.8 } // 120.1a Damage can’t be dealt to an object that’s neither a creature nor a planeswalker. diff --git a/forge-game/src/main/java/forge/game/card/CounterEnumType.java b/forge-game/src/main/java/forge/game/card/CounterEnumType.java index 16d43b010c5..6ab13e1b55f 100644 --- a/forge-game/src/main/java/forge/game/card/CounterEnumType.java +++ b/forge-game/src/main/java/forge/game/card/CounterEnumType.java @@ -294,6 +294,8 @@ public enum CounterEnumType { P2P2("+2/+2", "+2/+2", 96, 226, 23), QUEST("QUEST", 251, 189, 0), + + REPRIEVE("REPR", 240, 120, 50), RITUAL("RITUAL", 155, 17, 30), diff --git a/forge-game/src/main/java/forge/game/player/PlayerProperty.java b/forge-game/src/main/java/forge/game/player/PlayerProperty.java index 3bcda5ac413..a93167461f2 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerProperty.java +++ b/forge-game/src/main/java/forge/game/player/PlayerProperty.java @@ -160,7 +160,7 @@ public class PlayerProperty { return false; } } else if (property.equals("Defending")) { - if (!game.getCombat().getAttackersAndDefenders().values().contains(player)) { + if (game.getCombat() == null || !game.getCombat().getAttackersAndDefenders().values().contains(player)) { return false; } } else if (property.equals("LostLifeThisTurn")) { diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java index 43bd2d29646..adca5c1e5c2 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java @@ -29,7 +29,6 @@ public class StaticAbilityNumLoyaltyAct { } public static boolean applyLimitIncrease(final StaticAbility stAb, final Card card) { - if (!stAb.matchesValidParam("ValidCard", card)) { return false; } @@ -58,7 +57,7 @@ public class StaticAbilityNumLoyaltyAct { } } int more = AbilityUtils.calculateAmount(card, stAb.getParam("Additional"), stAb); - addl = addl + more; + addl += more; } } } diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index e4bf85331e9..479e7439b03 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -305,7 +305,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable { - public static FSkinImage MAIN_DECK_ICON = Forge.hdbuttons ? FSkinImage.HDLIBRARY :FSkinImage.DECKLIST; - public static FSkinImage SIDEBOARD_ICON = Forge.hdbuttons ? FSkinImage.HDSIDEBOARD : FSkinImage.FLASHBACK; - private static final float HEADER_HEIGHT = Math.round(Utils.AVG_FINGER_HEIGHT * 0.8f); - private static final FileHandle tomeIcon = Config.instance().getFile("ui/tome.png"); - private static Texture tomeIconTexture = tomeIcon.exists() ? new Texture(tomeIcon) : null; - private static FImage CATALOG_ICON = tomeIcon.exists() ? new FImage() { + private static final FileHandle deckIcon = Config.instance().getFile("ui/maindeck.png"); + private static Texture deckTexture = deckIcon.exists() ? new Texture(deckIcon) : null; + private static FImage MAIN_DECK_ICON = deckIcon.exists() ? new FImage() { @Override public float getWidth() { return 100f; @@ -55,7 +52,40 @@ import java.util.Map; } @Override public void draw(Graphics g, float x, float y, float w, float h) { - g.drawImage(tomeIconTexture, x, y, w, h); + g.drawImage(deckTexture, x, y, w, h); + } + } : Forge.hdbuttons ? FSkinImage.HDLIBRARY :FSkinImage.DECKLIST; + private static final FileHandle sideIcon = Config.instance().getFile("ui/sideboard.png"); + private static Texture sideTexture = sideIcon.exists() ? new Texture(sideIcon) : null; + private static FImage SIDEBOARD_ICON = sideIcon.exists() ? new FImage() { + @Override + public float getWidth() { + return 100f; + } + @Override + public float getHeight() { + return 100f; + } + @Override + public void draw(Graphics g, float x, float y, float w, float h) { + g.drawImage(sideTexture, x, y, w, h); + } + } : Forge.hdbuttons ? FSkinImage.HDSIDEBOARD : FSkinImage.FLASHBACK; + private static final float HEADER_HEIGHT = Math.round(Utils.AVG_FINGER_HEIGHT * 0.8f); + private static final FileHandle binderIcon = Config.instance().getFile("ui/binder.png"); + private static Texture binderTexture = binderIcon.exists() ? new Texture(binderIcon) : null; + private static FImage CATALOG_ICON = binderIcon.exists() ? new FImage() { + @Override + public float getWidth() { + return 100f; + } + @Override + public float getHeight() { + return 100f; + } + @Override + public void draw(Graphics g, float x, float y, float w, float h) { + g.drawImage(binderTexture, x, y, w, h); } } : FSkinImage.QUEST_BOX; private static final FileHandle sellIcon = Config.instance().getFile("ui/sell.png"); diff --git a/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java b/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java index df955d63e40..beb9aeef972 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java @@ -8,16 +8,13 @@ import forge.Graphics; import forge.LobbyPlayer; import forge.adventure.character.EnemySprite; import forge.adventure.character.PlayerSprite; -import forge.adventure.data.BiomeData; import forge.adventure.data.EffectData; import forge.adventure.data.EnemyData; import forge.adventure.data.ItemData; import forge.adventure.player.AdventurePlayer; import forge.adventure.stage.IAfterMatch; -import forge.adventure.stage.MapStage; import forge.adventure.util.Config; import forge.adventure.util.Current; -import forge.adventure.world.World; import forge.assets.FBufferedImage; import forge.assets.FSkin; import forge.deck.Deck; @@ -343,23 +340,6 @@ public class DuelScene extends ForgeScene { this.AIExtras.clear(); this.playerExtras.clear(); } - public String getCurrentLocation() { - String location = ""; - if(MapStage.getInstance().isInMap()) - location = TileMapScene.instance().rootPoint.getData().type; - else { - World world= Current.world(); - int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize())); - List biomeData = Current.world().getData().GetBiomes(); - try { - BiomeData data = biomeData.get(currentBiome); - location = data.name; - } catch (Exception e) { - e.printStackTrace(); - } - } - return location; - } private String selectAI(String ai) { //Decide opponent AI. String AI = ""; //Use user settings if it's null. diff --git a/forge-gui-mobile/src/forge/adventure/scene/GameScene.java b/forge-gui-mobile/src/forge/adventure/scene/GameScene.java index 595bf49453c..1698182a286 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/GameScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/GameScene.java @@ -3,8 +3,15 @@ package forge.adventure.scene; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; import forge.Forge; +import forge.adventure.character.PlayerSprite; +import forge.adventure.data.BiomeData; import forge.adventure.stage.MapStage; import forge.adventure.stage.WorldStage; +import forge.adventure.util.Current; +import forge.adventure.world.World; +import forge.util.TextUtil; + +import java.util.List; /** * Game scene main over world scene @@ -51,6 +58,24 @@ public class GameScene extends HudScene { super.enter(); WorldStage.getInstance().handlePointsOfInterestCollision(); } - + public String getAdventurePlayerLocation(boolean forHeader) { + String location = ""; + if(MapStage.getInstance().isInMap()) { + location = forHeader? TileMapScene.instance().rootPoint.getData().name : TileMapScene.instance().rootPoint.getData().type; + } else { + World world= Current.world(); + PlayerSprite player = WorldStage.getInstance().getPlayerSprite(); + int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize())); + List biomeData = Current.world().getData().GetBiomes(); + try { + BiomeData data = biomeData.get(currentBiome); + location = forHeader? TextUtil.capitalize(data.name)+" Map" : data.name; + } catch (Exception e) { + e.printStackTrace(); + location = ""; + } + } + return location; + } } diff --git a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java index aa0b94103c1..fa9436b5993 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java @@ -21,6 +21,7 @@ import forge.adventure.util.Current; import forge.adventure.world.WorldSave; import forge.adventure.world.WorldSaveHeader; import forge.screens.TransitionScreen; +import forge.util.TextUtil; import java.io.File; import java.io.FileInputStream; @@ -42,7 +43,7 @@ public class SaveLoadScene extends UIScene { TextraLabel header; int currentSlot = 0, lastSelectedSlot = 0; Image previewImage; - TextraLabel previewDate; + TextraLabel previewDate, playerLocation; Image previewBorder; TextraButton saveLoadButton, back; Selectable quickSave; @@ -50,6 +51,7 @@ public class SaveLoadScene extends UIScene { Actor lastHighlightedSave; SelectBox difficulty; ScrollPane scrollPane; + char ASCII_179 = '│'; private SaveLoadScene() { super(Forge.isLandscapeMode() ? "ui/save_load.json" : "ui/save_load_portrait.json"); @@ -68,9 +70,13 @@ public class SaveLoadScene extends UIScene { //DifficultyData difficulty1 = Config.instance().getConfigData().difficulties[difficulty.getSelectedIndex()]; return null; }); - previewImage = ui.findActor("preview"); previewDate = ui.findActor("saveDate"); + playerLocation = Controls.newTextraLabel(""); + playerLocation.setText(""); + playerLocation.setX(previewImage.getX()); + playerLocation.setY(previewImage.getY()+5); + ui.addActor(playerLocation); header = Controls.newTextraLabel(Forge.getLocalizer().getMessage("lblSave")); header.setAlignment(Align.center); layout.add(header).pad(2).colspan(4).align(Align.center).expandX(); @@ -169,9 +175,19 @@ public class SaveLoadScene extends UIScene { previewImage.setVisible(true); previewDate.setVisible(true); if (header.saveDate != null) - previewDate.setText(DateFormat.getDateInstance().format(header.saveDate) + "\n" + DateFormat.getTimeInstance(DateFormat.SHORT).format(header.saveDate)); + previewDate.setText("{Scale=98%}"+DateFormat.getDateInstance().format(header.saveDate) + " " + DateFormat.getTimeInstance(DateFormat.SHORT).format(header.saveDate)); else previewDate.setText(""); + if (header.name.contains(Character.toString(ASCII_179))) { + String[] split = TextUtil.split(header.name, ASCII_179); + try { + playerLocation.setText(split[1]); + } catch (Exception e) { + playerLocation.setText(""); + } + } else { + playerLocation.setText(""); + } } } else { if (previewImage != null) @@ -239,7 +255,7 @@ public class SaveLoadScene extends UIScene { public void save() { - if (WorldSave.getCurrentSave().save(textInput.getText(), currentSlot)) { + if (WorldSave.getCurrentSave().save(textInput.getText()+ASCII_179+GameScene.instance().getAdventurePlayerLocation(true), currentSlot)) { updateFiles(); //ensure the dialog is hidden before switching @@ -275,7 +291,13 @@ public class SaveLoadScene extends UIScene { int slot = WorldSave.filenameToSlot(name.getName()); WorldSaveHeader header = (WorldSaveHeader) oos.readObject(); - buttons.get(slot).actor.setText(header.name); + if (header.name.contains(Character.toString(ASCII_179))) { + String[] split = TextUtil.split(header.name, ASCII_179); + buttons.get(slot).actor.setText(split[0]); + //playerLocation.setText(split[1]); + } else { + buttons.get(slot).actor.setText(header.name); + } previews.put(slot, header); } diff --git a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java index d6c930b7877..03b29869492 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java +++ b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java @@ -111,12 +111,12 @@ public class GameHUD extends Stage { lifePoints = ui.findActor("lifePoints"); mana = ui.findActor("mana"); money = ui.findActor("money"); - mana.setText("0/0"); - lifePoints.setText("20/20"); - AdventurePlayer.current().onLifeChange(() -> lifePoints.setText(AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife())); - AdventurePlayer.current().onManaChange(() -> mana.setText(AdventurePlayer.current().getMana() + "/" + AdventurePlayer.current().getMaxMana())); + mana.setText("{Scale=80%}0/0"); + lifePoints.setText("{Scale=80%}20/20"); + AdventurePlayer.current().onLifeChange(() -> lifePoints.setText("{Scale=80%}"+AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife())); + AdventurePlayer.current().onManaChange(() -> mana.setText("{Scale=80%}"+AdventurePlayer.current().getMana() + "/" + AdventurePlayer.current().getMaxMana())); - WorldSave.getCurrentSave().getPlayer().onGoldChange(() -> money.setText(String.valueOf(AdventurePlayer.current().getGold()))); + WorldSave.getCurrentSave().getPlayer().onGoldChange(() -> money.setText("{Scale=80%}"+String.valueOf(AdventurePlayer.current().getGold()))); addActor(ui); addActor(miniMapPlayer); console = new Console(); diff --git a/forge-gui-mobile/src/forge/itemmanager/CardManager.java b/forge-gui-mobile/src/forge/itemmanager/CardManager.java index 937721f763d..6f194a42afc 100644 --- a/forge-gui-mobile/src/forge/itemmanager/CardManager.java +++ b/forge-gui-mobile/src/forge/itemmanager/CardManager.java @@ -2,7 +2,6 @@ package forge.itemmanager; import java.util.Map.Entry; -import forge.Forge; import forge.Graphics; import forge.assets.FSkinColor; import forge.assets.FSkinFont; @@ -49,8 +48,7 @@ public class CardManager extends ItemManager { public static void addDefaultFilters(final ItemManager itemManager) { itemManager.addFilter(new CardColorFilter(itemManager)); - if (!Forge.isMobileAdventureMode) - itemManager.addFilter(new CardFormatFilter(itemManager)); + itemManager.addFilter(new CardFormatFilter(itemManager)); itemManager.addFilter(new CardTypeFilter(itemManager)); } diff --git a/forge-gui-mobile/src/forge/itemmanager/filters/FormatFilter.java b/forge-gui-mobile/src/forge/itemmanager/filters/FormatFilter.java index 0db437ac335..79d18810b91 100644 --- a/forge-gui-mobile/src/forge/itemmanager/filters/FormatFilter.java +++ b/forge-gui-mobile/src/forge/itemmanager/filters/FormatFilter.java @@ -47,6 +47,7 @@ public abstract class FormatFilter extends ItemFilter 2000 ? 1.5f : 1f; - if (FSkin.getLogo() != null) { - g.drawImage(FSkin.getLogo(), Forge.getScreenWidth()/2 - (FSkin.getLogo().getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkin.getLogo().getHeight()*xmod)/2, FSkin.getLogo().getWidth()*xmod, FSkin.getLogo().getHeight()*xmod); + + if (logo != null) { + g.drawImage(logo, Forge.getScreenWidth()/2 - (logo.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (logo.getHeight()*xmod)/2, logo.getWidth()*xmod, logo.getHeight()*xmod); } else { - g.drawImage(FSkinImage.LOGO,Forge.getScreenWidth()/2 - (FSkinImage.LOGO.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkinImage.LOGO.getHeight()*xmod)/1.5f, FSkinImage.LOGO.getWidth()*xmod, FSkinImage.LOGO.getHeight()*xmod); + g.drawImage(FSkinImage.LOGO, Forge.getScreenWidth()/2 - (FSkinImage.LOGO.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkinImage.LOGO.getHeight()*xmod)/1.5f, FSkinImage.LOGO.getWidth()*xmod, FSkinImage.LOGO.getHeight()*xmod); } } @@ -87,12 +94,12 @@ public class ClosingScreen extends FContainer { } g.fillRect(Color.BLACK, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight()); g.setAlphaComposite(percentage); - g.drawImage(Forge.isMobileAdventureMode ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight()); + g.drawImage(Forge.isMobileAdventureMode || Forge.advStartup ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight()); g.setAlphaComposite(oldAlpha); float xmod = Forge.getScreenHeight() > 2000 ? 1.5f : 1f; xmod *= 21-(20*percentage); - if (FSkin.getLogo() != null) { - g.drawImage(FSkin.getLogo(), Forge.getScreenWidth()/2 - (FSkin.getLogo().getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkin.getLogo().getHeight()*xmod)/2, FSkin.getLogo().getWidth()*xmod, FSkin.getLogo().getHeight()*xmod); + if (logo != null) { + g.drawImage(logo, Forge.getScreenWidth()/2 - (logo.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (logo.getHeight()*xmod)/2, logo.getWidth()*xmod, logo.getHeight()*xmod); } else { g.drawImage(FSkinImage.LOGO,Forge.getScreenWidth()/2 - (FSkinImage.LOGO.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkinImage.LOGO.getHeight()*xmod)/1.5f, FSkinImage.LOGO.getWidth()*xmod, FSkinImage.LOGO.getHeight()*xmod); } diff --git a/forge-gui-mobile/src/forge/screens/TransitionScreen.java b/forge-gui-mobile/src/forge/screens/TransitionScreen.java index e8f7af7bed5..72ac3eeaed8 100644 --- a/forge-gui-mobile/src/forge/screens/TransitionScreen.java +++ b/forge-gui-mobile/src/forge/screens/TransitionScreen.java @@ -19,7 +19,7 @@ public class TransitionScreen extends FContainer { Runnable runnable; TextureRegion textureRegion; private String message = ""; - boolean matchTransition, isloading, isIntro, isFadeMusic, advStartup; + boolean matchTransition, isloading, isIntro, isFadeMusic; public TransitionScreen(Runnable proc, TextureRegion screen, boolean enterMatch, boolean loading) { this(proc, screen, enterMatch, loading, false, false); @@ -43,7 +43,7 @@ public class TransitionScreen extends FContainer { isIntro = intro; isFadeMusic = fadeMusic; message = loadingMessage; - advStartup = Forge.selector.equals("Adventure"); + Forge.advStartup = Forge.selector.equals("Adventure"); } public FProgressBar getProgressBar() { @@ -111,7 +111,7 @@ public class TransitionScreen extends FContainer { g.drawWarpImage(textureRegion, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight(), percentage); } else if (isIntro) { if (textureRegion != null) { - if (advStartup) { + if (Forge.advStartup) { g.drawGrayTransitionImage(Forge.getAssets().fallback_skins().get(0), 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight(), false, percentage); g.setAlphaComposite(1-percentage); g.drawImage(textureRegion, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight()); diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 92926f26f63..60c343330f1 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -4,7 +4,7 @@ import java.util.*; import java.util.Map.Entry; import com.badlogic.gdx.math.Vector2; -import forge.adventure.scene.DuelScene; +import forge.adventure.scene.GameScene; import forge.animation.ForgeAnimation; import forge.assets.FImage; import forge.card.CardImageRenderer; @@ -807,7 +807,7 @@ public class MatchScreen extends FScreen { FSkinTexture getBG() { if (Forge.isMobileAdventureMode) { //System.out.println("Adventure Location: "+DuelScene.instance().getCurrentLocation()); - switch(DuelScene.instance().getCurrentLocation()) { + switch(GameScene.instance().getAdventurePlayerLocation(false)) { case "green": return FSkinTexture.ADV_BG_FOREST; case "black": diff --git a/forge-gui/res/adventure/Shandalar/ui/binder.png b/forge-gui/res/adventure/Shandalar/ui/binder.png new file mode 100644 index 00000000000..2a0c82c9188 Binary files /dev/null and b/forge-gui/res/adventure/Shandalar/ui/binder.png differ diff --git a/forge-gui/res/adventure/Shandalar/ui/maindeck.png b/forge-gui/res/adventure/Shandalar/ui/maindeck.png new file mode 100644 index 00000000000..0c0316d584f Binary files /dev/null and b/forge-gui/res/adventure/Shandalar/ui/maindeck.png differ diff --git a/forge-gui/res/adventure/Shandalar/ui/save_load.json b/forge-gui/res/adventure/Shandalar/ui/save_load.json index dba74b8deeb..6f77b073af9 100644 --- a/forge-gui/res/adventure/Shandalar/ui/save_load.json +++ b/forge-gui/res/adventure/Shandalar/ui/save_load.json @@ -36,8 +36,8 @@ { "type": "Label", "name": "saveDate", - "x": 390, - "y": 125, + "x": 370, + "y": 24, "width": 86, "height": 32 }, diff --git a/forge-gui/res/adventure/Shandalar/ui/save_load_portrait.json b/forge-gui/res/adventure/Shandalar/ui/save_load_portrait.json index fc88558c579..397b785aef4 100644 --- a/forge-gui/res/adventure/Shandalar/ui/save_load_portrait.json +++ b/forge-gui/res/adventure/Shandalar/ui/save_load_portrait.json @@ -36,8 +36,8 @@ { "type": "Label", "name": "saveDate", - "x": 70, - "y": 40, + "x": 170, + "y": 8, "width": 96, "height": 16 }, diff --git a/forge-gui/res/adventure/Shandalar/ui/sideboard.png b/forge-gui/res/adventure/Shandalar/ui/sideboard.png new file mode 100644 index 00000000000..dc5f41332cb Binary files /dev/null and b/forge-gui/res/adventure/Shandalar/ui/sideboard.png differ diff --git a/forge-gui/res/cardsfolder/a/academy_loremaster.txt b/forge-gui/res/cardsfolder/a/academy_loremaster.txt index 81b9e42eb11..18ba66a4651 100644 --- a/forge-gui/res/cardsfolder/a/academy_loremaster.txt +++ b/forge-gui/res/cardsfolder/a/academy_loremaster.txt @@ -2,9 +2,9 @@ Name:Academy Loremaster ManaCost:U U Types:Creature Human Wizard PT:2/3 -T:Mode$ Phase | Phase$ Draw | ValidPlayer$ Player | TriggerZones$ Battlefield | OptionalDecider$ TriggeredPlayer | Execute$ TrigDraw | TriggerDescription$ At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast +T:Mode$ Phase | Phase$ Draw | ValidPlayer$ Player | TriggerZones$ Battlefield | OptionalDecider$ TriggeredPlayer | Execute$ TrigDraw | TriggerDescription$ At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast. SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ TriggeredPlayer | RememberDrawn$ True | SubAbility$ DBEffect -SVar:DBEffect:DB$ Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | Duration$ EndOfTurn | StaticAbilities$ RaiseCost | SubAbility$ DBCleanup | SpellDescription$ Spells they cast this turn cost {2} more to cast -SVar:RaiseCost:Mode$ RaiseCost | ValidCard$ Card.ActivePlayerCtrl | Type$ Spell | Amount$ 2 | Description$ Spells they cast this turn cost {2} more to cast +SVar:DBEffect:DB$ Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | Duration$ EndOfTurn | StaticAbilities$ RaiseCost | SubAbility$ DBCleanup +SVar:RaiseCost:Mode$ RaiseCost | ValidCard$ Card.ActivePlayerCtrl | Type$ Spell | Amount$ 2 | Description$ Spells they cast this turn cost {2} more to cast. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -Oracle:At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast +Oracle:At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast. diff --git a/forge-gui/res/cardsfolder/a/awakening.txt b/forge-gui/res/cardsfolder/a/awakening.txt index f72b293b02a..6949b70094d 100644 --- a/forge-gui/res/cardsfolder/a/awakening.txt +++ b/forge-gui/res/cardsfolder/a/awakening.txt @@ -2,7 +2,7 @@ Name:Awakening ManaCost:2 G G Types:Enchantment T:Mode$ Phase | Phase$ Upkeep | TriggerZones$ Battlefield | Execute$ TrigUntapAll | TriggerDescription$ At the beginning of each upkeep, untap all creatures and lands. -SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature,Land | SpellDescription$ untap all creatures and lands. +SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature,Land SVar:UntapsEachTurn:Creature,Land AI:RemoveDeck:Random Oracle:At the beginning of each upkeep, untap all creatures and lands. diff --git a/forge-gui/res/cardsfolder/b/barbed_shocker.txt b/forge-gui/res/cardsfolder/b/barbed_shocker.txt index bc5adff1780..5e8fb13273b 100644 --- a/forge-gui/res/cardsfolder/b/barbed_shocker.txt +++ b/forge-gui/res/cardsfolder/b/barbed_shocker.txt @@ -5,8 +5,8 @@ PT:2/2 K:Trample K:Haste T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | TriggerZones$ Battlefield | Execute$ TrigDiscard | TriggerDescription$ Whenever CARDNAME deals damage to a player, that player discards all the cards in their hand, then draws that many cards. -SVar:TrigDiscard:DB$ Discard | Defined$ TriggeredTarget | Mode$ Hand | RememberDiscarded$ True | SubAbility$ DBDraw | SpellDescription$ Discard hand -SVar:DBDraw:DB$ Draw | NumCards$ X | Defined$ TriggeredTarget | SubAbility$ DBCleanup | SpellDescription$ Draw that many cards +SVar:TrigDiscard:DB$ Discard | Defined$ TriggeredTarget | Mode$ Hand | RememberDiscarded$ True | SubAbility$ DBDraw +SVar:DBDraw:DB$ Draw | NumCards$ X | Defined$ TriggeredTarget | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Remembered$Amount Oracle:Trample, haste\nWhenever Barbed Shocker deals damage to a player, that player discards all the cards in their hand, then draws that many cards. diff --git a/forge-gui/res/cardsfolder/b/bartered_cow.txt b/forge-gui/res/cardsfolder/b/bartered_cow.txt index 306ee01e996..c81014c01ad 100644 --- a/forge-gui/res/cardsfolder/b/bartered_cow.txt +++ b/forge-gui/res/cardsfolder/b/bartered_cow.txt @@ -2,8 +2,8 @@ Name:Bartered Cow ManaCost:3 W Types:Creature Ox PT:3/3 -T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | TriggerController$ TriggeredCardController | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies or blocks you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") -T:Mode$ Discarded | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies or blocks you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | TriggerController$ TriggeredCardController | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies or when you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") +T:Mode$ Discarded | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies or when you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_food_sac | TokenOwner$ You SVar:SacMe:1 SVar:DiscardMe:3 diff --git a/forge-gui/res/cardsfolder/b/benthicore.txt b/forge-gui/res/cardsfolder/b/benthicore.txt index 1f1c8db3028..c2ed26357cc 100644 --- a/forge-gui/res/cardsfolder/b/benthicore.txt +++ b/forge-gui/res/cardsfolder/b/benthicore.txt @@ -3,7 +3,7 @@ ManaCost:6 U Types:Creature Elemental PT:5/5 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 1/1 blue Merfolk Wizard creature tokens. -SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ u_1_1_merfolk_wizard | TokenOwner$ You | SpellDescription$ Create two 1/1 blue Merfolk Wizard creature tokens. +SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ u_1_1_merfolk_wizard | TokenOwner$ You A:AB$ Untap | Cost$ tapXType<2/Merfolk> | SubAbility$ GainShroud | SpellDescription$ Untap CARDNAME. SVar:GainShroud:DB$ Pump | Defined$ Self | KW$ Shroud | SpellDescription$ CARDNAME gains shroud until end of turn. Oracle:When Benthicore enters the battlefield, create two 1/1 blue Merfolk Wizard creature tokens.\nTap two untapped Merfolk you control: Untap Benthicore. It gains shroud until end of turn. (It can't be the target of spells or abilities.) diff --git a/forge-gui/res/cardsfolder/b/borborygmos_enraged.txt b/forge-gui/res/cardsfolder/b/borborygmos_enraged.txt index 5e9275c28e5..cabfd133ee1 100644 --- a/forge-gui/res/cardsfolder/b/borborygmos_enraged.txt +++ b/forge-gui/res/cardsfolder/b/borborygmos_enraged.txt @@ -4,6 +4,6 @@ Types:Legendary Creature Cyclops PT:7/6 K:Trample T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDig | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, reveal the top three cards of your library. Put all land cards revealed this way into your hand and the rest into your graveyard. -SVar:TrigDig:DB$ Dig | DigNum$ 3 | Defined$ You | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone2$ Graveyard | SpellDescription$ Reveal the top three cards of your library. Put all land cards revealed this way into your hand and the rest into your graveyard. +SVar:TrigDig:DB$ Dig | DigNum$ 3 | Defined$ You | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone2$ Graveyard A:AB$ DealDamage | Cost$ Discard<1/Land> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to any target. Oracle:Trample\nWhenever Borborygmos Enraged deals combat damage to a player, reveal the top three cards of your library. Put all land cards revealed this way into your hand and the rest into your graveyard.\nDiscard a land card: Borborygmos Enraged deals 3 damage to any target. diff --git a/forge-gui/res/cardsfolder/c/crafty_cutpurse.txt b/forge-gui/res/cardsfolder/c/crafty_cutpurse.txt index fab73f2e1e7..7bafc1cafef 100644 --- a/forge-gui/res/cardsfolder/c/crafty_cutpurse.txt +++ b/forge-gui/res/cardsfolder/c/crafty_cutpurse.txt @@ -4,7 +4,7 @@ Types:Creature Human Pirate PT:2/2 K:Flash T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME enters the battlefield, each token that would be created under an opponent's control this turn is created under your control instead. -SVar:TrigEffect:DB$ Effect | Name$ Crafty Cutpurse Effect | ReplacementEffects$ OppCreatEnters | SpellDescription$ Each token that would be created under an opponent's control this turn is created under your control instead. +SVar:TrigEffect:DB$ Effect | Name$ Crafty Cutpurse Effect | ReplacementEffects$ OppCreatEnters SVar:OppCreatEnters:Event$ CreateToken | ActiveZones$ Command | ValidToken$ Card.OppCtrl | ReplaceWith$ ETBYourCtrl | Layer$ Control | Description$ Each token that would be created under an opponent's control this turn is created under your control instead. SVar:ETBYourCtrl:DB$ ReplaceToken | Type$ ReplaceController | ValidCard$ Card.OppCtrl | NewController$ You Oracle:Flash\nWhen Crafty Cutpurse enters the battlefield, each token that would be created under an opponent's control this turn is created under your control instead. diff --git a/forge-gui/res/cardsfolder/d/deathbringer_thoctar.txt b/forge-gui/res/cardsfolder/d/deathbringer_thoctar.txt index 2d172243e28..4c05365dd52 100644 --- a/forge-gui/res/cardsfolder/d/deathbringer_thoctar.txt +++ b/forge-gui/res/cardsfolder/d/deathbringer_thoctar.txt @@ -4,5 +4,6 @@ Types:Creature Zombie Beast PT:3/3 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.Other | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature dies, you may put a +1/+1 counter on CARDNAME. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 -A:AB$ DealDamage | Cost$ SubCounter<1/P1P1> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target. +A:AB$ DealDamage | Cost$ SubCounter<1/P1P1> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ It deals 1 damage to any target. +DeckHas:Ability$Counters Oracle:Whenever another creature dies, you may put a +1/+1 counter on Deathbringer Thoctar.\nRemove a +1/+1 counter from Deathbringer Thoctar: It deals 1 damage to any target. diff --git a/forge-gui/res/cardsfolder/d/debt_of_loyalty.txt b/forge-gui/res/cardsfolder/d/debt_of_loyalty.txt index ecbe779974b..c0d9ba4d9e0 100644 --- a/forge-gui/res/cardsfolder/d/debt_of_loyalty.txt +++ b/forge-gui/res/cardsfolder/d/debt_of_loyalty.txt @@ -2,6 +2,6 @@ Name:Debt of Loyalty ManaCost:1 W W Types:Instant A:SP$ Regenerate | Cost$ 1 W W | ValidTgts$ Creature | TgtPrompt$ Select target creature | RegenerationTrigger$ TrigGainControl | SpellDescription$ Regenerate target creature. You gain control of that creature if it regenerates this way. -SVar:TrigGainControl:ST$ GainControl | Cost$ 0 | Defined$ TriggeredCard | NewController$ You | SpellDescription$ Source controller gains control of CARDNAME if it regenerates this way. +SVar:TrigGainControl:ST$ GainControl | Cost$ 0 | Defined$ TriggeredCard | NewController$ You AI:RemoveDeck:All Oracle:Regenerate target creature. You gain control of that creature if it regenerates this way. diff --git a/forge-gui/res/cardsfolder/d/deserters_quarters.txt b/forge-gui/res/cardsfolder/d/deserters_quarters.txt index 866d8c0df9d..a7dec7c3ceb 100644 --- a/forge-gui/res/cardsfolder/d/deserters_quarters.txt +++ b/forge-gui/res/cardsfolder/d/deserters_quarters.txt @@ -2,7 +2,7 @@ Name:Deserter's Quarters ManaCost:2 Types:Artifact K:You may choose not to untap CARDNAME during your untap step. -A:AB$ Tap | Cost$ 6 T | ValidTgts$ Creature | RememberTapped$ True | AlwaysRemember$ True | SpellDescription$ Tap target creature. It doesn't untap during its controller's untap step for as long as Deserter's Quarters remains tapped. | StackDescription$ SpellDescription +A:AB$ Tap | Cost$ 6 T | ValidTgts$ Creature | RememberTapped$ True | AlwaysRemember$ True | SpellDescription$ Tap target creature. It doesn't untap during its controller's untap step for as long as CARDNAME remains tapped. | StackDescription$ SpellDescription S:Mode$ Continuous | Affected$ Card.IsRemembered | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ ClearRemembered | Static$ True SVar:ClearRemembered:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/d/dragonborn_champion.txt b/forge-gui/res/cardsfolder/d/dragonborn_champion.txt index d9ab5d07aa1..9d58306dffd 100644 --- a/forge-gui/res/cardsfolder/d/dragonborn_champion.txt +++ b/forge-gui/res/cardsfolder/d/dragonborn_champion.txt @@ -4,5 +4,5 @@ Types:Creature Dragon Warrior PT:5/3 K:Trample T:Mode$ DamageDone | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Player | TriggerZones$ Battlefield | DamageAmount$ GE5 | Execute$ TrigDraw | TriggerDescription$ Whenever a source you control deals 5 or more damage to a player, draw a card. -SVar:TrigDraw:DB$ Draw | NumCards$ 1 | SpellDescription$ Draw a card. +SVar:TrigDraw:DB$ Draw | NumCards$ 1 Oracle:Trample\nWhenever a source you control deals 5 or more damage to a player, draw a card. diff --git a/forge-gui/res/cardsfolder/e/euroakus.txt b/forge-gui/res/cardsfolder/e/euroakus.txt index cc4bf947253..7cf889a96f9 100644 --- a/forge-gui/res/cardsfolder/e/euroakus.txt +++ b/forge-gui/res/cardsfolder/e/euroakus.txt @@ -3,7 +3,7 @@ ManaCost:4 G G Types:Legendary Creature Treefolk Wizard PT:6/6 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a number of 1/1 blue Human Wizard creature tokens equal to the number of differently named lands you control. -SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ u_1_1_human_wizard | SpellDescription$ Create a number of 1/1 blue Human Wizard creature tokens equal to the number of differently named lands you control. +SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ u_1_1_human_wizard SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield A:AB$ Draw | Cost$ 4 G U | NumCards$ Y | SubAbility$ PumpAll | SpellDescription$ Draw a card for each Wizard you control. They each get +1/+1 until end of turn for each card in your hand. SVar:Y:Count$Valid Wizard.YouCtrl diff --git a/forge-gui/res/cardsfolder/g/gate_to_the_aether.txt b/forge-gui/res/cardsfolder/g/gate_to_the_aether.txt index 41e10748a6a..2ca8189afc6 100644 --- a/forge-gui/res/cardsfolder/g/gate_to_the_aether.txt +++ b/forge-gui/res/cardsfolder/g/gate_to_the_aether.txt @@ -1,7 +1,7 @@ Name:Gate to the Aether ManaCost:6 Types:Artifact -T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigAetherDig | TriggerController$ TriggeredPlayer | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player reveals the top card of their library. If it's an artifact, creature, enchantment, or land card, the player may put it onto the battlefield. -SVar:TrigAetherDig:DB$ Dig | Defined$ TriggeredPlayer | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Artifact,Creature,Enchantment,Land +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigAetherDig | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player reveals the top card of their library. If it's an artifact, creature, enchantment, or land card, the player may put it onto the battlefield. +SVar:TrigAetherDig:DB$ Dig | Defined$ TriggeredPlayer | Choser$ TriggeredPlayer | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Artifact,Creature,Enchantment,Land AI:RemoveDeck:Random Oracle:At the beginning of each player's upkeep, that player reveals the top card of their library. If it's an artifact, creature, enchantment, or land card, the player may put it onto the battlefield. diff --git a/forge-gui/res/cardsfolder/g/genesis_chamber.txt b/forge-gui/res/cardsfolder/g/genesis_chamber.txt index 91ff9e9bfa0..ee1c96f536e 100644 --- a/forge-gui/res/cardsfolder/g/genesis_chamber.txt +++ b/forge-gui/res/cardsfolder/g/genesis_chamber.txt @@ -2,7 +2,7 @@ Name:Genesis Chamber ManaCost:2 Types:Artifact T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken | TriggerZones$ Battlefield | Execute$ TrigToken | IsPresent$ Card.Self+untapped | TriggerDescription$ Whenever a nontoken creature enters the battlefield, if CARDNAME is untapped, that creature's controller creates a 1/1 colorless Myr artifact creature token. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ TriggeredCardController | TokenScript$ c_1_1_a_myr | SpellDescription$ Create a 1/1 Myr artifact creature token. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ TriggeredCardController | TokenScript$ c_1_1_a_myr AI:RemoveDeck:Random DeckHas:Ability$Token Oracle:Whenever a nontoken creature enters the battlefield, if Genesis Chamber is untapped, that creature's controller creates a 1/1 colorless Myr artifact creature token. diff --git a/forge-gui/res/cardsfolder/i/irregular_cohort.txt b/forge-gui/res/cardsfolder/i/irregular_cohort.txt index a3a211266f9..6e999cb2d97 100644 --- a/forge-gui/res/cardsfolder/i/irregular_cohort.txt +++ b/forge-gui/res/cardsfolder/i/irregular_cohort.txt @@ -4,6 +4,6 @@ Types:Creature Shapeshifter PT:2/2 K:Changeling T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a colorless Shapeshifter creature token with changeling. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_2_2_shapeshifter_changeling | TokenOwner$ You | SpellDescription$ Create a 2/2 colorless Shapeshifter creature token with changeling. (It has every creature type.) +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_2_2_shapeshifter_changeling | TokenOwner$ You DeckHas:Ability$Token Oracle:Changeling (This card is every creature type.)\nWhen Irregular Cohort enters the battlefield, create a 2/2 colorless Shapeshifter creature token with changeling. diff --git a/forge-gui/res/cardsfolder/j/jolrael_mwonvuli_recluse.txt b/forge-gui/res/cardsfolder/j/jolrael_mwonvuli_recluse.txt index 6984b82d5dd..3d617ce3faa 100644 --- a/forge-gui/res/cardsfolder/j/jolrael_mwonvuli_recluse.txt +++ b/forge-gui/res/cardsfolder/j/jolrael_mwonvuli_recluse.txt @@ -3,7 +3,7 @@ ManaCost:1 G Types:Legendary Creature Human Druid PT:1/2 T:Mode$ Drawn | ValidCard$ Card.YouCtrl | Number$ 2 | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever you draw your second card each turn, create a 2/2 green Cat creature token. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ g_2_2_cat | SpellDescription$ Create a 2/2 green Cat creature token. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ g_2_2_cat DeckHas:Ability$Token A:AB$ AnimateAll | Cost$ 4 G G | ValidCards$ Creature.YouCtrl | Power$ X | Toughness$ X | SpellDescription$ Until end of turn, creatures you control have base power and toughness X/X, where X is the number of cards in your hand. SVar:X:Count$InYourHand diff --git a/forge-gui/res/cardsfolder/j/josu_vess_lich_knight.txt b/forge-gui/res/cardsfolder/j/josu_vess_lich_knight.txt index 234b0820e55..55a55261d77 100644 --- a/forge-gui/res/cardsfolder/j/josu_vess_lich_knight.txt +++ b/forge-gui/res/cardsfolder/j/josu_vess_lich_knight.txt @@ -5,6 +5,6 @@ PT:4/5 K:Kicker:5 B K:Menace T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked | Origin$ Any | Destination$ Battlefield | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace. -SVar:TrigToken:DB$ Token | TokenAmount$ 8 | TokenScript$ b_2_2_zombie_knight_menace | TokenOwner$ You | SpellDescription$ When CARDNAME enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace. +SVar:TrigToken:DB$ Token | TokenAmount$ 8 | TokenScript$ b_2_2_zombie_knight_menace | TokenOwner$ You DeckHas:Ability$Token Oracle:Kicker {5}{B} (You may pay an additional {5}{B} as you cast this spell.)\nMenace\nWhen Josu Vess, Lich Knight enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace. diff --git a/forge-gui/res/cardsfolder/m/militant_angel.txt b/forge-gui/res/cardsfolder/m/militant_angel.txt index 2e468461510..1a47c0b7b7d 100644 --- a/forge-gui/res/cardsfolder/m/militant_angel.txt +++ b/forge-gui/res/cardsfolder/m/militant_angel.txt @@ -5,6 +5,6 @@ PT:3/4 K:Flying K:Lifelink T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn. -SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenAmount$ X | TokenScript$ w_2_2_knight_vigilance | SpellDescription$ Create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn. +SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenAmount$ X | TokenScript$ w_2_2_knight_vigilance SVar:X:TriggeredCardController$OpponentsAttackedThisTurn Oracle:Flying, lifelink\nWhen Militant Angel enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn. diff --git a/forge-gui/res/cardsfolder/o/obzedat_ghost_council.txt b/forge-gui/res/cardsfolder/o/obzedat_ghost_council.txt index 8f1da8421b5..c1262308ae2 100644 --- a/forge-gui/res/cardsfolder/o/obzedat_ghost_council.txt +++ b/forge-gui/res/cardsfolder/o/obzedat_ghost_council.txt @@ -6,9 +6,8 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S SVar:TrigDrain:DB$ LoseLife | ValidTgts$ Opponent | LifeAmount$ 2 | SubAbility$ DBGainLife SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ At the beginning of your end step you may exile NICKNAME. If you do, return it to the battlefield under it's owner's control at the beginning of your next upkeep. It gains haste. -SVar:TrigExile:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBDelaytrig -SVar:DBDelaytrig:DB$ Effect | Name$ Obzedat Effect | Triggers$ TrigEOT | RememberObjects$ Self | Duration$ Permanent -SVar:TrigEOT:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ ObzedatReturn | OneOff$ True | TriggerDescription$ Return CARDNAME to the battlefield under it's owner's control. It gains haste. -SVar:ObzedatReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | SubAbility$ ObzedatPump +SVar:TrigExile:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DelTrig +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ ObzedatReturn | ConditionDefined$ Remembered | ConditionPresent$ Card | RememberObjects$ Remembered | TriggerDescription$ Return CARDNAME to the battlefield under its owner's control at the beginning of the next end step. +SVar:ObzedatReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Exile,Command | Destination$ Battlefield | SubAbility$ ObzedatPump SVar:ObzedatPump:DB$ Pump | Defined$ Remembered | KW$ Haste | Duration$ Permanent Oracle:When Obzedat, Ghost Council enters the battlefield, target opponent loses 2 life and you gain 2 life.\nAt the beginning of your end step, you may exile Obzedat. If you do, return it to the battlefield under its owner's control at the beginning of your next upkeep. It gains haste. diff --git a/forge-gui/res/cardsfolder/o/old_man_of_the_sea.txt b/forge-gui/res/cardsfolder/o/old_man_of_the_sea.txt index 362760aebbd..f71e2a6507e 100644 --- a/forge-gui/res/cardsfolder/o/old_man_of_the_sea.txt +++ b/forge-gui/res/cardsfolder/o/old_man_of_the_sea.txt @@ -3,7 +3,7 @@ ManaCost:1 U U Types:Creature Djinn PT:2/3 K:You may choose not to untap CARDNAME during your untap step. -A:AB$ GainControl | Cost$ T | ValidTgts$ Creature.powerLEX | TgtPrompt$ Select target creature with power less than or equal to Old Man's. | LoseControl$ Untap,LeavesPlay,LoseControl,StaticCommandCheck | StaticCommandCheckSVar$ Y | StaticCommandSVarCompare$ GTX | SpellDescription$ Gain control of target creature with power less than or equal to Old Man of the Sea's power for as long as Old Man of the Sea remains tapped and that creature's power remains less than or equal to Old Man of the Sea's power. +A:AB$ GainControl | Cost$ T | ValidTgts$ Creature.powerLEX | TgtPrompt$ Select target creature with power less than or equal to Old Man's. | LoseControl$ Untap,LeavesPlay,LoseControl,StaticCommandCheck | StaticCommandCheckSVar$ Y | StaticCommandSVarCompare$ GTX | SpellDescription$ Gain control of target creature with power less than or equal to CARDNAME's power for as long as CARDNAME remains tapped and that creature's power remains less than or equal to CARDNAME's power. SVar:X:Count$CardPower # the hostcard of SVar Y is the controlled card SVar:Y:Count$CardPower diff --git a/forge-gui/res/cardsfolder/p/prophetic_titan.txt b/forge-gui/res/cardsfolder/p/prophetic_titan.txt index 8460bbfe93a..32107fa2aa0 100644 --- a/forge-gui/res/cardsfolder/p/prophetic_titan.txt +++ b/forge-gui/res/cardsfolder/p/prophetic_titan.txt @@ -2,7 +2,7 @@ Name:Prophetic Titan ManaCost:4 U R Types:Creature Giant Wizard PT:4/4 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ Delirium — When CARDNAME enters the battlefield, choose one. If there are four or more card types among cards in your graveyard, choose both instead. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ Delirium — When CARDNAME enters the battlefield, ABILITY SVar:TrigCharm:DB$ Charm | CharmNum$ X | Choices$ DBDealDamage,DBDig | AdditionalDescription$ If there are four or more card types in your graveyard, choose both. SVar:DBDealDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker,Player | TgtPrompt$ Select any target | NumDmg$ 4 | SpellDescription$ CARDNAME deals 4 damage to any target. SVar:DBDig:DB$ Dig | DigNum$ 4 | RestRandomOrder$ True | SpellDescription$ Look at the top four cards of your library. Put one of them into your hand and the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/p/pure_reflection.txt b/forge-gui/res/cardsfolder/p/pure_reflection.txt index 4abf93cfa22..57f067c4be2 100644 --- a/forge-gui/res/cardsfolder/p/pure_reflection.txt +++ b/forge-gui/res/cardsfolder/p/pure_reflection.txt @@ -2,7 +2,7 @@ Name:Pure Reflection ManaCost:2 W Types:Enchantment T:Mode$ SpellCast | ValidCard$ Creature | Execute$ TrigDestroy | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player casts a creature spell, destroy all Reflections. Then that player creates an X/X white Reflection creature token, where X is the mana value of that spell. -SVar:TrigDestroy:DB$ DestroyAll | ValidCards$ Reflection | SubAbility$ DBToken | SpellDescription$ Destroy all Reflections +SVar:TrigDestroy:DB$ DestroyAll | ValidCards$ Reflection | SubAbility$ DBToken SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenPower$ X | TokenToughness$ X | TokenScript$ w_x_x_reflection | TokenOwner$ TriggeredActivator SVar:X:TriggeredStackInstance$CardManaCostLKI Oracle:Whenever a player casts a creature spell, destroy all Reflections. Then that player creates an X/X white Reflection creature token, where X is the mana value of that spell. diff --git a/forge-gui/res/cardsfolder/r/regna_the_redeemer.txt b/forge-gui/res/cardsfolder/r/regna_the_redeemer.txt index 5ec291771c9..8ebab24bfa5 100644 --- a/forge-gui/res/cardsfolder/r/regna_the_redeemer.txt +++ b/forge-gui/res/cardsfolder/r/regna_the_redeemer.txt @@ -5,7 +5,7 @@ PT:4/4 K:Partner:Krav, the Unredeemed:Krav K:Flying T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ YouTeamLifeGained | SVarCompare$ GE1 | Execute$ TrigWarrior | TriggerDescription$ At the beginning of each end step, if your team gained life this turn, create two 1/1 white Warrior creature tokens. -SVar:TrigWarrior:DB$ Token | TokenAmount$ 2 | TokenScript$ w_1_1_warrior | TokenOwner$ You | SpellDescription$ Create two 1/1 white Warrior creature tokens. +SVar:TrigWarrior:DB$ Token | TokenAmount$ 2 | TokenScript$ w_1_1_warrior | TokenOwner$ You SVar:YouTeamLifeGained:Count$LifeYourTeamGainedThisTurn DeckHints:Name$Krav, the Unredeemed Oracle:Partner with Krav, the Unredeemed (When this creature enters the battlefield, target player may put Krav into their hand from their library, then shuffle.)\nFlying\nAt the beginning of each end step, if your team gained life this turn, create two 1/1 white Warrior creature tokens. diff --git a/forge-gui/res/cardsfolder/r/rumbling_slum_avatar.txt b/forge-gui/res/cardsfolder/r/rumbling_slum_avatar.txt index ca188bca282..b078e27d04c 100644 --- a/forge-gui/res/cardsfolder/r/rumbling_slum_avatar.txt +++ b/forge-gui/res/cardsfolder/r/rumbling_slum_avatar.txt @@ -3,5 +3,5 @@ ManaCost:no cost Types:Vanguard HandLifeModifier:+1/+1 T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigDmgOpp | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to each opponent. -SVar:TrigDmgOpp:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 1 +SVar:TrigDmgOpp:DB$ DealDamage | Defined$ Opponent | NumDmg$ 1 Oracle:Hand +1, life +1\nAt the beginning of your upkeep, Rumbling Slum Avatar deals 1 damage to each opponent. diff --git a/forge-gui/res/cardsfolder/t/thelonite_hermit.txt b/forge-gui/res/cardsfolder/t/thelonite_hermit.txt index c5bb2d29cea..1f9a3769a44 100644 --- a/forge-gui/res/cardsfolder/t/thelonite_hermit.txt +++ b/forge-gui/res/cardsfolder/t/thelonite_hermit.txt @@ -5,7 +5,7 @@ PT:1/1 K:Morph:3 G G S:Mode$ Continuous | Affected$ Creature.Saproling | AddPower$ 1 | AddToughness$ 1 | IsPresent$ Card.Self+faceUp | Description$ All Saprolings get +1/+1. T:Mode$ TurnFaceUp | ValidCard$ Card.Self | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME is turned face up, create four 1/1 green Saproling creature tokens. -SVar:TrigToken:DB$ Token | TokenAmount$ 4 | TokenScript$ g_1_1_saproling | TokenOwner$ You | SpellDescription$ Create four 1/1 green Saproling creature tokens. +SVar:TrigToken:DB$ Token | TokenAmount$ 4 | TokenScript$ g_1_1_saproling | TokenOwner$ You SVar:PlayMain1:TRUE DeckHints:Type$Fungus DeckHas:Ability$Token diff --git a/forge-gui/res/cardsfolder/upcoming/conductor_of_cacophony.txt b/forge-gui/res/cardsfolder/upcoming/conductor_of_cacophony.txt new file mode 100644 index 00000000000..0eeb4044ecf --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/conductor_of_cacophony.txt @@ -0,0 +1,9 @@ +Name:Conductor of Cacophony +ManaCost:3 B +Types:Creature Demon +PT:2/1 +K:etbCounter:P1P1:2 +A:AB$ DamageAll | Cost$ B SubCounter<1/P1P1> | ValidCards$ Creature.Other | ValidPlayers$ Player | NumDmg$ 1 | ValidDescription$ each other creature and each player. | SpellDescription$ It deals 1 damage to each other creature and each player. +DeckHas:Ability$Counters +DeckHints:Ability$Counters +Oracle:Conductor of Cacophony enters the battlefield with two +1/+1 counters on it.\n{B}, Remove a +1/+1 counter from Conductor of Cacophony: It deals 1 damage to each other creature and each player. diff --git a/forge-gui/res/cardsfolder/upcoming/distinguished_conjurer.txt b/forge-gui/res/cardsfolder/upcoming/distinguished_conjurer.txt new file mode 100644 index 00000000000..2673d340f03 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/distinguished_conjurer.txt @@ -0,0 +1,12 @@ +Name:Distinguished Conjurer +ManaCost:1 W +Types:Creature Human Wizard +PT:1/2 +T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever another creature enters the battlefield under your control, you gain 1 life. +SVar:TrigGainLife:DB$ GainLife | LifeAmount$ 1 +A:AB$ ChangeZone | Cost$ 4 W T | ValidTgts$ Creature.Other+YouCtrl | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select another target creature you control | RememberChanged$ True | SubAbility$ DBReturn | SpellDescription$ Exile another target creature you control, then return it to the battlefield under its owner's control. +SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Destination$ Battlefield | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +DeckHas:Ability$LifeGain +SVar:BuffedBy:Creature +Oracle:Whenever another creature enters the battlefield under your control, you gain 1 life.\n{4}{W}, {T}: Exile another target creature you control, then return it to the battlefield under its owner's control. diff --git a/forge-gui/res/cardsfolder/upcoming/dutiful_replicator.txt b/forge-gui/res/cardsfolder/upcoming/dutiful_replicator.txt new file mode 100644 index 00000000000..75ace52e6e9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/dutiful_replicator.txt @@ -0,0 +1,10 @@ +Name:Dutiful Replicator +ManaCost:3 +Types:Artifact Creature Assembly-Worker +PT:3/2 +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigImmediate | TriggerDescription$ When CARDNAME enters the battlefield, you may pay {1}. When you do, create a token that's a copy of target token you control not named Dutiful Replicator. +SVar:TrigImmediate:AB$ ImmediateTrigger | Cost$ 1 | Execute$ TrigClone | TriggerDescription$ When you do, create a token that's a copy of target token you control not named Dutiful Replicator. +SVar:TrigClone:DB$ CopyPermanent | ValidTgts$ Permanent.token+YouCtrl+notnamedDutiful Replicator | TgtPrompt$ Select target token you control not named Dutiful Replicator +DeckHas:Ability$Token +DeckNeeds:Ability$Token +Oracle:When Dutiful Replicator enters the battlefield, you may pay {1}. When you do, create a token that's a copy of target token you control not named Dutiful Replicator. diff --git a/forge-gui/res/cardsfolder/upcoming/hold_for_questioning.txt b/forge-gui/res/cardsfolder/upcoming/hold_for_questioning.txt new file mode 100644 index 00000000000..60a3dda9672 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/hold_for_questioning.txt @@ -0,0 +1,11 @@ +Name:Hold for Questioning +ManaCost:3 U +Types:Enchantment Aura +K:Enchant creature or planeswalker +A:SP$ Attach | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | AILogic$ Curse +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigTap | TriggerDescription$ When CARDNAME enters the battlefield, tap enchanted permanent and investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.") +SVar:TrigTap:DB$ Tap | Defined$ Enchanted | SubAbility$ DBInvestigate +SVar:DBInvestigate:DB$ Investigate +S:Mode$ Continuous | Affected$ Permanent.EnchantedBy | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. & CARDNAME's activated abilities can't be activated. | Description$ Enchanted permanent doesn't untap during its controller's untap step and its activated abilities can't be activated. +DeckHas:Ability$Investigate|Token|Sacrifice & Type$Artifact|Clue +Oracle:Enchant creature or planeswalker\nWhen Hold for Questioning enters the battlefield, tap enchanted permanent and investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.")\nEnchanted permanent doesn't untap during its controller's untap step and its activated abilities can't be activated. diff --git a/forge-gui/res/cardsfolder/upcoming/infernal_idol.txt b/forge-gui/res/cardsfolder/upcoming/infernal_idol.txt new file mode 100644 index 00000000000..d9ffb56ba15 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/infernal_idol.txt @@ -0,0 +1,8 @@ +Name:Infernal Idol +ManaCost:3 +Types:Artifact +A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}. +A:AB$ Draw | Cost$ 1 B B T Sac<1/CARDNAME> | NumCards$ 2 | SubAbility$ DBLoseLife | SpellDescription$ You draw two cards and you lose two life. +SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 2 +DeckNeeds:Color$Black +Oracle:{T}: Add {B}.\n{1}{B}{B}, {T}, Sacrifice Infernal Idol: You draw two cards and you lose two life. diff --git a/forge-gui/res/cardsfolder/upcoming/ingenious_leonin.txt b/forge-gui/res/cardsfolder/upcoming/ingenious_leonin.txt new file mode 100644 index 00000000000..df390b571c9 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/ingenious_leonin.txt @@ -0,0 +1,8 @@ +Name:Ingenious Leonin +ManaCost:4 W +Types:Creature Cat Soldier +PT:4/4 +A:AB$ PutCounter | Cost$ 3 W | ValidTgts$ Creature.attacking+Other+YouCtrl | TgtPrompt$ Select another target attacking creature you control | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBPump | SpellDescription$ Put a +1/+1 counter on another target attacking creature you control. If that creature is a Cat, it gains first strike until end of turn. +SVar:DBPump:DB$ Pump | Defined$ Targeted | ConditionDefined$ Targeted | ConditionPresent$ Cat | KW$ First Strike | StackDesc$ If that creature is a Cat, it gains first strike until end of turn +DeckHints:Type$Cat +Oracle:{3}{W}: Put a +1/+1 counter on another target attacking creature you control. If that creature is a Cat, it gains first strike until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/lita_mechanical_engineer.txt b/forge-gui/res/cardsfolder/upcoming/lita_mechanical_engineer.txt new file mode 100644 index 00000000000..119038c8f32 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/lita_mechanical_engineer.txt @@ -0,0 +1,11 @@ +Name:Lita, Mechanical Engineer +ManaCost:2 W +Types:Legendary Artifact Creature Artificer +PT:3/3 +K:Vigilance +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigUntap | TriggerDescription$ At the beginning of your end step, untap all artifact creatures you control. +SVar:TrigUntap:DB$ UntapAll | ValidCards$ Artifact.Creature+YouCtrl +A:AB$ Token | Cost$ 3 W T | TokenScript$ zeppelin | SpellDescription$ Create a 5/5 colorless Vehicle artifact token named Zeppelin with flying and crew 3. +DeckHas:Type$Vehicle & Ability$Token & Keyword$Flying +DeckHints:Type$Artifact +Oracle:Vigilance\nAt the beginning of your end step, untap all artifact creatures you control.\n{3}{W}, {T}: Create a 5/5 colorless Vehicle artifact token named Zeppelin with flying and crew 3. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/magnanimous_magistrate.txt b/forge-gui/res/cardsfolder/upcoming/magnanimous_magistrate.txt new file mode 100644 index 00000000000..668e78f8b88 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/magnanimous_magistrate.txt @@ -0,0 +1,10 @@ +Name:Magnanimous Magistrate +ManaCost:5 W +Types:Creature Human Advisor +PT:3/4 +K:etbCounter:REPR:5 +T:Mode$ ChangesZone | ValidCard$ Creature.Other+nonToken+cmcGE1 | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ Whenever another nontoken creature you control dies, if its mana value was 1 or greater, you may remove that many reprieve counters from CARDNAME. If you do, return that card to the battlefield under its owner's control. +SVar:TrigChangeZone:AB$ ChangeZone | Cost$ SubCounter | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield +SVar:X:TriggeredCard$CardManaCost +DeckHas:Ability$Counters +Oracle:Magnanimous Magistrate enters the battlefield with five reprieve counters on it.\nWhenever another nontoken creature you control dies, if its mana value was 1 or greater, you may remove that many reprieve counters from Magnanimous Magistrate. If you do, return that card to the battlefield under its owner's control. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/mild_mannered_librarian.txt b/forge-gui/res/cardsfolder/upcoming/mild_mannered_librarian.txt new file mode 100644 index 00000000000..6b13b16205d --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/mild_mannered_librarian.txt @@ -0,0 +1,9 @@ +Name:Mild-Mannered Librarian +ManaCost:G +Types:Creature Human +PT:1/1 +A:AB$ Animate | Cost$ 3 G | GameActivationLimit$ 1 | Types$ Werewolf | RemoveCreatureTypes$ True | Duration$ Permanent | SubAbility$ DBCounter | SpellDescription$ CARDNAME becomes a Werewolf. Put two +1/+1 counters on it and you draw a card. Activate only once. +SVar:DBCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBDraw +SVar:DBDraw:DB$ Draw +DeckHas:Ability$Counters & Type$Werewolf +Oracle:{3}{G}: Mild-Mannered Librarian becomes a Werewolf. Put two +1/+1 counters on it and you draw a card. Activate only once. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/pirated_copy.txt b/forge-gui/res/cardsfolder/upcoming/pirated_copy.txt new file mode 100644 index 00000000000..09d0e149464 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/pirated_copy.txt @@ -0,0 +1,9 @@ +Name:Pirated Copy +ManaCost:4 U +Types:Creature Shapeshifter Pirate +PT:0/0 +K:ETBReplacement:Copy:DBCopy:Optional +SVar:DBCopy:DB$ Clone | Choices$ Creature.Other | AddTypes$ Pirate | AddTriggers$ DrawTrig | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield, except it's a Pirate in addition to its other types and it has "Whenever this creature or another creature with the same name deals combat damage to a player, you draw a card." +SVar:DrawTrig:Mode$ DamageDone | ValidSource$ Card.Self,Creature.sameName | TriggerZones$ Battlefield | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ Whenever this creature or another creature with the same name deals combat damage to a player, you draw a card. +SVar:TrigDraw:DB$ Draw +Oracle:You may have Pirated Copy enter the battlefield as a copy of any creature on the battlefield, except it's a Pirate in addition to its other types and it has "Whenever this creature or another creature with the same name deals combat damage to a player, you draw a card." \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/preston_the_vanisher.txt b/forge-gui/res/cardsfolder/upcoming/preston_the_vanisher.txt new file mode 100644 index 00000000000..e5c79768152 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/preston_the_vanisher.txt @@ -0,0 +1,10 @@ +Name:Preston, the Vanisher +ManaCost:3 W +Types:Legendary Creature Rabbit Wizard +PT:2/5 +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken+wasNotCast+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigCopyPermanent | TriggerDescription$ Whenever another nontoken creature enters the battlefield under your control, if it wasn't cast, create a token that's a copy of that creature except it's a 0/1 white Illusion. +SVar:TrigCopyPermanent:DB$ CopyPermanent | Defined$ TriggeredCard | NumCopies$ 1 | SetColor$ White | SetCreatureTypes$ Illusion | SetPower$ 0 | SetToughness$ 1 +A:AB$ ChangeZone | Cost$ 1 W Sac<5/Illusion> | ValidTgts$ Permanent.nonLand | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select target nonland permanent | SpellDescription$ Exile target nonland permanent. +DeckHas:Ability$Token|Sacrifice & Type$Illusion +DeckHints:Type$Illusion & Ability$Graveyard +Oracle:Whenever another nontoken creature enters the battlefield under your control, if it wasn't cast, create a token that's a copy of that creature except it's a 0/1 white Illusion.\n{1}{W}, Sacrifice five Illusions: Exile target nonland permanent. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/primeval_herald.txt b/forge-gui/res/cardsfolder/upcoming/primeval_herald.txt new file mode 100644 index 00000000000..4826de131d1 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/primeval_herald.txt @@ -0,0 +1,10 @@ +Name:Primeval Herald +ManaCost:3 G +Types:Creature Elf Scout +PT:3/1 +K:Trample +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle. +T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChange | TriggerZones$ Battlefield | OptionalDecider$ You | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle. +SVar:TrigChange:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ 1 | ShuffleNonMandatory$ True +SVar:HasAttackEffect:TRUE +Oracle:Trample\nWhenever Primeval Herald enters the battlefield or attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/read_the_soul.txt b/forge-gui/res/cardsfolder/upcoming/read_the_soul.txt new file mode 100644 index 00000000000..dc774497a8b --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/read_the_soul.txt @@ -0,0 +1,7 @@ +Name:Read the Soul +ManaCost:3 U +Types:Instant +A:SP$ Charm | Choices$ Counter,Draw | CharmNum$ 1 +SVar:Counter:DB$ Counter | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 4 | SpellDescription$ Counter target spell unless its controller pays {4}. +SVar:Draw:DB$ Draw | NumCards$ 2 | SpellDescription$ Draw two cards. +Oracle:Choose one —\n• Counter target spell unless its controller pays {4}.\n• Draw two cards. diff --git a/forge-gui/res/cardsfolder/upcoming/rodolf_duskbringer.txt b/forge-gui/res/cardsfolder/upcoming/rodolf_duskbringer.txt new file mode 100644 index 00000000000..524e5634fc2 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/rodolf_duskbringer.txt @@ -0,0 +1,16 @@ +Name:Rodolf Duskbringer +ManaCost:5 B +Types:Legendary Creature Vampire Angel +PT:4/4 +K:Flying +K:Deathtouch +K:Lifelink +T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever you gain life, CARDNAME gains indestructible until end of turn. +SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ Indestructible +T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ X | Execute$ TrigImmediateTrig | TriggerDescription$ At the beginning of your end step, you may pay {1}{W/B}. When you do, return target creature with mana value X or less from your graveyard to the battlefield, where X is the amount of life you gained this turn. +SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ 1 WB | Execute$ TrigChangeZone | TriggerDescription$ When you do, return target creature with mana value X or less from your graveyard to the battlefield, where X is the amount of life you gained this turn. +SVar:TrigChangeZone:DB$ ChangeZone | ValidTgts$ Creature.cmcLEX+YouOwn | TgtPrompt$ Select target creature card with mana value X or less | Origin$ Graveyard | Destination$ Battlefield +SVar:X:Count$LifeYouGainedThisTurn +DeckHas:Ability$Graveyard|LifeGain & Keyword$indestructible +DeckHints:Ability$Graveyard|LifeGain|Mill +Oracle:Flying, deathtouch, lifelink\nWhenever you gain life, Rodolf Duskbringer gains indestructible until end of turn.\nAt the beginning of your end step, you may pay {1}{W/B}. When you do, return target creature with mana value X or less from your graveyard to the battlefield, where X is the amount of life you gained this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/runadi_behemoth_caller.txt b/forge-gui/res/cardsfolder/upcoming/runadi_behemoth_caller.txt new file mode 100644 index 00000000000..1b1d0b93602 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/runadi_behemoth_caller.txt @@ -0,0 +1,14 @@ +Name:Runadi, Behemoth Caller +ManaCost:2 G +Types:Legendary Creature Cat Shaman +PT:1/3 +T:Mode$ SpellCast | ValidCard$ Creature.cmcGE5 | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ Whenever you cast a creature spell with mana value 5 or greater, that creature enters the battlefield with X additional +1/+1 counters on it, where X is its mana value minus 4. +SVar:TrigEffect:DB$ Effect | RememberObjects$ TriggeredCard | ReplacementEffects$ ETBCreat | ExileOnMoved$ Stack +SVar:ETBCreat:Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated +SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ X +S:Mode$ Continuous | Affected$ Creature.YouCtrl+counters_GE3_P1P1 | AddKeyword$ Haste | Description$ Creatures you control with three or more +1/+1 counters on them have haste. +A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}. +SVar:X:Remembered$CardManaCost/Minus.4 +DeckHas:Ability$Counters +DeckHints:Type$Tyranid|Hydra +Oracle:Whenever you cast a creature spell with mana value 5 or greater, that creature enters the battlefield with X additional +1/+1 counters on it, where X is its mana value minus 4.\nCreatures you control with three or more +1/+1 counters on them have haste.\n{T}: Add {G}. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/towering_gibbon.txt b/forge-gui/res/cardsfolder/upcoming/towering_gibbon.txt new file mode 100644 index 00000000000..aabaefc4a8d --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/towering_gibbon.txt @@ -0,0 +1,8 @@ +Name:Towering Gibbon +ManaCost:3 G +Types:Creature Ape +PT:*/4 +K:Reach +S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | Description$ CARDNAME's power is equal to the highest mana value among creatures you control. +SVar:X:Count$Valid Creature.YouCtrl$GreatestCMC +Oracle:Reach\nTowering Gibbon's power is equal to the greatest mana value among creatures you control. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/zask_skittering_swarmlord.txt b/forge-gui/res/cardsfolder/upcoming/zask_skittering_swarmlord.txt new file mode 100644 index 00000000000..2baf77fcc63 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/zask_skittering_swarmlord.txt @@ -0,0 +1,12 @@ +Name:Zask, Skittering Swarmlord +ManaCost:3 G G +Types:Legendary Creature Insect +PT:5/5 +S:Mode$ Continuous | Affected$ Land.YouOwn,Insect.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands and cast Insect spells from your graveyard.o +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Insect.YouCtrl+Other | Execute$ TrigChange | TriggerDescription$ Whenever another Insect you control dies, put it on the bottom of its owner's library, then mill two cards. (Put the top two cards of your library into your graveyard.) +SVar:TrigChange:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Library | LibraryPosition$ -1 | SubAbility$ DBMill +SVar:DBMill:DB$ Mill | NumCards$ 2 +A:AB$ Pump | Cost$ 1 BG | ValidTgts$ Insect | NumAtt$ 1 | KW$ Deathtouch | SpellDescription$ Target Insect gets +1/+0 and gains deathtouch until end of turn. +DeckHas:Ability$Mill|Graveyard & Keyword$Deathtouch +DeckNeeds:Type$Insect +Oracle:You may play lands and cast Insect spells from your graveyard.\nWhenever another Insect you control dies, put it on the bottom of its owner's library, then mill two cards. (Put the top two cards of your library into your graveyard.)\n{1}{B/G}: Target Insect gets +1/+0 and gains deathtouch until end of turn. diff --git a/forge-gui/res/cardsfolder/w/watchful_giant.txt b/forge-gui/res/cardsfolder/w/watchful_giant.txt index 8df72a9e184..adf0987e2d5 100644 --- a/forge-gui/res/cardsfolder/w/watchful_giant.txt +++ b/forge-gui/res/cardsfolder/w/watchful_giant.txt @@ -3,7 +3,7 @@ ManaCost:5 W Types:Creature Giant Soldier PT:3/6 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 1/1 white Human creature token. -SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenOwner$ You | SpellDescription$ Create a 1/1 white Human creature token. +SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenOwner$ You DeckHints:Type$Human DeckHas:Ability$Token Oracle:When Watchful Giant enters the battlefield, create a 1/1 white Human creature token. diff --git a/forge-gui/res/cardsfolder/w/wild_evocation.txt b/forge-gui/res/cardsfolder/w/wild_evocation.txt index 1d00e3d27d6..d29161a75d3 100644 --- a/forge-gui/res/cardsfolder/w/wild_evocation.txt +++ b/forge-gui/res/cardsfolder/w/wild_evocation.txt @@ -4,7 +4,7 @@ Types:Enchantment T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigEvoke | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player reveals a card at random from their hand. If it's a land card, the player puts it onto the battlefield. Otherwise, the player casts it without paying its mana cost if able. SVar:TrigEvoke:DB$ Reveal | Random$ True | RememberRevealed$ True | Defined$ TriggeredPlayer | SubAbility$ DBEvokeLand SVar:DBEvokeLand:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ ValidHand Land.IsRemembered | ForgetChanged$ True | SubAbility$ DBEvokePlay -SVar:DBEvokePlay:DB$ Play | ValidZone$ Hand | Controller$ TriggeredPlayer | Defined$ Remembered | WithoutManaCost$ True | SubAbility$ DBCleanup +SVar:DBEvokePlay:DB$ Play | ValidZone$ Hand | Controller$ TriggeredPlayer | Defined$ Remembered | ValidSA$ Spell | WithoutManaCost$ True | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True AI:RemoveDeck:Random Oracle:At the beginning of each player's upkeep, that player reveals a card at random from their hand. If it's a land card, the player puts it onto the battlefield. Otherwise, the player casts it without paying its mana cost if able. diff --git a/forge-gui/res/editions/Jumpstart 2022.txt b/forge-gui/res/editions/Jumpstart 2022.txt index 0c57f069fa6..1f7ac883cd5 100644 --- a/forge-gui/res/editions/Jumpstart 2022.txt +++ b/forge-gui/res/editions/Jumpstart 2022.txt @@ -6,8 +6,75 @@ Type=Draft ScryfallCode=J22 [cards] +4 U Distinguished Conjurer @Nils Hamm +5 U Ingenious Leonin @Eric Deschamps +6 M Lita, Mechanical Engineer @Bartek Fedyczak +7 U Magnanimous Magistrate @Marie Magny +8 R Preston, the Vanisher @Christina Kraus +11 U Hold for Questioning @Samuel Perin 12 M Isu the Abominable @Victor Adame Minguez +15 C Merfolk Pupil @Caroline Gariba +16 M Pirated Copy @Daarken +19 M Ashcoat of the Shadow Swarm @Christina Kraus +20 U Conductor of Cacophony @Jason A. Engle +21 C Creeping Bloodsucker @Antonio José Manzanedo +23 U Disciple of Perdition @Alix Branwyn +25 R Rodolf Duskbringer @Billy Christian +28 R Termination Facilitator @Justine Cruz 29 R Ardoz, Cobbler of War @Kev Walker +40 M Kibo, Uktabi Prince @Zoltan Boros +41 U Mild-Mannered Librarian @Justyna Gil +42 U Primeval Herald @Tatiana Kirgetova +44 R Runadi, Behemoth Caller @Billy Christian +45 C Spectral Hunt-Caller @Uriah Voth +46 U Towering Gibbon @Chris Seaman +48 C Dutiful Replicator @Alexander Forssberg +49 C Infernal Idol @Drew Tucker +50 U Instruments of War @Drew Tucker +51 U Planar Atlas @Alexander Forssberg +52 U Arrest @Katana Canata +53 R Balan, Wandering Knight @Mai Okuma +56 C Flicker of Fate +57 U King of the Pride @Inuchiyo Meimaru +62 U Mirror Image @Yukie Tajima +64 U Spectral Sailor @Fuzichoco +65 C Spellstutter Sprite +66 U Whirler Rogue @I☆LA +67 C Diabolic Edict @Tetsu Kurosawa +68 U Feast on the Fallen +70 U Oathsworn Vampire @Border +71 R Ogre Slumlord 79 M Kiki-Jiki, Mirror Breaker @Ishikawa Kenta +85 U Arlinn, Voice of the Pack @Hisashi Momose +88 C Elvish Rejuvenator @Shiramine +92 U Thrashing Brontodon @Kemonomichi 94 U Coldsteel Heart @I☆LA +95 U Magnifying Glass @Yukihiro Maruo +96 R Peacewalker Colossus @Hisashi Momose +97 M Karn Liberated @Dai-XT +117 U Blood Artist @Julie Dillon +118 U Feast of Blood @Irina Nordsol +119 U Festering Evil @Samuel Araya +126 C Renegade Demon @Alexandre Honoré +133 U Uktabi Orangutan @Milivoj Ćeran +134 R Wicked Wolf @Steve Ellis +141 M Ajani, Strength of the Pride @Chris Rallis +142 U Ajani's Pridemate @Svetlin Velinov +184 R Felidar Retreat @Ralph Horsley +208 R Leonin Warleader @Jakub Kasper +232 R Regal Caracal @Filip Burburan +259 R Trove Warden @Lars Grant-West +323 U Nezumi Bone-Reader @Leonardo Santanna +384 C Burglar Rat @Tyler Walpole +387 C Chittering Rats @Yeong-Hao Han +392 U Crypt Rats @Matt Cavotta +397 R Demon of Catastrophes @Sidharth Chaturvedi +403 R Dread Presence @Anthony Palumbo +412 C Eviscerate @Min Yum +431 R Kothophed, Soul Hoarder @Jakub Kasper +463 R Seizan, Perverter of Truth @Kev Walker +465 C Sinuous Vermin @Jason Kang +468 C Typhoid Rats @Kev Walker +481 U Ulcerate @Johann Bodin +806 R Walking Ballista @Daniel Ljunggren 835 M Kibo, Uktabi Prince @Filipe Pagliuso diff --git a/forge-gui/res/editions/Secret Lair 30th Anniversary Countdown Kit.txt b/forge-gui/res/editions/Secret Lair 30th Anniversary Countdown Kit.txt index 958717bd4a0..7bd4987caf6 100644 --- a/forge-gui/res/editions/Secret Lair 30th Anniversary Countdown Kit.txt +++ b/forge-gui/res/editions/Secret Lair 30th Anniversary Countdown Kit.txt @@ -36,3 +36,4 @@ ScryfallCode=SLC 2020 R Shark Typhoon @Edgar Sánchez Hidalgo 2021 R Elite Spellbinder @Alexis Ziritt 2022 M Nashi, Moon Sage's Scion @Death Burger +2023 M Lotus Field @ZIUK diff --git a/forge-gui/res/tokenscripts/zeppelin.txt b/forge-gui/res/tokenscripts/zeppelin.txt new file mode 100644 index 00000000000..7147687015c --- /dev/null +++ b/forge-gui/res/tokenscripts/zeppelin.txt @@ -0,0 +1,7 @@ +Name:Zeppelin +ManaCost:no cost +Types:Artifact Creature +PT:5/5 +K:Flying +K:Crew:3 +Oracle:Flying\nCrew 3. \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectManyBase.java b/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectManyBase.java index ec6d1095826..0c1dacdedc3 100644 --- a/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectManyBase.java +++ b/forge-gui/src/main/java/forge/gamemodes/match/input/InputSelectManyBase.java @@ -64,8 +64,8 @@ public abstract class InputSelectManyBase extends InputSyn @Override public final void showMessage() { - if ( FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT) && - (card!=null) ) { + if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT) && + card != null) { final StringBuilder sb = new StringBuilder(); sb.append(card.toString()); if ( (sa != null) && (!sa.toString().isEmpty()) ) { // some spell abilities have no useful string value diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 654394c5efb..b96ff13ad81 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -743,13 +743,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont switch (sa.getParam("ShowCardInPrompt")) { case "FirstRemembered": o = sa.getHostCard().getFirstRemembered(); - if (o != null && o instanceof Card) { + if (o instanceof Card) { show = (Card)o; } break; case "LastRemembered": o = sa.getHostCard().getFirstRemembered(); - if (o != null && o instanceof Card) { + if (o instanceof Card) { show = (Card)o; } break;