forked from External/mage
- Adds Room + Room half card types - Adds Room unlock ability - Adds Room special functionality (locking halves, unlocking, changing names, changing mana values) - Adjusts name predicate handling for Room name handling (Rooms have between 0 and 2 names on the battlefield depending on their state. They have 1 name on the stack as a normal split card does). Allows cards to match these names properly - Adds Room game events (Unlock, Fully Unlock) and unlock triggers - Updates Split card constructor to allow a single type line as with Rooms - Adds empty name constant for fully unlocked rooms - Updates Permanent to include the door unlock states (that all permanents have) that are relevant when a permanent is or becomes a Room. - Updates ZonesHandler to properly move Room card parts onto and off of the battlefield. - Updated Eerie ability to function properly with Rooms - Implemented Bottomless Pool // Locker Room - Implemented Surgical Suite // Hospital Room - Added Room card tests
164 lines
5.7 KiB
Java
164 lines
5.7 KiB
Java
package mage.game.permanent;
|
||
|
||
import mage.MageInt;
|
||
import mage.MageObject;
|
||
import mage.abilities.Ability;
|
||
import mage.abilities.costs.mana.ManaCost;
|
||
import mage.abilities.keyword.ChangelingAbility;
|
||
import mage.abilities.keyword.TransformAbility;
|
||
import mage.cards.Card;
|
||
import mage.constants.EmptyNames;
|
||
import mage.game.Game;
|
||
import mage.game.events.ZoneChangeEvent;
|
||
import mage.game.permanent.token.Token;
|
||
import mage.util.CardUtil;
|
||
|
||
import java.util.UUID;
|
||
|
||
/**
|
||
* @author BetaSteward_at_googlemail.com
|
||
*/
|
||
public class PermanentToken extends PermanentImpl {
|
||
|
||
// non-modifyable container with token characteristics
|
||
// this PermanentToken resets to it on each game cycle
|
||
// TODO: see PermanentCard.card for usage research and fixes
|
||
protected Token token;
|
||
|
||
public PermanentToken(Token token, UUID controllerId, Game game) {
|
||
super(controllerId, controllerId, token.getName()); // random id
|
||
this.token = token.copy();
|
||
this.token.getAbilities().newOriginalId(); // neccessary if token has ability like DevourAbility()
|
||
this.token.getAbilities().setSourceId(objectId);
|
||
this.power = new MageInt(token.getPower().getModifiedBaseValue());
|
||
this.toughness = new MageInt(token.getToughness().getModifiedBaseValue());
|
||
this.copyFromToken(this.token, game, false); // needed to have at this time (e.g. for subtypes for entersTheBattlefield replacement effects)
|
||
|
||
// if transformed on ETB
|
||
if (this.token.isEntersTransformed()) {
|
||
TransformAbility.transformPermanent(this, game, null);
|
||
}
|
||
|
||
// token's ZCC must be synced with original token to keep abilities settings
|
||
// Example: kicker ability and kicked status
|
||
if (game != null) { // game == null in GUI for card viewer's tokens
|
||
this.setZoneChangeCounter(this.token.getZoneChangeCounter(game), game);
|
||
}
|
||
}
|
||
|
||
protected PermanentToken(final PermanentToken permanent) {
|
||
super(permanent);
|
||
this.token = permanent.token.copy();
|
||
}
|
||
|
||
@Override
|
||
public void reset(Game game) {
|
||
copyFromToken(token, game, true);
|
||
super.reset(game);
|
||
// Because the P/T objects have there own base value for reset we have to take it from there instead of from the basic token object
|
||
this.power.resetToBaseValue();
|
||
this.toughness.resetToBaseValue();
|
||
}
|
||
|
||
@Override
|
||
public int getManaValue() {
|
||
if (this.isTransformed()) {
|
||
return token.getManaValue();
|
||
}
|
||
return super.getManaValue();
|
||
}
|
||
|
||
@Override
|
||
public String getName() {
|
||
if (name.isEmpty()) {
|
||
return EmptyNames.FACE_DOWN_TOKEN.getObjectName();
|
||
} else {
|
||
return name;
|
||
}
|
||
}
|
||
|
||
private void copyFromToken(Token token, Game game, boolean reset) {
|
||
// modify all attributes permanently (without game usage)
|
||
this.name = token.getName();
|
||
this.abilities.clear();
|
||
if (reset) {
|
||
this.abilities.addAll(token.getAbilities());
|
||
} else {
|
||
// first time -> create ContinuousEffects only once
|
||
// so sourceId must be null (keep triggered abilities forever?)
|
||
for (Ability ability : token.getAbilities()) {
|
||
//Don't add subabilities since the original token already has them in its abilities list
|
||
this.addAbility(ability, null, game, true);
|
||
}
|
||
}
|
||
this.abilities.setControllerId(this.controllerId);
|
||
this.manaCost.clear();
|
||
for (ManaCost cost : token.getManaCost()) {
|
||
this.getManaCost().add(cost.copy());
|
||
}
|
||
this.cardType.clear();
|
||
this.cardType.addAll(token.getCardType(game));
|
||
this.color = token.getColor(game).copy();
|
||
this.frameColor = token.getFrameColor(game);
|
||
this.frameStyle = token.getFrameStyle();
|
||
this.supertype.clear();
|
||
this.supertype.addAll(token.getSuperType(game));
|
||
this.subtype.copyFrom(token.getSubtype(game));
|
||
this.startingLoyalty = token.getStartingLoyalty();
|
||
this.startingDefense = token.getStartingDefense();
|
||
// workaround for entersTheBattlefield replacement effects
|
||
if (this.abilities.containsClass(ChangelingAbility.class)) {
|
||
this.subtype.setIsAllCreatureTypes(true);
|
||
}
|
||
|
||
CardUtil.copySetAndCardNumber(this, token);
|
||
}
|
||
|
||
@Override
|
||
public MageObject getBasicMageObject() {
|
||
return token;
|
||
}
|
||
|
||
public Token getToken() {
|
||
return token;
|
||
}
|
||
|
||
@Override
|
||
public PermanentToken copy() {
|
||
return new PermanentToken(this);
|
||
}
|
||
|
||
@Override
|
||
public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) {
|
||
// token must change zcc on enters to battlefield (like cards do with stack),
|
||
// so it can keep abilities settings synced with copied spell/card
|
||
// example: kicker ability of copied creature spell
|
||
super.updateZoneChangeCounter(game, event);
|
||
}
|
||
|
||
@Override
|
||
public Card getMainCard() {
|
||
// Check if we have a copy source card (for tokens created from copied spells)
|
||
Card copySourceCard = token.getCopySourceCard();
|
||
if (copySourceCard != null) {
|
||
return copySourceCard;
|
||
}
|
||
|
||
// Fallback to current behavior
|
||
return this;
|
||
}
|
||
|
||
@Override
|
||
public boolean isTransformable() {
|
||
// 701.28c
|
||
// If a spell or ability instructs a player to transform a permanent that
|
||
// isn’t represented by a transforming token or a transforming double-faced card,
|
||
// nothing happens.
|
||
return token.getBackFace() != null;
|
||
}
|
||
|
||
@Override
|
||
public MageObject getOtherFace() {
|
||
return this.transformed ? token : this.token.getBackFace();
|
||
}
|
||
}
|