mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Multiple fixes.
- Make determination of card viewing permissions much faster; - A general fix related to choosing a fixed amount of options from a list; - Improve display of card's names; - Reduce card flickering when changing phases.
This commit is contained in:
@@ -809,12 +809,17 @@ public class GameAction {
|
||||
* <p>
|
||||
* checkStateEffects.
|
||||
* </p>
|
||||
*
|
||||
* @param runEvents
|
||||
* {@code true} to have this method run
|
||||
* {@link GameEventCardStatsChanged} events.
|
||||
* @return a set of affected cards.
|
||||
*/
|
||||
public final void checkStateEffects() {
|
||||
public final Set<Card> checkStateEffects(final boolean runEvents) {
|
||||
// sol(10/29) added for Phase updates, state effects shouldn't be
|
||||
// checked during Spell Resolution (except when persist-returning
|
||||
if (game.getStack().isResolving()) {
|
||||
return;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
// final JFrame frame = Singletons.getView().getFrame();
|
||||
@@ -823,7 +828,7 @@ public class GameAction {
|
||||
// }
|
||||
|
||||
if (game.isGameOver()) {
|
||||
return;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
// Max: I don't know where to put this! - but since it's a state based action, it must be in check state effects
|
||||
@@ -835,8 +840,8 @@ public class GameAction {
|
||||
final boolean refreeze = game.getStack().isFrozen();
|
||||
game.getStack().setFrozen(true);
|
||||
|
||||
// do this twice, sometimes creatures/permanents will survive when they
|
||||
// shouldn't
|
||||
// do this multiple times, sometimes creatures/permanents will survive
|
||||
// when they shouldn't
|
||||
final Set<Card> allAffectedCards = Sets.newHashSet();
|
||||
for (int q = 0; q < 9; q++) {
|
||||
final Set<Card> affectedCards = this.checkStaticAbilities(false);
|
||||
@@ -923,18 +928,22 @@ public class GameAction {
|
||||
if (!checkAgain) {
|
||||
break; // do not continue the loop
|
||||
}
|
||||
} // for q=0;q<2
|
||||
} // for q=0;q<9
|
||||
|
||||
game.fireEvent(new GameEventCardStatsChanged(allAffectedCards));
|
||||
if (runEvents) {
|
||||
game.fireEvent(new GameEventCardStatsChanged(allAffectedCards));
|
||||
}
|
||||
|
||||
checkGameOverCondition();
|
||||
if (game.getAge() != GameStage.Play)
|
||||
return;
|
||||
return Collections.emptySet();
|
||||
|
||||
game.getTriggerHandler().resetActiveTriggers();
|
||||
if (!refreeze) {
|
||||
game.getStack().unfreezeStack();
|
||||
}
|
||||
|
||||
return allAffectedCards;
|
||||
} // checkStateEffects()
|
||||
|
||||
/**
|
||||
@@ -1561,7 +1570,7 @@ public class GameAction {
|
||||
}
|
||||
|
||||
runOpeningHandActions(first);
|
||||
checkStateEffects(); // why?
|
||||
checkStateEffects(true); // why?
|
||||
|
||||
// Run Trigger beginning of the game
|
||||
final HashMap<String, Object> runParams = new HashMap<String, Object>();
|
||||
|
||||
@@ -86,6 +86,7 @@ public class StaticEffects implements IGameStateObject {
|
||||
final List<Card> affectedCards = se.getAffectedCards();
|
||||
final ArrayList<Player> affectedPlayers = se.getAffectedPlayers();
|
||||
final Map<String, String> params = se.getParams();
|
||||
final Player controller = se.getSource().getController();
|
||||
|
||||
String changeColorWordsTo = null;
|
||||
|
||||
@@ -97,6 +98,7 @@ public class StaticEffects implements IGameStateObject {
|
||||
boolean setPT = false;
|
||||
String[] addHiddenKeywords = null;
|
||||
String addColors = null;
|
||||
boolean removeMayLookAt = false;
|
||||
|
||||
if (params.containsKey("ChangeColorWordsTo")) {
|
||||
changeColorWordsTo = params.get("ChangeColorWordsTo");
|
||||
@@ -159,6 +161,10 @@ public class StaticEffects implements IGameStateObject {
|
||||
}
|
||||
}
|
||||
|
||||
if (params.containsKey("MayLookAt")) {
|
||||
removeMayLookAt = true;
|
||||
}
|
||||
|
||||
if (params.containsKey("IgnoreEffectCost")) {
|
||||
for (final SpellAbility s : se.getSource().getSpellAbilities()) {
|
||||
if (s instanceof AbilityStatic && s.isTemporary()) {
|
||||
@@ -249,6 +255,11 @@ public class StaticEffects implements IGameStateObject {
|
||||
affectedCard.removeColor(addColors, affectedCard, !se.isOverwriteColors(),
|
||||
se.getTimestamp(affectedCard));
|
||||
}
|
||||
|
||||
// remove may look at
|
||||
if (removeMayLookAt) {
|
||||
affectedCard.setMayLookAt(controller, false);
|
||||
}
|
||||
}
|
||||
se.clearTimestamps();
|
||||
return affectedCards;
|
||||
|
||||
@@ -33,7 +33,7 @@ public class EndTurnEffect extends SpellAbilityEffect {
|
||||
|
||||
// 3) State-based actions are checked. No player gets priority, and no
|
||||
// triggered abilities are put onto the stack.
|
||||
game.getAction().checkStateEffects();
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
// 4) The current phase and/or step ends. The game skips straight to the
|
||||
// cleanup step. The cleanup step happens in its entirety.
|
||||
|
||||
@@ -210,6 +210,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
private Player controller = null;
|
||||
private long controllerTimestamp = 0;
|
||||
private TreeMap<Long, Player> tempControllers = new TreeMap<Long, Player>();
|
||||
private final Set<Player> mayLookAt = Sets.newHashSet();
|
||||
|
||||
private String originalText = "", text = "";
|
||||
private String echoCost = "";
|
||||
@@ -3256,6 +3257,14 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
this.owner = player;
|
||||
}
|
||||
|
||||
public final void setMayLookAt(final Player player, final boolean mayLookAt) {
|
||||
if (mayLookAt) {
|
||||
this.mayLookAt.add(player);
|
||||
} else {
|
||||
this.mayLookAt.remove(player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>equippedBy</code>.
|
||||
@@ -4013,7 +4022,7 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
* left and right values of a {@link Pair}, respectively. A value of -1
|
||||
* means that particular property has not been set.
|
||||
*/
|
||||
private final Pair<Integer, Integer> getLatestPT() {
|
||||
private final synchronized Pair<Integer, Integer> getLatestPT() {
|
||||
// Find latest set power
|
||||
long maxPowerTimestamp = -2;
|
||||
int latestPower = -1;
|
||||
@@ -6336,9 +6345,13 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
final SpellAbility root = sa.getRootAbility();
|
||||
if (root != null && (root.getPaidList("MovedToGrave") != null)
|
||||
&& !root.getPaidList("MovedToGrave").isEmpty()) {
|
||||
List<Card> list = root.getPaidList("MovedToGrave");
|
||||
for (Card card : list) {
|
||||
if (this.getName().equals(card.getName())) {
|
||||
final List<Card> list = root.getPaidList("MovedToGrave");
|
||||
for (final Card card : list) {
|
||||
String name = card.getName();
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
name = card.getPaperCard().getName();
|
||||
}
|
||||
if (this.getName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -8933,15 +8946,9 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
return true;
|
||||
}
|
||||
|
||||
//one last check to see if card can be shown
|
||||
final Game game = this.getGame();
|
||||
for (Card host : game.getCardsIn(ZoneType.Battlefield)) {
|
||||
final ArrayList<StaticAbility> staticAbilities = host.getStaticAbilities();
|
||||
for (final StaticAbility stAb : staticAbilities) {
|
||||
if (stAb.applyAbility("MayLookAt", this, viewer)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// special viewing permissions for viewer
|
||||
if (this.mayLookAt.contains(viewer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//if viewer is controlled by another player, also check if card can be shown to that player
|
||||
@@ -8959,6 +8966,12 @@ public class Card extends GameEntity implements Comparable<Card>, IIdentifiable
|
||||
if (viewer.hasKeyword("CanSeeOpponentsFaceDownCards")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// special viewing permissions for viewer
|
||||
if (this.mayLookAt.contains(viewer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//if viewer is controlled by another player, also check if face can be shown to that player
|
||||
if (viewer.isMindSlaved() && canCardFaceBeShownTo(viewer.getMindSlaveMaster())) {
|
||||
return true;
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.game.phase;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.*;
|
||||
@@ -384,7 +385,7 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
|
||||
givePriorityToPlayer = false;
|
||||
|
||||
// Rule 514.3a - state-based actions
|
||||
game.getAction().checkStateEffects();
|
||||
game.getAction().checkStateEffects(true);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1001,17 +1002,19 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
|
||||
|
||||
int loopCount = 0;
|
||||
do {
|
||||
|
||||
final Set<Card> allAffectedCards = Sets.newHashSet();
|
||||
boolean addedAnythingToStack = false;
|
||||
do {
|
||||
// Rule 704.3 Whenever a player would get priority, the game checks ... for state-based actions,
|
||||
game.getAction().checkStateEffects();
|
||||
allAffectedCards.addAll(game.getAction().checkStateEffects(false));
|
||||
if (game.isGameOver())
|
||||
return; // state-based effects check could lead to game over
|
||||
|
||||
addedAnythingToStack = game.getStack().addAllTriggeredAbilitiesToStack();
|
||||
} while(addedAnythingToStack);
|
||||
|
||||
game.fireEvent(new GameEventCardStatsChanged(allAffectedCards));
|
||||
|
||||
if (playerTurn.hasLost() && pPlayerPriority.equals(playerTurn) && pFirstPriority.equals(playerTurn)) {
|
||||
// If the active player has lost, and they have priority, set the next player to have priority
|
||||
System.out.println("Active player is no longer in the game...");
|
||||
|
||||
@@ -288,10 +288,6 @@ public class StaticAbility extends CardTraitBase {
|
||||
return StaticAbilityCantBeCast.applyCantPlayLandAbility(this, card, player);
|
||||
}
|
||||
|
||||
if (mode.equals("MayLookAt")) {
|
||||
return StaticAbilityMayLookAt.applyMayLookAtAbility(this, card, player);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ public class StaticAbilityContinuous {
|
||||
public static List<Card> applyContinuousAbility(final StaticAbility stAb, List<Card> affectedCards) {
|
||||
final Map<String, String> params = stAb.getMapParams();
|
||||
final Card hostCard = stAb.getHostCard();
|
||||
final Player controller = hostCard.getController();
|
||||
|
||||
final StaticEffect se = new StaticEffect(hostCard);
|
||||
final ArrayList<Player> affectedPlayers = StaticAbilityContinuous.getAffectedPlayers(stAb);
|
||||
@@ -109,6 +110,7 @@ public class StaticAbilityContinuous {
|
||||
boolean removeCardTypes = false;
|
||||
boolean removeSubTypes = false;
|
||||
boolean removeCreatureTypes = false;
|
||||
boolean controllerMayLookAt = false;
|
||||
|
||||
//Global rules changes
|
||||
if (params.containsKey("GlobalRule")) {
|
||||
@@ -326,6 +328,10 @@ public class StaticAbilityContinuous {
|
||||
}
|
||||
}
|
||||
|
||||
if (params.containsKey("MayLookAt")) {
|
||||
controllerMayLookAt = true;
|
||||
}
|
||||
|
||||
if (params.containsKey("IgnoreEffectCost")) {
|
||||
String cost = params.get("IgnoreEffectCost");
|
||||
buildIgnorEffectAbility(stAb, cost, affectedPlayers, affectedCards);
|
||||
@@ -551,6 +557,10 @@ public class StaticAbilityContinuous {
|
||||
rE.setTemporarilySuppressed(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerMayLookAt) {
|
||||
affectedCard.setMayLookAt(controller, true);
|
||||
}
|
||||
}
|
||||
|
||||
return affectedCards;
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* 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.staticability;
|
||||
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The Class StaticAbility_CantBeCast.
|
||||
*/
|
||||
public class StaticAbilityMayLookAt {
|
||||
|
||||
/**
|
||||
* TODO Write javadoc for this method.
|
||||
*
|
||||
* @param stAb
|
||||
* a StaticAbility
|
||||
* @param card
|
||||
* the card
|
||||
* @param activator
|
||||
* the player
|
||||
* @return true, if successful
|
||||
*/
|
||||
public static boolean applyMayLookAtAbility(final StaticAbility stAb, final Card card, final Player player) {
|
||||
final Map<String, String> params = stAb.getMapParams();
|
||||
final Card hostCard = stAb.getHostCard();
|
||||
|
||||
if (params.containsKey("Affected")
|
||||
&& !card.isValid(params.get("Affected").split(","), hostCard.getController(), hostCard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.containsKey("Player") && player != null
|
||||
&& !player.isValid(params.get("Player"), hostCard.getController(), hostCard)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.containsKey("AffectedZone")) {
|
||||
ZoneType zone = card.getGame().getZoneOf(card).getZoneType();
|
||||
if (!ZoneType.listValueOf(params.get("AffectedZone")).contains(zone)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user