mirror of
https://github.com/Relintai/mtg-forge-ios.git
synced 2025-04-15 00:48:26 +02:00
- Added an experimental option to allow ordering cards going to graveyard when playing with cards that care about graveyard order (Volrath's Shapeshifter and others). Disabled by default.
git-svn-id: http://svn.slightlymagic.net/forge/trunk@35782 269b9781-a132-4a9b-9d4e-f004f1b56b58
This commit is contained in:
parent
1c2a47d1f2
commit
1f77d51632
@ -1,13 +1,5 @@
|
|||||||
package forge.ai;
|
package forge.ai;
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import forge.card.CardStateName;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import com.esotericsoftware.minlog.Log;
|
import com.esotericsoftware.minlog.Log;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
@ -15,9 +7,9 @@ import com.google.common.collect.Iterables;
|
|||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.ai.ability.ProtectAi;
|
import forge.ai.ability.ProtectAi;
|
||||||
|
import forge.card.CardStateName;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.ICardFace;
|
import forge.card.ICardFace;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
@ -40,11 +32,7 @@ import forge.game.mana.Mana;
|
|||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.DelayedReveal;
|
import forge.game.player.*;
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
|
||||||
import forge.game.player.PlayerController;
|
|
||||||
import forge.game.player.PlayerView;
|
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.*;
|
import forge.game.spellability.*;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
@ -55,6 +43,12 @@ import forge.util.ITriggerEvent;
|
|||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
import forge.util.collect.FCollection;
|
import forge.util.collect.FCollection;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.security.InvalidParameterException;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -298,7 +292,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone) {
|
public CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone, SpellAbility source) {
|
||||||
//TODO Add logic for AI ordering here
|
//TODO Add logic for AI ordering here
|
||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
@ -26,16 +24,10 @@ import com.google.common.collect.Iterables;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
|
import forge.card.CardStateName;
|
||||||
import forge.card.CardType.Supertype;
|
import forge.card.CardType.Supertype;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.event.Event;
|
import forge.game.event.Event;
|
||||||
@ -44,11 +36,7 @@ import forge.game.phase.Phase;
|
|||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.phase.Untap;
|
import forge.game.phase.Untap;
|
||||||
import forge.game.player.IGameEntitiesFactory;
|
import forge.game.player.*;
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.player.PlayerCollection;
|
|
||||||
import forge.game.player.PlayerView;
|
|
||||||
import forge.game.player.RegisteredPlayer;
|
|
||||||
import forge.game.replacement.ReplacementHandler;
|
import forge.game.replacement.ReplacementHandler;
|
||||||
import forge.game.spellability.Ability;
|
import forge.game.spellability.Ability;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
@ -56,11 +44,16 @@ import forge.game.spellability.SpellAbilityStackInstance;
|
|||||||
import forge.game.spellability.SpellAbilityView;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.game.trigger.TriggerHandler;
|
import forge.game.trigger.TriggerHandler;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.*;
|
import forge.game.zone.CostPaymentStack;
|
||||||
|
import forge.game.zone.MagicStack;
|
||||||
|
import forge.game.zone.Zone;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
import forge.trackable.Tracker;
|
import forge.trackable.Tracker;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.Visitor;
|
import forge.util.Visitor;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the state of a <i>single game</i>, a new instance is created for each game.
|
* Represents the state of a <i>single game</i>, a new instance is created for each game.
|
||||||
*/
|
*/
|
||||||
@ -108,6 +101,8 @@ public class Game {
|
|||||||
private final GameView view;
|
private final GameView view;
|
||||||
private final Tracker tracker = new Tracker();
|
private final Tracker tracker = new Tracker();
|
||||||
|
|
||||||
|
private Map<Player, Boolean> orderedGraveyardMap = new HashMap<>();
|
||||||
|
|
||||||
public Player getMonarch() {
|
public Player getMonarch() {
|
||||||
return monarch;
|
return monarch;
|
||||||
}
|
}
|
||||||
@ -877,4 +872,32 @@ public class Game {
|
|||||||
cardCache.clear();
|
cardCache.clear();
|
||||||
//playerCache.clear();
|
//playerCache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isGraveyardOrdered() {
|
||||||
|
boolean ordered = false;
|
||||||
|
for (Player p : getPlayers()) {
|
||||||
|
ordered |= isGraveyardOrdered(p);
|
||||||
|
}
|
||||||
|
return ordered;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGraveyardOrdered(final Player p) {
|
||||||
|
if (orderedGraveyardMap.containsKey(p)) {
|
||||||
|
return orderedGraveyardMap.get(p);
|
||||||
|
}
|
||||||
|
for (Card c : p.getAllCards()) {
|
||||||
|
if (c.hasSVar("NeedsOrderedGraveyard")) {
|
||||||
|
orderedGraveyardMap.put(p, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (c.getStates().contains(CardStateName.OriginalText)) {
|
||||||
|
if (c.getState(CardStateName.OriginalText).hasSVar("NeedsOrderedGraveyard")) {
|
||||||
|
orderedGraveyardMap.put(p, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orderedGraveyardMap.put(p, false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -861,6 +861,8 @@ public class GameAction {
|
|||||||
checkGameOverCondition();
|
checkGameOverCondition();
|
||||||
|
|
||||||
// do this multiple times, sometimes creatures/permanents will survive when they shouldn't
|
// do this multiple times, sometimes creatures/permanents will survive when they shouldn't
|
||||||
|
boolean orderedDesCreats = false;
|
||||||
|
boolean orderedNoRegCreats = false;
|
||||||
for (int q = 0; q < 9; q++) {
|
for (int q = 0; q < 9; q++) {
|
||||||
checkStaticAbilities(false, affectedCards);
|
checkStaticAbilities(false, affectedCards);
|
||||||
boolean checkAgain = false;
|
boolean checkAgain = false;
|
||||||
@ -877,14 +879,14 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Card> noRegCreats = null;
|
CardCollection noRegCreats = null;
|
||||||
List<Card> desCreats = null;
|
CardCollection desCreats = null;
|
||||||
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
for (final Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
||||||
if (c.isCreature()) {
|
if (c.isCreature()) {
|
||||||
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
||||||
if (c.getNetToughness() <= 0) {
|
if (c.getNetToughness() <= 0) {
|
||||||
if (noRegCreats == null) {
|
if (noRegCreats == null) {
|
||||||
noRegCreats = Lists.newLinkedList();
|
noRegCreats = new CardCollection();
|
||||||
}
|
}
|
||||||
noRegCreats.add(c);
|
noRegCreats.add(c);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
@ -892,7 +894,7 @@ public class GameAction {
|
|||||||
for (final Integer dmg : c.getReceivedDamageFromThisTurn().values()) {
|
for (final Integer dmg : c.getReceivedDamageFromThisTurn().values()) {
|
||||||
if (c.getNetToughness() <= dmg.intValue()) {
|
if (c.getNetToughness() <= dmg.intValue()) {
|
||||||
if (desCreats == null) {
|
if (desCreats == null) {
|
||||||
desCreats = Lists.newLinkedList();
|
desCreats = new CardCollection();
|
||||||
}
|
}
|
||||||
desCreats.add(c);
|
desCreats.add(c);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
@ -904,7 +906,7 @@ public class GameAction {
|
|||||||
// Rule 704.5h - Destroy due to deathtouch
|
// Rule 704.5h - Destroy due to deathtouch
|
||||||
else if (c.getNetToughness() <= c.getDamage() || c.hasBeenDealtDeathtouchDamage()) {
|
else if (c.getNetToughness() <= c.getDamage() || c.hasBeenDealtDeathtouchDamage()) {
|
||||||
if (desCreats == null) {
|
if (desCreats == null) {
|
||||||
desCreats = Lists.newLinkedList();
|
desCreats = new CardCollection();
|
||||||
}
|
}
|
||||||
desCreats.add(c);
|
desCreats.add(c);
|
||||||
c.setHasBeenDealtDeathtouchDamage(false);
|
c.setHasBeenDealtDeathtouchDamage(false);
|
||||||
@ -931,12 +933,29 @@ public class GameAction {
|
|||||||
// only check static abilities once after destroying all the creatures
|
// only check static abilities once after destroying all the creatures
|
||||||
// (e.g. helpful for Erebos's Titan and another creature dealing lethal damage to each other simultaneously)
|
// (e.g. helpful for Erebos's Titan and another creature dealing lethal damage to each other simultaneously)
|
||||||
setHoldCheckingStaticAbilities(true);
|
setHoldCheckingStaticAbilities(true);
|
||||||
|
|
||||||
if (noRegCreats != null) {
|
if (noRegCreats != null) {
|
||||||
|
if (noRegCreats.size() > 1 && game.isGraveyardOrdered() && !orderedNoRegCreats) {
|
||||||
|
noRegCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, noRegCreats, ZoneType.Graveyard);
|
||||||
|
orderedNoRegCreats = true;
|
||||||
|
}
|
||||||
for (Card c : noRegCreats) {
|
for (Card c : noRegCreats) {
|
||||||
sacrificeDestroy(c, null);
|
sacrificeDestroy(c, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (desCreats != null) {
|
if (desCreats != null) {
|
||||||
|
if (desCreats.size() > 1 && game.isGraveyardOrdered() && !orderedDesCreats) {
|
||||||
|
desCreats = CardLists.filter(desCreats, new Predicate<Card>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(Card card) {
|
||||||
|
return card.canBeDestroyed();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!desCreats.isEmpty()) {
|
||||||
|
desCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, desCreats, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
orderedDesCreats = true;
|
||||||
|
}
|
||||||
for (Card c : desCreats) {
|
for (Card c : desCreats) {
|
||||||
destroy(c, null);
|
destroy(c, null);
|
||||||
}
|
}
|
||||||
|
@ -538,4 +538,23 @@ public final class GameActionUtil {
|
|||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollectionView list, ZoneType dest) {
|
||||||
|
CardCollection completeList = new CardCollection();
|
||||||
|
for (Player p : game.getPlayers()) {
|
||||||
|
CardCollection subList = new CardCollection();
|
||||||
|
for (Card c : list) {
|
||||||
|
if (c.getOwner().equals(p)) {
|
||||||
|
subList.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CardCollectionView subListView = subList;
|
||||||
|
if (subList.size() > 1) {
|
||||||
|
subListView = p.getController().orderMoveToZoneList(subList, dest);
|
||||||
|
}
|
||||||
|
completeList.addAll(subListView);
|
||||||
|
}
|
||||||
|
return completeList;
|
||||||
|
}
|
||||||
|
|
||||||
} // end class GameActionUtil
|
} // end class GameActionUtil
|
||||||
|
@ -2,16 +2,12 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
@ -136,6 +132,10 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
|
|||||||
cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination);
|
cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (destination == ZoneType.Graveyard && game.isGraveyardOrdered()) {
|
||||||
|
cards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, cards, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
if (destination.equals(ZoneType.Library) && random) {
|
if (destination.equals(ZoneType.Library) && random) {
|
||||||
CardLists.shuffle(cards);
|
CardLists.shuffle(cards);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@ -80,6 +81,10 @@ public class DestroyAllEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (list.size() > 1 && game.isGraveyardOrdered()) {
|
||||||
|
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
if (noRegen) {
|
if (noRegen) {
|
||||||
for (Card c : list) {
|
for (Card c : list) {
|
||||||
if (game.getAction().destroyNoRegeneration(c, sa) && remDestroyed) {
|
if (game.getAction().destroyNoRegeneration(c, sa) && remDestroyed) {
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -72,8 +74,8 @@ public class DestroyEffect extends SpellAbilityEffect {
|
|||||||
final boolean noRegen = sa.hasParam("NoRegen");
|
final boolean noRegen = sa.hasParam("NoRegen");
|
||||||
final boolean sac = sa.hasParam("Sacrifice");
|
final boolean sac = sa.hasParam("Sacrifice");
|
||||||
|
|
||||||
final List<Card> tgtCards = getTargetCards(sa);
|
CardCollection tgtCards = getTargetCards(sa);
|
||||||
final List<Card> untargetedCards = new ArrayList<Card>();
|
CardCollection untargetedCards = new CardCollection();
|
||||||
|
|
||||||
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
final TargetRestrictions tgt = sa.getTargetRestrictions();
|
||||||
|
|
||||||
@ -84,6 +86,10 @@ public class DestroyEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tgtCards.size() > 1 && game.isGraveyardOrdered()) {
|
||||||
|
tgtCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (final Card tgtC : tgtCards) {
|
for (final Card tgtC : tgtCards) {
|
||||||
if (tgtC.isInPlay() && ((tgt == null) || tgtC.canBeTargetedBy(sa))) {
|
if (tgtC.isInPlay() && ((tgt == null) || tgtC.canBeTargetedBy(sa))) {
|
||||||
boolean destroyed = false;
|
boolean destroyed = false;
|
||||||
@ -109,6 +115,10 @@ public class DestroyEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (untargetedCards.size() > 1 && game.isGraveyardOrdered()) {
|
||||||
|
untargetedCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, untargetedCards, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (final Card unTgtC : untargetedCards) {
|
for (final Card unTgtC : untargetedCards) {
|
||||||
if (unTgtC.isInPlay()) {
|
if (unTgtC.isInPlay()) {
|
||||||
boolean destroyed = false;
|
boolean destroyed = false;
|
||||||
|
@ -2,6 +2,7 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import forge.card.CardStateName;
|
import forge.card.CardStateName;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@ -337,13 +338,18 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now, move the rest to destZone2
|
// now, move the rest to destZone2
|
||||||
if (destZone2 == ZoneType.Library || destZone2 == ZoneType.PlanarDeck || destZone2 == ZoneType.SchemeDeck) {
|
if (destZone2 == ZoneType.Library || destZone2 == ZoneType.PlanarDeck || destZone2 == ZoneType.SchemeDeck
|
||||||
|
|| (destZone2 == ZoneType.Graveyard && game.isGraveyardOrdered())) {
|
||||||
CardCollection afterOrder = rest;
|
CardCollection afterOrder = rest;
|
||||||
if (sa.hasParam("RestRandomOrder")) {
|
if (sa.hasParam("RestRandomOrder")) {
|
||||||
CardLists.shuffle(afterOrder);
|
CardLists.shuffle(afterOrder);
|
||||||
}
|
}
|
||||||
else if (!skipReorder && rest.size() > 1) {
|
else if (!skipReorder && rest.size() > 1) {
|
||||||
afterOrder = (CardCollection)chooser.getController().orderMoveToZoneList(rest, destZone2);
|
if (destZone2 == ZoneType.Graveyard) {
|
||||||
|
afterOrder = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, rest, destZone2);
|
||||||
|
} else {
|
||||||
|
afterOrder = (CardCollection) chooser.getController().orderMoveToZoneList(rest, destZone2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (libraryPosition2 != -1) {
|
if (libraryPosition2 != -1) {
|
||||||
// Closest to top
|
// Closest to top
|
||||||
|
@ -2,14 +2,10 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardFactoryUtil;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates.Presets;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
@ -17,7 +13,6 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
@ -138,7 +133,12 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
boolean runDiscard = !sa.hasParam("Optional")
|
boolean runDiscard = !sa.hasParam("Optional")
|
||||||
|| p.getController().confirmAction(sa, PlayerActionConfirmMode.Random, sa.getParam("DiscardMessage"));
|
|| p.getController().confirmAction(sa, PlayerActionConfirmMode.Random, sa.getParam("DiscardMessage"));
|
||||||
if (runDiscard) {
|
if (runDiscard) {
|
||||||
final List<Card> toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
|
CardCollectionView toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
|
||||||
|
|
||||||
|
if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
toDiscard = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (final Card c : toDiscard) {
|
for (final Card c : toDiscard) {
|
||||||
boolean hasDiscarded = p.discard(c, sa) != null;
|
boolean hasDiscarded = p.discard(c, sa) != null;
|
||||||
if (hasDiscarded) {
|
if (hasDiscarded) {
|
||||||
@ -157,7 +157,13 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
if (mode.equals("Hand")) {
|
if (mode.equals("Hand")) {
|
||||||
boolean shouldRemember = sa.hasParam("RememberDiscarded");
|
boolean shouldRemember = sa.hasParam("RememberDiscarded");
|
||||||
for(Card c : Lists.newArrayList(p.getCardsIn(ZoneType.Hand))) { // without copying will get concurrent modification exception
|
CardCollectionView toDiscard = new CardCollection(Lists.newArrayList(p.getCardsIn(ZoneType.Hand)));
|
||||||
|
|
||||||
|
if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
toDiscard = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Card c : toDiscard) { // without copying will get concurrent modification exception
|
||||||
boolean hasDiscarded = p.discard(c, sa) != null;
|
boolean hasDiscarded = p.discard(c, sa) != null;
|
||||||
if( hasDiscarded && shouldRemember )
|
if( hasDiscarded && shouldRemember )
|
||||||
source.addRemembered(c);
|
source.addRemembered(c);
|
||||||
@ -166,7 +172,11 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mode.equals("NotRemembered")) {
|
if (mode.equals("NotRemembered")) {
|
||||||
final List<Card> dPHand = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), "Card.IsNotRemembered", p, source);
|
CardCollectionView dPHand = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), "Card.IsNotRemembered", p, source);
|
||||||
|
if (dPHand.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
dPHand = GameActionUtil.orderCardsByTheirOwners(p.getGame(), dPHand, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (final Card c : dPHand) {
|
for (final Card c : dPHand) {
|
||||||
p.discard(c, sa);
|
p.discard(c, sa);
|
||||||
discarded.add(c);
|
discarded.add(c);
|
||||||
@ -190,15 +200,26 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card";
|
final String valid = sa.hasParam("DiscardValid") ? sa.getParam("DiscardValid") : "Card";
|
||||||
List<Card> list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), valid, source.getController(), source);
|
List<Card> list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), valid, source.getController(), source);
|
||||||
list = CardLists.filter(list, Presets.NON_TOKEN);
|
list = CardLists.filter(list, Presets.NON_TOKEN);
|
||||||
|
CardCollection toDiscard = new CardCollection();
|
||||||
for (int i = 0; i < numCards; i++) {
|
for (int i = 0; i < numCards; i++) {
|
||||||
if (list.isEmpty())
|
if (list.isEmpty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
final Card disc = Aggregates.random(list);
|
final Card disc = Aggregates.random(list);
|
||||||
if (p.discard(disc, sa) != null)
|
toDiscard.add(disc);
|
||||||
discarded.add(disc);
|
|
||||||
list.remove(disc);
|
list.remove(disc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CardCollectionView toDiscardView = toDiscard;
|
||||||
|
if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
toDiscardView = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Card c : toDiscardView) {
|
||||||
|
if (p.discard(c, sa) != null) {
|
||||||
|
discarded.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mode.equals("TgtChoose") && sa.hasParam("UnlessType")) {
|
else if (mode.equals("TgtChoose") && sa.hasParam("UnlessType")) {
|
||||||
@ -206,6 +227,11 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
CardCollectionView hand = p.getCardsIn(ZoneType.Hand);
|
CardCollectionView hand = p.getCardsIn(ZoneType.Hand);
|
||||||
hand = CardLists.filter(hand, Presets.NON_TOKEN);
|
hand = CardLists.filter(hand, Presets.NON_TOKEN);
|
||||||
CardCollectionView toDiscard = p.getController().chooseCardsToDiscardUnlessType(Math.min(numCards, numCardsInHand), hand, sa.getParam("UnlessType"), sa);
|
CardCollectionView toDiscard = p.getController().chooseCardsToDiscardUnlessType(Math.min(numCards, numCardsInHand), hand, sa.getParam("UnlessType"), sa);
|
||||||
|
|
||||||
|
if (toDiscard.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
toDiscard = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toDiscard, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (Card c : toDiscard) {
|
for (Card c : toDiscard) {
|
||||||
c.getController().discard(c, sa);
|
c.getController().discard(c, sa);
|
||||||
}
|
}
|
||||||
@ -226,8 +252,12 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
"X", Integer.toString(AbilityUtils.calculateAmount(source, "X", sa)));
|
"X", Integer.toString(AbilityUtils.calculateAmount(source, "X", sa)));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Card> dPChHand = CardLists.getValidCards(dPHand, valid.split(","), source.getController(), source, sa);
|
CardCollectionView dPChHand = CardLists.getValidCards(dPHand, valid.split(","), source.getController(), source, sa);
|
||||||
dPChHand = CardLists.filter(dPChHand, Presets.NON_TOKEN);
|
dPChHand = CardLists.filter(dPChHand, Presets.NON_TOKEN);
|
||||||
|
if (dPChHand.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
dPChHand = GameActionUtil.orderCardsByTheirOwners(p.getGame(), dPChHand, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
// Reveal cards that will be discarded?
|
// Reveal cards that will be discarded?
|
||||||
for (final Card c : dPChHand) {
|
for (final Card c : dPChHand) {
|
||||||
p.discard(c, sa);
|
p.discard(c, sa);
|
||||||
@ -263,6 +293,10 @@ public class DiscardEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
CardCollectionView toBeDiscarded = validCards.isEmpty() ? null : chooser.getController().chooseCardsToDiscardFrom(p, sa, validCards, min, max);
|
CardCollectionView toBeDiscarded = validCards.isEmpty() ? null : chooser.getController().chooseCardsToDiscardFrom(p, sa, validCards, min, max);
|
||||||
|
|
||||||
|
if (toBeDiscarded.size() > 1 && p.getGame().isGraveyardOrdered()) {
|
||||||
|
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(p.getGame(), toBeDiscarded, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
if (toBeDiscarded != null) {
|
if (toBeDiscarded != null) {
|
||||||
if (mode.startsWith("Reveal") ) {
|
if (mode.startsWith("Reveal") ) {
|
||||||
p.getController().reveal(toBeDiscarded, ZoneType.Hand, p,
|
p.getController().reveal(toBeDiscarded, ZoneType.Hand, p,
|
||||||
|
@ -38,7 +38,7 @@ public class ReorderZoneEffect extends SpellAbilityEffect {
|
|||||||
p.getZone(zone).setCards(list);
|
p.getZone(zone).setCards(list);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.getController().orderMoveToZoneList(list, zone);
|
p.getController().orderMoveToZoneList(list, zone, sa);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@ -62,6 +59,10 @@ public class SacrificeAllEffect extends SpellAbilityEffect {
|
|||||||
card.clearRemembered();
|
card.clearRemembered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (list.size() > 1 && game.isGraveyardOrdered()) {
|
||||||
|
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (Card sac : list) {
|
for (Card sac : list) {
|
||||||
final Card lKICopy = CardUtil.getLKICopy(sac);
|
final Card lKICopy = CardUtil.getLKICopy(sac);
|
||||||
if (game.getAction().sacrifice(sac, sa) != null && remSacrificed) {
|
if (game.getAction().sacrifice(sac, sa) != null && remSacrificed) {
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
package forge.game.ability.effects;
|
package forge.game.ability.effects;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameActionUtil;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerController.ManaPaymentPurpose;
|
import forge.game.player.PlayerController.ManaPaymentPurpose;
|
||||||
@ -18,14 +14,11 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
public class SacrificeEffect extends SpellAbilityEffect {
|
public class SacrificeEffect extends SpellAbilityEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -136,6 +129,10 @@ public class SacrificeEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (choosenToSacrifice.size() > 1 && game.isGraveyardOrdered()) {
|
||||||
|
choosenToSacrifice = GameActionUtil.orderCardsByTheirOwners(game, choosenToSacrifice, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
for (Card sac : choosenToSacrifice) {
|
for (Card sac : choosenToSacrifice) {
|
||||||
final Card lKICopy = CardUtil.getLKICopy(sac);
|
final Card lKICopy = CardUtil.getLKICopy(sac);
|
||||||
boolean wasSacrificed = !destroy && game.getAction().sacrifice(sac, sa) != null;
|
boolean wasSacrificed = !destroy && game.getAction().sacrifice(sac, sa) != null;
|
||||||
|
@ -17,60 +17,19 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
|
||||||
|
|
||||||
import forge.util.TextUtil;
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.game.Game;
|
import forge.game.*;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameLogEntryType;
|
|
||||||
import forge.game.GameStage;
|
|
||||||
import forge.game.GameType;
|
|
||||||
import forge.game.GlobalRuleChange;
|
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.ability.effects.DetachedCardEffect;
|
import forge.game.ability.effects.DetachedCardEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardDamageMap;
|
|
||||||
import forge.game.card.CardFactoryUtil;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardPredicates.Presets;
|
import forge.game.card.CardPredicates.Presets;
|
||||||
import forge.game.card.CardUtil;
|
import forge.game.event.*;
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.event.GameEventCardSacrificed;
|
|
||||||
import forge.game.event.GameEventLandPlayed;
|
|
||||||
import forge.game.event.GameEventMulligan;
|
|
||||||
import forge.game.event.GameEventPlayerControl;
|
|
||||||
import forge.game.event.GameEventPlayerCounters;
|
|
||||||
import forge.game.event.GameEventPlayerDamaged;
|
|
||||||
import forge.game.event.GameEventPlayerLivesChanged;
|
|
||||||
import forge.game.event.GameEventPlayerPoisoned;
|
|
||||||
import forge.game.event.GameEventPlayerStatsChanged;
|
|
||||||
import forge.game.event.GameEventScry;
|
|
||||||
import forge.game.event.GameEventShuffle;
|
|
||||||
import forge.game.keyword.KeywordCollection;
|
import forge.game.keyword.KeywordCollection;
|
||||||
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
||||||
import forge.game.keyword.KeywordsChange;
|
import forge.game.keyword.KeywordsChange;
|
||||||
@ -93,8 +52,14 @@ import forge.item.PaperCard;
|
|||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.TextUtil;
|
||||||
import forge.util.collect.FCollection;
|
import forge.util.collect.FCollection;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ConcurrentSkipListMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@ -1591,12 +1556,22 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
|
|
||||||
for (int i = 0; i < max; i++) {
|
for (int i = 0; i < max; i++) {
|
||||||
if (bottom) {
|
if (bottom) {
|
||||||
milled.add(game.getAction().moveTo(destination, lib.getLast(), null));
|
milled.add(lib.get(lib.size() - i - 1));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
milled.add(game.getAction().moveTo(destination, lib.getFirst(), null));
|
milled.add(lib.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CardCollectionView milledView = milled;
|
||||||
|
if (destination == ZoneType.Graveyard && milled.size() > 1 && game.isGraveyardOrdered()) {
|
||||||
|
milledView = GameActionUtil.orderCardsByTheirOwners(game, milled, ZoneType.Graveyard);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Card m : milledView) {
|
||||||
|
game.getAction().moveTo(destination, m, null);
|
||||||
|
}
|
||||||
|
|
||||||
return milled;
|
return milled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.ICardFace;
|
import forge.card.ICardFace;
|
||||||
@ -22,28 +14,25 @@ import forge.game.GameEntity;
|
|||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.GameOutcome.AnteResult;
|
import forge.game.GameOutcome.AnteResult;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardShields;
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostPart;
|
import forge.game.cost.CostPart;
|
||||||
import forge.game.cost.CostPartMana;
|
import forge.game.cost.CostPartMana;
|
||||||
import forge.game.mana.Mana;
|
import forge.game.mana.Mana;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.*;
|
||||||
import forge.game.spellability.OptionalCostValue;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
|
||||||
import forge.game.spellability.TargetChoices;
|
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.collect.FCollectionView;
|
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
|
import forge.util.collect.FCollectionView;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A prototype for player controller class
|
* A prototype for player controller class
|
||||||
@ -149,7 +138,10 @@ public abstract class PlayerController {
|
|||||||
public abstract void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value);
|
public abstract void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value);
|
||||||
public abstract ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN);
|
public abstract ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN);
|
||||||
public abstract boolean willPutCardOnTop(Card c);
|
public abstract boolean willPutCardOnTop(Card c);
|
||||||
public abstract CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone);
|
public final CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone) {
|
||||||
|
return orderMoveToZoneList(cards, destinationZone, null);
|
||||||
|
}
|
||||||
|
public abstract CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone, SpellAbility source);
|
||||||
|
|
||||||
/** p = target player, validCards - possible discards, min cards to discard */
|
/** p = target player, validCards - possible discards, min cards to discard */
|
||||||
public abstract CardCollectionView chooseCardsToDiscardFrom(Player playerDiscard, SpellAbility sa, CardCollection validCards, int min, int max);
|
public abstract CardCollectionView chooseCardsToDiscardFrom(Player playerDiscard, SpellAbility sa, CardCollection validCards, int min, int max);
|
||||||
|
@ -120,6 +120,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
|||||||
lstControls.add(Pair.of(view.getCbEscapeEndsTurn(), FPref.UI_ALLOW_ESC_TO_END_TURN));
|
lstControls.add(Pair.of(view.getCbEscapeEndsTurn(), FPref.UI_ALLOW_ESC_TO_END_TURN));
|
||||||
lstControls.add(Pair.of(view.getCbDetailedPaymentDesc(), FPref.UI_DETAILED_SPELLDESC_IN_PROMPT));
|
lstControls.add(Pair.of(view.getCbDetailedPaymentDesc(), FPref.UI_DETAILED_SPELLDESC_IN_PROMPT));
|
||||||
lstControls.add(Pair.of(view.getCbPreselectPrevAbOrder(), FPref.UI_PRESELECT_PREVIOUS_ABILITY_ORDER));
|
lstControls.add(Pair.of(view.getCbPreselectPrevAbOrder(), FPref.UI_PRESELECT_PREVIOUS_ABILITY_ORDER));
|
||||||
|
lstControls.add(Pair.of(view.getCbAllowOrderingGraveyard(), FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED));
|
||||||
lstControls.add(Pair.of(view.getCbShowStormCount(), FPref.UI_SHOW_STORM_COUNT_IN_PROMPT));
|
lstControls.add(Pair.of(view.getCbShowStormCount(), FPref.UI_SHOW_STORM_COUNT_IN_PROMPT));
|
||||||
|
|
||||||
lstControls.add(Pair.of(view.getCbFilterLandsByColorId(), FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY));
|
lstControls.add(Pair.of(view.getCbFilterLandsByColorId(), FPref.UI_FILTER_LANDS_BY_COLOR_IDENTITY));
|
||||||
|
@ -87,6 +87,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
private final JCheckBox cbCompactPrompt = new OptionsCheckBox("Compact Prompt");
|
private final JCheckBox cbCompactPrompt = new OptionsCheckBox("Compact Prompt");
|
||||||
private final JCheckBox cbEscapeEndsTurn = new OptionsCheckBox("Use Escape Key to End Turn");
|
private final JCheckBox cbEscapeEndsTurn = new OptionsCheckBox("Use Escape Key to End Turn");
|
||||||
private final JCheckBox cbPreselectPrevAbOrder = new OptionsCheckBox("Preselect Last Order of Abilities");
|
private final JCheckBox cbPreselectPrevAbOrder = new OptionsCheckBox("Preselect Last Order of Abilities");
|
||||||
|
private final JCheckBox cbAllowOrderingGraveyard = new OptionsCheckBox("Allow Ordering Graveyard if Needed");
|
||||||
private final JCheckBox cbHideReminderText = new OptionsCheckBox("Hide Reminder Text");
|
private final JCheckBox cbHideReminderText = new OptionsCheckBox("Hide Reminder Text");
|
||||||
private final JCheckBox cbOpenPacksIndiv = new OptionsCheckBox("Open Packs Individually");
|
private final JCheckBox cbOpenPacksIndiv = new OptionsCheckBox("Open Packs Individually");
|
||||||
private final JCheckBox cbTokensInSeparateRow = new OptionsCheckBox("Display Tokens in a Separate Row");
|
private final JCheckBox cbTokensInSeparateRow = new OptionsCheckBox("Display Tokens in a Separate Row");
|
||||||
@ -188,6 +189,9 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
pnlPrefs.add(cbPreselectPrevAbOrder, titleConstraints);
|
pnlPrefs.add(cbPreselectPrevAbOrder, titleConstraints);
|
||||||
pnlPrefs.add(new NoteLabel("When enabled, preselects the last defined simultaneous ability order in the ordering dialog."), descriptionConstraints);
|
pnlPrefs.add(new NoteLabel("When enabled, preselects the last defined simultaneous ability order in the ordering dialog."), descriptionConstraints);
|
||||||
|
|
||||||
|
pnlPrefs.add(cbAllowOrderingGraveyard, titleConstraints);
|
||||||
|
pnlPrefs.add(new NoteLabel("When enabled, allows to choose the order of cards going to graveyard when playing with cards for which it matters (for example, Volrath's Shapeshifter)."), descriptionConstraints);
|
||||||
|
|
||||||
pnlPrefs.add(cbpAutoYieldMode, comboBoxConstraints);
|
pnlPrefs.add(cbpAutoYieldMode, comboBoxConstraints);
|
||||||
pnlPrefs.add(new NoteLabel("Defines the granularity level of auto-yields (per unique ability or per unique card)."), descriptionConstraints);
|
pnlPrefs.add(new NoteLabel("Defines the granularity level of auto-yields (per unique ability or per unique card)."), descriptionConstraints);
|
||||||
|
|
||||||
@ -684,6 +688,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
return cbPreselectPrevAbOrder;
|
return cbPreselectPrevAbOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final JCheckBox getCbAllowOrderingGraveyard() {
|
||||||
|
return cbAllowOrderingGraveyard;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return {@link forge.toolbox.FLabel} */
|
/** @return {@link forge.toolbox.FLabel} */
|
||||||
public FLabel getBtnReset() {
|
public FLabel getBtnReset() {
|
||||||
return btnReset;
|
return btnReset;
|
||||||
|
@ -1,19 +1,9 @@
|
|||||||
package forge.gamesimulationtests.util;
|
package forge.gamesimulationtests.util;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
import org.testng.collections.Lists;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.ai.ComputerUtil;
|
import forge.ai.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
@ -33,12 +23,7 @@ import forge.game.GameEntity;
|
|||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardShields;
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
@ -46,34 +31,29 @@ import forge.game.cost.CostPart;
|
|||||||
import forge.game.cost.CostPartMana;
|
import forge.game.cost.CostPartMana;
|
||||||
import forge.game.mana.Mana;
|
import forge.game.mana.Mana;
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.player.DelayedReveal;
|
import forge.game.player.*;
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
|
||||||
import forge.game.player.PlayerController;
|
|
||||||
import forge.game.player.PlayerView;
|
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.*;
|
||||||
import forge.game.spellability.OptionalCostValue;
|
|
||||||
import forge.game.spellability.Spell;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
|
||||||
import forge.game.spellability.TargetChoices;
|
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gamesimulationtests.util.card.CardSpecification;
|
import forge.gamesimulationtests.util.card.CardSpecification;
|
||||||
import forge.gamesimulationtests.util.card.CardSpecificationHandler;
|
import forge.gamesimulationtests.util.card.CardSpecificationHandler;
|
||||||
import forge.gamesimulationtests.util.player.PlayerSpecification;
|
import forge.gamesimulationtests.util.player.PlayerSpecification;
|
||||||
import forge.gamesimulationtests.util.player.PlayerSpecificationHandler;
|
import forge.gamesimulationtests.util.player.PlayerSpecificationHandler;
|
||||||
import forge.gamesimulationtests.util.playeractions.ActivateAbilityAction;
|
import forge.gamesimulationtests.util.playeractions.*;
|
||||||
import forge.gamesimulationtests.util.playeractions.CastSpellFromHandAction;
|
|
||||||
import forge.gamesimulationtests.util.playeractions.DeclareAttackersAction;
|
|
||||||
import forge.gamesimulationtests.util.playeractions.DeclareBlockersAction;
|
|
||||||
import forge.gamesimulationtests.util.playeractions.PlayerActions;
|
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.player.HumanPlay;
|
import forge.player.HumanPlay;
|
||||||
import forge.util.collect.FCollectionView;
|
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.collect.FCollectionView;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.testng.collections.Lists;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default harmless implementation for tests.
|
* Default harmless implementation for tests.
|
||||||
@ -265,7 +245,7 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone) {
|
public CardCollectionView orderMoveToZoneList(CardCollectionView cards, ZoneType destinationZone, SpellAbility source) {
|
||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package forge.screens.settings;
|
package forge.screens.settings;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
|
import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment;
|
||||||
|
|
||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.Graphics;
|
import forge.Graphics;
|
||||||
import forge.ai.AiProfileUtil;
|
import forge.ai.AiProfileUtil;
|
||||||
@ -134,6 +133,10 @@ public class SettingsPage extends TabPage<SettingsScreen> {
|
|||||||
"Preselect Last Order of Abilities",
|
"Preselect Last Order of Abilities",
|
||||||
"When enabled, preselects the last defined simultaneous ability order in the ordering dialog."),
|
"When enabled, preselects the last defined simultaneous ability order in the ordering dialog."),
|
||||||
1);
|
1);
|
||||||
|
lstSettings.addItem(new BooleanSetting(FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED,
|
||||||
|
"Allow Ordering Graveyard if Needed",
|
||||||
|
"When enabled, allows to order cards going to graveyard when playing with cards for which it matters."),
|
||||||
|
1);
|
||||||
lstSettings.addItem(new CustomSelectSetting(FPref.UI_AUTO_YIELD_MODE,
|
lstSettings.addItem(new CustomSelectSetting(FPref.UI_AUTO_YIELD_MODE,
|
||||||
"Auto-Yield",
|
"Auto-Yield",
|
||||||
"Defines the granularity level of auto-yields (yield to each unique ability or to each unique card).",
|
"Defines the granularity level of auto-yields (yield to each unique ability or to each unique card).",
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
- Ixalan -
|
- Ixalan -
|
||||||
All 279 cards of the newly released Ixalan set are available in Forge. We've done our best to fix the issues that you reported with the cards in the pre-release version. If you still see anything wrong with the new cards, don't hesitate to report!
|
All 279 cards of the newly released Ixalan set are available in Forge. We've done our best to fix the issues that you reported with the cards in the pre-release version. If you still see anything wrong with the new cards, don't hesitate to report!
|
||||||
|
|
||||||
|
- Allow Ordering Graveyard if Needed (option) -
|
||||||
|
A new option is available in Forge that makes the game offer you to order the cards as they go into graveyard if, for example, several cards are destroyed, sacrificed or milled at the same time. When enabled, this option only takes effect in case there is at least one card in at least one player's library that cares about the order of cards in graveyard (currently the following cards are marked as caring about graveyard order: Nether Shadow, Spinning Darkness, Corpse Dance, Shallow Grave, Phyrexian Furnace, Krovikan Horror, Volrath's Shapeshifter, Ashen Ghoul, Phyrexian Grimoire, Nature's Kiss, Soldevi Digger, Guiding Spirit, Barrow Ghoul, Circling Vultures, Zombie Scavengers, Necratog, Mistmoon Griffin, Bone Dancer). Note that this option does not affect cards that reorder the graveyard as a part of their effect (Fossil Find). If this option is disabled, then no ordering is performed for cards like Volrath's Shapeshifter and the cards go into graveyards in whatever order the game automatically determines them to do so (this is the original Forge behavior). This mechanism is not perfect yet (please report cases in which you were not allowed to order cards in the graveyard, as well as any strange behavior in corner cases, e.g. when some permanents are indestructible, etc.). This option is disabled by default.
|
||||||
|
|
||||||
- Desktop Forge: Personal Card Ratings in Quest Mode -
|
- Desktop Forge: Personal Card Ratings in Quest Mode -
|
||||||
In Desktop Forge, it is now possible to assign personal ratings (from 1 star to 5 stars) to cards in Quest Mode by right clicking them and choosing the relevant context menu entry. It is then possible to filter cards by rating in both the deck editor and the quest shop, which should simplify managing bigger inventories. This patch was provided by Seravy.
|
In Desktop Forge, it is now possible to assign personal ratings (from 1 star to 5 stars) to cards in Quest Mode by right clicking them and choosing the relevant context menu entry. It is then possible to filter cards by rating in both the deck editor and the quest shop, which should simplify managing bigger inventories. This patch was provided by Seravy.
|
||||||
|
|
||||||
|
@ -4,5 +4,6 @@ Types:Creature Zombie
|
|||||||
PT:3/1
|
PT:3/1
|
||||||
K:Haste
|
K:Haste
|
||||||
A:AB$ ChangeZone | Cost$ B | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield | ActivationZone$ Graveyard | ActivationPhases$ Upkeep | PlayerTurn$ True | IsPresent$ Creature.YouOwn+Above | PresentZone$ Graveyard | PresentCompare$ GE3 | SpellDescription$ Return CARDNAME from your graveyard to the battlefield. Activate this ability only during your upkeep and only if three or more creature cards are above CARDNAME.
|
A:AB$ ChangeZone | Cost$ B | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield | ActivationZone$ Graveyard | ActivationPhases$ Upkeep | PlayerTurn$ True | IsPresent$ Creature.YouOwn+Above | PresentZone$ Graveyard | PresentCompare$ GE3 | SpellDescription$ Return CARDNAME from your graveyard to the battlefield. Activate this ability only during your upkeep and only if three or more creature cards are above CARDNAME.
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/ashen_ghoul.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/ashen_ghoul.jpg
|
||||||
Oracle:Haste\n{B}: Return Ashen Ghoul from your graveyard to the battlefield. Activate this ability only during your upkeep and only if three or more creature cards are above Ashen Ghoul.
|
Oracle:Haste\n{B}: Return Ashen Ghoul from your graveyard to the battlefield. Activate this ability only during your upkeep and only if three or more creature cards are above Ashen Ghoul.
|
||||||
|
@ -5,5 +5,6 @@ PT:4/4
|
|||||||
K:UpkeepCost:ExileFromGrave<1/Card.TopGraveyardCreature>
|
K:UpkeepCost:ExileFromGrave<1/Card.TopGraveyardCreature>
|
||||||
SVar:NeedsToPlayVar:Y GE2
|
SVar:NeedsToPlayVar:Y GE2
|
||||||
SVar:Y:Count$TypeInYourYard.Creature
|
SVar:Y:Count$TypeInYourYard.Creature
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/barrow_ghoul.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/barrow_ghoul.jpg
|
||||||
Oracle:At the beginning of your upkeep, sacrifice Barrow Ghoul unless you exile the top creature card of your graveyard.
|
Oracle:At the beginning of your upkeep, sacrifice Barrow Ghoul unless you exile the top creature card of your graveyard.
|
||||||
|
@ -5,5 +5,6 @@ PT:2/2
|
|||||||
T:Mode$ AttackerUnblocked | ValidCard$ Card.Self | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ DBChangeZone | TriggerDescription$ Whenever CARDNAME attacks and isn't blocked, you may put the top creature card of defending player's graveyard onto the battlefield under your control. If you do, CARDNAME assigns no combat damage this turn.
|
T:Mode$ AttackerUnblocked | ValidCard$ Card.Self | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ DBChangeZone | TriggerDescription$ Whenever CARDNAME attacks and isn't blocked, you may put the top creature card of defending player's graveyard onto the battlefield under your control. If you do, CARDNAME assigns no combat damage this turn.
|
||||||
SVar:DBChangeZone:DB$ChangeZoneAll | Cost$ 0 | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.TopGraveyardCreature+DefenderCtrl | GainControl$ True | ChangeNum$ 1 | SubAbility$ DBNoCombatDamage
|
SVar:DBChangeZone:DB$ChangeZoneAll | Cost$ 0 | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Creature.TopGraveyardCreature+DefenderCtrl | GainControl$ True | ChangeNum$ 1 | SubAbility$ DBNoCombatDamage
|
||||||
SVar:DBNoCombatDamage:DB$Pump | Defined$ Self | KW$ HIDDEN CARDNAME assigns no combat damage
|
SVar:DBNoCombatDamage:DB$Pump | Defined$ Self | KW$ HIDDEN CARDNAME assigns no combat damage
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/bone_dancer.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/bone_dancer.jpg
|
||||||
Oracle:Whenever Bone Dancer attacks and isn't blocked, you may put the top creature card of defending player's graveyard onto the battlefield under your control. If you do, Bone Dancer assigns no combat damage this turn.
|
Oracle:Whenever Bone Dancer attacks and isn't blocked, you may put the top creature card of defending player's graveyard onto the battlefield under your control. If you do, Bone Dancer assigns no combat damage this turn.
|
||||||
|
@ -6,5 +6,6 @@ K:Flying
|
|||||||
K:UpkeepCost:ExileFromGrave<1/Card.TopGraveyardCreature>
|
K:UpkeepCost:ExileFromGrave<1/Card.TopGraveyardCreature>
|
||||||
A:ST$ Discard | Cost$ 0 | Mode$ Defined | DefinedCards$ Self | Optional$ True | DiscardMessage$ Do you want discard this card? | ActivationZone$ Hand | InstantSpeed$ True | SpellDescription$ You may discard CARDNAME any time you could cast an instant.
|
A:ST$ Discard | Cost$ 0 | Mode$ Defined | DefinedCards$ Self | Optional$ True | DiscardMessage$ Do you want discard this card? | ActivationZone$ Hand | InstantSpeed$ True | SpellDescription$ You may discard CARDNAME any time you could cast an instant.
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/circling_vultures.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/circling_vultures.jpg
|
||||||
Oracle:Flying\nYou may discard Circling Vultures any time you could cast an instant.\nAt the beginning of your upkeep, sacrifice Circling Vultures unless you exile the top creature card of your graveyard.
|
Oracle:Flying\nYou may discard Circling Vultures any time you could cast an instant.\nAt the beginning of your upkeep, sacrifice Circling Vultures unless you exile the top creature card of your graveyard.
|
||||||
|
@ -6,5 +6,6 @@ A:SP$ ChangeZone | Cost$ 2 B | Origin$ Graveyard | Destination$ Battlefield | Ch
|
|||||||
SVar:DBPump:DB$ Animate | Keywords$ Haste | sVars$ SneakAttackEOT | Defined$ Remembered | AtEOT$ Exile | SubAbility$ DBCleanup
|
SVar:DBPump:DB$ Animate | Keywords$ Haste | sVars$ SneakAttackEOT | Defined$ Remembered | AtEOT$ Exile | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:SneakAttackEOT:SVar:EndOfTurnLeavePlay:True
|
SVar:SneakAttackEOT:SVar:EndOfTurnLeavePlay:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/corpse_dance.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/corpse_dance.jpg
|
||||||
Oracle:Buyback {2} (You may pay an additional {2} as you cast this spell. If you do, put this card into your hand as it resolves.)\nReturn the top creature card of your graveyard to the battlefield. That creature gains haste until end of turn. Exile it at the beginning of the next end step.
|
Oracle:Buyback {2} (You may pay an additional {2} as you cast this spell. If you do, put this card into your hand as it resolves.)\nReturn the top creature card of your graveyard to the battlefield. That creature gains haste until end of turn. Exile it at the beginning of the next end step.
|
||||||
|
@ -5,5 +5,6 @@ PT:1/2
|
|||||||
K:Flying
|
K:Flying
|
||||||
A:AB$ ChangeZoneAll | Cost$ T | ValidTgts$ Player | TgtPrompt$ Select target player | Origin$ Graveyard | Destination$ Library | ChangeType$ Card.TopGraveyardCreature | SpellDescription$ If the top card of target player's graveyard is a creature card, put that card on top of that player's library.
|
A:AB$ ChangeZoneAll | Cost$ T | ValidTgts$ Player | TgtPrompt$ Select target player | Origin$ Graveyard | Destination$ Library | ChangeType$ Card.TopGraveyardCreature | SpellDescription$ If the top card of target player's graveyard is a creature card, put that card on top of that player's library.
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/guiding_spirit.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/guiding_spirit.jpg
|
||||||
Oracle:Flying\n{T}: If the top card of target player's graveyard is a creature card, put that card on top of that player's library.
|
Oracle:Flying\n{T}: If the top card of target player's graveyard is a creature card, put that card on top of that player's library.
|
||||||
|
@ -7,5 +7,6 @@ SVar:TrigReturn:AB$ChangeZone | Cost$ 0 | Defined$ Self | Origin$ Graveyard | De
|
|||||||
A:AB$ DealDamage | Cost$ 1 Sac<1/Creature> | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to target creature or player.
|
A:AB$ DealDamage | Cost$ 1 Sac<1/Creature> | ValidTgts$ Creature,Player | TgtPrompt$ Select target creature or player | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to target creature or player.
|
||||||
SVar:DiscardMe:3
|
SVar:DiscardMe:3
|
||||||
SVar:SacMe:1
|
SVar:SacMe:1
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/krovikan_horror.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/krovikan_horror.jpg
|
||||||
Oracle:At the beginning of the end step, if Krovikan Horror is in your graveyard with a creature card directly above it, you may return Krovikan Horror to your hand.\n{1}, Sacrifice a creature: Krovikan Horror deals 1 damage to target creature or player.
|
Oracle:At the beginning of the end step, if Krovikan Horror is in your graveyard with a creature card directly above it, you may return Krovikan Horror to your hand.\n{1}, Sacrifice a creature: Krovikan Horror deals 1 damage to target creature or player.
|
||||||
|
@ -6,5 +6,6 @@ K:Flying
|
|||||||
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExileMe | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, exile CARDNAME, then return the top creature card of your graveyard to the battlefield.
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigExileMe | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, exile CARDNAME, then return the top creature card of your graveyard to the battlefield.
|
||||||
SVar:TrigExileMe:AB$ ChangeZone | Cost$ 0 | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBReturnCreature
|
SVar:TrigExileMe:AB$ ChangeZone | Cost$ 0 | Defined$ TriggeredCard | Origin$ Graveyard | Destination$ Exile | SubAbility$ DBReturnCreature
|
||||||
SVar:DBReturnCreature:DB$ ChangeZoneAll | ChangeType$ Creature.YouOwn+TopGraveyardCreature | Origin$ Graveyard | Destination$ Battlefield
|
SVar:DBReturnCreature:DB$ ChangeZoneAll | ChangeType$ Creature.YouOwn+TopGraveyardCreature | Origin$ Graveyard | Destination$ Battlefield
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/mistmoon_griffin.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/mistmoon_griffin.jpg
|
||||||
Oracle:Flying\nWhen Mistmoon Griffin dies, exile Mistmoon Griffin, then return the top creature card of your graveyard to the battlefield.
|
Oracle:Flying\nWhen Mistmoon Griffin dies, exile Mistmoon Griffin, then return the top creature card of your graveyard to the battlefield.
|
||||||
|
@ -6,5 +6,6 @@ A:SP$ Attach | Cost$ 1 G | ValidTgts$ Creature | AILogic$ Pump
|
|||||||
A:AB$ Pump | Cost$ 1 ExileFromGrave<1/Card.TopGraveyard> | Defined$ Enchanted | NumAtt$ +1 | NumDef$ +1 | CostDesc$ {1}, Exile the top card of your graveyard: | SpellDescription$ Enchanted creature gets +1/+1 until end of turn.
|
A:AB$ Pump | Cost$ 1 ExileFromGrave<1/Card.TopGraveyard> | Defined$ Enchanted | NumAtt$ +1 | NumDef$ +1 | CostDesc$ {1}, Exile the top card of your graveyard: | SpellDescription$ Enchanted creature gets +1/+1 until end of turn.
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
SVar:NonStackingAttachEffect:True
|
SVar:NonStackingAttachEffect:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/natures_kiss.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/natures_kiss.jpg
|
||||||
Oracle:Enchant creature\n{1}, Exile the top card of your graveyard: Enchanted creature gets +1/+1 until end of turn.
|
Oracle:Enchant creature\n{1}, Exile the top card of your graveyard: Enchanted creature gets +1/+1 until end of turn.
|
||||||
|
@ -3,5 +3,6 @@ ManaCost:1 B B
|
|||||||
Types:Creature Atog
|
Types:Creature Atog
|
||||||
PT:1/2
|
PT:1/2
|
||||||
A:AB$ Pump | Cost$ ExileFromGrave<1/Card.TopGraveyardCreature> | CostDesc$ Exile the top creature card of your graveyard: | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ CARDNAME gets +2/+2 until end of turn.
|
A:AB$ Pump | Cost$ ExileFromGrave<1/Card.TopGraveyardCreature> | CostDesc$ Exile the top creature card of your graveyard: | NumAtt$ +2 | NumDef$ +2 | SpellDescription$ CARDNAME gets +2/+2 until end of turn.
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/necratog.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/necratog.jpg
|
||||||
Oracle:Exile the top creature card of your graveyard: Necratog gets +2/+2 until end of turn.
|
Oracle:Exile the top creature card of your graveyard: Necratog gets +2/+2 until end of turn.
|
||||||
|
@ -6,5 +6,6 @@ K:Haste
|
|||||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Graveyard | IsPresent$ Creature.YouOwn+Above | PresentZone$ Graveyard | PresentCompare$ GE3 | Execute$ TrigReturn | OptionalDecider$ You | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is in your graveyard with three or more creature cards above it, you may put CARDNAME onto the battlefield.
|
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Graveyard | IsPresent$ Creature.YouOwn+Above | PresentZone$ Graveyard | PresentCompare$ GE3 | Execute$ TrigReturn | OptionalDecider$ You | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is in your graveyard with three or more creature cards above it, you may put CARDNAME onto the battlefield.
|
||||||
SVar:TrigReturn:AB$ChangeZone | Cost$ 0 | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield
|
SVar:TrigReturn:AB$ChangeZone | Cost$ 0 | Defined$ Self | Origin$ Graveyard | Destination$ Battlefield
|
||||||
SVar:DiscardMe:2
|
SVar:DiscardMe:2
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/nether_shadow.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/nether_shadow.jpg
|
||||||
Oracle:Haste\nAt the beginning of your upkeep, if Nether Shadow is in your graveyard with three or more creature cards above it, you may put Nether Shadow onto the battlefield.
|
Oracle:Haste\nAt the beginning of your upkeep, if Nether Shadow is in your graveyard with three or more creature cards above it, you may put Nether Shadow onto the battlefield.
|
||||||
|
@ -5,5 +5,6 @@ A:AB$ ChangeZoneAll | Cost$ T | ValidTgts$ Player | TgtPrompt$ Select target pla
|
|||||||
A:AB$ ChangeZone | Cost$ 1 Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Exile | TgtPrompt$ Choose target card in a graveyard | ValidTgts$ Card | SubAbility$ DBDraw | SpellDescription$ Exile target card from a graveyard. Draw a card.
|
A:AB$ ChangeZone | Cost$ 1 Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Exile | TgtPrompt$ Choose target card in a graveyard | ValidTgts$ Card | SubAbility$ DBDraw | SpellDescription$ Exile target card from a graveyard. Draw a card.
|
||||||
SVar:DBDraw:DB$Draw | NumCards$ 1
|
SVar:DBDraw:DB$Draw | NumCards$ 1
|
||||||
SVar:RemRandomDeck:True
|
SVar:RemRandomDeck:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/phyrexian_furnace.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/phyrexian_furnace.jpg
|
||||||
Oracle:{T}: Exile the bottom card of target player's graveyard.\n{1}, Sacrifice Phyrexian Furnace: Exile target card from a graveyard. Draw a card.
|
Oracle:{T}: Exile the bottom card of target player's graveyard.\n{1}, Sacrifice Phyrexian Furnace: Exile target card from a graveyard. Draw a card.
|
||||||
|
@ -7,5 +7,6 @@ SVar:DBExile:DB$ ChangeZone | Defined$ ChosenCard | Origin$ Graveyard | Destinat
|
|||||||
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Graveyard | Destination$ Hand | SubAbility$ DBCleanup
|
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Graveyard | Destination$ Hand | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/phyrexian_grimoire.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/phyrexian_grimoire.jpg
|
||||||
Oracle:{4}, {T}: Target opponent chooses one of the top two cards of your graveyard. Exile that card and put the other one into your hand.
|
Oracle:{4}, {T}: Target opponent chooses one of the top two cards of your graveyard. Exile that card and put the other one into your hand.
|
||||||
|
@ -5,5 +5,6 @@ A:SP$ ChangeZone | Cost$ 1 B | Origin$ Graveyard | Destination$ Battlefield | Ch
|
|||||||
SVar:DBPump:DB$ Animate | Keywords$ Haste | sVars$ SneakAttackEOT | Defined$ Remembered | AtEOT$ Exile | SubAbility$ DBCleanup
|
SVar:DBPump:DB$ Animate | Keywords$ Haste | sVars$ SneakAttackEOT | Defined$ Remembered | AtEOT$ Exile | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
SVar:SneakAttackEOT:SVar:EndOfTurnLeavePlay:True
|
SVar:SneakAttackEOT:SVar:EndOfTurnLeavePlay:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/shallow_grave.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/shallow_grave.jpg
|
||||||
Oracle:Return the top creature card of your graveyard to the battlefield. That creature gains haste until end of turn. Exile it at the beginning of the next end step.
|
Oracle:Return the top creature card of your graveyard to the battlefield. That creature gains haste until end of turn. Exile it at the beginning of the next end step.
|
||||||
|
@ -3,5 +3,6 @@ ManaCost:2
|
|||||||
Types:Artifact
|
Types:Artifact
|
||||||
A:AB$ ChangeZone | Cost$ 2 | Origin$ Graveyard | Destination$ Library | LibraryPosition$ -1 | Hidden$ True | Mandatory$ True | ChangeType$ Card.TopGraveyard+YouOwn | SpellDescription$ Put the top card of your graveyard on the bottom of your library. | StackDescription$ Put the top card of your graveyard on the bottom of your library.
|
A:AB$ ChangeZone | Cost$ 2 | Origin$ Graveyard | Destination$ Library | LibraryPosition$ -1 | Hidden$ True | Mandatory$ True | ChangeType$ Card.TopGraveyard+YouOwn | SpellDescription$ Put the top card of your graveyard on the bottom of your library. | StackDescription$ Put the top card of your graveyard on the bottom of your library.
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/soldevi_digger.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/soldevi_digger.jpg
|
||||||
Oracle:{2}: Put the top card of your graveyard on the bottom of your library.
|
Oracle:{2}: Put the top card of your graveyard on the bottom of your library.
|
||||||
|
@ -5,5 +5,6 @@ SVar:AltCost:Cost$ ExileFromGrave<3/Card.Black+FromTopGrave> | Description$ You
|
|||||||
A:SP$ DealDamage | Cost$ 4 B B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to target nonblack creature. You gain 3 life.
|
A:SP$ DealDamage | Cost$ 4 B B | ValidTgts$ Creature.nonBlack | TgtPrompt$ Select target nonblack creature | NumDmg$ 3 | SubAbility$ DBGainLife | SpellDescription$ CARDNAME deals 3 damage to target nonblack creature. You gain 3 life.
|
||||||
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 3
|
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 3
|
||||||
SVar:RemAIDeck:True
|
SVar:RemAIDeck:True
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/spinning_darkness.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/spinning_darkness.jpg
|
||||||
Oracle:You may exile the top three black cards of your graveyard rather than pay Spinning Darkness's mana cost.\nSpinning Darkness deals 3 damage to target nonblack creature. You gain 3 life.
|
Oracle:You may exile the top three black cards of your graveyard rather than pay Spinning Darkness's mana cost.\nSpinning Darkness deals 3 damage to target nonblack creature. You gain 3 life.
|
||||||
|
@ -4,5 +4,6 @@ Types:Creature Shapeshifter
|
|||||||
PT:0/1
|
PT:0/1
|
||||||
A:AB$ Discard | Cost$ 2 | Defined$ You | NumCards$ 1 | Mode$ TgtChoose | AILogic$ VolrathsShapeshifter | SpellDescription$ Discard a card.
|
A:AB$ Discard | Cost$ 2 | Defined$ You | NumCards$ 1 | Mode$ TgtChoose | AILogic$ VolrathsShapeshifter | SpellDescription$ Discard a card.
|
||||||
S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ Battlefield | GainTextOf$ Creature.TopGraveyard+YouCtrl | GainedTextHasThisStaticAbility$ True | Description$ ORIGINALTEXTONLY:As long as the top card of your graveyard is a creature card, CARDNAME has the full text of that card and has the text "{2}: Discard a card." (CARDNAME has that card's name, mana cost, color, types, abilities, power, and toughness.)
|
S:Mode$ Continuous | Affected$ Card.Self | EffectZone$ Battlefield | GainTextOf$ Creature.TopGraveyard+YouCtrl | GainedTextHasThisStaticAbility$ True | Description$ ORIGINALTEXTONLY:As long as the top card of your graveyard is a creature card, CARDNAME has the full text of that card and has the text "{2}: Discard a card." (CARDNAME has that card's name, mana cost, color, types, abilities, power, and toughness.)
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/volraths_shapeshifter.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/volraths_shapeshifter.jpg
|
||||||
Oracle:As long as the top card of your graveyard is a creature card, Volrath's Shapeshifter has the full text of that card and has the text "{2}: Discard a card." (Volrath's Shapeshifter has that card's name, mana cost, color, types, abilities, power, and toughness.)
|
Oracle:As long as the top card of your graveyard is a creature card, Volrath's Shapeshifter has the full text of that card and has the text "{2}: Discard a card." (Volrath's Shapeshifter has that card's name, mana cost, color, types, abilities, power, and toughness.)
|
@ -3,5 +3,6 @@ ManaCost:2 B
|
|||||||
Types:Creature Zombie
|
Types:Creature Zombie
|
||||||
PT:3/1
|
PT:3/1
|
||||||
A:AB$ Regenerate | Cost$ ExileFromGrave<1/Card.TopGraveyardCreature> | CostDesc$ Exile the top creature card of your graveyard: | SpellDescription$ Regenerate CARDNAME.
|
A:AB$ Regenerate | Cost$ ExileFromGrave<1/Card.TopGraveyardCreature> | CostDesc$ Exile the top creature card of your graveyard: | SpellDescription$ Regenerate CARDNAME.
|
||||||
|
SVar:NeedsOrderedGraveyard:TRUE
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/zombie_scavengers.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/zombie_scavengers.jpg
|
||||||
Oracle:Exile the top creature card of your graveyard: Regenerate Zombie Scavengers.
|
Oracle:Exile the top creature card of your graveyard: Regenerate Zombie Scavengers.
|
||||||
|
@ -687,7 +687,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CardCollectionView orderMoveToZoneList(final CardCollectionView cards, final ZoneType destinationZone) {
|
public CardCollectionView orderMoveToZoneList(final CardCollectionView cards, final ZoneType destinationZone, final SpellAbility source) {
|
||||||
|
if (source == null || source.getApi() != ApiType.ReorderZone) {
|
||||||
|
if (destinationZone == ZoneType.Graveyard
|
||||||
|
&& !FModel.getPreferences().getPrefBoolean(FPref.UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED) || !game.isGraveyardOrdered()) {
|
||||||
|
// Ordering not necessary
|
||||||
|
return cards;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<CardView> choices;
|
List<CardView> choices;
|
||||||
tempShowCards(cards);
|
tempShowCards(cards);
|
||||||
switch (destinationZone) {
|
switch (destinationZone) {
|
||||||
|
@ -97,6 +97,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
|||||||
UI_ROTATE_PLANE_OR_PHENOMENON("false"),
|
UI_ROTATE_PLANE_OR_PHENOMENON("false"),
|
||||||
UI_DYNAMIC_PLANECHASE_BG("false"),
|
UI_DYNAMIC_PLANECHASE_BG("false"),
|
||||||
UI_DISABLE_IMAGES_EFFECT_CARDS("false"),
|
UI_DISABLE_IMAGES_EFFECT_CARDS("false"),
|
||||||
|
UI_ALLOW_ORDER_GRAVEYARD_WHEN_NEEDED ("false"),
|
||||||
|
|
||||||
UI_FOR_TOUCHSCREN("false"),
|
UI_FOR_TOUCHSCREN("false"),
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user