mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 13:19:18 -08:00
refactor: clean up triggered abilities from graveyard (#13044)
* 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
This commit is contained in:
parent
90623b6a0e
commit
aa7a610db2
49 changed files with 331 additions and 737 deletions
|
|
@ -78,21 +78,15 @@ public class BeginningOfCombatTriggeredAbility extends TriggeredAbilityImpl {
|
|||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of combat on your turn, " + generateZoneString();
|
||||
return "At the beginning of combat on your turn, ";
|
||||
case OPPONENT:
|
||||
return "At the beginning of combat on each opponent's turn, " + generateZoneString();
|
||||
return "At the beginning of combat on each opponent's turn, ";
|
||||
case EACH_PLAYER:
|
||||
return "At the beginning of combat on each player's turn, " + generateZoneString();
|
||||
return "At the beginning of combat on each player's turn, ";
|
||||
case ANY:
|
||||
return "At the beginning of each combat, " + generateZoneString();
|
||||
return "At the beginning of each combat, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
if (getZone() == Zone.GRAVEYARD) {
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl {
|
|||
/**
|
||||
* The Ability sets if no target is defined the target pointer to the active
|
||||
* player of the current draw phase
|
||||
*
|
||||
* @param effect
|
||||
* @param targetController
|
||||
* @param isOptional
|
||||
*/
|
||||
public BeginningOfDrawTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional);
|
||||
|
|
@ -106,26 +102,19 @@ public class BeginningOfDrawTriggeredAbility extends TriggeredAbilityImpl {
|
|||
switch (targetController) {
|
||||
case ACTIVE:
|
||||
case YOU:
|
||||
return "At the beginning of your draw step, " + generateZoneString();
|
||||
return "At the beginning of your draw step, ";
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's draw step, " + generateZoneString();
|
||||
return "At the beginning of each opponent's draw step, ";
|
||||
case NOT_YOU:
|
||||
return "At the beginning of each other player's draw step, " + generateZoneString();
|
||||
return "At the beginning of each other player's draw step, ";
|
||||
case ANY:
|
||||
return "At the beginning of each player's draw step, " + generateZoneString();
|
||||
return "At the beginning of each player's draw step, ";
|
||||
case CONTROLLER_ATTACHED_TO:
|
||||
return "At the beginning of the draw step of enchanted creature's controller, " + generateZoneString();
|
||||
return "At the beginning of the draw step of enchanted creature's controller, ";
|
||||
case ENCHANTED:
|
||||
return "At the beginning of enchanted player's draw step, " + generateZoneString();
|
||||
return "At the beginning of enchanted player's draw step, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import mage.target.targetpointer.FixedTarget;
|
|||
|
||||
public class BeginningOfFirstMainTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private TargetController targetController;
|
||||
private boolean setTargetPointer;
|
||||
private final TargetController targetController;
|
||||
private final boolean setTargetPointer;
|
||||
|
||||
public BeginningOfFirstMainTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional, false);
|
||||
|
|
@ -81,20 +81,13 @@ public class BeginningOfFirstMainTriggeredAbility extends TriggeredAbilityImpl {
|
|||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of your first main phase, " + generateZoneString();
|
||||
return "At the beginning of your first main phase, ";
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's first main phase, " + generateZoneString();
|
||||
return "At the beginning of each opponent's first main phase, ";
|
||||
case ANY:
|
||||
return "At the beginning of each player's first main phase, " + generateZoneString();
|
||||
return "At the beginning of each player's first main phase, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ import mage.target.targetpointer.FixedTarget;
|
|||
*/
|
||||
public class BeginningOfPostCombatMainTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private TargetController targetController;
|
||||
private boolean setTargetPointer;
|
||||
private final TargetController targetController;
|
||||
private final boolean setTargetPointer;
|
||||
|
||||
public BeginningOfPostCombatMainTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional, false);
|
||||
|
|
@ -90,22 +90,15 @@ public class BeginningOfPostCombatMainTriggeredAbility extends TriggeredAbilityI
|
|||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of each of your postcombat main phases, " + generateZoneString();
|
||||
return "At the beginning of each of your postcombat main phases, ";
|
||||
case OPPONENT:
|
||||
return "At the beginning of each of your opponent's postcombat main phases, " + generateZoneString();
|
||||
return "At the beginning of each of your opponent's postcombat main phases, ";
|
||||
case ANY:
|
||||
return "At the beginning of each postcombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each postcombat main phase, ";
|
||||
case ENCHANTED:
|
||||
return "At the beginning of each of enchanted player's postcombat main phases, " + generateZoneString();
|
||||
return "At the beginning of each of enchanted player's postcombat main phases, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ import mage.watchers.Watcher;
|
|||
*/
|
||||
public class BeginningOfSecondMainTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private TargetController targetController;
|
||||
private boolean setTargetPointer;
|
||||
private final TargetController targetController;
|
||||
private final boolean setTargetPointer;
|
||||
|
||||
public BeginningOfSecondMainTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional, false);
|
||||
|
|
@ -101,24 +101,17 @@ public class BeginningOfSecondMainTriggeredAbility extends TriggeredAbilityImpl
|
|||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of your second main phase, " + generateZoneString();
|
||||
return "At the beginning of your second main phase, ";
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's second main phase, " + generateZoneString();
|
||||
return "At the beginning of each opponent's second main phase, ";
|
||||
case ANY:
|
||||
return "At the beginning of each player's second main phase, " + generateZoneString();
|
||||
return "At the beginning of each player's second main phase, ";
|
||||
case ENCHANTED:
|
||||
return "At the beginning of enchanted player's second main phase, " + generateZoneString();
|
||||
return "At the beginning of enchanted player's second main phase, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
class MainPhaseWatcher extends Watcher {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
private final TargetController targetController;
|
||||
private final boolean setTargetPointer;
|
||||
protected String ruleTrigger;
|
||||
|
||||
public BeginningOfUpkeepTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional);
|
||||
|
|
@ -27,14 +26,9 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
public BeginningOfUpkeepTriggeredAbility(Zone zone, Effect effect, TargetController targetController, boolean isOptional, boolean setTargetPointer) {
|
||||
this(zone, effect, targetController, isOptional, setTargetPointer, null);
|
||||
}
|
||||
|
||||
public BeginningOfUpkeepTriggeredAbility(Zone zone, Effect effect, TargetController targetController, boolean isOptional, boolean setTargetPointer, String ruleTrigger) {
|
||||
super(zone, effect, isOptional);
|
||||
this.targetController = targetController;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
this.ruleTrigger = ruleTrigger;
|
||||
setTriggerPhrase(generateTriggerPhrase());
|
||||
}
|
||||
|
||||
|
|
@ -42,7 +36,6 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
|
|||
super(ability);
|
||||
this.targetController = ability.targetController;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
this.ruleTrigger = ability.ruleTrigger;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -113,32 +106,22 @@ public class BeginningOfUpkeepTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
|
||||
private String generateTriggerPhrase() {
|
||||
if (ruleTrigger != null && !ruleTrigger.isEmpty()) {
|
||||
return ruleTrigger;
|
||||
}
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of your upkeep, " + generateZoneString();
|
||||
return "At the beginning of your upkeep, ";
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's upkeep, " + generateZoneString();
|
||||
return "At the beginning of each opponent's upkeep, ";
|
||||
case ANY:
|
||||
case ACTIVE:
|
||||
return "At the beginning of each player's upkeep, " + generateZoneString();
|
||||
return "At the beginning of each player's upkeep, ";
|
||||
case EACH_PLAYER:
|
||||
return "At the beginning of each upkeep, " + generateZoneString();
|
||||
return "At the beginning of each upkeep, ";
|
||||
case CONTROLLER_ATTACHED_TO:
|
||||
return "At the beginning of the upkeep of enchanted creature's controller, " + generateZoneString();
|
||||
return "At the beginning of the upkeep of enchanted creature's controller, ";
|
||||
case ENCHANTED:
|
||||
return "At the beginning of enchanted player's upkeep, " + generateZoneString();
|
||||
return "At the beginning of enchanted player's upkeep, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public class SurveilTriggeredAbility extends TriggeredAbilityImpl {
|
|||
|
||||
public SurveilTriggeredAbility(Zone zone, Effect effect) {
|
||||
super(zone, effect);
|
||||
setTriggerPhrase("Whenever you surveil, " + (zone == Zone.GRAVEYARD ? "if {this} is in your graveyard, " : ""));
|
||||
setTriggerPhrase("Whenever you surveil, ");
|
||||
}
|
||||
|
||||
private SurveilTriggeredAbility(final SurveilTriggeredAbility ability) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import mage.game.Game;
|
|||
*
|
||||
* @author Susucr
|
||||
*/
|
||||
|
||||
public enum SourceInGraveyardCondition implements Condition {
|
||||
instance;
|
||||
|
||||
|
|
@ -18,4 +17,10 @@ public enum SourceInGraveyardCondition implements Condition {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
return game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{this} is in your graveyard";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,20 @@
|
|||
|
||||
package mage.abilities.condition.common;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.CommandObject;
|
||||
|
||||
/**
|
||||
* As long as the sourceId permanent is on the battlefield, the condition is
|
||||
* true.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
import java.util.UUID;
|
||||
|
||||
public enum SourceOnBattlefieldOrCommandZoneCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Iterator<CommandObject> commandZone = game.getState().getCommand().iterator();
|
||||
while (commandZone.hasNext()) {
|
||||
UUID thing = commandZone.next().getId();
|
||||
for (CommandObject commandObject : game.getState().getCommand()) {
|
||||
UUID thing = commandObject.getId();
|
||||
if (thing.equals(source.getSourceId())) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -32,7 +24,7 @@ public enum SourceOnBattlefieldOrCommandZoneCondition implements Condition {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "if {this} is on the battlefield";
|
||||
return "if {this} is in the command zone or on the battlefield";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,26 +33,20 @@ public class RemoveCounterSourceEffect extends OneShotEffect {
|
|||
int toRemove = Math.min(counter.getCount(), permanent.getCounters(game).getCount(counter.getName()));
|
||||
if (toRemove > 0) {
|
||||
permanent.removeCounters(counter.getName(), toRemove, source, game);
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers("Removed " + toRemove + ' ' + counter.getName() + " counter from " + permanent.getLogName());
|
||||
}
|
||||
game.informPlayers("Removed " + toRemove + ' ' + counter.getName() + " counter from " + permanent.getLogName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!(source.getSourceObject(game) instanceof Permanent)) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
int toRemove = Math.min(counter.getCount(), card.getCounters(game).getCount(counter.getName()));
|
||||
if (toRemove > 0) {
|
||||
card.removeCounters(counter.getName(), toRemove, source, game);
|
||||
if (!game.isSimulation()) {
|
||||
game.informPlayers("Removed " + toRemove + ' ' + counter.getName()
|
||||
+ " counter from " + card.getLogName()
|
||||
+ " (" + card.getCounters(game).getCount(counter.getName()) + " left)");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Card card = source.getSourceCardIfItStillExists(game);
|
||||
if (card != null) {
|
||||
int toRemove = Math.min(counter.getCount(), card.getCounters(game).getCount(counter.getName()));
|
||||
if (toRemove > 0) {
|
||||
card.removeCounters(counter.getName(), toRemove, source, game);
|
||||
game.informPlayers("Removed " + toRemove + ' ' + counter.getName()
|
||||
+ " counter from " + card.getLogName()
|
||||
+ " (" + card.getCounters(game).getCount(counter.getName()) + " left)");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
|
||||
import mage.abilities.common.DiesSourceTriggeredAbility;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
|
||||
|
|
@ -27,28 +25,28 @@ import mage.target.targetpointer.FixedTarget;
|
|||
*/
|
||||
public class RepairAbility extends DiesSourceTriggeredAbility {
|
||||
|
||||
private final String ruleText;
|
||||
private final int count;
|
||||
|
||||
public RepairAbility(int count) {
|
||||
super(new AddCountersSourceEffect(
|
||||
CounterType.REPAIR.createInstance(), StaticValue.get(count), false, true));
|
||||
addSubAbility(new RepairBeginningOfUpkeepInterveningIfTriggeredAbility());
|
||||
addSubAbility(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD,
|
||||
new RemoveCounterSourceEffect(CounterType.REPAIR.createInstance()), TargetController.YOU, false)
|
||||
.setRuleVisible(false));
|
||||
addSubAbility(new RepairCastFromGraveyardTriggeredAbility());
|
||||
|
||||
ruleText = "Repair " + count + " <i>(When this creature dies, put " + count
|
||||
+ " repair counters on it. At the beginning of your upkeep, remove a repair counter. "
|
||||
+ "Whenever the last is removed, you may cast it from graveyard until end of turn.)</i>";
|
||||
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
protected RepairAbility(final RepairAbility ability) {
|
||||
super(ability);
|
||||
this.ruleText = ability.ruleText;
|
||||
this.count = ability.count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return ruleText;
|
||||
return "Repair " + count + " <i>(When this creature dies, put " + count
|
||||
+ " repair counters on it. At the beginning of your upkeep, remove a repair counter. "
|
||||
+ "Whenever the last is removed, you may cast it from graveyard until end of turn.)</i>";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -59,7 +57,7 @@ public class RepairAbility extends DiesSourceTriggeredAbility {
|
|||
|
||||
class RepairedCastFromGraveyardEffect extends OneShotEffect {
|
||||
|
||||
public RepairedCastFromGraveyardEffect() {
|
||||
RepairedCastFromGraveyardEffect() {
|
||||
super(Outcome.Benefit);
|
||||
}
|
||||
|
||||
|
|
@ -75,11 +73,8 @@ class RepairedCastFromGraveyardEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
return false;
|
||||
}
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card == null) {
|
||||
Card card = source.getSourceCardIfItStillExists(game);
|
||||
if (controller == null || card == null) {
|
||||
return false;
|
||||
}
|
||||
game.addEffect(new PlayFromNotOwnHandZoneTargetEffect(Zone.GRAVEYARD, Duration.UntilYourNextEndStep)
|
||||
|
|
@ -90,12 +85,12 @@ class RepairedCastFromGraveyardEffect extends OneShotEffect {
|
|||
|
||||
class RepairCastFromGraveyardTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public RepairCastFromGraveyardTriggeredAbility() {
|
||||
RepairCastFromGraveyardTriggeredAbility() {
|
||||
super(Zone.GRAVEYARD, new RepairedCastFromGraveyardEffect());
|
||||
setRuleVisible(false);
|
||||
}
|
||||
|
||||
public RepairCastFromGraveyardTriggeredAbility(RepairCastFromGraveyardTriggeredAbility ability) {
|
||||
private RepairCastFromGraveyardTriggeredAbility(RepairCastFromGraveyardTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
|
|
@ -109,6 +104,7 @@ class RepairCastFromGraveyardTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (event.getTargetId().equals(getSourceId())) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
return card != null && game.getState().getZone(card.getId()) == Zone.GRAVEYARD
|
||||
&& event.getData().equals(CounterType.REPAIR.getName())
|
||||
&& card.getCounters(game).getCount(CounterType.REPAIR) == 0;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -124,23 +120,3 @@ class RepairCastFromGraveyardTriggeredAbility extends TriggeredAbilityImpl {
|
|||
return new RepairCastFromGraveyardTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
||||
class RepairBeginningOfUpkeepInterveningIfTriggeredAbility extends ConditionalInterveningIfTriggeredAbility {
|
||||
|
||||
public RepairBeginningOfUpkeepInterveningIfTriggeredAbility() {
|
||||
super(new BeginningOfUpkeepTriggeredAbility(Zone.GRAVEYARD,
|
||||
new RemoveCounterSourceEffect(CounterType.REPAIR.createInstance()), TargetController.YOU, false),
|
||||
new SourceHasCounterCondition(CounterType.REPAIR),
|
||||
"At the beginning of your upkeep, remove a repair counter from {this}");
|
||||
this.setRuleVisible(false);
|
||||
}
|
||||
|
||||
protected RepairBeginningOfUpkeepInterveningIfTriggeredAbility(final RepairBeginningOfUpkeepInterveningIfTriggeredAbility effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepairBeginningOfUpkeepInterveningIfTriggeredAbility copy() {
|
||||
return new RepairBeginningOfUpkeepInterveningIfTriggeredAbility(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue