diff --git a/forge-game/src/main/java/forge/game/ability/ApiType.java b/forge-game/src/main/java/forge/game/ability/ApiType.java index 1d1e13a525b..e19938646fb 100644 --- a/forge-game/src/main/java/forge/game/ability/ApiType.java +++ b/forge-game/src/main/java/forge/game/ability/ApiType.java @@ -41,7 +41,6 @@ public enum ApiType { ChooseCard (ChooseCardEffect.class), ChooseColor (ChooseColorEffect.class), ChooseDirection (ChooseDirectionEffect.class), - ChooseEntity (ChooseEntityEffect.class), ChooseEvenOdd (ChooseEvenOddEffect.class), ChooseNumber (ChooseNumberEffect.class), ChoosePlayer (ChoosePlayerEffect.class), diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseEntityEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseEntityEffect.java deleted file mode 100644 index b702c7ed633..00000000000 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseEntityEffect.java +++ /dev/null @@ -1,54 +0,0 @@ -package forge.game.ability.effects; - -import com.google.common.collect.Lists; -import forge.game.Game; -import forge.game.GameEntity; -import forge.game.ability.AbilityUtils; -import forge.game.ability.SpellAbilityEffect; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardLists; -import forge.game.player.Player; -import forge.game.player.PlayerCollection; -import forge.game.spellability.SpellAbility; -import forge.game.zone.ZoneType; -import forge.util.Aggregates; - -import java.util.List; - -public class ChooseEntityEffect extends SpellAbilityEffect { - @Override - protected String getStackDescription(SpellAbility sa) { - return sa.hasParam("StackDescription") ? sa.getParam("StackDescription") : - sa.getParamOrDefault("SpellDescription", "Write a Stack/SpellDescription!"); - } - - @Override - public void resolve(SpellAbility sa) { - final Card host = sa.getHostCard(); - final Player activator = sa.getActivatingPlayer(); - final Game game = activator.getGame(); - - List choices = Lists.newArrayList(); - String cardsDef = sa.getParam("CardChoices"); - String playersDef = sa.getParam("PlayerChoices"); - CardCollection cards = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), cardsDef, activator, - host, sa); - choices.addAll(cards); - PlayerCollection players = AbilityUtils.getDefinedPlayers(host, playersDef, sa); - choices.addAll(players); - - Object chosen = null; - if (sa.hasParam("Random")) { // currently we only choose at random for this - chosen = Aggregates.random(choices); - } - if (chosen == null) { - System.err.println("Error: ChooseEntityEffect.java unable to choose an entity"); - return; - } - - if (sa.hasParam("RememberChosen")) { - host.addRemembered(chosen); - } - } -} 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 5f303703298..0ea92400ad2 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 @@ -17,13 +17,17 @@ import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardDamageMap; +import forge.game.card.CardLists; import forge.game.card.CardUtil; import forge.game.keyword.Keyword; import forge.game.player.Player; import forge.game.replacement.ReplacementType; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; +import forge.util.Aggregates; import forge.util.Lang; import forge.util.Localizer; +import forge.util.collect.FCollection; public class DamageDealEffect extends DamageBaseEffect { @@ -153,7 +157,37 @@ public class DamageDealEffect extends DamageBaseEffect { final boolean removeDamage = sa.hasParam("Remove"); final boolean divideOnResolution = sa.hasParam("DividerOnResolution"); - List tgts = getTargets(sa); + List tgts = Lists.newArrayList(); + if (sa.hasParam("CardChoices") || sa.hasParam("PlayerChoices")) { // choosing outside Defined/Targeted + final Player activator = sa.getActivatingPlayer(); + FCollection choices = new FCollection<>(); + if (sa.hasParam("CardChoices")) { + choices.addAll(CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), + sa.getParam("CardChoices"), activator, hostCard, sa)); + } + if (sa.hasParam("PlayerChoices")) { + choices.addAll(AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("PlayerChoices"), sa)); + } + + int n = sa.hasParam("ChoiceAmount") ? + AbilityUtils.calculateAmount(hostCard, sa.getParam("ChoiceAmount"), sa) : 1; + if (sa.hasParam("Random")) { // only for Whimsy and Faerie Dragon + for (int i = 0; i < n; i++) { + GameObject random = Aggregates.random(choices); + tgts.add(random); + choices.remove(random); + hostCard.addRemembered(random); // remember random choices for log + } + } else { // only for Comet, Stellar Pup + final String prompt = sa.hasParam("ChoicePrompt") ? sa.getParam("ChoicePrompt") : + Localizer.getInstance().getMessage("lblChooseEntityDmg"); + tgts.addAll(sa.getActivatingPlayer().getController().chooseEntitiesForEffect(choices, n, n, null, sa, + prompt, null, null)); + } + } else { + tgts = getTargets(sa); + } + if (sa.hasParam("OptionalDecider")) { Player decider = Iterables.getFirst(AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("OptionalDecider"), sa), null); if (decider != null && !decider.getController().confirmAction(sa, null, Localizer.getInstance().getMessage("lblDoyouWantDealTargetDamageToTarget", String.valueOf(dmg), tgts.toString()), null)) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffect.java index 4970b73264f..d06dab25e17 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffect.java @@ -2,13 +2,19 @@ package forge.game.ability.effects; import java.util.List; +import com.google.common.collect.Lists; +import forge.game.GameEntity; import forge.game.GameObject; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; +import forge.game.card.CardLists; import forge.game.card.CardUtil; import forge.game.player.Player; import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; +import forge.util.Aggregates; +import forge.util.collect.FCollection; public class DamagePreventEffect extends DamagePreventEffectBase { @@ -65,7 +71,26 @@ public class DamagePreventEffect extends DamagePreventEffectBase { Card host = sa.getHostCard(); int numDam = AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa); - final List tgts = getTargets(sa); + List tgts = Lists.newArrayList(); + if (sa.hasParam("CardChoices") || sa.hasParam("PlayerChoices")) { // choosing outside Defined/Targeted + // only for Whimsy, for more robust version see DamageDealEffect + FCollection choices = new FCollection<>(); + if (sa.hasParam("CardChoices")) { + choices.addAll(CardLists.getValidCards(host.getGame().getCardsIn(ZoneType.Battlefield), + sa.getParam("CardChoices"), sa.getActivatingPlayer(), host, sa)); + } + if (sa.hasParam("PlayerChoices")) { + choices.addAll(AbilityUtils.getDefinedPlayers(host, sa.getParam("PlayerChoices"), sa)); + } + if (sa.hasParam("Random")) { // currently everything using Choices is random + GameObject random = Aggregates.random(choices); + tgts.add(random); + host.addRemembered(random); // remember random choices for log + } + } else { + tgts = getTargets(sa); + } + final CardCollection untargetedCards = CardUtil.getRadiance(sa); final boolean targeted = sa.usesTargeting(); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java index 0ed423661a0..b22803c1936 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -38,6 +38,7 @@ import forge.game.cost.IndividualCostPaymentInstance; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.staticability.StaticAbilityCastWithFlash; +import forge.game.staticability.StaticAbilityNumLoyaltyAct; import forge.game.zone.Zone; import forge.game.zone.ZoneType; import forge.util.Expressions; @@ -474,11 +475,11 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { } if (sa.isPwAbility()) { - final int initialLimit = c.hasKeyword("CARDNAME's loyalty abilities can be activated twice each turn rather than only once") ? 1 : 0; - final int limits = c.getAmountOfKeyword("May activate CARDNAME's loyalty abilities once") + initialLimit; + final int initialLimit = StaticAbilityNumLoyaltyAct.limitIncrease(c) ? 1 : 0; + final int limit = StaticAbilityNumLoyaltyAct.additionalActivations(c, sa) + initialLimit; int numActivates = c.getPlaneswalkerAbilityActivated(); - if (numActivates > limits) { + if (numActivates > limit) { return false; } } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java new file mode 100644 index 00000000000..43bd2d29646 --- /dev/null +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityNumLoyaltyAct.java @@ -0,0 +1,67 @@ +package forge.game.staticability; + +import forge.game.ability.AbilityUtils; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; + +/** + * The Class StaticAbility_NumLoyaltyAct. + * - used to modify how many times a planeswalker may activate loyalty abilities per turn + */ +public class StaticAbilityNumLoyaltyAct { + + static String MODE = "NumLoyaltyAct"; + + public static boolean limitIncrease(final Card card) { + for (final Card ca : card.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } + + if (applyLimitIncrease(stAb, card)) { + return true; + } + } + } + return false; + } + + public static boolean applyLimitIncrease(final StaticAbility stAb, final Card card) { + + if (!stAb.matchesValidParam("ValidCard", card)) { + return false; + } + + if (!stAb.hasParam("Twice")) { + return false; + } + + return true; + } + + public static int additionalActivations(final Card card, final SpellAbility sa) { + int addl = 0; + for (final Card ca : card.getGame().getCardsIn(ZoneType.STATIC_ABILITIES_SOURCE_ZONES)) { + for (final StaticAbility stAb : ca.getStaticAbilities()) { + if (!stAb.getParam("Mode").equals(MODE) || stAb.isSuppressed() || !stAb.checkConditions()) { + continue; + } + if (!stAb.matchesValidParam("ValidCard", card)) { + continue; + } + if (stAb.hasParam("Additional")) { + if (stAb.hasParam("OnlySourceAbs")) { + if (!stAb.getHostCard().getEffectSourceAbility().getRootAbility().equals(sa)) { + continue; + } + } + int more = AbilityUtils.calculateAmount(card, stAb.getParam("Additional"), stAb); + addl = addl + more; + } + } + } + return addl; + } +} diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 01ebb5a7c96..0b34f0a2995 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -927,7 +927,11 @@ public final class CMatchUI if (enabled && firstEnabled < 0) { firstEnabled = index; } - GuiUtils.addMenuItem(menu, FSkin.encodeSymbols(ab.toString(), true), + String s = ab.toString(); + if (s.contains("\n")) { + s = s.substring(0, s.indexOf("\n")); + } + GuiUtils.addMenuItem(menu, FSkin.encodeSymbols(s, true), shortcut > 0 ? KeyStroke.getKeyStroke(shortcut, 0) : null, new Runnable() { @Override diff --git a/forge-gui/res/cardsfolder/f/faerie_dragon.txt b/forge-gui/res/cardsfolder/f/faerie_dragon.txt index bc6a8366519..bd249607b8a 100644 --- a/forge-gui/res/cardsfolder/f/faerie_dragon.txt +++ b/forge-gui/res/cardsfolder/f/faerie_dragon.txt @@ -22,8 +22,7 @@ SVar:White:DB$ ChooseCard | Choices$ Permanent | IncludeSpellsOnStack$ True | At SVar:DBAnimateW:DB$ Animate | Defined$ ChosenCard | Colors$ White | OverwriteColors$ True | Duration$ Permanent | LockInText$ True | SubAbility$ DBCleanup SVar:Red:DB$ ChooseCard | Choices$ Permanent | IncludeSpellsOnStack$ True | AtRandom$ True | LockInText$ True | SubAbility$ DBAnimateR | SpellDescription$ A spell or permanent chosen at random becomes red. (Mana symbols on that permanent remain unchanged.) SVar:DBAnimateR:DB$ Animate | Defined$ ChosenCard | Colors$ Red | OverwriteColors$ True | Duration$ Permanent | LockInText$ True | SubAbility$ DBCleanup -SVar:Damage3:DB$ ChooseEntity | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | RememberChosen$ True | SubAbility$ DBDamage3 | SpellDescription$ CARDNAME deals 3 damage to a creature or player chosen at random. -SVar:DBDamage3:DB$ DealDamage | Defined$ Remembered | NumDmg$ 3 | SubAbility$ DBCleanup +SVar:Damage3:DB$ DealDamage | NumDmg$ 3 | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | RememberRandomChoice$ True | SubAbility$ DBCleanup | SpellDescription$ CARDNAME deals 3 damage to a creature or player chosen at random. SVar:Flying:DB$ ChooseCard | Choices$ Creature | AtRandom$ True | SubAbility$ DBPump8 | SpellDescription$ A creature chosen at random gains flying until end of turn. SVar:DBPump8:DB$ Pump | Defined$ ChosenCard | KW$ Flying | SubAbility$ DBCleanup SVar:P3P3:DB$ ChooseCard | Choices$ Creature | AtRandom$ True | SubAbility$ DBPump9 | SpellDescription$ A creature chosen at random gets +3/+3 until end of turn. @@ -43,8 +42,7 @@ SVar:M2M0:DB$ ChooseCard | Choices$ Creature | AtRandom$ True | SubAbility$ DBPu SVar:DBPump15:DB$ Pump | Defined$ ChosenCard | NumAtt$ -2 | SubAbility$ DBCleanup SVar:ToHand:DB$ ChooseCard | Choices$ Creature | AtRandom$ True | SubAbility$ DBChangeZone16 | SpellDescription$ Return a creature chosen at random to its owner's hand. SVar:DBChangeZone16:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBCleanup -SVar:Damage1:DB$ ChooseEntity | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | RememberChosen$ True | SubAbility$ DBDamage1 | SpellDescription$ CARDNAME deals 1 damage to a creature or player chosen at random. -SVar:DBDamage1:DB$ DealDamage | Defined$ Remembered | NumDmg$ 1 | SubAbility$ DBCleanup +SVar:Damage1:DB$ DealDamage | NumDmg$ 1 | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | RememberRandomChoice$ True | SubAbility$ DBCleanup | SpellDescription$ CARDNAME deals 1 damage to a creature or player chosen at random. SVar:Nerf:DB$ ChooseCard | Choices$ Creature.Other | AtRandom$ True | SubAbility$ DBAnimate18 | SpellDescription$ A creature other than CARDNAME chosen at random becomes 0/2 until end of turn. SVar:DBAnimate18:DB$ Animate | Defined$ ChosenCard | Power$ 0 | Toughness$ 2 | SubAbility$ DBCleanup SVar:Exile:DB$ ChooseCard | Choices$ Creature | AtRandom$ True | SubAbility$ DBChangeZone19 | SpellDescription$ Exile a creature chosen at random. Its controller gains life equal to its power. diff --git a/forge-gui/res/cardsfolder/o/oath_of_teferi.txt b/forge-gui/res/cardsfolder/o/oath_of_teferi.txt index e3dbe0456a0..733d18d9f9d 100644 --- a/forge-gui/res/cardsfolder/o/oath_of_teferi.txt +++ b/forge-gui/res/cardsfolder/o/oath_of_teferi.txt @@ -6,6 +6,6 @@ SVar:TrigExile:DB$ ChangeZone | ValidTgts$ Permanent.Other+YouCtrl | Mandatory$ SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigBounce | TriggerDescription$ Return exiled permanent to the battlefield. | RememberObjects$ RememberedLKI | SubAbility$ DBCleanup SVar:TrigBounce:DB$ ChangeZone | Origin$ Exile | Destination$ Battlefield | Defined$ DelayTriggerRememberedLKI SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -S:Mode$ Continuous | AffectedZone$ Battlefield | Affected$ Planeswalker.YouCtrl | AddHiddenKeyword$ CARDNAME's loyalty abilities can be activated twice each turn rather than only once | Description$ You may activate the loyalty abilities of planeswalkers you control twice each turn rather than only once. +S:Mode$ NumLoyaltyAct | ValidCard$ Planeswalker.YouCtrl | Twice$ True | Description$ You may activate the loyalty abilities of planeswalkers you control twice each turn rather than only once. SVar:NeedsToPlay:Planeswalker.YouCtrl Oracle:When Oath of Teferi enters the battlefield, exile another target permanent you control. Return it to the battlefield under its owner's control at the beginning of the next end step.\nYou may activate the loyalty abilities of planeswalkers you control twice each turn rather than only once. diff --git a/forge-gui/res/cardsfolder/s/spark_fiend.txt b/forge-gui/res/cardsfolder/s/spark_fiend.txt index 35c897e9439..70187978c77 100644 --- a/forge-gui/res/cardsfolder/s/spark_fiend.txt +++ b/forge-gui/res/cardsfolder/s/spark_fiend.txt @@ -2,14 +2,14 @@ Name:Spark Fiend ManaCost:4 R Types:Creature Beast PT:5/6 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRollETB | TriggerDescription$ When Spark Fiend enters the battlefield, roll two six-sided dice. If you rolled 2, 3, or 12, sacrifice Spark Fiend. If you rolled 7 or 11, don't roll dice for Spark Fiend during any of your following upkeeps. If you rolled any other total, note that total. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigRollETB | TriggerDescription$ When Spark Fiend enters the battlefield, roll two six-sided dice. If you rolled 2, 3, or 12, sacrifice CARDNAME. If you rolled 7 or 11, don't roll dice for CARDNAME during any of your following upkeeps. If you rolled any other total, note that total. SVar:TrigRollETB:DB$ RollDice | Amount$ 2 | ResultSubAbilities$ 2-3:DBSac,12:DBSac,7:DBSafe,Else:DBNote | ResultSVar$ Result SVar:DBSac:DB$ Sacrifice | Defined$ Self SVar:Safe:Number$1 SVar:Noted:Number$0 SVar:DBSafe:DB$ StoreSVar | SVar$ Safe | Type$ Number | Expression$ 0 SVar:DBNote:DB$ StoreSVar | SVar$ Noted | Type$ CountSVar | Expression$ Result -T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | CheckSVar$ Safe | SVarCompare$ NE0 | TriggerZones$ Battlefield | Execute$ TrigRoll | TriggerDescription$ At the beginning of your upkeep, roll two six-sided dice. If you rolled 7, sacrifice Spark Fiend. If you roll the noted total, don't roll dice for Spark Fiend during any of your following upkeeps. Otherwise, do nothing. +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | CheckSVar$ Safe | SVarCompare$ NE0 | TriggerZones$ Battlefield | Execute$ TrigRoll | TriggerDescription$ At the beginning of your upkeep, roll two six-sided dice. If you rolled 7, sacrifice CARDNAME. If you roll the noted total, don't roll dice for CARDNAME during any of your following upkeeps. Otherwise, do nothing. SVar:TrigRoll:DB$ RollDice | Amount$ 2 | ResultSubAbilities$ 7:DBSac | ResultSVar$ Result | SubAbility$ DBCheck SVar:DBCheck:DB$ StoreSVar | SVar$ Safe | Type$ CountSVar | Expression$ Result/Minus.Noted Oracle:When Spark Fiend enters the battlefield, roll two six-sided dice. If you rolled 2, 3, or 12, sacrifice Spark Fiend. If you rolled 7 or 11, don't roll dice for Spark Fiend during any of your following upkeeps. If you rolled any other total, note that total.\nAt the beginning of your upkeep, roll two six-sided dice. If you rolled 7, sacrifice Spark Fiend. If you roll the noted total, don't roll dice for Spark Fiend during any of your following upkeeps. Otherwise, do nothing. diff --git a/forge-gui/res/cardsfolder/t/the_chain_veil.txt b/forge-gui/res/cardsfolder/t/the_chain_veil.txt index 887b7d12330..8a0d5967e50 100644 --- a/forge-gui/res/cardsfolder/t/the_chain_veil.txt +++ b/forge-gui/res/cardsfolder/t/the_chain_veil.txt @@ -3,8 +3,8 @@ ManaCost:4 Types:Legendary Artifact T:Mode$ Phase | Phase$ End of Turn | ActivateNoLoyaltyAbilitiesCondition$ True | ValidPlayer$ You | Execute$ TrigLoseLife | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your end step, if you didn't activate a loyalty ability of a planeswalker this turn, you lose 2 life. SVar:TrigLoseLife:DB$ LoseLife | Defined$ You | LifeAmount$ 2 -A:AB$ Effect | Cost$ 4 T | StaticAbilities$ STPump | AILogic$ ChainVeil | SpellDescription$ For each planeswalker you control, you may activate one of its loyalty abilities once this turn as though none of its loyalty abilities had been activated this turn. -SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Planeswalker.YouCtrl | AddHiddenKeyword$ May activate CARDNAME's loyalty abilities once | Description$ For each planeswalker you control, you may activate one of its loyalty abilities once this turn as though none of its loyalty abilities had been activated this turn. +A:AB$ Effect | Cost$ 4 T | StaticAbilities$ LoyaltyAbs | AILogic$ ChainVeil | SpellDescription$ For each planeswalker you control, you may activate one of its loyalty abilities once this turn as though none of its loyalty abilities had been activated this turn. +SVar:LoyaltyAbs:Mode$ NumLoyaltyAct | ValidCard$ Planeswalker.YouCtrl | Additional$ 1 | Description$ For each planeswalker you control, you may activate one of its loyalty abilities once this turn as though none of its loyalty abilities had been activated this turn. SVar:NeedsToPlay:Planeswalker.YouCtrl AI:RemoveDeck:All AI:RemoveDeck:Random diff --git a/forge-gui/res/cardsfolder/u/urza_assembles_the_titans.txt b/forge-gui/res/cardsfolder/u/urza_assembles_the_titans.txt index c9733d36e40..1826ac67eda 100644 --- a/forge-gui/res/cardsfolder/u/urza_assembles_the_titans.txt +++ b/forge-gui/res/cardsfolder/u/urza_assembles_the_titans.txt @@ -5,8 +5,8 @@ K:Read ahead:3:DBScry,DBChangeZone,DBLoyalty SVar:DBScry:DB$ Scry | ScryNum$ 4 | SubAbility$ DBDig | SpellAbility$ Scry 4, then you may reveal the top card of your library. If a planeswalker card is revealed this way, put it into your hand. SVar:DBDig:DB$ Dig | DigNum$ 1 | Reveal$ True | ChangeNum$ All | ChangeValid$ Planeswalker | LibraryPosition2$ 0 SVar:DBChangeZone:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Planeswalker.cmcLE6 | ChangeNum$ 1 | SpellDescription$ You may put a planeswalker card with mana value 6 or less from your hand onto the battlefield. -SVar:DBLoyalty:DB$ Effect | StaticAbilities$ STPump | SpellDescription$ You may activate the loyalty abilities of planeswalkers you control twice this turn rather than only once. -SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Planeswalker.YouCtrl | AddHiddenKeyword$ CARDNAME's loyalty abilities can be activated twice each turn rather than only once | Description$ You may activate the loyalty abilities of planeswalkers you control twice this turn rather than only once. +SVar:DBLoyalty:DB$ Effect | StaticAbilities$ PWTwice | SpellDescription$ You may activate the loyalty abilities of planeswalkers you control twice this turn rather than only once. +SVar:PWTwice:Mode$ NumLoyaltyAct | ValidCard$ Planeswalker.YouCtrl | Twice$ True | Description$ You may activate the loyalty abilities of planeswalkers you control twice this turn rather than only once. DeckNeeds:Type$Planeswalker AI:RemoveDeck:Random -Oracle:Read ahead (Choose a chapter and start with that many lore counters. Add one after your draw step. Skipped chapters don't trigger. Sacrifice after III.)\nI — Scry 4, then you may reveal the top card of your library. If a planeswalker card is revealed this way, put it into your hand.\nII — You may put a planeswalker card with mana value 6 or less from your hand onto the battlefield.\nIII — You may activate the loyalty abilities of planeswalkers you control twice this turn rather than only once. \ No newline at end of file +Oracle:Read ahead (Choose a chapter and start with that many lore counters. Add one after your draw step. Skipped chapters don't trigger. Sacrifice after III.)\nI — Scry 4, then you may reveal the top card of your library. If a planeswalker card is revealed this way, put it into your hand.\nII — You may put a planeswalker card with mana value 6 or less from your hand onto the battlefield.\nIII — You may activate the loyalty abilities of planeswalkers you control twice this turn rather than only once. diff --git a/forge-gui/res/cardsfolder/upcoming/comet_stellar_pup.txt b/forge-gui/res/cardsfolder/upcoming/comet_stellar_pup.txt new file mode 100644 index 00000000000..b1b7e642804 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/comet_stellar_pup.txt @@ -0,0 +1,18 @@ +Name:Comet, Stellar Pup +ManaCost:2 R W +Types:Legendary Planeswalker Comet +Loyalty:5 +A:AB$ RollDice | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | ResultSubAbilities$ 1-2:Token,3:Unearth,4-5:Damage,6:CometGo | SpellDescription$ Roll a six-sided die. +SVar:Token:DB$ PutCounter | CounterType$ LOYALTY | CounterNum$ 2 | SubAbility$ DBToken | SpellDescription$ 1 or 2 – [+2], then create two 1/1 green Squirrel creature tokens. They gain haste until end of turn. +SVar:DBToken:DB$ Token | TokenAmount$ 2 | TokenScript$ g_1_1_squirrel | PumpKeywords$ Haste | PumpDuration$ EOT +SVar:Unearth:DB$ RemoveCounter | CounterType$ LOYALTY | CounterNum$ 1 | SubAbility$ DBChangeZone | SpellDescription$ 3 – [-1], then return a card with mana value 2 or less from your graveyard to your hand. +SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | Mandatory$ True | ChangeType$ Card.YouOwn+cmcLE2 | ChangeDescription$ Choose a card with mana value 2 or less | Hidden$ True +SVar:Damage:DB$ DealDamage | NumDmg$ X | CardChoices$ Creature | PlayerChoices$ Player | SubAbility$ DBRemoveCounters | SpellDescription$ 4 or 5 – CARDNAME deals damage equal to the number of loyalty counters on him to a creature or player, then [-2]. +SVar:X:Count$CardCounters.LOYALTY +SVar:DBRemoveCounters:DB$ RemoveCounter | CounterType$ LOYALTY | CounterNum$ 2 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:CometGo:DB$ PutCounter | CounterType$ LOYALTY | SubAbility$ DBEffect | SpellDescription$ 6 – [+1], and you may activate CARDNAME's loyalty ability two more times this turn. +SVar:DBEffect:DB$ Effect | StaticAbilities$ LoyaltyAbs | RememberObjects$ Self | ExileOnMoved$ Battlefield +SVar:LoyaltyAbs:Mode$ NumLoyaltyAct | ValidCard$ Card.EffectSource | Additional$ 2 | OnlySourceAbs$ True | Description$ You may activate EFFECTSOURCE's loyalty ability two more times this turn. +DeckHas:Ability$Token|Graveyard & Type$Squirrel +Oracle:[0]: Roll a six-sided die.\n1 or 2 — [+2], then create two 1/1 green Squirrel creature tokens. They gain haste until end of turn.\n3 — [-1], then return a card with mana value 2 or less from your graveyard to your hand.\n4 or 5 — Comet, Stellar Pup deals damage equal to the number of loyalty counters on him to a creature or player, then [-2].\n6 — [+1], and you may activate Comet, Stellar Pup's loyalty ability two more times this turn. diff --git a/forge-gui/res/cardsfolder/upcoming/urza_lord_protector_urza_planeswalker.txt b/forge-gui/res/cardsfolder/upcoming/urza_lord_protector_urza_planeswalker.txt index b2f358db037..ea89383e69c 100644 --- a/forge-gui/res/cardsfolder/upcoming/urza_lord_protector_urza_planeswalker.txt +++ b/forge-gui/res/cardsfolder/upcoming/urza_lord_protector_urza_planeswalker.txt @@ -17,7 +17,7 @@ ManaCost:no cost Colors:white,blue Types:Legendary Planeswalker Urza Loyalty:7 -S:Mode$ Continuous | EffectZone$ Battlefield | Affected$ Card.Self | AddHiddenKeyword$ CARDNAME's loyalty abilities can be activated twice each turn rather than only once | Description$ You may activate the loyalty abilities of CARDNAME twice each turn rather than only once. +S:Mode$ NumLoyaltyAct | ValidCard$ Card.Self | Twice$ True | Description$ You may activate the loyalty abilities of CARDNAME twice each turn rather than only once. (You may activate the same ability twice.) A:AB$ Effect | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | StaticAbilities$ ReduceCost | SubAbility$ DBGainLife | SpellDescription$ Artifact, instant, and sorcery spells you cast this turn cost {2} less to cast. SVar:ReduceCost:Mode$ ReduceCost | EffectZone$ Command | ValidCard$ Artifact,Instant,Sorcery | Type$ Spell | Activator$ You | Amount$ 2 | Description$ Artifact, instant, and sorcery spells you cast this turn cost {2} less to cast. SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 | SpellDescription$ You gain 2 life. @@ -27,4 +27,6 @@ A:AB$ Token | Cost$ AddCounter<0/LOYALTY> | Planeswalker$ True | TokenScript$ c_ A:AB$ ChangeZone | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Permanent.nonLand | TgtPrompt$ Select target nonland permanent | Origin$ Battlefield | Destination$ Exile | SpellDescription$ Exile target nonland permanent. A:AB$ PumpAll | Cost$ SubCounter<10/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidCards$ Artifact.YouCtrl,Planeswalker.YouCtrl | KW$ Indestructible | SubAbility$ DBDestroyAll | SpellDescription$ Artifacts and planeswalkers you control gain indestructible until end of turn. SVar:DBDestroyAll:DB$ DestroyAll | ValidCards$ Permanent.nonLand | SpellDescription$ Destroy all nonland permanents. -Oracle:You may activate the loyalty abilities of Urza, Planeswalker twice each turn rather than only once.\n[+2]: Artifact, instant, and sorcery spells you cast this turn cost {2} less to cast. You gain 2 life.\n[+1]: Draw two cards, then discard a card.\n[-3]: Exile target nonland permanent.\n[-10]: Artifacts and planeswalkers you control gain indestructible until end of turn. Destroy all nonland permanents. +DeckHas:Ability$LifeGain|Discard|Token & Type$Soldier +DeckHints:Type$Planeswalker +Oracle:You may activate the loyalty abilities of Urza, Planeswalker twice each turn rather than only once. (You may activate the same ability twice.)\n[+2]: Artifact, instant, and sorcery spells you cast this turn cost {2} less to cast. You gain 2 life.\n[+1]: Draw two cards, then discard a card.\n[0]: Create two 1/1 colorless Soldier artifact creature tokens.\n[−3]: Exile target nonland permanent.\n[−10]: Artifacts and planeswalkers you control gain indestructible until end of turn. Destroy all nonland permanents. diff --git a/forge-gui/res/cardsfolder/w/whimsy.txt b/forge-gui/res/cardsfolder/w/whimsy.txt index 175a4822260..4e5a0d51294 100644 --- a/forge-gui/res/cardsfolder/w/whimsy.txt +++ b/forge-gui/res/cardsfolder/w/whimsy.txt @@ -9,8 +9,7 @@ SVar:Untap:DB$ ChooseCard | Choices$ Artifact.tapped,Creature.tapped,Land.tapped SVar:DBUntap4:DB$ Untap | Defined$ ChosenCard | SubAbility$ DBCleanup SVar:Tap:DB$ ChooseCard | Choices$ Artifact.untapped,Creature.untapped,Land.untapped | AtRandom$ True | SubAbility$ DBTap5 | SpellDescription$ Tap an artifact, creature or land chosen at random. SVar:DBTap5:DB$ Tap | Defined$ ChosenCard | SubAbility$ DBCleanup -SVar:Damage:DB$ ChooseEntity | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | RememberChosen$ True | SubAbility$ DBDamage6 | SpellDescription$ CARDNAME deals 4 damage to a creature or player chosen at random. -SVar:DBDamage6:DB$ DealDamage | Defined$ Remembered | NumDmg$ 4 | SubAbility$ DBCleanup +SVar:Damage:DB$ DealDamage | NumDmg$ 4 | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | SubAbility$ DBCleanup | SpellDescription$ CARDNAME deals 4 damage to a creature or player chosen at random. SVar:Draw3:DB$ ChoosePlayer | Choices$ Player | Random$ True | SubAbility$ DBDraw7 | SpellDescription$ A player chosen at random draws three cards. SVar:DBDraw7:DB$ Draw | NumCards$ 3 | Defined$ ChosenPlayer | SubAbility$ DBCleanup SVar:DestroyGain:DB$ ChooseCard | Choices$ Artifact | AtRandom$ True | SubAbility$ DBDestroy8 | SpellDescription$ Destroy an artifact chosen at random. It can't be regenerated. That artifact's controller gains life equal to its converted mana cost. @@ -21,8 +20,7 @@ SVar:DestroyAE:DB$ ChooseCard | Choices$ Artifact,Enchantment | AtRandom$ True | SVar:DBDestroy9:DB$ Destroy | Defined$ ChosenCard | SubAbility$ DBCleanup SVar:Gain3:DB$ ChoosePlayer | Choices$ Player | Random$ True | SubAbility$ DBGainLife10 | SpellDescription$ A player chosen at random gains 3 life. SVar:DBGainLife10:DB$ GainLife | Defined$ ChosenPlayer | LifeAmount$ 3 | SubAbility$ DBCleanup -SVar:Anoint:DB$ ChooseEntity | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | RememberChosen$ True | SubAbility$ DBPreventDamage11 | SpellDescription$ Prevent the next 3 damage that would be dealt to a creature or player chosen at random this turn. -SVar:DBPreventDamage11:DB$ PreventDamage | Defined$ Remembered | Amount$ 3 | SubAbility$ DBCleanup +SVar:Anoint:DB$ PreventDamage | Random$ True | CardChoices$ Creature | PlayerChoices$ Player | Amount$ 3 | SubAbility$ DBCleanup | SpellDescription$ Prevent the next 3 damage that would be dealt to a creature or player chosen at random this turn. SVar:DestroyCL:DB$ ChooseCard | Choices$ Creature,Land | AtRandom$ True | SubAbility$ DBDestroy12 | SpellDescription$ Destroy a creature or land chosen at random. It can't be regenerated. SVar:DBDestroy12:DB$ Destroy | Defined$ ChosenCard | NoRegen$ True | SubAbility$ DBCleanup SVar:Mill2:DB$ ChoosePlayer | Choices$ Player | Random$ True | SubAbility$ DBMill13 | SpellDescription$ A player chosen at random mills two cards. diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index fc27f0766f0..8eaf0cdf173 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1944,6 +1944,7 @@ lblChooseCardsToTakeTargetCounters=Nimm {0}-Marken von welcher Karte lblSelectRemoveCountersNumberOfTarget=Wähle die zu entfernende Anzahl %s-Marken lblSelectCountersTypeToRemove=Wähle Marken-Typ fürs Entfernen #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=Soll {1} {0} Schaden erleiden? #DigEffect.java lblChooser=Auswählender diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 4b2dc10895b..66fcc0e914c 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1945,6 +1945,7 @@ lblChooseCardsToTakeTargetCounters=Choose cards to take {0} counters from lblSelectRemoveCountersNumberOfTarget=Select the number of {0} counters to remove lblSelectCountersTypeToRemove=Select type of counters to remove #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=Do you want to deal {0} damage to {1}? #DigEffect.java lblChooser=Chooser diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index f9f5d7a844b..a1a5df2fb83 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1943,6 +1943,7 @@ lblChooseCardsToTakeTargetCounters=Elige las cartas de las que coger {0} contado lblSelectRemoveCountersNumberOfTarget=Selecciona el número de {0} contadores a eliminar lblSelectCountersTypeToRemove=Selecciona el tipo de contadores a eliminar #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=¿Quieres hacer {0} de daño a {1}? #DigEffect.java lblChooser=Elector diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index 909101ea843..fdd8dbc3bd6 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -1946,6 +1946,7 @@ lblChooseCardsToTakeTargetCounters=Choisissez des cartes pour prendre {0} marque lblSelectRemoveCountersNumberOfTarget=Sélectionnez le nombre de {0} marqueurs à supprimer lblSelectCountersTypeToRemove=Sélectionner le type de marqueurs à supprimer #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=Voulez-vous infliger {0} dégâts à {1} ? #DigEffect.java lblChooser=Sélecteur diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 0529e866d8c..5230f87f331 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1942,6 +1942,7 @@ lblChooseCardsToTakeTargetCounters=Scegli le carte da cui prendere i segnalini { lblSelectRemoveCountersNumberOfTarget=Scegli il numero di segnalini {0} da rimuovere lblSelectCountersTypeToRemove=Scegli il tipo di segnalini da rimuovere #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=Vuoi infliggere {0} danno/i a {1}? #DigEffect.java lblChooser=Fai la tua scelta diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index fecd6c619c6..cf8a1c42230 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -1942,6 +1942,7 @@ lblChooseCardsToTakeTargetCounters={0}カウンターを取り除くカードを lblSelectRemoveCountersNumberOfTarget=取り除く {0}カウンターの数を選ぶ lblSelectCountersTypeToRemove=取り除くカウンターの種類を選ぶ #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget={1}に {0}点のダメージを与えますか? #DigEffect.java lblChooser=選択者 diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index 15be37a0af0..7bfa690f3df 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -2004,6 +2004,7 @@ lblChooseCardsToTakeTargetCounters=Escolha as cartas para pegar {0} marcadores lblSelectRemoveCountersNumberOfTarget=Selecione o número de {0} marcadores para remover lblSelectCountersTypeToRemove=Selecione o tipo de marcadores para remover #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=Você quer dar {0} de dano em {1}? #DigEffect.java lblChooser=Seletor diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index be0a39cba5c..b701c5bdf86 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1946,6 +1946,7 @@ lblChooseCardsToTakeTargetCounters=选择牌要获得{0}指示物自 lblSelectRemoveCountersNumberOfTarget=选择要删除的{0}指示物的数量 lblSelectCountersTypeToRemove=选择要删除的指示物类型 #DamageDealEffect.java +lblChooseEntityDmg=Choose entity for damage lblDoyouWantDealTargetDamageToTarget=你想对{1}造成{0}伤害吗? #DigEffect.java lblChooser=选择者 diff --git a/forge-gui/res/lists/TypeLists.txt b/forge-gui/res/lists/TypeLists.txt index 7a110c0e896..11a4ff8bc3a 100644 --- a/forge-gui/res/lists/TypeLists.txt +++ b/forge-gui/res/lists/TypeLists.txt @@ -335,6 +335,7 @@ Basri Bolas Calix Chandra +Comet Dack Dakkon Daretti diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 07a17901f8c..24cedc83146 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -631,7 +631,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } @Override - public List chooseEntitiesForEffect(final FCollectionView optionList, final int min, final int max, + public List chooseEntitiesForEffect(final FCollectionView optionList, final int min, final int max, final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer, Map params) { // useful details for debugging problems with the mass select logic Sentry.setExtra("Card", sa.getCardView().toString());