diff --git a/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java b/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java index a84aa9d8643..9a837bc1601 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DestroyAllAi.java @@ -37,8 +37,7 @@ public class DestroyAllAi extends SpellAbilityAi { @Override public boolean chkAIDrawback(SpellAbility sa, Player aiPlayer) { - //TODO: Check for bad outcome - return true; + return doMassRemovalLogic(aiPlayer, sa); } @Override diff --git a/forge-core/src/main/java/forge/ImageKeys.java b/forge-core/src/main/java/forge/ImageKeys.java index 4ea30d2a17d..fe8d43bf31d 100644 --- a/forge-core/src/main/java/forge/ImageKeys.java +++ b/forge-core/src/main/java/forge/ImageKeys.java @@ -122,7 +122,7 @@ public final class ImageKeys { file = findFile(dir, TextUtil.fastReplace(fullborderFile, "1.fullborder", ".fullborder")); if (file != null) { return file; } // if there's an art variant try without it for .full images - file = findFile(dir, filename.replaceAll("[0-9].full]",".full")); + file = findFile(dir, filename.replaceAll("[0-9].full",".full")); if (file != null) { return file; } // if there's a 1st art variant try with it for .full images file = findFile(dir, filename.replaceAll("[0-9]*.full", "1.full")); diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java index 74110e12e3e..61ecba8da14 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveAllEffect.java @@ -11,7 +11,9 @@ import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; -import java.util.Set; +import java.util.Map; + +import com.google.common.collect.Lists; public class CountersRemoveAllEffect extends SpellAbilityEffect { @Override @@ -60,11 +62,10 @@ public class CountersRemoveAllEffect extends SpellAbilityEffect { int numberRemoved = 0; for (final Card tgtCard : cards) { if (sa.hasParam("AllCounterTypes")) { - Set types = tgtCard.getCounters().keySet(); - for(CounterType ct : types) { - numberRemoved += tgtCard.getCounters(ct); - tgtCard.subtractCounter(ct, tgtCard.getCounters(ct)); - } + for(Map.Entry e : Lists.newArrayList(tgtCard.getCounters().entrySet())) { + numberRemoved += e.getValue(); + tgtCard.subtractCounter(e.getKey(), e.getValue()); + } //tgtCard.getCounters().clear(); continue; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveEffect.java index 286cf8589a7..384f4e16376 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersRemoveEffect.java @@ -20,6 +20,7 @@ import java.util.Map; import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; public class CountersRemoveEffect extends SpellAbilityEffect { @@ -109,7 +110,7 @@ public class CountersRemoveEffect extends SpellAbilityEffect { // Removing energy if (!sa.usesTargeting() || tgtPlayer.canBeTargetedBy(sa)) { if (type.equals("All")) { - for (Map.Entry e : tgtPlayer.getCounters().entrySet()) { + for (Map.Entry e : Lists.newArrayList(tgtPlayer.getCounters().entrySet())) { tgtPlayer.subtractCounter(e.getKey(), e.getValue()); } } else { @@ -152,7 +153,7 @@ public class CountersRemoveEffect extends SpellAbilityEffect { if (!sa.usesTargeting() || gameCard.canBeTargetedBy(sa)) { final Zone zone = game.getZoneOf(gameCard); if (type.equals("All")) { - for (Map.Entry e : gameCard.getCounters().entrySet()) { + for (Map.Entry e : Lists.newArrayList(gameCard.getCounters().entrySet())) { gameCard.subtractCounter(e.getKey(), e.getValue()); } game.updateLastStateForCard(gameCard); diff --git a/forge-game/src/main/java/forge/game/cost/CostFlipCoin.java b/forge-game/src/main/java/forge/game/cost/CostFlipCoin.java index 82e7941c398..dac0618af50 100644 --- a/forge-game/src/main/java/forge/game/cost/CostFlipCoin.java +++ b/forge-game/src/main/java/forge/game/cost/CostFlipCoin.java @@ -18,14 +18,13 @@ package forge.game.cost; import forge.game.ability.effects.FlipCoinEffect; -import forge.game.card.Card; import forge.game.player.Player; import forge.game.spellability.SpellAbility; /** * This is for the "FlipCoin" Cost */ -public class CostFlipCoin extends CostPartWithList { +public class CostFlipCoin extends CostPart { /** * Serializables need a version ID. @@ -42,18 +41,6 @@ public class CostFlipCoin extends CostPartWithList { this.setAmount(amount); } - /* (non-Javadoc) - * @see forge.card.cost.CostPartWithList#getHashForList() - */ - @Override - public String getHashForLKIList() { - return "Flipped"; - } - @Override - public String getHashForCardList() { - return "FlippedCards"; - } - /* * (non-Javadoc) * @@ -71,15 +58,13 @@ public class CostFlipCoin extends CostPartWithList { return Cost.convertAmountTypeToWords(this.convertAmount(), this.getAmount(), "Coin"); } - /* (non-Javadoc) - * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) - */ @Override - protected Card doPayment(SpellAbility ability, Card targetCard) { - final Player activator = ability.getActivatingPlayer(); - int i = FlipCoinEffect.getFilpMultiplier(activator); - FlipCoinEffect.flipCoinCall(activator, ability, i); - return targetCard; + public boolean payAsDecided(Player payer, PaymentDecision pd, SpellAbility sa) { + int m = FlipCoinEffect.getFilpMultiplier(payer); + for (int i = 0; i < pd.c; i++) { + FlipCoinEffect.flipCoinCall(payer, sa, m); + } + return true; } public T accept(ICostVisitor visitor) { diff --git a/forge-game/src/main/java/forge/game/cost/CostPartWithList.java b/forge-game/src/main/java/forge/game/cost/CostPartWithList.java index 9a2964b4e18..e19ce9e7418 100644 --- a/forge-game/src/main/java/forge/game/cost/CostPartWithList.java +++ b/forge-game/src/main/java/forge/game/cost/CostPartWithList.java @@ -132,12 +132,8 @@ public abstract class CostPartWithList extends CostPart { } cardList.addAll(doListPayment(ability, targetCards)); } else { - if (targetCards.isEmpty() && this instanceof CostFlipCoin) { - doPayment(ability, null); // TODO: generalize for other cost types if necessary - } else { - for (Card c : targetCards) { - executePayment(ability, c); - } + for (Card c : targetCards) { + executePayment(ability, c); } } handleChangeZoneTrigger(payer, ability, targetCards); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java b/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java index 52f97018375..a77304e9dba 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java @@ -68,13 +68,19 @@ public class TriggerBecomesTarget extends Trigger { } } if (hasParam("ValidSource")) { - if (!matchesValid(((SpellAbility) runParams.get(AbilityKey.SourceSA)).getHostCard(), getParam("ValidSource").split(","), this.getHostCard())) { + SpellAbility source = (SpellAbility) runParams.get(AbilityKey.SourceSA); + if (source == null) { return false; } + String valid[] = getParam("ValidSource").split(","); + if (!matchesValid(source, valid, getHostCard())) { + if (!matchesValid(source.getHostCard(), valid, getHostCard())) { + return false; + } + } } if (hasParam("ValidTarget")) { - if (!matchesValid(runParams.get(AbilityKey.Target), getParam("ValidTarget").split(","), - this.getHostCard())) { + if (!matchesValid(runParams.get(AbilityKey.Target), getParam("ValidTarget").split(","), getHostCard())) { return false; } } diff --git a/forge-gui/res/blockdata/blocks.txt b/forge-gui/res/blockdata/blocks.txt index 0cb0ac21ab3..988de4e7568 100644 --- a/forge-gui/res/blockdata/blocks.txt +++ b/forge-gui/res/blockdata/blocks.txt @@ -86,4 +86,5 @@ Throne of Eldraine, 3/6/ELD, ELD Theros: Beyond Death, 3/6/THB, THB Mystery Booster, 3/6/THB, MB1 Ikoria: Lair of Behemoths, 3/6/IKO, IKO -Core Set 2021, 3/6/M21, M21 \ No newline at end of file +Core Set 2021, 3/6/M21, M21 +Double Masters, 3/6/2XM, 2XM diff --git a/forge-gui/res/blockdata/printsheets.txt b/forge-gui/res/blockdata/printsheets.txt index 90d2ddea895..985a1207f3d 100644 --- a/forge-gui/res/blockdata/printsheets.txt +++ b/forge-gui/res/blockdata/printsheets.txt @@ -3911,3 +3911,337 @@ Wind-Scarred Crag|M21 3 Forest|M21|2 3 Forest|M21|4 3 Forest|M21|3 + +[2XM Foils] +Karn Liberated+|2XM +Alabaster Mage+|2XM +Ancestral Blade+|2XM +Angel of the Dawn+|2XM +Archangel of Thune+|2XM +Auriok Salvagers+|2XM +Austere Command+|2XM +Avacyn, Angel of Hope+|2XM +Blade Splicer+|2XM +Boon Reflection+|2XM +Council's Judgment+|2XM +Crib Swap+|2XM +Crusader of Odric+|2XM +Ethersworn Canonist+|2XM +Fencing Ace+|2XM +Flickerwisp+|2XM +Fortify+|2XM +Glint-Sleeve Artisan+|2XM +Kemba, Kha Regent+|2XM +Land Tax+|2XM +Leonin Abunas+|2XM +Master Splicer+|2XM +Myrsmith+|2XM +Open the Vaults+|2XM +Path to Exile+|2XM +Puresteel Paladin+|2XM +Remember the Fallen+|2XM +Revoke Existence+|2XM +Sanctum Gargoyle+|2XM +Sanctum Spirit+|2XM +Stoneforge Mystic+|2XM +Stonehewer Giant+|2XM +Strength of Arms+|2XM +Tempered Steel+|2XM +Thraben Inspector+|2XM +Topple the Statue+|2XM +Valor in Akros+|2XM +Valorous Stance+|2XM +Wrath of God+|2XM +Apprentice Wizard+|2XM +Arcum Dagsson+|2XM +Argivian Restoration+|2XM +Braids, Conjurer Adept+|2XM +Brainstorm+|2XM +Cloudreader Sphinx+|2XM +Corridor Monitor+|2XM +Cyclonic Rift+|2XM +Deepglow Skate+|2XM +Esperzoa+|2XM +Faerie Mechanist+|2XM +Force of Will+|2XM +Frogify+|2XM +Grand Architect+|2XM +Hinder+|2XM +Inkwell Leviathan+|2XM +Jace, the Mind Sculptor+|2XM +Master of Etherium+|2XM +Master Transmuter+|2XM +Metallic Rebuke+|2XM +Parasitic Strix+|2XM +Phyrexian Metamorph+|2XM +Pongify+|2XM +Relic Runner+|2XM +Reshape+|2XM +Riddlesmith+|2XM +Rush of Knowledge+|2XM +Sentinel of the Pearl Trident+|2XM +Serra Sphinx+|2XM +Sift+|2XM +Steel Sabotage+|2XM +Thirst for Knowledge+|2XM +Thought Reflection+|2XM +Treasure Mage+|2XM +Vedalken Infuser+|2XM +Well of Ideas+|2XM +Ad Nauseam+|2XM +Beacon of Unrest+|2XM +Bone Picker+|2XM +Cast Down+|2XM +Costly Plunder+|2XM +Dark Confidant+|2XM +Death's Shadow+|2XM +Defiant Salvager+|2XM +Dire Fleet Hoarder+|2XM +Disciple of Bolas+|2XM +Disciple of the Vault+|2XM +Divest+|2XM +Doomed Necromancer+|2XM +Dread Return+|2XM +Driver of the Dead+|2XM +Drown in Sorrow+|2XM +Executioner's Capsule+|2XM +Fatal Push+|2XM +Geth, Lord of the Vault+|2XM +Glaze Fiend+|2XM +Heartless Pillage+|2XM +Magus of the Abyss+|2XM +Magus of the Will+|2XM +Morkrut Banshee+|2XM +Oubliette+|2XM +Ovalchase Daredevil+|2XM +Painsmith+|2XM +Ravenous Trap+|2XM +Salvage Titan+|2XM +Silumgar Scavenger+|2XM +Skirsdag High Priest+|2XM +Skithiryx, the Blight Dragon+|2XM +Supernatural Stamina+|2XM +Thoughtseize+|2XM +Toxic Deluge+|2XM +Twisted Abomination+|2XM +Vampire Hexmage+|2XM +Wound Reflection+|2XM +Abrade+|2XM +Balduvian Rage+|2XM +Battle-Rattle Shaman+|2XM +Blasphemous Act+|2XM +Blood Moon+|2XM +Bloodshot Trainee+|2XM +Brimstone Volley+|2XM +Cathartic Reunion+|2XM +Cragganwick Cremator+|2XM +Dismantle+|2XM +Dualcaster Mage+|2XM +Galvanic Blast+|2XM +Goblin Gaveleer+|2XM +Goblin Guide+|2XM +Godo, Bandit Warlord+|2XM +Grim Lavamancer+|2XM +Heat Shimmer+|2XM +Imperial Recruiter+|2XM +Ion Storm+|2XM +Kazuul's Toll Collector+|2XM +Kuldotha Flamefiend+|2XM +Lightning Axe+|2XM +Mana Echoes+|2XM +Orcish Vandal+|2XM +Pyrewild Shaman+|2XM +Rage Reflection+|2XM +Rapacious Dragon+|2XM +Ravenous Intruder+|2XM +Rolling Earthquake+|2XM +Salivating Gremlins+|2XM +Skinbrand Goblin+|2XM +Sneak Attack+|2XM +Temur Battle Rage+|2XM +Thopter Engineer+|2XM +Trash for Treasure+|2XM +Tuktuk the Explorer+|2XM +Weapon Surge+|2XM +Ancient Stirrings+|2XM +Avenger of Zendikar+|2XM +Awakening Zone+|2XM +Bloodbriar+|2XM +Bloodspore Thrinax+|2XM +Champion of Lambholt+|2XM +Chatter of the Squirrel+|2XM +Chord of Calling+|2XM +Clear Shot+|2XM +Conclave Naturalists+|2XM +Crop Rotation+|2XM +Crushing Vines+|2XM +Death-Hood Cobra+|2XM +Doubling Season+|2XM +Elvish Aberration+|2XM +Enlarge+|2XM +Exploration+|2XM +Fierce Empath+|2XM +Gelatinous Genesis+|2XM +Greater Good+|2XM +Heartbeat of Spring+|2XM +Invigorate+|2XM +Kozilek's Predator+|2XM +Liege of the Tangle+|2XM +Mana Reflection+|2XM +Might of the Masses+|2XM +Noble Hierarch+|2XM +Reclamation Sage+|2XM +Shamanic Revelation+|2XM +Skullmulcher+|2XM +Sylvan Might+|2XM +Terastodon+|2XM +Thragtusk+|2XM +Ulvenwald Mysteries+|2XM +Vengevine+|2XM +Veteran Explorer+|2XM +Whisperer of the Wilds+|2XM +Woodland Champion+|2XM +Arixmethes, Slumbering Isle+|2XM +Atraxa, Praetors' Voice+|2XM +Baleful Strix+|2XM +Breya, Etherium Shaper+|2XM +Brudiclad, Telchor Engineer+|2XM +Deathreap Ritual+|2XM +Falkenrath Aristocrat+|2XM +Fulminator Mage+|2XM +Geist of Saint Traft+|2XM +Ghor-Clan Rampager+|2XM +Glassdust Hulk+|2XM +Hanna, Ship's Navigator+|2XM +Hidden Stockpile+|2XM +Izzet Charm+|2XM +Jhoira, Weatherlight Captain+|2XM +Kaalia of the Vast+|2XM +Karrthus, Tyrant of Jund+|2XM +Maelstrom Nexus+|2XM +Maelstrom Pulse+|2XM +Manamorphose+|2XM +Mazirek, Kraul Death Priest+|2XM +Meddling Mage+|2XM +Merciless Eviction+|2XM +Progenitor Mimic+|2XM +Rhys the Redeemed+|2XM +Riku of Two Reflections+|2XM +Savageborn Hydra+|2XM +The Scarab God+|2XM +Selesnya Guildmage+|2XM +Sen Triplets+|2XM +Sharuum the Hegemon+|2XM +Sphinx Summoner+|2XM +Swiftblade Vindicator+|2XM +Thopter Foundry+|2XM +Time Sieve+|2XM +Unlicensed Disintegration+|2XM +Vexing Shusher+|2XM +Vish Kal, Blood Arbiter+|2XM +Voice of Resurgence+|2XM +Weapons Trainer+|2XM +Yavimaya's Embrace+|2XM +Accomplished Automaton+|2XM +Adaptive Automaton+|2XM +Basalt Monolith+|2XM +Basilisk Collar+|2XM +Batterskull+|2XM +Blightsteel Colossus+|2XM +Bosh, Iron Golem+|2XM +Cathodion+|2XM +Chief of the Foundry+|2XM +Chromatic Star+|2XM +Chrome Mox+|2XM +Clone Shell+|2XM +Cogwork Assembler+|2XM +Conjurer's Closet+|2XM +Coretapper+|2XM +Cranial Plating+|2XM +Culling Dais+|2XM +Darksteel Axe+|2XM +Darksteel Forge+|2XM +Duplicant+|2XM +Eager Construct+|2XM +Endless Atlas+|2XM +Engineered Explosives+|2XM +Ensnaring Bridge+|2XM +Everflowing Chalice+|2XM +Expedition Map+|2XM +Flayer Husk+|2XM +Gleaming Barrier+|2XM +Golem Artisan+|2XM +Golem-Skin Gauntlets+|2XM +Hammer of Nazahn+|2XM +Ichor Wellspring+|2XM +Iron Bully+|2XM +Iron League Steed+|2XM +Isochron Scepter+|2XM +Jhoira's Familiar+|2XM +Kuldotha Forgemaster+|2XM +Lightning Greaves+|2XM +Lux Cannon+|2XM +Magnifying Glass+|2XM +Mana Crypt+|2XM +Masterwork of Ingenuity+|2XM +Mesmeric Orb+|2XM +Metalspinner's Puzzleknot+|2XM +Mishra's Bauble+|2XM +Mox Opal+|2XM +Myr Battlesphere+|2XM +Myr Retriever+|2XM +O-Naginata+|2XM +Oblivion Stone+|2XM +Peace Strider+|2XM +Pentad Prism+|2XM +Phyrexian Revoker+|2XM +Pyrite Spellbomb+|2XM +Ratchet Bomb+|2XM +Sandstone Oracle+|2XM +Sculpting Steel+|2XM +Sickleslicer+|2XM +Skinwing+|2XM +Spellskite+|2XM +Sphinx of the Guildpact+|2XM +Springleaf Drum+|2XM +Sundering Titan+|2XM +Sunforger+|2XM +Surge Node+|2XM +Sword of Body and Mind+|2XM +Sword of Feast and Famine+|2XM +Sword of Fire and Ice+|2XM +Sword of Light and Shadow+|2XM +Sword of the Meek+|2XM +Sword of War and Peace+|2XM +Throne of Geth+|2XM +Treasure Keeper+|2XM +Trinisphere+|2XM +Tumble Magnet+|2XM +Vulshok Gauntlets+|2XM +Walking Ballista+|2XM +Welding Jar+|2XM +Wurmcoil Engine+|2XM +Academy Ruins+|2XM +Ash Barrens+|2XM +Blinkmoth Nexus+|2XM +Buried Ruin+|2XM +Cascade Bluffs+|2XM +Dark Depths+|2XM +Darksteel Citadel+|2XM +Fetid Heath+|2XM +Fire-Lit Thicket+|2XM +Flooded Grove+|2XM +Glimmervoid+|2XM +Graven Cairns+|2XM +High Market+|2XM +Maze of Ith+|2XM +Mishra's Factory+|2XM +Mystic Gate+|2XM +Rugged Prairie+|2XM +Sunken Ruins+|2XM +Thespian's Stage+|2XM +Twilight Mire+|2XM +Urza's Mine+|2XM +Urza's Power Plant+|2XM +Urza's Tower+|2XM +Wooded Bastion+|2XM diff --git a/forge-gui/res/cardsfolder/p/primordial_mist.txt b/forge-gui/res/cardsfolder/p/primordial_mist.txt index e9805b606b9..49df8aa2d79 100644 --- a/forge-gui/res/cardsfolder/p/primordial_mist.txt +++ b/forge-gui/res/cardsfolder/p/primordial_mist.txt @@ -3,7 +3,7 @@ ManaCost:4 U Types:Enchantment T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigManifest | OptionalDecider$ You | TriggerDescription$ At the beginning of your end step, you may manifest the top card of your library. SVar:TrigManifest:DB$ Manifest | Amount$ 1 | Defined$ TopOfLibrary -A:AB$ Effect | Cost$ Exile<1/Permanent.faceDown>| RememberObjects$ ExiledCards | StaticAbilities$ Play | ExileOnMoved$ Exile | SpellDescription$ Exile a face-down permanent you control face up: You may play that card this turn. (You still pay its costs. Timing rules still apply.) +A:AB$ Effect | Cost$ Exile<1/Permanent.faceDown> | CostDesc$ Exile a face-down permanent you control face up: | RememberObjects$ ExiledCards | StaticAbilities$ Play | ExileOnMoved$ Exile | SpellDescription$ You may play that card this turn. (You still pay its costs. Timing rules still apply.) SVar:Play:Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered | AffectedZone$ Exile | Description$ You may play remembered card. AI:RemoveDeck:All Oracle:At the beginning of your end step, you may manifest the top card of your library. (Put it onto the battlefield face down as a 2/2 creature. Turn it face up any time for its mana cost if it's a creature card.)\nExile a face-down permanent you control face up: You may play that card this turn. (You still pay its costs. Timing rules still apply.) diff --git a/forge-gui/res/cardsfolder/s/sarkhan_vol.txt b/forge-gui/res/cardsfolder/s/sarkhan_vol.txt index 8b1e5199d33..1a81d255230 100644 --- a/forge-gui/res/cardsfolder/s/sarkhan_vol.txt +++ b/forge-gui/res/cardsfolder/s/sarkhan_vol.txt @@ -5,6 +5,6 @@ Loyalty:4 A:AB$ PumpAll | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidCards$ Creature.YouCtrl | NumAtt$ +1 | NumDef$ +1 | KW$ Haste | SpellDescription$ Creatures you control get +1/+1 and gain haste until end of turn. A:AB$ GainControl | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SpellDescription$ Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn. A:AB$ Token | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | TokenAmount$ 5 | TokenScript$ r_4_4_dragon_flying | TokenOwner$ You | LegacyImage$ r 4 4 dragon flying ala | SpellDescription$ Create five 4/4 red Dragon creature tokens with flying. -SVar:PlayMain1:TRUE +SVar:PlayMain1:ALWAYS SVar:Picture:http://www.wizards.com/global/images/magic/general/sarkhan_vol.jpg Oracle:[+1]: Creatures you control get +1/+1 and gain haste until end of turn.\n[-2]: Gain control of target creature until end of turn. Untap that creature. It gains haste until end of turn.\n[-6]: Create five 4/4 red Dragon creature tokens with flying. diff --git a/forge-gui/res/editions/Double Masters.txt b/forge-gui/res/editions/Double Masters.txt new file mode 100644 index 00000000000..c088e550891 --- /dev/null +++ b/forge-gui/res/editions/Double Masters.txt @@ -0,0 +1,426 @@ +[metadata] +Code=2XM +Date=2020-08-07 +Name=Double Masters +Type=Reprint +BoosterCovers=3 +Booster=8 Common, 3 Uncommon, 2 RareMythic, 2 fromSheet("2XM Foils") +Foil=NotSupported + +[cards] +1 M Karn Liberated +2 C Alabaster Mage +3 C Ancestral Blade +4 C Angel of the Dawn +5 M Archangel of Thune +6 U Auriok Salvagers +7 R Austere Command +8 M Avacyn, Angel of Hope +9 R Blade Splicer +10 R Boon Reflection +11 R Council's Judgment +12 C Crib Swap +13 C Crusader of Odric +14 R Ethersworn Canonist +15 U Fencing Ace +16 U Flickerwisp +17 C Fortify +18 C Glint-Sleeve Artisan +19 R Kemba, Kha Regent +20 M Land Tax +21 R Leonin Abunas +22 U Master Splicer +23 U Myrsmith +24 R Open the Vaults +25 U Path to Exile +26 R Puresteel Paladin +27 C Remember the Fallen +28 C Revoke Existence +29 C Sanctum Gargoyle +30 C Sanctum Spirit +31 R Stoneforge Mystic +32 R Stonehewer Giant +33 C Strength of Arms +34 R Tempered Steel +35 C Thraben Inspector +36 U Topple the Statue +37 U Valor in Akros +38 U Valorous Stance +39 R Wrath of God +40 C Apprentice Wizard +41 M Arcum Dagsson +42 C Argivian Restoration +43 R Braids, Conjurer Adept +44 C Brainstorm +45 C Cloudreader Sphinx +46 C Corridor Monitor +47 R Cyclonic Rift +48 R Deepglow Skate +49 U Esperzoa +50 C Faerie Mechanist +51 M Force of Will +52 C Frogify +53 R Grand Architect +54 U Hinder +55 R Inkwell Leviathan +56 M Jace, the Mind Sculptor +57 R Master of Etherium +58 R Master Transmuter +59 C Metallic Rebuke +60 C Parasitic Strix +61 R Phyrexian Metamorph +62 U Pongify +63 C Relic Runner +64 R Reshape +65 U Riddlesmith +66 U Rush of Knowledge +67 U Sentinel of the Pearl Trident +68 U Serra Sphinx +69 C Sift +70 C Steel Sabotage +71 U Thirst for Knowledge +72 R Thought Reflection +73 U Treasure Mage +74 C Vedalken Infuser +75 R Well of Ideas +76 R Ad Nauseam +77 R Beacon of Unrest +78 C Bone Picker +79 C Cast Down +80 C Costly Plunder +81 M Dark Confidant +82 R Death's Shadow +83 C Defiant Salvager +84 C Dire Fleet Hoarder +85 R Disciple of Bolas +86 U Disciple of the Vault +87 C Divest +88 R Doomed Necromancer +89 U Dread Return +90 C Driver of the Dead +91 U Drown in Sorrow +92 C Executioner's Capsule +93 U Fatal Push +94 M Geth, Lord of the Vault +95 C Glaze Fiend +96 C Heartless Pillage +97 R Magus of the Abyss +98 R Magus of the Will +99 U Morkrut Banshee +100 U Oubliette +101 U Ovalchase Daredevil +102 U Painsmith +103 R Ravenous Trap +104 R Salvage Titan +105 C Silumgar Scavenger +106 R Skirsdag High Priest +107 M Skithiryx, the Blight Dragon +108 C Supernatural Stamina +109 R Thoughtseize +110 R Toxic Deluge +111 C Twisted Abomination +112 U Vampire Hexmage +113 R Wound Reflection +114 C Abrade +115 C Balduvian Rage +116 C Battle-Rattle Shaman +117 R Blasphemous Act +118 R Blood Moon +119 U Bloodshot Trainee +120 U Brimstone Volley +121 C Cathartic Reunion +122 R Cragganwick Cremator +123 U Dismantle +124 R Dualcaster Mage +125 U Galvanic Blast +126 C Goblin Gaveleer +127 R Goblin Guide +128 R Godo, Bandit Warlord +129 R Grim Lavamancer +130 R Heat Shimmer +131 M Imperial Recruiter +132 R Ion Storm +133 C Kazuul's Toll Collector +134 U Kuldotha Flamefiend +135 C Lightning Axe +136 M Mana Echoes +137 C Orcish Vandal +138 U Pyrewild Shaman +139 R Rage Reflection +140 C Rapacious Dragon +141 U Ravenous Intruder +142 R Rolling Earthquake +143 C Salivating Gremlins +144 C Skinbrand Goblin +145 M Sneak Attack +146 C Temur Battle Rage +147 U Thopter Engineer +148 U Trash for Treasure +149 R Tuktuk the Explorer +150 C Weapon Surge +151 C Ancient Stirrings +152 M Avenger of Zendikar +153 R Awakening Zone +154 C Bloodbriar +155 R Bloodspore Thrinax +156 R Champion of Lambholt +157 C Chatter of the Squirrel +158 R Chord of Calling +159 C Clear Shot +160 C Conclave Naturalists +161 U Crop Rotation +162 C Crushing Vines +163 C Death-Hood Cobra +164 M Doubling Season +165 C Elvish Aberration +166 U Enlarge +167 R Exploration +168 C Fierce Empath +169 U Gelatinous Genesis +170 R Greater Good +171 R Heartbeat of Spring +172 U Invigorate +173 C Kozilek's Predator +174 R Liege of the Tangle +175 R Mana Reflection +176 C Might of the Masses +177 R Noble Hierarch +178 U Reclamation Sage +179 R Shamanic Revelation +180 U Skullmulcher +181 C Sylvan Might +182 R Terastodon +183 R Thragtusk +184 U Ulvenwald Mysteries +185 M Vengevine +186 U Veteran Explorer +187 C Whisperer of the Wilds +188 U Woodland Champion +189 R Arixmethes, Slumbering Isle +190 M Atraxa, Praetors' Voice +191 R Baleful Strix +192 M Breya, Etherium Shaper +193 R Brudiclad, Telchor Engineer +194 U Deathreap Ritual +195 R Falkenrath Aristocrat +196 R Fulminator Mage +197 M Geist of Saint Traft +198 U Ghor-Clan Rampager +199 U Glassdust Hulk +200 R Hanna, Ship's Navigator +201 U Hidden Stockpile +202 U Izzet Charm +203 R Jhoira, Weatherlight Captain +204 M Kaalia of the Vast +205 M Karrthus, Tyrant of Jund +206 M Maelstrom Nexus +207 R Maelstrom Pulse +208 U Manamorphose +209 R Mazirek, Kraul Death Priest +210 R Meddling Mage +211 R Merciless Eviction +212 R Progenitor Mimic +213 R Rhys the Redeemed +214 M Riku of Two Reflections +215 R Savageborn Hydra +216 M The Scarab God +217 U Selesnya Guildmage +218 M Sen Triplets +219 R Sharuum the Hegemon +220 U Sphinx Summoner +221 R Swiftblade Vindicator +222 U Thopter Foundry +223 R Time Sieve +224 U Unlicensed Disintegration +225 R Vexing Shusher +226 R Vish Kal, Blood Arbiter +227 R Voice of Resurgence +228 U Weapons Trainer +229 U Yavimaya's Embrace +230 C Accomplished Automaton +231 R Adaptive Automaton +232 U Basalt Monolith +233 R Basilisk Collar +234 M Batterskull +235 M Blightsteel Colossus +236 R Bosh, Iron Golem +237 C Cathodion +238 U Chief of the Foundry +239 C Chromatic Star +240 M Chrome Mox +241 U Clone Shell +242 U Cogwork Assembler +243 R Conjurer's Closet +244 U Coretapper +245 U Cranial Plating +246 U Culling Dais +247 C Darksteel Axe +248 M Darksteel Forge +249 R Duplicant +250 C Eager Construct +251 R Endless Atlas +252 R Engineered Explosives +253 M Ensnaring Bridge +254 C Everflowing Chalice +255 C Expedition Map +256 C Flayer Husk +257 C Gleaming Barrier +258 U Golem Artisan +259 C Golem-Skin Gauntlets +260 R Hammer of Nazahn +261 C Ichor Wellspring +262 C Iron Bully +263 C Iron League Steed +264 R Isochron Scepter +265 U Jhoira's Familiar +266 R Kuldotha Forgemaster +267 U Lightning Greaves +268 R Lux Cannon +269 C Magnifying Glass +270 M Mana Crypt +271 R Masterwork of Ingenuity +272 R Mesmeric Orb +273 C Metalspinner's Puzzleknot +274 U Mishra's Bauble +275 M Mox Opal +276 R Myr Battlesphere +277 C Myr Retriever +278 U O-Naginata +279 R Oblivion Stone +280 C Peace Strider +281 U Pentad Prism +282 R Phyrexian Revoker +283 C Pyrite Spellbomb +284 R Ratchet Bomb +285 U Sandstone Oracle +286 R Sculpting Steel +287 C Sickleslicer +288 C Skinwing +289 R Spellskite +290 U Sphinx of the Guildpact +291 U Springleaf Drum +292 R Sundering Titan +293 R Sunforger +294 C Surge Node +295 M Sword of Body and Mind +296 M Sword of Feast and Famine +297 M Sword of Fire and Ice +298 M Sword of Light and Shadow +299 R Sword of the Meek +300 M Sword of War and Peace +301 U Throne of Geth +302 U Treasure Keeper +303 M Trinisphere +304 C Tumble Magnet +305 C Vulshok Gauntlets +306 R Walking Ballista +307 U Welding Jar +308 M Wurmcoil Engine +309 R Academy Ruins +310 U Ash Barrens +311 R Blinkmoth Nexus +312 U Buried Ruin +313 R Cascade Bluffs +314 M Dark Depths +315 U Darksteel Citadel +316 R Fetid Heath +317 R Fire-Lit Thicket +318 R Flooded Grove +319 R Glimmervoid +320 R Graven Cairns +321 R High Market +322 R Maze of Ith +323 U Mishra's Factory +324 R Mystic Gate +325 R Rugged Prairie +326 R Sunken Ruins +327 R Thespian's Stage +328 R Twilight Mire +329 C Urza's Mine +330 C Urza's Power Plant +331 C Urza's Tower +332 R Wooded Bastion +333 M Karn Liberated +334 M Jace, the Mind Sculptor +335 M Avacyn, Angel of Hope +336 R Council's Judgment +337 R Stoneforge Mystic +338 R Brainstorm +339 R Cyclonic Rift +340 M Force of Will +341 R Phyrexian Metamorph +342 M Dark Confidant +343 R Fatal Push +344 R Thoughtseize +345 R Toxic Deluge +346 R Blood Moon +347 R Goblin Guide +348 M Sneak Attack +349 R Crop Rotation +350 M Doubling Season +351 R Exploration +352 R Noble Hierarch +353 M Atraxa, Praetors' Voice +354 M Kaalia of the Vast +355 R Meddling Mage +356 M Batterskull +357 M Blightsteel Colossus +358 M Chrome Mox +359 R Expedition Map +360 R Lightning Greaves +361 M Mana Crypt +362 M Mox Opal +363 M Sword of Body and Mind +364 M Sword of Feast and Famine +365 M Sword of Fire and Ice +366 M Sword of Light and Shadow +367 M Sword of War and Peace +368 M Wurmcoil Engine +369 R Academy Ruins +370 R Urza's Mine +371 R Urza's Power Plant +372 R Urza's Tower +373 L Plains +374 L Plains +375 L Island +376 L Island +377 L Swamp +378 L Swamp +379 L Mountain +380 L Mountain +381 L Forest +382 L Forest +383 R Wrath of God +384 R Chord of Calling + +[tokens] +b_0_0_germ +b_5_5_demon_flying +c_0_1_eldrazi_spawn_sac +c_1_1_a_myr +c_1_1_a_servo +c_1_1_a_thopter_flying +c_1_1_shapeshifter_changeling +c_3_3_a_golem +c_3_3_a_wurm_deathtouch +c_3_3_a_wurm_lifelink +c_a_clue_draw +c_a_treasure_sac +g_0_1_plant +g_1_1_saproling +g_1_1_squirrel +g_2_2_wolf +g_3_3_ape +g_3_3_beast +g_3_3_elephant +g_x_x_ooze +gw_1_1_elf_warrior +gw_x_x_elemental_total_creatures +marit_lage +tuktuk_the_returned +u_1_1_a_thopter_flying +u_2_1_a_myr +w_1_1_human_soldier +w_1_1_soldier +w_2_2_cat +w_4_4_angel_flying diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 82c3e928822..80a126a3e65 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1658,8 +1658,8 @@ lblOr=oder lblDoYouWantPay=Möchtest du bezahlen: lblDoYouWantPayNLife=Möchtest du {0} Leben bezahlen? lblDoyouWantTo=Möchtest du -lblDoYouWantMillNCardsOrDoAction=Möchtest du {0} Karte(n) von der Bibliothek auf den Friedhof legen? -lblDoYouWantFlipNCoinOrDoAction=Möchtest du {0} Münze(n) werfen? {1} +lblDoYouWantMillNCardsOrDoAction=Möchtest du {0} Karte(n) von der Bibliothek auf den Friedhof legen? {1} +lblDoYouWantFlipNCoinAction=Möchtest du {0} Münze(n) werfen? lblDoYouWantRemoveNTargetTypeCounterFromCard=Möchtest du {0} {1}-Marken von {2} entfernen? lblDoYouWantRemoveCountersFromCard=Möchtest du Marken von {0} entfernen? lblDoYouWantExileNCardsFromYourLibrary=Möchtest du {0} Karte(n) von deiner Bibliothek ins Exil schicken? diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 8346e089c24..8a51c20d86e 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1659,7 +1659,7 @@ lblDoYouWantPay=Do you want to pay lblDoYouWantPayNLife=Do you want to pay {0} life? lblDoyouWantTo=Do you want to lblDoYouWantMillNCardsOrDoAction=Do you want to mill {0} card(s)? {1} -lblDoYouWantFlipNCoinOrDoAction=Do you want to flip {0} coin(s)? {1} +lblDoYouWantFlipNCoinAction=Do you want to flip {0} coin(s)? lblDoYouWantRemoveNTargetTypeCounterFromCard=Do you want to remove {0} {1} counter from {2}? lblDoYouWantRemoveCountersFromCard=Do you want to remove counters from {0}? lblDoYouWantExileNCardsFromYourLibrary=Do you want to exile {0} card(s) from your library? diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 41cd304b057..9b3138f1902 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1659,7 +1659,7 @@ lblDoYouWantPay=¿Quieres pagar lblDoYouWantPayNLife=¿Quieres pagar {0} de vida? lblDoyouWantTo=¿Quieres lblDoYouWantMillNCardsOrDoAction=¿Quieres moler {0} carta(s)? {1} -lblDoYouWantFlipNCoinOrDoAction=¿Quieres lanzar {0} moneda(s)? {1} +lblDoYouWantFlipNCoinAction=¿Quieres lanzar {0} moneda(s)? lblDoYouWantRemoveNTargetTypeCounterFromCard=¿Quieres quitar el contador {0} {1} de {2}? lblDoYouWantRemoveCountersFromCard=¿Quieres quitar los contadores de {0}? lblDoYouWantExileNCardsFromYourLibrary=¿Quieres exiliar {0} carta(s) de tu biblioteca? diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index dc4a8a42e2e..5914b341f26 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1659,7 +1659,7 @@ lblDoYouWantPay=Do you want to pay lblDoYouWantPayNLife=Do you want to pay {0} life? lblDoyouWantTo=Do you want to lblDoYouWantMillNCardsOrDoAction=Do you want to mill {0} card(s)? {1} -lblDoYouWantFlipNCoinOrDoAction=Do you want to flip {0} coin(s)? {1} +lblDoYouWantFlipNCoinAction=Do you want to flip {0} coin(s)? lblDoYouWantRemoveNTargetTypeCounterFromCard=Do you want to remove {0} {1} counter from {2}? lblDoYouWantRemoveCountersFromCard=Do you want to remove counters from {0}? lblDoYouWantExileNCardsFromYourLibrary=Do you want to exile {0} card(s) from your library? diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index ef7e4fedadd..40ef0108e25 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1659,7 +1659,7 @@ lblDoYouWantPay=你想要支付 lblDoYouWantPayNLife=你想要支付{0}点生命吗? lblDoyouWantTo=你想要 lblDoYouWantMillNCardsOrDoAction=你想要磨{0}张牌吗? {1} -lblDoYouWantFlipNCoinOrDoAction=你想要抛{0}个硬币吗? {1} +lblDoYouWantFlipNCoinAction=你想要抛{0}个硬币吗? lblDoYouWantRemoveNTargetTypeCounterFromCard=你想要从{2}移除{0}个{1}指示物吗? lblDoYouWantRemoveCountersFromCard=你想要从{0}删除指示物吗? lblDoYouWantExileNCardsFromYourLibrary=你想要从你的牌库放逐{0}张牌吗? diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index b2496fb2254..15c31774702 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -525,14 +525,13 @@ public class HumanCostDecision extends CostDecisionMakerBase { Integer c = cost.convertAmount(); if (c == null) { - final String sVar = ability.getSVar(amount); - // Generalize this - if (sVar.equals("XChoice")) { - c = chooseXValue(cost.getLKIList().size()); - } else { - c = AbilityUtils.calculateAmount(source, amount, ability); - } + c = AbilityUtils.calculateAmount(source, amount, ability); } + + if (!player.getController().confirmPayment(cost, Localizer.getInstance().getMessage("lblDoYouWantFlipNCoinAction", String.valueOf(c)), ability)) { + return null; + } + return PaymentDecision.number(c); } diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index 404671b8792..33afd029f80 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -11,7 +11,6 @@ import forge.game.GameEntityViewMap; import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.effects.CharmEffect; -import forge.game.ability.effects.FlipCoinEffect; import forge.game.card.*; import forge.game.card.CardPredicates.Presets; import forge.game.cost.*; @@ -322,16 +321,22 @@ public class HumanPlay { ((CostMill) part).payAsDecided(p, PaymentDecision.card(listmill), sourceAbility); } else if (part instanceof CostFlipCoin) { - final int amount = getAmountFromPart(part, source, sourceAbility); - if (!p.getController().confirmPayment(part, Localizer.getInstance().getMessage("lblDoYouWantFlipNCoinOrDoAction", String.valueOf(amount), orString), sourceAbility)) { + if (!part.canPay(sourceAbility, p)) { return false; } - final int n = FlipCoinEffect.getFilpMultiplier(p); - for (int i = 0; i < amount; i++) { - FlipCoinEffect.flipCoinCall(p, sourceAbility, n); - } + + PaymentDecision pd = part.accept(hcd); + + if (pd == null) + return false; + else + part.payAsDecided(p, pd, sourceAbility); } else if (part instanceof CostDamage) { + if (!part.canPay(sourceAbility, p)) { + return false; + } + // not a pay life but damage! PaymentDecision pd = part.accept(hcd); @@ -341,6 +346,10 @@ public class HumanPlay { part.payAsDecided(p, pd, sourceAbility); } else if (part instanceof CostPutCounter) { + if (!part.canPay(sourceAbility, p)) { + return false; + } + PaymentDecision pd = part.accept(hcd); if (pd == null)