Merge pull request #3499 from tool4ever/playFix

PlayEffect: Fix casting with unpayable cost if no alternative provided
This commit is contained in:
Anthony Calosa
2023-07-21 12:28:38 +08:00
committed by GitHub
11 changed files with 49 additions and 17 deletions

View File

@@ -370,15 +370,23 @@ public class PlayEffect extends SpellAbilityEffect {
if ((sa.hasParam("WithoutManaCost") || sa.hasParam("PlayCost")) && tgtSA.costHasManaX() && !tgtSA.getPayCosts().getCostMana().canXbe0()) { if ((sa.hasParam("WithoutManaCost") || sa.hasParam("PlayCost")) && tgtSA.costHasManaX() && !tgtSA.getPayCosts().getCostMana().canXbe0()) {
continue; continue;
} }
boolean unpayableCost = tgtSA.getHostCard().getManaCost().isNoCost();
if (sa.hasParam("WithoutManaCost")) { if (sa.hasParam("WithoutManaCost")) {
tgtSA = tgtSA.copyWithNoManaCost(); tgtSA = tgtSA.copyWithNoManaCost();
} else if (sa.hasParam("PlayCost")) { } else if (sa.hasParam("PlayCost")) {
Cost abCost; Cost abCost;
String cost = sa.getParam("PlayCost"); String cost = sa.getParam("PlayCost");
if (cost.equals("ManaCost")) { if (cost.equals("ManaCost")) {
if (unpayableCost) {
continue;
}
abCost = new Cost(source.getManaCost(), false); abCost = new Cost(source.getManaCost(), false);
} else { } else {
if (cost.contains("ConvertedManaCost")) { if (cost.contains("ConvertedManaCost")) {
if (unpayableCost) {
continue;
}
final String costcmc = Integer.toString(tgtCard.getCMC()); final String costcmc = Integer.toString(tgtCard.getCMC());
cost = cost.replace("ConvertedManaCost", costcmc); cost = cost.replace("ConvertedManaCost", costcmc);
} }
@@ -386,6 +394,8 @@ public class PlayEffect extends SpellAbilityEffect {
} }
tgtSA = tgtSA.copyWithManaCostReplaced(tgtSA.getActivatingPlayer(), abCost); tgtSA = tgtSA.copyWithManaCostReplaced(tgtSA.getActivatingPlayer(), abCost);
} else if (unpayableCost) {
continue;
} }
if (!optional) { if (!optional) {

View File

@@ -90,7 +90,17 @@ public class StaticAbilityCantAttackBlock {
} }
} }
final Player defender = target instanceof Card ? ((Card) target).getController() : (Player) target; final Player defender;
if (target instanceof Player) {
defender = (Player) target;
} else {
Card c = (Card) target;
if (c.isBattle()) {
defender = c.getProtectingPlayer();
} else {
defender = c.getController();
}
}
if (stAb.hasParam("UnlessDefenderControls")) { if (stAb.hasParam("UnlessDefenderControls")) {
String type = stAb.getParam("UnlessDefenderControls"); String type = stAb.getParam("UnlessDefenderControls");
@@ -108,10 +118,21 @@ public class StaticAbilityCantAttackBlock {
return false; return false;
} }
} }
if (stAb.hasParam("DefenderNotNearestToYouInChosenDirection") && (hostCard.getChosenDirection() == null if (stAb.hasParam("DefenderNotNearestToYouInChosenDirection")) {
|| defender.equals(game.getNextPlayerAfter(card.getController(), hostCard.getChosenDirection())))) { if (hostCard.getChosenDirection() == null) {
return false; return false;
} }
if (target instanceof Card && ((Card) target).isBattle()) {
return false;
}
Player next = card.getController();
while (!next.isOpponentOf(card.getController())) {
next = game.getNextPlayerAfter(next, hostCard.getChosenDirection());
}
if (defender.equals(next)) {
return false;
}
}
if (stAb.hasParam("UnlessDefender")) { if (stAb.hasParam("UnlessDefender")) {
final String type = stAb.getParam("UnlessDefender"); final String type = stAb.getParam("UnlessDefender");
if (defender.hasProperty(type, hostCard.getController(), hostCard, stAb)) { if (defender.hasProperty(type, hostCard.getController(), hostCard, stAb)) {

View File

@@ -2,9 +2,9 @@ Name:Ascendant Spirit
ManaCost:U ManaCost:U
Types:Snow Creature Spirit Types:Snow Creature Spirit
PT:1/1 PT:1/1
A:AB$ Animate | Cost$ S S | Types$ Spirit,Warrior | Duration$ Permanent | Power$ 2 | Toughness$ 3 | StackDescription$ SpellDescription | SpellDescription$ CARDNAME becomes a Spirit Warrior with base power and toughness 2/3. A:AB$ Animate | Cost$ S S | Types$ Spirit,Warrior | RemoveCreatureTypes$ True | Duration$ Permanent | Power$ 2 | Toughness$ 3 | StackDescription$ SpellDescription | SpellDescription$ CARDNAME becomes a Spirit Warrior with base power and toughness 2/3.
A:AB$ PutCounter | Cost$ S S S | ConditionPresent$ Card.Self+Warrior | CounterType$ Flying | CounterNum$ 1 | SubAbility$ TrigAnimate | StackDescription$ SpellDescription | SpellDescription$ If CARDNAME is a Warrior, put a flying counter on it and it becomes an Angel Spirit Warrior with base power and toughness 4/4. A:AB$ PutCounter | Cost$ S S S | ConditionPresent$ Card.Self+Warrior | CounterType$ Flying | CounterNum$ 1 | SubAbility$ TrigAnimate | StackDescription$ SpellDescription | SpellDescription$ If CARDNAME is a Warrior, put a flying counter on it and it becomes an Angel Spirit Warrior with base power and toughness 4/4.
SVar:TrigAnimate:DB$ Animate | ConditionPresent$ Card.Self+Warrior | Types$ Angel,Spirit,Warrior | Duration$ Permanent | Power$ 4 | Toughness$ 4 SVar:TrigAnimate:DB$ Animate | ConditionPresent$ Card.Self+Warrior | Types$ Angel,Spirit,Warrior | RemoveCreatureTypes$ True | Duration$ Permanent | Power$ 4 | Toughness$ 4
A:AB$ PutCounter | Cost$ S S S S | ConditionPresent$ Card.Self+Angel | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ AddTrigger | StackDescription$ SpellDescription | SpellDescription$ If CARDNAME is an Angel, put two +1/+1 counters on it and it gains "Whenever this creature deals combat damage to a player, draw a card." A:AB$ PutCounter | Cost$ S S S S | ConditionPresent$ Card.Self+Angel | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ AddTrigger | StackDescription$ SpellDescription | SpellDescription$ If CARDNAME is an Angel, put two +1/+1 counters on it and it gains "Whenever this creature deals combat damage to a player, draw a card."
SVar:AddTrigger:DB$ Animate | Defined$ Self | ConditionPresent$ Card.Self+Angel | Triggers$ DamageDraw | Duration$ Permanent SVar:AddTrigger:DB$ Animate | Defined$ Self | ConditionPresent$ Card.Self+Angel | Triggers$ DamageDraw | Duration$ Permanent
SVar:DamageDraw:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, draw a card. SVar:DamageDraw:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | TriggerZones$ Battlefield | Execute$ TrigDraw | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, draw a card.

View File

@@ -1,5 +1,5 @@
Name:Bee Sting Name:Bee Sting
ManaCost:3 G ManaCost:3 G
Types:Sorcery Types:Sorcery
A:SP$ DealDamage | Cost$ 3 G | ValidTgts$ Any | NumDmg$ 2 | SpellDescription$ Bee Sting deals 2 damage to any target. A:SP$ DealDamage | Cost$ 3 G | ValidTgts$ Any | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target.
Oracle:Bee Sting deals 2 damage to any target. Oracle:Bee Sting deals 2 damage to any target.

View File

@@ -1,7 +1,7 @@
Name:Comet Storm Name:Comet Storm
ManaCost:X R R ManaCost:X R R
Types:Instant Types:Instant
A:SP$ DealDamage | Cost$ X R R | Announce$ Multikicker,X | ValidTgts$ Any | NumDmg$ X | TargetMin$ TargetsNum | TargetMax$ TargetsNum | SpellDescription$ CARDNAME deals X damage to each targets. A:SP$ DealDamage | Cost$ X R R | Announce$ Multikicker | ValidTgts$ Any | NumDmg$ X | TargetMin$ TargetsNum | TargetMax$ TargetsNum | SpellDescription$ CARDNAME deals X damage to each targets.
K:Multikicker:1 K:Multikicker:1
SVar:TargetsNum:Count$TimesKicked/Plus.1 SVar:TargetsNum:Count$TimesKicked/Plus.1
SVar:X:Count$xPaid SVar:X:Count$xPaid

View File

@@ -2,7 +2,7 @@ Name:Figure of Destiny
ManaCost:RW ManaCost:RW
Types:Creature Kithkin Types:Creature Kithkin
PT:1/1 PT:1/1
A:AB$ Animate | Cost$ RW | Types$ Kithkin,Spirit | Duration$ Permanent | Power$ 2 | Toughness$ 2 | SpellDescription$ CARDNAME becomes a Kithkin Spirit with base power and toughness 2/2. A:AB$ Animate | Cost$ RW | Types$ Kithkin,Spirit | RemoveCreatureTypes$ True | Duration$ Permanent | Power$ 2 | Toughness$ 2 | SpellDescription$ CARDNAME becomes a Kithkin Spirit with base power and toughness 2/2.
A:AB$ Animate | Cost$ RW RW RW | ConditionPresent$ Card.Self+Spirit | Types$ Kithkin,Spirit,Warrior | Duration$ Permanent | Power$ 4 | Toughness$ 4 | SpellDescription$ If CARDNAME is a Spirit, it becomes a Kithkin Spirit Warrior with base power and toughness 4/4. A:AB$ Animate | Cost$ RW RW RW | ConditionPresent$ Card.Self+Spirit | Types$ Kithkin,Spirit,Warrior | RemoveCreatureTypes$ True | Duration$ Permanent | Power$ 4 | Toughness$ 4 | SpellDescription$ If CARDNAME is a Spirit, it becomes a Kithkin Spirit Warrior with base power and toughness 4/4.
A:AB$ Animate | Cost$ RW RW RW RW RW RW | ConditionPresent$ Card.Self+Warrior | Types$ Kithkin,Spirit,Warrior,Avatar | Duration$ Permanent | Power$ 8 | Toughness$ 8 | Keywords$ Flying & First Strike | SpellDescription$ If CARDNAME is a Warrior, it becomes a Kithkin Spirit Warrior Avatar with base power and toughness 8/8, flying, and first strike. A:AB$ Animate | Cost$ RW RW RW RW RW RW | ConditionPresent$ Card.Self+Warrior | Types$ Kithkin,Spirit,Warrior,Avatar | RemoveCreatureTypes$ True | Duration$ Permanent | Power$ 8 | Toughness$ 8 | Keywords$ Flying & First Strike | SpellDescription$ If CARDNAME is a Warrior, it becomes a Kithkin Spirit Warrior Avatar with base power and toughness 8/8, flying, and first strike.
Oracle:{R/W}: Figure of Destiny becomes a Kithkin Spirit with base power and toughness 2/2.\n{R/W}{R/W}{R/W}: If Figure of Destiny is a Spirit, it becomes a Kithkin Spirit Warrior with base power and toughness 4/4.\n{R/W}{R/W}{R/W}{R/W}{R/W}{R/W}: If Figure of Destiny is a Warrior, it becomes a Kithkin Spirit Warrior Avatar with base power and toughness 8/8, flying, and first strike. Oracle:{R/W}: Figure of Destiny becomes a Kithkin Spirit with base power and toughness 2/2.\n{R/W}{R/W}{R/W}: If Figure of Destiny is a Spirit, it becomes a Kithkin Spirit Warrior with base power and toughness 4/4.\n{R/W}{R/W}{R/W}{R/W}{R/W}{R/W}: If Figure of Destiny is a Warrior, it becomes a Kithkin Spirit Warrior Avatar with base power and toughness 8/8, flying, and first strike.

View File

@@ -2,6 +2,6 @@ Name:Kazuul, Tyrant of the Cliffs
ManaCost:3 R R ManaCost:3 R R
Types:Legendary Creature Ogre Warrior Types:Legendary Creature Ogre Warrior
PT:5/4 PT:5/4
T:Mode$ Attacks | ValidCard$ Creature.OppCtrl | Attacked$ You,Planeswalker.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever a creature an opponent controls attacks, if you're the defending player, create a 3/3 red Ogre creature token unless that creature's controller pays {3}. T:Mode$ Attacks | ValidCard$ Creature.OppCtrl | Attacked$ You,Planeswalker.YouCtrl,Battle.ProtectedBy You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever a creature an opponent controls attacks, if you're the defending player, create a 3/3 red Ogre creature token unless that creature's controller pays {3}.
SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenAmount$ 1 | TokenScript$ r_3_3_ogre | UnlessCost$ 3 | UnlessPayer$ TriggeredAttackerController SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenAmount$ 1 | TokenScript$ r_3_3_ogre | UnlessCost$ 3 | UnlessPayer$ TriggeredAttackerController
Oracle:Whenever a creature an opponent controls attacks, if you're the defending player, create a 3/3 red Ogre creature token unless that creature's controller pays {3}. Oracle:Whenever a creature an opponent controls attacks, if you're the defending player, create a 3/3 red Ogre creature token unless that creature's controller pays {3}.

View File

@@ -6,7 +6,8 @@ A:SP$ Attach | ValidTgts$ Creature | AILogic$ Pump
T:Mode$ ChangesZone | ValidCard$ Card.EnchantedBy | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ When enchanted creature dies, you may put a creature card you own with lesser mana value from your hand or from the command zone onto the battlefield. If you do, return CARDNAME to the battlefield attached to that creature at the beginning of the next end step. T:Mode$ ChangesZone | ValidCard$ Card.EnchantedBy | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ When enchanted creature dies, you may put a creature card you own with lesser mana value from your hand or from the command zone onto the battlefield. If you do, return CARDNAME to the battlefield attached to that creature at the beginning of the next end step.
SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Hand,Command | Destination$ Battlefield | ChangeType$ Creature.cmcLTX+YouOwn | RememberChanged$ True | SubAbility$ DBDelayedTrigger SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Hand,Command | Destination$ Battlefield | ChangeType$ Creature.cmcLTX+YouOwn | RememberChanged$ True | SubAbility$ DBDelayedTrigger
SVar:X:TriggeredCard$CardManaCost SVar:X:TriggeredCard$CardManaCost
SVar:DBDelayedTrigger:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigReturn | RememberObjects$ Remembered | TriggerDescription$ If you do, return CARDNAME to the battlefield attached to that creature at the beginning of the next end step. SVar:DBDelayedTrigger:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigReturn | RememberObjects$ Remembered | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup | TriggerDescription$ If you do, return CARDNAME to the battlefield attached to that creature at the beginning of the next end step.
SVar:TrigReturn:DB$ ChangeZone | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield | AttachedTo$ DelayTriggerRememberedLKI SVar:TrigReturn:DB$ ChangeZone | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield | AttachedTo$ DelayTriggerRememberedLKI
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
DeckHas:Ability$Graveyard DeckHas:Ability$Graveyard
Oracle:Enchant creature\nWhen enchanted creature dies, you may put a creature card you own with lesser mana value from your hand or from the command zone onto the battlefield. If you do, return Next of Kin to the battlefield attached to that creature at the beginning of the next end step. Oracle:Enchant creature\nWhen enchanted creature dies, you may put a creature card you own with lesser mana value from your hand or from the command zone onto the battlefield. If you do, return Next of Kin to the battlefield attached to that creature at the beginning of the next end step.

View File

@@ -4,7 +4,7 @@ Types:Legendary Creature Human Wizard
PT:3/3 PT:3/3
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ This spell costs {1} less to cast for each different mana value among cards in your graveyard. S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ This spell costs {1} less to cast for each different mana value among cards in your graveyard.
SVar:X:Count$ValidGraveyard Card.YouOwn$DifferentCMC SVar:X:Count$ValidGraveyard Card.YouOwn$DifferentCMC
T:Mode$ Discarded | ValidPlayer$ You | ValidCard$ Card.nonLand | TriggerZones$ Battlefield | Execute$ TrigPlay | TriggerDescription$ Whenever you discard a card, you may cast it from your graveyard. T:Mode$ Discarded | ValidPlayer$ You | ValidCard$ Card.nonLand | TriggerZones$ Battlefield | Execute$ TrigPlay | TriggerDescription$ Whenever you discard a nonland card, you may cast it from your graveyard.
SVar:TrigPlay:DB$ Play | Defined$ TriggeredCard | ValidSA$ Spell | Controller$ You | Optional$ True | Amount$ All SVar:TrigPlay:DB$ Play | Defined$ TriggeredCard | ValidSA$ Spell | Controller$ You | Optional$ True | Amount$ All
DeckHas:Ability$Graveyard DeckHas:Ability$Graveyard
DeckNeeds:Ability$Discard DeckNeeds:Ability$Discard

View File

@@ -2,7 +2,7 @@ Name:Strength of the Tajuru
ManaCost:X G G ManaCost:X G G
Types:Instant Types:Instant
K:Multikicker:1 K:Multikicker:1
A:SP$ PutCounter | CounterType$ P1P1 | CounterNum$ X | Cost$ X G G | Announce$ Multikicker,X | ValidTgts$ Creature | TgtPrompt$ Select target creature | TargetMin$ TargetsNum | TargetMax$ TargetsNum | SpellDescription$ Choose target creature, then choose another target creature for each time this spell was kicked. Put X +1/+1 counters on each of them. A:SP$ PutCounter | CounterType$ P1P1 | CounterNum$ X | Cost$ X G G | Announce$ Multikicker | ValidTgts$ Creature | TgtPrompt$ Select target creature | TargetMin$ TargetsNum | TargetMax$ TargetsNum | SpellDescription$ Choose target creature, then choose another target creature for each time this spell was kicked. Put X +1/+1 counters on each of them.
SVar:X:Count$xPaid SVar:X:Count$xPaid
SVar:TargetsNum:Count$TimesKicked/Plus.1 SVar:TargetsNum:Count$TimesKicked/Plus.1
DeckHas:Ability$Counters DeckHas:Ability$Counters

View File

@@ -2,7 +2,7 @@ Name:Warden of the First Tree
ManaCost:G ManaCost:G
Types:Creature Human Types:Creature Human
PT:1/1 PT:1/1
A:AB$ Animate | Cost$ 1 WB | Types$ Human,Warrior | Duration$ Permanent | Power$ 3 | Toughness$ 3 | SpellDescription$ CARDNAME becomes a Human Warrior with base power and toughness 3/3. A:AB$ Animate | Cost$ 1 WB | Types$ Human,Warrior | RemoveCreatureTypes$ True | Duration$ Permanent | Power$ 3 | Toughness$ 3 | SpellDescription$ CARDNAME becomes a Human Warrior with base power and toughness 3/3.
A:AB$ Animate | Cost$ 2 WB WB | Defined$ Self | ConditionPresent$ Card.Self+Warrior | Types$ Human,Warrior,Spirit | Duration$ Permanent | Keywords$ Trample & Lifelink | SpellDescription$ If CARDNAME is a Warrior, it becomes a Human Spirit Warrior with trample and lifelink. A:AB$ Animate | Cost$ 2 WB WB | Defined$ Self | ConditionPresent$ Card.Self+Warrior | Types$ Human,Warrior,Spirit | RemoveCreatureTypes$ True | Duration$ Permanent | Keywords$ Trample & Lifelink | SpellDescription$ If CARDNAME is a Warrior, it becomes a Human Spirit Warrior with trample and lifelink.
A:AB$ PutCounter | Cost$ 3 WB WB WB | ConditionPresent$ Card.Self+Spirit | CounterType$ P1P1 | CounterNum$ 5 | SpellDescription$ If CARDNAME is a Spirit, put five +1/+1 counters on it. A:AB$ PutCounter | Cost$ 3 WB WB WB | ConditionPresent$ Card.Self+Spirit | CounterType$ P1P1 | CounterNum$ 5 | SpellDescription$ If CARDNAME is a Spirit, put five +1/+1 counters on it.
Oracle:{1}{W/B}: Warden of the First Tree becomes a Human Warrior with base power and toughness 3/3.\n{2}{W/B}{W/B}: If Warden of the First Tree is a Warrior, it becomes a Human Spirit Warrior with trample and lifelink.\n{3}{W/B}{W/B}{W/B}: If Warden of the First Tree is a Spirit, put five +1/+1 counters on it. Oracle:{1}{W/B}: Warden of the First Tree becomes a Human Warrior with base power and toughness 3/3.\n{2}{W/B}{W/B}: If Warden of the First Tree is a Warrior, it becomes a Human Spirit Warrior with trample and lifelink.\n{3}{W/B}{W/B}{W/B}: If Warden of the First Tree is a Spirit, put five +1/+1 counters on it.