Skip to content

Commit

Permalink
refactor: clean up triggered abilities from graveyard (#13044)
Browse files Browse the repository at this point in the history
* some improvements to counter removing triggers

* fix Zone.GRAVEYARD text/conditions for beginning of upkeep triggers

* remaining refactors

* add condition text

* text corrections

* remove remaining generateZoneString

* remove superfluous hardcoded rules text param
  • Loading branch information
xenohedron authored Oct 27, 2024
1 parent 90623b6 commit aa7a610
Show file tree
Hide file tree
Showing 49 changed files with 331 additions and 737 deletions.
2 changes: 1 addition & 1 deletion Mage.Sets/src/mage/cards/a/AbandonedSarcophagus.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class AbandonedSarcophagusReplacementEffect extends ReplacementEffectImpl {

AbandonedSarcophagusReplacementEffect() {
super(Duration.WhileOnBattlefield, Outcome.Exile);
staticText = "If a card with cycling would be put into your graveyard from anywhere and it wasn't cycled, exile it instead";
staticText = "If a card that has a cycling ability would be put into your graveyard from anywhere and it wasn't cycled, exile it instead";
}

private AbandonedSarcophagusReplacementEffect(final AbandonedSarcophagusReplacementEffect effect) {
Expand Down
18 changes: 6 additions & 12 deletions Mage.Sets/src/mage/cards/a/AkutaBornOfAsh.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@

package mage.cards.a;

import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.common.MoreCardsInHandThanOpponentsCondition;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToBattlefieldEffect;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledPermanent;
import mage.target.common.TargetControlledPermanent;

import java.util.UUID;

/**
*
Expand All @@ -38,14 +35,11 @@ public AkutaBornOfAsh(UUID ownerId, CardSetInfo setInfo) {

// Haste
this.addAbility(HasteAbility.getInstance());

// At the beginning of your upkeep, if you have more cards in hand than each opponent, you may sacrifice a Swamp. If you do, return Akuta, Born of Ash from your graveyard to the battlefield.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD,
new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new SacrificeTargetCost(filterSwamp)),
TargetController.YOU, false),
MoreCardsInHandThanOpponentsCondition.instance,
"At the beginning of your upkeep, if you have more cards in hand than each opponent, you may sacrifice a Swamp. If you do, return {this} from your graveyard to the battlefield.");
this.addAbility(ability);
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD,
new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), new SacrificeTargetCost(filterSwamp)),
TargetController.YOU, false).withInterveningIf(MoreCardsInHandThanOpponentsCondition.instance));
}

private AkutaBornOfAsh(final AkutaBornOfAsh card) {
Expand Down
17 changes: 7 additions & 10 deletions Mage.Sets/src/mage/cards/a/ArahboRoarOfTheWorld.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

package mage.cards.a;

import mage.MageInt;
Expand All @@ -7,7 +6,6 @@
import mage.abilities.common.BeginningOfCombatTriggeredAbility;
import mage.abilities.condition.common.SourceOnBattlefieldOrCommandZoneCondition;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
Expand Down Expand Up @@ -54,19 +52,18 @@ public ArahboRoarOfTheWorld(UUID ownerId, CardSetInfo setInfo) {
this.toughness = new MageInt(5);

// Eminence — At the beginning of combat on your turn, if Arahbo, Roar of the World is in the command zone or on the battlefield, another target Cat you control gets +3/+3 until end of turn.
Ability ability = new ConditionalInterveningIfTriggeredAbility(
new BeginningOfCombatTriggeredAbility(Zone.ALL, new BoostTargetEffect(3, 3, Duration.EndOfTurn), TargetController.YOU, false, false),
SourceOnBattlefieldOrCommandZoneCondition.instance,
"At the beginning of combat on your turn, if {this} is in the command zone or on the battlefield, another target Cat you control gets +3/+3 until end of turn.");
Ability ability = new BeginningOfCombatTriggeredAbility(Zone.ALL,
new BoostTargetEffect(3, 3, Duration.EndOfTurn),
TargetController.YOU, false, false).withInterveningIf(
SourceOnBattlefieldOrCommandZoneCondition.instance);
ability.addTarget(new TargetCreaturePermanent(filter));
ability.setAbilityWord(AbilityWord.EMINENCE);
this.addAbility(ability);

// Whenever another Cat you control attacks, you may pay {1}{G}{W}. If you do, it gains trample and gets +X/+X until end of turn, where X is its power.
// Effect effect = new DoIfCostPaid(new ArahboEffect(), new ManaCostsImpl<>("{1}{G}{W}"));
ability = new AttacksCreatureYouControlTriggeredAbility(
new DoIfCostPaid(new ArahboEffect(), new ManaCostsImpl<>("{1}{G}{W}")), false, filter2, true);
this.addAbility(ability);
this.addAbility(new AttacksCreatureYouControlTriggeredAbility(new DoIfCostPaid(
new ArahboEffect(), new ManaCostsImpl<>("{1}{G}{W}")
), false, filter2, true));
}

private ArahboRoarOfTheWorld(final ArahboRoarOfTheWorld card) {
Expand Down
9 changes: 3 additions & 6 deletions Mage.Sets/src/mage/cards/a/ArdenAngel.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.condition.common.SourceInGraveyardCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
Expand Down Expand Up @@ -32,11 +31,8 @@ public ArdenAngel(UUID ownerId, CardSetInfo setInfo) {
this.addAbility(FlyingAbility.getInstance());

// At the beginning of your upkeep, if Arden Angel is in your graveyard, roll a four-sided die. If the result is 1, return Arden Angel from your graveyard to the battlefield.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(
new BeginningOfUpkeepTriggeredAbility(new ArdenAngelEffect(), TargetController.YOU, false),
SourceInGraveyardCondition.instance, "At the beginning of your upkeep, if {this} is in your graveyard, " +
"roll a four-sided die. If the result is 1, return {this} from your graveyard to the battlefield."
));
this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD, new ArdenAngelEffect(), TargetController.YOU, false)
.withInterveningIf(SourceInGraveyardCondition.instance));
}

private ArdenAngel(final ArdenAngel card) {
Expand All @@ -53,6 +49,7 @@ class ArdenAngelEffect extends OneShotEffect {

ArdenAngelEffect() {
super(Outcome.Benefit);
this.staticText = "roll a four-sided die. If the result is 1, return {this} from your graveyard to the battlefield";
}

private ArdenAngelEffect(final ArdenAngelEffect effect) {
Expand Down
68 changes: 18 additions & 50 deletions Mage.Sets/src/mage/cards/a/AuntiesSnitch.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@

package mage.cards.a;

import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.CantBlockAbility;
import mage.abilities.effects.common.ReturnToHandSourceEffect;
import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility;
import mage.abilities.condition.common.SourceInGraveyardCondition;
import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect;
import mage.abilities.keyword.ProwlAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.game.events.DamagedPlayerEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;

import java.util.UUID;

/**
*
* @author LevelX2
*/
public final class AuntiesSnitch extends CardImpl {

private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Goblin or Rogue you control");
static {
filter.add(Predicates.or(SubType.GOBLIN.getPredicate(), SubType.ROGUE.getPredicate()));
}

public AuntiesSnitch(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{B}");
this.subtype.add(SubType.GOBLIN);
Expand All @@ -36,10 +38,15 @@ public AuntiesSnitch(UUID ownerId, CardSetInfo setInfo) {

// Auntie's Snitch can't block.
this.addAbility(new CantBlockAbility());

// Prowl {1}{B}
this.addAbility(new ProwlAbility("{1}{B}"));

// Whenever a Goblin or Rogue you control deals combat damage to a player, if Auntie's Snitch is in your graveyard, you may return Auntie's Snitch to your hand.
this.addAbility(new AuntiesSnitchTriggeredAbility());
this.addAbility(new DealsDamageToAPlayerAllTriggeredAbility(Zone.GRAVEYARD,
new ReturnSourceFromGraveyardToHandEffect().setText("return {this} to your hand"),
filter, true, SetTargetPointer.NONE, true, false
).withInterveningIf(SourceInGraveyardCondition.instance));
}

private AuntiesSnitch(final AuntiesSnitch card) {
Expand All @@ -51,42 +58,3 @@ public AuntiesSnitch copy() {
return new AuntiesSnitch(this);
}
}

class AuntiesSnitchTriggeredAbility extends TriggeredAbilityImpl {

private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Goblin or Rogue you control");
static {
filter.add(TargetController.YOU.getControllerPredicate());
filter.add(Predicates.or(SubType.GOBLIN.getPredicate(), SubType.ROGUE.getPredicate()));
}

public AuntiesSnitchTriggeredAbility() {
super(Zone.GRAVEYARD, new ReturnToHandSourceEffect(), true);
}

private AuntiesSnitchTriggeredAbility(final AuntiesSnitchTriggeredAbility ability) {
super(ability);
}

@Override
public AuntiesSnitchTriggeredAbility copy() {
return new AuntiesSnitchTriggeredAbility(this);
}

@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DAMAGED_PLAYER;
}

@Override
public boolean checkTrigger(GameEvent event, Game game) {
DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event;
Permanent p = game.getPermanent(event.getSourceId());
return damageEvent.isCombatDamage() && filter.match(p, getControllerId(), this, game);
}

@Override
public String getRule() {
return "Whenever a Goblin or Rogue you control deals combat damage to a player, if {this} is in your graveyard, you may return {this} to your hand.";
}
}
43 changes: 5 additions & 38 deletions Mage.Sets/src/mage/cards/b/BarbedWire.java
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
package mage.cards.b;

import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.PreventionEffectImpl;
import mage.abilities.effects.common.DamageTargetEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.players.Player;

import java.util.UUID;

/**
*
* @author jeffwadsworth
*/
public final class BarbedWire extends CardImpl {

private static final String rule = "At the beginning of each player's upkeep, "
+ "Barbed Wire deals 1 damage to that player.";

public BarbedWire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");

// At the beginning of each player's upkeep, Barbed Wire deals 1 damage to that player.
this.addAbility(new BeginningOfUpkeepTriggeredAbility(
Zone.BATTLEFIELD,
new BarbwireDamageEffect(),
new DamageTargetEffect(1).withTargetDescription("that player"),
TargetController.ACTIVE,
false, true, rule));
false, true));

// {2}: Prevent the next 1 damage that would be dealt by Barbed Wire this turn.
this.addAbility(new SimpleActivatedAbility(
Expand All @@ -53,34 +48,6 @@ public BarbedWire copy() {
}
}

class BarbwireDamageEffect extends OneShotEffect {

BarbwireDamageEffect() {
super(Outcome.Damage);
this.staticText = "";
}

private BarbwireDamageEffect(final BarbwireDamageEffect effect) {
super(effect);
}

@Override
public BarbwireDamageEffect copy() {
return new BarbwireDamageEffect(this);
}

@Override
public boolean apply(Game game, Ability source) {
Player activePlayer = game.getPlayer(getTargetPointer().getFirst(game, source));
if (activePlayer != null) {
activePlayer.damage(1, source.getSourceId(), source, game);
return true;
}

return false;
}
}

class BarbedWirePreventionEffect extends PreventionEffectImpl {

BarbedWirePreventionEffect() {
Expand Down
3 changes: 2 additions & 1 deletion Mage.Sets/src/mage/cards/b/BloodOperative.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SurveilTriggeredAbility;
import mage.abilities.condition.common.SourceInGraveyardCondition;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.ExileTargetEffect;
Expand Down Expand Up @@ -42,7 +43,7 @@ public BloodOperative(UUID ownerId, CardSetInfo setInfo) {
// Whenever you surveil, if Blood Operative is in your graveyard, you may pay 3 life. If you do, return Blood Operative to your hand.
this.addAbility(new SurveilTriggeredAbility(Zone.GRAVEYARD, new DoIfCostPaid(
new ReturnSourceFromGraveyardToHandEffect().setText("return {this} to your hand"), new PayLifeCost(3)
)));
)).withInterveningIf(SourceInGraveyardCondition.instance));
}

private BloodOperative(final BloodOperative card) {
Expand Down
28 changes: 9 additions & 19 deletions Mage.Sets/src/mage/cards/b/BridgeFromBelow.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mage.cards.b;

import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.condition.common.SourceInGraveyardCondition;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.ExileSourceEffect;
Expand All @@ -17,16 +17,17 @@
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;

import java.util.UUID;

/**
*
* @author Plopman
*/
public final class BridgeFromBelow extends CardImpl {

private static final FilterCreaturePermanent filter1 = new FilterCreaturePermanent("Whenever a nontoken creature is put into your graveyard from the battlefield");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("When a creature is put into an opponent's graveyard from the battlefield");
private static final FilterCreaturePermanent filter1 = new FilterCreaturePermanent("Whenever a nontoken creature is put into your graveyard from the battlefield, ");
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent("When a creature is put into an opponent's graveyard from the battlefield, ");

static {
filter1.add(TargetController.YOU.getOwnerPredicate());
Expand Down Expand Up @@ -59,10 +60,11 @@ class BridgeFromBelowAbility extends TriggeredAbilityImpl {

private final FilterCreaturePermanent filter;

public BridgeFromBelowAbility(Effect effect, FilterCreaturePermanent filter) {
BridgeFromBelowAbility(Effect effect, FilterCreaturePermanent filter) {
super(Zone.GRAVEYARD, effect, false);
this.filter = filter;
setTriggerPhrase(filter.getMessage() + ", if {this} is in your graveyard, ");
this.withInterveningIf(SourceInGraveyardCondition.instance);
setTriggerPhrase(filter.getMessage());
}

private BridgeFromBelowAbility(final BridgeFromBelowAbility ability) {
Expand All @@ -82,23 +84,11 @@ public boolean checkEventType(GameEvent event, Game game) {

@Override
public boolean checkTrigger(GameEvent event, Game game) {
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
if (!zEvent.isDiesEvent()) {
return false;
}

Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
if (permanent == null) {
if (permanent == null || !((ZoneChangeEvent) event).isDiesEvent()) {
return false;
}

return filter.match(permanent, controllerId, this, game);
}

@Override
public boolean checkInterveningIfClause(Game game) {
Player controller = game.getPlayer(this.getControllerId());
return controller != null
&& controller.getGraveyard().contains(this.getSourceId());
}
}
Loading

0 comments on commit aa7a610

Please sign in to comment.