diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index e663feb77da..4939cdd9282 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -1398,7 +1398,7 @@ public abstract class GameState { c.setTurnInZone(turn); } else if (info.equals("IsToken")) { c.setGamePieceType(GamePieceType.TOKEN); - } else if (info.equals("ClassLevel:")) { + } else if (info.startsWith("ClassLevel:")) { c.setClassLevel(Integer.parseInt(info.substring(info.indexOf(':') + 1))); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java index 7f3ca431d7d..08ac7418f67 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CopyPermanentEffect.java @@ -258,6 +258,10 @@ public class CopyPermanentEffect extends TokenEffectBase { if (sa.hasParam("ForEach")) { for (Player p : AbilityUtils.getDefinedPlayers(host, sa.getParam("ForEach"), sa)) { + if (sa.hasParam("OptionalForEach") && !activator.getController().confirmAction(sa, null, + Localizer.getInstance().getMessage("lblCopyPermanentConfirm") + " (" + p + ")", null)) { + continue; + } Card proto = getProtoType(sa, c, controller); proto.addRemembered(p); tokenTable.put(controller, proto, numCopies); 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 df4e2fc8cfe..fe5b8489d91 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -7206,6 +7206,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr setRegeneratedThisTurn(0); resetShieldCount(); setBecameTargetThisTurn(false); + setValiant(false); setFoughtThisTurn(false); turnedFaceUpThisTurn = false; clearMustBlockCards(); diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 4d64ee8fb2d..ecb07b2b39b 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1553,7 +1553,7 @@ public class CardFactoryUtil { final String actualTrigger = "Mode$ Attacks | ValidCard$ Card.Self | Secondary$ True" + " | TriggerDescription$ Myriad (" + inst.getReminderText() + ")"; - final String copyStr = "DB$ CopyPermanent | Defined$ Self | TokenTapped$ True | Optional$ True | TokenAttacking$ RememberedPlayer & Valid Planeswalker.ControlledBy Remembered" + final String copyStr = "DB$ CopyPermanent | Defined$ Self | TokenTapped$ True | OptionalForEach$ True | TokenAttacking$ RememberedPlayer & Valid Planeswalker.ControlledBy Remembered" + "| ForEach$ OppNonDefendingPlayer | AtEOT$ ExileCombat | CleanupForEach$ True"; final SpellAbility copySA = AbilityFactory.getAbility(copyStr, card); diff --git a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java index 1b2933d00f0..04788a01ae3 100644 --- a/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java +++ b/forge-game/src/main/java/forge/game/mana/ManaCostBeingPaid.java @@ -307,7 +307,7 @@ public class ManaCostBeingPaid { sc.xCount = sc.totalCount; } // nothing more left in otherSubtract - return; + break; } } } @@ -327,7 +327,7 @@ public class ManaCostBeingPaid { sc.xCount = sc.totalCount; } // nothing more left in otherSubtract - return; + break; } } } @@ -347,7 +347,7 @@ public class ManaCostBeingPaid { sc.xCount = sc.totalCount; } // nothing more left in otherSubtract - return; + break; } } } @@ -367,7 +367,7 @@ public class ManaCostBeingPaid { sc.xCount = sc.totalCount; } // nothing more left in otherSubtract - return; + break; } } } @@ -389,7 +389,7 @@ public class ManaCostBeingPaid { sc.xCount = sc.totalCount; } // nothing more left in otherSubtract - return; + break; } } else if (sc.xCount > 0) { // X part that can only be paid by specific color if (otherSubtract >= sc.xCount) { @@ -403,7 +403,7 @@ public class ManaCostBeingPaid { sc.totalCount -= otherSubtract; sc.xCount -= otherSubtract; // nothing more left in otherSubtract - return; + break; } } } diff --git a/forge-gui/res/cardsfolder/d/doomsday.txt b/forge-gui/res/cardsfolder/d/doomsday.txt index 2554696e343..e0b92280dc4 100644 --- a/forge-gui/res/cardsfolder/d/doomsday.txt +++ b/forge-gui/res/cardsfolder/d/doomsday.txt @@ -1,7 +1,7 @@ Name:Doomsday ManaCost:B B B Types:Sorcery -A:SP$ ChangeZone | Origin$ Graveyard,Library | Destination$ Library | ChangeType$ Card | ChangeNum$ 5 | SubAbility$ DBChangeZone | RememberChanged$ True | Mandatory$ True | SpellDescription$ Search your library and graveyard for five cards and exile the rest. Put the chosen cards on top of your library in any order. You lose half your life, rounded up. +A:SP$ ChangeZone | Origin$ Graveyard,Library | Destination$ Library | ChangeType$ Card | ChangeNum$ 5 | Shuffle$ False | SubAbility$ DBChangeZone | RememberChanged$ True | Mandatory$ True | SpellDescription$ Search your library and graveyard for five cards and exile the rest. Put the chosen cards on top of your library in any order. You lose half your life, rounded up. SVar:DBChangeZone:DB$ ChangeZoneAll | Defined$ You | Origin$ Graveyard,Library | Destination$ Exile | ChangeType$ Card.IsNotRemembered | SubAbility$ DBDig SVar:DBDig:DB$ RearrangeTopOfLibrary | Defined$ You | NumCards$ X | SubAbility$ DBLoseLife SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ Y | SubAbility$ DBCleanup diff --git a/forge-gui/res/cardsfolder/s/saw_in_half.txt b/forge-gui/res/cardsfolder/s/saw_in_half.txt index 9a6f9ba25af..de86038d9a0 100644 --- a/forge-gui/res/cardsfolder/s/saw_in_half.txt +++ b/forge-gui/res/cardsfolder/s/saw_in_half.txt @@ -2,7 +2,7 @@ Name:Saw in Half ManaCost:2 B Types:Instant A:SP$ Destroy | ValidTgts$ Creature | TgtPrompt$ Select target creature | SubAbility$ DBCopy | RememberLKI$ True | SpellDescription$ Destroy target creature. -SVar:DBCopy:DB$ CopyPermanent | Defined$ Remembered | NumCopies$ 2 | Controller$ TargetedController | SetPower$ dX | SetToughness$ dY | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup | StackDescription$ SpellDescription | SpellDescription$ If that creature dies this way, its controller creates two tokens that are copies of that creature, except their base power is half that creature's power and their base toughness is half that creature's toughness. Round up each time. +SVar:DBCopy:DB$ CopyPermanent | Defined$ RememberedLKI | NumCopies$ 2 | Controller$ TargetedController | SetPower$ dX | SetToughness$ dY | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup | StackDescription$ SpellDescription | SpellDescription$ If that creature dies this way, its controller creates two tokens that are copies of that creature, except their base power is half that creature's power and their base toughness is half that creature's toughness. Round up each time. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Remembered$Amount SVar:dX:RememberedLKI$CardPower/HalfUp diff --git a/forge-gui/res/cardsfolder/upcoming/friendly_teddy.txt b/forge-gui/res/cardsfolder/upcoming/friendly_teddy.txt index 95cb1eb8a63..28d409da95f 100644 --- a/forge-gui/res/cardsfolder/upcoming/friendly_teddy.txt +++ b/forge-gui/res/cardsfolder/upcoming/friendly_teddy.txt @@ -2,6 +2,6 @@ Name:Friendly Teddy ManaCost:2 Types:Artifact Creature Bear Toy PT:2/2 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME enters, each player draws a card. +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$ When CARDNAME dies, each player draws a card. SVar:TrigDraw:DB$ Draw | Defined$ Player -Oracle:When Friendly Teddy enters, each player draws a card. \ No newline at end of file +Oracle:When Friendly Teddy dies, each player draws a card. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/monstrous_emergence.txt b/forge-gui/res/cardsfolder/upcoming/monstrous_emergence.txt new file mode 100644 index 00000000000..1473bb4189d --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/monstrous_emergence.txt @@ -0,0 +1,7 @@ +Name:Monstrous Emergence +ManaCost:1 G +Types:Sorcery +A:SP$ DealDamage | Cost$ 1 G RevealOrChoose<1/Creature> | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ X | SpellDescription$ CARDNAME deals damage equal to the power of the creature you chose or the card you revealed to target creature. +SVar:X:Revealed$CardPower +AI:RemoveDeck:All +Oracle:As an additional cost to cast this spell, choose a creature you control or reveal a creature card from your hand.\nMonstrous Emergence deals damage equal to the power of the creature you chose or the card you revealed to target creature. diff --git a/forge-gui/res/cardsfolder/upcoming/valgavoth_terror_eater.txt b/forge-gui/res/cardsfolder/upcoming/valgavoth_terror_eater.txt index 8d953f72576..6f003372032 100644 --- a/forge-gui/res/cardsfolder/upcoming/valgavoth_terror_eater.txt +++ b/forge-gui/res/cardsfolder/upcoming/valgavoth_terror_eater.txt @@ -5,7 +5,7 @@ PT:9/9 K:Flying K:Lifelink K:Ward:Sac<3/Permanent.nonLand/nonland permanent> -R:Event$ Moved | ActiveZones$ Battlefield | Destination$ Graveyard | ValidCard$ Card.nonToken+YouDontCtrl+OppOwn | ReplaceWith$ Exile | Description$ If a card you didn't control would be put into an opponent's graveyard from anywhere, exile it instead. +R:Event$ Moved | ActiveZones$ Battlefield | Destination$ Graveyard | ValidLKI$ Card.nonToken+YouDontCtrl+OppOwn | ReplaceWith$ Exile | Description$ If a card you didn't control would be put into an opponent's graveyard from anywhere, exile it instead. SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard S:Mode$ Continuous | Condition$ PlayerTurn | MayPlay$ True | Affected$ Card.ExiledWithSource | AffectedZone$ Exile | MayPlayAltManaCost$ PayLife | Description$ During your turn, you may play cards exiled with NICKNAME. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost. Oracle:Flying, lifelink\nWard—Sacrifice three nonland permanents.\nIf a card you didn't control would be put into an opponent's graveyard from anywhere, exile it instead.\nDuring your turn, you may play cards exiled with Valgavoth. If you cast a spell this way, pay life equal to its mana value rather than pay its mana cost. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/upcoming/valgavoths_onslaught.txt b/forge-gui/res/cardsfolder/upcoming/valgavoths_onslaught.txt index b40db49938f..96b8e79f6f4 100644 --- a/forge-gui/res/cardsfolder/upcoming/valgavoths_onslaught.txt +++ b/forge-gui/res/cardsfolder/upcoming/valgavoths_onslaught.txt @@ -1,6 +1,6 @@ Name:Valgavoth's Onslaught ManaCost:X X G -Types:Instant +Types:Sorcery A:SP$ ManifestDread | Amount$ X | RememberManifested$ True | SubAbility$ DBPutCounter SVar:DBPutCounter:DB$ PutCounter | Defined$ RememberedCard | CounterType$ P1P1 | CounterNum$ X | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/puzzle/PS_BLB4.pzl b/forge-gui/res/puzzle/PS_BLB4.pzl new file mode 100644 index 00000000000..6ce0bc5ecad --- /dev/null +++ b/forge-gui/res/puzzle/PS_BLB4.pzl @@ -0,0 +1,16 @@ +[metadata] +Name:Possibility Storm - Bloomburrow #04 +URL:https://i2.wp.com/www.possibilitystorm.com/wp-content/uploads/2024/09/latest-scaled.jpg?ssl=1 +Goal:Win +Turns:1 +Difficulty:Mythic +Description:Win this turn. Ensure your solution satisfies all possible blocking decisions. Good luck! +[state] +turn=1 +activeplayer=p0 +activephase=MAIN1 +p0life=20 +p0hand=Ornery Tumblewagg;Oko, the Ringleader;Season of Gathering;Shivan Devastator;Ferocification +p0battlefield=Innkeeper's Talent|ClassLevel:2;Rampaging Geoderm;Kami of Whispered Hopes|Counters:P1P1=2;Island;Island;Mountain;Mountain;Forest;Forest +p1life=17 +p1battlefield=Fear of Immobility;Shield-Wall Sentinel