mirror of
https://github.com/magefree/mage.git
synced 2026-01-26 21:29:17 -08:00
Rework "second main phase" abilities (#12970)
* replace all instances of "postcombat main phase" with "second main phase" minus exceptions * second main trigger now works correctly * add survival test * additional text fixes
This commit is contained in:
parent
3131365abd
commit
1484e3b575
39 changed files with 339 additions and 115 deletions
|
|
@ -1,28 +1,26 @@
|
|||
package mage.abilities.abilityword;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.BeginningOfSecondMainTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* TODO: This should only trigger on the second main phase, this is part of a larger refactor that has to be done
|
||||
*
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class SurvivalAbility extends TriggeredAbilityImpl {
|
||||
public class SurvivalAbility extends BeginningOfSecondMainTriggeredAbility {
|
||||
|
||||
public SurvivalAbility(Effect effect) {
|
||||
this(effect, false);
|
||||
}
|
||||
|
||||
public SurvivalAbility(Effect effect, boolean optional) {
|
||||
super(Zone.BATTLEFIELD, effect, optional);
|
||||
super(Zone.BATTLEFIELD, effect, TargetController.YOU, optional, false);
|
||||
setTriggerPhrase("At the beginning of your second main phase, if {this} is tapped, ");
|
||||
setAbilityWord(AbilityWord.SURVIVAL);
|
||||
}
|
||||
|
|
@ -36,20 +34,10 @@ public class SurvivalAbility extends TriggeredAbilityImpl {
|
|||
return new SurvivalAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.POSTCOMBAT_MAIN_PHASE_PRE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return game.isActivePlayer(getControllerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
return Optional
|
||||
.ofNullable(getSourcePermanentIfItStillExists(game))
|
||||
.ofNullable(getSourcePermanentOrLKI(game))
|
||||
.map(Permanent::isTapped)
|
||||
.orElse(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,31 +12,31 @@ import mage.target.targetpointer.FixedTarget;
|
|||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class BeginningOfPreCombatMainTriggeredAbility extends TriggeredAbilityImpl {
|
||||
public class BeginningOfFirstMainTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private TargetController targetController;
|
||||
private boolean setTargetPointer;
|
||||
|
||||
public BeginningOfPreCombatMainTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
public BeginningOfFirstMainTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional, false);
|
||||
}
|
||||
|
||||
public BeginningOfPreCombatMainTriggeredAbility(Zone zone, Effect effect, TargetController targetController, boolean isOptional, boolean setTargetPointer) {
|
||||
public BeginningOfFirstMainTriggeredAbility(Zone zone, Effect effect, TargetController targetController, boolean isOptional, boolean setTargetPointer) {
|
||||
super(zone, effect, isOptional);
|
||||
this.targetController = targetController;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
setTriggerPhrase(generateTriggerPhrase());
|
||||
}
|
||||
|
||||
protected BeginningOfPreCombatMainTriggeredAbility(final BeginningOfPreCombatMainTriggeredAbility ability) {
|
||||
protected BeginningOfFirstMainTriggeredAbility(final BeginningOfFirstMainTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.targetController = ability.targetController;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeginningOfPreCombatMainTriggeredAbility copy() {
|
||||
return new BeginningOfPreCombatMainTriggeredAbility(this);
|
||||
public BeginningOfFirstMainTriggeredAbility copy() {
|
||||
return new BeginningOfFirstMainTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -81,11 +81,11 @@ public class BeginningOfPreCombatMainTriggeredAbility extends TriggeredAbilityIm
|
|||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of your precombat main phase, " + generateZoneString();
|
||||
return "At the beginning of your first main phase, " + generateZoneString();
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's precombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each opponent's first main phase, " + generateZoneString();
|
||||
case ANY:
|
||||
return "At the beginning of each player's precombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each player's first main phase, " + generateZoneString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
@ -48,25 +48,25 @@ public class BeginningOfPostCombatMainTriggeredAbility extends TriggeredAbilityI
|
|||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
boolean yours = event.getPlayerId().equals(this.controllerId);
|
||||
if (yours && setTargetPointer) {
|
||||
if (getTargets().isEmpty()) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
if (!isControlledBy(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
if (setTargetPointer && getTargets().isEmpty()) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
}
|
||||
return yours;
|
||||
return true;
|
||||
case OPPONENT:
|
||||
if (game.getPlayer(this.controllerId).hasOpponent(event.getPlayerId(), game)) {
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
if (!game.getOpponents(this.controllerId).contains(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case ANY:
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
|
|
@ -77,7 +77,7 @@ public class BeginningOfPostCombatMainTriggeredAbility extends TriggeredAbilityI
|
|||
case ENCHANTED:
|
||||
Permanent permanent = getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || !game.isActivePlayer(permanent.getAttachedTo())) {
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
if (getTargets().isEmpty()) {
|
||||
this.getEffects().setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
|
|
@ -90,13 +90,13 @@ public class BeginningOfPostCombatMainTriggeredAbility extends TriggeredAbilityI
|
|||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of your postcombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each of your postcombat main phases, " + generateZoneString();
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's postcombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each of your opponent's postcombat main phases, " + generateZoneString();
|
||||
case ANY:
|
||||
return "At the beginning of each player's postcombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each postcombat main phase, " + generateZoneString();
|
||||
case ENCHANTED:
|
||||
return "At the beginning of enchanted player's postcombat main phase, " + generateZoneString();
|
||||
return "At the beginning of each of enchanted player's postcombat main phases, " + generateZoneString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,153 @@
|
|||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
*/
|
||||
public class BeginningOfSecondMainTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
private TargetController targetController;
|
||||
private boolean setTargetPointer;
|
||||
|
||||
public BeginningOfSecondMainTriggeredAbility(Effect effect, TargetController targetController, boolean isOptional) {
|
||||
this(Zone.BATTLEFIELD, effect, targetController, isOptional, false);
|
||||
}
|
||||
|
||||
public BeginningOfSecondMainTriggeredAbility(Zone zone, Effect effect, TargetController targetController, boolean isOptional, boolean setTargetPointer) {
|
||||
super(zone, effect, isOptional);
|
||||
this.targetController = targetController;
|
||||
this.setTargetPointer = setTargetPointer;
|
||||
setTriggerPhrase(generateTriggerPhrase());
|
||||
this.addWatcher(new MainPhaseWatcher());
|
||||
}
|
||||
|
||||
protected BeginningOfSecondMainTriggeredAbility(final BeginningOfSecondMainTriggeredAbility ability) {
|
||||
super(ability);
|
||||
this.targetController = ability.targetController;
|
||||
this.setTargetPointer = ability.setTargetPointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeginningOfSecondMainTriggeredAbility copy() {
|
||||
return new BeginningOfSecondMainTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEventType(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case PRECOMBAT_MAIN_PHASE_PRE:
|
||||
case POSTCOMBAT_MAIN_PHASE_PRE:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (!MainPhaseWatcher.checkCount(game)) {
|
||||
return false;
|
||||
}
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
if (!isControlledBy(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
if (setTargetPointer && getTargets().isEmpty()) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case OPPONENT:
|
||||
if (!game.getOpponents(this.controllerId).contains(event.getPlayerId())) {
|
||||
return false;
|
||||
}
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case ANY:
|
||||
if (setTargetPointer) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case ENCHANTED:
|
||||
Permanent permanent = getSourcePermanentIfItStillExists(game);
|
||||
if (permanent == null || !game.isActivePlayer(permanent.getAttachedTo())) {
|
||||
return false;
|
||||
}
|
||||
if (getTargets().isEmpty()) {
|
||||
this.getEffects().setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private String generateTriggerPhrase() {
|
||||
switch (targetController) {
|
||||
case YOU:
|
||||
return "At the beginning of your second main phase, " + generateZoneString();
|
||||
case OPPONENT:
|
||||
return "At the beginning of each opponent's second main phase, " + generateZoneString();
|
||||
case ANY:
|
||||
return "At the beginning of each player's second main phase, " + generateZoneString();
|
||||
case ENCHANTED:
|
||||
return "At the beginning of enchanted player's second main phase, " + generateZoneString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private String generateZoneString() {
|
||||
switch (getZone()) {
|
||||
case GRAVEYARD:
|
||||
return "if {this} is in your graveyard, ";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
class MainPhaseWatcher extends Watcher {
|
||||
|
||||
private int mainPhaseCount = 0;
|
||||
|
||||
MainPhaseWatcher() {
|
||||
super(WatcherScope.GAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
switch (event.getType()) {
|
||||
case PRECOMBAT_MAIN_PHASE_PRE:
|
||||
case POSTCOMBAT_MAIN_PHASE_PRE:
|
||||
mainPhaseCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
this.mainPhaseCount = 0;
|
||||
}
|
||||
|
||||
static boolean checkCount(Game game) {
|
||||
return game
|
||||
.getState()
|
||||
.getWatcher(MainPhaseWatcher.class)
|
||||
.mainPhaseCount == 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ public class AtTheBeginOfMainPhaseDelayedTriggeredAbility extends DelayedTrigger
|
|||
|
||||
public enum PhaseSelection {
|
||||
|
||||
NEXT_PRECOMBAT_MAIN("next precombat main phase"),
|
||||
NEXT_PRECOMBAT_MAIN("next first main phase"),
|
||||
NEXT_POSTCOMBAT_MAIN("next postcombat main phase"),
|
||||
NEXT_MAIN("next main phase"),
|
||||
NEXT_MAIN_THIS_TURN("next main phase this turn", Duration.EndOfTurn);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package mage.game.command.emblems;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.BeginningOfPreCombatMainTriggeredAbility;
|
||||
import mage.abilities.common.BeginningOfFirstMainTriggeredAbility;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
|
|
@ -31,7 +31,7 @@ public class RadiationEmblem extends Emblem {
|
|||
this.frameStyle = FrameStyle.M15_NORMAL;
|
||||
|
||||
this.getAbilities().add(new ConditionalInterveningIfTriggeredAbility(
|
||||
new BeginningOfPreCombatMainTriggeredAbility(Zone.ALL, new RadiationEffect(), TargetController.YOU, false, false),
|
||||
new BeginningOfFirstMainTriggeredAbility(Zone.ALL, new RadiationEffect(), TargetController.YOU, false, false),
|
||||
RadiationCondition.instance,
|
||||
"At the beginning of your precombat main phase, if you have any rad counters, "
|
||||
+ "mill that many cards. For each nonland card milled this way, you lose 1 life and a rad counter."
|
||||
|
|
@ -112,4 +112,4 @@ class RadiationEffect extends OneShotEffect {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue