diff --git a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java index 3a73a3876d0..2c229c7b7c0 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java @@ -1,5 +1,6 @@ package forge.ai.ability; +import java.util.Collections; import java.util.List; import java.util.Map; @@ -25,6 +26,7 @@ public class CharmAi extends SpellAbilityAi { protected boolean checkApiLogic(Player ai, SpellAbility sa) { final Card source = sa.getHostCard(); List choices = CharmEffect.makePossibleOptions(sa); + Collections.shuffle(choices); final int num; final int min; diff --git a/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java b/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java index 0495aff8d1f..e3554f94aa3 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ManaEffectAi.java @@ -114,7 +114,7 @@ public class ManaEffectAi extends SpellAbilityAi { } // Dark Ritual and other similar instants/sorceries that add mana to mana pool - private boolean doManaRitualLogic(Player ai, SpellAbility sa) { + public static boolean doManaRitualLogic(Player ai, SpellAbility sa) { final Card host = sa.getHostCard(); final String logic = sa.getParamOrDefault("AILogic", ""); @@ -123,7 +123,7 @@ public class ManaEffectAi extends SpellAbilityAi { int manaReceived = sa.hasParam("Amount") ? AbilityUtils.calculateAmount(host, sa.getParam("Amount"), sa) : 1; manaReceived *= sa.getParam("Produced").split(" ").length; - int selfCost = sa.getPayCosts().getCostMana() != null ? sa.getPayCosts().getCostMana().getMana().getCMC() : 0; + int selfCost = sa.getRootAbility().getPayCosts().getCostMana() != null ? sa.getRootAbility().getPayCosts().getCostMana().getMana().getCMC() : 0; String produced = sa.getParam("Produced"); byte producedColor = produced.equals("Any") ? MagicColor.ALL_COLORS : MagicColor.fromName(produced); diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java index 3822c65bcd5..35e7a7b4692 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java @@ -34,6 +34,8 @@ import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.player.PlayerActionConfirmMode; +import forge.game.player.PlayerCollection; +import forge.game.player.PlayerPredicates; import forge.game.spellability.SpellAbility; import forge.game.spellability.TargetRestrictions; import forge.game.staticability.StaticAbility; @@ -510,6 +512,15 @@ public class PumpAi extends PumpAiBase { } return false; + } else if ("ManaRitual".equals(sa.getParam("AILogic"))) { + PlayerCollection targetableOpps = ai.getOpponents().filter(PlayerPredicates.isTargetableBy(sa)); + if (targetableOpps.isEmpty()) { + return false; + } + Player mostCards = targetableOpps.max(PlayerPredicates.compareByZoneSize(ZoneType.Hand)); + sa.resetTargets(); + sa.getTargets().add(mostCards); + return mandatory || ManaEffectAi.doManaRitualLogic(ai, sa.getSubAbility()); } if (isFight) { diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index 6c68ed42e08..097aebcf786 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -3201,7 +3201,7 @@ public class CardFactoryUtil { return true; } - return this.getHostCard().getOwner().canCastSorcery() || this.getHostCard().getFirstSpellAbility().withFlash(this.getHostCard(), this.getActivatingPlayer()); + return this.getHostCard().getFirstSpellAbility().canCastTiming(this.getHostCard(), this.getActivatingPlayer()); } @Override diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index ee0baf82aa2..168b9520b54 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -2341,7 +2341,6 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit public boolean canCastTiming(Player activator) { return canCastTiming(getHostCard(), activator); } - public boolean canCastTiming(Card host, Player activator) { // for companion if (this instanceof AbilityStatic && getRestrictions().isSorcerySpeed() && !activator.canCastSorcery()) { @@ -2360,7 +2359,9 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit // spells per default are sorcerySpeed if (isSpell()) { return false; - } else if (isActivatedAbility()) { + } + + if (isActivatedAbility()) { // Activated Abillties are instant speed per default return !getRestrictions().isSorcerySpeed(); } diff --git a/forge-gui/res/cardsfolder/j/jeskas_will.txt b/forge-gui/res/cardsfolder/j/jeskas_will.txt index 6dc84b06b55..84b91e5c9b2 100644 --- a/forge-gui/res/cardsfolder/j/jeskas_will.txt +++ b/forge-gui/res/cardsfolder/j/jeskas_will.txt @@ -2,7 +2,7 @@ Name:Jeska's Will ManaCost:2 R Types:Sorcery A:SP$ Charm | Cost$ 2 R | MinCharmNum$ 1 | CharmNum$ X | Choices$ DBHandTarget,DBExile | AdditionalDescription$ If you control a commander as you cast this spell, you may choose both. -SVar:DBHandTarget:DB$ Pump | ValidTgts$ Opponent | SubAbility$ DBMana | SpellDescription$ Add {R} for each card in target opponent's hand. +SVar:DBHandTarget:DB$ Pump | ValidTgts$ Opponent | SubAbility$ DBMana | AILogic$ ManaRitual | SpellDescription$ Add {R} for each card in target opponent's hand. SVar:DBMana:DB$ Mana | Produced$ R | Amount$ Z | StackDescription$ None SVar:DBExile:DB$ Dig | Defined$ You | DigNum$ 3 | ChangeNum$ All | DestinationZone$ Exile | RememberChanged$ True | SubAbility$ DBEffect | SpellDescription$ Exile the top three cards of your library. You may play them this turn. SVar:DBEffect:DB$ Effect | RememberObjects$ RememberedCard | StaticAbilities$ Play | SubAbility$ DBCleanup | ForgetOnMoved$ Exile diff --git a/forge-gui/res/cardsfolder/r/rousing_refrain.txt b/forge-gui/res/cardsfolder/r/rousing_refrain.txt index 8a9d7915683..194b7b7ce7d 100644 --- a/forge-gui/res/cardsfolder/r/rousing_refrain.txt +++ b/forge-gui/res/cardsfolder/r/rousing_refrain.txt @@ -2,8 +2,8 @@ Name:Rousing Refrain ManaCost:3 R R Types:Sorcery K:Suspend:3:1 R -A:SP$ Pump | Cost$ 3 R R | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | SubAbility$ DBMana | StackDescription$ None | SpellDescription$ Add {R} for each card in target opponent's hand. -SVar:DBMana:DB$ Mana | Produced$ R | Amount$ Z | PersistentMana$ True | StackDescription$ None | SubAbility$ DBChange |SpellDescription$ Until end of turn, you don't lose this mana as steps and phases end. +A:SP$ Pump | Cost$ 3 R R | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | SubAbility$ DBMana | AILogic$ ManaRitual | StackDescription$ SpellDescription | SpellDescription$ Add {R} for each card in target opponent's hand. +SVar:DBMana:DB$ Mana | Produced$ R | Amount$ Z | PersistentMana$ True | SubAbility$ DBChange | StackDescription$ SpellDescription | SpellDescription$ Until end of turn, you don't lose this mana as steps and phases end. SVar:Z:TargetedPlayer$CardsInHand SVar:DBChange:DB$ ChangeZone | Origin$ Stack | Destination$ Exile | WithCountersType$ TIME | WithCountersAmount$ 3 | SpellDescription$ Exile CARDNAME with three time counters on it. Oracle:Add {R} for each card in target opponent's hand. Until end of turn, you don't lose this mana as steps and phases end. Exile Rousing Refrain with three time counters on it.\nSuspend 3—{1}{R} (Rather than cast this card from your hand, you may pay {1}{R} and exile it with three time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost.)