From 7160670597a7fb45a2e0ac5f1f54d96ad4ff79d5 Mon Sep 17 00:00:00 2001 From: Hanmac Date: Tue, 7 May 2019 23:00:24 +0200 Subject: [PATCH 1/2] PW Ability: store num of activations in card --- .../src/main/java/forge/ai/AiController.java | 2 +- .../main/java/forge/ai/ComputerUtilCost.java | 2 +- .../main/java/forge/ai/SpellAbilityAi.java | 4 ++-- .../java/forge/ai/ability/DamageDealAi.java | 3 +-- .../main/java/forge/ai/ability/TokenAi.java | 4 ++-- .../java/forge/ai/simulation/GameCopier.java | 3 ++- .../ai/simulation/SpellAbilityPicker.java | 2 +- .../src/main/java/forge/game/GameAction.java | 4 +--- .../src/main/java/forge/game/card/Card.java | 17 ++++++++++++++ .../forge/game/player/AchievementTracker.java | 2 +- .../forge/game/spellability/SpellAbility.java | 7 +++++- .../spellability/SpellAbilityRestriction.java | 16 ++----------- .../spellability/SpellAbilityVariables.java | 23 ------------------- .../StaticAbilityCantBeCast.java | 4 ++-- .../StaticAbilityContinuous.java | 2 +- .../main/java/forge/game/zone/MagicStack.java | 8 +++++-- .../java/forge/player/HumanCostDecision.java | 2 +- 17 files changed, 47 insertions(+), 58 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index ab523e47e81..9b2c98bad32 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1010,7 +1010,7 @@ public class AiController { p += 9; } // sort planeswalker abilities with most costly first - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { final CostPart cost = sa.getPayCosts().getCostParts().get(0); if (cost instanceof CostRemoveCounter) { p += cost.convertAmount() == null ? 1 : cost.convertAmount(); diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index fb44ff4e31c..4afe5174eb8 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -481,7 +481,7 @@ public class ComputerUtilCost { } // Try not to lose Planeswalker if not threatened - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { for (final CostPart part : sa.getPayCosts().getCostParts()) { if (part instanceof CostRemoveCounter) { if (part.convertAmount() != null && part.convertAmount() == sa.getHostCard().getCurrentLoyalty()) { diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index 03c96209a0c..d86989d87a8 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -247,7 +247,7 @@ public abstract class SpellAbilityAi { protected static boolean isSorcerySpeed(final SpellAbility sa) { return (sa.getRootAbility().isSpell() && sa.getHostCard().isSorcery()) || (sa.getRootAbility().isAbility() && sa.getRestrictions().isSorcerySpeed()) - || (sa.getRestrictions().isPwAbility() && !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed.")); + || (sa.isPwAbility() && !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed.")); } /** @@ -276,7 +276,7 @@ public abstract class SpellAbilityAi { return true; } - if (sa.getRestrictions().isPwAbility() && phase.is(PhaseType.MAIN2)) { + if (sa.isPwAbility() && phase.is(PhaseType.MAIN2)) { return true; } if (sa.isSpell() && !sa.isBuyBackAbility()) { diff --git a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java index 1d088464afb..531ba01988a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DamageDealAi.java @@ -717,8 +717,7 @@ public class DamageDealAi extends DamageAiBase { } if (phase.is(PhaseType.MAIN2) && sa.isAbility()) { - if (sa.getRestrictions().isPwAbility() - || source.hasSVar("EndOfTurnLeavePlay")) + if (sa.isPwAbility() || source.hasSVar("EndOfTurnLeavePlay")) freePing = true; } } diff --git a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java index 4a193850e01..feae6ff6106 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TokenAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TokenAi.java @@ -78,7 +78,7 @@ public class TokenAi extends SpellAbilityAi { // Planeswalker-related flags boolean pwMinus = false; boolean pwPlus = false; - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { /* * Planeswalker token ability with loyalty costs should be played in * Main1 or it might never be used due to other positive abilities. @@ -230,7 +230,7 @@ public class TokenAi extends SpellAbilityAi { alwaysOnOppAttack = aic.getBooleanProperty(AiProps.TOKEN_GENERATION_ALWAYS_IF_OPP_ATTACKS); } - if (sa.getRestrictions() != null && sa.getRestrictions().isPwAbility() && alwaysFromPW) { + if (sa.isPwAbility() && alwaysFromPW) { return true; } else if (ai.getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS) && ai.getGame().getPhaseHandler().getPlayerTurn().isOpponentOf(ai) diff --git a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java index 30ffb85619a..72aedd7513e 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java +++ b/forge-ai/src/main/java/forge/ai/simulation/GameCopier.java @@ -324,11 +324,12 @@ public class GameCopier { if (c.isPlaneswalker()) { for (SpellAbility sa : c.getAllSpellAbilities()) { SpellAbilityRestriction restrict = sa.getRestrictions(); - if (restrict.isPwAbility() && restrict.getNumberTurnActivations() > 0) { + if (sa.isPwAbility() && restrict.getNumberTurnActivations() > 0) { SpellAbility newSa = findSAInCard(sa, newCard); if (newSa != null) { for (int i = 0; i < restrict.getNumberTurnActivations(); i++) { newSa.getRestrictions().abilityActivated(); + newCard.addPlaneswalkerAbilityActivated(); } } } diff --git a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java index 210930785b7..a14f2b94047 100644 --- a/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java +++ b/forge-ai/src/main/java/forge/ai/simulation/SpellAbilityPicker.java @@ -148,7 +148,7 @@ public class SpellAbilityPicker { if (sa.isSpell()) { return !sa.getHostCard().isInstant() && !sa.getHostCard().withFlash(player); } - if (sa.getRestrictions().isPwAbility()) { + if (sa.isPwAbility()) { return !sa.getHostCard().hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed."); } return sa.isAbility() && sa.getRestrictions().isSorcerySpeed(); diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index 6b515831aad..f9043497e96 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -72,9 +72,7 @@ public class GameAction { public final void resetActivationsPerTurn() { // Reset Activations per Turn for (final Card card : game.getCardsInGame()) { - for (final SpellAbility sa : card.getAllSpellAbilities()) { - sa.getRestrictions().resetTurnActivations(); - } + card.resetActivationsPerTurn(); } } diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 6dabca8a792..75a752c9593 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -267,6 +267,8 @@ public class Card extends GameEntity implements Comparable { private SpellAbility[] basicLandAbilities = new SpellAbility[MagicColor.WUBRG.length]; + private int planeswalkerAbilityActivated = 0; + // Enumeration for CMC request types public enum SplitCMCMode { CurrentSideCMC, @@ -6183,4 +6185,19 @@ public class Card extends GameEntity implements Comparable { return true; } + + public int getPlaneswalkerAbilityActivated() { + return planeswalkerAbilityActivated; + } + + public void addPlaneswalkerAbilityActivated() { + planeswalkerAbilityActivated++; + } + + public void resetActivationsPerTurn() { + planeswalkerAbilityActivated = 0; + for (final SpellAbility sa : this.getAllSpellAbilities()) { + sa.getRestrictions().resetTurnActivations(); + } + } } diff --git a/forge-game/src/main/java/forge/game/player/AchievementTracker.java b/forge-game/src/main/java/forge/game/player/AchievementTracker.java index 7f7d0d0d82e..58ff288510e 100644 --- a/forge-game/src/main/java/forge/game/player/AchievementTracker.java +++ b/forge-game/src/main/java/forge/game/player/AchievementTracker.java @@ -19,7 +19,7 @@ public class AchievementTracker { public void onSpellAbilityPlayed(final SpellAbility sa) { final Card card = sa.getHostCard(); - if (sa.getRestrictions().isPwAbility() && sa.hasParam("Ultimate")) { + if (sa.isPwAbility() && sa.hasParam("Ultimate")) { activatedUltimates.add(card.getName()); } if (card.determineColor().equals(ColorSet.ALL_COLORS)) { 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 7d4fe9b8656..79d2bce6599 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -264,7 +264,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit } // without a target if (usesTargeting()) { return false; } - if (restrictions != null && restrictions.isPwAbility()) { + if (isPwAbility()) { return false; //Loyalty ability, not a mana ability. } if (isWrapper() && ((WrappedAbility) this).getTrigger().getMode() != TriggerType.TapsForMana) { @@ -438,6 +438,11 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit return hasParam("IsCurse"); } + public final boolean isPwAbility() { + // TODO try to check the Cost itself + return hasParam("Planeswalker"); + } + // begin - Input methods public Cost getPayCosts() { diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java index e992a95a90c..f57128a9ae1 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityRestriction.java @@ -153,10 +153,6 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { this.setColorToCheck(params.get("ActivationChosenColor")); } - if (params.containsKey("Planeswalker")) { - this.setPwAbility(true); - } - if (params.containsKey("IsPresent")) { this.setIsPresent(params.get("IsPresent")); if (params.containsKey("PresentCompare")) { @@ -482,7 +478,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { } } - if (this.isPwAbility()) { + if (sa.isPwAbility()) { if (!c.hasKeyword("CARDNAME's loyalty abilities can be activated at instant speed.") && !activator.canCastSorcery()) { return false; @@ -491,15 +487,7 @@ public class SpellAbilityRestriction extends SpellAbilityVariables { final int initialLimit = c.hasKeyword("CARDNAME's loyalty abilities can be activated twice each turn rather than only once") ? 1 : 0; final int limits = c.getAmountOfKeyword("May activate CARDNAME's loyalty abilities once") + initialLimit; - int numActivates = 0; - for (final SpellAbility pwAbs : c.getAllSpellAbilities()) { - // check all abilities on card that have their planeswalker - // restriction set to confirm they haven't been activated - final SpellAbilityRestriction restrict = pwAbs.getRestrictions(); - if (restrict.isPwAbility()) { - numActivates += restrict.getNumberTurnActivations(); - } - } + int numActivates = c.getPlaneswalkerAbilityActivated(); if (numActivates > limits) { return false; } diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java index ed4cc49e41f..d51bb0069ac 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityVariables.java @@ -90,7 +90,6 @@ public class SpellAbilityVariables implements Cloneable { this.manaSpent = sav.getManaSpent(); this.targetValidTargeting = sav.getTargetValidTargeting(); this.targetsSingleTarget = sav.targetsSingleTarget(); - this.pwAbility = sav.isPwAbility(); this.presenceCondition = sav.getPresenceCondition(); } @@ -197,9 +196,6 @@ public class SpellAbilityVariables implements Cloneable { /** The mana spent. */ private String manaSpent = ""; - /** The pw ability. */ - private boolean pwAbility = false; - /** The chosen colors string. */ private String chosenColors = null; @@ -674,25 +670,6 @@ public class SpellAbilityVariables implements Cloneable { this.shareAllColors = shareAllColors; } - /** - * Checks if is pw ability. - * - * @return the pwAbility - */ - public final boolean isPwAbility() { - return this.pwAbility; - } - - /** - * Sets the pw ability. - * - * @param pwAbility0 - * the new pw ability - */ - public final void setPwAbility(final boolean pwAbility0) { - this.pwAbility = pwAbility0; - } - /** * Checks if is player turn. * diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java index 58b910d01eb..bf0213da0f2 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java @@ -126,11 +126,11 @@ public class StaticAbilityCantBeCast { return false; } - if (params.containsKey("NonLoyalty") && (spellAbility.getRestrictions().isPwAbility())) { + if (params.containsKey("NonLoyalty") && spellAbility.isPwAbility()) { return false; } - if (params.containsKey("Loyalty") && !(spellAbility.getRestrictions().isPwAbility())) { + if (params.containsKey("Loyalty") && !spellAbility.isPwAbility()) { return false; } diff --git a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java index ff9ff5ffb51..d5f1786bbcf 100644 --- a/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java +++ b/forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java @@ -394,7 +394,7 @@ public final class StaticAbilityContinuous { for (Card c : cardsIGainedAbilitiesFrom) { for (SpellAbility sa : c.getSpellAbilities()) { if (sa instanceof AbilityActivated) { - if (loyaltyAB && !sa.getRestrictions().isPwAbility()) { + if (loyaltyAB && !sa.isPwAbility()) { continue; } SpellAbility newSA = sa.copy(hostCard, false); diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index 016ab697d17..07242065e5a 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -133,16 +133,20 @@ public class MagicStack /* extends MyObservable */ implements Iterable Date: Tue, 7 May 2019 23:01:12 +0200 Subject: [PATCH 2/2] cards: some card fixes --- forge-gui/res/cardsfolder/g/god_eternal_kefnet.txt | 2 +- forge-gui/res/cardsfolder/r/ravager_wurm.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-gui/res/cardsfolder/g/god_eternal_kefnet.txt b/forge-gui/res/cardsfolder/g/god_eternal_kefnet.txt index 5bf82ef7c01..c7fc66267cf 100644 --- a/forge-gui/res/cardsfolder/g/god_eternal_kefnet.txt +++ b/forge-gui/res/cardsfolder/g/god_eternal_kefnet.txt @@ -3,7 +3,7 @@ ManaCost:2 U U Types:Legendary Creature Zombie God PT:4/5 K:Flying -T:Mode$ Drawn | ValidCard$ Card.YouOwn | Number$ 1 | OptionalDecider$ You | Static$ True | Execute$ DBReveal | TriggerDescription$ You may reveal the first card you draw each turn as you draw it. Whenever you reveal an instant or sorcery card this way, copy that card and you may cast the copy. That copy costs {2} less to cast. +T:Mode$ Drawn | ValidCard$ Card.YouOwn | Number$ 1 | OptionalDecider$ You | Static$ True | Execute$ DBReveal | TriggerZones$ Battlefield | TriggerDescription$ You may reveal the first card you draw each turn as you draw it. Whenever you reveal an instant or sorcery card this way, copy that card and you may cast the copy. That copy costs {2} less to cast. SVar:DBReveal:DB$ Reveal | Defined$ You | RevealDefined$ TriggeredCard | RememberRevealed$ True | SubAbility$ DBTrigger | AILogic$ Kefnet SVar:DBTrigger:DB$ ImmediateTrigger | RememberObjects$ RememberedCard | ConditionDefined$ Remembered | ConditionPresent$ Instant,Sorcery | SubAbility$ DBCleanup | Execute$ DBPlay | TriggerDescription$ Whenever you reveal an instant or sorcery card this way, copy that card and you may cast the copy. That copy costs {2} less to cast. SVar:DBPlay:DB$ Play | Defined$ DelayTriggerRemembered | PlayReduceCost$ 2 | CopyOnce$ True | Optional$ True | CopyCard$ True diff --git a/forge-gui/res/cardsfolder/r/ravager_wurm.txt b/forge-gui/res/cardsfolder/r/ravager_wurm.txt index dc241c32c6f..42a0f4eaf90 100644 --- a/forge-gui/res/cardsfolder/r/ravager_wurm.txt +++ b/forge-gui/res/cardsfolder/r/ravager_wurm.txt @@ -6,6 +6,6 @@ K:Riot T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ When CARDNAME enters the battlefield, ABILITY SVar:TrigCharm:DB$ Charm | MinCharmNum$ 0 | CharmNum$ 1 | Choices$ DBFight,DBDestroy SVar:DBFight:DB$ Fight | Defined$ TriggeredCardLKICopy | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Choose target creature you don't control | SpellDescription$ CARDNAME fights target creature you don't control. -SVar:DBDestroy:DB$ Destroy | ValidTgts$ Land.hasNonManaActivatedAbility | TgtPrompt$ Select target land with an activated ability that isn't a mana ability | SpellDescription$ Destroy target land with an activated ability that iasn't a mana ability. +SVar:DBDestroy:DB$ Destroy | ValidTgts$ Land.hasNonManaActivatedAbility | TgtPrompt$ Select target land with an activated ability that isn't a mana ability | SpellDescription$ Destroy target land with an activated ability that isn't a mana ability. DeckHas:Ability$Counters Oracle:Riot (This creature enters the battlefield with your choice of a +1/+1 counter or haste.)\nWhen Ravager Wurm enters the battlefield, choose up to one -\n- Ravager Wurm fights target creature you don't control.\n- Destroy target land with an activated ability that isn't a mana ability.