implement [EOE] Kav Landseeker; fix & test Meandering Towershell along the way

This commit is contained in:
Susucre 2025-07-11 20:40:50 +02:00
parent 2b7f8869dd
commit 0dceeb78bd
8 changed files with 298 additions and 53 deletions

View file

@ -0,0 +1,83 @@
package mage.abilities.common.delayed;
import mage.abilities.DelayedTriggeredAbility;
import mage.abilities.effects.Effect;
import mage.constants.Duration;
import mage.game.Game;
import mage.game.events.GameEvent;
/**
* @author Susucr
*/
public class AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility extends DelayedTriggeredAbility {
private GameEvent.EventType stepEvent;
private int nextTurn = -1; // once the controller starts a new turn, register it to trigger that turn.
private boolean isActive = true;
public AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility(Effect effect, GameEvent.EventType stepEvent) {
this(effect, stepEvent, false);
}
public AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility(Effect effect, GameEvent.EventType stepEvent, boolean optional) {
super(effect, Duration.Custom, true, optional);
this.stepEvent = stepEvent;
this.setTriggerPhrase(generateTriggerPhrase());
}
private AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility(final AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility ability) {
super(ability);
this.nextTurn = ability.nextTurn;
this.isActive = ability.isActive;
this.stepEvent = ability.stepEvent;
}
@Override
public AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility copy() {
return new AtTheBeginOfStepOfYourNextTurnDelayedTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == stepEvent
|| event.getType() == GameEvent.EventType.BEGIN_TURN;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) {
// not your turn.
return false;
}
int turn = game.getTurnNum();
switch (event.getType()) {
case BEGIN_TURN:
// We register the turn number at the start of your next turn.
// This is in order to not trigger if that turn ends without an end step.
if (this.nextTurn == -1) {
this.nextTurn = turn;
} else if (turn > this.nextTurn) {
this.isActive = false; // to have the delayed trigger being cleaned up
}
return false;
default:
return turn == this.nextTurn && event.getType() == stepEvent;
}
}
@Override
public boolean isInactive(Game game) {
return super.isInactive(game) || !isActive;
}
private String generateTriggerPhrase() {
switch (stepEvent) {
case END_TURN_STEP_PRE:
return "At the beginning of the end step on your next turn, ";
case DECLARE_ATTACKERS_STEP_PRE:
return "At the beginning of the declare attackers step on your next turn, ";
}
throw new IllegalArgumentException("stepEvent only supports steps events");
}
}

View file

@ -40,6 +40,7 @@ public class GameEvent implements Serializable {
PREVENT_DAMAGE, PREVENTED_DAMAGE,
//Turn-based events
PLAY_TURN, EXTRA_TURN,
BEGIN_TURN, // event fired on actual begin of turn.
CHANGE_PHASE, PHASE_CHANGED,
CHANGE_STEP, STEP_CHANGED,
BEGINNING_PHASE, BEGINNING_PHASE_PRE, BEGINNING_PHASE_POST, // The normal beginning phase -- at the beginning of turn

View file

@ -547,6 +547,8 @@ public abstract class PlayerImpl implements Player, Serializable {
resetLandsPlayed();
updateRange(game);
game.getState().removeTurnStartEffect(game);
GameEvent event = new GameEvent(GameEvent.EventType.BEGIN_TURN, null, null, getId());
game.fireEvent(event);
}
@Override