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 caf567a5066..7d80f295144 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -566,7 +566,10 @@ public class AbilityUtils { } else if (calcX[0].equals("LastStateBattlefield") && ability instanceof SpellAbility) { Card c = ((SpellAbility) ability).getLastStateBattlefield().get(card); val = c == null ? 0 : xCount(c, calcX[1], ability); - } else if (calcX[0].startsWith("Remembered")) { + } else if (calcX[0].startsWith("ExiledWith")) { + val = handlePaid(card.getExiledCards(), calcX[1], card, ability); + } + else if (calcX[0].startsWith("Remembered")) { // Add whole Remembered list to handlePaid final CardCollection list = new CardCollection(); Card newCard = card; diff --git a/forge-game/src/main/java/forge/game/cost/CostExile.java b/forge-game/src/main/java/forge/game/cost/CostExile.java index cb1347ac665..d1ae6869344 100644 --- a/forge-game/src/main/java/forge/game/cost/CostExile.java +++ b/forge-game/src/main/java/forge/game/cost/CostExile.java @@ -123,11 +123,6 @@ public class CostExile extends CostPartWithList { return String.format ("Exile any number of %s from your %s", desc, origin); } - //for very specific situations like Timothar - if (desc.startsWith("the")) { - return String.format("Exile %s from your %s", desc, origin); - } - return String.format("Exile %s from your %s", Cost.convertAmountTypeToWords(i, this.getAmount(), desc), origin); } diff --git a/forge-gui/res/cardsfolder/a/academy_rector.txt b/forge-gui/res/cardsfolder/a/academy_rector.txt index b1520725d1e..42d4cc90466 100644 --- a/forge-gui/res/cardsfolder/a/academy_rector.txt +++ b/forge-gui/res/cardsfolder/a/academy_rector.txt @@ -2,9 +2,8 @@ Name:Academy Rector ManaCost:3 W Types:Creature Human Cleric PT:1/2 -T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, search your library for an enchantment card and put that card onto the battlefield, then shuffle. -SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | SubAbility$ DBReturn -SVar:DBReturn:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Enchantment.YouOwn | ChangeNum$ 1 +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, search your library for an enchantment card and put that card onto the battlefield, then shuffle. +SVar:TrigReturn:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Library | Destination$ Battlefield | ChangeType$ Enchantment.YouOwn | ChangeNum$ 1 SVar:SacMe:4 AI:RemoveDeck:Random DeckNeeds:Type$Enchantment diff --git a/forge-gui/res/cardsfolder/a/arena_rector.txt b/forge-gui/res/cardsfolder/a/arena_rector.txt index 07fc3ee3885..6352b57e0ac 100644 --- a/forge-gui/res/cardsfolder/a/arena_rector.txt +++ b/forge-gui/res/cardsfolder/a/arena_rector.txt @@ -2,9 +2,8 @@ Name:Arena Rector ManaCost:3 W Types:Creature Human Cleric PT:1/2 -T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, search your library for a planeswalker card, put it onto the battlefield, then shuffle. -SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | SubAbility$ DBReturn -SVar:DBReturn:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Planeswalker.YouOwn | ChangeNum$ 1 +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, search your library for a planeswalker card, put it onto the battlefield, then shuffle. +SVar:TrigExile:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Library | Destination$ Battlefield | ChangeType$ Planeswalker.YouOwn | ChangeNum$ 1 SVar:SacMe:4 AI:RemoveDeck:Random DeckNeeds:Type$Planeswalker diff --git a/forge-gui/res/cardsfolder/c/cavalier_of_thorns.txt b/forge-gui/res/cardsfolder/c/cavalier_of_thorns.txt index 46e1a8d3fb0..5d48d3f1356 100644 --- a/forge-gui/res/cardsfolder/c/cavalier_of_thorns.txt +++ b/forge-gui/res/cardsfolder/c/cavalier_of_thorns.txt @@ -5,7 +5,6 @@ PT:5/6 K:Reach T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDig | TriggerDescription$ When CARDNAME enters the battlefield, reveal the top five cards of your library. Put a land card from among them onto the battlefield and the rest into your graveyard. SVar:TrigDig:DB$ Dig | DigNum$ 5 | ChangeNum$ 1 | ChangeValid$ Land | Optional$ True | DestinationZone$ Battlefield | DestinationZone2$ Graveyard -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, put another target card from your graveyard on top of your library. -SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | SubAbility$ DBChange -SVar:DBChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | ValidTgts$ Card.YouOwn+Other | TgtPrompt$ Select another target card from your graveyard | AITgts$ Card.Other | ChangeNum$ 1 +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile| TriggerDescription$ When CARDNAME dies, you may exile it. If you do, put another target card from your graveyard on top of your library. +SVar:TrigExile:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Graveyard | Destination$ Library | ValidTgts$ Card.YouOwn+Other | TgtPrompt$ Select another target card from your graveyard | AITgts$ Card.Other | ChangeNum$ 1 Oracle:Reach\nWhen Cavalier of Thorns enters the battlefield, reveal the top five cards of your library. Put a land card from among them onto the battlefield and the rest into your graveyard.\nWhen Cavalier of Thorns dies, you may exile it. If you do, put another target card from your graveyard on top of your library. diff --git a/forge-gui/res/cardsfolder/c/colfenors_urn.txt b/forge-gui/res/cardsfolder/c/colfenors_urn.txt index 922a4ef549c..bdb6a88a793 100644 --- a/forge-gui/res/cardsfolder/c/colfenors_urn.txt +++ b/forge-gui/res/cardsfolder/c/colfenors_urn.txt @@ -2,9 +2,8 @@ Name:Colfenor's Urn ManaCost:3 Types:Artifact T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | ValidCard$ Creature.toughnessGE4+YouOwn | OptionalDecider$ You | Execute$ TrigExile | TriggerDescription$ Whenever a creature with toughness 4 or greater is put into your graveyard from the battlefield, you may exile it. -SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | RememberChanged$ True +SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE3 | Execute$ TrigReturnAll | TriggerDescription$ At the beginning of the end step, if three or more cards have been exiled with CARDNAME, sacrifice it. If you do, return those cards to the battlefield under their owner's control. -SVar:TrigReturnAll:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | SubAbility$ DBSacSelf -SVar:DBSacSelf:DB$ Sacrifice -SVar:X:Remembered$Amount +SVar:TrigReturnAll:AB$ ChangeZone | Cost$ Mandatory Sac<1/CARDNAME> | Defined$ ExiledWith | Origin$ Exile | Destination$ Battlefield +SVar:X:ExiledWith$Amount Oracle:Whenever a creature with toughness 4 or greater is put into your graveyard from the battlefield, you may exile it.\nAt the beginning of the end step, if three or more cards have been exiled with Colfenor's Urn, sacrifice it. If you do, return those cards to the battlefield under their owner's control. diff --git a/forge-gui/res/cardsfolder/c/creeping_chill.txt b/forge-gui/res/cardsfolder/c/creeping_chill.txt index 6afe9895037..29edfe7bbe8 100644 --- a/forge-gui/res/cardsfolder/c/creeping_chill.txt +++ b/forge-gui/res/cardsfolder/c/creeping_chill.txt @@ -3,7 +3,6 @@ ManaCost:3 B Types:Sorcery A:SP$ DamageAll | StackDescription$ CARDNAME deals 3 damage to each opponent and | Cost$ 3 B | ValidPlayers$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to each opponent and you gain 3 life. T:Mode$ ChangesZone | Origin$ Library | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ When CARDNAME is put into your graveyard from your library, you may exile it. If you do, CARDNAME deals 3 damage to each opponent and you gain 3 life. -SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBDamage -SVar:DBDamage:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife +SVar:TrigExile:AB$ DealDamage | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Defined$ Player.Opponent | NumDmg$ 3 | SubAbility$ DBGainLife SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 3 Oracle:Creeping Chill deals 3 damage to each opponent and you gain 3 life.\nWhen Creeping Chill is put into your graveyard from your library, you may exile it. If you do, Creeping Chill deals 3 damage to each opponent and you gain 3 life. diff --git a/forge-gui/res/cardsfolder/g/gamekeeper.txt b/forge-gui/res/cardsfolder/g/gamekeeper.txt index f4d4ee2260a..6ad8af5e234 100644 --- a/forge-gui/res/cardsfolder/g/gamekeeper.txt +++ b/forge-gui/res/cardsfolder/g/gamekeeper.txt @@ -2,7 +2,6 @@ Name:Gamekeeper ManaCost:3 G Types:Creature Elf PT:2/2 -T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, reveal cards from the top of your library until you reveal a creature card. Put that card onto the battlefield and put all other cards revealed this way into your graveyard. -SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBDigUntil -SVar:DBDigUntil:DB$ DigUntil | Valid$ Creature | ValidDescription$ Creature | FoundDestination$ Battlefield | RevealedDestination$ Graveyard +T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, reveal cards from the top of your library until you reveal a creature card. Put that card onto the battlefield and put all other cards revealed this way into your graveyard. +SVar:TrigExile:AB$ DigUntil | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Valid$ Creature | ValidDescription$ Creature | FoundDestination$ Battlefield | RevealedDestination$ Graveyard Oracle:When Gamekeeper dies, you may exile it. If you do, reveal cards from the top of your library until you reveal a creature card. Put that card onto the battlefield and put all other cards revealed this way into your graveyard. diff --git a/forge-gui/res/cardsfolder/g/greenbelt_rampager.txt b/forge-gui/res/cardsfolder/g/greenbelt_rampager.txt index b6a707642fd..85ea5e2e4bc 100644 --- a/forge-gui/res/cardsfolder/g/greenbelt_rampager.txt +++ b/forge-gui/res/cardsfolder/g/greenbelt_rampager.txt @@ -2,7 +2,7 @@ Name:Greenbelt Rampager ManaCost:G Types:Creature Elephant PT:3/4 -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ PaymentCheck | TriggerDescription$ When CARDNAME enters the battlefield, pay {E}{E} (two energy counters). If you can't, return Greenbelt Rampager to its owner's hand and you get {E}. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ PaymentCheck | TriggerDescription$ When CARDNAME enters the battlefield, pay {E}{E} (two energy counters). If you can't, return CARDNAME to its owner's hand and you get {E}. SVar:PaymentCheck:DB$ Pump | UnlessCost$ Mandatory PayEnergy<2> | UnlessPayer$ You | UnlessResolveSubs$ WhenNotPaid | SubAbility$ DBReturnToHand SVar:DBReturnToHand:DB$ ChangeZone | Origin$ Battlefield | Destination$ Hand | Defined$ Self | SubAbility$ GetEnergy SVar:GetEnergy:DB$ PutCounter | Defined$ You | CounterType$ ENERGY | CounterNum$ 1 diff --git a/forge-gui/res/cardsfolder/g/greenwarden_of_murasa.txt b/forge-gui/res/cardsfolder/g/greenwarden_of_murasa.txt index c37072ba62d..68f0961563c 100644 --- a/forge-gui/res/cardsfolder/g/greenwarden_of_murasa.txt +++ b/forge-gui/res/cardsfolder/g/greenwarden_of_murasa.txt @@ -4,7 +4,6 @@ Types:Creature Elemental PT:5/4 T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may return target card from your graveyard to your hand. SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Card.YouCtrl -T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, return target card from your graveyard to your hand. -SVar:TrigExile:DB$ ChangeZone | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | SubAbility$ DBReturn -SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Card.YouCtrl +T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, return target card from your graveyard to your hand. +SVar:TrigExile:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Card.YouCtrl Oracle:When Greenwarden of Murasa enters the battlefield, you may return target card from your graveyard to your hand.\nWhen Greenwarden of Murasa dies, you may exile it. If you do, return target card from your graveyard to your hand. diff --git a/forge-gui/res/cardsfolder/i/iname_as_one.txt b/forge-gui/res/cardsfolder/i/iname_as_one.txt index 88ac2e52b1f..cc4dd17e20d 100644 --- a/forge-gui/res/cardsfolder/i/iname_as_one.txt +++ b/forge-gui/res/cardsfolder/i/iname_as_one.txt @@ -5,6 +5,5 @@ PT:8/8 T:Mode$ ChangesZone | ValidCard$ Card.wasCastFromYourHandByYou+Self | Destination$ Battlefield | Execute$ TrigSearch | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle. SVar:TrigSearch:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Spirit.YouCtrl | ChangeNum$ 1 | ShuffleNonMandatory$ True T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, return target Spirit permanent card from your graveyard to the battlefield. -SVar:TrigExile:DB$ ChangeZone | Origin$ Graveyard | Destination$ Exile | Defined$ TriggeredNewCardLKICopy | SubAbility$ DBReturn -SVar:DBReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | Hidden$ True | ChangeType$ Spirit.YouCtrl | ChangeNum$ 1 +SVar:TrigExile:AB$ ChangeZone | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Spirit.YouCtrl Oracle:When Iname as One enters the battlefield, if you cast it from your hand, you may search your library for a Spirit permanent card, put it onto the battlefield, then shuffle.\nWhen Iname as One dies, you may exile it. If you do, return target Spirit permanent card from your graveyard to the battlefield. diff --git a/forge-gui/res/cardsfolder/k/kinzu_of_the_bleak_coven.txt b/forge-gui/res/cardsfolder/k/kinzu_of_the_bleak_coven.txt index d512fda3610..00ced35171a 100644 --- a/forge-gui/res/cardsfolder/k/kinzu_of_the_bleak_coven.txt +++ b/forge-gui/res/cardsfolder/k/kinzu_of_the_bleak_coven.txt @@ -4,6 +4,6 @@ Types:Legendary Creature Phyrexian Vampire PT:5/4 K:Flying T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+Other+YouCtrl | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ Whenever another nontoken creature you control dies, you may pay 2 life and exile it. If you do, create a token that's a copy of that creature, except it's 1/1 and has toxic 1. (Players dealt combat damage by it also get a poison counter.) -SVar:TrigExile:AB$ CopyPermanent | Cost$ PayLife<2> ExileAnyGrave<1/Card.TriggeredCard/Exile nontoken creature that just died> | AddKeywords$ Toxic:1 | Defined$ TriggeredCardLKICopy | SetPower$ 1 | SetToughness$ 1 +SVar:TrigExile:AB$ CopyPermanent | Cost$ PayLife<2> ExileAnyGrave<1/Card.TriggeredNewCard> | AddKeywords$ Toxic:1 | Defined$ TriggeredCardLKICopy | SetPower$ 1 | SetToughness$ 1 DeckHas:Ability$Token Oracle:Flying\nWhenever another nontoken creature you control dies, you may pay 2 life and exile it. If you do, create a token that's a copy of that creature, except it's 1/1 and has toxic 1. (Players dealt combat damage by it also get a poison counter.) diff --git a/forge-gui/res/cardsfolder/k/kozileks_return.txt b/forge-gui/res/cardsfolder/k/kozileks_return.txt index 143e2660c38..c27edd5c8e5 100644 --- a/forge-gui/res/cardsfolder/k/kozileks_return.txt +++ b/forge-gui/res/cardsfolder/k/kozileks_return.txt @@ -4,5 +4,5 @@ Types:Instant K:Devoid A:SP$ DamageAll | Cost$ 2 R | NumDmg$ 2 | ValidCards$ Creature | ValidDescription$ each creature. | SpellDescription$ CARDNAME deals 2 damage to each creature. T:Mode$ SpellCast | ValidCard$ Creature.Eldrazi+cmcGE7+YouCtrl | TriggerZones$ Graveyard | Execute$ DBDamageAll | TriggerDescription$ Whenever you cast an Eldrazi creature spell with mana value 7 or greater, you may exile CARDNAME from your graveyard. If you do, CARDNAME deals 5 damage to each creature. -SVar:DBDamageAll:AB$ DamageAll | Cost$ ExileFromGrave<1/Card.Self> | ValidCards$ Creature | NumDmg$ 5 | ValidDescription$ each creature. +SVar:DBDamageAll:AB$ DamageAll | Cost$ ExileFromGrave<1/CARDNAME> | ValidCards$ Creature | NumDmg$ 5 | ValidDescription$ each creature. Oracle:Devoid (This card has no color.)\nKozilek's Return deals 2 damage to each creature.\nWhenever you cast an Eldrazi creature spell with mana value 7 or greater, you may exile Kozilek's Return from your graveyard. If you do, Kozilek's Return deals 5 damage to each creature. diff --git a/forge-gui/res/cardsfolder/r/rooting_kavu.txt b/forge-gui/res/cardsfolder/r/rooting_kavu.txt index c2fbfba6017..3819999ee8a 100644 --- a/forge-gui/res/cardsfolder/r/rooting_kavu.txt +++ b/forge-gui/res/cardsfolder/r/rooting_kavu.txt @@ -3,6 +3,5 @@ ManaCost:2 G G Types:Creature Kavu PT:4/3 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigExile | OptionalDecider$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you may exile it. If you do, shuffle all creature cards from your graveyard into your library. -SVar:TrigExile:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBShuffle -SVar:DBShuffle:DB$ ChangeZoneAll | ChangeType$ Creature.YouCtrl | Origin$ Graveyard | Destination$ Library | Shuffle$ True +SVar:TrigExile:AB$ ChangeZoneAll | Cost$ ExileAnyGrave<1/Card.TriggeredNewCard> | ChangeType$ Creature.YouCtrl | Origin$ Graveyard | Destination$ Library | Shuffle$ True Oracle:When Rooting Kavu dies, you may exile it. If you do, shuffle all creature cards from your graveyard into your library. diff --git a/forge-gui/res/cardsfolder/t/timothar_baron_of_bats.txt b/forge-gui/res/cardsfolder/t/timothar_baron_of_bats.txt index c77b7f40f12..8ebdd33e1ff 100644 --- a/forge-gui/res/cardsfolder/t/timothar_baron_of_bats.txt +++ b/forge-gui/res/cardsfolder/t/timothar_baron_of_bats.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Vampire Noble PT:4/4 K:Ward:Discard<1/Card> T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Vampire.Other+nonToken+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever another nontoken Vampire you control dies, you may pay {1} and exile it. If you do, create a 1/1 black Bat creature token with flying. It gains "When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped." -SVar:TrigToken:AB$ Token | Cost$ 1 ExileAnyGrave<1/Card.TriggeredNewCard/the Vampire card> | TokenRemembered$ ExiledCards | TokenScript$ b_1_1_bat_flying | ImprintTokens$ True | SubAbility$ DBAnimate +SVar:TrigToken:AB$ Token | Cost$ 1 ExileAnyGrave<1/Card.TriggeredNewCard> | TokenRemembered$ ExiledCards | TokenScript$ b_1_1_bat_flying | ImprintTokens$ True | SubAbility$ DBAnimate SVar:DBAnimate:DB$ Animate | Defined$ Imprinted | Duration$ Permanent | Triggers$ CDTrigger SVar:CDTrigger:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ When this creature deals combat damage to a player, sacrifice it and return the exiled card to the battlefield tapped. SVar:TrigSac:DB$ Sacrifice | SubAbility$ DBReturn diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index 165c10c5f92..69f0dcaf8b8 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -269,9 +269,9 @@ public class HumanCostDecision extends CostDecisionMakerBase { return inp.hasCancelled() ? null : PaymentDecision.card(inp.getSelected()); } - if (cost.from == ZoneType.Library) { return exileFromTop(cost, ability, player, c); } - if (fromTopGrave) { return exileFromTopGraveType(ability, c, list); } - if (cost.zoneRestriction != 0) { return exileFromMiscZone(cost, ability, c, list); } + if (cost.from == ZoneType.Library) { return exileFromTop(cost, c); } + if (fromTopGrave) { return exileFromTopGraveType(c, list); } + if (cost.zoneRestriction != 0) { return exileFromMiscZone(cost, c, list); } final FCollectionView players = game.getPlayers(); final List payableZone = new ArrayList<>(); @@ -363,22 +363,27 @@ public class HumanCostDecision extends CostDecisionMakerBase { return PaymentDecision.spellabilities(exiled); } - private PaymentDecision exileFromTop(final CostExile cost, final SpellAbility sa, final Player player, final int nNeeded) { + private PaymentDecision exileFromTop(final CostExile cost, final int nNeeded) { final CardCollectionView list = player.getCardsIn(ZoneType.Library, nNeeded); - - if (list.size() > nNeeded || !confirmAction(cost, Localizer.getInstance().getMessage("lblExileNCardFromYourTopLibraryConfirm"))) { + if (!confirmAction(cost, Localizer.getInstance().getMessage("lblExileNCardFromYourTopLibraryConfirm"))) { return null; } return PaymentDecision.card(list); } - private PaymentDecision exileFromMiscZone(final CostExile cost, final SpellAbility sa, final int nNeeded, final CardCollection typeList) { - if (typeList.size() < nNeeded) { return null; } + private PaymentDecision exileFromMiscZone(final CostExile cost, final int nNeeded, final CardCollection typeList) { + // when it's always a single triggered card getting exiled don't act like it might be different by offering the zone for choice + if (cost.zoneRestriction == -1 && ability.isTrigger() && nNeeded == 1 && typeList.size() == 1) { + if (confirmAction(cost, Localizer.getInstance().getMessage("lblExileConfirm", CardTranslation.getTranslatedName(typeList.getFirst().getName())))) { + return PaymentDecision.card(typeList.getFirst()); + } + return null; + } final List origin = Lists.newArrayList(cost.from); final CardCollection exiled = new CardCollection(); - final List chosen = controller.chooseCardsForZoneChange(ZoneType.Exile, origin, sa, typeList, mandatory ? nNeeded : 0, + final List chosen = controller.chooseCardsForZoneChange(ZoneType.Exile, origin, ability, typeList, mandatory ? nNeeded : 0, nNeeded, null, cost.toString(), null); exiled.addAll(chosen); @@ -388,9 +393,7 @@ public class HumanCostDecision extends CostDecisionMakerBase { return PaymentDecision.card(exiled); } - private PaymentDecision exileFromTopGraveType(final SpellAbility sa, final int nNeeded, final CardCollection typeList) { - if (typeList.size() < nNeeded) { return null; } - + private PaymentDecision exileFromTopGraveType(final int nNeeded, final CardCollection typeList) { Collections.reverse(typeList); return PaymentDecision.card(Iterables.limit(typeList, nNeeded)); } diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index 5228ade69dd..8adf2994cb7 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -5,7 +5,6 @@ import java.util.List; import forge.ImageKeys; import forge.game.cost.*; -import forge.game.spellability.SpellAbilityStackInstance; import com.google.common.collect.Iterables; @@ -262,6 +261,7 @@ public class HumanPlay { || part instanceof CostRollDice || part instanceof CostDamage || part instanceof CostEnlist + || part instanceof CostExileFromStack || part instanceof CostPutCounter || part instanceof CostRemoveCounter || part instanceof CostRemoveAnyCounter @@ -337,53 +337,6 @@ public class HumanPlay { } } } - else if (part instanceof CostExileFromStack) { - CostExileFromStack costExile = (CostExileFromStack) part; - - final List saList = new ArrayList<>(); - final List descList = new ArrayList<>(); - - for (final SpellAbilityStackInstance si : p.getGame().getStack()) { - final Card stC = si.getSourceCard(); - final SpellAbility stSA = si.getSpellAbility(true).getRootAbility(); - if (stC.isValid(part.getType().split(";"), p, source, sourceAbility) && stSA.isSpell()) { - saList.add(stSA); - if (stC.isCopiedSpell()) { - descList.add(stSA.getStackDescription() + " (Copied Spell)"); - } else { - descList.add(stSA.getStackDescription()); - } - } - } - - List payList = new ArrayList<>(); - if (part.getType().equals("All")) { - payList.addAll(saList); - } else { - final int c = part.getAbilityAmount(sourceAbility); - - if (saList.size() < c) { - return false; - } - - for (int i = 0; i < c; i++) { - //Have to use the stack descriptions here because some copied spells have no description otherwise - final String o = controller.getGui().oneOrNone(Localizer.getInstance().getMessage("lblExileFromStack"), descList); - - if (o == null) { - return false; - } - final SpellAbility toExile = saList.get(descList.indexOf(o)); - - saList.remove(toExile); - descList.remove(o); - - payList.add(toExile); - } - } - - costExile.payAsDecided(p, PaymentDecision.spellabilities(payList), sourceAbility, hcd.isEffect()); - } else if (part instanceof CostPutCardToLib) { int amount = Integer.parseInt(part.getAmount()); final ZoneType from = ((CostPutCardToLib) part).getFrom();