diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index c1654ffa096..6d75feae75d 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -253,7 +253,7 @@ public abstract class SpellAbilityAi { */ protected static boolean isSorcerySpeed(final SpellAbility sa, Player ai) { return (sa.getRootAbility().isSpell() && sa.getHostCard().isSorcery()) - || (sa.getRootAbility().isActivatedAbility() && sa.getRestrictions().isSorcerySpeed()) + || (sa.getRootAbility().isActivatedAbility() && sa.getRootAbility().getRestrictions().isSorcerySpeed()) || (sa.getRootAbility().isAdventure() && sa.getHostCard().getState(CardStateName.Adventure).getType().isSorcery()) || (sa.isPwAbility() && !sa.withFlash(sa.getHostCard(), ai)); } diff --git a/forge-ai/src/main/java/forge/ai/ability/EffectAi.java b/forge-ai/src/main/java/forge/ai/ability/EffectAi.java index df52d56b582..21c976b9a52 100644 --- a/forge-ai/src/main/java/forge/ai/ability/EffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/EffectAi.java @@ -285,12 +285,10 @@ public class EffectAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) { - String aiLogic = sa.getParamOrDefault("AILogic", ""); - // E.g. Nova Pentacle - if (aiLogic.equals("RedirectFromOppToCreature")) { + if (sa.usesTargeting() && !sa.getTargetRestrictions().canTgtPlayer()) { // try to target the opponent's best targetable permanent, if able - CardCollection oppPerms = CardLists.getValidCards(aiPlayer.getOpponents().getCardsIn(ZoneType.Battlefield), sa.getTargetRestrictions().getValidTgts(), aiPlayer, sa.getHostCard(), sa); + CardCollection oppPerms = CardLists.getValidCards(aiPlayer.getOpponents().getCardsIn(sa.getTargetRestrictions().getZone()), sa.getTargetRestrictions().getValidTgts(), aiPlayer, sa.getHostCard(), sa); if (!oppPerms.isEmpty()) { sa.resetTargets(); sa.getTargets().add(ComputerUtilCard.getBestAI(oppPerms)); @@ -299,7 +297,7 @@ public class EffectAi extends SpellAbilityAi { if (mandatory) { // try to target the AI's worst targetable permanent, if able - CardCollection aiPerms = CardLists.getValidCards(aiPlayer.getCardsIn(ZoneType.Battlefield), sa.getTargetRestrictions().getValidTgts(), aiPlayer, sa.getHostCard(), sa); + CardCollection aiPerms = CardLists.getValidCards(aiPlayer.getCardsIn(sa.getTargetRestrictions().getZone()), sa.getTargetRestrictions().getValidTgts(), aiPlayer, sa.getHostCard(), sa); if (!aiPerms.isEmpty()) { sa.resetTargets(); sa.getTargets().add(ComputerUtilCard.getWorstAI(aiPerms)); 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 6377c5dab0c..17032b0e41b 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -940,7 +940,7 @@ public class Player extends GameEntity implements Comparable { public final void addChangedKeywords(final List addKeywords, final List removeKeywords, final Long timestamp, final long staticId) { List kws = Lists.newArrayList(); if (addKeywords != null) { - for(String kw : addKeywords) { + for (String kw : addKeywords) { kws.add(getKeywordForStaticAbility(kw, staticId)); } } diff --git a/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java b/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java index 79a80192a10..3fae0daa1c6 100644 --- a/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/player/PlayerFactoryUtil.java @@ -37,7 +37,7 @@ public class PlayerFactoryUtil { inst.addStaticAbility(StaticAbility.create(effect, card, card.getCurrentState(), false)); } else if (keyword.startsWith("Protection")) { String valid = CardFactoryUtil.getProtectionValid(keyword, false); - String effect = "Mode$ CantTarget | Protection$ True | ValidCard$ Player.You | Secondary$ True "; + String effect = "Mode$ CantTarget | Protection$ True | ValidPlayer$ Player.You | EffectZone$ Command | Secondary$ True "; if (!valid.isEmpty()) { effect += "| ValidSource$ " + valid; } @@ -45,7 +45,7 @@ public class PlayerFactoryUtil { inst.addStaticAbility(StaticAbility.create(effect, card, card.getCurrentState(), false)); // Attach - effect = "Mode$ CantAttach | Protection$ True | Target$ Player.You | Secondary$ True "; + effect = "Mode$ CantAttach | Protection$ True | Target$ Player.You| EffectZone$ Command | Secondary$ True "; if (!valid.isEmpty()) { effect += "| ValidCard$ " + valid; } diff --git a/forge-gui/res/cardsfolder/i/icebreaker_kraken.txt b/forge-gui/res/cardsfolder/i/icebreaker_kraken.txt index 0f9b69c25b7..2023fc6fc08 100644 --- a/forge-gui/res/cardsfolder/i/icebreaker_kraken.txt +++ b/forge-gui/res/cardsfolder/i/icebreaker_kraken.txt @@ -3,13 +3,12 @@ ManaCost:10 U U Types:Snow Creature Kraken PT:8/8 S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ X | EffectZone$ All | Description$ CARDNAME costs {1} less to cast for each snow land you control. -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | ValidCards$ Artifact,Creature | Execute$ DBEffect | TriggerDescription$ When CARDNAME enters the battlefield, artifacts and creatures target opponent controls don't untap during that player's next untap step. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ DBEffect | TriggerDescription$ When CARDNAME enters the battlefield, artifacts and creatures target opponent controls don't untap during that player's next untap step. A:AB$ ChangeZone | Cost$ Return<3/Land.Snow> | Origin$ Battlefield | Destination$ Hand | SpellDescription$ Return CARDNAME to its owner's hand. -SVar:DBEffect:DB$ Effect | StaticAbilities$ DontUntap | Triggers$ RemoveEffect | Duration$ Permanent | ValidTgts$ Opponent | RememberObjects$ Targeted | SubAbility$ DBCleanup | SpellDescription$ During that player's next untap step, artifacts and creatures they control don't untap. +SVar:DBEffect:DB$ Effect | StaticAbilities$ DontUntap | Triggers$ RemoveEffect | Duration$ Permanent | ValidTgts$ Opponent | RememberObjects$ Targeted | SpellDescription$ During that player's next untap step, artifacts and creatures they control don't untap. SVar:DontUntap:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Artifact.RememberedPlayerCtrl,Creature.RememberedPlayerCtrl | AddHiddenKeyword$ This card doesn't untap during your next untap step. | Description$ Artifacts and creatures target opponent controls don't untap during their next untap step. SVar:RemoveEffect:Mode$ Phase | Phase$ Untap | ValidPlayer$ Player.IsRemembered | TriggerZones$ Command | Static$ True | Execute$ ExileEffect SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Count$Valid Land.Snow+YouCtrl DeckHints:Type$Snow Oracle:This spell costs {1} less to cast for each snow land you control.\nWhen Icebreaker Kraken enters the battlefield, artifacts and creatures target opponent controls don't untap during that player's next untap step.\nReturn three snow lands you control to their owner's hand: Return Icebreaker Kraken to its owner's hand. diff --git a/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros_gideon_battle_forged.txt b/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros_gideon_battle_forged.txt index 225737c79ad..a8ac73b0080 100644 --- a/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros_gideon_battle_forged.txt +++ b/forge-gui/res/cardsfolder/k/kytheon_hero_of_akros_gideon_battle_forged.txt @@ -21,9 +21,8 @@ Colors:white Types:Legendary Planeswalker Gideon Loyalty:3 A:AB$ DelayedTrigger | Cost$ AddCounter<2/LOYALTY> | Planeswalker$ True | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | Mode$ Phase | Phase$ Upkeep-> | ValidPlayer$ Player.controlsCard.IsTriggerRemembered | UpcomingTurn$ True | RememberObjects$ Targeted | Execute$ TrigEffect | Static$ True | SpellDescription$ Up to one target creature an opponent controls attacks CARDNAME during its controller's next turn if able. -SVar:TrigEffect:DB$ Effect | RememberObjects$ DelayTriggerRemembered | StaticAbilities$ MustAttack | SubAbility$ DBCleanup +SVar:TrigEffect:DB$ Effect | RememberObjects$ DelayTriggerRemembered | StaticAbilities$ MustAttack SVar:MustAttack:Mode$ MustAttack | EffectZone$ Command | ValidCreature$ Creature.IsRemembered | MustAttack$ EffectSource | Description$ This creature attacks EFFECTSOURCE during its controller's next turn if able. -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True A:AB$ Pump | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | KW$ Indestructible | Duration$ UntilYourNextTurn | SubAbility$ DBUntap | SpellDescription$ Until your next turn, target creature gains indestructible. Untap that creature. SVar:DBUntap:DB$ Untap | Defined$ Targeted A:AB$ Animate | Cost$ AddCounter<0/LOYALTY> | Defined$ Self | Power$ 4 | Toughness$ 4 | Types$ Creature,Human,Soldier | Keywords$ Indestructible | SubAbility$ DBPrevent | Planeswalker$ True | Ultimate$ True | SpellDescription$ Until end of turn, CARDNAME becomes a 4/4 Human Soldier creature with indestructible that's still a planeswalker. Prevent all damage that would be dealt to him this turn. diff --git a/forge-gui/res/cardsfolder/m/misstep.txt b/forge-gui/res/cardsfolder/m/misstep.txt index a816747549e..62bf9386cca 100644 --- a/forge-gui/res/cardsfolder/m/misstep.txt +++ b/forge-gui/res/cardsfolder/m/misstep.txt @@ -1,9 +1,8 @@ Name:Misstep ManaCost:1 U Types:Sorcery -A:SP$ Effect | Cost$ 1 U | ValidTgts$ Player | StaticAbilities$ DontUntap | Triggers$ RemoveEffect | Duration$ Permanent | RememberObjects$ Targeted | SubAbility$ DBCleanup | SpellDescription$ Creatures target player controls don't untap during that player's next untap step. +A:SP$ Effect | Cost$ 1 U | ValidTgts$ Player | StaticAbilities$ DontUntap | Triggers$ RemoveEffect | Duration$ Permanent | RememberObjects$ Targeted | SpellDescription$ Creatures target player controls don't untap during that player's next untap step. SVar:DontUntap:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.RememberedPlayerCtrl | AddHiddenKeyword$ This card doesn't untap during your next untap step. | Description$ Creatures target player controls don't untap during their next untap step. SVar:RemoveEffect:Mode$ Phase | Phase$ Untap | ValidPlayer$ Player.IsRemembered | TriggerZones$ Command | Static$ True | Execute$ ExileEffect SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True Oracle:Creatures target player controls don't untap during that player's next untap step. diff --git a/forge-gui/res/cardsfolder/n/nova_pentacle.txt b/forge-gui/res/cardsfolder/n/nova_pentacle.txt index 6ebbf782d6d..df84516ff16 100644 --- a/forge-gui/res/cardsfolder/n/nova_pentacle.txt +++ b/forge-gui/res/cardsfolder/n/nova_pentacle.txt @@ -2,7 +2,7 @@ Name:Nova Pentacle ManaCost:4 Types:Artifact A:AB$ ChooseSource | Cost$ 3 T | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead. -SVar:DBEffect:DB$ Effect | TargetingPlayer$ Player.Opponent | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect the damage to | ReplacementEffects$ SelflessDamage | ExileOnMoved$ Battlefield | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | AILogic$ RedirectFromOppToCreature +SVar:DBEffect:DB$ Effect | TargetingPlayer$ Player.Opponent | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect the damage to | ReplacementEffects$ SelflessDamage | ExileOnMoved$ Battlefield | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Card.ChosenCardStrict,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ Remembered | Description$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead. SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Remembered | VarType$ Card | SubAbility$ ExileEffect SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile diff --git a/forge-gui/res/cardsfolder/x/xantid_swarm.txt b/forge-gui/res/cardsfolder/x/xantid_swarm.txt index c10866766e9..a12cf1e1b31 100644 --- a/forge-gui/res/cardsfolder/x/xantid_swarm.txt +++ b/forge-gui/res/cardsfolder/x/xantid_swarm.txt @@ -4,8 +4,7 @@ Types:Creature Insect PT:0/1 K:Flying T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ When CARDNAME attacks, defending player can't cast spells this turn. -SVar:TrigEffect:DB$ Effect | Name$ Xantid Swarm Effect | RememberObjects$ TriggeredDefendingPlayer | StaticAbilities$ CantBeCast | SubAbility$ DBCleanup -SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:TrigEffect:DB$ Effect | RememberObjects$ TriggeredDefendingPlayer | StaticAbilities$ CantBeCast SVar:CantBeCast:Mode$ CantBeCast | EffectZone$ Command | ValidCard$ Card | Caster$ Player.IsRemembered | Description$ Defending player can't cast spells. AI:RemoveDeck:Random SVar:HasAttackEffect:TRUE