* Fixed that as thought effects could wrongly only apply to the ability controller.

This commit is contained in:
LevelX2 2014-09-17 15:57:06 +02:00
parent b3c0cc10b0
commit f9f49e9c00
11 changed files with 77 additions and 95 deletions

View file

@ -29,22 +29,27 @@
package mage.sets.betrayersofkamigawa;
import java.util.UUID;
import mage.constants.*;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardsImpl;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Library;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import mage.target.targetpointer.FixedTarget;
/**
*
@ -92,15 +97,18 @@ class OrnateKanzashiEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(targetPointer.getFirst(game, source));
if (player != null && player.getLibrary().size() > 0) {
Library library = player.getLibrary();
Card card = library.removeFromTop(game);
card.moveToExile(source.getSourceId(), "Ornate Kanzashi", source.getSourceId(), game);
if (card != null) {
player.revealCards("Card to play", new CardsImpl(card), game);
game.addEffect(new OrnateKanzashiCastFromExileEffect(card.getId()), source);
Player opponent = game.getPlayer(targetPointer.getFirst(game, source));
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject != null && opponent != null) {
if (opponent.getLibrary().size() > 0) {
Library library = opponent.getLibrary();
Card card = library.getFromTop(game);
if (card != null) {
opponent.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getLogName(), source.getSourceId(), game, Zone.LIBRARY);
ContinuousEffect effect = new OrnateKanzashiCastFromExileEffect(card.getId());
effect.setTargetPointer(new FixedTarget(card.getId()));
game.addEffect(effect, source);
}
}
return true;
}
@ -110,17 +118,13 @@ class OrnateKanzashiEffect extends OneShotEffect {
class OrnateKanzashiCastFromExileEffect extends AsThoughEffectImpl {
private UUID cardId;
public OrnateKanzashiCastFromExileEffect(UUID cardId) {
super(AsThoughEffectType.CAST_FROM_NON_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
staticText = "You may play card from exile";
this.cardId = cardId;
staticText = "You may play that card from exile this turn";
}
public OrnateKanzashiCastFromExileEffect(final OrnateKanzashiCastFromExileEffect effect) {
super(effect);
cardId = effect.cardId;
}
@Override
@ -134,26 +138,7 @@ class OrnateKanzashiCastFromExileEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
if (sourceId.equals(this.cardId)) {
Card card = game.getCard(this.cardId);
if (card != null && game.getState().getZone(this.cardId) == Zone.EXILED) {
Player player = game.getPlayer(source.getControllerId());
if (player != null && player.chooseUse(Outcome.Benefit, "Play this card?", game)) {
if (card.getCardType().contains(CardType.LAND)) {
// If the revealed card is a land, you can play it only if it's your turn and you haven't yet played a land this turn.
if (game.getActivePlayerId().equals(player.getId()) && player.getLandsPlayed() < player.getLandsPerTurn()) {
return player.playLand(card, game);
}
} else {
Ability ability = card.getSpellAbility();
if (ability != null && ability instanceof SpellAbility) {
return player.cast((SpellAbility) ability, game, false);
}
}
}
}
}
return false;
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return source.getControllerId().equals(affectedControllerId) && objectId.equals(getTargetPointer().getFirst(game, source));
}
}

View file

@ -40,7 +40,6 @@ import mage.abilities.effects.AsThoughEffectImpl;
import mage.abilities.effects.common.ExileFromZoneTargetEffect;
import mage.abilities.effects.common.RegenerateSourceEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.filter.FilterCard;
import mage.filter.common.FilterControlledCreaturePermanent;
@ -118,16 +117,12 @@ class FiendOfTheShadowsEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(sourceId);
if (card != null) {
ExileZone zone = game.getExile().getExileZone(exileId);
if (zone != null && zone.contains(card.getId())) {
if (card.getCardType().contains(CardType.INSTANT) || game.canPlaySorcery(source.getControllerId())) {
card.setControllerId(source.getControllerId());
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (affectedControllerId.equals(source.getControllerId())) {
ExileZone zone = game.getExile().getExileZone(exileId);
if (zone != null && zone.contains(objectId)) {
return true;
}
}
}
return false;
}

View file

@ -114,8 +114,10 @@ class HavengulLichPlayEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
return targetPointer.getFirst(game, source).equals(sourceId) && game.getState().getZone(sourceId) == Zone.GRAVEYARD;
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return source.getControllerId().equals(affectedControllerId)
&& targetPointer.getFirst(game, source).equals(objectId)
&& game.getState().getZone(objectId) == Zone.GRAVEYARD;
}
}

View file

@ -37,6 +37,7 @@ import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.Zone;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
@ -56,6 +57,7 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.common.TargetCardInHand;
import mage.util.CardUtil;
/**
* Gatecrash FAQ (01.2013)
@ -99,12 +101,11 @@ public class BaneAlleyBroker extends CardImpl {
this.power = new MageInt(0);
this.toughness = new MageInt(3);
// {tap}: Draw a card, then exile a card from your hand face down.
// {tap}: Draw a card, then exile a card from your hand face down.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BaneAlleyBrokerDrawExileEffect(), new TapSourceCost()));
// You may look at cards exiled with Bane Alley Broker.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BaneAlleyBrokerLookAtCardEffect()));
this.addAbility(new SimpleStaticAbility(Zone.ALL, new BaneAlleyBrokerLookAtCardEffect()));
// {U}{B}, {tap}: Return a card exiled with Bane Alley Broker to its owner's hand.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new ManaCostsImpl("{U}{B}"));
@ -143,15 +144,10 @@ class BaneAlleyBrokerDrawExileEffect extends OneShotEffect {
Target target = new TargetCardInHand(new FilterCard("card to exile"));
if (player.chooseTarget(outcome, target, source, game)) {
Card card = game.getCard(target.getFirstTarget());
Card sourceCard = game.getCard(source.getSourceId());
if (card != null && sourceCard != null) {
MageObject sourceObject = game.getObject(source.getSourceId());
if (card != null && sourceObject != null) {
card.setFaceDown(true);
UUID exileId = (UUID) game.getState().getValue(new StringBuilder("exileZone").append(source.getSourceId()).append(sourceCard.getZoneChangeCounter()).toString());
if (exileId == null) {
exileId = UUID.randomUUID();
game.getState().setValue(new StringBuilder("exileZone").append(source.getSourceId()).append(sourceCard.getZoneChangeCounter()).toString(), exileId);
}
return card.moveToExile(exileId, new StringBuilder(sourceCard.getName()).append("(").append(sourceCard.getZoneChangeCounter()).append(")").toString(), source.getSourceId(), game);
return card.moveToExile(CardUtil.getCardExileZoneId(game, source), new StringBuilder(sourceObject.getLogName()).toString(), source.getSourceId(), game);
}
}
}
@ -176,10 +172,10 @@ class TargetCardInBaneAlleyBrokerExile extends TargetCard {
@Override
public Set<UUID> possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) {
Set<UUID> possibleTargets = new HashSet<UUID>();
Set<UUID> possibleTargets = new HashSet<>();
Card sourceCard = game.getCard(sourceId);
if (sourceCard != null) {
UUID exileId = (UUID) game.getState().getValue(new StringBuilder("exileZone").append(sourceId).append(sourceCard.getZoneChangeCounter()).toString());
UUID exileId = CardUtil.getCardExileZoneId(game, sourceId);
ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null && exile.size() > 0) {
possibleTargets.addAll(exile);
@ -192,7 +188,7 @@ class TargetCardInBaneAlleyBrokerExile extends TargetCard {
public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) {
Card sourceCard = game.getCard(sourceId);
if (sourceCard != null) {
UUID exileId = (UUID) game.getState().getValue(new StringBuilder("exileZone").append(sourceId).append(sourceCard.getZoneChangeCounter()).toString());
UUID exileId = CardUtil.getCardExileZoneId(game, sourceId);
ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null && exile.size() > 0) {
return true;
@ -208,7 +204,7 @@ class TargetCardInBaneAlleyBrokerExile extends TargetCard {
ExileZone exile = null;
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard != null) {
UUID exileId = (UUID) game.getState().getValue(new StringBuilder("exileZone").append(source.getSourceId()).append(sourceCard.getZoneChangeCounter()).toString());
UUID exileId = CardUtil.getCardExileZoneId(game, source);
exile = game.getExile().getExileZone(exileId);
}
if (exile != null && exile.contains(id)) {
@ -246,20 +242,22 @@ class BaneAlleyBrokerLookAtCardEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(sourceId);
if (card != null && game.getState().getZone(sourceId) == Zone.EXILED) {
Card sourceCard = game.getCard(source.getSourceId());
if (sourceCard == null) {
return false;
}
UUID exileId = (UUID) game.getState().getValue(new StringBuilder("exileZone").append(source.getSourceId()).append(sourceCard.getZoneChangeCounter()).toString());
ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null && exile.contains(sourceId)) {
Cards cards = new CardsImpl(card);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.lookAtCards("Exiled with " + sourceCard.getName(), cards, game);
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
if (affectedControllerId.equals(source.getControllerId())) {
Card card = game.getCard(objectId);
if (card != null) {
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject == null) {
return false;
}
UUID exileId = CardUtil.getCardExileZoneId(game, source);
ExileZone exile = game.getExile().getExileZone(exileId);
if (exile != null && exile.contains(objectId)) {
Cards cards = new CardsImpl(card);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.lookAtCards("Exiled with " + sourceObject.getLogName(), cards, game);
}
}
}
}

View file

@ -112,10 +112,12 @@ class GlaringSpotlightEffect extends AsThoughEffectImpl {
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
Permanent creature = game.getPermanent(sourceId);
if (creature != null) {
if (game.getOpponents(source.getControllerId()).contains(creature.getControllerId())) {
return true;
if (affectedControllerId.equals(source.getControllerId())) {
Permanent creature = game.getPermanent(sourceId);
if (creature != null) {
if (game.getOpponents(source.getControllerId()).contains(creature.getControllerId())) {
return true;
}
}
}
return false;

View file

@ -149,10 +149,9 @@ class NightveilSpecterEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(sourceId);
Player controller = game.getPlayer(source.getControllerId());
if (controller != null && card != null && game.getState().getZone(card.getId()) == Zone.EXILED) {
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
Card card = game.getCard(objectId);
if (affectedControllerId.equals(source.getControllerId()) && card != null && game.getState().getZone(card.getId()) == Zone.EXILED) {
ExileZone zone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
return zone != null && zone.contains(card.getId());
}

View file

@ -117,7 +117,7 @@ class QuickenAsThoughEffect extends AsThoughEffectImpl {
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
if (quickenWatcher.isQuickenSpellActive(source.getSourceId(), zoneChangeCounter)) {
Card card = game.getCard(sourceId);
if (card != null && card.getCardType().contains(CardType.SORCERY) && card.getOwnerId().equals(source.getControllerId())) {
if (card != null && card.getCardType().contains(CardType.SORCERY) && source.getControllerId().equals(affectedControllerId)) {
return card.getSpellAbility().isInUseableZone(game, card, false);
}
}

View file

@ -124,7 +124,7 @@ class PropheticFlamespeakerCastFromExileEffect extends AsThoughEffectImpl {
public PropheticFlamespeakerCastFromExileEffect() {
super(AsThoughEffectType.CAST_FROM_NON_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
staticText = "You may play card from exile";
staticText = "You may play the card from exile";
}
public PropheticFlamespeakerCastFromExileEffect(final PropheticFlamespeakerCastFromExileEffect effect) {
@ -142,7 +142,8 @@ class PropheticFlamespeakerCastFromExileEffect extends AsThoughEffectImpl {
}
@Override
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
return sourceId.equals(getTargetPointer().getFirst(game, source)) && game.getState().getZone(sourceId) == Zone.EXILED;
public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) {
return source.getControllerId().equals(affectedControllerId) &&
objectId.equals(getTargetPointer().getFirst(game, source));
}
}

View file

@ -72,7 +72,7 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
*
* @param cost alternate cost to pay
* @param condition only if the condition is true it's possible to use the alternate costs
* @param rule if set used as rule text
* @param rule if != null used as rule text
* @param filter filters the cards this alternate cost can be applied to
* @param onlyMana if true only the mana costs are replaced by this costs, other costs stay untouched
*/

View file

@ -435,7 +435,7 @@ public class ContinuousEffects implements Serializable {
for (AsThoughEffect effect: asThoughEffectsList) {
HashSet<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) {
if (controllerId.equals(ability.getControllerId())) {
//if (controllerId.equals(ability.getControllerId())) { must be checked in the applies method
if (affectedAbility == null) {
if (effect.applies(objectId, ability, controllerId, game)) {
return true;
@ -445,7 +445,7 @@ public class ContinuousEffects implements Serializable {
return true;
}
}
}
//}
}
}
return false;

View file

@ -490,7 +490,7 @@ public class CardUtil {
uniqueString.append(text);
}
uniqueString.append(cardId);
Card card = game.getCard(cardId);
Card card = game.getCard(cardId); // if called for a token, the id is enough
if (card != null) {
uniqueString.append(card.getZoneChangeCounter());
}