mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Ensure state-based effects and triggers updated when using Setup Game State
Remove unnecessary duplicate of setup game state code
This commit is contained in:
@@ -745,11 +745,12 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
else {
|
||||
nextPlayer.setExtraTurn(false);
|
||||
}
|
||||
|
||||
|
||||
if (nextPlayer.hasKeyword("Skip your next turn.")) {
|
||||
nextPlayer.removeKeyword("Skip your next turn.");
|
||||
if( null == extraTurn )
|
||||
if (extraTurn == null) {
|
||||
setPlayerTurn(nextPlayer);
|
||||
}
|
||||
return getNextActivePlayer();
|
||||
}
|
||||
|
||||
@@ -853,7 +854,6 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
|
||||
// MAIN GAME LOOP
|
||||
while (!game.isGameOver()) {
|
||||
|
||||
if (givePriorityToPlayer) {
|
||||
if (DEBUG_PHASES) {
|
||||
sw.start();
|
||||
@@ -869,11 +869,11 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
do {
|
||||
// Rule 704.3 Whenever a player would get priority, the game checks ... for state-based actions,
|
||||
allAffectedCards.addAll(game.getAction().checkStateEffects(false));
|
||||
if (game.isGameOver())
|
||||
if (game.isGameOver()) {
|
||||
return; // state-based effects check could lead to game over
|
||||
|
||||
}
|
||||
addedAnythingToStack = game.getStack().addAllTriggeredAbilitiesToStack();
|
||||
} while(addedAnythingToStack);
|
||||
} while (addedAnythingToStack);
|
||||
|
||||
game.fireEvent(new GameEventCardStatsChanged(allAffectedCards));
|
||||
|
||||
@@ -885,12 +885,12 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
}
|
||||
|
||||
chosenSa = pPlayerPriority.getController().chooseSpellAbilityToPlay();
|
||||
if( null == chosenSa )
|
||||
if (chosenSa == null) {
|
||||
break; // that means 'I pass'
|
||||
|
||||
if (DEBUG_PHASES)
|
||||
}
|
||||
if (DEBUG_PHASES) {
|
||||
System.out.print("... " + pPlayerPriority + " plays " + chosenSa);
|
||||
|
||||
}
|
||||
pFirstPriority = pPlayerPriority; // all opponents have to pass before stack is allowed to resolve
|
||||
pPlayerPriority.getController().playChosenSpellAbility(chosenSa);
|
||||
loopCount++;
|
||||
@@ -918,13 +918,15 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
|
||||
if (game.isGameOver() || nextPlayer == null) { return; } // conceded?
|
||||
|
||||
if( DEBUG_PHASES )
|
||||
if (DEBUG_PHASES) {
|
||||
System.out.println(String.format("%s %s: %s is active, previous was %s", playerTurn, phase, pPlayerPriority, nextPlayer));
|
||||
}
|
||||
if (pFirstPriority == nextPlayer) {
|
||||
if (game.getStack().isEmpty()) {
|
||||
if (playerTurn.hasLost()) {
|
||||
setPriority(game.getNextPlayerAfter(playerTurn));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
setPriority(playerTurn);
|
||||
}
|
||||
|
||||
@@ -933,8 +935,10 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
onPhaseEnd();
|
||||
advanceToNextPhase();
|
||||
onPhaseBegin();
|
||||
} else if (!game.getStack().hasSimultaneousStackEntries())
|
||||
}
|
||||
else if (!game.getStack().hasSimultaneousStackEntries()) {
|
||||
game.getStack().resolveStack();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// pass the priority to other player
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
package forge.match;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
@@ -23,7 +15,6 @@ import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.ai.LobbyPlayerAi;
|
||||
import forge.card.CardStateName;
|
||||
import forge.control.FControlGameEventHandler;
|
||||
import forge.control.FControlGamePlayback;
|
||||
import forge.control.WatchLocalGame;
|
||||
@@ -37,15 +28,10 @@ import forge.game.GameRules;
|
||||
import forge.game.GameType;
|
||||
import forge.game.GameView;
|
||||
import forge.game.Match;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.match.input.InputPlaybackControl;
|
||||
import forge.match.input.InputQueue;
|
||||
import forge.model.FModel;
|
||||
@@ -390,180 +376,6 @@ public class MatchUtil {
|
||||
}
|
||||
uiEvents.post(uiEvent);
|
||||
}
|
||||
|
||||
public static void setupGameState(String filename) {
|
||||
int humanLife = -1;
|
||||
int aiLife = -1;
|
||||
|
||||
final Map<ZoneType, String> humanCardTexts = new EnumMap<ZoneType, String>(ZoneType.class);
|
||||
final Map<ZoneType, String> aiCardTexts = new EnumMap<ZoneType, String>(ZoneType.class);
|
||||
|
||||
String tChangePlayer = "NONE";
|
||||
String tChangePhase = "NONE";
|
||||
|
||||
try {
|
||||
final FileInputStream fstream = new FileInputStream(filename);
|
||||
final DataInputStream in = new DataInputStream(fstream);
|
||||
final BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
||||
|
||||
String temp = "";
|
||||
|
||||
while ((temp = br.readLine()) != null) {
|
||||
final String[] tempData = temp.split("=");
|
||||
if (tempData.length < 2 || temp.charAt(0) == '#') {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String categoryName = tempData[0].toLowerCase();
|
||||
final String categoryValue = tempData[1];
|
||||
|
||||
switch (categoryName) {
|
||||
case "humanlife":
|
||||
humanLife = Integer.parseInt(categoryValue);
|
||||
break;
|
||||
case "ailife":
|
||||
aiLife = Integer.parseInt(categoryValue);
|
||||
break;
|
||||
case "activeplayer":
|
||||
tChangePlayer = categoryValue.trim().toLowerCase();
|
||||
break;
|
||||
case "activephase":
|
||||
tChangePhase = categoryValue;
|
||||
break;
|
||||
case "humancardsinplay":
|
||||
humanCardTexts.put(ZoneType.Battlefield, categoryValue);
|
||||
break;
|
||||
case "aicardsinplay":
|
||||
aiCardTexts.put(ZoneType.Battlefield, categoryValue);
|
||||
break;
|
||||
case "humancardsinhand":
|
||||
humanCardTexts.put(ZoneType.Hand, categoryValue);
|
||||
break;
|
||||
case "aicardsinhand":
|
||||
aiCardTexts.put(ZoneType.Hand, categoryValue);
|
||||
break;
|
||||
case "humancardsingraveyard":
|
||||
humanCardTexts.put(ZoneType.Graveyard, categoryValue);
|
||||
break;
|
||||
case "aicardsingraveyard":
|
||||
aiCardTexts.put(ZoneType.Graveyard, categoryValue);
|
||||
break;
|
||||
case "humancardsinlibrary":
|
||||
humanCardTexts.put(ZoneType.Library, categoryValue);
|
||||
break;
|
||||
case "aicardsinlibrary":
|
||||
aiCardTexts.put(ZoneType.Library, categoryValue);
|
||||
break;
|
||||
case "humancardsinexile":
|
||||
humanCardTexts.put(ZoneType.Exile, categoryValue);
|
||||
break;
|
||||
case "aicardsinexile":
|
||||
aiCardTexts.put(ZoneType.Exile, categoryValue);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in.close();
|
||||
}
|
||||
catch (final FileNotFoundException fnfe) {
|
||||
SOptionPane.showErrorDialog("File not found: " + filename);
|
||||
}
|
||||
catch (final Exception e) {
|
||||
SOptionPane.showErrorDialog("Error loading battle setup file!");
|
||||
return;
|
||||
}
|
||||
|
||||
setupGameState(humanLife, aiLife, humanCardTexts, aiCardTexts, tChangePlayer, tChangePhase);
|
||||
}
|
||||
|
||||
public static void setupGameState(final int humanLife, final int aiLife, final Map<ZoneType, String> humanCardTexts,
|
||||
final Map<ZoneType, String> aiCardTexts, final String tChangePlayer, final String tChangePhase) {
|
||||
|
||||
game.getAction().invoke(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Player human = game.getPlayers().get(0);
|
||||
final Player ai = game.getPlayers().get(1);
|
||||
|
||||
Player newPlayerTurn = tChangePlayer.equals("human") ? newPlayerTurn = human : tChangePlayer.equals("ai") ? newPlayerTurn = ai : null;
|
||||
PhaseType newPhase = tChangePhase.trim().equalsIgnoreCase("none") ? null : PhaseType.smartValueOf(tChangePhase);
|
||||
|
||||
game.getPhaseHandler().devModeSet(newPhase, newPlayerTurn);
|
||||
|
||||
game.getTriggerHandler().suppressMode(TriggerType.ChangesZone);
|
||||
|
||||
setupPlayerState(humanLife, humanCardTexts, human);
|
||||
setupPlayerState(aiLife, aiCardTexts, ai);
|
||||
|
||||
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
|
||||
|
||||
game.getAction().checkStaticAbilities(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void setupPlayerState(int life, Map<ZoneType, String> cardTexts, final Player p) {
|
||||
Map<ZoneType, List<Card>> humanCards = new EnumMap<ZoneType, List<Card>>(ZoneType.class);
|
||||
for (Entry<ZoneType, String> kv : cardTexts.entrySet()) {
|
||||
humanCards.put(kv.getKey(), processCardsForZone(kv.getValue().split(";"), p));
|
||||
}
|
||||
|
||||
if (life > 0) {
|
||||
p.setLife(life, null);
|
||||
}
|
||||
|
||||
for (Entry<ZoneType, List<Card>> kv : humanCards.entrySet()) {
|
||||
if (kv.getKey() == ZoneType.Battlefield) {
|
||||
for (final Card c : kv.getValue()) {
|
||||
p.getZone(ZoneType.Hand).add(c);
|
||||
p.getGame().getAction().moveToPlay(c);
|
||||
c.setSickness(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.getZone(kv.getKey()).setCards(kv.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Card> processCardsForZone(final String[] data, final Player player) {
|
||||
final List<Card> cl = new ArrayList<Card>();
|
||||
for (final String element : data) {
|
||||
final String[] cardinfo = element.trim().split("\\|");
|
||||
|
||||
final Card c = Card.fromPaperCard(FModel.getMagicDb().getCommonCards().getCard(cardinfo[0]), player);
|
||||
|
||||
boolean hasSetCurSet = false;
|
||||
for (final String info : cardinfo) {
|
||||
if (info.startsWith("Set:")) {
|
||||
c.setSetCode(info.substring(info.indexOf(':') + 1));
|
||||
hasSetCurSet = true;
|
||||
}
|
||||
else if (info.equalsIgnoreCase("Tapped:True")) {
|
||||
c.tap();
|
||||
}
|
||||
else if (info.startsWith("Counters:")) {
|
||||
final String[] counterStrings = info.substring(info.indexOf(':') + 1).split(",");
|
||||
for (final String counter : counterStrings) {
|
||||
c.addCounter(CounterType.valueOf(counter), 1, true);
|
||||
}
|
||||
}
|
||||
else if (info.equalsIgnoreCase("SummonSick:True")) {
|
||||
c.setSickness(true);
|
||||
}
|
||||
else if (info.equalsIgnoreCase("FaceDown:True")) {
|
||||
c.setState(CardStateName.FaceDown, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasSetCurSet) {
|
||||
c.setSetCode(c.getMostRecentSet());
|
||||
}
|
||||
|
||||
cl.add(c);
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
|
||||
/** Returns a random name from the supplied list. */
|
||||
public static String getRandomName() {
|
||||
|
||||
@@ -1551,6 +1551,8 @@ public class PlayerControllerHuman extends PlayerController {
|
||||
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
|
||||
|
||||
game.getAction().checkStaticAbilities(true);
|
||||
|
||||
game.getAction().checkStateEffects(true); //ensure state based effects and triggers are updated
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user