cleanup EntersBattlefieldAllTriggeredAbility and subclasses (#11372)

* comment out rule override to use generated text instead

* new ETB Opponent trigger class

* text improvements

* update ETB cast trigger

* remove controlledtext parameter

* more text improvements

* more fixes

* lots of other fixes

* most of the remaining fixes

* fix halana text

* fix smoke shroud text

* improve text gen

* remove rule param from constructors

* minor adjustments

* whenever a player puts

* final fixes

* standardize when/whenever phrase generation
This commit is contained in:
xenohedron 2023-10-31 21:00:45 -04:00 committed by GitHub
parent c53db0810d
commit ebf71941a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
161 changed files with 504 additions and 839 deletions

View file

@ -2,7 +2,7 @@ package mage.abilities;
import mage.MageObject;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.*;
import mage.constants.AbilityType;
import mage.constants.AbilityWord;
import mage.constants.Zone;
@ -257,6 +257,19 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|| ruleLow.startsWith("untap");
}
/**
* For use in generating trigger phrases with correct text
* @return "When " for an effect that always removes the source from the battlefield, otherwise "Whenever "
*/
protected final String getWhen() {
return (!optional && getAllEffects().stream().anyMatch(
effect -> effect instanceof SacrificeSourceEffect
|| effect instanceof ReturnToHandSourceEffect
|| effect instanceof ShuffleIntoLibrarySourceEffect
|| effect instanceof ExileSourceEffect
) ? "When " : "Whenever ");
}
@Override
public boolean isInUseableZone(Game game, MageObject source, GameEvent event) {

View file

@ -2,10 +2,6 @@ package mage.abilities.common;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ExileSourceEffect;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.effects.common.SacrificeSourceEffect;
import mage.abilities.effects.common.ShuffleIntoLibrarySourceEffect;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.FilterStackObject;
@ -36,11 +32,7 @@ public class BecomesTargetSourceTriggeredAbility extends TriggeredAbilityImpl {
super(Zone.BATTLEFIELD, effect, optional);
this.filter = filter;
this.setTargetPointer = setTargetPointer;
boolean textWhen = !optional && (effect instanceof SacrificeSourceEffect
|| effect instanceof ReturnToHandSourceEffect
|| effect instanceof ShuffleIntoLibrarySourceEffect
|| effect instanceof ExileSourceEffect);
setTriggerPhrase((textWhen ? "When" : "Whenever") + " {this} becomes the target of " + filter.getMessage() + ", ");
setTriggerPhrase(getWhen() + "{this} becomes the target of " + filter.getMessage() + ", ");
this.replaceRuleText = true; // default true to replace "{this}" with "it"
}

View file

@ -9,8 +9,7 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
import mage.util.CardUtil;
/**
* @author LevelX2
@ -18,54 +17,29 @@ import java.util.UUID;
public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
protected FilterPermanent filter;
protected String rule;
protected boolean controlledText;
protected SetTargetPointer setTargetPointer;
/**
* zone = BATTLEFIELD optional = false
*
* @param effect
* @param filter
*/
public EntersBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter) {
this(Zone.BATTLEFIELD, effect, filter, false);
}
public EntersBattlefieldAllTriggeredAbility(Effect effect, FilterPermanent filter, String rule) {
this(Zone.BATTLEFIELD, effect, filter, false, rule);
}
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional) {
this(zone, effect, filter, optional, SetTargetPointer.NONE, null, false);
this(zone, effect, filter, optional, SetTargetPointer.NONE);
}
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule) {
this(zone, effect, filter, optional, rule, false);
}
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule, boolean controlledText) {
this(zone, effect, filter, optional, SetTargetPointer.NONE, rule, controlledText);
}
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule) {
this(zone, effect, filter, optional, setTargetPointer, rule, false);
}
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule, boolean controlledText) {
public EntersBattlefieldAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer) {
super(zone, effect, optional);
this.filter = filter;
this.rule = rule;
this.controlledText = controlledText;
this.setTargetPointer = setTargetPointer;
setTriggerPhrase(generateTriggerPhrase());
setTriggerPhrase(getTriggerPhraseFromFilter() + ", ");
}
protected EntersBattlefieldAllTriggeredAbility(final EntersBattlefieldAllTriggeredAbility ability) {
super(ability);
this.filter = ability.filter;
this.rule = ability.rule;
this.controlledText = ability.controlledText;
this.setTargetPointer = ability.setTargetPointer;
}
@ -76,8 +50,7 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
UUID targetId = event.getTargetId();
Permanent permanent = game.getPermanent(targetId);
Permanent permanent = game.getPermanent(event.getTargetId());
if (!filter.match(permanent, getControllerId(), this, game)) {
return false;
}
@ -95,28 +68,12 @@ public class EntersBattlefieldAllTriggeredAbility extends TriggeredAbilityImpl {
return true;
}
@Override
public String getRule() {
if (rule != null && !rule.isEmpty()) {
return rule;
protected final String getTriggerPhraseFromFilter() {
String filterMessage = filter.getMessage();
if (filterMessage.startsWith("one or more")) {
return getWhen() + filterMessage + " enter the battlefield";
}
return super.getRule();
}
protected String generateTriggerPhrase() {
StringBuilder sb = new StringBuilder("Whenever ");
sb.append(filter.getMessage());
if (filter.getMessage().startsWith("one or more")) {
sb.append(" enter the battlefield");
} else {
sb.append(" enters the battlefield");
}
if (controlledText) {
sb.append(" under your control, ");
} else {
sb.append(", ");
}
return sb.toString();
return getWhen() + CardUtil.addArticle(filterMessage) + " enters the battlefield";
}
@Override

View file

@ -1,7 +1,5 @@
package mage.abilities.common;
import java.util.UUID;
import mage.abilities.effects.Effect;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
@ -12,82 +10,31 @@ import mage.watchers.common.PermanentWasCastWatcher;
/**
* An extension of triggered abilities that trigger when permanents enter the
* battlefield, but this time they either must be cast or must not be cast.
* battlefield under your control, but this time they either must be cast or must not be cast.
*
* @author alexander-novo
*/
public class EntersBattlefieldCastTriggeredAbility extends EntersBattlefieldAllTriggeredAbility {
public class EntersBattlefieldCastTriggeredAbility extends EntersBattlefieldControlledTriggeredAbility {
private final boolean mustCast;
/**
* zone = BATTLEFIELD optional = false
*
* @param effect
* @param filter
*/
public EntersBattlefieldCastTriggeredAbility(Effect effect, FilterPermanent filter, boolean mustCast) {
this(Zone.BATTLEFIELD, effect, filter, mustCast, false);
}
public EntersBattlefieldCastTriggeredAbility(Effect effect, FilterPermanent filter, boolean mustCast, String rule) {
this(Zone.BATTLEFIELD, effect, filter, mustCast, false, rule);
}
public EntersBattlefieldCastTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean mustCast,
boolean optional) {
this(zone, effect, filter, mustCast, optional, SetTargetPointer.NONE, null, false);
}
public EntersBattlefieldCastTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean mustCast,
boolean optional,
String rule) {
this(zone, effect, filter, mustCast, optional, rule, false);
}
public EntersBattlefieldCastTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean mustCast,
boolean optional,
String rule, boolean controlledText) {
this(zone, effect, filter, mustCast, optional, SetTargetPointer.NONE, rule, controlledText);
}
public EntersBattlefieldCastTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean mustCast,
boolean optional,
SetTargetPointer setTargetPointer, String rule) {
this(zone, effect, filter, mustCast, optional, setTargetPointer, rule, false);
}
public EntersBattlefieldCastTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean mustCast,
boolean optional,
SetTargetPointer setTargetPointer, String rule, boolean controlledText) {
super(zone, effect, filter, optional, setTargetPointer, rule, controlledText);
public EntersBattlefieldCastTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional,
SetTargetPointer setTargetPointer, boolean mustCast) {
super(zone, effect, filter, optional, setTargetPointer);
this.mustCast = mustCast;
this.addWatcher(new PermanentWasCastWatcher());
StringBuilder triggerPhrase = new StringBuilder(this.generateTriggerPhrase());
if (mustCast) {
triggerPhrase.append("if it was cast, ");
} else {
triggerPhrase.append("if it wasn't cast, ");
}
this.setTriggerPhrase(triggerPhrase.toString());
setTriggerPhrase(getTriggerPhraseFromFilter() + " under your control, if it " + (mustCast ? "was" : "wasn't") + " cast, " );
}
protected EntersBattlefieldCastTriggeredAbility(final EntersBattlefieldCastTriggeredAbility ability) {
super(ability);
this.mustCast = ability.mustCast;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!super.checkTrigger(event, game))
return false;
PermanentWasCastWatcher watcher = game.getState().getWatcher(PermanentWasCastWatcher.class);
UUID targetId = event.getTargetId();
return watcher.wasPermanentCastThisTurn(targetId) == this.mustCast;
return watcher != null && watcher.wasPermanentCastThisTurn(event.getTargetId()) == this.mustCast
&& super.checkTrigger(event, game);
}
@Override

View file

@ -1,5 +1,3 @@
package mage.abilities.common;
import mage.abilities.effects.Effect;
@ -17,32 +15,19 @@ import mage.game.permanent.Permanent;
public class EntersBattlefieldControlledTriggeredAbility extends EntersBattlefieldAllTriggeredAbility {
/**
* zone = BATTLEFIELD
* optional = false
* rule = null
*
* @param effect
* @param filter
* zone = BATTLEFIELD, optional = false
*/
public EntersBattlefieldControlledTriggeredAbility(Effect effect, FilterPermanent filter) {
this(Zone.BATTLEFIELD, effect, filter, false);
}
public EntersBattlefieldControlledTriggeredAbility(Effect effect, FilterPermanent filter, String rule) {
this(Zone.BATTLEFIELD, effect, filter, false, rule);
}
public EntersBattlefieldControlledTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional) {
this(zone, effect, filter, optional, null);
this.filter = filter;
this(zone, effect, filter, optional, SetTargetPointer.NONE);
}
public EntersBattlefieldControlledTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, String rule) {
this(zone, effect, filter, optional, SetTargetPointer.NONE, rule);
}
public EntersBattlefieldControlledTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, String rule) {
super(zone, effect, filter, optional, setTargetPointer, rule, true);
public EntersBattlefieldControlledTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer) {
super(zone, effect, filter, optional, setTargetPointer);
setTriggerPhrase(getTriggerPhraseFromFilter() + " under your control, ");
}
protected EntersBattlefieldControlledTriggeredAbility(final EntersBattlefieldControlledTriggeredAbility ability) {

View file

@ -0,0 +1,42 @@
package mage.abilities.common;
import mage.abilities.effects.Effect;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
/**
* @author xenohedron
*/
public class EntersBattlefieldOpponentTriggeredAbility extends EntersBattlefieldAllTriggeredAbility {
public EntersBattlefieldOpponentTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional) {
this(Zone.BATTLEFIELD, effect, filter, optional, SetTargetPointer.NONE);
}
public EntersBattlefieldOpponentTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer) {
super(zone, effect, filter, optional, setTargetPointer);
setTriggerPhrase(getTriggerPhraseFromFilter() + " under an opponent's control, ");
}
protected EntersBattlefieldOpponentTriggeredAbility(final EntersBattlefieldOpponentTriggeredAbility ability) {
super(ability);
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
Permanent permanent = game.getPermanent(event.getTargetId());
if (permanent == null || !game.getOpponents(this.getControllerId()).contains(permanent.getControllerId())) {
return false;
}
return super.checkTrigger(event, game);
}
@Override
public EntersBattlefieldOpponentTriggeredAbility copy() {
return new EntersBattlefieldOpponentTriggeredAbility(this);
}
}

View file

@ -11,22 +11,13 @@ import mage.filter.FilterPermanentThisOrAnother;
*/
public class EntersBattlefieldThisOrAnotherTriggeredAbility extends EntersBattlefieldAllTriggeredAbility {
public EntersBattlefieldThisOrAnotherTriggeredAbility(Effect effect, FilterPermanent filter) {
this(effect, filter, false, false);
}
public EntersBattlefieldThisOrAnotherTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, boolean onlyControlled) {
this(effect, filter, optional, SetTargetPointer.NONE, onlyControlled);
}
public EntersBattlefieldThisOrAnotherTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyControlled) {
this(Zone.BATTLEFIELD, effect, filter, optional, setTargetPointer, onlyControlled);
}
public EntersBattlefieldThisOrAnotherTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyControlled) {
super(zone, effect,
new FilterPermanentThisOrAnother(filter, onlyControlled),
optional, setTargetPointer, null, onlyControlled);
super(Zone.BATTLEFIELD, effect, new FilterPermanentThisOrAnother(filter, onlyControlled), optional, setTargetPointer);
setTriggerPhrase("Whenever " + this.filter.getMessage() + " enters the battlefield" + (onlyControlled ? " under your control, " : ", "));
}
private EntersBattlefieldThisOrAnotherTriggeredAbility(final EntersBattlefieldThisOrAnotherTriggeredAbility ability) {
@ -37,4 +28,4 @@ public class EntersBattlefieldThisOrAnotherTriggeredAbility extends EntersBattle
public EntersBattlefieldThisOrAnotherTriggeredAbility copy() {
return new EntersBattlefieldThisOrAnotherTriggeredAbility(this);
}
}
}

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
@ -60,10 +59,10 @@ public class ReturnToHandChosenPermanentEffect extends OneShotEffect {
protected String getText() {
StringBuilder sb = new StringBuilder("that player returns ");
if (!filter.getMessage().startsWith("another")) {
sb.append(CardUtil.numberToText(number, "a"));
if (!filter.getMessage().startsWith("another") && !filter.getMessage().startsWith("a ")) {
sb.append(CardUtil.numberToText(number, "a")).append(' ');
}
sb.append(' ').append(filter.getMessage());
sb.append(filter.getMessage());
sb.append(" they control");
if (number > 1) {
sb.append(" to their owner's hand");

View file

@ -175,7 +175,7 @@ class SoulbondEntersOtherAbility extends EntersBattlefieldAllTriggeredAbility {
}
public SoulbondEntersOtherAbility() {
super(Zone.BATTLEFIELD, new SoulboundEntersOtherEffect(), soulbondFilter, true, SetTargetPointer.PERMANENT, "");
super(Zone.BATTLEFIELD, new SoulboundEntersOtherEffect(), soulbondFilter, true, SetTargetPointer.PERMANENT);
setRuleVisible(false);
}

View file

@ -6,7 +6,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.command.Emblem;
import mage.game.permanent.Permanent;
@ -17,14 +17,11 @@ import mage.target.common.TargetCreaturePermanent;
*/
public final class KioraMasterOfTheDepthsEmblem extends Emblem {
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures");
public KioraMasterOfTheDepthsEmblem() {
super("Emblem Kiora");
Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.COMMAND,
new KioraFightEffect(), filter, true, SetTargetPointer.PERMANENT,
"Whenever a creature enters the battlefield under your control, you may have it fight target creature.");
new KioraFightEffect(), StaticFilters.FILTER_PERMANENT_A_CREATURE, true, SetTargetPointer.PERMANENT);
ability.addTarget(new TargetCreaturePermanent());
this.getAbilities().add(ability);
}
@ -43,6 +40,7 @@ class KioraFightEffect extends OneShotEffect {
KioraFightEffect() {
super(Outcome.Damage);
staticText = "you may have it fight target creature";
}
KioraFightEffect(final KioraFightEffect effect) {

View file

@ -1,10 +1,10 @@
package mage.game.command.emblems;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.constants.Zone;
import mage.filter.common.FilterControlledLandPermanent;
import mage.filter.StaticFilters;
import mage.game.command.Emblem;
/**
@ -15,8 +15,8 @@ public final class NissaVitalForceEmblem extends Emblem {
public NissaVitalForceEmblem() {
super("Emblem Nissa");
Ability ability = new EntersBattlefieldAllTriggeredAbility(Zone.COMMAND, new DrawCardSourceControllerEffect(1), new FilterControlledLandPermanent("a land"),
true, null, true);
Ability ability = new EntersBattlefieldControlledTriggeredAbility(Zone.COMMAND,
new DrawCardSourceControllerEffect(1), StaticFilters.FILTER_LAND_A, true);
getAbilities().add(ability);
}