mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Arcane Savant and friends
This commit is contained in:
@@ -579,7 +579,7 @@ public class AiCostDecision extends CostDecisionMakerBase {
|
||||
@Override
|
||||
public PaymentDecision visit(CostReveal cost) {
|
||||
final String type = cost.getType();
|
||||
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
|
||||
CardCollectionView hand = player.getCardsIn(cost.getRevealFrom());
|
||||
|
||||
if (cost.payCostFromSource()) {
|
||||
if (!hand.contains(source)) {
|
||||
|
||||
@@ -1558,8 +1558,7 @@ public class GameAction {
|
||||
// Where there are none, it should bring up speed controls
|
||||
game.fireEvent(new GameEventGameStarted(gameType, first, game.getPlayers()));
|
||||
|
||||
// Emissary's Plot
|
||||
// runPreOpeningHandActions(first);
|
||||
runPreOpeningHandActions(first);
|
||||
|
||||
game.setAge(GameStage.Mulligan);
|
||||
for (final Player p1 : game.getPlayers()) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.game;
|
||||
|
||||
import com.google.common.base.Enums;
|
||||
import com.google.common.base.Function;
|
||||
import forge.StaticData;
|
||||
import forge.deck.CardPool;
|
||||
@@ -144,4 +145,8 @@ public enum GameType {
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public static GameType smartValueOf(String name) {
|
||||
return Enums.getIfPresent(GameType.class, name).orNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,6 +260,8 @@ public class AbilityUtils {
|
||||
list = sa.getRootAbility().getPaidList("SacrificedCards");
|
||||
} else if (defined.startsWith("Sacrificed")) {
|
||||
list = sa.getRootAbility().getPaidList("Sacrificed");
|
||||
} else if (defined.startsWith("Revealed")) {
|
||||
list = sa.getRootAbility().getPaidList("Revealed");
|
||||
} else if (defined.startsWith("DiscardedCards")) {
|
||||
list = sa.getRootAbility().getPaidList("DiscardedCards");
|
||||
} else if (defined.startsWith("Discarded")) {
|
||||
|
||||
@@ -58,6 +58,15 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
|
||||
validDesc = sa.getParam("ValidDesc");
|
||||
}
|
||||
|
||||
String message;
|
||||
if (sa.hasParam("SelectPrompt")) {
|
||||
message = sa.getParam("SelectPrompt");
|
||||
} else if (validDesc.equals("card")) {
|
||||
message = Localizer.getInstance().getMessage("lblChooseACardName");
|
||||
} else {
|
||||
message = Localizer.getInstance().getMessage("lblChooseASpecificCard", validDesc);
|
||||
}
|
||||
|
||||
boolean randomChoice = sa.hasParam("AtRandom");
|
||||
boolean chooseFromDefined = sa.hasParam("ChooseFromDefinedCards");
|
||||
for (final Player p : tgtPlayers) {
|
||||
@@ -100,12 +109,9 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
Collections.sort(faces);
|
||||
chosen = p.getController().chooseCardName(sa, faces, Localizer.getInstance().getMessage("lblChooseACardName"));
|
||||
chosen = p.getController().chooseCardName(sa, faces, message);
|
||||
} else {
|
||||
// use CardFace because you might name a alternate name
|
||||
//"name a card" in mtg card oracle text is "choose a card name",change text
|
||||
final String message = validDesc.equals("card") ? Localizer.getInstance().getMessage("lblChooseACardName") : Localizer.getInstance().getMessage("lblChooseASpecificCard", validDesc);
|
||||
|
||||
// use CardFace because you might name a alternate names
|
||||
Predicate<ICardFace> cpp = Predicates.alwaysTrue();
|
||||
if (sa.hasParam("ValidCards")) {
|
||||
cpp = CardFacePredicates.valid(valid);
|
||||
@@ -119,6 +125,9 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
|
||||
p.getGame().getAction().nofityOfValue(sa, host, Localizer.getInstance().getMessage("lblPlayerPickedChosen", p.getName(), chosen), p);
|
||||
p.setNamedCard(chosen);
|
||||
}
|
||||
if (sa.hasParam("NoteFor")) {
|
||||
p.addNoteForName(sa.getParam("NoteFor"), "Name:" + chosen);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,6 +345,14 @@ public class PumpEffect extends SpellAbilityEffect {
|
||||
pumpForget = sa.getParam("ForgetObjects");
|
||||
}
|
||||
|
||||
if (sa.hasParam("NoteCardsFor")) {
|
||||
for (final Card c : AbilityUtils.getDefinedCards(host, sa.getParam("NoteCards"), sa)) {
|
||||
for (Player p : tgtPlayers) {
|
||||
p.addNoteForName(sa.getParam("NoteCardsFor"), "Id:" + c.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pumpForget != null) {
|
||||
for (final Object o : AbilityUtils.getDefinedObjects(host, pumpForget, sa)) {
|
||||
host.removeRemembered(o);
|
||||
@@ -394,7 +402,7 @@ public class PumpEffect extends SpellAbilityEffect {
|
||||
if (sa.hasParam("AtEOT") && !tgtCards.isEmpty()) {
|
||||
registerDelayedTrigger(sa, sa.getParam("AtEOT"), tgtCards);
|
||||
}
|
||||
|
||||
|
||||
for (final Card tgtC : untargetedCards) {
|
||||
// only pump things in PumpZone
|
||||
if (!tgtC.isInZone(pumpZone)) {
|
||||
|
||||
@@ -1817,7 +1817,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
sbLong.append(getName()).append(" can block ")
|
||||
.append(CardType.getPluralType(k[1]))
|
||||
.append(" as though it had reach.\r\n");
|
||||
} else if (keyword.startsWith("MayEffectFromOpeningHand")) {
|
||||
} else if (keyword.startsWith("MayEffectFromOpening")) {
|
||||
final String[] k = keyword.split(":");
|
||||
// need to get SpellDescription from Svar
|
||||
String desc = AbilityFactory.getMapParams(getSVar(k[1])).get("SpellDescription");
|
||||
|
||||
@@ -1759,6 +1759,17 @@ public class CardProperty {
|
||||
if (!card.isCommander()) {
|
||||
return false;
|
||||
}
|
||||
} else if (property.startsWith("NotedFor")) {
|
||||
final String key = property.substring("NotedFor".length());
|
||||
for (String note : sourceController.getNotesForName(key)) {
|
||||
if (note.equals("Name:" + card.getName())) {
|
||||
return true;
|
||||
}
|
||||
if (note.equals("Id:" + card.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// StringType done in CardState
|
||||
if (!card.getCurrentState().hasProperty(property, sourceController, source, spellAbility)) {
|
||||
|
||||
@@ -286,6 +286,8 @@ public class Cost implements Serializable {
|
||||
costParts.add(0, cp);
|
||||
}
|
||||
}
|
||||
|
||||
sort();
|
||||
}
|
||||
|
||||
private static CostPart parseCostPart(String parse, boolean tapCost, boolean untapCost) {
|
||||
@@ -457,6 +459,12 @@ public class Cost implements Serializable {
|
||||
return new CostReveal(splitStr[0], splitStr[1], description);
|
||||
}
|
||||
|
||||
if (parse.startsWith("RevealFromExile<")) {
|
||||
final String[] splitStr = abCostParse(parse, 3);
|
||||
final String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
return new CostReveal(splitStr[0], splitStr[1], description, ZoneType.Exile);
|
||||
}
|
||||
|
||||
if (parse.startsWith("ExiledMoveToGrave<")) {
|
||||
final String[] splitStr = abCostParse(parse, 3);
|
||||
final String description = splitStr.length > 2 ? splitStr[2] : null;
|
||||
|
||||
@@ -38,26 +38,37 @@ public class CostReveal extends CostPartWithList {
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ZoneType revealFrom = ZoneType.Hand;
|
||||
|
||||
public CostReveal(final String amount, final String type, final String description) {
|
||||
super(amount, type, description);
|
||||
}
|
||||
|
||||
public CostReveal(final String amount, final String type, final String description, final ZoneType zoneType) {
|
||||
super(amount, type, description);
|
||||
this.revealFrom = zoneType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReusable() { return true; }
|
||||
|
||||
@Override
|
||||
public boolean isRenewable() { return true; }
|
||||
|
||||
public ZoneType getRevealFrom() {
|
||||
return revealFrom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean canPay(final SpellAbility ability, final Player payer) {
|
||||
final Card source = ability.getHostCard();
|
||||
|
||||
CardCollectionView handList = payer.getCardsIn(ZoneType.Hand);
|
||||
CardCollectionView handList = payer.getCardsIn(revealFrom);
|
||||
final String type = this.getType();
|
||||
final Integer amount = this.convertAmount();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
return source.isInZone(ZoneType.Hand);
|
||||
return source.isInZone(revealFrom);
|
||||
} else if (this.getType().equals("Hand")) {
|
||||
return true;
|
||||
} else if (this.getType().equals("SameColor")) {
|
||||
@@ -100,7 +111,7 @@ public class CostReveal extends CostPartWithList {
|
||||
if (this.payCostFromSource()) {
|
||||
sb.append(this.getType());
|
||||
} else if (this.getType().equals("Hand")) {
|
||||
return ("Reveal you hand");
|
||||
return ("Reveal your hand");
|
||||
} else if (this.getType().equals("SameColor")) {
|
||||
return ("Reveal " + i + " cards from your hand that share a color");
|
||||
} else {
|
||||
@@ -115,7 +126,9 @@ public class CostReveal extends CostPartWithList {
|
||||
|
||||
sb.append(Cost.convertAmountTypeToWords(i, this.getAmount(), desc.toString()));
|
||||
}
|
||||
sb.append(" from your hand");
|
||||
|
||||
sb.append(" from your ");
|
||||
sb.append(revealFrom.getTranslatedName());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -154,4 +167,11 @@ public class CostReveal extends CostPartWithList {
|
||||
public <T> T accept(ICostVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int paymentOrder() {
|
||||
// Caller of the Untamed needs the reveal to happen before the mana cost
|
||||
if (!revealFrom.equals(ZoneType.Hand)) { return -1; }
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import forge.game.event.*;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.keyword.KeywordCollection;
|
||||
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
||||
import forge.game.keyword.KeywordInterface;
|
||||
import forge.game.keyword.KeywordsChange;
|
||||
import forge.game.mana.ManaPool;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
@@ -108,6 +109,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
private int numDrawnThisDrawStep = 0;
|
||||
private int numDiscardedThisTurn = 0;
|
||||
private int numCardsInHandStartedThisTurnWith = 0;
|
||||
private final Map<String, FCollection<String>> notes = Maps.newHashMap();
|
||||
|
||||
private boolean revolt = false;
|
||||
|
||||
@@ -1601,6 +1603,19 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
numCardsInHandStartedThisTurnWith = num;
|
||||
}
|
||||
|
||||
public void addNoteForName(String notedFor, String noted) {
|
||||
if (!notes.containsKey(notedFor)) {
|
||||
notes.put(notedFor, new FCollection<>());
|
||||
}
|
||||
notes.get(notedFor).add(noted);
|
||||
}
|
||||
public FCollection<String> getNotesForName(String notedFor) {
|
||||
if (!notes.containsKey(notedFor)) {
|
||||
notes.put(notedFor, new FCollection<>());
|
||||
}
|
||||
return notes.get(notedFor);
|
||||
}
|
||||
|
||||
public final CardCollectionView mill(final int n, final ZoneType destination,
|
||||
final boolean bottom, SpellAbility sa, CardZoneTable table) {
|
||||
final CardCollectionView lib = getCardsIn(ZoneType.Library);
|
||||
@@ -2748,6 +2763,21 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
}
|
||||
com.add(conspire);
|
||||
}
|
||||
|
||||
for (final Card c : getCardsIn(ZoneType.Library)) {
|
||||
for (KeywordInterface inst : c.getKeywords()) {
|
||||
String kw = inst.getOriginal();
|
||||
if (kw.startsWith("MayEffectFromOpeningDeck")) {
|
||||
String[] split = kw.split(":");
|
||||
final String effName = split[1];
|
||||
|
||||
final SpellAbility effect = AbilityFactory.getAbility(c.getSVar(effName), c);
|
||||
effect.setActivatingPlayer(this);
|
||||
|
||||
getController().playSpellAbilityNoStack(effect, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static DetachedCardEffect createCommanderEffect(Game game, Card commander) {
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
*/
|
||||
package forge.game.spellability;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollectionView;
|
||||
@@ -36,11 +38,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -147,6 +145,15 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
this.setPhases(PhaseType.parseRange(params.get("ConditionPhases")));
|
||||
}
|
||||
|
||||
if (params.containsKey("ConditionGameTypes")) {
|
||||
String[] gameTypeNames = params.get("ConditionGameTypes").split(",");
|
||||
List<GameType> gameTypes = Lists.newArrayList();
|
||||
for (String name : gameTypeNames) {
|
||||
gameTypes.add(GameType.smartValueOf(name));
|
||||
}
|
||||
this.setGameTypes(gameTypes);
|
||||
}
|
||||
|
||||
if (params.containsKey("ConditionChosenColor")) {
|
||||
this.setColorToCheck(params.get("ConditionChosenColor"));
|
||||
}
|
||||
@@ -322,6 +329,13 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getGameTypes().size() > 0) {
|
||||
GameType currGameType = sa.getHostCard().getGame().getRules().getGameType();
|
||||
if (!getGameTypes().contains(currGameType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getCardsInHand() != -1) {
|
||||
// Can handle Library of Alexandria, or Hellbent
|
||||
if (activator.getCardsIn(ZoneType.Hand).size() != this.getCardsInHand()) {
|
||||
|
||||
@@ -20,7 +20,9 @@ package forge.game.spellability;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollectionView;
|
||||
@@ -141,6 +143,15 @@ public class SpellAbilityRestriction extends SpellAbilityVariables {
|
||||
this.setPhases(PhaseType.parseRange(params.get("ActivationPhases")));
|
||||
}
|
||||
|
||||
if (params.containsKey("ActivationGameTypes")) {
|
||||
String[] gameTypeNames = params.get("ActivationGameTypes").split(",");
|
||||
List<GameType> gameTypes = Lists.newArrayList();
|
||||
for (String name : gameTypeNames) {
|
||||
gameTypes.add(GameType.smartValueOf(name));
|
||||
}
|
||||
this.setGameTypes(gameTypes);
|
||||
}
|
||||
|
||||
if (params.containsKey("ActivationCardsInHand")) {
|
||||
this.setActivateCardsInHand(Integer.parseInt(params.get("ActivationCardsInHand")));
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.game.GameType;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
@@ -98,6 +99,9 @@ public class SpellAbilityVariables implements Cloneable {
|
||||
/** The phases. */
|
||||
private List<PhaseType> phases = Lists.newArrayList();
|
||||
|
||||
/** The GameTypes */
|
||||
private List<GameType> gameTypes = Lists.newArrayList();
|
||||
|
||||
/** The b sorcery speed. */
|
||||
private boolean sorcerySpeed = false;
|
||||
|
||||
@@ -386,6 +390,18 @@ public class SpellAbilityVariables implements Cloneable {
|
||||
this.phases.addAll(phases);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>gameTypes</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param gameTypes
|
||||
*/
|
||||
public final void setGameTypes(final List<GameType> gameTypes) {
|
||||
this.gameTypes.clear();
|
||||
this.gameTypes.addAll(gameTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* setActivateCardsInHand.
|
||||
@@ -686,6 +702,15 @@ public class SpellAbilityVariables implements Cloneable {
|
||||
return this.phases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the game types.
|
||||
*
|
||||
* @return the phases
|
||||
*/
|
||||
public final List<GameType> getGameTypes() {
|
||||
return this.gameTypes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the present defined.
|
||||
|
||||
13
forge-gui/res/cardsfolder/a/arcane_savant.txt
Normal file
13
forge-gui/res/cardsfolder/a/arcane_savant.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Arcane Savant
|
||||
ManaCost:3 U U
|
||||
Types:Creature Human Wizard
|
||||
PT:3/3
|
||||
K:MayEffectFromOpeningDeck:DBReveal
|
||||
SVar:DBReveal:DB$ Reveal | RevealDefined$ Self | SubAbility$ DBExile | SpellDescription$ Before you shuffle your deck to start the game, you may reveal this card from your deck and exile an instant or sorcery card you drafted that isn’t in your deck.
|
||||
SVar:DBExile:DB$ ChangeZone | Origin$ Sideboard | Destination$ Exile | ChangeType$ Instant.YouOwn,Sorcery.YouOwn | ChangeNum$ 1 | Optional$ True | RememberChanged$ True | SubAbility$ DBPump | ConditionGameTypes$ Draft,QuestDraft | SelectPrompt$ Exile with Arcane Savant
|
||||
SVar:DBPump:DB$ Pump | NoteCards$ Remembered | NoteCardsFor$ ArcaneSavant | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$Cleanup | ClearRemembered$ True
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPlay | TriggerDescription$ When CARDNAME enters the battlefield, copy a card you exiled with cards named Arcane Savant. You may cast the copy without paying its mana cost.
|
||||
SVar:TrigPlay:DB$ Play | Valid$ Card.YouOwn+NotedForArcaneSavant | ValidZone$ Exile | Amount$ 1 | CopyOnce$ True | WithoutManaCost$ True | Optional$ True | CopyCard$ True | SpellDescription$ You may copy the exiled card. If you do, you may cast the copy without paying its mana cost. | SubAbility$ DBCleanup
|
||||
SVar:Picture:https://img.scryfall.com/cards/large/en/cn2/27.jpg?1517813031
|
||||
Oracle:Before you shuffle your deck to start the game, you may reveal this card from your deck and exile an instant or sorcery card you drafted that isn’t in your deck.\nWhen Arcane Savant enters the battlefield, copy a card you exiled with cards named Arcane Savant. You may cast the copy without paying its mana cost.
|
||||
13
forge-gui/res/cardsfolder/c/caller_of_the_untamed.txt
Normal file
13
forge-gui/res/cardsfolder/c/caller_of_the_untamed.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
Name:Caller of the Untamed
|
||||
ManaCost:3 G
|
||||
Types:Creature Elf Shaman
|
||||
PT:2/4
|
||||
K:MayEffectFromOpeningDeck:DBReveal
|
||||
SVar:DBReveal:DB$ Reveal | RevealDefined$ Self | SubAbility$ DBExile | SpellDescription$ Before you shuffle your deck to start the game, you may reveal this card from your deck and exile an instant or sorcery card you drafted that isn’t in your deck.
|
||||
SVar:DBExile:DB$ ChangeZone | Origin$ Sideboard | Destination$ Exile | ChangeType$ Creature.YouOwn | ChangeNum$ 1 | Optional$ True | RememberChanged$ True | SubAbility$ DBPump | ConditionGameTypes$ Draft,QuestDraft | SelectPrompt$ Exile with Caller of the Untamed
|
||||
SVar:DBPump:DB$ Pump | NoteCards$ Remembered | NoteCardsFor$ CallerOfTheUntamed | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$Cleanup | ClearRemembered$ True
|
||||
A:AB$ CopyPermanent | Cost$ RevealFromExile<1/Creature.YouOwn+NotedForCallerOfTheUntamed> X T | CostDesc$ {X}, {T} | Defined$ Revealed | References$ X | SpellDescription$ Create a token that’s a copy of a card you exiled with cards named Caller of the Untamed. X is the converted mana cost of that card. | SubAbility$ DBCleanup
|
||||
SVar:X:Revealed$CardManaCost
|
||||
SVar:Picture:https://img.scryfall.com/cards/large/en/cn2/62.jpg?1517813031
|
||||
Oracle:Before you shuffle your deck to start the game, you may reveal this card from your deck and exile a creature card you drafted that isn’t in your deck.\n{X}, {T}: Create a token that’s a copy of a card you exiled with cards named Caller of the Untamed. X is the converted mana cost of that card.
|
||||
16
forge-gui/res/cardsfolder/v/volatile_chimera.txt
Normal file
16
forge-gui/res/cardsfolder/v/volatile_chimera.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
Name:Volatile Chimera
|
||||
ManaCost:2 R
|
||||
Types:Creature Elemental Chimera
|
||||
PT:3/2
|
||||
K:MayEffectFromOpeningDeck:DBReveal
|
||||
SVar:DBReveal:DB$ Reveal | RevealDefined$ Self | SubAbility$ DBChoose | SpellDescription$ Before you shuffle your deck to start the game, you may reveal this card from your deck and exile three or more creature cards you drafted that aren't in your deck.
|
||||
SVar:DBChoose:DB$ ChooseCard | MinAmount$ 0 | Amount$ X | References$ X | Choices$ Creature.YouOwn | ChoiceTitle$ Exile with Volatile Chimera | ChoiceZone$ Sideboard | RememberChosen$ True | ConditionGameTypes$ Draft,QuestDraft | SubAbility$ DBExile
|
||||
SVar:DBExile:DB$ ChangeZone | Origin$ Sideboard | Destination$ Exile | Defined$ Remembered | ConditionCheckSVar$ Y | ConditionSVarCompare$ GE3 | SubAbility$ DBPump | References$ Y
|
||||
SVar:DBPump:DB$ Pump | NoteCards$ Remembered | NoteCardsFor$ VolatileChimera | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$Cleanup | ClearRemembered$ True
|
||||
A:AB$ ChooseCard | Cost$ 1 R | ChoiceZone$ Exile | AtRandom$ True | Choices$ Card.YouOwn+NotedForVolatileChimera | SubAbility$ DBClone | SpellDescription$ Choose a card at random you exiled with cards named Volatile Chimera. Volatile Chimera becomes a copy of that card, except it has this ability.
|
||||
SVar:DBClone:DB$ Clone | Defined$ ChosenCard | GainThisAbility$ True
|
||||
SVar:X:Count$InYourSideboard
|
||||
SVar:Y:Count$RememberedSize
|
||||
SVar:Picture:https://img.scryfall.com/cards/large/en/cn2/62.jpg?1517813031
|
||||
Oracle:Before you shuffle your deck to start the game, you may reveal this card from your deck and exile three or more creature cards you drafted that aren't in your deck.\n{1}{R}: Choose a card at random you exiled with cards named Volatile Chimera. Volatile Chimera becomes a copy of that card, except it has this ability.
|
||||
@@ -811,7 +811,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
InputSelectCardsFromList inp = null;
|
||||
if (cost.getType().equals("SameColor")) {
|
||||
final Integer num = cost.convertAmount();
|
||||
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
|
||||
CardCollectionView hand = player.getCardsIn(cost.getRevealFrom());
|
||||
final CardCollectionView hand2 = hand;
|
||||
hand = CardLists.filter(hand, new Predicate<Card>() {
|
||||
@Override
|
||||
@@ -844,7 +844,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
else {
|
||||
Integer num = cost.convertAmount();
|
||||
|
||||
CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
|
||||
CardCollectionView hand = player.getCardsIn(cost.getRevealFrom());
|
||||
hand = CardLists.getValidCards(hand, cost.getType().split(";"), player, source, ability);
|
||||
|
||||
if (num == null) {
|
||||
@@ -861,6 +861,9 @@ public class HumanCostDecision extends CostDecisionMakerBase {
|
||||
if (num == 0) {
|
||||
return PaymentDecision.number(0);
|
||||
}
|
||||
if (hand.size() == num) {
|
||||
return PaymentDecision.card(hand);
|
||||
}
|
||||
|
||||
inp = new InputSelectCardsFromList(controller, num, num, hand, ability);
|
||||
inp.setMessage("Select %d more " + cost.getDescriptiveType() + " card(s) to reveal.");
|
||||
|
||||
@@ -606,7 +606,8 @@ public class HumanPlay {
|
||||
}
|
||||
}
|
||||
else if (part instanceof CostReveal) {
|
||||
CardCollectionView list = CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), part.getType(), p, source);
|
||||
CostReveal costReveal = (CostReveal) part;
|
||||
CardCollectionView list = CardLists.getValidCards(p.getCardsIn(costReveal.getRevealFrom()), part.getType(), p, source);
|
||||
int amount = getAmountFromPartX(part, source, sourceAbility);
|
||||
boolean hasPaid = payCostPart(controller, sourceAbility, (CostPartWithList)part, amount, list, Localizer.getInstance().getMessage("lblReveal") + orString);
|
||||
if (!hasPaid) { return false; }
|
||||
|
||||
Reference in New Issue
Block a user