mirror of
https://github.com/correl/mage.git
synced 2024-12-25 03:00:15 +00:00
* Added Morph ability.
This commit is contained in:
parent
b1de70a3bf
commit
d244551e3b
45 changed files with 929 additions and 191 deletions
|
@ -6,6 +6,7 @@ import java.util.ArrayList;
|
|||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingConstants;
|
||||
import mage.client.cards.Permanent;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.MageObjectType;
|
||||
|
@ -221,7 +222,11 @@ public class GuiDisplayUtil {
|
|||
buffer.append(pt).append("</b></td>");
|
||||
buffer.append("<td align='right'>");
|
||||
if (!card.isControlledByOwner()) {
|
||||
buffer.append("[only controlled] ");
|
||||
if (card instanceof PermanentView) {
|
||||
buffer.append("[").append(((PermanentView) card).getNameOwner()).append("] ");
|
||||
} else {
|
||||
buffer.append("[only controlled] ");
|
||||
}
|
||||
}
|
||||
buffer.append(card.getMageObjectType().toString()).append("</td>");
|
||||
buffer.append("</tr></table>");
|
||||
|
|
|
@ -703,7 +703,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
}
|
||||
setText(card);
|
||||
|
||||
boolean updateImage = !gameCard.getName().equals(card.getName()); // update after e.g. turning a night/day card
|
||||
boolean updateImage = !gameCard.getName().equals(card.getName()) || gameCard.isFaceDown() != card.isFaceDown(); // update after e.g. turning a night/day card
|
||||
this.gameCard = card;
|
||||
|
||||
String cardType = getType(card);
|
||||
|
@ -776,7 +776,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
if (gameCard.isFaceDown()) {
|
||||
if (gameCard.hideInfo()) {
|
||||
return;
|
||||
}
|
||||
if (!popupShowing) {
|
||||
|
@ -798,7 +798,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
if (gameCard.isFaceDown()) {
|
||||
if (gameCard.hideInfo()) {
|
||||
return;
|
||||
}
|
||||
data.component = this;
|
||||
|
@ -807,7 +807,7 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
if (gameCard.isFaceDown()) {
|
||||
if (gameCard.hideInfo()) {
|
||||
return;
|
||||
}
|
||||
if (getMousePosition(true) != null) {
|
||||
|
@ -974,10 +974,11 @@ public class CardPanel extends MagePermanent implements MouseListener, MouseMoti
|
|||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (gameCard.isFaceDown()) {
|
||||
if (gameCard.hideInfo()) {
|
||||
return;
|
||||
}
|
||||
data.component = this;
|
||||
callback.mouseWheelMoved(e, data);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public class ImageCache {
|
|||
info.setToken(true);
|
||||
path = CardImageUtils.generateTokenImagePath(info);
|
||||
if (path == null) {
|
||||
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.tokenFrameFilename;
|
||||
path = DirectLinksForDownload.outDir + File.separator + DirectLinksForDownload.cardbackFilename;
|
||||
}
|
||||
} else {
|
||||
path = CardImageUtils.generateImagePath(info);
|
||||
|
@ -180,21 +180,21 @@ public class ImageCache {
|
|||
return getImage(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the Path
|
||||
*/
|
||||
private static BufferedImage getImageByPath(String path) {
|
||||
if (path == null) {
|
||||
return null;
|
||||
}
|
||||
TFile file = new TFile(path);
|
||||
if (!file.exists()) {
|
||||
log.warn("File does not exist: " + file.toString());
|
||||
return null;
|
||||
}
|
||||
return getWizardsCard(loadImage(file));
|
||||
|
||||
}
|
||||
// /**
|
||||
// * Returns the Image corresponding to the Path
|
||||
// */
|
||||
// private static BufferedImage getImageByPath(String path) {
|
||||
// if (path == null) {
|
||||
// return null;
|
||||
// }
|
||||
// TFile file = new TFile(path);
|
||||
// if (!file.exists()) {
|
||||
// log.warn("File does not exist: " + file.toString());
|
||||
// return null;
|
||||
// }
|
||||
// return getWizardsCard(loadImage(file));
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns the Image corresponding to the key
|
||||
|
|
|
@ -9,11 +9,12 @@ import org.mage.plugins.card.properties.SettingsManager;
|
|||
|
||||
public class CardImageUtils {
|
||||
|
||||
private static HashMap<CardDownloadData, String> pathCache = new HashMap<CardDownloadData, String>();
|
||||
private static final HashMap<CardDownloadData, String> pathCache = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param card
|
||||
* @return String if image exists, else null
|
||||
*/
|
||||
public static String generateTokenImagePath(CardDownloadData card) {
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
package mage.view;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import mage.constants.CardType;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
|
||||
|
@ -38,24 +37,25 @@ import mage.abilities.Ability;
|
|||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class AbilityView extends CardView {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String sourceName;
|
||||
private CardView sourceCard;
|
||||
private final String sourceName;
|
||||
private final CardView sourceCard;
|
||||
|
||||
public AbilityView(Ability ability, String sourceName, CardView sourceCard) {
|
||||
this.id = ability.getId();
|
||||
this.name = "Ability";
|
||||
this.sourceName = sourceName;
|
||||
this.sourceCard = sourceCard;
|
||||
this.rules = new ArrayList<String>();
|
||||
this.rules = new ArrayList<>();
|
||||
rules.add(ability.getRule());
|
||||
this.power = "";
|
||||
this.toughness = "";
|
||||
this.loyalty = "";
|
||||
this.cardTypes = new ArrayList<CardType>();
|
||||
this.subTypes = new ArrayList<String>();
|
||||
this.superTypes = new ArrayList<String>();
|
||||
this.cardTypes = new ArrayList<>();
|
||||
this.subTypes = new ArrayList<>();
|
||||
this.superTypes = new ArrayList<>();
|
||||
this.color = new ObjectColor();
|
||||
this.manaCost = ability.getManaCosts().getSymbols();
|
||||
}
|
||||
|
|
|
@ -33,9 +33,12 @@ import java.util.List;
|
|||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Modes;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.common.TurnFaceUpAbility;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.CardType;
|
||||
|
@ -46,6 +49,7 @@ import mage.counters.Counter;
|
|||
import mage.counters.CounterType;
|
||||
import mage.game.command.Emblem;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.game.permanent.token.Token;
|
||||
import mage.game.stack.Spell;
|
||||
|
@ -108,19 +112,48 @@ public class CardView extends SimpleCardView {
|
|||
protected boolean controlledByOwner = true;
|
||||
|
||||
protected boolean rotate;
|
||||
protected boolean hideInfo; // controlls if the tooltip window is shown (eg. controlled face down morph card)
|
||||
|
||||
public CardView(Card card) {
|
||||
this(card, null, false);
|
||||
}
|
||||
|
||||
public CardView(Card card, UUID cardId) {
|
||||
this(card);
|
||||
this(card, null, false);
|
||||
this.id = cardId;
|
||||
}
|
||||
|
||||
public CardView(Card card) {
|
||||
/**
|
||||
*
|
||||
* @param card
|
||||
* @param cardId
|
||||
* @param controlled is the card view created for the card controller - used for morph cards to know which player may see information for the card
|
||||
*/
|
||||
public CardView(Card card, UUID cardId, boolean controlled) {
|
||||
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.isFaceDown(), card.getUsesVariousArt(), card.getTokenSetCode());
|
||||
|
||||
// no information available for face down cards
|
||||
if (this.faceDown) {
|
||||
fillEmpty();
|
||||
return;
|
||||
// no information available for face down cards as long it's not a controlled face down morph card
|
||||
// TODO: Better handle this in Framework (but currently I'm not sure how to do it there) LevelX2
|
||||
if (card.isFaceDown()) {
|
||||
if (card.isMorphCard()) {
|
||||
// special handling for Morph cards
|
||||
this.fillEmpty(card, controlled);
|
||||
if (card instanceof Spell) {
|
||||
if (controlled) {
|
||||
this.name = card.getName();
|
||||
this.displayName = card.getName();
|
||||
}
|
||||
this.power = "2";
|
||||
this.toughness = "2";
|
||||
this.rules.add("You may cast this card as a 2/2 face-down creature, with no text," +
|
||||
" no name, no subtypes, and no mana cost by paying {3} rather than paying its mana cost.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.fillEmpty(card, false);
|
||||
this.hideInfo = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SplitCard splitCard = null;
|
||||
|
@ -241,8 +274,7 @@ public class CardView extends SimpleCardView {
|
|||
this.rules.add("<span color='green'><i>Chosen mode: " + spell.getSpellAbility().getEffects().getText(modes.get(modeId))+"</i></span>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public CardView(MageObject object) {
|
||||
|
@ -309,7 +341,7 @@ public class CardView extends SimpleCardView {
|
|||
if (!empty) {
|
||||
throw new IllegalArgumentException("Not supported.");
|
||||
}
|
||||
fillEmpty();
|
||||
fillEmpty(null, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -319,8 +351,9 @@ public class CardView extends SimpleCardView {
|
|||
this.displayName = name;
|
||||
}
|
||||
|
||||
private void fillEmpty() {
|
||||
private void fillEmpty(Card card, boolean controlled) {
|
||||
this.name = "Face Down";
|
||||
this.displayName = name;
|
||||
this.rules = new ArrayList<>();
|
||||
this.power = "";
|
||||
this.toughness = "";
|
||||
|
@ -331,9 +364,34 @@ public class CardView extends SimpleCardView {
|
|||
this.color = new ObjectColor();
|
||||
this.manaCost = new ArrayList<>();
|
||||
this.convertedManaCost = 0;
|
||||
this.rarity = Rarity.COMMON;
|
||||
this.expansionSetCode = "";
|
||||
this.cardNumber = 0;
|
||||
|
||||
// the controller can see more information (e.g. enlarged image) than other players for face down cards (e.g. Morph played face down)
|
||||
if (!controlled) {
|
||||
this.rarity = Rarity.COMMON;
|
||||
this.expansionSetCode = "";
|
||||
this.cardNumber = 0;
|
||||
} else {
|
||||
this.rarity = card.getRarity();
|
||||
}
|
||||
|
||||
if (card != null) {
|
||||
if (card instanceof Permanent) {
|
||||
this.mageObjectType = MageObjectType.PERMANENT;
|
||||
} else {
|
||||
if (card.isCopy()) {
|
||||
this.mageObjectType = MageObjectType.COPY_CARD;
|
||||
} else {
|
||||
this.mageObjectType = MageObjectType.CARD;
|
||||
}
|
||||
}
|
||||
if (card instanceof PermanentToken) {
|
||||
this.mageObjectType = MageObjectType.TOKEN;
|
||||
}
|
||||
if (card instanceof Spell) {
|
||||
this.mageObjectType = MageObjectType.SPELL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CardView(Token token) {
|
||||
|
@ -611,5 +669,9 @@ public class CardView extends SimpleCardView {
|
|||
public boolean isToRotate() {
|
||||
return rotate;
|
||||
}
|
||||
|
||||
public boolean hideInfo() {
|
||||
return hideInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,10 +43,10 @@ import java.util.UUID;
|
|||
public class CombatGroupView implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private CardsView attackers = new CardsView();
|
||||
private CardsView blockers = new CardsView();
|
||||
private final CardsView attackers = new CardsView();
|
||||
private final CardsView blockers = new CardsView();
|
||||
private String defenderName = "";
|
||||
private UUID defenderId;
|
||||
private final UUID defenderId;
|
||||
|
||||
public CombatGroupView(CombatGroup combatGroup, Game game) {
|
||||
Player player = game.getPlayer(combatGroup.getDefenderId());
|
||||
|
@ -55,19 +55,22 @@ public class CombatGroupView implements Serializable {
|
|||
}
|
||||
else {
|
||||
Permanent perm = game.getPermanent(combatGroup.getDefenderId());
|
||||
if (perm != null)
|
||||
if (perm != null) {
|
||||
this.defenderName = perm.getName();
|
||||
}
|
||||
}
|
||||
this.defenderId = combatGroup.getDefenderId();
|
||||
for (UUID id: combatGroup.getAttackers()) {
|
||||
Permanent attacker = game.getPermanent(id);
|
||||
if (attacker != null)
|
||||
attackers.put(id, new PermanentView(attacker, game.getCard(attacker.getId())));
|
||||
if (attacker != null) {
|
||||
attackers.put(id, new PermanentView(attacker, game.getCard(attacker.getId()),null, game));
|
||||
}
|
||||
}
|
||||
for (UUID id: combatGroup.getBlockerOrder()) {
|
||||
Permanent blocker = game.getPermanent(id);
|
||||
if (blocker != null)
|
||||
blockers.put(id, new PermanentView(blocker, game.getCard(blocker.getId())));
|
||||
if (blocker != null) {
|
||||
blockers.put(id, new PermanentView(blocker, game.getCard(blocker.getId()), null, game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public class GameEndView implements Serializable {
|
|||
int winner = 0;
|
||||
Player you = null;
|
||||
for (Player player: state.getPlayers().values()) {
|
||||
PlayerView playerView = new PlayerView(player, state, game);
|
||||
PlayerView playerView = new PlayerView(player, state, game, playerId);
|
||||
if (playerView.getPlayerId().equals(playerId)) {
|
||||
clientPlayer = playerView;
|
||||
you = player;
|
||||
|
|
|
@ -60,14 +60,14 @@ public class GameView implements Serializable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int priorityTime;
|
||||
private final List<PlayerView> players = new ArrayList<PlayerView>();
|
||||
private final List<PlayerView> players = new ArrayList<>();
|
||||
private SimpleCardsView hand;
|
||||
private Map<String, SimpleCardsView> opponentHands;
|
||||
private final CardsView stack = new CardsView();
|
||||
private final List<ExileView> exiles = new ArrayList<ExileView>();
|
||||
private final List<RevealedView> revealed = new ArrayList<RevealedView>();
|
||||
private List<LookedAtView> lookedAt = new ArrayList<LookedAtView>();
|
||||
private final List<CombatGroupView> combat = new ArrayList<CombatGroupView>();
|
||||
private final List<ExileView> exiles = new ArrayList<>();
|
||||
private final List<RevealedView> revealed = new ArrayList<>();
|
||||
private List<LookedAtView> lookedAt = new ArrayList<>();
|
||||
private final List<CombatGroupView> combat = new ArrayList<>();
|
||||
private final TurnPhase phase;
|
||||
private final PhaseStep step;
|
||||
private final UUID activePlayerId;
|
||||
|
@ -78,11 +78,11 @@ public class GameView implements Serializable {
|
|||
private final boolean isPlayer;
|
||||
|
||||
|
||||
public GameView(GameState state, Game game, boolean isPlayer) {
|
||||
this.isPlayer = isPlayer;
|
||||
public GameView(GameState state, Game game, UUID createdForPlayerId) {
|
||||
this.isPlayer = createdForPlayerId != null;
|
||||
this.priorityTime = game.getPriorityTime();
|
||||
for (Player player: state.getPlayers().values()) {
|
||||
players.add(new PlayerView(player, state, game));
|
||||
players.add(new PlayerView(player, state, game, createdForPlayerId));
|
||||
}
|
||||
for (StackObject stackObject: state.getStack()) {
|
||||
if (stackObject instanceof StackAbility) {
|
||||
|
@ -127,7 +127,7 @@ public class GameView implements Serializable {
|
|||
}
|
||||
else {
|
||||
// Spell
|
||||
stack.put(stackObject.getId(), new CardView((Spell)stackObject));
|
||||
stack.put(stackObject.getId(), new CardView((Spell)stackObject, null, stackObject.getControllerId().equals(createdForPlayerId)));
|
||||
checkPaid(stackObject.getId(), (Spell)stackObject);
|
||||
}
|
||||
//stackOrder.add(stackObject.getId());
|
||||
|
|
|
@ -31,9 +31,16 @@ package mage.view;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.TurnFaceUpAbility;
|
||||
import mage.abilities.common.TurnedFaceUpTriggeredAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Rarity;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
import mage.game.permanent.PermanentToken;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -45,20 +52,21 @@ public class PermanentView extends CardView {
|
|||
private boolean tapped;
|
||||
private final boolean flipped;
|
||||
private final boolean phasedIn;
|
||||
private final boolean faceUp;
|
||||
private final boolean summoningSickness;
|
||||
private final int damage;
|
||||
private List<UUID> attachments;
|
||||
private final CardView original;
|
||||
private final boolean copy;
|
||||
private final String nameOwner; // only filled if != controller
|
||||
private final boolean controlled;
|
||||
|
||||
public PermanentView(Permanent permanent, Card card) {
|
||||
super(permanent);
|
||||
public PermanentView(Permanent permanent, Card card, UUID createdForPlayerId, Game game) {
|
||||
super(permanent, null, permanent.getControllerId().equals(createdForPlayerId));
|
||||
this.controlled = permanent.getControllerId().equals(createdForPlayerId);
|
||||
this.rules = permanent.getRules();
|
||||
this.tapped = permanent.isTapped();
|
||||
this.flipped = permanent.isFlipped();
|
||||
this.phasedIn = permanent.isPhasedIn();
|
||||
this.faceUp = permanent.isFaceUp();
|
||||
this.summoningSickness = permanent.hasSummoningSickness();
|
||||
this.damage = permanent.getDamage();
|
||||
if (permanent.getAttachments().size() > 0) {
|
||||
|
@ -90,6 +98,41 @@ public class PermanentView extends CardView {
|
|||
this.originalName = this.getName();
|
||||
}
|
||||
}
|
||||
if (!permanent.getOwnerId().equals(permanent.getControllerId())) {
|
||||
Player owner = game.getPlayer(permanent.getOwnerId());
|
||||
if (owner != null) {
|
||||
this.nameOwner = owner.getName();
|
||||
} else {
|
||||
this.nameOwner = "";
|
||||
}
|
||||
} else {
|
||||
this.nameOwner = "";
|
||||
}
|
||||
|
||||
if (permanent.isFaceDown() && permanent.isMorphCard()) {
|
||||
// add morph rule text
|
||||
if (card != null) {
|
||||
if (controlled) {
|
||||
for (Ability permanentAbility : permanent.getAbilities()) {
|
||||
if (permanentAbility instanceof TurnFaceUpAbility && !permanentAbility.getRuleVisible()) {
|
||||
this.rules.add(permanentAbility.getRule(true));
|
||||
}
|
||||
if (permanentAbility instanceof TurnedFaceUpTriggeredAbility) {
|
||||
this.rules.add(permanentAbility.getRule());
|
||||
}
|
||||
}
|
||||
this.name = card.getName();
|
||||
this.expansionSetCode = card.getExpansionSetCode();
|
||||
this.cardNumber = card.getCardNumber();
|
||||
} else {
|
||||
this.rules.add("If the controller has priority, he or she may turn this permanent face up." +
|
||||
" This is a special action; it doesnt use the stack. To do this he or she pays the morph costs," +
|
||||
" then turns this permanent face up.");
|
||||
this.rarity = Rarity.COMMON;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -113,10 +156,6 @@ public class PermanentView extends CardView {
|
|||
return phasedIn;
|
||||
}
|
||||
|
||||
public boolean isFaceUp() {
|
||||
return faceUp;
|
||||
}
|
||||
|
||||
public boolean hasSummoningSickness(){
|
||||
return summoningSickness;
|
||||
}
|
||||
|
@ -132,4 +171,13 @@ public class PermanentView extends CardView {
|
|||
public void overrideTapped(boolean tapped) {
|
||||
this.tapped = tapped;
|
||||
}
|
||||
|
||||
public String getNameOwner() {
|
||||
return nameOwner;
|
||||
}
|
||||
|
||||
public boolean isControlled() {
|
||||
return controlled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class PlayerView implements Serializable {
|
|||
private final int statesSavedSize;
|
||||
private final int priorityTimeLeft;
|
||||
|
||||
public PlayerView(Player player, GameState state, Game game) {
|
||||
public PlayerView(Player player, GameState state, Game game, UUID createdForPlayerId) {
|
||||
this.playerId = player.getId();
|
||||
this.name = player.getName();
|
||||
this.life = player.getLife();
|
||||
|
@ -83,7 +83,7 @@ public class PlayerView implements Serializable {
|
|||
}
|
||||
for (Permanent permanent: state.getBattlefield().getAllPermanents()) {
|
||||
if (showInBattlefield(permanent, state)) {
|
||||
PermanentView view = new PermanentView(permanent, game.getCard(permanent.getId()));
|
||||
PermanentView view = new PermanentView(permanent, game.getCard(permanent.getId()), createdForPlayerId, game);
|
||||
battlefield.put(view.getId(), view);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -597,7 +597,7 @@ public class GameController implements GameCallback {
|
|||
} else if (perms != null) {
|
||||
CardsView permsView = new CardsView();
|
||||
for (Permanent perm: perms) {
|
||||
permsView.put(perm.getId(), new PermanentView(perm, game.getCard(perm.getId())));
|
||||
permsView.put(perm.getId(), new PermanentView(perm, game.getCard(perm.getId()), playerId, game));
|
||||
}
|
||||
getGameSession(playerId).target(question, permsView, targets, required, options);
|
||||
} else {
|
||||
|
|
|
@ -240,7 +240,7 @@ public class GameSession extends GameWatcher {
|
|||
public GameView getGameView() {
|
||||
Player player = game.getPlayer(playerId);
|
||||
player.setUserData(this.userData);
|
||||
GameView gameView = new GameView(game.getState(), game, this.isPlayer);
|
||||
GameView gameView = new GameView(game.getState(), game, playerId);
|
||||
gameView.setHand(new SimpleCardsView(player.getHand().getCards(game)));
|
||||
|
||||
if (player.getPlayersUnderYourControl().size() > 0) {
|
||||
|
|
|
@ -120,7 +120,7 @@ public class GameWatcher {
|
|||
}
|
||||
|
||||
public GameView getGameView() {
|
||||
return new GameView(game.getState(), game, this.isPlayer);
|
||||
return new GameView(game.getState(), game, null);
|
||||
}
|
||||
|
||||
public GameEndView getGameEndView(UUID playerId, Match match) {
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ReplaySession implements GameCallback {
|
|||
replay.start();
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
user.fireCallback(new ClientCallback("replayInit", replay.getGame().getId(), new GameView(replay.next(), replay.getGame(), false)));
|
||||
user.fireCallback(new ClientCallback("replayInit", replay.getGame().getId(), new GameView(replay.next(), replay.getGame(), null)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public class ReplaySession implements GameCallback {
|
|||
else {
|
||||
User user = UserManager.getInstance().getUser(userId);
|
||||
if (user != null) {
|
||||
user.fireCallback(new ClientCallback("replayUpdate", replay.getGame().getId(), new GameView(state, game, false)));
|
||||
user.fireCallback(new ClientCallback("replayUpdate", replay.getGame().getId(), new GameView(state, game, null)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,6 @@
|
|||
package mage.sets.newphyrexia;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.MageInt;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Abilities;
|
||||
|
@ -44,6 +41,9 @@ import mage.abilities.mana.TriggeredManaAbility;
|
|||
import mage.cards.CardImpl;
|
||||
import mage.choices.Choice;
|
||||
import mage.choices.ChoiceImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
|
@ -99,10 +99,7 @@ class VorinclexTriggeredAbility1 extends TriggeredManaAbility {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.TAPPED_FOR_MANA && event.getPlayerId().equals(controllerId)) {
|
||||
Permanent permanent = game.getPermanent(event.getSourceId());
|
||||
if (permanent == null) {
|
||||
permanent = (Permanent) game.getLastKnownInformation(event.getSourceId(), Zone.BATTLEFIELD);
|
||||
}
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getSourceId());
|
||||
if (permanent != null && permanent.getCardType().contains(CardType.LAND)) {
|
||||
getEffects().get(0).setTargetPointer(new FixedTarget(permanent.getId()));
|
||||
return true;
|
||||
|
@ -136,7 +133,7 @@ class VorinclexEffect extends ManaEffect {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Permanent land = game.getPermanent(this.targetPointer.getFirst(game, source));
|
||||
Permanent land = game.getPermanentOrLKIBattlefield(this.targetPointer.getFirst(game, source));
|
||||
Abilities<ManaAbility> mana = land.getAbilities().getManaAbilities(Zone.BATTLEFIELD);
|
||||
Mana types = new Mana();
|
||||
for (ManaAbility ability: mana) {
|
||||
|
@ -144,47 +141,50 @@ class VorinclexEffect extends ManaEffect {
|
|||
}
|
||||
Choice choice = new ChoiceImpl(true);
|
||||
choice.setMessage("Pick a mana color");
|
||||
if (types.getBlack() > 0)
|
||||
if (types.getBlack() > 0) {
|
||||
choice.getChoices().add("Black");
|
||||
if (types.getRed() > 0)
|
||||
}
|
||||
if (types.getRed() > 0) {
|
||||
choice.getChoices().add("Red");
|
||||
if (types.getBlue() > 0)
|
||||
}
|
||||
if (types.getBlue() > 0) {
|
||||
choice.getChoices().add("Blue");
|
||||
if (types.getGreen() > 0)
|
||||
}
|
||||
if (types.getGreen() > 0) {
|
||||
choice.getChoices().add("Green");
|
||||
if (types.getWhite() > 0)
|
||||
}
|
||||
if (types.getWhite() > 0) {
|
||||
choice.getChoices().add("White");
|
||||
if (types.getColorless() > 0)
|
||||
}
|
||||
if (types.getColorless() > 0) {
|
||||
choice.getChoices().add("Colorless");
|
||||
}
|
||||
if (choice.getChoices().size() > 0) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (choice.getChoices().size() == 1)
|
||||
if (choice.getChoices().size() == 1) {
|
||||
choice.setChoice(choice.getChoices().iterator().next());
|
||||
else
|
||||
} else {
|
||||
player.choose(outcome, choice, game);
|
||||
if (choice.getChoice().equals("Black")) {
|
||||
player.getManaPool().addMana(Mana.BlackMana, game, source);
|
||||
return true;
|
||||
}
|
||||
else if (choice.getChoice().equals("Blue")) {
|
||||
player.getManaPool().addMana(Mana.BlueMana, game, source);
|
||||
return true;
|
||||
}
|
||||
else if (choice.getChoice().equals("Red")) {
|
||||
player.getManaPool().addMana(Mana.RedMana, game, source);
|
||||
return true;
|
||||
}
|
||||
else if (choice.getChoice().equals("Green")) {
|
||||
player.getManaPool().addMana(Mana.GreenMana, game, source);
|
||||
return true;
|
||||
}
|
||||
else if (choice.getChoice().equals("White")) {
|
||||
player.getManaPool().addMana(Mana.WhiteMana, game, source);
|
||||
return true;
|
||||
}
|
||||
else if (choice.getChoice().equals("Colorless")) {
|
||||
player.getManaPool().addMana(Mana.ColorlessMana, game, source);
|
||||
return true;
|
||||
switch (choice.getChoice()) {
|
||||
case "Black":
|
||||
player.getManaPool().addMana(Mana.BlackMana, game, source);
|
||||
return true;
|
||||
case "Blue":
|
||||
player.getManaPool().addMana(Mana.BlueMana, game, source);
|
||||
return true;
|
||||
case "Red":
|
||||
player.getManaPool().addMana(Mana.RedMana, game, source);
|
||||
return true;
|
||||
case "Green":
|
||||
player.getManaPool().addMana(Mana.GreenMana, game, source);
|
||||
return true;
|
||||
case "White":
|
||||
player.getManaPool().addMana(Mana.WhiteMana, game, source);
|
||||
return true;
|
||||
case "Colorless":
|
||||
player.getManaPool().addMana(Mana.ColorlessMana, game, source);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -13,6 +13,7 @@ import mage.game.Game;
|
|||
public interface MageObject extends MageItem, Serializable {
|
||||
|
||||
String getName();
|
||||
String getLogName();
|
||||
String getImageName();
|
||||
void setName(String name);
|
||||
|
||||
|
|
|
@ -94,6 +94,10 @@ public abstract class MageObjectImpl implements MageObject {
|
|||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageName() {
|
||||
|
|
|
@ -821,14 +821,14 @@ public abstract class AbilityImpl implements Ability {
|
|||
if (object instanceof StackAbility) {
|
||||
Card card = game.getCard(((StackAbility) object).getSourceId());
|
||||
if (card != null) {
|
||||
sb.append(card.getName());
|
||||
sb.append(card.getLogName());
|
||||
} else {
|
||||
sb.append(object.getName());
|
||||
}
|
||||
} else {
|
||||
if (object instanceof Spell) {
|
||||
Spell spell = (Spell) object;
|
||||
String castText = spell.getSpellAbility().toString();
|
||||
String castText = spell.getSpellCastText(game);
|
||||
sb.append((castText.startsWith("Cast ") ? castText.substring(5):castText));
|
||||
if (spell.getFromZone() == Zone.GRAVEYARD) {
|
||||
sb.append(" from graveyard");
|
||||
|
|
|
@ -82,8 +82,8 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
Player player = game.getPlayer(this.getControllerId());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (object != null) {
|
||||
sb.append("Use the following ability from ").append(object.getName()).append("? ");
|
||||
sb.append(this.getRule(object.getName()));
|
||||
sb.append("Use the following ability from ").append(object.getLogName()).append("? ");
|
||||
sb.append(this.getRule(object.getLogName()));
|
||||
}
|
||||
else {
|
||||
sb.append("Use the following ability? ").append(this.getRule());
|
||||
|
@ -104,7 +104,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
MageObject object = game.getObject(sourceId);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (object != null) {
|
||||
sb.append("Ability triggers: ").append(object.getName()).append(" - ").append(this.getRule(object.getName()));
|
||||
sb.append("Ability triggers: ").append(object.getLogName()).append(" - ").append(this.getRule(object.getLogName()));
|
||||
} else {
|
||||
sb.append("Ability triggers: ").append(this.getRule());
|
||||
}
|
||||
|
|
97
Mage/src/mage/abilities/common/TurnFaceUpAbility.java
Normal file
97
Mage/src/mage/abilities/common/TurnFaceUpAbility.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class TurnFaceUpAbility extends ActivatedAbilityImpl {
|
||||
|
||||
public TurnFaceUpAbility(Costs costs) {
|
||||
super(Zone.BATTLEFIELD, new TurnFaceUpEffect(), costs);
|
||||
this.usesStack = false;
|
||||
this.setRuleVisible(false); // will be made visible only to controller in CardView
|
||||
}
|
||||
|
||||
public TurnFaceUpAbility(final TurnFaceUpAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TurnFaceUpAbility copy() {
|
||||
return new TurnFaceUpAbility(this);
|
||||
}
|
||||
}
|
||||
|
||||
class TurnFaceUpEffect extends OneShotEffect {
|
||||
|
||||
public TurnFaceUpEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "Turn this face-down permanent face up";
|
||||
}
|
||||
|
||||
public TurnFaceUpEffect(final TurnFaceUpEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TurnFaceUpEffect copy() {
|
||||
return new TurnFaceUpEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (controller != null && card !=null) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
if (sourcePermanent != null) {
|
||||
if (sourcePermanent.turnFaceUp(game, source.getControllerId())) {
|
||||
game.informPlayers(controller.getName() + " pays the costs of " + card.getLogName() + " to turn it face up");
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
package mage.abilities.common;
|
||||
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class TurnedFaceUpTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
public TurnedFaceUpTriggeredAbility(Effect effect) {
|
||||
super(Zone.BATTLEFIELD, effect);
|
||||
}
|
||||
|
||||
public TurnedFaceUpTriggeredAbility(final TurnedFaceUpTriggeredAbility ability) {
|
||||
super(ability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TurnedFaceUpTriggeredAbility copy() {
|
||||
return new TurnedFaceUpTriggeredAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
return EventType.TURNEDFACEUP.equals(event.getType()) && event.getTargetId().equals(this.getSourceId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "When {this} is turned face up, " + super.getRule();
|
||||
}
|
||||
}
|
|
@ -105,7 +105,7 @@ public class RemoveCounterCost extends CostImpl {
|
|||
}
|
||||
}
|
||||
choice.setChoices(choices);
|
||||
choice.setMessage("Choose a counter to remove from " + permanent.getName());
|
||||
choice.setMessage("Choose a counter to remove from " + permanent.getLogName());
|
||||
controller.choose(Outcome.UnboostCreature, choice, game);
|
||||
counterName = choice.getChoice();
|
||||
} else {
|
||||
|
@ -122,7 +122,7 @@ public class RemoveCounterCost extends CostImpl {
|
|||
int numberOfCountersSelected = 1;
|
||||
if (countersLeft > 1 && countersOnPermanent > 1) {
|
||||
numberOfCountersSelected = controller.getAmount(1, Math.min(countersLeft, countersOnPermanent),
|
||||
new StringBuilder("Remove how many counters from ").append(permanent.getName()).toString(), game);
|
||||
new StringBuilder("Remove how many counters from ").append(permanent.getLogName()).toString(), game);
|
||||
}
|
||||
permanent.removeCounters(counterName, numberOfCountersSelected, game);
|
||||
if (permanent.getCounters().getCount(counterName) == 0 ){
|
||||
|
|
|
@ -911,7 +911,7 @@ public class ContinuousEffects implements Serializable {
|
|||
for (Ability ability :(HashSet<Ability>) entry.getValue()) {
|
||||
MageObject object = game.getObject(ability.getSourceId());
|
||||
if (object != null) {
|
||||
texts.add(ability.getRule(object.getName()));
|
||||
texts.add(ability.getRule(object.getLogName()));
|
||||
} else {
|
||||
texts.add(((ReplacementEffect)entry.getKey()).getText(null));
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
|
|||
if (controller == null || object == null) {
|
||||
return false;
|
||||
}
|
||||
if (!controller.chooseUse(outcome, new StringBuilder("Use effect of ").append(object.getName()).append("?").toString(), game)) {
|
||||
if (!controller.chooseUse(outcome, new StringBuilder("Use effect of ").append(object.getLogName()).append("?").toString(), game)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ public class PlaneswalkerRedirectionEffect extends RedirectionEffect {
|
|||
game.informPlayers(new StringBuilder(player.getName()).append(" redirects ")
|
||||
.append(event.getAmount())
|
||||
.append(" damage to ")
|
||||
.append(game.getPermanent(redirectTarget.getFirstTarget()).getName()).toString());
|
||||
.append(game.getPermanent(redirectTarget.getFirstTarget()).getLogName()).toString());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class ChooseColorEffect extends OneShotEffect {
|
|||
if (player != null && permanent != null) {
|
||||
ChoiceColor colorChoice = new ChoiceColor();
|
||||
if (player.choose(outcome, colorChoice, game)) {
|
||||
game.informPlayers(new StringBuilder(permanent.getName()).append(": ").append(player.getName()).append(" has chosen ").append(colorChoice.getChoice()).toString());
|
||||
game.informPlayers(new StringBuilder(permanent.getLogName()).append(": ").append(player.getName()).append(" has chosen ").append(colorChoice.getChoice()).toString());
|
||||
game.getState().setValue(source.getSourceId() + "_color", colorChoice.getColor());
|
||||
permanent.addInfo("chosen color", "<font color = 'blue'>Chosen color: " + colorChoice.getColor().getDescription() + "</font>");
|
||||
}
|
||||
|
|
|
@ -94,12 +94,12 @@ public class CipherEffect extends OneShotEffect {
|
|||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
Permanent targetCreature = game.getPermanent(target.getFirstTarget());
|
||||
if (targetCreature != null && sourceCard != null) {
|
||||
String ruleText = new StringBuilder("you may cast a copy of ").append(sourceCard.getName()).append(" without paying its mana cost").toString();
|
||||
String ruleText = new StringBuilder("you may cast a copy of ").append(sourceCard.getLogName()).append(" without paying its mana cost").toString();
|
||||
Ability ability = new DealsCombatDamageToAPlayerTriggeredAbility(new CipherStoreEffect(source.getSourceId(), ruleText), true);
|
||||
ContinuousEffect effect = new GainAbilityTargetEffect(ability, Duration.Custom);
|
||||
effect.setTargetPointer(new FixedTarget(target.getFirstTarget()));
|
||||
game.addEffect(effect, source);
|
||||
game.informPlayers(new StringBuilder(sourceCard.getName()).append(": Spell ciphered to ").append(targetCreature.getName()).toString());
|
||||
game.informPlayers(new StringBuilder(sourceCard.getLogName()).append(": Spell ciphered to ").append(targetCreature.getLogName()).toString());
|
||||
return sourceCard.moveToExile(null, "", source.getId(), game);
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -104,7 +104,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
if (informPlayers) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
game.informPlayers(new StringBuilder(player.getName()).append(" puts ").append(newCounter.getCount()).append(" ").append(newCounter.getName().toLowerCase()).append(" counter on ").append(card.getName()).toString());
|
||||
game.informPlayers(new StringBuilder(player.getName()).append(" puts ").append(newCounter.getCount()).append(" ").append(newCounter.getName().toLowerCase()).append(" counter on ").append(card.getLogName()).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ public class AddCountersSourceEffect extends OneShotEffect {
|
|||
if (informPlayers) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player != null) {
|
||||
game.informPlayers(new StringBuilder(player.getName()).append(" puts ").append(newCounter.getCount()).append(" ").append(newCounter.getName().toLowerCase()).append(" counter on ").append(permanent.getName()).toString());
|
||||
game.informPlayers(new StringBuilder(player.getName()).append(" puts ").append(newCounter.getCount()).append(" ").append(newCounter.getName().toLowerCase()).append(" counter on ").append(permanent.getLogName()).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,10 +93,10 @@ public class AddCountersTargetEffect extends OneShotEffect {
|
|||
newCounter.add(amount.calculate(game, source));
|
||||
permanent.addCounters(newCounter, game);
|
||||
affectedTargets ++;
|
||||
game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ")
|
||||
game.informPlayers(new StringBuilder(sourceObject.getLogName()).append(": ")
|
||||
.append(controller.getName()).append(" puts ")
|
||||
.append(counter.getCount()).append(" ").append(counter.getName().toLowerCase())
|
||||
.append(" counter on ").append(permanent.getName()).toString());
|
||||
.append(" counter on ").append(permanent.getLogName()).toString());
|
||||
}
|
||||
} else {
|
||||
Player player = game.getPlayer(uuid);
|
||||
|
@ -105,7 +105,7 @@ public class AddCountersTargetEffect extends OneShotEffect {
|
|||
newCounter.add(amount.calculate(game, source));
|
||||
player.addCounters(newCounter, game);
|
||||
affectedTargets ++;
|
||||
game.informPlayers(new StringBuilder(sourceObject.getName()).append(": ")
|
||||
game.informPlayers(new StringBuilder(sourceObject.getLogName()).append(": ")
|
||||
.append(controller.getName()).append(" puts ")
|
||||
.append(counter.getCount()).append(" ").append(counter.getName().toLowerCase())
|
||||
.append(" counter on ").append(player.getName()).toString());
|
||||
|
|
348
Mage/src/mage/abilities/keyword/MorphAbility.java
Normal file
348
Mage/src/mage/abilities/keyword/MorphAbility.java
Normal file
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.StaticAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.common.TurnFaceUpAbility;
|
||||
import mage.abilities.common.TurnedFaceUpTriggeredAbility;
|
||||
import mage.abilities.costs.AlternativeCost2;
|
||||
import mage.abilities.costs.AlternativeCost2Impl;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.Costs;
|
||||
import mage.abilities.costs.CostsImpl;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ContinuousEffectImpl;
|
||||
import mage.abilities.effects.common.continious.SourceEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
* 702.36. Morph
|
||||
*
|
||||
* 702.36a Morph is a static ability that functions in any zone from which you could play
|
||||
* the card its on, and the morph effect works any time the card is face down.
|
||||
* "Morph [cost]" means "You may cast this card as a 2/2 face-down creature, with no text,
|
||||
* no name, no subtypes, and no mana cost by paying {3} rather than paying its mana cost."
|
||||
* (See rule 707, "Face-Down Spells and Permanents.")
|
||||
*
|
||||
* 702.36b To cast a card using its morph ability, turn it face down. It becomes a 2/2
|
||||
* face-down creature card, with no text, no name, no subtypes, and no mana cost. Any
|
||||
* effects or prohibitions that would apply to casting a card with these characteristics
|
||||
* (and not the face-up cards characteristics) are applied to casting this card. These
|
||||
* values are the copiable values of that objects characteristics. (See rule 613,
|
||||
* "Interaction of Continuous Effects," and rule 706, "Copying Objects.") Put it onto the
|
||||
* stack (as a face-down spell with the same characteristics), and pay {3} rather than pay
|
||||
* its mana cost. This follows the rules for paying alternative costs. You can use morph
|
||||
* to cast a card from any zone from which you could normally play it. When the spell
|
||||
* resolves, it enters the battlefield with the same characteristics the spell had. The
|
||||
* morph effect applies to the face-down object wherever it is, and it ends when the
|
||||
* permanent is turned face up. #
|
||||
*
|
||||
* 702.36c You cant cast a card face down if it doesnt have morph.
|
||||
*
|
||||
* 702.36d If you have priority, you may turn a face-down permanent you control face up.
|
||||
* This is a special action; it doesnt use the stack (see rule 115). To do this, show
|
||||
* all players what the permanents morph cost would be if it were face up, pay that cost,
|
||||
* then turn the permanent face up. (If the permanent wouldnt have a morph cost if it
|
||||
* were face up, it cant be turned face up this way.) The morph effect on it ends, and
|
||||
* it regains its normal characteristics. Any abilities relating to the permanent entering
|
||||
* the battlefield dont trigger when its turned face up and dont have any effect, because
|
||||
* the permanent has already entered the battlefield.
|
||||
*
|
||||
* 702.36e See rule 707, "Face-Down Spells and Permanents," for more information on how to
|
||||
* cast cards with morph.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
public class MorphAbility extends StaticAbility implements AlternativeSourceCosts {
|
||||
|
||||
protected static final String ABILITY_KEYWORD = "Morph";
|
||||
protected static final String REMINDER_TEXT = "(You may cast this face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)";
|
||||
protected String morphCostsText;
|
||||
protected List<AlternativeCost2> alternateCosts = new LinkedList<>();
|
||||
|
||||
// needed to check activation status, if card changes zone after casting it
|
||||
private int zoneChangeCounter = 0;
|
||||
|
||||
public MorphAbility(Card card, Cost morphCost) {
|
||||
this(card, createCosts(morphCost));
|
||||
}
|
||||
|
||||
public MorphAbility(Card card, Costs morphCosts) {
|
||||
super(Zone.HAND, null);
|
||||
card.setMorphCard(true);
|
||||
name = ABILITY_KEYWORD;
|
||||
morphCostsText = morphCosts.getText();
|
||||
alternateCosts.add(new AlternativeCost2Impl(ABILITY_KEYWORD, REMINDER_TEXT, new GenericManaCost(3)));
|
||||
|
||||
Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesFaceDownCreatureEffect(morphCosts));
|
||||
ability.setRuleVisible(false);
|
||||
card.addAbility(ability);
|
||||
|
||||
}
|
||||
|
||||
public MorphAbility(final MorphAbility ability) {
|
||||
super(ability);
|
||||
this.alternateCosts.addAll(ability.alternateCosts);
|
||||
this.zoneChangeCounter = ability.zoneChangeCounter;
|
||||
}
|
||||
|
||||
private static Costs createCosts(Cost cost) {
|
||||
Costs costs = new CostsImpl();
|
||||
costs.add(cost);
|
||||
return costs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MorphAbility copy() {
|
||||
return new MorphAbility(this);
|
||||
}
|
||||
|
||||
public void resetMorph() {
|
||||
for (AlternativeCost2 cost: alternateCosts) {
|
||||
cost.reset();
|
||||
}
|
||||
zoneChangeCounter = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActivated(Ability ability, Game game) {
|
||||
Card card = game.getCard(sourceId);
|
||||
if (card != null && card.getZoneChangeCounter() <= zoneChangeCounter +1) {
|
||||
for (AlternativeCost2 cost: alternateCosts) {
|
||||
if(cost.isActivated(game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(Ability source, Game game) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean askToActivateAlternativeCosts(Ability ability, Game game) {
|
||||
if (ability instanceof SpellAbility) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player != null) {
|
||||
this.resetMorph();
|
||||
for (AlternativeCost2 alternateCastingCost: alternateCosts) {
|
||||
if (alternateCastingCost.canPay(sourceId, controllerId, game) &&
|
||||
player.chooseUse(Outcome.Benefit, new StringBuilder("Cast this card as a 2/2 face-down creature for ").append(alternateCastingCost.getText(true)).append(" ?").toString(), game)) {
|
||||
|
||||
Spell spell = game.getStack().getSpell(ability.getId());
|
||||
if (spell != null) {
|
||||
spell.setFaceDown(true);
|
||||
} activateMorph(alternateCastingCost, game);
|
||||
ability.getManaCostsToPay().clear();
|
||||
ability.getCosts().clear();
|
||||
for (Iterator it = ((Costs) alternateCastingCost).iterator(); it.hasNext();) {
|
||||
Cost cost = (Cost) it.next();
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Card card = game.getCard(getSourceId()); // face down was set to true in PlayerImpl.cast, reset it here if not cast face down
|
||||
if (card != null) {
|
||||
card.setFaceDown(false);
|
||||
}
|
||||
Spell spell = game.getStack().getSpell(ability.getId());
|
||||
if (spell != null) {
|
||||
spell.setFaceDown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isActivated(ability, game);
|
||||
}
|
||||
|
||||
private void activateMorph(AlternativeCost2 cost, Game game) {
|
||||
cost.activate();
|
||||
// remember zone change counter
|
||||
if (zoneChangeCounter == 0) {
|
||||
Card card = game.getCard(getSourceId());
|
||||
if (card != null) {
|
||||
zoneChangeCounter = card.getZoneChangeCounter();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Morph source card not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int numberCosts = 0;
|
||||
String remarkText = "";
|
||||
for (AlternativeCost2 alternateCastingCost: alternateCosts) {
|
||||
if (numberCosts == 0) {
|
||||
sb.append(alternateCastingCost.getText(false));
|
||||
remarkText = alternateCastingCost.getReminderText();
|
||||
} else {
|
||||
sb.append(" and/or ").append(alternateCastingCost.getText(true));
|
||||
}
|
||||
++numberCosts;
|
||||
}
|
||||
if (numberCosts == 1) {
|
||||
sb.append(" ").append(remarkText);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCastMessageSuffix(Game game) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int position = 0;
|
||||
for (AlternativeCost2 cost : alternateCosts) {
|
||||
if (cost.isActivated(game)) {
|
||||
sb.append(cost.getCastSuffixMessage(position));
|
||||
++position;
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This effect lets the creature always be a 2/2 face-down creature, with no text,
|
||||
* no name, no subtypes, and no mana cost, if it's fac down on the battlefield.
|
||||
* And it adds the MorphTurnFaceUpAbility ability.
|
||||
* TODO: Check if it's better to create this effect always as a creature on the battelfield turns face down or
|
||||
* a creature enters the battlefield face down. Then the effect could be removed as the permanent turns face up.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
class BecomesFaceDownCreatureEffect extends ContinuousEffectImpl implements SourceEffect {
|
||||
|
||||
protected int zoneChangeCounter;
|
||||
protected Ability turnFaceUpAbility = null;
|
||||
|
||||
public BecomesFaceDownCreatureEffect(Costs morphCosts) {
|
||||
super(Duration.WhileOnBattlefield, Outcome.BecomeCreature);
|
||||
this.zoneChangeCounter = Integer.MIN_VALUE;
|
||||
if (morphCosts != null) {
|
||||
this.turnFaceUpAbility = new TurnFaceUpAbility(morphCosts);
|
||||
}
|
||||
staticText = "{this} becomes a 2/2 face-down creature, with no text, no name, no subtypes, and no mana cost";
|
||||
}
|
||||
|
||||
public BecomesFaceDownCreatureEffect(final BecomesFaceDownCreatureEffect effect) {
|
||||
super(effect);
|
||||
this.zoneChangeCounter = effect.zoneChangeCounter;
|
||||
this.turnFaceUpAbility = effect.turnFaceUpAbility.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BecomesFaceDownCreatureEffect copy() {
|
||||
return new BecomesFaceDownCreatureEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) {
|
||||
Permanent permanent = game.getPermanent(source.getSourceId());
|
||||
if (permanent != null && permanent.isFaceDown()) {
|
||||
switch (layer) {
|
||||
case TypeChangingEffects_4:
|
||||
permanent.setName("");
|
||||
permanent.getSubtype().clear();
|
||||
permanent.getManaCost().clear();
|
||||
break;
|
||||
case ColorChangingEffects_5:
|
||||
permanent.getColor().setColor(new ObjectColor());
|
||||
break;
|
||||
case AbilityAddingRemovingEffects_6:
|
||||
List<Ability> abilities = new ArrayList<>();
|
||||
for (Ability ability : permanent.getAbilities()) {
|
||||
// TODO: Add flag "works also face down" to ability and use it to control ability removement instead of instanceof check
|
||||
if (ability instanceof TurnedFaceUpTriggeredAbility) {
|
||||
ability.setRuleVisible(false);
|
||||
continue;
|
||||
}
|
||||
if (!ability.getRuleVisible() && !ability.getEffects().isEmpty()) {
|
||||
if (ability.getEffects().get(0) instanceof BecomesFaceDownCreatureEffect) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
abilities.add(ability);
|
||||
}
|
||||
permanent.getAbilities().removeAll(abilities);
|
||||
if (turnFaceUpAbility != null) {
|
||||
permanent.addAbility(turnFaceUpAbility, game);
|
||||
}
|
||||
break;
|
||||
case PTChangingEffects_7:
|
||||
if (sublayer == SubLayer.SetPT_7b) {
|
||||
permanent.getPower().setValue(2);
|
||||
permanent.getToughness().setValue(2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return layer == Layer.PTChangingEffects_7 || layer == Layer.AbilityAddingRemovingEffects_6 || layer == Layer.ColorChangingEffects_5 || layer == Layer.TypeChangingEffects_4;
|
||||
}
|
||||
|
||||
}
|
|
@ -28,21 +28,20 @@
|
|||
|
||||
package mage.cards;
|
||||
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.Game;
|
||||
import mage.watchers.Watcher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface Card extends MageObject {
|
||||
|
||||
UUID getOwnerId();
|
||||
|
@ -62,6 +61,8 @@ public interface Card extends MageObject {
|
|||
void setExpansionSetCode(String expansionSetCode);
|
||||
void setFaceDown(boolean value);
|
||||
boolean isFaceDown();
|
||||
boolean turnFaceUp(Game game, UUID playerId);
|
||||
boolean turnFaceDown(Game game, UUID playerId);
|
||||
boolean isFlipCard();
|
||||
String getFlipCardName();
|
||||
void setFlipCard(boolean flipCard);
|
||||
|
@ -132,6 +133,10 @@ public interface Card extends MageObject {
|
|||
|
||||
void removeCounters(String name, int amount, Game game);
|
||||
void removeCounters(Counter counter, Game game);
|
||||
|
||||
void setMorphCard(boolean morphCard);
|
||||
boolean isMorphCard();
|
||||
|
||||
@Override
|
||||
Card copy();
|
||||
}
|
||||
|
|
|
@ -28,18 +28,38 @@
|
|||
|
||||
package mage.cards;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Zone;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectImpl;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.PlayLandAbility;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.mana.ManaAbility;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import static mage.constants.Zone.BATTLEFIELD;
|
||||
import static mage.constants.Zone.COMMAND;
|
||||
import static mage.constants.Zone.EXILED;
|
||||
import static mage.constants.Zone.GRAVEYARD;
|
||||
import static mage.constants.Zone.HAND;
|
||||
import static mage.constants.Zone.LIBRARY;
|
||||
import static mage.constants.Zone.OUTSIDE;
|
||||
import static mage.constants.Zone.PICK;
|
||||
import static mage.constants.Zone.STACK;
|
||||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.Commander;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
|
@ -47,13 +67,6 @@ import mage.game.stack.Spell;
|
|||
import mage.watchers.Watcher;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.*;
|
||||
import mage.MageObject;
|
||||
import mage.constants.SpellAbilityType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.game.command.Commander;
|
||||
|
||||
public abstract class CardImpl extends MageObjectImpl implements Card {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
@ -77,6 +90,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
protected boolean usesVariousArt = false;
|
||||
protected Counters counters;
|
||||
protected boolean splitCard;
|
||||
protected boolean morphCard;
|
||||
|
||||
public CardImpl(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs) {
|
||||
this(ownerId, cardNumber, name, rarity, cardTypes, costs, SpellAbilityType.BASE);
|
||||
|
@ -103,6 +117,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
}
|
||||
this.usesVariousArt = Character.isDigit(this.getClass().getName().charAt(this.getClass().getName().length()-1));
|
||||
this.counters = new Counters();
|
||||
this.morphCard = false;
|
||||
}
|
||||
|
||||
protected CardImpl(UUID ownerId, String name) {
|
||||
|
@ -144,6 +159,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
splitCard = card.splitCard;
|
||||
usesVariousArt = card.usesVariousArt;
|
||||
counters = card.counters.copy();
|
||||
morphCard = card.isMorphCard();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -532,12 +548,36 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
|
||||
@Override
|
||||
public void setFaceDown(boolean value) {
|
||||
this.faceDown = value;
|
||||
faceDown = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFaceDown() {
|
||||
return this.faceDown;
|
||||
return faceDown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceUp(Game game, UUID playerId) {
|
||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.TURNFACEUP, getId(), playerId);
|
||||
if (!game.replaceEvent(event)) {
|
||||
setFaceDown(false);
|
||||
game.getCard(objectId).setFaceDown(false); // Another instance?
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.TURNEDFACEUP, getId(), playerId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceDown(Game game, UUID playerId) {
|
||||
GameEvent event = GameEvent.getEvent(GameEvent.EventType.TURNFACEDOWN, getId(), playerId);
|
||||
if (!game.replaceEvent(event)) {
|
||||
setFaceDown(true);
|
||||
game.getCard(objectId).setFaceDown(true); // Another instance?
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.TURNEDFACEDOWN, getId(), playerId));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -673,4 +713,16 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
|
|||
public void removeCounters(Counter counter, Game game) {
|
||||
removeCounters(counter.getName(), counter.getCount(), game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMorphCard(boolean morphCard) {
|
||||
this.morphCard = morphCard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMorphCard() {
|
||||
return morphCard;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -98,6 +98,11 @@ public class Commander implements CommandObject{
|
|||
return card.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return card.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
|
||||
|
|
|
@ -97,6 +97,11 @@ public class Emblem implements CommandObject {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageName() {
|
||||
return this.name;
|
||||
|
|
|
@ -29,16 +29,15 @@
|
|||
package mage.game.permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Controllable;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.constants.Zone;
|
||||
|
||||
public interface Permanent extends Card, Controllable {
|
||||
|
||||
boolean isTapped();
|
||||
|
@ -68,10 +67,6 @@ public interface Permanent extends Card, Controllable {
|
|||
boolean phaseIn(Game game);
|
||||
boolean phaseOut(Game game);
|
||||
|
||||
boolean isFaceUp();
|
||||
boolean turnFaceUp(Game game);
|
||||
boolean turnFaceDown(Game game);
|
||||
|
||||
boolean isMonstrous();
|
||||
void setMonstrous(boolean value);
|
||||
|
||||
|
@ -208,12 +203,14 @@ public interface Permanent extends Card, Controllable {
|
|||
/**
|
||||
* Returns connected cards.
|
||||
* Very similar to Imprint except that it is for internal use only.
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
List<UUID> getConnectedCards(String key);
|
||||
|
||||
/**
|
||||
* Clear all connected cards.
|
||||
* @param key
|
||||
*/
|
||||
void clearConnectedCards(String key);
|
||||
|
||||
|
|
|
@ -29,17 +29,15 @@
|
|||
package mage.game.permanent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import mage.constants.Zone;
|
||||
import java.util.UUID;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.LevelerCard;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.command.Commander;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.game.command.Commander;
|
||||
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
|
@ -116,6 +114,8 @@ public class PermanentCard extends PermanentImpl {
|
|||
}
|
||||
this.flipCard = card.isFlipCard();
|
||||
this.flipCardName = card.getFlipCardName();
|
||||
this.morphCard = card.isMorphCard();
|
||||
this.faceDown = card.isFaceDown();
|
||||
}
|
||||
|
||||
public Card getCard() {
|
||||
|
@ -205,4 +205,22 @@ public class PermanentCard extends PermanentImpl {
|
|||
return this.maxLevelCounters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceUp(Game game, UUID playerId) {
|
||||
if (super.turnFaceUp(game, playerId)) {
|
||||
card.setFaceDown(false);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceDown(Game game, UUID playerId) {
|
||||
if (super.turnFaceDown(game, playerId)) {
|
||||
card.setFaceDown(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -85,7 +85,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
protected boolean controlledFromStartOfControllerTurn;
|
||||
protected int turnsOnBattlefield;
|
||||
protected boolean phasedIn = true;
|
||||
protected boolean faceUp = true;
|
||||
protected boolean attacking;
|
||||
protected int blocking;
|
||||
// number of creatures the permanent can block
|
||||
|
@ -127,7 +126,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
this.controlledFromStartOfControllerTurn = permanent.controlledFromStartOfControllerTurn;
|
||||
this.turnsOnBattlefield = permanent.turnsOnBattlefield;
|
||||
this.phasedIn = permanent.phasedIn;
|
||||
this.faceUp = permanent.faceUp;
|
||||
this.attacking = permanent.attacking;
|
||||
this.blocking = permanent.blocking;
|
||||
this.maxBlocks = permanent.maxBlocks;
|
||||
|
@ -213,7 +211,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
public void addAbility(Ability ability, UUID sourceId, Game game) {
|
||||
if (!abilities.containsKey(ability.getId())) {
|
||||
Ability copyAbility = ability.copy();
|
||||
copyAbility.newId(); // needed so that sourc can get an ability multiple times (e.g. Raging Ravine)
|
||||
copyAbility.newId(); // needed so that source can get an ability multiple times (e.g. Raging Ravine)
|
||||
copyAbility.setControllerId(controllerId);
|
||||
copyAbility.setSourceId(objectId);
|
||||
game.getState().addAbility(copyAbility, sourceId, this);
|
||||
|
@ -411,23 +409,6 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFaceUp() {
|
||||
return faceUp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceUp(Game game) {
|
||||
//TODO: implement this
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceDown(Game game) {
|
||||
//TODO: implement this
|
||||
return false;
|
||||
}
|
||||
|
||||
public void removeSummoningSickness() {
|
||||
this.controlledFromStartOfControllerTurn = true;
|
||||
}
|
||||
|
@ -1064,4 +1045,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
|
|||
public void clearPairedCard() {
|
||||
this.pairedCard = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
if (name.isEmpty()) {
|
||||
if (isFaceDown()) {
|
||||
return "face down creature";
|
||||
} else {
|
||||
return "a creature without name";
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ import mage.abilities.Abilities;
|
|||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
|
@ -46,6 +47,7 @@ import mage.abilities.dynamicvalue.common.StaticValue;
|
|||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.PostResolveEffect;
|
||||
import mage.abilities.keyword.BestowAbility;
|
||||
import mage.abilities.keyword.MorphAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.SplitCard;
|
||||
import mage.constants.CardType;
|
||||
|
@ -56,6 +58,7 @@ import mage.constants.Zone;
|
|||
import mage.counters.Counter;
|
||||
import mage.counters.Counters;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.ZoneChangeEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.permanent.PermanentCard;
|
||||
|
@ -154,6 +157,17 @@ public class Spell implements StackObject, Card {
|
|||
return sb.append(ability.getGameLogMessage(game)).toString();
|
||||
}
|
||||
|
||||
public String getSpellCastText(Game game) {
|
||||
for (Ability spellAbility : (Abilities<Ability>) getAbilities()) {
|
||||
if (spellAbility instanceof MorphAbility
|
||||
&& ((AlternativeSourceCosts) spellAbility).isActivated(getSpellAbility(), game)) {
|
||||
return "a card face down";
|
||||
}
|
||||
}
|
||||
return getSpellAbility().toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resolve(Game game) {
|
||||
boolean result;
|
||||
|
@ -503,6 +517,11 @@ public class Spell implements StackObject, Card {
|
|||
public String getName() {
|
||||
return card.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return card.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageName() {
|
||||
|
@ -649,12 +668,22 @@ public class Spell implements StackObject, Card {
|
|||
|
||||
@Override
|
||||
public void setFaceDown(boolean value) {
|
||||
throw new RuntimeException("Not implemented.");
|
||||
card.setFaceDown(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceUp(Game game, UUID playerId) {
|
||||
return card.turnFaceUp(game, playerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean turnFaceDown(Game game, UUID playerId) {
|
||||
return card.turnFaceDown(game, playerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFaceDown() {
|
||||
return false;
|
||||
return card.isFaceDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -893,4 +922,14 @@ public class Spell implements StackObject, Card {
|
|||
return card;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMorphCard(boolean morphCard) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMorphCard() {
|
||||
return card.isMorphCard();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -112,6 +112,11 @@ public class StackAbility implements StackObject, Ability {
|
|||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImageName() {
|
||||
return name;
|
||||
|
|
|
@ -737,6 +737,9 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
//20091005 - 601.2a
|
||||
Card card = game.getCard(ability.getSourceId());
|
||||
if (card != null) {
|
||||
if (card.isMorphCard()) {
|
||||
card.setFaceDown(true);
|
||||
}
|
||||
if (!game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL, ability.getId(), ability.getSourceId(), playerId))) {
|
||||
int bookmark = game.bookmarkState();
|
||||
Zone fromZone = game.getState().getZone(card.getId());
|
||||
|
|
|
@ -236,7 +236,7 @@ public class TargetSpellOrPermanent extends TargetImpl {
|
|||
for (UUID targetId: getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetId);
|
||||
if (permanent != null) {
|
||||
sb.append(permanent.getName()).append(" ");
|
||||
sb.append(permanent.getLogName()).append(" ");
|
||||
}
|
||||
else {
|
||||
Spell spell = game.getStack().getSpell(targetId);
|
||||
|
|
|
@ -126,7 +126,7 @@ public class TraceUtil {
|
|||
String uuid = "[" + UUID.randomUUID() + "] ";
|
||||
log.error(uuid+"Tracing game state...");
|
||||
if (blocker != null) {
|
||||
log.error(uuid+blocker.getName() + " could block " + attacker.getName());
|
||||
log.error(uuid+blocker.getLogName() + " could block " + attacker.getLogName());
|
||||
}
|
||||
|
||||
log.error(uuid);
|
||||
|
|
|
@ -84,7 +84,7 @@ public class CommanderCombatDamageWatcher extends Watcher {
|
|||
Player player = game.getPlayer(playerUUID);
|
||||
MageObject commander = game.getObject(sourceId);
|
||||
if (player != null && commander != null){
|
||||
game.informPlayers(commander.getName() + " did " + damage + " combat damage to " + player.getName() + " during the game.");
|
||||
game.informPlayers(commander.getLogName() + " did " + damage + " combat damage to " + player.getName() + " during the game.");
|
||||
this.addCardInfoToCommander(game);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ public class SoulbondWatcher extends Watcher {
|
|||
if (chosen != null) {
|
||||
chosen.setPairedCard(permanent.getId());
|
||||
permanent.setPairedCard(chosen.getId());
|
||||
game.informPlayers(new StringBuilder(controller.getName()).append(" souldbonds ").append(permanent.getName()).append(" with ").append(chosen.getName()).toString());
|
||||
game.informPlayers(new StringBuilder(controller.getName()).append(" souldbonds ").append(permanent.getLogName()).append(" with ").append(chosen.getName()).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,10 +109,10 @@ public class SoulbondWatcher extends Watcher {
|
|||
Cards cards = new CardsImpl(Zone.PICK);
|
||||
cards.add(chosen);
|
||||
controller.lookAtCards("Soulbond", cards, game);
|
||||
if (controller.chooseUse(Outcome.Benefit, "Use Soulbond for recent " + permanent.getName() + "?", game)) {
|
||||
if (controller.chooseUse(Outcome.Benefit, "Use Soulbond for recent " + permanent.getLogName() + "?", game)) {
|
||||
chosen.setPairedCard(permanent.getId());
|
||||
permanent.setPairedCard(chosen.getId());
|
||||
game.informPlayers(new StringBuilder(controller.getName()).append(" souldbonds ").append(permanent.getName()).append(" with ").append(chosen.getName()).toString());
|
||||
game.informPlayers(new StringBuilder(controller.getName()).append(" souldbonds ").append(permanent.getLogName()).append(" with ").append(chosen.getName()).toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue