forked from External/mage
747 lines
29 KiB
Java
747 lines
29 KiB
Java
/*
|
|
* 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.cards;
|
|
|
|
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.ColoredManaSymbol;
|
|
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;
|
|
import mage.game.stack.Spell;
|
|
import mage.game.stack.StackObject;
|
|
import mage.watchers.Watcher;
|
|
import org.apache.log4j.Logger;
|
|
|
|
public abstract class CardImpl extends MageObjectImpl implements Card {
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private static final Logger logger = Logger.getLogger(CardImpl.class);
|
|
|
|
protected UUID ownerId;
|
|
protected int cardNumber;
|
|
protected String expansionSetCode;
|
|
protected String tokenSetCode;
|
|
protected Rarity rarity;
|
|
protected boolean faceDown;
|
|
protected boolean canTransform;
|
|
protected Card secondSideCard;
|
|
protected boolean nightCard;
|
|
protected SpellAbility spellAbility;
|
|
protected boolean flipCard;
|
|
protected String flipCardName;
|
|
protected int zoneChangeCounter = 1;
|
|
protected Map<String, String> info;
|
|
protected boolean usesVariousArt = false;
|
|
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);
|
|
}
|
|
|
|
public CardImpl(UUID ownerId, int cardNumber, String name, Rarity rarity, CardType[] cardTypes, String costs, SpellAbilityType spellAbilityType) {
|
|
this(ownerId, name);
|
|
this.rarity = rarity;
|
|
this.cardNumber = cardNumber;
|
|
this.cardType.addAll(Arrays.asList(cardTypes));
|
|
this.manaCost.load(costs);
|
|
setDefaultColor();
|
|
if (cardType.contains(CardType.LAND)) {
|
|
Ability ability = new PlayLandAbility(name);
|
|
ability.setSourceId(this.getId());
|
|
abilities.add(ability);
|
|
}
|
|
else {
|
|
SpellAbility ability = new SpellAbility(manaCost, name, Zone.HAND, spellAbilityType);
|
|
if (!cardType.contains(CardType.INSTANT)) {
|
|
ability.setTiming(TimingRule.SORCERY);
|
|
}
|
|
ability.setSourceId(this.getId());
|
|
abilities.add(ability);
|
|
}
|
|
this.usesVariousArt = Character.isDigit(this.getClass().getName().charAt(this.getClass().getName().length()-1));
|
|
this.morphCard = false;
|
|
}
|
|
|
|
private void setDefaultColor() {
|
|
this.color.setWhite(this.manaCost.containsColor(ColoredManaSymbol.W));
|
|
this.color.setBlue(this.manaCost.containsColor(ColoredManaSymbol.U));
|
|
this.color.setBlack(this.manaCost.containsColor(ColoredManaSymbol.B));
|
|
this.color.setRed(this.manaCost.containsColor(ColoredManaSymbol.R));
|
|
this.color.setGreen(this.manaCost.containsColor(ColoredManaSymbol.G));
|
|
}
|
|
|
|
protected CardImpl(UUID ownerId, String name) {
|
|
this.ownerId = ownerId;
|
|
this.name = name;
|
|
}
|
|
|
|
protected CardImpl(UUID id, UUID ownerId, String name) {
|
|
super(id);
|
|
this.ownerId = ownerId;
|
|
this.name = name;
|
|
}
|
|
|
|
public CardImpl(final CardImpl card) {
|
|
super(card);
|
|
ownerId = card.ownerId;
|
|
cardNumber = card.cardNumber;
|
|
expansionSetCode = card.expansionSetCode;
|
|
rarity = card.rarity;
|
|
faceDown = card.faceDown;
|
|
|
|
canTransform = card.canTransform;
|
|
if (canTransform) {
|
|
secondSideCard = card.secondSideCard;
|
|
nightCard = card.nightCard;
|
|
}
|
|
zoneChangeCounter = card.zoneChangeCounter;
|
|
if (card.info != null) {
|
|
info = new HashMap<>();
|
|
info.putAll(card.info);
|
|
}
|
|
flipCard = card.flipCard;
|
|
flipCardName = card.flipCardName;
|
|
splitCard = card.splitCard;
|
|
usesVariousArt = card.usesVariousArt;
|
|
morphCard = card.isMorphCard();
|
|
}
|
|
|
|
@Override
|
|
public void assignNewId() {
|
|
this.objectId = UUID.randomUUID();
|
|
this.abilities.newOriginalId();
|
|
this.abilities.setSourceId(objectId);
|
|
}
|
|
|
|
public static Card createCard(String name) {
|
|
try {
|
|
return createCard(Class.forName(name));
|
|
} catch (ClassNotFoundException ex) {
|
|
logger.fatal("Error loading card: " + name, ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static Card createCard(Class<?> clazz) {
|
|
try {
|
|
Constructor<?> con = clazz.getConstructor(new Class[]{UUID.class});
|
|
Card card = (Card) con.newInstance(new Object[]{null});
|
|
card.build();
|
|
return card;
|
|
} catch (Exception e) {
|
|
logger.fatal("Error loading card: " + clazz.getCanonicalName(), e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public UUID getOwnerId() {
|
|
return ownerId;
|
|
}
|
|
|
|
@Override
|
|
public int getCardNumber() {
|
|
return cardNumber;
|
|
}
|
|
|
|
@Override
|
|
public Rarity getRarity() {
|
|
return rarity;
|
|
}
|
|
|
|
@Override
|
|
public List<String> getRules() {
|
|
try {
|
|
List<String> rules = abilities.getRules(this.getLogName());
|
|
if (info != null) {
|
|
for (String data : info.values()) {
|
|
rules.add(data);
|
|
}
|
|
}
|
|
return rules;
|
|
} catch (Exception e) {
|
|
System.out.println("Exception in rules generation for card: " + this.getName());
|
|
e.printStackTrace();
|
|
}
|
|
ArrayList<String> rules = new ArrayList<>();
|
|
rules.add("Exception occured in rules generation");
|
|
return rules;
|
|
}
|
|
|
|
@Override
|
|
public void addAbility(Ability ability) {
|
|
ability.setSourceId(this.getId());
|
|
abilities.add(ability);
|
|
}
|
|
|
|
protected void addAbility(Ability ability, Watcher watcher) {
|
|
addAbility(ability);
|
|
ability.addWatcher(watcher);
|
|
}
|
|
|
|
@Override
|
|
public SpellAbility getSpellAbility() {
|
|
if (spellAbility == null) {
|
|
for (Ability ability : abilities.getActivatedAbilities(Zone.HAND)) {
|
|
// name check prevents that alternate casting methods (like "cast [card name] using bestow") are returned here
|
|
if (ability instanceof SpellAbility && ability.toString().endsWith(getName())) {
|
|
spellAbility = (SpellAbility) ability;
|
|
}
|
|
}
|
|
}
|
|
return spellAbility;
|
|
}
|
|
|
|
@Override
|
|
public void setOwnerId(UUID ownerId) {
|
|
this.ownerId = ownerId;
|
|
abilities.setControllerId(ownerId);
|
|
}
|
|
|
|
@Override
|
|
public String getExpansionSetCode() {
|
|
return expansionSetCode;
|
|
}
|
|
|
|
@Override
|
|
public String getTokenSetCode() {
|
|
return tokenSetCode;
|
|
}
|
|
|
|
@Override
|
|
public List<Mana> getMana() {
|
|
List<Mana> mana = new ArrayList<>();
|
|
for (ManaAbility ability : this.abilities.getManaAbilities(Zone.BATTLEFIELD)) {
|
|
for (Mana netMana: ability.getNetMana(null)) {
|
|
mana.add(netMana);
|
|
}
|
|
}
|
|
return mana;
|
|
}
|
|
|
|
@Override
|
|
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag) {
|
|
return this.moveToZone(toZone, sourceId, game, flag, null);
|
|
}
|
|
|
|
@Override
|
|
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) {
|
|
Zone fromZone = game.getState().getZone(objectId);
|
|
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects);
|
|
if (!game.replaceEvent(event)) {
|
|
if (event.getFromZone() != null) {
|
|
switch (event.getFromZone()) {
|
|
case GRAVEYARD:
|
|
game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
|
break;
|
|
case HAND:
|
|
game.getPlayer(ownerId).removeFromHand(this, game);
|
|
break;
|
|
case LIBRARY:
|
|
game.getPlayer(ownerId).removeFromLibrary(this, game);
|
|
break;
|
|
case EXILED:
|
|
game.getExile().removeCard(this, game);
|
|
break;
|
|
case OUTSIDE:
|
|
game.getPlayer(ownerId).getSideboard().remove(this);
|
|
break;
|
|
case COMMAND:
|
|
game.getState().getCommand().remove((Commander)game.getObject(objectId));
|
|
break;
|
|
case STACK:
|
|
StackObject stackObject = game.getStack().getSpell(getId());
|
|
if (stackObject != null) {
|
|
game.getStack().remove(stackObject);
|
|
}
|
|
break;
|
|
case PICK:
|
|
case BATTLEFIELD: // for sacrificing permanents or putting to library
|
|
break;
|
|
default:
|
|
Card sourceCard = game.getCard(sourceId);
|
|
logger.fatal(new StringBuilder("Invalid from zone [").append(fromZone)
|
|
.append("] for card [").append(this.getName())
|
|
.append("] to zone [").append(toZone)
|
|
.append("] source [").append(sourceCard != null ? sourceCard.getName():"null").append("]").toString());
|
|
break;
|
|
}
|
|
game.rememberLKI(objectId, event.getFromZone(), this);
|
|
}
|
|
|
|
if (isFaceDown() && !event.getToZone().equals(Zone.BATTLEFIELD)) { // to battlefield is possible because of Morph
|
|
setFaceDown(false);
|
|
game.getCard(this.getId()).setFaceDown(false);
|
|
}
|
|
updateZoneChangeCounter();
|
|
switch (event.getToZone()) {
|
|
case GRAVEYARD:
|
|
game.getPlayer(ownerId).putInGraveyard(this, game, !flag);
|
|
break;
|
|
case HAND:
|
|
game.getPlayer(ownerId).getHand().add(this);
|
|
break;
|
|
case STACK:
|
|
game.getStack().push(new Spell(this, this.getSpellAbility().copy(), ownerId, event.getFromZone()));
|
|
break;
|
|
case EXILED:
|
|
game.getExile().getPermanentExile().add(this);
|
|
break;
|
|
case COMMAND:
|
|
game.addCommander(new Commander(this));
|
|
break;
|
|
case LIBRARY:
|
|
if (flag) {
|
|
game.getPlayer(ownerId).getLibrary().putOnTop(this, game);
|
|
}
|
|
else {
|
|
game.getPlayer(ownerId).getLibrary().putOnBottom(this, game);
|
|
}
|
|
break;
|
|
case BATTLEFIELD:
|
|
PermanentCard permanent = new PermanentCard(this, event.getPlayerId()); // controller can be replaced (e.g. Gather Specimens)
|
|
game.addPermanent(permanent);
|
|
game.setZone(objectId, Zone.BATTLEFIELD);
|
|
game.setScopeRelevant(true);
|
|
game.applyEffects();
|
|
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
|
|
game.setScopeRelevant(false);
|
|
game.applyEffects();
|
|
if (flag) {
|
|
permanent.setTapped(true);
|
|
}
|
|
event.setTarget(permanent);
|
|
break;
|
|
default:
|
|
Card sourceCard = game.getCard(sourceId);
|
|
logger.fatal(new StringBuilder("Invalid to zone [").append(toZone)
|
|
.append("] for card [").append(this.getName())
|
|
.append("] to zone [").append(toZone)
|
|
.append("] source [").append(sourceCard != null ? sourceCard.getName():"null").append("]").toString());
|
|
return false;
|
|
}
|
|
game.setZone(objectId, event.getToZone());
|
|
game.addSimultaneousEvent(event);
|
|
return game.getState().getZone(objectId) == toZone;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
|
|
Card mainCard = getMainCard();
|
|
ZoneChangeEvent event = new ZoneChangeEvent(mainCard.getId(), ability.getId(), controllerId, fromZone, Zone.STACK);
|
|
if (!game.replaceEvent(event)) {
|
|
if (event.getFromZone() != null) {
|
|
switch (event.getFromZone()) {
|
|
case GRAVEYARD:
|
|
game.getPlayer(ownerId).removeFromGraveyard(mainCard, game);
|
|
break;
|
|
case HAND:
|
|
game.getPlayer(ownerId).removeFromHand(mainCard, game);
|
|
break;
|
|
case LIBRARY:
|
|
game.getPlayer(ownerId).removeFromLibrary(mainCard, game);
|
|
break;
|
|
case EXILED:
|
|
game.getExile().removeCard(mainCard, game);
|
|
break;
|
|
case OUTSIDE:
|
|
game.getPlayer(ownerId).getSideboard().remove(mainCard);
|
|
break;
|
|
|
|
case COMMAND:
|
|
game.getState().getCommand().remove((Commander)game.getObject(mainCard.getId()));
|
|
break;
|
|
default:
|
|
//logger.warning("moveToZone, not fully implemented: from="+event.getFromZone() + ", to="+event.getToZone());
|
|
}
|
|
game.rememberLKI(mainCard.getId(), event.getFromZone(), this);
|
|
}
|
|
game.getStack().push(new Spell(this, ability.copy(), controllerId, event.getFromZone()));
|
|
setZone(event.getToZone(), game);
|
|
game.fireEvent(event);
|
|
return game.getState().getZone(mainCard.getId()) == Zone.STACK;
|
|
}
|
|
return false;
|
|
}
|
|
@Override
|
|
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game) {
|
|
return moveToExile(exileId, name, sourceId, game, null);
|
|
}
|
|
|
|
@Override
|
|
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) {
|
|
Zone fromZone = game.getState().getZone(objectId);
|
|
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
|
|
if (!game.replaceEvent(event)) {
|
|
if (fromZone != null) {
|
|
switch (fromZone) {
|
|
case GRAVEYARD:
|
|
game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
|
break;
|
|
case HAND:
|
|
game.getPlayer(ownerId).removeFromHand(this, game);
|
|
break;
|
|
case LIBRARY:
|
|
game.getPlayer(ownerId).removeFromLibrary(this, game);
|
|
break;
|
|
case EXILED:
|
|
game.getExile().removeCard(this, game);
|
|
break;
|
|
case STACK:
|
|
case PICK:
|
|
// nothing to do
|
|
break;
|
|
default:
|
|
MageObject object = game.getObject(sourceId);
|
|
logger.warn(new StringBuilder("moveToExile, not fully implemented: from = ").append(fromZone).append(" - ").append(object != null ? object.getName():"null"));
|
|
}
|
|
game.rememberLKI(objectId, event.getFromZone(), this);
|
|
}
|
|
|
|
if (exileId == null) {
|
|
game.getExile().getPermanentExile().add(this);
|
|
} else {
|
|
game.getExile().createZone(exileId, name).add(this);
|
|
}
|
|
updateZoneChangeCounter();
|
|
game.setZone(objectId, event.getToZone());
|
|
game.addSimultaneousEvent(event);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId) {
|
|
return this.putOntoBattlefield(game, fromZone, sourceId, controllerId, false);
|
|
}
|
|
|
|
@Override
|
|
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped){
|
|
return this.putOntoBattlefield(game, fromZone, sourceId, controllerId, tapped, null);
|
|
|
|
}
|
|
|
|
@Override
|
|
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, ArrayList<UUID> appliedEffects){
|
|
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, controllerId, fromZone, Zone.BATTLEFIELD, appliedEffects, tapped);
|
|
if (!game.replaceEvent(event)) {
|
|
if (fromZone != null) {
|
|
boolean removed = false;
|
|
switch (fromZone) {
|
|
case GRAVEYARD:
|
|
removed = game.getPlayer(ownerId).removeFromGraveyard(this, game);
|
|
break;
|
|
case HAND:
|
|
removed = game.getPlayer(ownerId).removeFromHand(this, game);
|
|
break;
|
|
case LIBRARY:
|
|
removed = game.getPlayer(ownerId).removeFromLibrary(this, game);
|
|
break;
|
|
case EXILED:
|
|
game.getExile().removeCard(this, game);
|
|
if (isFaceDown()) {
|
|
// 110.6b Permanents enter the battlefield untapped, unflipped, face up, and phased in unless a spell or ability says otherwise.
|
|
this.setFaceDown(false);
|
|
}
|
|
removed = true;
|
|
break;
|
|
case COMMAND:
|
|
// command object (commander) is only on the stack, so no removing neccessary here
|
|
removed = true;
|
|
break;
|
|
case PICK:
|
|
removed = true;
|
|
break;
|
|
default:
|
|
logger.warn("putOntoBattlefield, not fully implemented: fromZone="+fromZone);
|
|
}
|
|
game.rememberLKI(objectId, event.getFromZone(), this);
|
|
if (!removed) {
|
|
logger.warn("Couldn't find card in fromZone, card=" + getName() + ", fromZone=" + fromZone);
|
|
}
|
|
}
|
|
updateZoneChangeCounter();
|
|
PermanentCard permanent = new PermanentCard(this, event.getPlayerId());
|
|
// make sure the controller of all continuous effects of this card are switched to the current controller
|
|
game.getContinuousEffects().setController(objectId, event.getPlayerId());
|
|
game.addPermanent(permanent);
|
|
setZone(Zone.BATTLEFIELD, game);
|
|
game.setScopeRelevant(true);
|
|
permanent.setTapped(tapped);
|
|
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
|
|
game.setScopeRelevant(false);
|
|
game.applyEffects();
|
|
game.fireEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public void setFaceDown(boolean value) {
|
|
faceDown = value;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFaceDown() {
|
|
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?
|
|
for (Ability ability :abilities) { // abilities that were set to not visible face down must be set to visible again
|
|
if (ability.getWorksFaceDown() && !ability.getRuleVisible()) {
|
|
ability.setRuleVisible(true);
|
|
}
|
|
}
|
|
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
|
|
public boolean canTransform() {
|
|
return this.canTransform;
|
|
}
|
|
|
|
@Override
|
|
public Card getSecondCardFace() {
|
|
return this.secondSideCard;
|
|
}
|
|
|
|
@Override
|
|
public boolean isNightCard() {
|
|
return this.nightCard;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFlipCard() {
|
|
return flipCard;
|
|
}
|
|
|
|
@Override
|
|
public String getFlipCardName() {
|
|
return flipCardName;
|
|
}
|
|
|
|
@Override
|
|
public boolean isSplitCard() {
|
|
return splitCard;
|
|
}
|
|
|
|
|
|
@Override
|
|
public int getZoneChangeCounter() {
|
|
// logger.info(name + " get= " + zoneChangeCounter + " " + ((this instanceof Permanent) ? " Permanent":"Card"));
|
|
return zoneChangeCounter;
|
|
|
|
}
|
|
|
|
@Override
|
|
public void updateZoneChangeCounter() {
|
|
zoneChangeCounter++;
|
|
// logger.info(name + " set= " + zoneChangeCounter + " " + ((this instanceof Permanent) ? " Permanent":"Card"));
|
|
}
|
|
|
|
@Override
|
|
public void addInfo(String key, String value) {
|
|
if (info == null) {
|
|
info = new HashMap<>();
|
|
}
|
|
if (value == null || value.isEmpty()) {
|
|
info.remove(key);
|
|
} else {
|
|
info.put(key, value);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void build() {}
|
|
|
|
@Override
|
|
public void setUsesVariousArt(boolean usesVariousArt) {
|
|
this.usesVariousArt = usesVariousArt;
|
|
}
|
|
|
|
@Override
|
|
public boolean getUsesVariousArt() {
|
|
return usesVariousArt;
|
|
}
|
|
|
|
@Override
|
|
public Counters getCounters(Game game) {
|
|
return game.getState().getCardState(this.objectId).getCounters();
|
|
}
|
|
|
|
@Override
|
|
public void addCounters(String name, int amount, Game game) {
|
|
addCounters(name, amount, game, null);
|
|
}
|
|
|
|
@Override
|
|
public void addCounters(String name, int amount, Game game, ArrayList<UUID> appliedEffects) {
|
|
GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, ownerId, name, amount);
|
|
countersEvent.setAppliedEffects(appliedEffects);
|
|
if (!game.replaceEvent(countersEvent)) {
|
|
for (int i = 0; i < countersEvent.getAmount(); i++) {
|
|
GameEvent event = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTER, objectId, ownerId, name, 1);
|
|
event.setAppliedEffects(appliedEffects);
|
|
if (!game.replaceEvent(event)) {
|
|
game.getState().getCardState(this.objectId).getCounters().addCounter(name, 1);
|
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER_ADDED, objectId, ownerId, name, 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void addCounters(Counter counter, Game game) {
|
|
addCounters(counter, game, null);
|
|
}
|
|
|
|
@Override
|
|
public void addCounters(Counter counter, Game game, ArrayList<UUID> appliedEffects) {
|
|
GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, ownerId, counter.getName(), counter.getCount());
|
|
countersEvent.setAppliedEffects(appliedEffects);
|
|
if (!game.replaceEvent(countersEvent)) {
|
|
int amount = countersEvent.getAmount();
|
|
for (int i = 0; i < amount; i++) {
|
|
Counter eventCounter = counter.copy();
|
|
eventCounter.remove(amount - 1);
|
|
GameEvent event = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTER, objectId, ownerId, counter.getName(), 1);
|
|
event.setAppliedEffects(appliedEffects);
|
|
if (!game.replaceEvent(event)) {
|
|
game.getState().getCardState(this.objectId).getCounters().addCounter(eventCounter);
|
|
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.COUNTER_ADDED, objectId, ownerId, counter.getName(), 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeCounters(String name, int amount, Game game) {
|
|
for (int i = 0; i < amount; i++) {
|
|
game.getState().getCardState(this.objectId).getCounters().removeCounter(name, 1);
|
|
GameEvent event = GameEvent.getEvent(GameEvent.EventType.COUNTER_REMOVED, objectId, ownerId);
|
|
event.setData(name);
|
|
game.fireEvent(event);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
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;
|
|
}
|
|
|
|
@Override
|
|
public String getLogName() {
|
|
if (this.isFaceDown()) {
|
|
return "facedown card";
|
|
}
|
|
return name;
|
|
}
|
|
|
|
@Override
|
|
public Card getMainCard() {
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
public void setZone(Zone zone, Game game) {
|
|
game.setZone(getId(), zone);
|
|
}
|
|
|
|
@Override
|
|
public void setSpellAbility(SpellAbility ability) {
|
|
spellAbility = ability;
|
|
}
|
|
|
|
}
|