mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
SacrificeAllEffect: check timestamp for LKI objects
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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") ) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -40,39 +40,56 @@ 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) {
|
||||
card.addRemembered(lKICopy);
|
||||
if (game.getAction().sacrifice(sac, sa, table) != null) {
|
||||
if (remSacrificed) {
|
||||
card.addRemembered(lKICopy);
|
||||
}
|
||||
if (sa.hasParam("ImprintSacrificed")) {
|
||||
card.addImprintedCard(lKICopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
table.triggerChangesZoneAll(game);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1136,7 +1136,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
newTop = c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (newTop != null) {
|
||||
removeMutatedStates();
|
||||
newTop.mergedCards = mergedCards;
|
||||
@@ -6265,24 +6265,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
return true;
|
||||
}
|
||||
|
||||
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 ((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.")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isPermanent() && !isLand() && source.getActivatingPlayer().hasKeyword("You can't sacrifice nonland permanents to cast spells or activate abilities.")) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -31,6 +31,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();
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user