mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
790 lines
22 KiB
Java
790 lines
22 KiB
Java
/*
|
|
* Forge: Play Magic: the Gathering.
|
|
* Copyright (C) 2011 Forge Team
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package forge.game.phase;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Stack;
|
|
|
|
import com.esotericsoftware.minlog.Log;
|
|
|
|
import forge.Card;
|
|
import forge.CardLists;
|
|
import forge.CardPredicates;
|
|
import forge.Singletons;
|
|
import forge.card.trigger.TriggerType;
|
|
import forge.game.GameState;
|
|
import forge.game.event.EndOfTurnEvent;
|
|
import forge.game.event.ManaBurnEvent;
|
|
import forge.game.player.Player;
|
|
import forge.game.zone.ZoneType;
|
|
import forge.properties.ForgePreferences.FPref;
|
|
import forge.util.MyObservable;
|
|
|
|
|
|
/**
|
|
* <p>
|
|
* Phase class.
|
|
* </p>
|
|
*
|
|
* @author Forge
|
|
* @version $Id: PhaseHandler.java 13001 2012-01-08 12:25:25Z Sloth $
|
|
*/
|
|
public class PhaseHandler extends MyObservable implements java.io.Serializable {
|
|
|
|
/** Constant <code>serialVersionUID=5207222278370963197L</code>. */
|
|
private static final long serialVersionUID = 5207222278370963197L;
|
|
|
|
private PhaseType phase = PhaseType.MULLIGAN;
|
|
private int turn = 0;
|
|
// Start turn at 0, so first untap step will turn it to 1
|
|
|
|
transient private final Stack<ExtraTurn> extraTurns = new Stack<ExtraTurn>();
|
|
|
|
private int extraCombats = 0;
|
|
|
|
private int nCombatsThisTurn = 0;
|
|
private boolean bPreventCombatDamageThisTurn = false;
|
|
|
|
private Player playerTurn = null;
|
|
|
|
// priority player
|
|
|
|
private Player pPlayerPriority = null;
|
|
private Player pFirstPriority = null;
|
|
private boolean bPhaseEffects = true;
|
|
private boolean bCombat = false;
|
|
private boolean bRepeat = false;
|
|
|
|
/** The need to next phase. */
|
|
private boolean isPlayerPriorityAllowed = false;
|
|
|
|
transient private final GameState game;
|
|
|
|
public PhaseHandler(final GameState game0)
|
|
{
|
|
game = game0;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* isPlayerTurn.
|
|
* </p>
|
|
*
|
|
* @param player
|
|
* a {@link forge.game.player.Player} object.
|
|
* @return a boolean.
|
|
*/
|
|
public final boolean isPlayerTurn(final Player player) {
|
|
return this.playerTurn.equals(player);
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* Setter for the field <code>playerTurn</code>.
|
|
* </p>
|
|
*
|
|
* @param s
|
|
* a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final void setPlayerTurn(final Player s) {
|
|
this.playerTurn = s;
|
|
this.setPriority(s);
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* Getter for the field <code>playerTurn</code>.
|
|
* </p>
|
|
*
|
|
* @return a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final Player getPlayerTurn() {
|
|
return this.playerTurn;
|
|
}
|
|
|
|
// priority player
|
|
|
|
/**
|
|
* <p>
|
|
* getPriorityPlayer.
|
|
* </p>
|
|
*
|
|
* @return a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final Player getPriorityPlayer() {
|
|
return this.pPlayerPriority;
|
|
}
|
|
|
|
|
|
/**
|
|
* <p>
|
|
* getFirstPriority.
|
|
* </p>
|
|
*
|
|
* @return a {@link forge.game.player.Player} object.
|
|
*/
|
|
private final Player getFirstPriority() {
|
|
return this.pFirstPriority;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* setPriority.
|
|
* </p>
|
|
*
|
|
* @param p
|
|
* a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final void setPriority(final Player p) {
|
|
if (game.getStack() != null) {
|
|
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
|
|
}
|
|
|
|
this.pFirstPriority = p;
|
|
this.pPlayerPriority = p;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* resetPriority.
|
|
* </p>
|
|
*/
|
|
public final void resetPriority() {
|
|
this.setPriority(this.playerTurn);
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* doPhaseEffects.
|
|
* </p>
|
|
*
|
|
* @return a boolean.
|
|
*/
|
|
public final boolean hasPhaseEffects() {
|
|
return this.bPhaseEffects;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* setPhaseEffects.
|
|
* </p>
|
|
*
|
|
* @param b
|
|
* a boolean.
|
|
*/
|
|
private final void setPhaseEffects(final boolean b) {
|
|
this.bPhaseEffects = b;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* inCombat.
|
|
* </p>
|
|
*
|
|
* @return a boolean.
|
|
*/
|
|
public final boolean inCombat() {
|
|
return this.bCombat;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* setCombat.
|
|
* </p>
|
|
*
|
|
* @param b
|
|
* a boolean.
|
|
*/
|
|
public final void setCombat(final boolean b) {
|
|
this.bCombat = b;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* repeatPhase.
|
|
* </p>
|
|
*/
|
|
public final void repeatPhase() {
|
|
this.bRepeat = true;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* handleBeginPhase.
|
|
* </p>
|
|
*/
|
|
public final void handleBeginPhase() {
|
|
if ( null == playerTurn ) return;
|
|
|
|
this.setPhaseEffects(false);
|
|
// Handle effects that happen at the beginning of phases
|
|
game.getAction().checkStateEffects();
|
|
|
|
|
|
switch(this.getPhase()) {
|
|
case UNTAP:
|
|
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
|
|
PhaseUtil.handleUntap(game);
|
|
break;
|
|
|
|
case UPKEEP:
|
|
if (this.getPlayerTurn().hasKeyword("Skip your upkeep step.")) {
|
|
// Slowtrips all say "on the next turn's upkeep" if there is no
|
|
// upkeep next turn, the trigger will never occur.
|
|
for( Player p : game.getPlayers() ) {
|
|
p.clearSlowtripList();
|
|
}
|
|
this.setPlayerMayHavePriority(false);
|
|
} else {
|
|
game.getUpkeep().executeUntil(this.getPlayerTurn());
|
|
game.getUpkeep().executeAt();
|
|
}
|
|
break;
|
|
|
|
case DRAW:
|
|
if (getTurn() == 1 || PhaseUtil.skipDraw(this.getPlayerTurn()))
|
|
this.setPlayerMayHavePriority(false);
|
|
else
|
|
this.getPlayerTurn().drawCards(1, true);
|
|
break;
|
|
|
|
case COMBAT_BEGIN:
|
|
//PhaseUtil.verifyCombat();
|
|
if (playerTurn.isSkippingCombat()) {
|
|
this.setPlayerMayHavePriority(false);
|
|
}
|
|
break;
|
|
|
|
case COMBAT_DECLARE_ATTACKERS:
|
|
if (playerTurn.isSkippingCombat()) {
|
|
this.setPlayerMayHavePriority(false);
|
|
playerTurn.removeKeyword("Skip your next combat phase.");
|
|
}
|
|
break;
|
|
|
|
case COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY:
|
|
if (this.inCombat()) {
|
|
PhaseUtil.handleDeclareAttackers(game.getCombat());
|
|
CombatUtil.showCombat();
|
|
} else {
|
|
this.setPlayerMayHavePriority(false);
|
|
}
|
|
break;
|
|
// we can skip AfterBlockers and AfterAttackers if necessary
|
|
case COMBAT_DECLARE_BLOCKERS:
|
|
if (this.inCombat()) {
|
|
game.getCombat().verifyCreaturesInPlay();
|
|
CombatUtil.showCombat();
|
|
} else {
|
|
this.setPlayerMayHavePriority(false);
|
|
}
|
|
break;
|
|
|
|
case COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY:
|
|
// After declare blockers are finished being declared mark them
|
|
// blocked and trigger blocking things
|
|
if (this.inCombat()) {
|
|
PhaseUtil.handleDeclareBlockers(game);
|
|
CombatUtil.showCombat();
|
|
} else {
|
|
this.setPlayerMayHavePriority(false);
|
|
}
|
|
break;
|
|
|
|
case COMBAT_FIRST_STRIKE_DAMAGE:
|
|
if (!this.inCombat()) {
|
|
this.setPlayerMayHavePriority(false);
|
|
} else {
|
|
game.getCombat().verifyCreaturesInPlay();
|
|
|
|
// no first strikers, skip this step
|
|
if (!game.getCombat().assignCombatDamage(true)) {
|
|
this.setPlayerMayHavePriority(false);
|
|
} else {
|
|
game.getCombat().dealAssignedDamage();
|
|
game.getAction().checkStateEffects();
|
|
CombatUtil.showCombat();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case COMBAT_DAMAGE:
|
|
if (!this.inCombat()) {
|
|
this.setPlayerMayHavePriority(false);
|
|
} else {
|
|
game.getCombat().verifyCreaturesInPlay();
|
|
|
|
if (!game.getCombat().assignCombatDamage(false)) {
|
|
this.setPlayerMayHavePriority(false);
|
|
} else {
|
|
game.getCombat().dealAssignedDamage();
|
|
game.getAction().checkStateEffects();
|
|
CombatUtil.showCombat();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case COMBAT_END:
|
|
// End Combat always happens
|
|
game.getEndOfCombat().executeUntil();
|
|
game.getEndOfCombat().executeAt();
|
|
CombatUtil.showCombat();
|
|
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
|
|
break;
|
|
|
|
case MAIN2:
|
|
CombatUtil.showCombat();
|
|
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
|
|
break;
|
|
|
|
case END_OF_TURN:
|
|
game.getEndOfTurn().executeAt();
|
|
break;
|
|
|
|
case CLEANUP:
|
|
// Reset Damage received map
|
|
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
|
c.onCleanupPhase(playerTurn);
|
|
}
|
|
|
|
game.getEndOfTurn().executeUntil();
|
|
|
|
for (Player player : game.getPlayers()) {
|
|
player.onCleanupPhase();
|
|
player.getController().autoPassCancel(); // autopass won't wrap to next turn
|
|
}
|
|
this.getPlayerTurn().removeKeyword("Skip all combat phases of this turn.");
|
|
game.getCleanup().executeUntilTurn(this.getNextTurn());
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (this.mayPlayerHavePriority()) {
|
|
// Run triggers if phase isn't being skipped
|
|
final HashMap<String, Object> runParams = new HashMap<String, Object>();
|
|
runParams.put("Phase", this.getPhase().Name);
|
|
runParams.put("Player", this.getPlayerTurn());
|
|
game.getTriggerHandler().runTrigger(TriggerType.Phase, runParams);
|
|
|
|
}
|
|
|
|
// This line fixes Combat Damage triggers not going off when they should
|
|
game.getStack().unfreezeStack();
|
|
|
|
// UNTAP
|
|
if (this.getPhase() != PhaseType.UNTAP) {
|
|
// during untap
|
|
this.resetPriority();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if is prevent combat damage this turn.
|
|
*
|
|
* @return true, if is prevent combat damage this turn
|
|
*/
|
|
public final boolean isPreventCombatDamageThisTurn() {
|
|
return this.bPreventCombatDamageThisTurn;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* nextPhase.
|
|
* </p>
|
|
*/
|
|
public final void nextPhase() {
|
|
|
|
this.setPlayerMayHavePriority(true);// PlayerPriorityAllowed = false;
|
|
|
|
// If the Stack isn't empty why is nextPhase being called?
|
|
if (game.getStack().size() != 0) {
|
|
Log.debug("Phase.nextPhase() is called, but Stack isn't empty.");
|
|
return;
|
|
}
|
|
setPhaseEffects(true);
|
|
|
|
for (Player p : game.getPlayers()) {
|
|
int burn = p.getManaPool().clearPool(true);
|
|
if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_MANABURN)) {
|
|
p.loseLife(burn);
|
|
|
|
// Play the Mana Burn sound
|
|
Singletons.getModel().getGame().getEvents().post(new ManaBurnEvent());
|
|
}
|
|
p.updateObservers();
|
|
}
|
|
|
|
switch (this.phase) {
|
|
case UNTAP:
|
|
this.nCombatsThisTurn = 0;
|
|
break;
|
|
|
|
case COMBAT_DECLARE_ATTACKERS:
|
|
game.getStack().unfreezeStack();
|
|
this.nCombatsThisTurn++;
|
|
break;
|
|
|
|
case COMBAT_DECLARE_BLOCKERS:
|
|
game.getStack().unfreezeStack();
|
|
break;
|
|
|
|
case COMBAT_END:
|
|
//SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
|
|
game.getCombat().reset();
|
|
this.resetAttackedThisCombat(this.getPlayerTurn());
|
|
this.bCombat = false;
|
|
|
|
// TODO: ExtraCombat needs to be changed for other spell/abilities
|
|
// that give extra combat can do it like ExtraTurn stack ExtraPhases
|
|
if (this.extraCombats > 0) {
|
|
final Player player = this.getPlayerTurn();
|
|
|
|
this.bCombat = true;
|
|
this.extraCombats--;
|
|
game.getCombat().reset();
|
|
game.getCombat().setAttackingPlayer(player);
|
|
this.phase = PhaseType.COMBAT_BEGIN;
|
|
}
|
|
break;
|
|
|
|
case CLEANUP:
|
|
this.bPreventCombatDamageThisTurn = false;
|
|
if (!this.bRepeat) {
|
|
this.setPlayerTurn(this.handleNextTurn());
|
|
}
|
|
// Play the End Turn sound
|
|
Singletons.getModel().getGame().getEvents().post(new EndOfTurnEvent());
|
|
break;
|
|
default: // no action
|
|
}
|
|
|
|
if (this.bRepeat) { // for when Cleanup needs to repeat itself
|
|
this.bRepeat = false;
|
|
} else {
|
|
this.phase = phase.getNextPhase();
|
|
}
|
|
|
|
game.getGameLog().add("Phase", this.getPlayerTurn() + " " + this.getPhase().Name, 6);
|
|
|
|
// **** Anything BELOW Here is actually in the next phase. Maybe move
|
|
// this to handleBeginPhase
|
|
if (this.phase == PhaseType.UNTAP) {
|
|
this.turn++;
|
|
game.getGameLog().add("Turn", "Turn " + this.turn + " (" + this.getPlayerTurn() + ")", 0);
|
|
}
|
|
|
|
PhaseUtil.visuallyActivatePhase(this.getPlayerTurn(), this.getPhase());
|
|
|
|
// When consecutively skipping phases (like in combat) this section
|
|
// pushes through that block
|
|
this.updateObservers();
|
|
// it no longer does.
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* handleNextTurn.
|
|
* </p>
|
|
*
|
|
* @return a {@link forge.game.player.Player} object.
|
|
*/
|
|
private Player handleNextTurn() {
|
|
|
|
game.getStack().setCardsCastLastTurn();
|
|
game.getStack().clearCardsCastThisTurn();
|
|
|
|
for (final Player p1 : game.getPlayers()) {
|
|
for (final ZoneType z : Player.ALL_ZONES) {
|
|
p1.getZone(z).resetCardsAddedThisTurn();
|
|
}
|
|
}
|
|
for( Player p : game.getPlayers() )
|
|
{
|
|
p.resetProwl();
|
|
p.setLifeLostThisTurn(0);
|
|
|
|
p.removeKeyword("At the beginning of this turn's end step, you lose the game.");
|
|
p.removeKeyword("Skip the untap step of this turn.");
|
|
}
|
|
|
|
return getNextActivePlayer();
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* getNextActivePlayer.
|
|
* </p>
|
|
*
|
|
* @return a {@link forge.game.player.Player} object.
|
|
*/
|
|
private Player getNextActivePlayer() {
|
|
Player nextTurn = game.getNextPlayerAfter(this.getPlayerTurn());
|
|
if (!this.extraTurns.isEmpty()) {
|
|
ExtraTurn extraTurn = this.extraTurns.pop();
|
|
nextTurn = extraTurn.getPlayer();
|
|
if (nextTurn.skipTurnTimeVault()) {
|
|
return getNextActivePlayer();
|
|
}
|
|
if (extraTurn.isLoseAtEndStep()) {
|
|
nextTurn.addKeyword("At the beginning of this turn's end step, you lose the game.");
|
|
}
|
|
if (extraTurn.isSkipUntap()) {
|
|
nextTurn.addKeyword("Skip the untap step of this turn.");
|
|
}
|
|
return nextTurn;
|
|
}
|
|
if (nextTurn.skipTurnTimeVault()) {
|
|
this.setPlayerTurn(nextTurn);
|
|
return getNextActivePlayer();
|
|
}
|
|
return nextTurn;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* is.
|
|
* </p>
|
|
*
|
|
* @param phase
|
|
* a {@link java.lang.String} object.
|
|
* @param player
|
|
* a {@link forge.game.player.Player} object.
|
|
* @return a boolean.
|
|
*/
|
|
public final synchronized boolean is(final PhaseType phase, final Player player) {
|
|
return this.getPhase() == phase && this.getPlayerTurn().equals(player);
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* is.
|
|
* </p>
|
|
*
|
|
* @param phase
|
|
* a {@link java.lang.String} object.
|
|
* @return a boolean.
|
|
*/
|
|
public final synchronized boolean is(final PhaseType phase0) {
|
|
return this.getPhase() == phase0;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* getPhase.
|
|
* </p>
|
|
*
|
|
* @return a {@link java.lang.String} object.
|
|
*/
|
|
public final PhaseType getPhase() {
|
|
return phase;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* Getter for the field <code>turn</code>.
|
|
* </p>
|
|
*
|
|
* @return a int.
|
|
*/
|
|
public final int getTurn() {
|
|
return this.turn;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* getNextTurn.
|
|
* </p>
|
|
*
|
|
* @return a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final Player getNextTurn() {
|
|
if (this.extraTurns.isEmpty()) {
|
|
return game.getNextPlayerAfter(this.getPlayerTurn());
|
|
}
|
|
|
|
return this.extraTurns.peek().getPlayer();
|
|
}
|
|
|
|
|
|
/**
|
|
* <p>
|
|
* addExtraTurn.
|
|
* </p>
|
|
*
|
|
* @param player
|
|
* a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final ExtraTurn addExtraTurn(final Player player) {
|
|
// use a stack to handle extra turns, make sure the bottom of the stack
|
|
// restores original turn order
|
|
if (this.extraTurns.isEmpty()) {
|
|
this.extraTurns.push(new ExtraTurn(game.getNextPlayerAfter(this.getPlayerTurn())));
|
|
}
|
|
|
|
return this.extraTurns.push(new ExtraTurn(player));
|
|
}
|
|
|
|
|
|
/**
|
|
* <p>
|
|
* addExtraCombat.
|
|
* </p>
|
|
*/
|
|
public final void addExtraCombat() {
|
|
// Extra combats can only happen
|
|
this.extraCombats++;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* isFirstCombat.
|
|
* </p>
|
|
*
|
|
* @return a boolean.
|
|
*/
|
|
public final boolean isFirstCombat() {
|
|
return (this.nCombatsThisTurn == 1);
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* resetAttackedThisCombat.
|
|
* </p>
|
|
*
|
|
* @param player
|
|
* a {@link forge.game.player.Player} object.
|
|
*/
|
|
public final void resetAttackedThisCombat(final Player player) {
|
|
// resets the status of attacked/blocked this phase
|
|
List<Card> list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
|
|
|
|
for (int i = 0; i < list.size(); i++) {
|
|
final Card c = list.get(i);
|
|
if (c.getDamageHistory().getCreatureAttackedThisCombat()) {
|
|
c.getDamageHistory().setCreatureAttackedThisCombat(false);
|
|
}
|
|
if (c.getDamageHistory().getCreatureBlockedThisCombat()) {
|
|
c.getDamageHistory().setCreatureBlockedThisCombat(false);
|
|
}
|
|
|
|
if (c.getDamageHistory().getCreatureGotBlockedThisCombat()) {
|
|
c.getDamageHistory().setCreatureGotBlockedThisCombat(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* passPriority.
|
|
* </p>
|
|
*/
|
|
public final void passPriority() {
|
|
// stop game if it's outcome is clear
|
|
if ( game.isGameOver() ) return;
|
|
|
|
final Player actingPlayer = this.getPriorityPlayer();
|
|
final Player firstAction = this.getFirstPriority();
|
|
|
|
// actingPlayer is the player who may act
|
|
// the firstAction is the player who gained Priority First in this segment
|
|
// of Priority
|
|
|
|
Player nextPlayer = game.getNextPlayerAfter(actingPlayer);
|
|
if (firstAction.equals(nextPlayer)) {
|
|
if (game.getStack().isEmpty()) {
|
|
this.setPriority(this.getPlayerTurn()); // this needs to be set early as we exit the phase
|
|
// end phase
|
|
setPlayerMayHavePriority(true);
|
|
nextPhase();
|
|
return;
|
|
} else if (!game.getStack().hasSimultaneousStackEntries()) {
|
|
game.getStack().resolveStack();
|
|
}
|
|
} else {
|
|
// pass the priority to other player
|
|
this.pPlayerPriority = nextPlayer;
|
|
Singletons.getModel().getMatch().getInput().resetInput();
|
|
|
|
}
|
|
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* Setter for the field <code>needToNextPhase</code>.
|
|
* </p>
|
|
*
|
|
* @param needToNextPhase
|
|
* a boolean.
|
|
*/
|
|
public final void setPlayerMayHavePriority(final boolean mayHavePriority) {
|
|
this.isPlayerPriorityAllowed = mayHavePriority;
|
|
}
|
|
|
|
/**
|
|
* <p>
|
|
* isNeedToNextPhase.
|
|
* </p>
|
|
*
|
|
* @return a boolean.
|
|
*/
|
|
public final boolean mayPlayerHavePriority() {
|
|
return this.isPlayerPriorityAllowed;
|
|
}
|
|
|
|
// this is a hack for the setup game state mode, do not use outside of
|
|
// devSetupGameState code
|
|
// as it avoids calling any of the phase effects that may be necessary in a
|
|
// less enforced context
|
|
/**
|
|
* <p>
|
|
* setDevPhaseState.
|
|
* </p>
|
|
*
|
|
* @param phase
|
|
* a {@link java.forge.game.phase.PhaseType} object.
|
|
*/
|
|
public final void setDevPhaseState(final PhaseType phase0) {
|
|
this.phase = phase0;
|
|
}
|
|
|
|
/**
|
|
* Sets the phase state.
|
|
*
|
|
* @param phaseID the new phase state
|
|
*/
|
|
public final void setPhaseState(final PhaseType phase0) {
|
|
this.phase = phase0;
|
|
this.handleBeginPhase();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* TODO Write javadoc for this method.
|
|
*
|
|
* @param b
|
|
* a boolean
|
|
*/
|
|
public final void setPreventCombatDamageThisTurn(final boolean b) {
|
|
this.bPreventCombatDamageThisTurn = true;
|
|
}
|
|
}
|