mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +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:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -594,7 +594,6 @@ forge-game/src/main/java/forge/game/staticability/StaticAbilityCantBeCast.java s
|
||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityCantTarget.java -text
|
||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityContinuous.java svneol=native#text/plain
|
||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityETBTapped.java -text
|
||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityMayLookAt.java -text
|
||||
forge-game/src/main/java/forge/game/staticability/StaticAbilityPreventDamage.java svneol=native#text/plain
|
||||
forge-game/src/main/java/forge/game/staticability/package-info.java svneol=native#text/plain
|
||||
forge-game/src/main/java/forge/game/trigger/Trigger.java svneol=native#text/plain
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,13 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.assets.FSkinProp;
|
||||
@@ -145,11 +147,7 @@ public class GuiDesktop implements IGuiBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions) {
|
||||
if (initialInput instanceof GameObject || (inputOptions != null && inputOptions.length > 0 && inputOptions[0] instanceof GameObject)) {
|
||||
System.err.println("Warning: GameObject passed to GUI! Printing stack trace.");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
public String showInputDialog(String message, String title, FSkinProp icon, String initialInput, String[] inputOptions) {
|
||||
return FOptionPane.showInputDialog(message, title, icon == null ? null : FSkin.getImage(icon), initialInput, inputOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Application.ApplicationType;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
@@ -153,8 +154,8 @@ public class GuiMobile implements IGuiBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T showInputDialog(final String message, final String title, final FSkinProp icon, final T initialInput, final T[] inputOptions) {
|
||||
return new WaitCallback<T>() {
|
||||
public String showInputDialog(final String message, final String title, final FSkinProp icon, final String initialInput, final String[] inputOptions) {
|
||||
return new WaitCallback<String>() {
|
||||
@Override
|
||||
public void run() {
|
||||
FOptionPane.showInputDialog(message, title, icon == null ? null : FSkin.getImages().get(icon), initialInput, inputOptions, this);
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Human Rogue
|
||||
PT:0/3
|
||||
A:AB$ Draw | Cost$ T | NumCards$ 1 | SubAbility$ DBExile | SpellDescription$ Draw a card, then exile a card from your hand face down.
|
||||
SVar:DBExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | ChangeType$ Card | ChangeNum$ 1 | ExileFaceDown$ True | Mandatory$ True | RememberChanged$ True
|
||||
S:Mode$ MayLookAt | Affected$ Card.IsRemembered | Player$ You | AffectedZone$ Exile | Description$ You may look at cards exiled with CARDNAME.
|
||||
S:Mode$ Continuous | Affected$ Card.IsRemembered | AffectedZone$ Exile | MayLookAt$ True | Description$ You may look at cards exiled with CARDNAME.
|
||||
A:AB$ ChooseCard | Cost$ U B T | Defined$ You | Amount$ 1 | Mandatory$ True | AILogic$ AtLeast1 | ChoiceTitle$ Choose a card to put into your hand | Choices$ Card.IsRemembered | ChoiceZone$ Exile | SubAbility$ MoveChosen | SpellDescription$ Return a card exiled with CARDNAME to its owner's hand.
|
||||
SVar:MoveChosen:DB$ ChangeZone | Origin$ Exile | Destination$ Hand | Defined$ ChosenCard
|
||||
T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Merfolk Rogue
|
||||
PT:2/2
|
||||
T:Mode$ Taps | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ Whenever CARDNAME becomes tapped, exile the top three cards of target opponent's library face down.
|
||||
SVar:TrigExile:AB$ Mill | Cost$ 0 | ValidTgts$ Opponent | NumCards$ 3 | Destination$ Exile | ExileFaceDown$ True | RememberMilled$ True
|
||||
S:Mode$ MayLookAt | Affected$ Card.IsRemembered | Player$ You | AffectedZone$ Exile | Description$ You may look at cards exiled with CARDNAME.
|
||||
S:Mode$ Continuous | Affected$ Card.IsRemembered | AffectedZone$ Exile | MayLookAt$ True | Description$ You may look at cards exiled with CARDNAME.
|
||||
A:AB$ SetState | Cost$ U Sac<1/CARDNAME> | Defined$ Remembered | Mode$ TurnFace | SubAbility$ DBCounter | SpellDescription$ Turn all cards exiled with CARDNAME face up. Counter all spells with those names.
|
||||
SVar:DBCounter:DB$ Counter | AllType$ Spell | AllValid$ Card.sharesNameWith Remembered | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Name:Gustha's Scepter
|
||||
ManaCost:0
|
||||
Types:Artifact
|
||||
A:AB$ ChangeZone | Cost$ T | ChangeType$ Card | ChangeNum$ 1 | Origin$ Hand | Destination$ Exile | ExileFaceDown$ True | RememberChanged$ True | Mandatory$ True | SpellDescription$ Exile a card from your hand face down. You may look at it for as long as it remains exiled.
|
||||
S:Mode$ MayLookAt | Affected$ Card.IsRemembered | Player$ You | AffectedZone$ Exile
|
||||
A:AB$ ChangeZone | Cost$ T | ChangeType$ Card | ChangeNum$ 1 | Origin$ Hand | Destination$ Exile | ExileFaceDown$ True | RememberChanged$ True | Mandatory$ True | SubAbility$ DBMayLookAt | SpellDescription$ Exile a card from your hand face down. You may look at it for as long as it remains exiled.
|
||||
SVar:DBMayLookAt:DB$ Pump | Defined$ Remembered | PumpZone$ Exile | KW$ You may look at this card. | Permanent$ True
|
||||
A:AB$ ChooseCard | Cost$ T | Defined$ You | Amount$ 1 | Mandatory$ True | AILogic$ AtLeast1 | ChoiceTitle$ Choose a card you own to put into your hand | Choices$ Card.IsRemembered+YouOwn | ChoiceZone$ Exile | SubAbility$ MoveChosen | SpellDescription$ Return a card you own exiled with CARDNAME to your hand.
|
||||
SVar:MoveChosen:DB$ ChangeZone | Origin$ Exile | Destination$ Hand | Defined$ ChosenCard
|
||||
T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
Name:Jester's Scepter
|
||||
ManaCost:3
|
||||
Types:Artifact
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile the top five cards of target player's library face down.
|
||||
SVar:TrigExile:AB$ Mill | Cost$ 0 | ValidTgts$ Player | NumCards$ 5 | Destination$ Exile | ExileFaceDown$ True | RememberMilled$ True
|
||||
S:Mode$ MayLookAt | Affected$ Card.IsRemembered | Player$ You | AffectedZone$ Exile | Description$ You may look at cards exiled with CARDNAME.
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile the top five cards of target player's library face down. You may look at those cards for as long as they remain exiled.
|
||||
SVar:TrigExile:AB$ Mill | Cost$ 0 | ValidTgts$ Player | NumCards$ 5 | Destination$ Exile | ExileFaceDown$ True | RememberMilled$ True | SubAbility$ DBMayLookAt
|
||||
SVar:DBMayLookAt:DB$ Effect | Name$ Jester's Scepter Effect | StaticAbilities$ SMayLookAt | Triggers$ TForget | SVars$ DBForget | RememberObjects$ Remembered | Duration$ Permanent
|
||||
SVar:SMayLookAt:Mode$ Continuous | Affected$ Card.IsRemembered | AffectedZone$ Exile | EffectZone$ Command | MayLookAt$ True | Duration$ Permanent
|
||||
SVar:TForget:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
|
||||
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ DBCleanup | Static$ True
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCard$ Card.IsRemembered | Execute$ DBForget
|
||||
@@ -12,4 +14,4 @@ A:AB$ Counter | Cost$ 2 T ExiledMoveToGrave<1/Card.IsRemembered/card exiled with
|
||||
SVar:X:Targeted$Valid Card.sharesNameWith MovedToGrave
|
||||
SVar:RemAIDeck:True
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/jesters_scepter.jpg
|
||||
Oracle:When Jester's Scepter enters the battlefield, exile the top five cards of target player's library face down. You may look at those cards for as long as they remain exiled.\n{2}, {T}, Put a card exiled with Jester's Scepter into its owner's graveyard: Counter target spell if it has the same name as that card.
|
||||
Oracle:When Jester's Scepter enters the battlefield, exile the top five cards of target player's library face down. You may look at those cards for as long as they remain exiled.\n{2}, {T}, Put a card exiled with Jester's Scepter into its owner's graveyard: Counter target spell if it has the same name as that card.
|
||||
@@ -102,7 +102,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void updateCombat() {
|
||||
private void updateCombat() {
|
||||
if (!isMainHandler || combatUpdPlanned.getAndSet(true)) { return; }
|
||||
|
||||
FThreads.invokeInEdtNowOrLater(gameView.getGui(), new Runnable() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package forge.interfaces;
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
@@ -29,7 +30,7 @@ public interface IGuiBase {
|
||||
void showImageDialog(ISkinImage image, String message, String title);
|
||||
int showOptionDialog(String message, String title, FSkinProp icon, String[] options, int defaultOption);
|
||||
int showCardOptionDialog(CardView card, String message, String title, FSkinProp icon, String[] options, int defaultOption);
|
||||
<T> T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions);
|
||||
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, String[] inputOptions);
|
||||
<T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display);
|
||||
<T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
|
||||
final List<T> sourceChoices, final List<T> destChoices, final CardView referenceCard, final boolean sideboardingMode);
|
||||
|
||||
@@ -192,7 +192,7 @@ public class SGuiChoose {
|
||||
}
|
||||
|
||||
public static <T> List<T> many(final IGuiBase gui, final String title, final String topCaption, int cnt, final List<T> sourceChoices, final CardView referenceCard) {
|
||||
return order(gui, title, topCaption, cnt, cnt, sourceChoices, null, referenceCard, false);
|
||||
return many(gui, title, topCaption, cnt, cnt, sourceChoices, referenceCard);
|
||||
}
|
||||
|
||||
public static <T> List<T> many(final IGuiBase gui, final String title, final String topCaption, int min, int max, final List<T> sourceChoices, final CardView referenceCard) {
|
||||
|
||||
@@ -76,7 +76,7 @@ public class SOptionPane {
|
||||
return showInputDialog(gui, message, title, icon, initialInput, null);
|
||||
}
|
||||
|
||||
public static <T> T showInputDialog(IGuiBase gui, String message, String title, FSkinProp icon, T initialInput, T[] inputOptions) {
|
||||
public static String showInputDialog(IGuiBase gui, String message, String title, FSkinProp icon, String initialInput, String[] inputOptions) {
|
||||
return gui.showInputDialog(message, title, icon, initialInput, inputOptions);
|
||||
}
|
||||
|
||||
|
||||
@@ -726,7 +726,23 @@ public class CardView extends GameEntityView {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getOriginal().toString();
|
||||
if (StringUtils.isEmpty(this.getOriginal().getName())) {
|
||||
if (this.getId() <= 0) {
|
||||
return "(Unknown card)";
|
||||
} else if (this.hasAltState()) {
|
||||
return "Face-down card (" + this.getAlternate().getName() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
return this.getOriginal().getName() + " (" + this.getId() + ")";
|
||||
}
|
||||
|
||||
public String determineName(final CardStateView state) {
|
||||
if (state == original) {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
return this.getAlternate().getName() + " (" + this.getId() + ")";
|
||||
}
|
||||
|
||||
public class CardStateView {
|
||||
@@ -767,10 +783,7 @@ public class CardView extends GameEntityView {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (StringUtils.isEmpty(this.getName()) && this.getCard().getId() <= 0) {
|
||||
return "(Unknown card)";
|
||||
}
|
||||
return this.getName() + " (" + this.getCard().getId() + ")";
|
||||
return this.getCard().determineName(this);
|
||||
}
|
||||
|
||||
public CardView getCard() {
|
||||
|
||||
Reference in New Issue
Block a user