diff --git a/forge-ai/src/main/java/forge/ai/ability/PlayAi.java b/forge-ai/src/main/java/forge/ai/ability/PlayAi.java index 7168f4c911e..443fb1eacfa 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PlayAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PlayAi.java @@ -1,6 +1,9 @@ package forge.ai.ability; import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + import forge.ai.*; import forge.card.CardStateName; import forge.card.CardTypeView; @@ -14,11 +17,13 @@ import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; import forge.game.spellability.Spell; import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityPredicates; import forge.game.spellability.SpellPermanent; import forge.game.spellability.TargetRestrictions; import forge.game.zone.ZoneType; import forge.util.MyRandom; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -55,6 +60,21 @@ public class PlayAi extends SpellAbilityAi { } } + if (sa.hasParam("ValidSA")) { + final String valid[] = {sa.getParam("ValidSA")}; + final Iterator itr = cards.iterator(); + while (itr.hasNext()) { + final Card c = itr.next(); + final List validSA = Lists.newArrayList(Iterables.filter(AbilityUtils.getBasicSpellsFromPlayEffect(c, ai), SpellAbilityPredicates.isValid(valid, ai , c, sa))); + if (validSA.size() == 0) { + itr.remove(); + } + } + if (cards.isEmpty()) { + return false; + } + } + if (game.getRules().hasAppliedVariant(GameType.MoJhoSto) && source.getName().equals("Jhoira of the Ghitu Avatar")) { // Additional logic for MoJhoSto: // Do not activate Jhoira too early, usually there are few good targets diff --git a/forge-game/src/main/java/forge/game/ForgeScript.java b/forge-game/src/main/java/forge/game/ForgeScript.java index bf35e289bad..0565c8981e5 100644 --- a/forge-game/src/main/java/forge/game/ForgeScript.java +++ b/forge-game/src/main/java/forge/game/ForgeScript.java @@ -177,6 +177,12 @@ public class ForgeScript { return sa.getActivatingPlayer().equals(sourceController); } else if (property.equals("OppCtrl")) { return sa.getActivatingPlayer().isOpponentOf(sourceController); + } else if (property.startsWith("cmc")) { + int y = sa.getPayCosts().getTotalMana().getCMC(); + int x = AbilityUtils.calculateAmount(spellAbility.getHostCard(), property.substring(5), spellAbility); + if (!Expressions.compare(y, property, x)) { + return false; + } } else if (sa.getHostCard() != null) { return sa.getHostCard().hasProperty(property, sourceController, source, spellAbility); } 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 6ea3b8dfbc6..68d68535008 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -3,7 +3,10 @@ package forge.game.ability; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; + +import forge.card.CardStateName; import forge.card.CardType; import forge.card.ColorSet; import forge.card.MagicColor; @@ -1814,7 +1817,11 @@ public class AbilityUtils { public static final List getBasicSpellsFromPlayEffect(final Card tgtCard, final Player controller) { List sas = new ArrayList<>(); - for (SpellAbility s : tgtCard.getBasicSpells()) { + List list = Lists.newArrayList(tgtCard.getBasicSpells()); + if (tgtCard.isModal()) { + list.addAll(Lists.newArrayList(tgtCard.getBasicSpells(tgtCard.getState(CardStateName.Modal)))); + } + for (SpellAbility s : list) { final Spell newSA = (Spell) s.copy(); newSA.setActivatingPlayer(controller); SpellAbilityRestriction res = new SpellAbilityRestriction(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java index 1bceee39de1..17490640e78 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java @@ -1,6 +1,7 @@ package forge.game.ability.effects; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import org.apache.commons.lang3.StringUtils; @@ -28,6 +29,7 @@ import forge.game.replacement.ReplacementHandler; import forge.game.replacement.ReplacementLayer; import forge.game.spellability.AlternativeCost; import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellAbilityPredicates; import forge.game.trigger.TriggerType; import forge.game.zone.Zone; import forge.game.zone.ZoneType; @@ -82,7 +84,7 @@ public class PlayEffect extends SpellAbilityEffect { tgtCards = new CardCollection( AbilityUtils.filterListByType(game.getCardsIn(zones), sa.getParam("Valid"), sa) ); - if ( sa.hasParam("ShowCards") ) { + if (sa.hasParam("ShowCards")) { showCards = new CardCollection(AbilityUtils.filterListByType(game.getCardsIn(zones), sa.getParam("ShowCards"), sa)); } } @@ -102,7 +104,7 @@ public class PlayEffect extends SpellAbilityEffect { final CardCollection choice = new CardCollection(); final String num = sa.hasParam("RandomNum") ? sa.getParam("RandomNum") : "1"; int ncopied = AbilityUtils.calculateAmount(source, num, sa); - while(ncopied > 0) { + while (ncopied > 0) { final PaperCard cp = Aggregates.random(copysource); final Card possibleCard = Card.fromPaperCard(cp, sa.getActivatingPlayer()); // Need to temporarily set the Owner so the Game is set @@ -145,6 +147,21 @@ public class PlayEffect extends SpellAbilityEffect { return; } + if (sa.hasParam("ValidSA")) { + final String valid[] = {sa.getParam("ValidSA")}; + final Iterator itr = tgtCards.iterator(); + while (itr.hasNext()) { + final Card c = itr.next(); + final List validSA = Lists.newArrayList(Iterables.filter(AbilityUtils.getBasicSpellsFromPlayEffect(c, controller), SpellAbilityPredicates.isValid(valid, controller , c, sa))); + if (validSA.size() == 0) { + itr.remove(); + } + } + if (tgtCards.isEmpty()) { + return; + } + } + if (sa.hasParam("Amount") && sa.getParam("Amount").equals("All")) { amount = tgtCards.size(); } @@ -214,7 +231,12 @@ public class PlayEffect extends SpellAbilityEffect { } // get basic spells (no flashback, etc.) - final List sas = AbilityUtils.getBasicSpellsFromPlayEffect(tgtCard, controller); + List sas = AbilityUtils.getBasicSpellsFromPlayEffect(tgtCard, controller); + if (sa.hasParam("ValidSA")) { + final String valid[] = {sa.getParam("ValidSA")}; + sas = Lists.newArrayList(Iterables.filter(sas, SpellAbilityPredicates.isValid(valid, controller , source, sa))); + } + if (sas.isEmpty()) { continue; } @@ -233,6 +255,10 @@ public class PlayEffect extends SpellAbilityEffect { // For Illusionary Mask effect tgtSA = CardFactoryUtil.abilityMorphDown(tgtCard); } + // in case player canceled from choice dialog + if (tgtSA == null) { + continue; + } final boolean noManaCost = sa.hasParam("WithoutManaCost"); if (noManaCost) { diff --git a/forge-gui/res/cardsfolder/b/barals_expertise.txt b/forge-gui/res/cardsfolder/b/barals_expertise.txt index 558dc4e6ea5..5edfaaf6aba 100644 --- a/forge-gui/res/cardsfolder/b/barals_expertise.txt +++ b/forge-gui/res/cardsfolder/b/barals_expertise.txt @@ -1,7 +1,7 @@ Name:Baral's Expertise ManaCost:3 U U Types:Sorcery -A:SP$ ChangeZone | Cost$ 3 U U | TargetMin$ 0 | TargetMax$ 3 | ValidTgts$ Artifact,Creature | TgtPrompt$ Select target artifact or creature | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBPlay | SpellDescription$ Return up to three target artifacts and/or creatures to their owners' hands. You may cast a card with converted mana cost 4 or less from your hand without paying its mana cost. -SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn+cmcLE4 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True +A:SP$ ChangeZone | Cost$ 3 U U | TargetMin$ 0 | TargetMax$ 3 | ValidTgts$ Artifact,Creature | TgtPrompt$ Select target artifact or creature | Origin$ Battlefield | Destination$ Hand | SubAbility$ DBPlay | SpellDescription$ Return up to three target artifacts and/or creatures to their owners' hands. You may cast a spell with converted mana cost 4 or less from your hand without paying its mana cost. +SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn | ValidSA$ Spell.cmcLE4 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/barals_expertise.jpg -Oracle:Return up to three target artifacts and/or creatures to their owners' hands.\nYou may cast a card with converted mana cost 4 or less from your hand without paying its mana cost. \ No newline at end of file +Oracle:Return up to three target artifacts and/or creatures to their owners' hands.\nYou may cast a spell with converted mana cost 4 or less from your hand without paying its mana cost. \ No newline at end of file diff --git a/forge-gui/res/cardsfolder/c/coveted_prize.txt b/forge-gui/res/cardsfolder/c/coveted_prize.txt index f4c05ff38ea..2ce756671cf 100755 --- a/forge-gui/res/cardsfolder/c/coveted_prize.txt +++ b/forge-gui/res/cardsfolder/c/coveted_prize.txt @@ -4,7 +4,7 @@ Types:Sorcery S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | References$ X | Description$ This spell costs {1} less to cast for each creature in your party. SVar:X:Count$Party A:SP$ ChangeZone | Cost$ 4 B | Origin$ Library | Destination$ Hand | ChangeType$ Card | ChangeNum$ 1 | Mandatory$ True | SubAbility$ DBPlay | StackDescription$ SpellDescription | SpellDescription$ Search your library for a card, put it into your hand, then shuffle your library. If you have a full party, you may cast a spell with converted mana cost 4 or less from your hand without paying its mana cost. -SVar:DBPlay:DB$ Play | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ4 | References$ X | Optional$ True | Valid$ Card.nonLand+YouOwn+cmcLE4 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | StackDescription$ None +SVar:DBPlay:DB$ Play | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ4 | References$ X | Optional$ True | Valid$ Card.nonLand+YouOwn | ValidSA$ Spell.cmcLE4 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | StackDescription$ None DeckHas:Ability$Party DeckHints:Type$Cleric|Rogue|Warrior|Wizard Oracle:This spell costs {1} less to cast for each creature in your party. (Your party consists of up to one each of Cleric, Rogue, Warrior, and Wizard.)\nSearch your library for a card, put it into your hand, then shuffle your library. If you have a full party, you may cast a spell with converted mana cost 4 or less from your hand without paying its mana cost. diff --git a/forge-gui/res/cardsfolder/e/electrodominance.txt b/forge-gui/res/cardsfolder/e/electrodominance.txt index 9d272b3eea8..2da42bca1b5 100644 --- a/forge-gui/res/cardsfolder/e/electrodominance.txt +++ b/forge-gui/res/cardsfolder/e/electrodominance.txt @@ -1,7 +1,7 @@ Name:Electrodominance ManaCost:X R R Types:Instant -A:SP$ DealDamage | Cost$ X R R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | SubAbility$ DBPlay | SpellDescription$ CARDNAME deals X damage to any target. You may cast a card with converted mana cost X or less from your hand without paying its mana cost. -SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn+cmcLEX | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True | References$ X +A:SP$ DealDamage | Cost$ X R R | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ X | References$ X | SubAbility$ DBPlay | SpellDescription$ CARDNAME deals X damage to any target. You may cast a spell with converted mana cost X or less from your hand without paying its mana cost. +SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn | ValidSA$ Spell.cmcLEX | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True | References$ X SVar:X:Count$xPaid -Oracle:Electrodominance deals X damage to any target. You may cast a card with converted mana cost X or less from your hand without paying its mana cost. +Oracle:Electrodominance deals X damage to any target. You may cast a spell with converted mana cost X or less from your hand without paying its mana cost. diff --git a/forge-gui/res/cardsfolder/k/kari_zevs_expertise.txt b/forge-gui/res/cardsfolder/k/kari_zevs_expertise.txt index 9c8ad5fa108..e267485ae52 100644 --- a/forge-gui/res/cardsfolder/k/kari_zevs_expertise.txt +++ b/forge-gui/res/cardsfolder/k/kari_zevs_expertise.txt @@ -1,7 +1,7 @@ Name:Kari Zev's Expertise ManaCost:1 R R Types:Sorcery -A:SP$ GainControl | Cost$ 1 R R | ValidTgts$ Creature,Vehicle | TgtPrompt$ Select target creature or vehicle | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBCast | SpellDescription$ Gain control of target creature or Vehicle until end of turn. Untap it. It gains haste until end of turn. You may cast a card with converted mana cost 2 or less from your hand without paying its mana cost. -SVar:DBCast:DB$ Play | ValidZone$ Hand | Valid$ Card.YouOwn+nonLand+cmcLE2 | Controller$ You | WithoutManaCost$ True | Optional$ True | Amount$ 1 +A:SP$ GainControl | Cost$ 1 R R | ValidTgts$ Creature,Vehicle | TgtPrompt$ Select target creature or vehicle | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBCast | SpellDescription$ Gain control of target creature or Vehicle until end of turn. Untap it. It gains haste until end of turn. You may cast a spell with converted mana cost 2 or less from your hand without paying its mana cost. +SVar:DBCast:DB$ Play | ValidZone$ Hand | Valid$ Card.YouOwn+nonLand | ValidSA$ Spell.cmcLE2 | Controller$ You | WithoutManaCost$ True | Optional$ True | Amount$ 1 SVar:Picture:http://www.wizards.com/global/images/magic/general/kari_zevs_expertise.jpg -Oracle:Gain control of target creature or Vehicle until end of turn. Untap it. It gains haste until end of turn.\nYou may cast a card with converted mana cost 2 or less from your hand without paying its mana cost. +Oracle:Gain control of target creature or Vehicle until end of turn. Untap it. It gains haste until end of turn.\nYou may cast a spell with converted mana cost 2 or less from your hand without paying its mana cost. diff --git a/forge-gui/res/cardsfolder/r/rishkars_expertise.txt b/forge-gui/res/cardsfolder/r/rishkars_expertise.txt index b9f2d53b08c..e0a1599eb5b 100644 --- a/forge-gui/res/cardsfolder/r/rishkars_expertise.txt +++ b/forge-gui/res/cardsfolder/r/rishkars_expertise.txt @@ -1,8 +1,8 @@ Name:Rishkar's Expertise ManaCost:4 G G Types:Sorcery -A:SP$ Draw | Cost$ 4 G G | NumCards$ X | References$ X | SubAbility$ DBPlay | SpellDescription$ Draw cards equal to the greatest power among creatures you control. You may cast a card with converted mana cost 5 or less from your hand without paying its mana cost. +A:SP$ Draw | Cost$ 4 G G | NumCards$ X | References$ X | SubAbility$ DBPlay | SpellDescription$ Draw cards equal to the greatest power among creatures you control. You may cast a spell with converted mana cost 5 or less from your hand without paying its mana cost. SVar:X:Count$GreatestPower_Creature.YouCtrl -SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn+cmcLE5 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True +SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn | ValidSA$ Spell.cmcLE5 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/rishkars_expertise.jpg -Oracle:Draw cards equal to the greatest power among creatures you control.\nYou may cast a card with converted mana cost 5 or less from your hand without paying its mana cost. +Oracle:Draw cards equal to the greatest power among creatures you control.\nYou may cast a spell with converted mana cost 5 or less from your hand without paying its mana cost. diff --git a/forge-gui/res/cardsfolder/s/srams_expertise.txt b/forge-gui/res/cardsfolder/s/srams_expertise.txt index 1e4e4043f37..e22dc46ee7e 100644 --- a/forge-gui/res/cardsfolder/s/srams_expertise.txt +++ b/forge-gui/res/cardsfolder/s/srams_expertise.txt @@ -1,7 +1,7 @@ Name:Sram's Expertise ManaCost:2 W W Types:Sorcery -A:SP$ Token | Cost$ 2 W W | TokenAmount$ 3 | TokenScript$ c_1_1_a_servo | TokenOwner$ You | LegacyImage$ c 1 1 a servo aer | SubAbility$ DBPlay | SpellDescription$ Create three 1/1 colorless Servo artifact creature tokens. You may cast a card with converted mana cost 3 or less from your hand without paying its mana cost. -SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn+cmcLE3 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True +A:SP$ Token | Cost$ 2 W W | TokenAmount$ 3 | TokenScript$ c_1_1_a_servo | TokenOwner$ You | LegacyImage$ c 1 1 a servo aer | SubAbility$ DBPlay | SpellDescription$ Create three 1/1 colorless Servo artifact creature tokens. You may cast a spell with converted mana cost 3 or less from your hand without paying its mana cost. +SVar:DBPlay:DB$ Play | Valid$ Card.nonLand+YouOwn | ValidSA$ Spell.cmcLE3 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/srams_expertise.jpg -Oracle:Create three 1/1 colorless Servo artifact creature tokens.\nYou may cast a card with converted mana cost 3 or less from your hand without paying its mana cost. +Oracle:Create three 1/1 colorless Servo artifact creature tokens.\nYou may cast a spell with converted mana cost 3 or less from your hand without paying its mana cost. diff --git a/forge-gui/res/cardsfolder/y/yahennis_expertise.txt b/forge-gui/res/cardsfolder/y/yahennis_expertise.txt index 3e686e4d23f..a059feb3578 100644 --- a/forge-gui/res/cardsfolder/y/yahennis_expertise.txt +++ b/forge-gui/res/cardsfolder/y/yahennis_expertise.txt @@ -1,7 +1,7 @@ Name:Yahenni's Expertise ManaCost:2 B B Types:Sorcery -A:SP$ PumpAll | Cost$ 2 B B | ValidCards$ Creature | NumAtt$ -3 | NumDef$ -3 | IsCurse$ True | SubAbility$ DBPlay | SpellDescription$ All creatures get -3/-3 until end of turn. You may cast a card with converted mana cost 3 or less from your hand without paying its mana cost. -SVar:DBPlay:DB$Play | Valid$ Card.nonLand+YouOwn+cmcLE3 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True +A:SP$ PumpAll | Cost$ 2 B B | ValidCards$ Creature | NumAtt$ -3 | NumDef$ -3 | IsCurse$ True | SubAbility$ DBPlay | SpellDescription$ All creatures get -3/-3 until end of turn. You may cast a spell with converted mana cost 3 or less from your hand without paying its mana cost. +SVar:DBPlay:DB$Play | Valid$ Card.nonLand+YouOwn | ValidSA$ Spell.cmcLE3 | ValidZone$ Hand | WithoutManaCost$ True | Amount$ 1 | Controller$ You | Optional$ True SVar:Picture:http://www.wizards.com/global/images/magic/general/yahennis_expertise.jpg -Oracle:All creatures get -3/-3 until end of turn.\nYou may cast a card with converted mana cost 3 or less from your hand without paying its mana cost. +Oracle:All creatures get -3/-3 until end of turn.\nYou may cast a spell with converted mana cost 3 or less from your hand without paying its mana cost.