SacrificeAllEffect: check timestamp for LKI objects

This commit is contained in:
Hans Mackowiak
2021-03-13 10:39:59 +01:00
parent a2e27f40c9
commit 174836a57f
43 changed files with 146 additions and 150 deletions

View File

@@ -88,7 +88,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
}
else if (type.equals("Hand")) {
if (hand.size() > 1 && ability.getActivatingPlayer() != null) {
hand = ability.getActivatingPlayer().getController().orderMoveToZoneList(hand, ZoneType.Graveyard);
hand = ability.getActivatingPlayer().getController().orderMoveToZoneList(hand, ZoneType.Graveyard, ability);
}
return PaymentDecision.card(hand);
}
@@ -104,7 +104,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
if (type.equals("Random")) {
CardCollectionView randomSubset = CardLists.getRandomSubList(new CardCollection(hand), c);
if (randomSubset.size() > 1 && ability.getActivatingPlayer() != null) {
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard);
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard, ability);
}
return PaymentDecision.card(randomSubset);
}

View File

@@ -316,9 +316,9 @@ public class GameAction {
cards.set(cards.indexOf(c), copied);
// 721.3b
if (cause != null && zoneTo.getZoneType() == ZoneType.Exile) {
cards = (CardCollection) cause.getHostCard().getController().getController().orderMoveToZoneList(cards, zoneTo.getZoneType());
cards = (CardCollection) cause.getHostCard().getController().getController().orderMoveToZoneList(cards, zoneTo.getZoneType(), cause);
} else {
cards = (CardCollection) c.getOwner().getController().orderMoveToZoneList(cards, zoneTo.getZoneType());
cards = (CardCollection) c.getOwner().getController().orderMoveToZoneList(cards, zoneTo.getZoneType(), cause);
}
cards.set(cards.indexOf(copied), c);
if (zoneTo.is(ZoneType.Library)) {
@@ -1169,7 +1169,7 @@ public class GameAction {
if (noRegCreats != null) {
if (noRegCreats.size() > 1 && !orderedNoRegCreats) {
noRegCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, noRegCreats, ZoneType.Graveyard);
noRegCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, noRegCreats, ZoneType.Graveyard, null);
orderedNoRegCreats = true;
}
for (Card c : noRegCreats) {
@@ -1180,7 +1180,7 @@ public class GameAction {
if (desCreats.size() > 1 && !orderedDesCreats) {
desCreats = CardLists.filter(desCreats, CardPredicates.Presets.CAN_BE_DESTROYED);
if (!desCreats.isEmpty()) {
desCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, desCreats, ZoneType.Graveyard);
desCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, desCreats, ZoneType.Graveyard, null);
}
orderedDesCreats = true;
}

View File

@@ -625,7 +625,7 @@ public final class GameActionUtil {
return sb.toString();
}
public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollectionView list, ZoneType dest) {
public static CardCollectionView orderCardsByTheirOwners(Game game, CardCollectionView list, ZoneType dest, SpellAbility sa) {
CardCollection completeList = new CardCollection();
for (Player p : game.getPlayers()) {
CardCollection subList = new CardCollection();
@@ -636,7 +636,7 @@ public final class GameActionUtil {
}
CardCollectionView subListView = subList;
if (subList.size() > 1) {
subListView = p.getController().orderMoveToZoneList(subList, dest);
subListView = p.getController().orderMoveToZoneList(subList, dest, sa);
}
completeList.addAll(subListView);
}

View File

@@ -238,7 +238,7 @@ public abstract class SpellAbilityEffect {
}
protected static void registerDelayedTrigger(final SpellAbility sa, String location, final List<Card> crds) {
protected static void registerDelayedTrigger(final SpellAbility sa, String location, final Iterable<Card> crds) {
boolean intrinsic = sa.isIntrinsic();
boolean your = location.startsWith("Your");
boolean combat = location.endsWith("Combat");
@@ -298,9 +298,9 @@ public abstract class SpellAbilityEffect {
if (location.equals("Hand")) {
trigSA = "DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Battlefield | Destination$ Hand";
} else if (location.equals("SacrificeCtrl")) {
trigSA = "DB$ SacrificeAll | Defined$ DelayTriggerRemembered";
trigSA = "DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI";
} else if (location.equals("Sacrifice")) {
trigSA = "DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You";
trigSA = "DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI | Controller$ You";
} else if (location.equals("Exile")) {
trigSA = "DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Battlefield | Destination$ Exile";
} else if (location.equals("Destroy")) {

View File

@@ -126,14 +126,14 @@ public class ChangeZoneAllEffect extends SpellAbilityEffect {
if ((destination == ZoneType.Library || destination == ZoneType.PlanarDeck)
&& !sa.hasParam("Shuffle") && cards.size() >= 2 && !random) {
Player p = AbilityUtils.getDefinedPlayers(source, sa.getParamOrDefault("DefinedPlayer", "You"), sa).get(0);
cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination);
cards = (CardCollection) p.getController().orderMoveToZoneList(cards, destination, sa);
//the last card in this list will be the closest to the top, but we want the first card to be closest.
//so reverse it here before moving them to the library.
java.util.Collections.reverse(cards);
}
if (destination == ZoneType.Graveyard) {
cards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, cards, ZoneType.Graveyard);
cards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, cards, ZoneType.Graveyard, sa);
}
if (destination.equals(ZoneType.Library) && random) {

View File

@@ -797,6 +797,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
triggerList.triggerChangesZoneAll(game);
counterTable.triggerCountersPutAll(game);
if (sa.hasParam("AtEOT") && !triggerList.isEmpty()) {
registerDelayedTrigger(sa, sa.getParam("AtEOT"), triggerList.allCards());
}
// for things like Gaea's Blessing
if (destination.equals(ZoneType.Library) && sa.hasParam("Shuffle") && "True".equals(sa.getParam("Shuffle"))) {
PlayerCollection pl = new PlayerCollection();
@@ -1374,6 +1378,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
player.shuffle(sa);
}
if (sa.hasParam("AtEOT") && !movedCards.isEmpty()) {
registerDelayedTrigger(sa, sa.getParam("AtEOT"), movedCards);
}
if (combatChanged) {
game.updateCombatForView();
game.fireEvent(new GameEventCombatChanged());

View File

@@ -86,7 +86,7 @@ public class DestroyAllEffect extends SpellAbilityEffect {
list = CardLists.filter(list, CardPredicates.Presets.CAN_BE_DESTROYED);
if (list.size() > 1) {
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard);
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
}
CardZoneTable table = new CardZoneTable();

View File

@@ -76,7 +76,7 @@ public class DestroyEffect extends SpellAbilityEffect {
CardCollection untargetedCards = CardUtil.getRadiance(sa);
if (tgtCards.size() > 1) {
tgtCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard);
tgtCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, tgtCards, ZoneType.Graveyard, sa);
}
CardZoneTable table = new CardZoneTable();
@@ -95,7 +95,7 @@ public class DestroyEffect extends SpellAbilityEffect {
}
if (untargetedCards.size() > 1) {
untargetedCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, untargetedCards, ZoneType.Graveyard);
untargetedCards = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, untargetedCards, ZoneType.Graveyard, sa);
}
for (final Card unTgtC : untargetedCards) {

View File

@@ -353,9 +353,9 @@ public class DigEffect extends SpellAbilityEffect {
CardLists.shuffle(afterOrder);
} else if (!skipReorder && rest.size() > 1) {
if (destZone2 == ZoneType.Graveyard) {
afterOrder = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, rest, destZone2);
afterOrder = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, rest, destZone2, sa);
} else {
afterOrder = (CardCollection) chooser.getController().orderMoveToZoneList(rest, destZone2);
afterOrder = (CardCollection) chooser.getController().orderMoveToZoneList(rest, destZone2, sa);
}
}
if (libraryPosition2 != -1) {

View File

@@ -162,7 +162,7 @@ public class DigUntilEffect extends SpellAbilityEffect {
if (foundDest != null) {
// Allow ordering of found cards
if ((foundDest.isKnown()) && found.size() >= 2 && !foundDest.equals(ZoneType.Exile)) {
found = (CardCollection)p.getController().orderMoveToZoneList(found, foundDest);
found = (CardCollection)p.getController().orderMoveToZoneList(found, foundDest, sa);
}
final Iterator<Card> itr = found.iterator();
@@ -213,11 +213,11 @@ public class DigUntilEffect extends SpellAbilityEffect {
if (sa.hasParam("NoneFoundDestination") && found.size() < untilAmount) {
// Allow ordering the revealed cards
if ((noneFoundDest.isKnown()) && revealed.size() >= 2) {
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, noneFoundDest);
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, noneFoundDest, sa);
}
if (noneFoundDest == ZoneType.Library && !shuffle
&& !sa.hasParam("RevealRandomOrder") && revealed.size() >= 2) {
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, noneFoundDest);
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, noneFoundDest, sa);
}
final Iterator<Card> itr = revealed.iterator();
@@ -232,11 +232,11 @@ public class DigUntilEffect extends SpellAbilityEffect {
} else {
// Allow ordering the rest of the revealed cards
if ((revealedDest.isKnown()) && revealed.size() >= 2) {
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, revealedDest);
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, revealedDest, sa);
}
if (revealedDest == ZoneType.Library && !shuffle
&& !sa.hasParam("RevealRandomOrder") && revealed.size() >= 2) {
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, revealedDest);
revealed = (CardCollection)p.getController().orderMoveToZoneList(revealed, revealedDest, sa);
}
final Iterator<Card> itr = revealed.iterator();

View File

@@ -145,7 +145,7 @@ public class DiscardEffect extends SpellAbilityEffect {
CardCollectionView toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
if (toDiscard.size() > 1) {
toDiscard = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard);
toDiscard = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard, sa);
}
for (final Card c : toDiscard) {
@@ -164,7 +164,7 @@ public class DiscardEffect extends SpellAbilityEffect {
CardCollectionView toDiscard = p.getCardsIn(ZoneType.Hand);
if (toDiscard.size() > 1) {
toDiscard = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard);
toDiscard = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard, sa);
}
for(Card c : Lists.newArrayList(toDiscard)) { // without copying will get concurrent modification exception
@@ -181,7 +181,7 @@ public class DiscardEffect extends SpellAbilityEffect {
}
CardCollectionView dPHand = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), "Card.IsNotRemembered", p, source);
if (dPHand.size() > 1) {
dPHand = GameActionUtil.orderCardsByTheirOwners(game, dPHand, ZoneType.Graveyard);
dPHand = GameActionUtil.orderCardsByTheirOwners(game, dPHand, ZoneType.Graveyard, sa);
}
for (final Card c : dPHand) {
@@ -221,7 +221,7 @@ public class DiscardEffect extends SpellAbilityEffect {
CardCollectionView toDiscardView = toDiscard;
if (toDiscard.size() > 1) {
toDiscardView = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard);
toDiscardView = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard, sa);
}
for (Card c : toDiscardView) {
@@ -242,7 +242,7 @@ public class DiscardEffect extends SpellAbilityEffect {
CardCollectionView toDiscard = p.getController().chooseCardsToDiscardUnlessType(Math.min(numCards, numCardsInHand), hand, sa.getParam("UnlessType"), sa);
if (toDiscard.size() > 1) {
toDiscard = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard);
toDiscard = GameActionUtil.orderCardsByTheirOwners(game, toDiscard, ZoneType.Graveyard, sa);
}
for (Card c : toDiscard) {
@@ -275,7 +275,7 @@ public class DiscardEffect extends SpellAbilityEffect {
CardCollectionView dPChHand = CardLists.getValidCards(dPHand, valid.split(","), source.getController(), source, sa);
dPChHand = CardLists.filter(dPChHand, Presets.NON_TOKEN);
if (dPChHand.size() > 1) {
dPChHand = GameActionUtil.orderCardsByTheirOwners(game, dPChHand, ZoneType.Graveyard);
dPChHand = GameActionUtil.orderCardsByTheirOwners(game, dPChHand, ZoneType.Graveyard, sa);
}
// Reveal cards that will be discarded?
@@ -322,7 +322,7 @@ public class DiscardEffect extends SpellAbilityEffect {
if (toBeDiscarded != null) {
if (toBeDiscarded.size() > 1) {
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard);
toBeDiscarded = GameActionUtil.orderCardsByTheirOwners(game, toBeDiscarded, ZoneType.Graveyard, sa);
}
if (mode.startsWith("Reveal") ) {

View File

@@ -5,10 +5,10 @@ import forge.game.Game;
import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardCollectionView;
import forge.game.card.CardFactoryUtil;
import forge.game.event.GameEventCardStatsChanged;
import forge.game.player.Player;
import forge.game.player.PlayerCollection;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.TextUtil;
@@ -16,11 +16,12 @@ import forge.util.TextUtil;
import java.util.Arrays;
import java.util.List;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
public class PumpAllEffect extends SpellAbilityEffect {
private static void applyPumpAll(final SpellAbility sa,
final List<Card> list, final int a, final int d,
final Iterable<Card> list, final int a, final int d,
final List<String> keywords, final List<ZoneType> affectedZones) {
final Game game = sa.getActivatingPlayer().getGame();
@@ -109,6 +110,10 @@ public class PumpAllEffect extends SpellAbilityEffect {
game.fireEvent(new GameEventCardStatsChanged(tgtC));
}
if (sa.hasParam("AtEOT") && !Iterables.isEmpty(list)) {
registerDelayedTrigger(sa, sa.getParam("AtEOT"), list);
}
}
@Override
@@ -127,7 +132,7 @@ public class PumpAllEffect extends SpellAbilityEffect {
@Override
public void resolve(final SpellAbility sa) {
final List<Player> tgtPlayers = getTargetPlayers(sa);
final PlayerCollection tgtPlayers = getTargetPlayers(sa);
final List<ZoneType> affectedZones = Lists.newArrayList();
final Game game = sa.getActivatingPlayer().getGame();
@@ -137,17 +142,11 @@ public class PumpAllEffect extends SpellAbilityEffect {
affectedZones.add(ZoneType.Battlefield);
}
CardCollection list = new CardCollection();
CardCollectionView list;
if (!sa.usesTargeting() && !sa.hasParam("Defined")) {
for (final ZoneType zone : affectedZones) {
list.addAll(game.getCardsIn(zone));
}
list = game.getCardsIn(affectedZones);
} else {
for (final ZoneType zone : affectedZones) {
for (final Player p : tgtPlayers) {
list.addAll(p.getCardsIn(zone));
}
}
list = tgtPlayers.getCardsIn(affectedZones);
}
String valid = "";
@@ -155,7 +154,7 @@ public class PumpAllEffect extends SpellAbilityEffect {
valid = sa.getParam("ValidCards");
}
list = (CardCollection)AbilityUtils.filterListByType(list, valid, sa);
list = AbilityUtils.filterListByType(list, valid, sa);
List<String> keywords = Lists.newArrayList();
if (sa.hasParam("KW")) {
@@ -174,6 +173,6 @@ public class PumpAllEffect extends SpellAbilityEffect {
applyPumpAll(sa, list, a, d, keywords, affectedZones);
replaceDying(sa);
} // pumpAllResolve()
}
}

View File

@@ -112,7 +112,7 @@ public class RearrangeTopOfLibraryEffect extends SpellAbilityEffect {
CardCollection topCards = player.getTopXCardsFromLibrary(numCards);
int maxCards = topCards.size();
CardCollectionView orderedCards = activator.getController().orderMoveToZoneList(topCards, ZoneType.Library);
CardCollectionView orderedCards = activator.getController().orderMoveToZoneList(topCards, ZoneType.Library, sa);
for (int i = maxCards - 1; i >= 0; i--) {
Card next = orderedCards.get(i);
player.getGame().getAction().moveToLibrary(next, 0, sa);

View File

@@ -89,7 +89,7 @@ public class RepeatEachEffect extends SpellAbilityEffect {
if (loopOverCards) {
if (sa.hasParam("ChooseOrder") && repeatCards.size() >= 2) {
repeatCards = player.getController().orderMoveToZoneList(repeatCards, ZoneType.Stack);
repeatCards = player.getController().orderMoveToZoneList(repeatCards, ZoneType.Stack, sa);
}
for (Card card : repeatCards) {

View File

@@ -40,40 +40,57 @@ public class SacrificeAllEffect extends SpellAbilityEffect {
final Player activator = sa.getActivatingPlayer();
final Game game = activator.getGame();
String valid = "";
if (sa.hasParam("ValidCards")) {
valid = sa.getParam("ValidCards");
}
CardCollectionView list;
if (sa.hasParam("Defined")) {
list = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
} else {
list = game.getCardsIn(ZoneType.Battlefield);
if (sa.hasParam("ValidCards")) {
list = AbilityUtils.filterListByType(list, sa.getParam("ValidCards"), sa);
}
else {
list = AbilityUtils.filterListByType(game.getCardsIn(ZoneType.Battlefield), valid, sa);
}
if (sa.hasParam("Controller")) {
list = CardLists.filterControlledBy(list, AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Controller"), sa));
}
list = CardLists.filter(list, CardPredicates.canBeSacrificedBy(sa));
final boolean remSacrificed = sa.hasParam("RememberSacrificed");
if (remSacrificed) {
card.clearRemembered();
}
// update cards that where using LKI
CardCollection gameList = new CardCollection();
for (Card sac : list) {
final Card gameCard = game.getCardState(sac, null);
// gameCard is LKI in that case, the card is not in game anymore
// or the timestamp did change
// this should check Self too
if (gameCard == null || !sac.equalsWithTimestamp(gameCard) || !gameCard.canBeSacrificedBy(sa)) {
continue;
}
gameList.add(gameCard);
}
list = gameList;
// Do controller check after LKI got updated
if (sa.hasParam("Controller")) {
list = CardLists.filterControlledBy(list, AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Controller"), sa));
}
if (list.size() > 1) {
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard);
list = GameActionUtil.orderCardsByTheirOwners(game, list, ZoneType.Graveyard, sa);
}
CardZoneTable table = new CardZoneTable();
Map<Integer, Card> cachedMap = Maps.newHashMap();
for (Card sac : list) {
final Card lKICopy = CardUtil.getLKICopy(sac, cachedMap);
if (game.getAction().sacrifice(sac, sa, table) != null && remSacrificed) {
if (game.getAction().sacrifice(sac, sa, table) != null) {
if (remSacrificed) {
card.addRemembered(lKICopy);
}
if (sa.hasParam("ImprintSacrificed")) {
card.addImprintedCard(lKICopy);
}
}
}
table.triggerChangesZoneAll(game);
}

View File

@@ -138,7 +138,7 @@ public class SacrificeEffect extends SpellAbilityEffect {
}
if (choosenToSacrifice.size() > 1) {
choosenToSacrifice = GameActionUtil.orderCardsByTheirOwners(game, choosenToSacrifice, ZoneType.Graveyard);
choosenToSacrifice = GameActionUtil.orderCardsByTheirOwners(game, choosenToSacrifice, ZoneType.Graveyard, sa);
}
Map<Integer, Card> cachedMap = Maps.newHashMap();

View File

@@ -6265,24 +6265,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return true;
}
if ((source.isSpell() || source.isActivatedAbility()) && source.getPayCosts().hasSpecificCostType(CostSacrifice.class)) {
if (isCreature() && source.getActivatingPlayer().hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) {
Cost srcCost = source.getPayCosts();
if (srcCost != null) {
if (srcCost.hasSpecificCostType(CostSacrifice.class)) {
return false;
}
}
}
if (isPermanent() && !isLand() && source.getActivatingPlayer().hasKeyword("You can't sacrifice nonland permanents to cast spells or activate abilities.")) {
Cost srcCost = source.getPayCosts();
if (srcCost != null) {
if (srcCost.hasSpecificCostType(CostSacrifice.class)) {
return false;
}
}
}
return getController().canSacrificeBy(source);
}

View File

@@ -3327,7 +3327,7 @@ public class CardFactoryUtil {
+ " the controller of the permanent it becomes sacrifices it at the beginning of the next cleanup step.";
final String strDelay = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Cleanup | TriggerDescription$ At the beginning of the next cleanup step, sacrifice CARDNAME.";
final String strSac = "DB$ SacrificeAll | ValidCards$ Card.Self";
final String strSac = "DB$ SacrificeAll | Defined$ Self";
SpellAbility saDelay = AbilityFactory.getAbility(strDelay, card);
saDelay.setAdditionalAbility("Execute", (AbilitySub) AbilityFactory.getAbility(strSac, card));
@@ -4433,7 +4433,7 @@ public class CardFactoryUtil {
final String delTrigStr = "DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | RememberObjects$ Imprinted " +
"| StackDescription$ None | TriggerDescription$ Sacrifice them at the beginning of the next end step.";
final String sacStr = "DB$ SacrificeAll | Defined$ DelayTriggerRemembered";
final String sacStr = "DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI";
final String cleanupStr = "DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True";

View File

@@ -7,6 +7,7 @@ import java.util.Map;
import com.google.common.collect.ForwardingTable;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Table;
import forge.game.Game;
@@ -94,4 +95,8 @@ public class CardZoneTable extends ForwardingTable<ZoneType, ZoneType, CardColle
}
return allCards;
}
public Iterable<Card> allCards() {
return Iterables.concat(values());
}
}

View File

@@ -1780,7 +1780,7 @@ public class Player extends GameEntity implements Comparable<Player> {
CardCollectionView milledView = milled;
if (destination == ZoneType.Graveyard && milled.size() > 1) {
milledView = GameActionUtil.orderCardsByTheirOwners(game, milled, ZoneType.Graveyard);
milledView = GameActionUtil.orderCardsByTheirOwners(game, milled, ZoneType.Graveyard, sa);
}
for (Card m : milledView) {

View File

@@ -32,6 +32,14 @@ public class PlayerCollection extends FCollection<Player> {
return result;
}
public final CardCollection getCardsIn(Iterable<ZoneType> zones) {
CardCollection result = new CardCollection();
for (Player p : this) {
result.addAll(p.getCardsIn(zones));
}
return result;
}
public final CardCollection getCreaturesInPlay() {
CardCollection result = new CardCollection();
for (Player p : this) {

View File

@@ -163,9 +163,6 @@ public abstract class PlayerController {
public abstract ImmutablePair<CardCollection, CardCollection> arrangeForSurveil(CardCollection topN);
public abstract boolean willPutCardOnTop(Card c);
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 */

View File

@@ -42,7 +42,8 @@ public class WrappedAbility extends Ability {
ApiType.Destroy,
ApiType.Token,
ApiType.SetState,
ApiType.Play
ApiType.Play,
ApiType.SacrificeAll
);
private final SpellAbility sa;

View File

@@ -6,10 +6,9 @@ A:AB$ Discard | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | Defined$ Play
SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ Player.Opponent
A:AB$ GainControl | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DelTrig | SpellDescription$ Gain control of target creature until end of turn. Untap it. It gains haste until end of turn. Sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player | Execute$ TrigSac | RememberObjects$ Targeted | TriggerDescription$ Sacrifice that creature at the beginning of the next end step if it has converted mana cost 3 or less.
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You | ConditionDefined$ DelayTriggerRemembered | ConditionPresent$ Card.cmcLE3
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI | Controller$ You | ConditionDefined$ DelayTriggerRememberedLKI | ConditionPresent$ Card.cmcLE3
A:AB$ RepeatEach | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ DBLoseLife2 | SpellDescription$ Each opponent loses life equal to the number of cards in their graveyard.
SVar:DBLoseLife2:DB$ LoseLife | Defined$ Player.IsRemembered | LifeAmount$ X | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Count$ValidGraveyard Card.RememberedPlayerCtrl
SVar:Picture:http://www.wizards.com/global/images/magic/general/angrath_the_flame_chained.jpg
Oracle:[+1]: Each opponent discards a card and loses 2 life.\n[3]: Gain control of target creature until end of turn. Untap it. It gains haste until end of turn. Sacrifice it at the beginning of the next end step if it has converted mana cost 3 or less.\n[8]: Each opponent loses life equal to the number of cards in their graveyard.

View File

@@ -9,9 +9,7 @@ SVar:RevealedDraw:DB$ Draw | Defined$ Player.Chosen | NumCards$ 1 | SubAbility$
SVar:TrigReveal:DB$ Reveal | Defined$ Player.Chosen | RevealValid$ Card.IsRemembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
T:Mode$ Drawn | ValidCard$ Card.NamedCard+OwnedBy Player.Chosen | TriggerZones$ Battlefield | Execute$ TrapTriggered | TriggerDescription$ When the chosen player draws a card with the chosen name, sacrifice CARDNAME. If you do, CARDNAME deals 10 damage to that player.
SVar:TrapTriggered:DB$ SacrificeAll | ValidCards$ Card.Self | RememberSacrificed$ True | SubAbility$ Explosion
SVar:Explosion:DB$ DealDamage | NumDmg$ 10 | Defined$ Player.Chosen | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup
SVar:X:Remembered$Amount
SVar:TrapTriggered:DB$ SacrificeAll | Defined$ Self | RememberSacrificed$ True | SubAbility$ Explosion
SVar:Explosion:DB$ DealDamage | NumDmg$ 10 | Defined$ Player.Chosen | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/booby_trap.jpg
Oracle:As Booby Trap enters the battlefield, choose an opponent and a card name other than a basic land card name.\nThe chosen player reveals each card they draw.\nWhen the chosen player draws a card with the chosen name, sacrifice Booby Trap. If you do, Booby Trap deals 10 damage to that player.

View File

@@ -4,7 +4,7 @@ Types:Instant
SVar:AltCost:Cost$ ExileFromHand<1/Card.Red+Other> | OpponentTurn$ True | Description$ If it's not your turn, you may exile a red card from your hand rather than pay this spell's mana cost.
A:SP$ Token | Cost$ 1 R R | TokenAmount$ 2 | TokenScript$ r_3_1_elemental_trample_haste | TokenOwner$ You | LegacyImage$ r 3 1 elemental trample haste mh1 | SubAbility$ DelayedSac | RememberTokens$ True | SpellDescription$ Create two 3/1 red Elemental creature tokens with trample and haste. Sacrifice those tokens at the beginning of your next upkeep.
SVar:DelayedSac:DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ DBSacToken | RememberObjects$ Remembered | SubAbility$ DBCleanup | TriggerDescription$ Sacrifice those tokens at the beginning of your next upkeep.
SVar:DBSacToken:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You
SVar:DBSacToken:DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI | Controller$ You
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
DeckHas:Ability$Token
Oracle:If it's not your turn, you may exile a red card from your hand rather than pay this spell's mana cost.\nCreate two 3/1 red Elemental creature tokens with trample and haste. Sacrifice those tokens at the beginning of your next upkeep.

View File

@@ -4,6 +4,5 @@ Types:Enchantment
A:AB$ Pump | Cost$ R | ValidTgts$ Creature.YouCtrl+toughnessLE2 | TgtPrompt$ Choose creature you control with toughness 2 or less | KW$ Flying | SubAbility$ DelTrig | SpellDescription$ Target creature you control with toughness 2 or less gains flying until end of turn. Flip a coin at the beginning of the next end step. If you lose the flip, sacrifice that creature.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigFlip | RememberObjects$ Targeted | TriggerDescription$ Flip a coin at the beginning of the next end step. If you lose the flip, sacrifice that creature.
SVar:TrigFlip:DB$ FlipACoin | LoseSubAbility$ DBSacrifice
SVar:DBSacrifice:DB$ SacrificeAll | Controller$ You | Defined$ DelayTriggerRemembered
SVar:Picture:http://www.wizards.com/global/images/magic/general/goblin_kites.jpg
SVar:DBSacrifice:DB$ SacrificeAll | Controller$ You | Defined$ DelayTriggerRememberedLKI
Oracle:{R}: Target creature you control with toughness 2 or less gains flying until end of turn. Flip a coin at the beginning of the next end step. If you lose the flip, sacrifice that creature.

View File

@@ -2,9 +2,9 @@ Name:Grave Peril
ManaCost:1 B
Types:Enchantment
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonBlack |TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ When a nonblack creature enters the battlefield, sacrifice Grave Peril. If you do, destroy that creature.
SVar:TrigSac:DB$ SacrificeAll | ValidCards$ Card.Self | SubAbility$ DBDestroy | RememberSacrificed$ True
SVar:DBDestroy:DB$ Destroy | Defined$ TriggeredCardLKICopy | ConditionDefined$ Remembered | ConditionPresent$ Card
SVar:TrigSac:DB$ SacrificeAll | Defined$ Self | SubAbility$ DBDestroy | RememberSacrificed$ True
SVar:DBDestroy:DB$ Destroy | Defined$ TriggeredCardLKICopy | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:NonStackingEffect:True
AI:RemoveDeck:Random
SVar:Picture:http://www.wizards.com/global/images/magic/general/grave_peril.jpg
Oracle:When a nonblack creature enters the battlefield, sacrifice Grave Peril. If you do, destroy that creature.

View File

@@ -4,9 +4,7 @@ Types:Legendary Creature Boar God
PT:6/6
K:Trample
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChange | TriggerZones$ Battlefield | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME attacks, you may put a creature card from your hand onto the battlefield tapped and attacking. Return that creature to your hand at the beginning of the next end step.
SVar:TrigChange:DB$ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.YouCtrl | Tapped$ True | Attacking$ True | RememberChanged$ True | SubAbility$ DBPump
SVar:DBPump:DB$ Animate | AtEOT$ Hand | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:TrigChange:DB$ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.YouCtrl | Tapped$ True | Attacking$ True | AtEOT$ Hand
SVar:HasAttackEffect:TRUE
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard,Exile | ValidCard$ Card.Self | Execute$ TriReturn | OptionalDecider$ You | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies or is put into exile from the battlefield, you may put it into its owner's library third from the top.
SVar:TriReturn:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Destination$ Library | LibraryPosition$ 2

View File

@@ -2,12 +2,11 @@ Name:Knowledge Vault
ManaCost:4
Types:Artifact
A:AB$ ChangeZone | Cost$ 2 T | Defined$ TopOfLibrary | Origin$ Library | Destination$ Exile | ExileFaceDown$ True | RememberChanged$ True | SpellDescription$ Exile the top card of your library face down.
A:AB$ SacrificeAll | Cost$ 0 | ValidCards$ Card.Self | RememberSacrificed$ True | SubAbility$ DBDiscardHand | SpellDescription$ Sacrifice CARDNAME. If you do, discard your hand, then put all cards exiled with CARDNAME into their owner's hand.
SVar:DBDiscardHand:DB$ Discard | Mode$ Hand | SubAbility$ DBChangeZoneAll | ConditionCheckSVar$ VaultX | ConditionSVarCompare$ GT0
SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Remembered | Origin$ Exile | Destination$ Hand | ConditionCheckSVar$ VaultX | ConditionSVarCompare$ GT0
A:AB$ SacrificeAll | Cost$ 0 | Defined$ Self | ImprintSacrificed$ True | SubAbility$ DBDiscardHand | SpellDescription$ Sacrifice CARDNAME. If you do, discard your hand, then put all cards exiled with CARDNAME into their owner's hand.
SVar:DBDiscardHand:DB$ Discard | Mode$ Hand | SubAbility$ DBChangeZoneAll | ConditionDefined$ Imprinted | ConditionPresent$ Card
SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Remembered | Origin$ Exile | Destination$ Hand | ConditionDefined$ Imprinted | ConditionPresent$ Card | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Any | Hidden$ True | Execute$ TrigGraveyard | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME leaves the battlefield, put all cards exiled with CARDNAME into their owner's graveyard.
SVar:TrigGraveyard:DB$ ChangeZoneAll | ChangeType$ Remembered | Origin$ Exile | Destination$ Graveyard
SVar:VaultX:Remembered$Valid Card.Self
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/knowledge_vault.jpg
Oracle:{2}, {T}: Exile the top card of your library face down.\n{0}: Sacrifice Knowledge Vault. If you do, discard your hand, then put all cards exiled with Knowledge Vault into their owner's hand.\nWhen Knowledge Vault leaves the battlefield, put all cards exiled with Knowledge Vault into their owner's graveyard.

View File

@@ -11,7 +11,7 @@ T:Mode$ TurnBegin | Execute$ DBCleanup | Static$ True
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player | TriggerZones$ Battlefield | CheckSVar$ X | SVarCompare$ GE1 | IsPresent$ Card.Self | Execute$ TrigChange | TriggerDescription$ At the beginning of each end step, if a creature dealt damage by CARDNAME this turn died, put that card onto the battlefield under your control. Sacrifice it when you lose control of CARDNAME.
SVar:TrigChange:DB$ ChangeZoneAll | ChangeType$ Creature.IsRemembered+ThisTurnEnteredFrom_Battlefield | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | RememberChanged$ True | ForgetOtherRemembered$ True | SubAbility$ TrigDelay
SVar:TrigDelay:DB$ DelayedTrigger | Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | RememberObjects$ Remembered | Execute$ TrigSac | Secondary$ True | SubAbility$ DBCleanup | SpellDescription$ Sacrifice it when you lose control of CARDNAME.
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | SubAbility$ DBCleanup
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI | Controller$ You
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Remembered$Amount
Oracle:At the beginning of each end step, if a creature dealt damage by Krovikan Vampire this turn died, put that card onto the battlefield under your control. Sacrifice it when you lose control of Krovikan Vampire.

View File

@@ -2,8 +2,6 @@ Name:Planebound Accomplice
ManaCost:2 R
Types:Creature Human Wizard
PT:1/3
A:AB$ ChangeZone | Cost$ R | Origin$ Hand | Destination$ Battlefield | ChangeType$ Planeswalker.YouOwn | RememberChanged$ True | Optional$ True | SubAbility$ DBPump | AILogic$ BeforeCombat | SpellDescription$ You may put a planeswalker card from your hand onto the battlefield. Sacrifice it at the beginning of the next end step.
SVar:DBPump:DB$ Pump | Defined$ Remembered | AtEOT$ Sacrifice | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
A:AB$ ChangeZone | Cost$ R | Origin$ Hand | Destination$ Battlefield | ChangeType$ Planeswalker.YouOwn | Optional$ True | AtEOT$ Sacrifice | AILogic$ BeforeCombat | SpellDescription$ You may put a planeswalker card from your hand onto the battlefield. Sacrifice it at the beginning of the next end step.
AI:RemoveDeck:Random
Oracle:{R}: You may put a planeswalker card from your hand onto the battlefield. Sacrifice it at the beginning of the next end step.

View File

@@ -2,9 +2,7 @@ Name:Promise of Bunrei
ManaCost:2 W
Types:Enchantment
T:Mode$ ChangesZone | ValidCard$ Creature.YouCtrl | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigSac | TriggerZones$ Battlefield | TriggerDescription$ When a creature you control dies, sacrifice CARDNAME. If you do, create four 1/1 colorless Spirit creature tokens.
SVar:TrigSac:DB$ SacrificeAll | ValidCards$ Card.Self | RememberSacrificed$ True | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenAmount$ 4 | TokenScript$ c_1_1_spirit | TokenOwner$ You | LegacyImage$ c 1 1 spirit sok | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup
SVar:TrigSac:DB$ SacrificeAll | Defined$ Self | RememberSacrificed$ True | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenAmount$ 4 | TokenScript$ c_1_1_spirit | TokenOwner$ You | LegacyImage$ c 1 1 spirit sok | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Remembered$Amount
SVar:Picture:http://www.wizards.com/global/images/magic/general/promise_of_bunrei.jpg
Oracle:When a creature you control dies, sacrifice Promise of Bunrei. If you do, create four 1/1 colorless Spirit creature tokens.

View File

@@ -7,7 +7,5 @@ S:Mode$ Continuous | Affected$ Card.Self | RemoveType$ Creature | CheckSVar$ X |
SVar:X:Count$Devotion.Red
SVar:BuffedBy:Permanent.Red
S:Mode$ Continuous | Affected$ Creature.YouCtrl+Other | AddKeyword$ Haste | Description$ Other creatures you control have haste.
A:AB$ ChangeZone | Cost$ 2 R | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.Red,Creature.Artifact | ChangeNum$ 1 | Optional$ You | RememberChanged$ True | SubAbility$ DBPump | StackDescription$ SpellDescription | SpellDescription$ You may put a red creature card or an artifact creature card from your hand onto the battlefield. Sacrifice it at the beginning of the next end step.
SVar:DBPump:DB$ Pump | Defined$ Remembered | AtEOT$ Sacrifice | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
A:AB$ ChangeZone | Cost$ 2 R | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.Red,Creature.Artifact | ChangeNum$ 1 | Optional$ You | AtEOT$ Sacrifice | StackDescription$ SpellDescription | SpellDescription$ You may put a red creature card or an artifact creature card from your hand onto the battlefield. Sacrifice it at the beginning of the next end step.
Oracle:Indestructible\nAs long as your devotion to red is less than five, Purphoros isn't a creature.\nOther creatures you control have haste.\n{2}{R}: You may put a red creature card or an artifact creature card from your hand onto the battlefield. Sacrifice it at the beginning of the next end step.

View File

@@ -2,9 +2,7 @@ Name:Purphoros's Intervention
ManaCost:X R
Types:Sorcery
A:SP$ Charm | Cost$ X R | Choices$ DBToken,DBDealDamage
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ r_x_1_elemental_trample_haste | TokenOwner$ You | TokenPower$ X | LegacyImage$ r x 1 elemental trample haste thb | RememberTokens$ True | SubAbility$ DBPump | SpellDescription$ Create an X/1 red Elemental creature token with trample and haste. Sacrifice it at the beginning of the next end step.
SVar:DBPump:DB$ Pump | Defined$ Remembered | AtEOT$ Sacrifice | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ r_x_1_elemental_trample_haste | TokenOwner$ You | TokenPower$ X | LegacyImage$ r x 1 elemental trample haste thb | AtEOT$ Sacrifice | SpellDescription$ Create an X/1 red Elemental creature token with trample and haste. Sacrifice it at the beginning of the next end step.
SVar:DBDealDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | NumDmg$ XX | SpellDescription$ CARDNAME deals twice X damage to target creature or planeswalker.
SVar:X:Count$xPaid
SVar:XX:SVar$X/Twice

View File

@@ -5,9 +5,8 @@ PT:1/1
A:AB$ ChangeZone | Cost$ 3 U Exile<1/CARDNAME> | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.YouOwn | Optional$ True | RememberChanged$ True | SubAbility$ DBPump | SpellDescription$ You may put a creature card from your hand onto the battlefield. If you do, that creature gains haste until end of turn. At the beginning of the next end step, sacrifice that creature. If you do, return CARDNAME to the battlefield.
SVar:DBPump:DB$ Pump | Defined$ Remembered | KW$ Haste | ConditionDefined$ Remembered | ConditionPresent$ Creature | ConditionCompare$ EQ1 | SubAbility$ DBDelTrig
SVar:DBDelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigSac | TriggerDescription$ At the beginning of the next end step, sacrifice that creature. | RememberObjects$ Remembered | ConditionDefined$ Remembered | ConditionPresent$ Creature | SubAbility$ DBCleanup
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You | RememberSacrificed$ True | SubAbility$ DBBounce
SVar:DBBounce:DB$ ChangeZone | Origin$ Exile | Defined$ Self | Destination$ Battlefield | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI | Controller$ You | RememberSacrificed$ True | SubAbility$ DBBounce
SVar:DBBounce:DB$ ChangeZone | Origin$ Exile | Defined$ Self | Destination$ Battlefield | ConditionDefined$ Remembered | ConditionPresent$ Card
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/shifty_doppelganger.jpg
Oracle:{3}{U}, Exile Shifty Doppelganger: You may put a creature card from your hand onto the battlefield. If you do, that creature gains haste until end of turn. At the beginning of the next end step, sacrifice that creature. If you do, return Shifty Doppelganger to the battlefield.

View File

@@ -4,9 +4,6 @@ Types:Creature Human Wizard
PT:1/2
K:Haste
A:AB$ SetState | Cost$ T | ValidTgts$ Creature.YouCtrl+faceDown | Mode$ TurnFace | SubAbility$ DBDelTrig | SpellDescription$ Turn target face-down creature you control face up. At the beginning of the next end step, sacrifice it.
SVar:DBDelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigSac | RememberObjects$ Targeted | TriggerDescription$ At the beginning of the next end step, sacrifice it. | SubAbility$ DBCleanup
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:DBPump:DB$ Pump | Defined$ Targeted | AtEOT$ Sacrifice
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/skirk_alarmist.jpg
Oracle:Haste\n{T}: Turn target face-down creature you control face up. At the beginning of the next end step, sacrifice it.

View File

@@ -4,10 +4,9 @@ Types:Instant
A:SP$ GainControl | Cost$ 3 U U B | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select target creature you don't control | ActivationPhases$ BeginCombat->EndCombat | Untap$ True | AddKWs$ Haste | SubAbility$ DBAnimate | SpellDescription$ Cast this spell only during combat. Untap target creature you don't control and gain control of it. It gains haste until end of turn. At the beginning of the next end step, sacrifice it. If you do, you gain life equal to its toughness.
SVar:DBAnimate:DB$ Animate | Defined$ Targeted | Keywords$ Haste | sVars$ SneakAttackEOT | SubAbility$ DelTrig
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigSac | RememberObjects$ Targeted | TriggerDescription$ At the beginning of the next end step, sacrifice it. If you do, you gain life equal to its toughness. | AILogic$ Always | ConditionDefined$ Targeted | ConditionPresent$ Card | ConditionCompare$ GE1
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You | RememberSacrificed$ True | SubAbility$ DBGainLife
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI | Controller$ You | RememberSacrificed$ True | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | LifeAmount$ X | SubAbility$ DBCleanup | ConditionDefined$ Remembered | ConditionPresent$ Card
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:RememberedLKI$CardToughness
SVar:SneakAttackEOT:SVar:EndOfTurnLeavePlay:AtEOT
SVar:Picture:http://www.wizards.com/global/images/magic/general/spinal_embrace.jpg
Oracle:Cast this spell only during combat.\nUntap target creature you don't control and gain control of it. It gains haste until end of turn. At the beginning of the next end step, sacrifice it. If you do, you gain life equal to its toughness.

View File

@@ -2,10 +2,7 @@ Name:Tears of Rage
ManaCost:2 R R
Types:Instant
Text:Cast this spell only during the declare attackers step.\r\n
A:SP$ PumpAll | Cost$ 2 R R | ActivationPhases$ Declare Attackers | ValidCards$ Creature.attacking+YouCtrl | NumAtt$ +X | SubAbility$ DelTrig | SpellDescription$ Attacking creatures you control get +X/+0 until end of turn, where X is the number of attacking creatures. Sacrifice those creatures at the beginning of the next end step.
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End Of Turn | Execute$ TrigSac | RememberObjects$ Valid Creature.attacking+YouCtrl | TriggerDescription$ CARDNAME - Sacrifice those creature at the beginning of the next end step. | AILogic$ Always
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You
A:SP$ PumpAll | Cost$ 2 R R | ActivationPhases$ Declare Attackers | ValidCards$ Creature.attacking+YouCtrl | NumAtt$ +X | AtEOT$ Sacrifice | SpellDescription$ Attacking creatures you control get +X/+0 until end of turn, where X is the number of attacking creatures. Sacrifice those creatures at the beginning of the next end step.
SVar:X:Count$Valid Creature.attacking+YouCtrl
AI:RemoveDeck:All
SVar:Picture:http://www.wizards.com/global/images/magic/general/tears_of_rage.jpg
Oracle:Cast this spell only during the declare attackers step.\nAttacking creatures you control get +X/+0 until end of turn, where X is the number of attacking creatures. Sacrifice those creatures at the beginning of the next end step.

View File

@@ -4,9 +4,7 @@ Types:Creature Thalakos Wizard
PT:1/1
K:Shadow
T:Mode$ AttackerUnblocked | ValidCard$ Card.Self | Execute$ TrigSacrifice | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME attacks and isn't blocked, you may sacrifice it. If you do, gain control of target creature. (This effect lasts indefinitely.)
SVar:TrigSacrifice:DB$ SacrificeAll | ValidCards$ Card.Self | RememberSacrificed$ True | SubAbility$ DBGainControl
SVar:DBGainControl:DB$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | SubAbility$ DBCleanup
SVar:TrigSacrifice:DB$ SacrificeAll | Defined$ Self | RememberSacrificed$ True | SubAbility$ DBGainControl
SVar:DBGainControl:DB$ GainControl | ValidTgts$ Creature | TgtPrompt$ Select target creature | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Remembered$Amount
SVar:Picture:http://www.wizards.com/global/images/magic/general/thalakos_deceiver.jpg
Oracle:Shadow (This creature can block or be blocked by only creatures with shadow.)\nWhenever Thalakos Deceiver attacks and isn't blocked, you may sacrifice it. If you do, gain control of target creature. (This effect lasts indefinitely.)

View File

@@ -4,9 +4,6 @@ Types:Creature Elemental Shaman
PT:1/2
K:Haste
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChange | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, choose target Elemental creature card in your graveyard with toughness less than CARDNAME's toughness. Return that card to the battlefield tapped and attacking. Sacrifice it at the beginning of the next end step.
SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.Elemental+YouCtrl+toughnessLTX | TgtPrompt$ Select target Elemental creature card in your graveyard | Mandatory$ True | Tapped$ True | Attacking$ True | RememberChanged$ True | SubAbility$ DelTrig
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | Execute$ TrigSac | RememberObjects$ Remembered | TriggerDescription$ Sacrifice it at the beginning of the next end step | SubAbility$ DBCleanup
SVar:TrigSac:DB$ SacrificeAll | Defined$ DelayTriggerRemembered | Controller$ You
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:TrigChange:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | ValidTgts$ Creature.Elemental+YouCtrl+toughnessLTX | TgtPrompt$ Select target Elemental creature card in your graveyard | Mandatory$ True | Tapped$ True | Attacking$ True | AtEOT$ Sacrifice
SVar:X:Count$CardToughness
Oracle:Haste\nWhenever Thunderkin Awakener attacks, choose target Elemental creature card in your graveyard with toughness less than Thunderkin Awakener's toughness. Return that card to the battlefield tapped and attacking. Sacrifice it at the beginning of the next end step.

View File

@@ -5,10 +5,8 @@ PT:1/1
K:Flying
K:Infect
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | OptionalDecider$ You | Execute$ TrigSacrifice | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, you may sacrifice it. If you do, that player discards a card for each poison counter they have.
SVar:TrigSacrifice:DB$ SacrificeAll | ValidCards$ Card.Self | RememberSacrificed$ True | SubAbility$ DBDiscard
SVar:DBDiscard:DB$ Discard | Defined$ TriggeredTarget | NumCards$ X | Mode$ TgtChoose | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ1 | SubAbility$ DBCleanup
SVar:TrigSacrifice:DB$ SacrificeAll | Defined$ Self | RememberSacrificed$ True | SubAbility$ DBDiscard
SVar:DBDiscard:DB$ Discard | Defined$ TriggeredTarget | NumCards$ X | Mode$ TgtChoose | ConditionDefined$ Remembered | ConditionPresent$ Card | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:TriggeredTarget$PoisonCounters
SVar:Y:Remembered$Amount
SVar:Picture:http://www.wizards.com/global/images/magic/general/whispering_specter.jpg
Oracle:Flying\nInfect (This creature deals damage to creatures in the form of -1/-1 counters and to players in the form of poison counters.)\nWhenever Whispering Specter deals combat damage to a player, you may sacrifice it. If you do, that player discards a card for each poison counter they have.

View File

@@ -86,7 +86,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (discardType.equals("Hand")) {
if (hand.size() > 1 && ability.getActivatingPlayer() != null) {
hand = ability.getActivatingPlayer().getController().orderMoveToZoneList(hand, ZoneType.Graveyard);
hand = ability.getActivatingPlayer().getController().orderMoveToZoneList(hand, ZoneType.Graveyard, ability);
}
return PaymentDecision.card(hand);
}
@@ -105,7 +105,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
CardCollectionView randomSubset = Aggregates.random(hand, c, new CardCollection());
if (randomSubset.size() > 1 && ability.getActivatingPlayer() != null) {
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard);
randomSubset = ability.getActivatingPlayer().getController().orderMoveToZoneList(randomSubset, ZoneType.Graveyard, ability);
}
return PaymentDecision.card(randomSubset);
}