* Fixed some cost classes that didn't hadle correctly if a cost concerning card movement is paid or not.

This commit is contained in:
LevelX2 2015-12-25 11:04:46 +01:00
parent eb0ae55257
commit 0c2abc69de
21 changed files with 141 additions and 112 deletions

View file

@ -1,16 +1,16 @@
/*
* 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
@ -20,12 +20,11 @@
* 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.costs.common;
import java.util.ArrayList;
@ -34,6 +33,8 @@ import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
@ -53,18 +54,17 @@ public class ExileFromGraveCost extends CostImpl {
public ExileFromGraveCost(TargetCardInYourGraveyard target) {
this.addTarget(target);
if (target.getMaxNumberOfTargets() > 1) {
this.text = "Exile " +
(target.getNumberOfTargets() == 1 && target.getMaxNumberOfTargets() == Integer.MAX_VALUE ? "one or more" :
((target.getNumberOfTargets() < target.getMaxNumberOfTargets() ? "up to ":"")) +
CardUtil.numberToText(target.getMaxNumberOfTargets())) +
" " + target.getTargetName();
}
else {
this.text = "Exile "
+ (target.getNumberOfTargets() == 1 && target.getMaxNumberOfTargets() == Integer.MAX_VALUE ? "one or more"
: ((target.getNumberOfTargets() < target.getMaxNumberOfTargets() ? "up to " : ""))
+ CardUtil.numberToText(target.getMaxNumberOfTargets()))
+ " " + target.getTargetName();
} else {
this.text = "Exile " + target.getTargetName();
}
if (!this.text.endsWith(" from your graveyard")) {
this.text = this.text + " from your graveyard";
}
}
}
public ExileFromGraveCost(TargetCardInYourGraveyard target, String text) {
@ -77,7 +77,6 @@ public class ExileFromGraveCost extends CostImpl {
this.text = "Exile " + target.getTargetName();
}
public ExileFromGraveCost(final ExileFromGraveCost cost) {
super(cost);
this.exiledCards.addAll(cost.getExiledCards());
@ -88,15 +87,18 @@ public class ExileFromGraveCost extends CostImpl {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.Exile, controllerId, sourceId, game)) {
for (UUID targetId: targets.get(0).getTargets()) {
for (UUID targetId : targets.get(0).getTargets()) {
Card card = game.getCard(targetId);
if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) {
return false;
}
exiledCards.add(card);
paid |= controller.moveCardToExileWithInfo(card, null, null, sourceId, game, Zone.GRAVEYARD, true);
}
}
Cards cardsToExile = new CardsImpl();
cardsToExile.addAll(exiledCards);
controller.moveCards(cardsToExile, Zone.EXILED, ability, game);
paid = true;
}
return paid;

View file

@ -25,17 +25,17 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.costs.common;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.abilities.costs.mana.VariableManaCost;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
@ -47,47 +47,52 @@ import mage.target.common.TargetCardInHand;
* @author LevelX2
*/
public class ExileFromHandCost extends CostImpl {
List<Card> cards = new ArrayList<>();
private boolean setXFromCMC;
public ExileFromHandCost(TargetCardInHand target) {
this(target, false);
}
/**
*
*
* @param target
* @param setXFromCMC the spells X value on the stack is set to the converted mana costs of the exiled card
* @param setXFromCMC the spells X value on the stack is set to the
* converted mana costs of the exiled card
*/
public ExileFromHandCost(TargetCardInHand target, boolean setXFromCMC) {
this.addTarget(target);
this.text = "exile " + target.getTargetName();
this.setXFromCMC = setXFromCMC;
}
public ExileFromHandCost(final ExileFromHandCost cost) {
super(cost);
for (Card card: cost.cards) {
for (Card card : cost.cards) {
this.cards.add(card.copy());
}
this.setXFromCMC = cost.setXFromCMC;
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
if (targets.choose(Outcome.Exile, controllerId, sourceId, game)) {
Player player = game.getPlayer(controllerId);
int cmc = 0;
for (UUID targetId: targets.get(0).getTargets()) {
for (UUID targetId : targets.get(0).getTargets()) {
Card card = player.getHand().get(targetId, game);
if (card == null) {
return false;
}
cmc += card.getManaCost().convertedManaCost();
this.cards.add(card);
paid |= player.moveCardToExileWithInfo(card, null, null, ability.getSourceId(), game, Zone.HAND, true);
}
if (paid && setXFromCMC) {
Cards cardsToExile = new CardsImpl();
cardsToExile.addAll(cards);
player.moveCards(cardsToExile, Zone.EXILED, ability, game);
paid = true;
if (setXFromCMC) {
VariableManaCost vmc = new VariableManaCost();
vmc.setAmount(cmc);
vmc.setPaid();
@ -96,18 +101,18 @@ public class ExileFromHandCost extends CostImpl {
}
return paid;
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return targets.canChoose(sourceId, controllerId, game);
}
@Override
public ExileFromHandCost copy() {
return new ExileFromHandCost(this);
}
public List<Card> getCards() {
public List<Card> getCards() {
return cards;
}
}

View file

@ -25,11 +25,9 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.costs.common;
import java.util.UUID;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.constants.Outcome;
@ -37,45 +35,46 @@ import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSpell;
/**
*
* @author LevelX2
*/
public class ExileFromStackCost extends CostImpl {
public ExileFromStackCost(TargetSpell target) {
this.addTarget(target);
this.text = "Exile " + target.getTargetName();
}
public ExileFromStackCost(ExileFromStackCost cost) {
super(cost);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
if (targets.choose(Outcome.Exile, controllerId, sourceId, game)) {
Player player = game.getPlayer(controllerId);
for (UUID targetId: targets.get(0).getTargets()) {
for (UUID targetId : targets.get(0).getTargets()) {
Spell spellToExile = game.getStack().getSpell(targetId);
if (spellToExile == null) {
return false;
}
paid |= spellToExile.moveToExile(null, "", ability.getSourceId(), game);
if (paid && !game.isSimulation()) {
game.informPlayers(player.getLogName() + " exiles " + spellToExile.getName() +" (as costs)");
spellToExile.moveToExile(null, "", ability.getSourceId(), game);
paid = true;
if (!game.isSimulation()) {
game.informPlayers(player.getLogName() + " exiles " + spellToExile.getName() + " (as costs)");
}
}
}
return paid;
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
return targets.canChoose(controllerId, game);
}
@Override
public ExileFromStackCost copy() {
return new ExileFromStackCost(this);

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.costs.common;
import java.util.UUID;
@ -47,7 +46,7 @@ public class ExileFromTopOfLibraryCost extends CostImpl {
public ExileFromTopOfLibraryCost(int amount) {
this.amount = amount;
this.text = "Exile the top " + (amount == 1 ? "card" : CardUtil.numberToText(amount) + " cards")
+ " of your library";
+ " of your library";
}
public ExileFromTopOfLibraryCost(ExileFromTopOfLibraryCost cost) {
@ -58,7 +57,7 @@ public class ExileFromTopOfLibraryCost extends CostImpl {
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
Player controller = game.getPlayer(controllerId);
if(controller == null) {
if (controller == null) {
return false;
}
return controller.getLibrary().size() >= amount;
@ -67,8 +66,8 @@ public class ExileFromTopOfLibraryCost extends CostImpl {
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
Player controller = game.getPlayer(controllerId);
if(controller != null) {
controller.moveCards(controller.getLibrary().getTopCards(game, amount), Zone.LIBRARY, Zone.EXILED, ability, game);
if (controller != null) {
controller.moveCards(controller.getLibrary().getTopCards(game, amount), Zone.EXILED, ability, game);
paid = true;
}
return paid;

View file

@ -48,7 +48,7 @@ public class ExileOpponentsCardFromExileToGraveyardCost extends CostImpl {
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
paid = true;
controller.moveCards(card, null, Zone.GRAVEYARD, ability, game);
controller.moveCards(card, Zone.GRAVEYARD, ability, game);
}
}
}

View file

@ -1,16 +1,16 @@
/*
* 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
@ -20,12 +20,11 @@
* 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.costs.common;
import java.util.UUID;
@ -45,14 +44,16 @@ import mage.util.CardUtil;
public class ExileSourceCost extends CostImpl {
private boolean toUniqueExileZone;
public ExileSourceCost() {
this.text = "Exile {this}";
}
/**
*
* @param toUniqueExileZone moves the card to a source object dependant unique exile zone, so another
* effect of the same source object (e.g. Deadeye Navigator) can identify the card
*
* @param toUniqueExileZone moves the card to a source object dependant
* unique exile zone, so another effect of the same source object (e.g.
* Deadeye Navigator) can identify the card
*/
public ExileSourceCost(boolean toUniqueExileZone) {
this.text = "Exile {this}";
@ -68,14 +69,19 @@ public class ExileSourceCost extends CostImpl {
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
MageObject sourceObject = ability.getSourceObject(game);
Player controller = game.getPlayer(controllerId);
if (controller != null && sourceObject != null && (sourceObject instanceof Card)) {
if (controller != null && sourceObject != null && (sourceObject instanceof Card)) {
UUID exileZoneId = null;
String exileZoneName = "";
if (toUniqueExileZone) {
exileZoneId = CardUtil.getExileZoneId(game, ability.getSourceId(), ability.getSourceObjectZoneChangeCounter());
exileZoneName = sourceObject.getName();
}
paid = controller.moveCardToExileWithInfo((Card) sourceObject, exileZoneId, exileZoneName, sourceId, game, game.getState().getZone(sourceObject.getId()), true);
exileZoneName = sourceObject.getName();
}
controller.moveCardToExileWithInfo((Card) sourceObject, exileZoneId, exileZoneName, sourceId, game, game.getState().getZone(sourceObject.getId()), true);
// 117.11. The actions performed when paying a cost may be modified by effects.
// Even if they are, meaning the actions that are performed don't match the actions
// that are called for, the cost has still been paid.
// so return state here is not important because the user indended to exile the target anyway
paid = true;
}
return paid;
}

View file

@ -1,16 +1,16 @@
/*
* 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
@ -20,12 +20,11 @@
* 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.costs.common;
import java.util.UUID;
@ -56,7 +55,12 @@ public class ExileSourceFromGraveCost extends CostImpl {
if (controller != null) {
Card card = game.getCard(sourceId);
if (card != null && game.getState().getZone(sourceId).equals(Zone.GRAVEYARD)) {
paid = controller.moveCardToExileWithInfo(card, null, "", sourceId, game, Zone.GRAVEYARD, true);
controller.moveCardToExileWithInfo(card, null, "", sourceId, game, Zone.GRAVEYARD, true);
// 117.11. The actions performed when paying a cost may be modified by effects.
// Even if they are, meaning the actions that are performed don't match the actions
// that are called for, the cost has still been paid.
// so return state here is not important because the user indended to exile the target anyway
paid = true;
}
}
return paid;

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.costs.common;
import mage.abilities.Ability;
@ -40,8 +39,7 @@ import mage.target.common.TargetCardInYourGraveyard;
*
* @author LevelX2
*/
public class ExileXFromYourGraveCost extends VariableCostImpl {
public class ExileXFromYourGraveCost extends VariableCostImpl {
protected FilterCard filter;
@ -50,10 +48,9 @@ public class ExileXFromYourGraveCost extends VariableCostImpl {
}
public ExileXFromYourGraveCost(FilterCard filter, boolean additionalCostText) {
super(new StringBuilder(filter.getMessage()).append(" to exile").toString());
super(filter.getMessage() + " to exile");
this.filter = filter;
this.text = new StringBuilder(additionalCostText ? "As an additional cost to cast {source}, exile ":"Exile ")
.append(xText).append(" ").append(filter.getMessage()).toString();
this.text = (additionalCostText ? "As an additional cost to cast {source}, exile " : "Exile ") + xText + " " + filter.getMessage();
}
public ExileXFromYourGraveCost(final ExileXFromYourGraveCost cost) {

View file

@ -27,10 +27,14 @@
*/
package mage.abilities.costs.common;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
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;
@ -61,13 +65,16 @@ public class ReturnToHandChosenControlledPermanentCost extends CostImpl {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.ReturnToHand, controllerId, sourceId, game)) {
Set<Card> permanentsToReturn = new HashSet<>();
for (UUID targetId : targets.get(0).getTargets()) {
Permanent permanent = game.getPermanent(targetId);
if (permanent == null) {
return false;
}
paid |= controller.moveCardToHandWithInfo(permanent, sourceId, game);
permanentsToReturn.add((Card) permanent);
}
controller.moveCards(permanentsToReturn, Zone.HAND, ability, game);
paid = true;
}
}
return paid;

View file

@ -25,36 +25,38 @@
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.abilities.costs.common;
import java.util.UUID;
import mage.constants.Zone;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
/**
* @author Loki
*/
public class ReturnToHandSourceCost extends CostImpl {
public class ReturnToHandFromBattlefieldSourceCost extends CostImpl {
public ReturnToHandSourceCost() {
public ReturnToHandFromBattlefieldSourceCost() {
this.text = "return {this} to its owner's hand";
}
public ReturnToHandSourceCost(ReturnToHandSourceCost cost) {
public ReturnToHandFromBattlefieldSourceCost(ReturnToHandFromBattlefieldSourceCost cost) {
super(cost);
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana) {
Permanent permanent = game.getPermanent(sourceId);
if (permanent == null)
Player controller = game.getPlayer(controllerId);
if (permanent == null || controller == null) {
return false;
paid = permanent.moveToZone(Zone.HAND, sourceId, game, false);
}
controller.moveCards(permanent, Zone.HAND, ability, game);
paid = true;
return paid;
}
@ -64,7 +66,7 @@ public class ReturnToHandSourceCost extends CostImpl {
}
@Override
public ReturnToHandSourceCost copy() {
return new ReturnToHandSourceCost(this);
public ReturnToHandFromBattlefieldSourceCost copy() {
return new ReturnToHandFromBattlefieldSourceCost(this);
}
}

View file

@ -27,10 +27,14 @@
*/
package mage.abilities.costs.common;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.CostImpl;
import mage.cards.Card;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInYourGraveyard;
@ -59,14 +63,18 @@ public class ReturnToHandFromGraveyardCost extends CostImpl {
Player controller = game.getPlayer(controllerId);
if (controller != null) {
if (targets.choose(Outcome.ReturnToHand, controllerId, sourceId, game)) {
Set<Card> cardsToMove = new LinkedHashSet<>();
for (UUID targetId : targets.get(0).getTargets()) {
mage.cards.Card targetCard = game.getCard(targetId);
if (targetCard == null) {
return false;
}
paid |= controller.moveCardToHandWithInfo(targetCard, sourceId, game);
cardsToMove.add(targetCard);
}
controller.moveCards(cardsToMove, Zone.HAND, ability, game);
paid = true;
}
}
return paid;
}