TriggerChangesZone: add NewCard for leave the battlefield trigger

This commit is contained in:
Hans Mackowiak
2020-11-11 04:07:04 +00:00
committed by Michael Kamensky
parent 7b18fc4474
commit f0ed3f095d
132 changed files with 233 additions and 285 deletions

View File

@@ -127,6 +127,13 @@ public class GameAction {
// get the LKI from above like ChangeZoneEffect
if (params != null && params.containsKey(AbilityKey.CardLKI)) {
lastKnownInfo = (Card) params.get(AbilityKey.CardLKI);
} else if (toBattlefield && cause != null && cause.isReplacementAbility()) {
// if to Battlefield and it is caused by an replacement effect,
// try to get previous LKI if able
ReplacementEffect re = cause.getReplacementEffect();
if (ReplacementType.Moved.equals(re.getMode())) {
lastKnownInfo = (Card) cause.getReplacingObject(AbilityKey.CardLKI);
}
}
if (c.isSplitCard()) {
@@ -165,17 +172,6 @@ public class GameAction {
if (suppress || (!fromBattlefield && !toHand)) {
copied = c;
// if to Battlefield and it is caused by an replacement effect,
// try to get previous LKI if able
if (toBattlefield) {
if (cause != null && cause.isReplacementAbility()) {
ReplacementEffect re = cause.getReplacementEffect();
if (ReplacementType.Moved.equals(re.getMode())) {
lastKnownInfo = (Card) cause.getReplacingObject(AbilityKey.CardLKI);
}
}
}
if (lastKnownInfo == null) {
lastKnownInfo = CardUtil.getLKICopy(c);
}

View File

@@ -73,6 +73,7 @@ public enum AbilityKey {
LifeGained("LifeGained"),
Mana("Mana"),
MonstrosityAmount("MonstrosityAmount"),
NewCard("NewCard"),
NewCounterAmount("NewCounterAmount"),
NoPreventDamage("NoPreventDamage"),
Num("Num"), // TODO confirm that this and NumThisTurn can be merged
@@ -94,6 +95,7 @@ public enum AbilityKey {
Prevention("Prevention"),
Produced("Produced"),
Regeneration("Regeneration"),
ReplacementEffect("ReplacementEffect"),
ReplacementResult("ReplacementResult"),
Result("Result"),
Scheme("Scheme"),

View File

@@ -1969,7 +1969,20 @@ public class AbilityUtils {
}
}
}
public static SpellAbility getCause(SpellAbility sa) {
final SpellAbility root = sa.getRootAbility();
SpellAbility cause = sa;
if (root.isReplacementAbility()) {
SpellAbility replacingObject = (SpellAbility) root.getReplacingObject(AbilityKey.Cause);
if (replacingObject != null) {
cause = replacingObject;
}
}
return cause;
}
public static SpellAbility addSpliceEffects(final SpellAbility sa) {
final Card source = sa.getHostCard();
final Player player = sa.getActivatingPlayer();

View File

@@ -21,6 +21,8 @@ import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.player.PlayerCollection;
import forge.game.player.PlayerView;
import forge.game.replacement.ReplacementEffect;
import forge.game.replacement.ReplacementType;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
@@ -430,6 +432,8 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
final Game game = player.getGame();
final CardCollection commandCards = new CardCollection();
SpellAbility cause = AbilityUtils.getCause(sa);
ZoneType destination = ZoneType.smartValueOf(sa.getParam("Destination"));
final List<ZoneType> origin = Lists.newArrayList();
if (sa.hasParam("Origin")) {
@@ -527,7 +531,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
}
movedCard = game.getAction().moveToLibrary(gameCard, libraryPosition, sa);
movedCard = game.getAction().moveToLibrary(gameCard, libraryPosition, cause);
} else {
if (destination.equals(ZoneType.Battlefield)) {
@@ -585,10 +589,19 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
Map<AbilityKey, Object> moveParams = Maps.newEnumMap(AbilityKey.class);
if (sa.isReplacementAbility()) {
ReplacementEffect re = sa.getReplacementEffect();
moveParams.put(AbilityKey.ReplacementEffect, re);
if (ReplacementType.Moved.equals(re.getMode()) && sa.getReplacingObject(AbilityKey.CardLKI) != null) {
moveParams.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
}
}
if (sa.hasAdditionalAbility("AnimateSubAbility")) {
// need LKI before Animate does apply
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(gameCard));
if (!moveParams.containsKey(AbilityKey.CardLKI)) {
moveParams.put(AbilityKey.CardLKI, CardUtil.getLKICopy(gameCard));
}
hostCard.addRemembered(gameCard);
AbilityUtils.resolve(sa.getAdditionalAbility("AnimateSubAbility"));
@@ -610,7 +623,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
}
movedCard = game.getAction().moveTo(gameCard.getController().getZone(destination), gameCard, sa, moveParams);
movedCard = game.getAction().moveTo(gameCard.getController().getZone(destination), gameCard, cause, moveParams);
if (sa.hasParam("Unearth")) {
movedCard.setUnearthed(true);
movedCard.addChangedCardKeywords(Lists.newArrayList("Haste"), null, false, false,
@@ -649,7 +662,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
gameCard.setExiledWith(host);
}
movedCard = game.getAction().moveTo(destination, gameCard, sa);
movedCard = game.getAction().moveTo(destination, gameCard, cause);
if (ZoneType.Hand.equals(destination) && ZoneType.Command.equals(originZone.getZoneType())) {
StringBuilder sb = new StringBuilder();
sb.append(movedCard.getName()).append(" has moved from Command Zone to ").append(player).append("'s hand.");
@@ -782,6 +795,16 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
}
final SpellAbility root = sa.getRootAbility();
SpellAbility cause = sa;
if (root.isReplacementAbility()) {
SpellAbility replacingObject = (SpellAbility) root.getReplacingObject(AbilityKey.Cause);
if (replacingObject != null) {
cause = replacingObject;
}
}
List<ZoneType> origin = Lists.newArrayList();
if (sa.hasParam("Origin")) {
origin = ZoneType.listValueOf(sa.getParam("Origin"));
@@ -1049,7 +1072,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
Card movedCard = null;
final Zone originZone = game.getZoneOf(c);
if (destination.equals(ZoneType.Library)) {
movedCard = game.getAction().moveToLibrary(c, libraryPos, sa);
movedCard = game.getAction().moveToLibrary(c, libraryPos, cause);
}
else if (destination.equals(ZoneType.Battlefield)) {
if (sa.hasParam("Tapped")) {
@@ -1163,7 +1186,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
c.addFaceupCommand(unanimate);
}
}
movedCard = game.getAction().moveTo(c.getController().getZone(destination), c, sa, moveParams);
movedCard = game.getAction().moveTo(c.getController().getZone(destination), c, cause, moveParams);
if (sa.hasParam("Tapped")) {
movedCard.setTapped(true);
}
@@ -1188,7 +1211,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
}
}
else {
movedCard = game.getAction().moveTo(destination, c, sa);
movedCard = game.getAction().moveTo(destination, c, cause);
}
movedCards.add(movedCard);

View File

@@ -1,6 +1,9 @@
package forge.game.ability.effects;
import java.util.Map;
import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.spellability.SpellAbility;
@@ -12,6 +15,10 @@ import forge.game.spellability.SpellAbility;
public class ETBReplacementEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
sa.getActivatingPlayer().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject(AbilityKey.Card)), sa);
final Card card = (Card) sa.getReplacingObject(AbilityKey.Card);
Map<AbilityKey, Object> params = AbilityKey.newMap();
params.put(AbilityKey.CardLKI, sa.getReplacingObject(AbilityKey.CardLKI));
params.put(AbilityKey.ReplacementEffect, sa.getReplacementEffect());
sa.getActivatingPlayer().getGame().getAction().moveToPlay(card, card.getController(), AbilityUtils.getCause(sa), params);
}
}

View File

@@ -19,7 +19,6 @@ package forge.game.ability.effects;
import org.apache.commons.lang3.mutable.MutableBoolean;
import forge.game.ability.AbilityKey;
import forge.game.card.token.TokenInfo;
import forge.game.Game;
@@ -56,7 +55,6 @@ public class TokenEffect extends TokenEffectBase {
public void resolve(SpellAbility sa) {
final Card host = sa.getHostCard();
final Game game = host.getGame();
final SpellAbility root = sa.getRootAbility();
// linked Abilities, if it needs chosen values, but nothing is chosen, no token can be created
if (sa.hasParam("TokenTypes")) {
@@ -72,13 +70,7 @@ public class TokenEffect extends TokenEffectBase {
// Cause of the Token Effect, in general it should be this
// but if its a Replacement Effect, it might be something else or null
SpellAbility cause = sa;
if (root.isReplacementAbility()) {
SpellAbility replacingObject = (SpellAbility) root.getReplacingObject(AbilityKey.Cause);
if (replacingObject != null) {
cause = replacingObject;
}
}
SpellAbility cause = AbilityUtils.getCause(sa);
Card prototype = loadTokenPrototype(sa);

View File

@@ -188,11 +188,6 @@ public class TokenInfo {
return list;
}
@Deprecated
public List<Card> makeTokenWithMultiplier(final Player controller, int amount, final boolean applyMultiplier) {
return makeToken(makeOneToken(controller), controller, applyMultiplier, amount);
}
static public List<Card> makeTokensFromPrototype(Card prototype, final Player owner, int amount, final boolean applyMultiplier) {
return makeToken(prototype, owner, applyMultiplier, amount);
}

View File

@@ -177,7 +177,7 @@ public class CostPutCounter extends CostPartWithList {
@Override
protected Card doPayment(SpellAbility ability, Card targetCard){
final Integer i = this.convertAmount();
targetCard.addCounter(this.getCounter(), i, ability.getActivatingPlayer(), false, counterTable);
targetCard.addCounter(this.getCounter(), i, ability.getActivatingPlayer(), ability.getRootAbility().isTrigger(), counterTable);
return targetCard;
}

View File

@@ -70,13 +70,12 @@ public class ReplacementHandler {
if (ReplacementType.Moved.equals(event) && ZoneType.Battlefield.equals(runParams.get(AbilityKey.Destination))) {
// if it was caused by an replacement effect, use the already calculated RE list
// otherwise the RIOT card would cause a StackError
SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
if (cause != null && cause.isReplacementAbility()) {
final ReplacementEffect re = cause.getReplacementEffect();
final ReplacementEffect causeRE = (ReplacementEffect) runParams.get(AbilityKey.ReplacementEffect);
if (causeRE != null) {
// only return for same layer
if (ReplacementType.Moved.equals(re.getMode()) && layer.equals(re.getLayer())) {
if (!re.getOtherChoices().isEmpty())
return re.getOtherChoices();
if (ReplacementType.Moved.equals(causeRE.getMode()) && layer.equals(causeRE.getLayer())) {
if (!causeRE.getOtherChoices().isEmpty())
return causeRE.getOtherChoices();
}
}

View File

@@ -109,7 +109,7 @@ public class TriggerChangesZone extends Trigger {
}
if (hasParam("ValidCause")) {
if (!runParams.containsKey(AbilityKey.Cause) ) {
if (!runParams.containsKey(AbilityKey.Cause)) {
return false;
}
SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
@@ -159,6 +159,15 @@ public class TriggerChangesZone extends Trigger {
}
}
if (hasParam("NotThisAbility")) {
if (runParams.containsKey(AbilityKey.Cause)) {
SpellAbility cause = (SpellAbility) runParams.get(AbilityKey.Cause);
if (cause != null && this.equals(cause.getRootAbility().getTrigger())) {
return false;
}
}
}
/* this trigger can only be activated once per turn, verify it hasn't already run */
if (hasParam("ActivationLimit")) {
return this.getActivationsThisTurn() < Integer.parseInt(getParam("ActivationLimit"));
@@ -170,8 +179,10 @@ public class TriggerChangesZone extends Trigger {
/** {@inheritDoc} */
@Override
public final void setTriggeringObjects(final SpellAbility sa, Map<AbilityKey, Object> runParams) {
// TODO use better way to always copy both Card and CardLKI
if ("Battlefield".equals(getParam("Origin"))) {
sa.setTriggeringObject(AbilityKey.Card, runParams.get(AbilityKey.CardLKI));
sa.setTriggeringObject(AbilityKey.NewCard, runParams.get(AbilityKey.Card));
} else {
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card);
}