mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
- Cleanup and fix PlayEffect, especially related to optionally playing multiple cards
- Fix Jace, Architect of Thought's ultimate to search each player's library
This commit is contained in:
@@ -30,7 +30,7 @@ import forge.util.Lang;
|
|||||||
|
|
||||||
public class PlayEffect extends SpellAbilityEffect {
|
public class PlayEffect extends SpellAbilityEffect {
|
||||||
@Override
|
@Override
|
||||||
protected String getStackDescription(SpellAbility sa) {
|
protected String getStackDescription(final SpellAbility sa) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
sb.append("Play ");
|
sb.append("Play ");
|
||||||
@@ -49,13 +49,12 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(final SpellAbility sa) {
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
Player activator = sa.getActivatingPlayer();
|
Player activator = sa.getActivatingPlayer();
|
||||||
final Game game = activator.getGame();
|
final Game game = activator.getGame();
|
||||||
boolean optional = sa.hasParam("Optional");
|
final boolean optional = sa.hasParam("Optional");
|
||||||
boolean remember = sa.hasParam("RememberPlayed");
|
boolean remember = sa.hasParam("RememberPlayed");
|
||||||
boolean wasFaceDown = false;
|
|
||||||
boolean useEncoded = false;
|
boolean useEncoded = false;
|
||||||
int amount = 1;
|
int amount = 1;
|
||||||
if (sa.hasParam("Amount") && !sa.getParam("Amount").equals("All")) {
|
if (sa.hasParam("Amount") && !sa.getParam("Amount").equals("All")) {
|
||||||
@@ -84,23 +83,23 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
else if (sa.hasParam("AnySupportedCard")) {
|
else if (sa.hasParam("AnySupportedCard")) {
|
||||||
List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
List<PaperCard> cards = Lists.newArrayList(StaticData.instance().getCommonCards().getUniqueCards());
|
||||||
String valid = sa.getParam("AnySupportedCard");
|
final String valid = sa.getParam("AnySupportedCard");
|
||||||
if (StringUtils.containsIgnoreCase(valid, "sorcery")) {
|
if (StringUtils.containsIgnoreCase(valid, "sorcery")) {
|
||||||
Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_SORCERY, PaperCard.FN_GET_RULES);
|
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_SORCERY, PaperCard.FN_GET_RULES);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
if (StringUtils.containsIgnoreCase(valid, "instant")) {
|
if (StringUtils.containsIgnoreCase(valid, "instant")) {
|
||||||
Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_INSTANT, PaperCard.FN_GET_RULES);
|
final Predicate<PaperCard> cpp = Predicates.compose(CardRulesPredicates.Presets.IS_INSTANT, PaperCard.FN_GET_RULES);
|
||||||
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
cards = Lists.newArrayList(Iterables.filter(cards, cpp));
|
||||||
}
|
}
|
||||||
if (sa.hasParam("RandomCopied")) {
|
if (sa.hasParam("RandomCopied")) {
|
||||||
List<PaperCard> copysource = new ArrayList<PaperCard>(cards);
|
final List<PaperCard> copysource = new ArrayList<PaperCard>(cards);
|
||||||
CardCollection choice = new CardCollection();
|
final CardCollection choice = new CardCollection();
|
||||||
final String num = sa.hasParam("RandomNum") ? sa.getParam("RandomNum") : "1";
|
final String num = sa.hasParam("RandomNum") ? sa.getParam("RandomNum") : "1";
|
||||||
int ncopied = AbilityUtils.calculateAmount(source, num, sa);
|
int ncopied = AbilityUtils.calculateAmount(source, num, sa);
|
||||||
while(ncopied > 0) {
|
while(ncopied > 0) {
|
||||||
final PaperCard cp = Aggregates.random(copysource);
|
final PaperCard cp = Aggregates.random(copysource);
|
||||||
Card possibleCard = Card.fromPaperCard(cp, null);
|
final Card possibleCard = Card.fromPaperCard(cp, null);
|
||||||
// Need to temporarily set the Owner so the Game is set
|
// Need to temporarily set the Owner so the Game is set
|
||||||
possibleCard.setOwner(sa.getActivatingPlayer());
|
possibleCard.setOwner(sa.getActivatingPlayer());
|
||||||
|
|
||||||
@@ -134,31 +133,39 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
amount = tgtCards.size();
|
amount = tgtCards.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < amount; i++) {
|
final CardCollection saidNoTo = new CardCollection();
|
||||||
|
while (tgtCards.size() > saidNoTo.size() && amount > 0) {
|
||||||
Card tgtCard = controller.getController().chooseSingleEntityForEffect(tgtCards, sa, "Select a card to play");
|
Card tgtCard = controller.getController().chooseSingleEntityForEffect(tgtCards, sa, "Select a card to play");
|
||||||
if (tgtCard == null) {
|
if (tgtCard == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean wasFaceDown;
|
||||||
if (tgtCard.isFaceDown()) {
|
if (tgtCard.isFaceDown()) {
|
||||||
tgtCard.setState(CardStateName.Original, false);
|
tgtCard.setState(CardStateName.Original, false);
|
||||||
wasFaceDown = true;
|
wasFaceDown = true;
|
||||||
|
} else {
|
||||||
|
wasFaceDown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optional && !controller.getController().confirmAction(sa, null, "Do you want to play " + tgtCard + "?")) {
|
if (optional && !controller.getController().confirmAction(sa, null, String.format("Do you want to play %s?", tgtCard))) {
|
||||||
// i--; // This causes an infinite loop (ArsenalNut)
|
|
||||||
if (wasFaceDown) {
|
if (wasFaceDown) {
|
||||||
tgtCard.setState(CardStateName.FaceDown, false);
|
tgtCard.setState(CardStateName.FaceDown, false);
|
||||||
}
|
}
|
||||||
|
saidNoTo.add(tgtCard);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tgtCards.remove(tgtCard);
|
||||||
|
|
||||||
if (wasFaceDown) {
|
if (wasFaceDown) {
|
||||||
tgtCard.updateStateForView();
|
tgtCard.updateStateForView();
|
||||||
}
|
}
|
||||||
if (sa.hasParam("ForgetRemembered")) {
|
if (sa.hasParam("ForgetRemembered")) {
|
||||||
source.clearRemembered();
|
source.clearRemembered();
|
||||||
}
|
}
|
||||||
Card original = tgtCard;
|
|
||||||
|
final Card original = tgtCard;
|
||||||
if (sa.hasParam("CopyCard")) {
|
if (sa.hasParam("CopyCard")) {
|
||||||
final Zone zone = tgtCard.getZone();
|
final Zone zone = tgtCard.getZone();
|
||||||
tgtCard = Card.fromPaperCard(tgtCard.getPaperCard(), sa.getActivatingPlayer());
|
tgtCard = Card.fromPaperCard(tgtCard.getPaperCard(), sa.getActivatingPlayer());
|
||||||
@@ -173,24 +180,30 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
tgtCard.setSVar("IsEncoded", "Number$1");
|
tgtCard.setSVar("IsEncoded", "Number$1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sa.hasParam("SuspendCast")) {
|
if(sa.hasParam("SuspendCast")) {
|
||||||
tgtCard.setSuspendCast(true);
|
tgtCard.setSuspendCast(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// lands will be played
|
// lands will be played
|
||||||
if (tgtCard.isLand()) {
|
if (tgtCard.isLand()) {
|
||||||
if (controller.playLand(tgtCard, true) && remember) {
|
if (controller.playLand(tgtCard, true)) {
|
||||||
source.addRemembered(tgtCard);
|
amount--;
|
||||||
|
if (remember) {
|
||||||
|
source.addRemembered(tgtCard);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
saidNoTo.add(tgtCard);
|
||||||
}
|
}
|
||||||
tgtCards.remove(tgtCard);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get basic spells (no flashback, etc.)
|
// get basic spells (no flashback, etc.)
|
||||||
List<SpellAbility> sas = AbilityUtils.getBasicSpellsFromPlayEffect(tgtCard, controller);
|
final List<SpellAbility> sas = AbilityUtils.getBasicSpellsFromPlayEffect(tgtCard, controller);
|
||||||
if (sas.isEmpty()) {
|
if (sas.isEmpty()) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
tgtCards.remove(tgtCard);
|
|
||||||
// play copied cards with linked abilities, e.g. Elite Arcanist
|
// play copied cards with linked abilities, e.g. Elite Arcanist
|
||||||
if (sa.hasParam("CopyOnce")) {
|
if (sa.hasParam("CopyOnce")) {
|
||||||
tgtCards.remove(original);
|
tgtCards.remove(original);
|
||||||
@@ -198,11 +211,11 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
// only one mode can be used
|
// only one mode can be used
|
||||||
SpellAbility tgtSA = sa.getActivatingPlayer().getController().getAbilityToPlay(tgtCard, sas);
|
SpellAbility tgtSA = sa.getActivatingPlayer().getController().getAbilityToPlay(tgtCard, sas);
|
||||||
boolean noManaCost = sa.hasParam("WithoutManaCost");
|
final boolean noManaCost = sa.hasParam("WithoutManaCost");
|
||||||
if (noManaCost) {
|
if (noManaCost) {
|
||||||
tgtSA = tgtSA.copyWithNoManaCost();
|
tgtSA = tgtSA.copyWithNoManaCost();
|
||||||
} else if (sa.hasParam("PlayMadness")) {
|
} else if (sa.hasParam("PlayMadness")) {
|
||||||
Cost abCost = new Cost(sa.getParam("PlayMadness"), false);
|
final Cost abCost = new Cost(sa.getParam("PlayMadness"), false);
|
||||||
tgtSA = tgtSA.copyWithDefinedCost(abCost);
|
tgtSA = tgtSA.copyWithDefinedCost(abCost);
|
||||||
tgtSA.getHostCard().setMadness(true);
|
tgtSA.getHostCard().setMadness(true);
|
||||||
}
|
}
|
||||||
@@ -211,12 +224,12 @@ public class PlayEffect extends SpellAbilityEffect {
|
|||||||
tgtSA.getTargetRestrictions().setMandatory(true);
|
tgtSA.getTargetRestrictions().setMandatory(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
remember &= controller.getController().playSaFromPlayEffect(tgtSA);
|
remember &= controller.getController().playSaFromPlayEffect(tgtSA);
|
||||||
if (remember) {
|
if (remember) {
|
||||||
source.addRemembered(tgtSA.getHostCard());
|
source.addRemembered(tgtSA.getHostCard());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
amount--;
|
||||||
}
|
}
|
||||||
} // end resolve
|
} // end resolve
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,9 @@ A:AB$ Dig | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | DigNum$ 3 | Revea
|
|||||||
SVar:DBTwoPiles:DB$ TwoPiles | Defined$ You | DefinedCards$ Remembered | Separator$ Opponent | ChosenPile$ DBHand | UnchosenPile$ DBLibraryBottom
|
SVar:DBTwoPiles:DB$ TwoPiles | Defined$ You | DefinedCards$ Remembered | Separator$ Opponent | ChosenPile$ DBHand | UnchosenPile$ DBLibraryBottom
|
||||||
SVar:DBHand:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand
|
SVar:DBHand:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Hand
|
||||||
SVar:DBLibraryBottom:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Library | LibraryPosition$ -1 | SubAbility$ DBCleanup
|
SVar:DBLibraryBottom:DB$ ChangeZone | Defined$ Remembered | Origin$ Library | Destination$ Library | LibraryPosition$ -1 | SubAbility$ DBCleanup
|
||||||
A:AB$ ChangeZone | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | Origin$ Library | Destination$ Exile | DefinedPlayer$ Opponent | Chooser$ You | ChangeType$ Card.nonLand | ChangeNum$ 1 | RememberChanged$ True | Shuffle$ True | SubAbility$ JaceYourself | SpellDescription$ For each player, search that player's library for a nonland card and exile it, then that player shuffles his or her library. You may cast those cards without paying their mana costs.
|
A:AB$ RepeatEach | Cost$ SubCounter<8/LOYALTY> | Planeswalker$ True | Ultimate$ True | RepeatPlayers$ Each | RepeatSubAbility$ DBJaceExile | SubAbility$ DBPlayIt | SpellDescription$ For each player, search that player's library for a nonland card and exile it, then that player shuffles his or her library. You may cast those cards without paying their mana costs.
|
||||||
SVar:JaceYourself:DB$ ChangeZone | Origin$ Library | Destination$ Exile | DefinedPlayer$ You | ChangeType$ Card.nonLand | ChangeNum$ 1 | RememberChanged$ True | Shuffle$ True | SubAbility$ DBPlayIT
|
SVar:DBJaceExile:DB$ ChangeZone | Origin$ Library | Destination$ Exile | DefinedPlayer$ Remembered | Chooser$ You | ChangeType$ Card.nonLand | ChangeNum$ 1 | Imprint$ True | Shuffle$ True
|
||||||
SVar:DBPlayIT:DB$ Play | Defined$ Remembered | Amount$ Thoughts | References$ Thoughts | Controller$ You | WithoutManaCost$ True | Optional$ True | RememberPlayed$ True | SubAbility$ DBCleanup
|
SVar:DBPlayIt:DB$ Play | Defined$ Imprinted | Amount$ All | Controller$ You | WithoutManaCost$ True | Optional$ True | RememberPlayed$ True | SubAbility$ DBCleanup
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
|
||||||
SVar:Thoughts:Remembered$Amount
|
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/jace_architect_of_thought.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/jace_architect_of_thought.jpg
|
||||||
Oracle:[+1] Until your next turn, whenever a creature an opponent controls attacks, it gets -1/-0 until end of turn.\n[-2] Reveal the top three cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other on the bottom of your library in any order.\n[-8] For each player, search that player's library for a nonland card and exile it, then that player shuffles his or her library. You may cast those cards without paying their mana costs.
|
Oracle:[+1] Until your next turn, whenever a creature an opponent controls attacks, it gets -1/-0 until end of turn.\n[-2] Reveal the top three cards of your library. An opponent separates those cards into two piles. Put one pile into your hand and the other on the bottom of your library in any order.\n[-8] For each player, search that player's library for a nonland card and exile it, then that player shuffles his or her library. You may cast those cards without paying their mana costs.
|
||||||
|
|||||||
Reference in New Issue
Block a user