From 9f35da4698db5cffc3aa0cf385b62bae2f9d16c2 Mon Sep 17 00:00:00 2001
From: Hans Mackowiak
Date: Thu, 12 Mar 2020 13:34:27 +0000
Subject: [PATCH] ManaPart: use Effect for enter the battlefield when mana was
spent
---
.../main/java/forge/game/GameActionUtil.java | 66 +++++++++++++-
.../main/java/forge/game/mana/ManaPool.java | 2 +-
.../game/spellability/AbilityManaPart.java | 87 ++++++++++++++-----
3 files changed, 129 insertions(+), 26 deletions(-)
diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java
index b54c727370f..6d9ed807964 100644
--- a/forge-game/src/main/java/forge/game/GameActionUtil.java
+++ b/forge-game/src/main/java/forge/game/GameActionUtil.java
@@ -22,8 +22,10 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import forge.card.MagicColor;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostParser;
+import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.ApiType;
import forge.game.card.*;
@@ -32,9 +34,15 @@ import forge.game.cost.Cost;
import forge.game.keyword.KeywordInterface;
import forge.game.player.Player;
import forge.game.player.PlayerController;
+import forge.game.replacement.ReplacementEffect;
+import forge.game.replacement.ReplacementHandler;
+import forge.game.replacement.ReplacementLayer;
import forge.game.spellability.*;
import forge.game.trigger.Trigger;
+import forge.game.trigger.TriggerHandler;
+import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
+import forge.util.Lang;
import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils;
@@ -363,10 +371,11 @@ public final class GameActionUtil {
}
SpellAbility result = null;
final Card host = sa.getHostCard();
+ final Game game = host.getGame();
final Player activator = sa.getActivatingPlayer();
final PlayerController pc = activator.getController();
- host.getGame().getAction().checkStaticAbilities(false);
+ game.getAction().checkStaticAbilities(false);
boolean reset = false;
@@ -429,7 +438,60 @@ public final class GameActionUtil {
int v = pc.chooseNumberForKeywordCost(sa, cost, ki, str, Integer.MAX_VALUE);
if (v > 0) {
- host.addReplacementEffect(CardFactoryUtil.makeEtbCounter("etbCounter:P1P1:" + v, host, false));
+
+ final Card eff = new Card(game.nextCardId(), game);
+ eff.setTimestamp(game.getNextTimestamp());
+ eff.setName(c.getName() + "'s Effect");
+ eff.addType("Effect");
+ eff.setToken(true); // Set token to true, so when leaving play it gets nuked
+ eff.setOwner(activator);
+
+ eff.setImageKey(c.getImageKey());
+ eff.setColor(MagicColor.COLORLESS);
+ eff.setImmutable(true);
+ // try to get the SpellAbility from the mana ability
+ //eff.setEffectSource((SpellAbility)null);
+
+ eff.addRemembered(host);
+
+ String abStr = "DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ " + v;
+
+ SpellAbility saAb = AbilityFactory.getAbility(abStr, c);
+
+ CardFactoryUtil.setupETBReplacementAbility(saAb);
+
+ String desc = "It enters the battlefield with ";
+ desc += Lang.nounWithNumeral(v, CounterType.P1P1.getName() + " counter");
+ desc += " on it.";
+
+ String repeffstr = "Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | Description$ " + desc;
+
+ ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true);
+ re.setLayer(ReplacementLayer.Other);
+ re.setOverridingAbility(saAb);
+
+ eff.addReplacementEffect(re);
+
+ // Forgot Trigger
+ String trig = "Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Stack | Destination$ Any | TriggerZones$ Command | Static$ True";
+ String forgetEffect = "DB$ Pump | ForgetObjects$ TriggeredCard";
+ String exileEffect = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile"
+ + " | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0";
+
+ SpellAbility saForget = AbilityFactory.getAbility(forgetEffect, eff);
+ AbilitySub saExile = (AbilitySub) AbilityFactory.getAbility(exileEffect, eff);
+ saForget.setSubAbility(saExile);
+
+ final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig, eff, true);
+ parsedTrigger.setOverridingAbility(saForget);
+ eff.addTrigger(parsedTrigger);
+ eff.updateStateForView();
+
+ // TODO: Add targeting to the effect so it knows who it's dealing with
+ game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
+ game.getAction().moveTo(ZoneType.Command, eff, null);
+ game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
+
if (result == null) {
result = sa.copy();
}
diff --git a/forge-game/src/main/java/forge/game/mana/ManaPool.java b/forge-game/src/main/java/forge/game/mana/ManaPool.java
index e90e6eb9b50..d11afbe776c 100644
--- a/forge-game/src/main/java/forge/game/mana/ManaPool.java
+++ b/forge-game/src/main/java/forge/game/mana/ManaPool.java
@@ -254,7 +254,7 @@ public class ManaPool extends ManaConversionMatrix implements Iterable {
}
}
if (mana.addsCounters(sa)) {
- mana.getManaAbility().createETBCounters(host);
+ mana.getManaAbility().createETBCounters(host, this.owner);
}
if (mana.triggersWhenSpent()) {
mana.getManaAbility().addTriggersWhenSpent(sa, host);
diff --git a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java
index f2976852559..510458a6189 100644
--- a/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java
+++ b/forge-game/src/main/java/forge/game/spellability/AbilityManaPart.java
@@ -6,23 +6,24 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package forge.game.spellability;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.mana.ManaAtom;
+import forge.game.Game;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityKey;
import forge.game.card.Card;
@@ -35,6 +36,8 @@ import forge.game.replacement.*;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.trigger.TriggerType;
+import forge.game.zone.ZoneType;
+import forge.util.Lang;
import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils;
@@ -47,7 +50,7 @@ import java.util.regex.Pattern;
*
* Abstract AbilityMana class.
*
- *
+ *
* @author Forge
* @version $Id$
*/
@@ -79,7 +82,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* Constructor for AbilityMana.
*
- *
+ *
* @param sourceCard
* a {@link forge.game.card.Card} object.
*/
@@ -112,7 +115,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* produceMana.
*
- *
+ *
* @param produced
* a {@link java.lang.String} object.
* @param player
@@ -170,7 +173,7 @@ public class AbilityManaPart implements java.io.Serializable {
* cannotCounterPaidWith.
*
* @param saBeingPaid
- *
+ *
* @return a {@link java.lang.String} object.
*/
public boolean cannotCounterPaidWith(SpellAbility saBeingPaid) {
@@ -187,7 +190,7 @@ public class AbilityManaPart implements java.io.Serializable {
* addKeywords.
*
* @param saBeingPaid
- *
+ *
* @return a {@link java.lang.String} object.
*/
public boolean addKeywords(SpellAbility saBeingPaid) {
@@ -206,7 +209,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* getKeywords.
*
- *
+ *
* @return a {@link java.lang.String} object.
*/
public String getKeywords() {
@@ -218,7 +221,7 @@ public class AbilityManaPart implements java.io.Serializable {
* addsCounters.
*
* @param saBeingPaid
- *
+ *
* @return a {@link java.lang.String} object.
*/
public boolean addsCounters(SpellAbility saBeingPaid) {
@@ -228,10 +231,26 @@ public class AbilityManaPart implements java.io.Serializable {
/**
* createETBCounters
*/
- public void createETBCounters(Card c) {
+ public void createETBCounters(Card c, Player controller) {
String[] parse = this.addsCounters.split("_");
// Convert random SVars if there are other cards with this effect
if (c.isValid(parse[0], c.getController(), c, null)) {
+ final Game game = this.sourceCard.getGame();
+ final Card eff = new Card(game.nextCardId(), game);
+ eff.setTimestamp(game.getNextTimestamp());
+ eff.setName(sourceCard.getName() + "'s Effect");
+ eff.addType("Effect");
+ eff.setToken(true); // Set token to true, so when leaving play it gets nuked
+ eff.setOwner(controller);
+
+ eff.setImageKey(sourceCard.getImageKey());
+ eff.setColor(MagicColor.COLORLESS);
+ eff.setImmutable(true);
+ // try to get the SpellAbility from the mana ability
+ //eff.setEffectSource((SpellAbility)null);
+
+ eff.addRemembered(c);
+
String abStr = "DB$ PutCounter | Defined$ ReplacedCard | CounterType$ " + parse[1]
+ " | ETB$ True | CounterNum$ " + parse[2];
@@ -241,15 +260,37 @@ public class AbilityManaPart implements java.io.Serializable {
}
CardFactoryUtil.setupETBReplacementAbility(sa);
- String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield "
- + " | Secondary$ True | Description$ CARDNAME"
- + " enters the battlefield with " + CounterType.valueOf(parse[1]).getName() + " counters.";
+ String desc = "It enters the battlefield with ";
+ desc += Lang.nounWithNumeral(parse[2], CounterType.valueOf(parse[1]).getName() + " counter");
+ desc += " on it.";
- ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, c, false);
+ String repeffstr = "Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | Description$ " + desc;
+
+ ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true);
re.setLayer(ReplacementLayer.Other);
re.setOverridingAbility(sa);
- c.addChangedCardTraits(null, null, null, ImmutableList.of(re), null, false, false, false, sa.getHostCard().getGame().getNextTimestamp());
+ eff.addReplacementEffect(re);
+
+ // Forgot Trigger
+ String trig = "Mode$ ChangesZone | ValidCard$ Card.IsRemembered | Origin$ Stack | Destination$ Any | TriggerZones$ Command | Static$ True";
+ String forgetEffect = "DB$ Pump | ForgetObjects$ TriggeredCard";
+ String exileEffect = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile"
+ + " | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0";
+
+ SpellAbility saForget = AbilityFactory.getAbility(forgetEffect, eff);
+ AbilitySub saExile = (AbilitySub) AbilityFactory.getAbility(exileEffect, eff);
+ saForget.setSubAbility(saExile);
+
+ final Trigger parsedTrigger = TriggerHandler.parseTrigger(trig, eff, true);
+ parsedTrigger.setOverridingAbility(saForget);
+ eff.addTrigger(parsedTrigger);
+ eff.updateStateForView();
+
+ // TODO: Add targeting to the effect so it knows who it's dealing with
+ game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
+ game.getAction().moveTo(ZoneType.Command, eff, null);
+ game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
}
}
@@ -270,7 +311,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* getManaRestrictions.
*
- *
+ *
* @return a {@link java.lang.String} object.
*/
public String getManaRestrictions() {
@@ -281,7 +322,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* meetsManaRestrictions.
*
- *
+ *
* @param sa
* a {@link forge.game.spellability.SpellAbility} object.
* @return a boolean.
@@ -297,7 +338,7 @@ public class AbilityManaPart implements java.io.Serializable {
if (restriction.equals("nonSpell")) {
return !sa.isSpell();
}
-
+
if (restriction.equals("CumulativeUpkeep")) {
if (sa.isCumulativeupkeep()) {
return true;
@@ -350,7 +391,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* mana.
*
- *
+ *
* @return a {@link java.lang.String} object.
*/
public final String mana() {
@@ -439,7 +480,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* canProduce.
*
- *
+ *
* @param s
* a {@link java.lang.String} object.
* @return a boolean.
@@ -469,7 +510,7 @@ public class AbilityManaPart implements java.io.Serializable {
*
* isBasic.
*
- *
+ *
* @return a boolean.
*/
public final boolean isBasic() {
@@ -542,7 +583,7 @@ public class AbilityManaPart implements java.io.Serializable {
public Card getSourceCard() {
return sourceCard;
}
-
+
public void setSourceCard(final Card host) {
sourceCard = host;
}