mirror of
https://github.com/magefree/mage.git
synced 2025-12-25 21:12:04 -08:00
Merge remote-tracking branch 'remotes/upstream/master'
This commit is contained in:
commit
dfa4bad8c5
138 changed files with 1836 additions and 856 deletions
|
|
@ -149,7 +149,7 @@ public class BeginningOfEndStepTriggeredAbility extends TriggeredAbilityImpl {
|
|||
case ANY:
|
||||
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of each end step, ").toString();
|
||||
case CONTROLLER_ATTACHED_TO:
|
||||
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of the end step of enchanted creature's controller, ").toString();
|
||||
return sb.insert(0, generateConditionString()).insert(0, abilityWordRule + "At the beginning of the end step of enchanted permanent's controller, ").toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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.abilities.condition.common;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.keyword.BuybackAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.game.Game;
|
||||
|
||||
/**
|
||||
* @author spjspj
|
||||
*/
|
||||
public enum BuybackCondition implements Condition {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Card card = game.getCard(source.getSourceId());
|
||||
if (card != null) {
|
||||
return card.getAbilities().stream()
|
||||
.filter(a -> a instanceof BuybackAbility)
|
||||
.anyMatch(b -> ((BuybackAbility) b).isActivated());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
|
||||
package mage.abilities.costs.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
|
||||
public class CyclingDiscardCost extends CostImpl {
|
||||
|
||||
public CyclingDiscardCost() {
|
||||
}
|
||||
|
||||
public CyclingDiscardCost(CyclingDiscardCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
return game.getPlayer(controllerId).getHand().contains(sourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player != null) {
|
||||
Card card = player.getHand().get(sourceId, game);
|
||||
if (card != null) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CYCLE_CARD, card.getId(), card.getId(), card.getOwnerId()));
|
||||
paid = player.discard(card, null, game);
|
||||
if (paid) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CYCLED_CARD, card.getId(), card.getId(), card.getOwnerId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Discard this card";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CyclingDiscardCost copy() {
|
||||
return new CyclingDiscardCost(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,6 @@ import mage.abilities.Ability;
|
|||
import mage.abilities.effects.AsThoughEffectImpl;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Outcome;
|
||||
import mage.filter.FilterCard;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ import mage.constants.Duration;
|
|||
import mage.constants.Layer;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.SubLayer;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.players.Player;
|
||||
|
||||
/**
|
||||
|
|
@ -70,11 +73,11 @@ public class PlayWithTheTopCardRevealedEffect extends ContinuousEffectImpl {
|
|||
if (allPlayers) {
|
||||
for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null) {
|
||||
if (player != null && !isCastFromPlayersLibrary(game, playerId)) {
|
||||
player.setTopCardRevealed(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (!isCastFromPlayersLibrary(game, controller.getId())) {
|
||||
controller.setTopCardRevealed(true);
|
||||
}
|
||||
return true;
|
||||
|
|
@ -82,6 +85,16 @@ public class PlayWithTheTopCardRevealedEffect extends ContinuousEffectImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
boolean isCastFromPlayersLibrary(Game game, UUID playerId) {
|
||||
if (!game.getStack().isEmpty()) {
|
||||
StackObject stackObject = game.getStack().getLast();
|
||||
return stackObject instanceof Spell
|
||||
&& !((Spell) stackObject).isDoneActivatingManaAbilities()
|
||||
&& Zone.LIBRARY.equals(((Spell) stackObject).getFromZone());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayWithTheTopCardRevealedEffect copy() {
|
||||
return new PlayWithTheTopCardRevealedEffect(this);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import mage.abilities.costs.Costs;
|
|||
import mage.abilities.costs.OptionalAdditionalCost;
|
||||
import mage.abilities.costs.OptionalAdditionalCostImpl;
|
||||
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
||||
import mage.abilities.costs.mana.GenericManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.effects.ReplacementEffectImpl;
|
||||
import mage.cards.Card;
|
||||
|
|
@ -66,6 +67,7 @@ public class BuybackAbility extends StaticAbility implements OptionalAdditionalS
|
|||
private static final String reminderTextCost = "You may {cost} in addition to any other costs as you cast this spell. If you do, put this card into your hand as it resolves.";
|
||||
private static final String reminderTextMana = "You may pay an additional {cost} as you cast this spell. If you do, put this card into your hand as it resolves.";
|
||||
protected OptionalAdditionalCost buybackCost;
|
||||
private int amountToReduceBy = 0;
|
||||
|
||||
public BuybackAbility(String manaString) {
|
||||
super(Zone.STACK, new BuybackEffect());
|
||||
|
|
@ -96,17 +98,51 @@ public class BuybackAbility extends StaticAbility implements OptionalAdditionalS
|
|||
}
|
||||
}
|
||||
|
||||
public void resetReduceCost() {
|
||||
amountToReduceBy = 0;
|
||||
}
|
||||
|
||||
// Called by Memory Crystal to reduce mana costs.
|
||||
public int reduceCost(int genericManaToReduce) {
|
||||
int amountToReduce = genericManaToReduce;
|
||||
boolean foundCostToReduce = false;
|
||||
if (buybackCost != null) {
|
||||
for (Object cost : ((Costs) buybackCost)) {
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
for (Object c : (ManaCostsImpl) cost) {
|
||||
if (c instanceof GenericManaCost) {
|
||||
int newCostCMC = ((GenericManaCost) c).convertedManaCost() - amountToReduceBy - genericManaToReduce;
|
||||
foundCostToReduce = true;
|
||||
if (newCostCMC > 0) {
|
||||
amountToReduceBy += genericManaToReduce;
|
||||
} else {
|
||||
amountToReduce = ((GenericManaCost) c).convertedManaCost() - amountToReduceBy;
|
||||
amountToReduceBy = ((GenericManaCost) c).convertedManaCost();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (foundCostToReduce) {
|
||||
return amountToReduce;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActivated() {
|
||||
if (buybackCost != null) {
|
||||
return buybackCost.isActivated();
|
||||
}
|
||||
resetReduceCost();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resetBuyback() {
|
||||
if (buybackCost != null) {
|
||||
buybackCost.reset();
|
||||
resetReduceCost();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,20 +27,14 @@
|
|||
*/
|
||||
package mage.abilities.keyword;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.ActivatedAbilityImpl;
|
||||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.costs.CostImpl;
|
||||
import mage.abilities.costs.common.CyclingDiscardCost;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
|
||||
/**
|
||||
|
|
@ -90,44 +84,3 @@ public class CyclingAbility extends ActivatedAbilityImpl {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
class CyclingDiscardCost extends CostImpl {
|
||||
|
||||
public CyclingDiscardCost() {
|
||||
}
|
||||
|
||||
public CyclingDiscardCost(CyclingDiscardCost cost) {
|
||||
super(cost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
|
||||
return game.getPlayer(controllerId).getHand().contains(sourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
|
||||
Player player = game.getPlayer(controllerId);
|
||||
if (player != null) {
|
||||
Card card = player.getHand().get(sourceId, game);
|
||||
if (card != null) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CYCLE_CARD, card.getId(), card.getId(), card.getOwnerId()));
|
||||
paid = player.discard(card, null, game);
|
||||
if (paid) {
|
||||
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.CYCLED_CARD, card.getId(), card.getId(), card.getOwnerId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return paid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return "Discard this card";
|
||||
}
|
||||
|
||||
@Override
|
||||
public CyclingDiscardCost copy() {
|
||||
return new CyclingDiscardCost(this);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,4 +53,9 @@ public class ActivateAsSorceryManaAbility extends SimpleManaAbility {
|
|||
public ActivateAsSorceryManaAbility copy() {
|
||||
return new ActivateAsSorceryManaAbility(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return super.getRule() + " Activate this ability only any time you could cast a sorcery.";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ import mage.abilities.ActivatedAbilityImpl;
|
|||
import mage.abilities.costs.Cost;
|
||||
import mage.abilities.effects.common.ManaEffect;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.AsThoughEffectType;
|
||||
import mage.constants.TimingRule;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.Game;
|
||||
|
||||
|
|
@ -70,7 +72,12 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
|
|||
if (!controlsAbility(playerId, game)) {
|
||||
return false;
|
||||
}
|
||||
// check if player is in the process of playing spell costs and he is no longer allowed to use activated mana abilities (e.g. becaus he started to use improvise)
|
||||
if (timing == TimingRule.SORCERY
|
||||
&& !game.canPlaySorcery(playerId)
|
||||
&& !game.getContinuousEffects().asThough(sourceId, AsThoughEffectType.ACTIVATE_AS_INSTANT, this, controllerId, game)) {
|
||||
return false;
|
||||
}
|
||||
// check if player is in the process of playing spell costs and he is no longer allowed to use activated mana abilities (e.g. because he started to use improvise)
|
||||
//20091005 - 605.3a
|
||||
return costs.canPay(this, sourceId, controllerId, game);
|
||||
|
||||
|
|
|
|||
|
|
@ -322,6 +322,7 @@ public enum SubType {
|
|||
GIDEON("Gideon", SubTypeSet.PlaneswalkerType, false),
|
||||
JACE("Jace", SubTypeSet.PlaneswalkerType, false),
|
||||
KARN("Karn", SubTypeSet.PlaneswalkerType, false),
|
||||
KAYA("Kaya", SubTypeSet.PlaneswalkerType, false),
|
||||
KIORA("Kiora", SubTypeSet.PlaneswalkerType, false),
|
||||
KOTH("Koth", SubTypeSet.PlaneswalkerType, false),
|
||||
LILIANA("Liliana", SubTypeSet.PlaneswalkerType, false),
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ public final class StaticFilters {
|
|||
public static final FilterControlledPermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control");
|
||||
public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_ANOTHER_CREATURE = new FilterControlledCreaturePermanent("another creature");
|
||||
public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_NON_LAND = new FilterControlledPermanent("nonland permanent");
|
||||
public static final FilterLandPermanent FILTER_LAND = new FilterLandPermanent();
|
||||
public static final FilterLandPermanent FILTER_LANDS = new FilterLandPermanent("lands");
|
||||
public static final FilterLandPermanent FILTER_BASIC_LAND = new FilterLandPermanent();
|
||||
|
||||
public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE = new FilterCreaturePermanent();
|
||||
public static final FilterCreaturePermanent FILTER_PERMANENT_A_CREATURE = new FilterCreaturePermanent("a creature");
|
||||
|
|
@ -51,6 +54,10 @@ public final class StaticFilters {
|
|||
public static final FilterSpell FILTER_SPELL_NON_CREATURE
|
||||
= (FilterSpell) new FilterSpell("noncreature spell").add(Predicates.not(new CardTypePredicate(CardType.CREATURE)));
|
||||
|
||||
public static final FilterSpell FILTER_SPELL = new FilterSpell();
|
||||
|
||||
public static final FilterSpell FILTER_INSTANT_OR_SORCERY_SPELL = new FilterSpell("instant or sorcery spell");
|
||||
|
||||
public static final FilterPermanent FILTER_CREATURE_TOKENS = new FilterCreaturePermanent("creature tokens");
|
||||
|
||||
public static final FilterPermanent FILTER_ATTACKING_CREATURES = new FilterCreaturePermanent("attacking creatures");
|
||||
|
|
@ -58,6 +65,8 @@ public final class StaticFilters {
|
|||
static {
|
||||
FILTER_CONTROLLED_PERMANENT_NON_LAND.add(
|
||||
Predicates.not(new CardTypePredicate(CardType.LAND)));
|
||||
|
||||
|
||||
FILTER_CREATURE_TOKENS.add(new TokenPredicate());
|
||||
|
||||
FILTER_ATTACKING_CREATURES.add(new AttackingPredicate());
|
||||
|
|
@ -87,6 +96,11 @@ public final class StaticFilters {
|
|||
new CardTypePredicate(CardType.ARTIFACT),
|
||||
new CardTypePredicate(CardType.CREATURE)
|
||||
));
|
||||
|
||||
FILTER_INSTANT_OR_SORCERY_SPELL.add(Predicates.or(
|
||||
new CardTypePredicate(CardType.INSTANT),
|
||||
new CardTypePredicate(CardType.SORCERY)
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,14 +33,22 @@ import mage.abilities.common.SimpleStaticAbility;
|
|||
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
|
||||
import mage.abilities.effects.common.continuous.SetPowerToughnessSourceEffect;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import static mage.game.permanent.token.DokaiWeaverofLifeToken.filterLands;
|
||||
import mage.filter.common.FilterControlledPermanent;
|
||||
import mage.filter.predicate.mageobject.SubtypePredicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class KalonianTwingroveTreefolkWarriorToken extends Token {
|
||||
|
||||
final static FilterControlledPermanent filterLands = new FilterControlledPermanent("Forests you control");
|
||||
|
||||
static {
|
||||
filterLands.add(new SubtypePredicate(SubType.FOREST));
|
||||
}
|
||||
|
||||
public KalonianTwingroveTreefolkWarriorToken() {
|
||||
super("Treefolk Warrior", "green Treefolk Warrior creature token with \"This creature's power and toughness are each equal to the number of Forests you control.\"");
|
||||
|
|
|
|||
|
|
@ -44,6 +44,5 @@ public class RhonassLastStandToken extends Token {
|
|||
subtype.add("Snake");
|
||||
power = new MageInt(5);
|
||||
toughness = new MageInt(4);
|
||||
addAbility(TrampleAbility.getInstance());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
|
||||
public boolean activate(Game game, boolean noMana) {
|
||||
setDoneActivatingManaAbilities(false); // Used for e.g. improvise
|
||||
if (!spellAbilities.get(0).activate(game, noMana)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -157,7 +158,7 @@ public class Spell extends StackObjImpl implements Card {
|
|||
}
|
||||
}
|
||||
}
|
||||
setDoneActivatingManaAbilities(false); // can be activated again maybe during the resolution of the spell (e.g. Metallic Rebuke)
|
||||
setDoneActivatingManaAbilities(true); // can be activated again maybe during the resolution of the spell (e.g. Metallic Rebuke)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ package mage.target;
|
|||
import mage.abilities.Ability;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.game.stack.StackObject;
|
||||
|
|
@ -49,7 +50,7 @@ public class TargetSpell extends TargetObject {
|
|||
private final Set<UUID> sourceIds = new HashSet<>();
|
||||
|
||||
public TargetSpell() {
|
||||
this(1, 1, new FilterSpell());
|
||||
this(1, 1, StaticFilters.FILTER_SPELL);
|
||||
}
|
||||
|
||||
public TargetSpell(FilterSpell filter) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package mage.watchers.common;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
|
|
@ -16,7 +15,8 @@ import mage.watchers.Watcher;
|
|||
*/
|
||||
public class LandfallWatcher extends Watcher {
|
||||
|
||||
final Set<UUID> playerPlayedLand = new HashSet<>();
|
||||
final Set<UUID> playerPlayedLand = new HashSet<>(); // player that played land
|
||||
final Set<UUID> landPlayed = new HashSet<>(); // land played
|
||||
|
||||
public LandfallWatcher() {
|
||||
super(LandfallWatcher.class.getSimpleName(), WatcherScope.GAME);
|
||||
|
|
@ -25,6 +25,7 @@ public class LandfallWatcher extends Watcher {
|
|||
public LandfallWatcher(final LandfallWatcher watcher) {
|
||||
super(watcher);
|
||||
playerPlayedLand.addAll(watcher.playerPlayedLand);
|
||||
landPlayed.addAll(watcher.landPlayed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -34,10 +35,13 @@ public class LandfallWatcher extends Watcher {
|
|||
|
||||
@Override
|
||||
public void watch(GameEvent event, Game game) {
|
||||
if (event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD) {
|
||||
if (event.getType() == GameEvent.EventType.LAND_PLAYED) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId());
|
||||
if (permanent != null && permanent.isLand() && !playerPlayedLand.contains(event.getPlayerId())) {
|
||||
if (permanent != null
|
||||
&& permanent.isLand()
|
||||
&& !playerPlayedLand.contains(event.getPlayerId())) {
|
||||
playerPlayedLand.add(event.getPlayerId());
|
||||
landPlayed.add(event.getTargetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,10 +49,15 @@ public class LandfallWatcher extends Watcher {
|
|||
@Override
|
||||
public void reset() {
|
||||
playerPlayedLand.clear();
|
||||
landPlayed.clear();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
public boolean landPlayed(UUID playerId) {
|
||||
return playerPlayedLand.contains(playerId);
|
||||
}
|
||||
|
||||
public boolean wasLandPlayed(UUID landId) {
|
||||
return landPlayed.contains(landId);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue