1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-10 09:11:04 -09:00

Fixed some possible null pointer exceptions.

This commit is contained in:
LevelX2 2015-07-28 00:04:57 +02:00
parent b23d987fe7
commit 1ef74f3293
6 changed files with 164 additions and 79 deletions
Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human
Mage/src/mage

View file

@ -251,7 +251,7 @@ public class HumanPlayer extends PlayerImpl {
@Override @Override
public boolean choose(Outcome outcome, Choice choice, Game game) { public boolean choose(Outcome outcome, Choice choice, Game game) {
if (outcome.equals(Outcome.PutManaInPool)) { if (Outcome.PutManaInPool.equals(outcome)) {
if (currentlyUnpaidMana != null if (currentlyUnpaidMana != null
&& ManaUtil.tryToAutoSelectAManaColor(choice, currentlyUnpaidMana)) { && ManaUtil.tryToAutoSelectAManaColor(choice, currentlyUnpaidMana)) {
return true; return true;

View file

@ -51,13 +51,15 @@ import mage.target.common.TargetCardInGraveyard;
/** /**
* Cards with the Aura subtype don't change the zone they are in, if there is no * Cards with the Aura subtype don't change the zone they are in, if there is no
* valid target on the battlefield. Also, when entering the battlefield and it * valid target on the battlefield. Also, when entering the battlefield and it
* was not cast (so from Zone != Hand), this effect gets the target to whitch to attach it * was not cast (so from Zone != Hand), this effect gets the target to whitch to
* and adds the Aura the the battlefield and attachs it to the target. * attach it and adds the Aura the the battlefield and attachs it to the target.
* The "attachTo:" value in game state has to be set therefore. * The "attachTo:" value in game state has to be set therefore.
*
* If no "attachTo:" value is defined, the controlling player has to chose the aura target.
* *
* This effect is automatically added to ContinuousEffects at the start of a game * If no "attachTo:" value is defined, the controlling player has to chose the
* aura target.
*
* This effect is automatically added to ContinuousEffects at the start of a
* game
* *
* @author North * @author North
*/ */
@ -93,7 +95,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
return false; return false;
} }
// Aura enters the battlefield attached // Aura enters the battlefield attached
Object object = game.getState().getValue("attachTo:"+card.getId()); Object object = game.getState().getValue("attachTo:" + card.getId());
if (object != null && object instanceof PermanentCard) { if (object != null && object instanceof PermanentCard) {
return false; return false;
} }
@ -113,7 +115,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
targetId = stackAbility.getEffects().get(0).getTargetPointer().getFirst(game, stackAbility); targetId = stackAbility.getEffects().get(0).getTargetPointer().getFirst(game, stackAbility);
} }
} }
if (targetId == null) { if (targetId == null) {
Target target = card.getSpellAbility().getTargets().get(0); Target target = card.getSpellAbility().getTargets().get(0);
enchantCardInGraveyard = target instanceof TargetCardInGraveyard; enchantCardInGraveyard = target instanceof TargetCardInGraveyard;
@ -122,9 +124,10 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
} }
Player player = game.getPlayer(card.getOwnerId()); Player player = game.getPlayer(card.getOwnerId());
Outcome auraOutcome = Outcome.BoostCreature; Outcome auraOutcome = Outcome.BoostCreature;
Ability: for (Ability ability:card.getAbilities()) { Ability:
for (Ability ability : card.getAbilities()) {
if (ability instanceof SpellAbility) { if (ability instanceof SpellAbility) {
for (Effect effect: ability.getEffects()) { for (Effect effect : ability.getEffects()) {
if (effect instanceof AttachEffect) { if (effect instanceof AttachEffect) {
auraOutcome = effect.getOutcome(); auraOutcome = effect.getOutcome();
break Ability; break Ability;
@ -167,13 +170,16 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
game.getBattlefield().addPermanent(permanent); game.getBattlefield().addPermanent(permanent);
card.setZone(Zone.BATTLEFIELD, game); card.setZone(Zone.BATTLEFIELD, game);
game.applyEffects(); game.applyEffects();
permanent.entersBattlefield(event.getSourceId(), game, fromZone, true); boolean entered = permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
game.applyEffects(); game.applyEffects();
if (!entered) {
return false;
}
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
if (targetCard != null) { if (targetCard != null) {
permanent.attachTo(targetCard.getId(), game); permanent.attachTo(targetCard.getId(), game);
} }
if (targetPermanent != null) { if (targetPermanent != null) {
targetPermanent.addAttachment(permanent.getId(), game); targetPermanent.addAttachment(permanent.getId(), game);
} }
@ -183,7 +189,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
} }
return true; return true;
} }
@Override @Override
public boolean checksEventType(GameEvent event, Game game) { public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.ZONE_CHANGE; return event.getType() == GameEvent.EventType.ZONE_CHANGE;
@ -192,7 +198,7 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
@Override @Override
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD) if (((ZoneChangeEvent) event).getToZone().equals(Zone.BATTLEFIELD)
&& !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND)) ) { && !(((ZoneChangeEvent) event).getFromZone().equals(Zone.HAND))) {
Card card = game.getCard(event.getTargetId()); Card card = game.getCard(event.getTargetId());
if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) { if (card != null && card.getCardType().contains(CardType.ENCHANTMENT) && card.hasSubtype("Aura")) {
return true; return true;

View file

@ -421,13 +421,17 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
game.setZone(objectId, Zone.BATTLEFIELD); game.setZone(objectId, Zone.BATTLEFIELD);
game.setScopeRelevant(true); game.setScopeRelevant(true);
game.applyEffects(); game.applyEffects();
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); boolean entered = permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
game.setScopeRelevant(false); game.setScopeRelevant(false);
game.applyEffects(); game.applyEffects();
if (flag) { if (entered) {
permanent.setTapped(true); if (flag) {
permanent.setTapped(true);
}
event.setTarget(permanent);
} else {
return false;
} }
event.setTarget(permanent);
break; break;
default: default:
Card sourceCard = game.getCard(sourceId); Card sourceCard = game.getCard(sourceId);
@ -603,11 +607,13 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
game.setScopeRelevant(true); game.setScopeRelevant(true);
permanent.setTapped(tapped); permanent.setTapped(tapped);
permanent.setFaceDown(facedown, game); permanent.setFaceDown(facedown, game);
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); boolean entered = permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
game.setScopeRelevant(false); game.setScopeRelevant(false);
game.applyEffects(); game.applyEffects();
game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD)); if (entered) {
return true; game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD));
return true;
}
} }
if (facedown) { if (facedown) {
this.setFaceDown(false, game); this.setFaceDown(false, game);

View file

@ -810,19 +810,21 @@ public class Combat implements Serializable, Copyable<Combat> {
// check now, if it already blocks a creature that mustBeBlockedByAtLeastOne // check now, if it already blocks a creature that mustBeBlockedByAtLeastOne
if (possibleBlocker.getBlocking() > 0) { if (possibleBlocker.getBlocking() > 0) {
CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId); CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId);
for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) { if (combatGroupOfPossibleBlocker != null) {
if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) { for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) {
// blocks a creature that has to be blocked by at least one if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) {
if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) { // blocks a creature that has to be blocked by at least one
// the creature blocks alone already a creature that has to be blocked by at least one, if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) {
// so this is ok // the creature blocks alone already a creature that has to be blocked by at least one,
return null; // so this is ok
return null;
}
// TODO: Check if the attacker is already blocked by another creature
// and despite there is need that this attacker blocks this attacker also
// I don't know why
Permanent blockedAttacker = game.getPermanent(blockedAttackerId);
return possibleBlocker.getIdName() + " blocks with other creatures " + blockedAttacker.getIdName() + ", which has to be blocked by only one creature. ";
} }
// TODO: Check if the attacker is already blocked by another creature
// and despite there is need that this attacker blocks this attacker also
// I don't know why
Permanent blockedAttacker = game.getPermanent(blockedAttackerId);
return possibleBlocker.getIdName() + " blocks with other creatures " + blockedAttacker.getIdName() + ", which has to be blocked by only one creature. ";
} }
} }
} }
@ -947,9 +949,12 @@ public class Combat implements Serializable, Copyable<Combat> {
if (!canDefenderBeAttacked(attackerId, defenderId, game)) { if (!canDefenderBeAttacked(attackerId, defenderId, game)) {
return false; return false;
} }
Permanent attacker = game.getPermanent(attackerId);
if (attacker == null) {
return false;
}
CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId); CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId);
newGroup.attackers.add(attackerId); newGroup.attackers.add(attackerId);
Permanent attacker = game.getPermanent(attackerId);
attacker.setAttacking(true); attacker.setAttacking(true);
groups.add(newGroup); groups.add(newGroup);
return true; return true;

View file

@ -1,31 +1,30 @@
/* /*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, are * Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met: * permitted provided that the following conditions are met:
* *
* 1. Redistributions of source code must retain the above copyright notice, this list of * 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer. * conditions and the following disclaimer.
* *
* 2. Redistributions in binary form must reproduce the above copyright notice, this list * 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 * of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution. * provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * 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 * 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 * 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 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 * 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 * 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 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* The views and conclusions contained in the software and documentation are those of the * 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 * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.game.permanent; package mage.game.permanent;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,60 +44,89 @@ import mage.game.Game;
public interface Permanent extends Card, Controllable { public interface Permanent extends Card, Controllable {
void setControllerId(UUID controllerId); void setControllerId(UUID controllerId);
boolean isTapped(); boolean isTapped();
boolean untap(Game game); boolean untap(Game game);
boolean tap(Game game); boolean tap(Game game);
/** /**
* use tap(game) * use tap(game)
* <p>setTapped doesn't trigger TAPPED event and should be used * <p>
* only if you want permanent to enter battlefield tapped</p> * setTapped doesn't trigger TAPPED event and should be used only if you
* want permanent to enter battlefield tapped</p>
* *
* @param tapped * @param tapped
* @deprecated * @deprecated
*/ */
@Deprecated @Deprecated
void setTapped(boolean tapped); void setTapped(boolean tapped);
boolean canTap(); boolean canTap();
boolean isFlipped(); boolean isFlipped();
boolean unflip(Game game); boolean unflip(Game game);
boolean flip(Game game); boolean flip(Game game);
boolean transform(Game game); boolean transform(Game game);
boolean isTransformed(); boolean isTransformed();
void setTransformed(boolean value); void setTransformed(boolean value);
boolean isPhasedIn(); boolean isPhasedIn();
boolean phaseIn(Game game); boolean phaseIn(Game game);
boolean phaseOut(Game game); boolean phaseOut(Game game);
boolean isMonstrous(); boolean isMonstrous();
void setMonstrous(boolean value); void setMonstrous(boolean value);
boolean isRenowned(); boolean isRenowned();
void setRenowned(boolean value); void setRenowned(boolean value);
void setCardNumber(int cid); void setCardNumber(int cid);
void setExpansionSetCode(String expansionSetCode); void setExpansionSetCode(String expansionSetCode);
void setRarity(Rarity rarity); void setRarity(Rarity rarity);
void setFlipCard(boolean flipCard); void setFlipCard(boolean flipCard);
void setFlipCardName(String flipCardName); void setFlipCardName(String flipCardName);
void setSecondCardFace(Card card); void setSecondCardFace(Card card);
Counters getCounters(); Counters getCounters();
List<UUID> getAttachments(); List<UUID> getAttachments();
UUID getAttachedTo(); UUID getAttachedTo();
void attachTo(UUID permanentId, Game game); void attachTo(UUID permanentId, Game game);
boolean addAttachment(UUID permanentId, Game game); boolean addAttachment(UUID permanentId, Game game);
boolean removeAttachment(UUID permanentId, Game game); boolean removeAttachment(UUID permanentId, Game game);
boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game); boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game);
boolean hasProtectionFrom(MageObject source, Game game); boolean hasProtectionFrom(MageObject source, Game game);
boolean cantBeEnchantedBy(MageObject source, Game game); boolean cantBeEnchantedBy(MageObject source, Game game);
boolean wasControlledFromStartOfControllerTurn(); boolean wasControlledFromStartOfControllerTurn();
boolean hasSummoningSickness(); boolean hasSummoningSickness();
int getDamage(); int getDamage();
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable); int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable);
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects); int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects);
@ -114,58 +142,83 @@ public interface Permanent extends Card, Controllable {
* @return * @return
*/ */
int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat); int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
int applyDamage(Game game); int applyDamage(Game game);
void removeAllDamage(Game game); void removeAllDamage(Game game);
void reset(Game game); void reset(Game game);
boolean destroy(UUID sourceId, Game game, boolean noRegen); boolean destroy(UUID sourceId, Game game, boolean noRegen);
boolean sacrifice(UUID sourceId, Game game); boolean sacrifice(UUID sourceId, Game game);
boolean regenerate(UUID sourceId, Game game); boolean regenerate(UUID sourceId, Game game);
boolean fight(Permanent fightTarget, Ability source, Game game); boolean fight(Permanent fightTarget, Ability source, Game game);
void entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent); boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent);
String getValue(); String getValue();
@Deprecated @Deprecated
void addAbility(Ability ability); void addAbility(Ability ability);
@Deprecated @Deprecated
void addAbility(Ability ability, Game game); void addAbility(Ability ability, Game game);
void addAbility(Ability ability, UUID sourceId, Game game); void addAbility(Ability ability, UUID sourceId, Game game);
void addAbility(Ability ability, UUID sourceId, Game game, boolean createNewId); void addAbility(Ability ability, UUID sourceId, Game game, boolean createNewId);
void removeAllAbilities(UUID sourceId, Game game); void removeAllAbilities(UUID sourceId, Game game);
void addLoyaltyUsed(); void addLoyaltyUsed();
boolean canLoyaltyBeUsed(Game game); boolean canLoyaltyBeUsed(Game game);
public void resetControl(); public void resetControl();
boolean changeControllerId(UUID controllerId, Game game); boolean changeControllerId(UUID controllerId, Game game);
boolean checkControlChanged(Game game); boolean checkControlChanged(Game game);
void beginningOfTurn(Game game); void beginningOfTurn(Game game);
void endOfTurn(Game game); void endOfTurn(Game game);
int getTurnsOnBattlefield(); int getTurnsOnBattlefield();
void addPower(int power); void addPower(int power);
void addToughness(int toughness); void addToughness(int toughness);
boolean isAttacking(); boolean isAttacking();
int getBlocking(); int getBlocking();
void setAttacking(boolean attacking); void setAttacking(boolean attacking);
void setBlocking(int blocking); void setBlocking(int blocking);
int getMaxBlocks(); int getMaxBlocks();
void setMaxBlocks(int maxBlocks); void setMaxBlocks(int maxBlocks);
int getMinBlockedBy(); int getMinBlockedBy();
void setMinBlockedBy(int minBlockedBy); void setMinBlockedBy(int minBlockedBy);
int getMaxBlockedBy(); int getMaxBlockedBy();
boolean isRemovedFromCombat(); boolean isRemovedFromCombat();
void setRemovedFromCombat(boolean removedFromCombat); void setRemovedFromCombat(boolean removedFromCombat);
/** /**
* Sets the maximum number of blockers the creature can be blocked by. * Sets the maximum number of blockers the creature can be blocked by.
* Default = 0 which means there is no restriction in the number of blockers. * Default = 0 which means there is no restriction in the number of
* blockers.
* *
* @param maxBlockedBy maximum number of blockers * @param maxBlockedBy maximum number of blockers
*/ */
@ -180,11 +233,14 @@ public interface Permanent extends Card, Controllable {
* @return * @return
*/ */
boolean canAttack(UUID defenderId, Game game); boolean canAttack(UUID defenderId, Game game);
boolean canBlock(UUID attackerId, Game game); boolean canBlock(UUID attackerId, Game game);
boolean canBlockAny(Game game); boolean canBlockAny(Game game);
/** /**
* Checks by restriction effects if the permanent can use activated abilities * Checks by restriction effects if the permanent can use activated
* abilities
* *
* @param game * @param game
* @return true - permanent can use activated abilities * @return true - permanent can use activated abilities
@ -192,11 +248,15 @@ public interface Permanent extends Card, Controllable {
boolean canUseActivatedAbilities(Game game); boolean canUseActivatedAbilities(Game game);
boolean removeFromCombat(Game game); boolean removeFromCombat(Game game);
boolean removeFromCombat(Game game, boolean withInfo); boolean removeFromCombat(Game game, boolean withInfo);
boolean isDeathtouched(); boolean isDeathtouched();
/** /**
* Returns a list of object refrences that dealt damage this turn to this permanent * Returns a list of object refrences that dealt damage this turn to this
* permanent
*
* @return * @return
*/ */
HashSet<MageObjectReference> getDealtDamageByThisTurn(); HashSet<MageObjectReference> getDealtDamageByThisTurn();
@ -222,13 +282,14 @@ public interface Permanent extends Card, Controllable {
* Get card that was imprinted on this one. * Get card that was imprinted on this one.
* *
* Can be null if no card was imprinted. * Can be null if no card was imprinted.
*
* @return Imprinted card UUID. * @return Imprinted card UUID.
*/ */
List<UUID> getImprinted(); List<UUID> getImprinted();
/** /**
* Allows to connect any card to permanent. * Allows to connect any card to permanent. Very similar to Imprint except
* Very similar to Imprint except that it is for internal use only. * that it is for internal use only.
* *
* @param key * @param key
* @param connectedCard * @param connectedCard
@ -236,8 +297,9 @@ public interface Permanent extends Card, Controllable {
void addConnectedCard(String key, UUID connectedCard); void addConnectedCard(String key, UUID connectedCard);
/** /**
* Returns connected cards. * Returns connected cards. Very similar to Imprint except that it is for
* Very similar to Imprint except that it is for internal use only. * internal use only.
*
* @param key * @param key
* @return * @return
*/ */
@ -245,6 +307,7 @@ public interface Permanent extends Card, Controllable {
/** /**
* Clear all connected cards. * Clear all connected cards.
*
* @param key * @param key
*/ */
void clearConnectedCards(String key); void clearConnectedCards(String key);
@ -269,9 +332,11 @@ public interface Permanent extends Card, Controllable {
void clearPairedCard(); void clearPairedCard();
void setMorphed(boolean value); void setMorphed(boolean value);
boolean isMorphed(); boolean isMorphed();
void setManifested(boolean value); void setManifested(boolean value);
boolean isManifested(); boolean isManifested();
@Override @Override
@ -280,5 +345,6 @@ public interface Permanent extends Card, Controllable {
// Simple int counter to set a timewise create order , the lower the number the earlier the object was created // Simple int counter to set a timewise create order , the lower the number the earlier the object was created
// if objects enter the battlefield at the same time they can get (and should) get the same number. // if objects enter the battlefield at the same time they can get (and should) get the same number.
int getCreateOrder(); int getCreateOrder();
void setCreateOrder(int createOrder); void setCreateOrder(int createOrder);
} }

View file

@ -159,15 +159,17 @@ public class Token extends MageObjectImpl {
this.lastAddedTokenId = newToken.getId(); this.lastAddedTokenId = newToken.getId();
game.setScopeRelevant(true); game.setScopeRelevant(true);
game.applyEffects(); game.applyEffects();
newToken.entersBattlefield(sourceId, game, Zone.OUTSIDE, true); boolean entered = newToken.entersBattlefield(sourceId, game, Zone.OUTSIDE, true);
game.setScopeRelevant(false); game.setScopeRelevant(false);
game.applyEffects(); game.applyEffects();
game.fireEvent(new ZoneChangeEvent(newToken, event.getPlayerId(), Zone.OUTSIDE, Zone.BATTLEFIELD)); if (entered) {
if (attacking && game.getCombat() != null) { game.fireEvent(new ZoneChangeEvent(newToken, event.getPlayerId(), Zone.OUTSIDE, Zone.BATTLEFIELD));
game.getCombat().addAttackingCreature(newToken.getId(), game); if (attacking && game.getCombat() != null) {
} game.getCombat().addAttackingCreature(newToken.getId(), game);
if (!game.isSimulation()) { }
game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield"); if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield");
}
} }
} }