From d3487231f5bbab51beb9c0aa4f9fb4bf35c3a227 Mon Sep 17 00:00:00 2001 From: Lyu Zong-Hong Date: Sat, 17 Jul 2021 18:07:19 +0900 Subject: [PATCH] Add more AFC Roll Dice cards --- .../java/forge/game/ability/AbilityUtils.java | 4 +++ .../src/main/java/forge/game/card/Card.java | 31 ++++++++----------- .../java/forge/game/card/CounterEnumType.java | 2 ++ .../main/java/forge/game/player/Player.java | 3 ++ .../cardsfolder/upcoming/bag_of_tricks.txt | 6 ++++ .../upcoming/bucknards_everfull_purse.txt | 8 +++++ .../cardsfolder/upcoming/component_pouch.txt | 9 ++++++ .../res/cardsfolder/upcoming/ebony_fly.txt | 10 ++++++ .../cardsfolder/upcoming/maddening_hex.txt | 12 +++++++ .../upcoming/song_of_inspiration.txt | 11 +++++++ .../cardsfolder/upcoming/sword_of_hours.txt | 12 +++++++ .../cardsfolder/upcoming/underdark_rift.txt | 8 +++++ 12 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 forge-gui/res/cardsfolder/upcoming/bag_of_tricks.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/bucknards_everfull_purse.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/component_pouch.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/ebony_fly.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/maddening_hex.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/song_of_inspiration.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/sword_of_hours.txt create mode 100644 forge-gui/res/cardsfolder/upcoming/underdark_rift.txt diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 426a740137f..11dd1ada434 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -31,6 +31,7 @@ import forge.card.mana.ManaCost; import forge.card.mana.ManaCostParser; import forge.card.mana.ManaCostShard; import forge.game.CardTraitBase; +import forge.game.Direction; import forge.game.Game; import forge.game.GameEntity; import forge.game.GameObject; @@ -1268,6 +1269,9 @@ public class AbilityUtils { } else if (defined.equals("Opponent")) { players.addAll(player.getOpponents()); + } else if (defined.startsWith("NextPlayerToYour")) { + Direction dir = defined.substring(16).equals("Left") ? Direction.Left : Direction.Right; + players.add(game.getNextPlayerAfter(player, dir)); } else { for (Player p : game.getPlayersInTurnOrder()) { 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 f62cd15a2fe..24e466b381c 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -2213,6 +2213,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public String getAbilityText(final CardState state) { + final String linebreak = "\r\n\r\n"; final String grayTag = ""; final String endTag = ""; final CardTypeView type = state.getType(); @@ -2260,9 +2261,9 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // Get original description since text might be translated if (replacementEffect.hasParam("Description") && replacementEffect.getParam("Description").contains("enters the battlefield")) { - sb.append(text).append("\r\n"); + sb.append(text).append(linebreak); } else { - replacementEffects.append(text).append("\r\n"); + replacementEffects.append(text).append(linebreak); } } } @@ -2274,7 +2275,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { Cost cost = first.getPayCosts(); if (cost != null && !cost.isOnlyManaCost()) { sb.append(cost.toString()); - sb.append("\r\n"); + sb.append(linebreak); } } } @@ -2294,9 +2295,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } // Give spellText line breaks for easier reading - sb.append("\r\n"); sb.append(text.replaceAll("\\\\r\\\\n", "\r\n")); - sb.append("\r\n"); + sb.append(linebreak); // Triggered abilities for (final Trigger trig : state.getTriggers()) { @@ -2310,7 +2310,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { if (disabled) sb.append(grayTag); sb.append(trigStr.replaceAll("\\\\r\\\\n", "\r\n")); if (disabled) sb.append(endTag); - sb.append("\r\n"); + sb.append(linebreak); } } @@ -2322,7 +2322,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { if (!stAb.isSecondary() && !stAb.isClassAbility()) { final String stAbD = stAb.toString(); if (!stAbD.equals("")) { - sb.append(stAbD).append("\r\n"); + sb.append(stAbD).append(linebreak); } } } @@ -2395,7 +2395,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { desc = TextUtil.fastReplace(desc, "EFFECTSOURCE", host.getEffectSource().getName()); } sb.append(desc); - sb.append("\r\n"); + sb.append(linebreak); } } } @@ -2403,7 +2403,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // Class Abilities if (isClassCard()) { - String linebreak = "\r\n\r\n"; sb.append(linebreak); // Currently the maximum levels of all Class cards are all 3 for (int level = 1; level <= 3; ++level) { @@ -4895,15 +4894,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars { final String excR = incR[1]; final String[] exRs = excR.split("\\+"); // Exclusive Restrictions are ... for (String exR : exRs) { - if (exR.startsWith("!")) { - exR = exR.substring(1); - if (hasProperty(exR, sourceController, source, spellAbility)) { - return testFailed; - } - } else { - if (!hasProperty(exR, sourceController, source, spellAbility)) { - return testFailed; - } + if (!hasProperty(exR, sourceController, source, spellAbility)) { + return testFailed; } } } @@ -4913,6 +4905,9 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // Takes arguments like Blue or withFlying @Override public boolean hasProperty(final String property, final Player sourceController, final Card source, CardTraitBase spellAbility) { + if (property.startsWith("!")) { + return !CardProperty.cardHasProperty(this, property.substring(1), sourceController, source, spellAbility); + } return CardProperty.cardHasProperty(this, property, sourceController, source, spellAbility); } 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 8821fe46376..2a606219a63 100644 --- a/forge-game/src/main/java/forge/game/card/CounterEnumType.java +++ b/forge-game/src/main/java/forge/game/card/CounterEnumType.java @@ -65,6 +65,8 @@ public enum CounterEnumType { COIN("COIN",255,215,0), + COMPONENT("COMPN", 224, 160, 48), + CORPSE("CRPSE", 230, 186, 209), CORRUPTION("CRPTN", 210, 121, 210), diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index a109941e95f..3792241e456 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -2217,6 +2217,9 @@ public class Player extends GameEntity implements Comparable { @Override public final boolean hasProperty(final String property, final Player sourceController, final Card source, CardTraitBase spellAbility) { + if (property.startsWith("!")) { + return !PlayerProperty.playerHasProperty(this, property.substring(1), sourceController, source, spellAbility); + } return PlayerProperty.playerHasProperty(this, property, sourceController, source, spellAbility); } diff --git a/forge-gui/res/cardsfolder/upcoming/bag_of_tricks.txt b/forge-gui/res/cardsfolder/upcoming/bag_of_tricks.txt new file mode 100644 index 00000000000..896545c4949 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/bag_of_tricks.txt @@ -0,0 +1,6 @@ +Name:Bag of Tricks +ManaCost:1 G +Types:Artifact +A:AB$ RollDice | Cost$ 4 G T | Defined$ You | Sides$ 8 | ResultSVar$ X | SubAbility$ DBReveal | StackDescription$ SpellDescription | SpellDescription$ Roll a d8. Reveal cards from the top of your library until you reveal a creature card with mana value equal to the result. Put that card onto the battlefield and the rest on the bottom of your library in a random order. +SVar:DBReveal:DB$ DigUntil | Defined$ You | Valid$ Creature.cmcEQX | FoundDestination$ Battlefield | RevealedDestination$ Library | RevealedLibraryPosition$ -1 | RevealRandomOrder$ True | StackDescription$ None +Oracle:{4}{G}, {T}: Roll a d8. Reveal cards from the top of your library until you reveal a creature card with mana value equal to the result. Put that card onto the battlefield and the rest on the bottom of your library in a random order. diff --git a/forge-gui/res/cardsfolder/upcoming/bucknards_everfull_purse.txt b/forge-gui/res/cardsfolder/upcoming/bucknards_everfull_purse.txt new file mode 100644 index 00000000000..7645bd353fb --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/bucknards_everfull_purse.txt @@ -0,0 +1,8 @@ +Name:Bucknard's Everfull Purse +ManaCost:2 +Types:Artifact +A:AB$ RollDice | Cost$ 1 T | Defined$ You | Sides$ 4 | ResultSVar$ X | SubAbility$ DBTreasure | StackDescription$ SpellDescription | SpellDescription$ Roll a d4 and create a number of Treasure tokens equal to the result. The player to your right gains control of CARDNAME. +SVar:DBTreasure:DB$ Token | TokenAmount$ X | TokenScript$ c_a_treasure_sac | TokenOwner$ You | SubAbility$ DBPass +SVar:DBPass:DB$ GainControl | Defined$ Self | NewController$ NextPlayerToYourRight +DeckHas:Ability$Token +Oracle:{1}, {T}: Roll a d4 and create a number of Treasure tokens equal to the result. The player to your right gains control of Bucknard's Everfull Purse. diff --git a/forge-gui/res/cardsfolder/upcoming/component_pouch.txt b/forge-gui/res/cardsfolder/upcoming/component_pouch.txt new file mode 100644 index 00000000000..be7ad6622b2 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/component_pouch.txt @@ -0,0 +1,9 @@ +Name:Component Pouch +ManaCost:3 +Types:Artifact +A:AB$ Mana | Cost$ T SubCounter<1/COMPONENT> | Amount$ 2 | Produced$ Combo AnyDifferent | SpellDescription$ Add two mana of different colors. +A:AB$ RollDice | Cost$ T | Sides$ 20 | ResultSubAbilities$ 1-9:PutOne,10-20:PutTwo | SpellDescription$ Roll a d20. +SVar:PutOne:DB$ PutCounter | Defined$ Self | CounterType$ COMPONENT | CounterNum$ 1 | SpellDescription$ 1-9 VERT Put a component counter on CARDNAME. +SVar:PutTwo:DB$ PutCounter | Defined$ Self | CounterType$ COMPONENT | CounterNum$ 2 | SpellDescription$ 10-20 VERT Put two component counters on CARDNAME. +DeckHas:Ability$Counters +Oracle:{T}, Remove a component counter from Component Pouch: Add two mana of different colors.\n{T}: Roll a d20.\n1-9 | Put a component counter on Component Pouch.\n10-20 | Put two component counters on Component Pouch. diff --git a/forge-gui/res/cardsfolder/upcoming/ebony_fly.txt b/forge-gui/res/cardsfolder/upcoming/ebony_fly.txt new file mode 100644 index 00000000000..2db7666fb07 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/ebony_fly.txt @@ -0,0 +1,10 @@ +Name:Ebony Fly +ManaCost:2 +Types:Artifact +K:CARDNAME enters the battlefield tapped. +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ RollDice | Cost$ 4 | Sides$ 6 | ResultSVar$ X | SubAbility$ DBAnimate | SpellDescription$ Roll a d6. +SVar:DBAnimate:DB$ Animate | Defined$ Self | Power$ X | Toughness$ X | Types$ Artifact,Creature,Insect | Keywords$ Flying | RemoveCardTypes$ True | Optional$ True | StackDescription$ SpellDescription | SpellDescription$ Until end of turn, you may have CARDNAME become an X/X Insect artifact creature with flying, where X is the result. +T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever CARDNAME attacks, another target attacking creature gains flying until end of turn. +SVar:TrigPump:DB$ Pump | ValidTgts$ Creature.Other+attacking | TgtPrompt$ Select another target attacking creature | KW$ Flying +Oracle:Ebony Fly enters the battlefield tapped.\n{T}: Add {C}.\n{4}: Roll a d6. Until end of turn, you may have Ebony Fly become an X/X Insect artifact creature with flying, where X is the result.\nWhenever Ebony Fly attacks, another target attacking creature gains flying until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/maddening_hex.txt b/forge-gui/res/cardsfolder/upcoming/maddening_hex.txt new file mode 100644 index 00000000000..a0d18f59040 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/maddening_hex.txt @@ -0,0 +1,12 @@ +Name:Maddening Hex +ManaCost:1 R R +Types:Enchantment Aura Curse +K:Enchant player +A:SP$ Attach | Cost$ 1 R R | ValidTgts$ Player | AILogic$ Curse +T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Player.EnchantedBy | TriggerZones$ Battlefield | Execute$ TrigRollDice | TriggerDescription$ Whenever enchanted player casts a noncreature spell, roll a d6. CARDNAME deals damage to that player equal to the result. Then attach CARDNAME to another one of your opponents chosen at random. +SVar:TrigRollDice:DB$ RollDice | ResultSVar$ X | SubAbility$ DBDamage +SVar:DBDamage:DB$ DealDamage | Defined$ Player.EnchantedBy | NumDmg$ X | SubAbility$ DBChoose +SVar:DBChoose:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent+!EnchantedBy | Random$ True | SubAbility$ DBAttach +SVar:DBAttach:DB$ Attach | Defined$ ChosenPlayer | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearChosenPlayer$ True +Oracle:Enchant player\nWhenever enchanted player casts a noncreature spell, roll a d6. Maddening Hex deals damage to that player equal to the result. Then attach Maddening Hex to another one of your opponents chosen at random. diff --git a/forge-gui/res/cardsfolder/upcoming/song_of_inspiration.txt b/forge-gui/res/cardsfolder/upcoming/song_of_inspiration.txt new file mode 100644 index 00000000000..f64c6bb597a --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/song_of_inspiration.txt @@ -0,0 +1,11 @@ +Name:Song of Inspiration +ManaCost:3 G G +Types:Instant +A:SP$ Pump | ValidTgts$ Permanent.YouCtrl | TgtZone$ Graveyard | TargetMin$ 0 | TargetMax$ 2 | SubAbility$ DBRollDice | StackDescription$ SpellDescription | SpellDescription$ Choose up to two target permanent cards in your graveyard. Roll a d20 and add the total mana value of those cards. +SVar:DBRollDice:DB$ RollDice | Defined$ You | Sides$ 20 | Modifier$ X | ResultSubAbilities$ 1-14:ToHand,Else:HandAndLife +SVar:ToHand:DB$ ChangeZone | Defined$ Targeted | Origin$ Graveyard | Destination$ Hand | SpellDescription$ 1-14 VERT Return those cards to your hand. +SVar:HandAndLife:DB$ ChangeZone | Defined$ Targeted | Origin$ Graveyard | Destination$ Hand | SubAbility$ DBGainLife | SpellDescription$ 15+ VERT Return those cards to your hand. You gain life equal to their total mana value. +SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ X +SVar:X:Targeted$CardManaCost +DeckHas:Ability$Graveyard & Ability$LifeGain +Oracle:Choose up to two target permanent cards in your graveyard. Roll a d20 and add the total mana value of those cards.\n1-14 | Return those cards to your hand.\n15+ | Return those cards to your hand. You gain life equal to their total mana value. diff --git a/forge-gui/res/cardsfolder/upcoming/sword_of_hours.txt b/forge-gui/res/cardsfolder/upcoming/sword_of_hours.txt new file mode 100644 index 00000000000..7624c7b9a43 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/sword_of_hours.txt @@ -0,0 +1,12 @@ +Name:Sword of Hours +ManaCost:2 +Types:Artifact Equipment +K:Equip:2 +T:Mode$ Attacks | ValidCard$ Card.EquippedBy | Execute$ TrigPutCounter | TriggerDescription$ Whenever equipped creature attacks, put a +1/+1 counter on it. +SVar:TrigPutCounter:DB$ PutCounter | Defined$ Equipped | CounterType$ P1P1 | CounterNum$ 1 +T:Mode$ DamageDealtOnce | CombatDamage$ True | ValidSource$ Creature.EquippedBy | Execute$ TrigRollDice | TriggerZones$ Battlefield | TriggerDescription$ Whenever equipped creature deals combat damage, roll a d12. If the result is greater than the damage dealt or the result is 12, double the number of +1/+1 counters on that creature. +SVar:TrigRollDice:DB$ RollDice | Sides$ 12 | ResultSVar$ X | SubAbility$ DBDouble +SVar:DBDouble:DB$ MultiplyCounter | Defined$ Equipped | CounterType$ P1P1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GTY +SVar:Y:TriggerCount$DamageAmount/LimitMax.11 +DeckHas:Ability$Counters +Oracle:Whenever equipped creature attacks, put a +1/+1 counter on it.\nWhenever equipped creature deals combat damage, roll a d12. If the result is greater than the damage dealt or the result is 12, double the number of +1/+1 counters on that creature.\nEquip {2} ({2}: Attach to target creature you control. Equip only as a sorcery.) diff --git a/forge-gui/res/cardsfolder/upcoming/underdark_rift.txt b/forge-gui/res/cardsfolder/upcoming/underdark_rift.txt new file mode 100644 index 00000000000..52f987f5d53 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/underdark_rift.txt @@ -0,0 +1,8 @@ +Name:Underdark Rift +ManaCost:no cost +Types:Land +A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}. +A:AB$ Pump | Cost$ 5 T Exile<1/CARDNAME> | ValidTgts$ Artifact,Creature,Planeswalker | TgtPrompt$ Select target artifact, creature, or planeswalker | SorcerySpeed$ True | IsCurse$ True | SubAbility$ DBRollDice | StackDescription$ None | SpellDescription$ Roll a d10. Put target artifact, creature, or planeswalker into its owner's library just beneath the top X cards of that library, where X is the result. Activate only as a sorcery. +SVar:DBRollDice:DB$ RollDice | Sides$ 10 | ResultSVar$ X | SubAbility$ DBReturn +SVar:DBReturn:DB$ ChangeZone | Defined$ Targeted | Destination$ Library | LibraryPosition$ X | StackDescription$ Put {c:Targeted} into its owner's library just beneath the top X cards of that library, where X is the result. +Oracle:{T}: Add {C}.\n{5}, {T}, Exile Underdark Rift: Roll a d10. Put target artifact, creature, or planeswalker into its owner's library just beneath the top X cards of that library, where X is the result. Activate only as a sorcery.