mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-11 16:26:22 +00:00
Compare commits
18 Commits
219e3d6182
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e70aa429b6 | ||
|
|
355722516f | ||
|
|
f08d3f6447 | ||
|
|
d7a69b72e4 | ||
|
|
bce5466c62 | ||
|
|
c90ddd1bac | ||
|
|
f12fbb1774 | ||
|
|
c3c74efbe0 | ||
|
|
5fd44c4788 | ||
|
|
539bea6b11 | ||
|
|
40e9480c2c | ||
|
|
3db276f323 | ||
|
|
c9a5fe9135 | ||
|
|
d9e356e20c | ||
|
|
843f2de272 | ||
|
|
f27eb1042f | ||
|
|
48be3406c7 | ||
|
|
50a98238d1 |
@@ -1345,9 +1345,7 @@ public class ComputerUtilMana {
|
||||
}
|
||||
}
|
||||
|
||||
if (!effect) {
|
||||
CostAdjustment.adjust(manaCost, sa, null, test);
|
||||
}
|
||||
CostAdjustment.adjust(manaCost, sa, null, test, effect);
|
||||
|
||||
if ("NumTimes".equals(sa.getParam("Announce"))) { // e.g. the Adversary cycle
|
||||
ManaCost mkCost = sa.getPayCosts().getTotalMana();
|
||||
@@ -1773,15 +1771,18 @@ public class ComputerUtilMana {
|
||||
|
||||
/**
|
||||
* Matches list of creatures to shards in mana cost for convoking.
|
||||
* @param cost cost of convoked ability
|
||||
* @param list creatures to be evaluated
|
||||
* @param improvise
|
||||
*
|
||||
* @param cost cost of convoked ability
|
||||
* @param list creatures to be evaluated
|
||||
* @param artifacts
|
||||
* @param creatures
|
||||
* @return map between creatures and shards to convoke
|
||||
*/
|
||||
public static Map<Card, ManaCostShard> getConvokeOrImproviseFromList(final ManaCost cost, List<Card> list, boolean improvise) {
|
||||
public static Map<Card, ManaCostShard> getConvokeOrImproviseFromList(final ManaCost cost, List<Card> list, boolean artifacts, boolean creatures) {
|
||||
final Map<Card, ManaCostShard> convoke = new HashMap<>();
|
||||
Card convoked = null;
|
||||
if (!improvise) {
|
||||
if (creatures && !artifacts) {
|
||||
// Run for convoke but not improvise or waterbending
|
||||
for (ManaCostShard toPay : cost) {
|
||||
if (toPay.isSnow() || toPay.isColorless()) {
|
||||
continue;
|
||||
|
||||
@@ -1382,7 +1382,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCards, boolean improvise) {
|
||||
public Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCards, boolean artifacts, boolean creatures, Integer maxReduction) {
|
||||
final Player ai = sa.getActivatingPlayer();
|
||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||
//Filter out mana sources that will interfere with payManaCost()
|
||||
@@ -1390,9 +1390,10 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
// Filter out creatures if AI hasn't attacked yet
|
||||
if (ph.isPlayerTurn(ai) && ph.getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)) {
|
||||
if (improvise) {
|
||||
if (!creatures) {
|
||||
untapped = CardLists.filter(untapped, c -> !c.isCreature());
|
||||
} else {
|
||||
// TODO AI needs to learn how to use Convoke or Waterbend
|
||||
return new HashMap<>();
|
||||
}
|
||||
}
|
||||
@@ -1406,13 +1407,16 @@ public class PlayerControllerAi extends PlayerController {
|
||||
if (!ai.getGame().getStack().isEmpty()) {
|
||||
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), null);
|
||||
for (Card c : blockers) {
|
||||
if (objects.contains(c) && (!improvise || c.isArtifact())) {
|
||||
if (objects.contains(c) && (creatures || c.isArtifact())) {
|
||||
untapped.add(c);
|
||||
}
|
||||
if (maxReduction != null && untapped.size() >= maxReduction) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ComputerUtilMana.getConvokeOrImproviseFromList(manaCost, untapped, improvise);
|
||||
return ComputerUtilMana.getConvokeOrImproviseFromList(manaCost, untapped, artifacts, creatures);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.AiAbilityDecision;
|
||||
import forge.ai.AiPlayDecision;
|
||||
import forge.ai.*;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
|
||||
@@ -776,7 +776,7 @@ public class StaticData {
|
||||
Queue<String> TOKEN_Q = new ConcurrentLinkedQueue<>();
|
||||
boolean nifHeader = false;
|
||||
boolean cniHeader = false;
|
||||
final Pattern funnyCardCollectorNumberPattern = Pattern.compile("^F\\d+");
|
||||
final Pattern funnyCardCollectorNumberPattern = Pattern.compile("^F★?\\d+★?");
|
||||
for (CardEdition e : editions) {
|
||||
if (CardEdition.Type.FUNNY.equals(e.getType()))
|
||||
continue;
|
||||
|
||||
@@ -75,11 +75,13 @@ public class Game {
|
||||
|
||||
private List<Card> activePlanes = null;
|
||||
|
||||
public final Phase cleanup;
|
||||
public final Phase endOfCombat;
|
||||
public final Phase endOfTurn;
|
||||
public final Untap untap;
|
||||
public final Phase upkeep;
|
||||
public final Phase beginOfCombat;
|
||||
public final Phase endOfCombat;
|
||||
public final Phase endOfTurn;
|
||||
public final Phase cleanup;
|
||||
|
||||
// to execute commands for "current" phase each time state based action is checked
|
||||
public final List<GameCommand> sbaCheckedCommandList;
|
||||
public final MagicStack stack;
|
||||
@@ -363,9 +365,10 @@ public class Game {
|
||||
|
||||
untap = new Untap(this);
|
||||
upkeep = new Phase(PhaseType.UPKEEP);
|
||||
cleanup = new Phase(PhaseType.CLEANUP);
|
||||
beginOfCombat = new Phase(PhaseType.COMBAT_BEGIN);
|
||||
endOfCombat = new Phase(PhaseType.COMBAT_END);
|
||||
endOfTurn = new Phase(PhaseType.END_OF_TURN);
|
||||
cleanup = new Phase(PhaseType.CLEANUP);
|
||||
|
||||
sbaCheckedCommandList = new ArrayList<>();
|
||||
|
||||
@@ -428,6 +431,9 @@ public class Game {
|
||||
public final Phase getUpkeep() {
|
||||
return upkeep;
|
||||
}
|
||||
public final Phase getBeginOfCombat() {
|
||||
return beginOfCombat;
|
||||
}
|
||||
public final Phase getEndOfCombat() {
|
||||
return endOfCombat;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import forge.game.*;
|
||||
import forge.game.ability.AbilityFactory.AbilityRecordType;
|
||||
import forge.game.card.*;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostAdjustment;
|
||||
import forge.game.cost.IndividualCostPaymentInstance;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.keyword.KeywordInterface;
|
||||
@@ -1527,6 +1528,7 @@ public class AbilityUtils {
|
||||
else {
|
||||
cost = new Cost(unlessCost, true);
|
||||
}
|
||||
cost = CostAdjustment.adjust(cost, sa, true);
|
||||
return cost;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
|
||||
|
||||
sb.append(Lang.joinHomogenous(getTargetPlayers(sa)));
|
||||
|
||||
sb.append("chooses a source.");
|
||||
sb.append(" chooses a source.");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package forge.game.ability.effects;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import forge.GameCommand;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
@@ -28,10 +27,11 @@ public class ControlPlayerEffect extends SpellAbilityEffect {
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Player controller = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Controller"), sa).get(0);
|
||||
final Game game = controller.getGame();
|
||||
final boolean combat = sa.hasParam("Combat");
|
||||
|
||||
for (final Player pTarget: getTargetPlayers(sa)) {
|
||||
// before next untap gain control
|
||||
game.getCleanup().addUntil(pTarget, (GameCommand) () -> {
|
||||
(combat ? game.getBeginOfCombat() : game.getCleanup()).addUntil(pTarget, () -> {
|
||||
// CR 800.4b
|
||||
if (!controller.isInGame()) {
|
||||
return;
|
||||
@@ -41,7 +41,7 @@ public class ControlPlayerEffect extends SpellAbilityEffect {
|
||||
pTarget.addController(ts, controller);
|
||||
|
||||
// after following cleanup release control
|
||||
game.getCleanup().addUntil((GameCommand) () -> pTarget.removeController(ts));
|
||||
(combat ? game.getEndOfCombat() : game.getCleanup()).addUntil(() -> pTarget.removeController(ts));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
||||
// stores the card traits created by static abilities
|
||||
private final Table<StaticAbility, String, SpellAbility> storedSpellAbility = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, String, Trigger> storedTrigger = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, SpellAbility, SpellAbility> storedAbilityForTrigger = HashBasedTable.create();
|
||||
private final Table<StaticAbility, String, ReplacementEffect> storedReplacementEffect = TreeBasedTable.create();
|
||||
private final Table<StaticAbility, String, StaticAbility> storedStaticAbility = TreeBasedTable.create();
|
||||
|
||||
@@ -4974,7 +4975,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars, ITr
|
||||
String str = trig.toString() + trig.getId();
|
||||
Trigger result = storedTrigger.get(stAb, str);
|
||||
if (result == null) {
|
||||
result = trig.copy(this, false);
|
||||
SpellAbility ab = null;
|
||||
if (trig.hasParam("Execute") && trig.getOverridingAbility() != null) {
|
||||
ab = storedAbilityForTrigger.get(stAb, trig.getOverridingAbility());
|
||||
if (ab == null) {
|
||||
ab = trig.getOverridingAbility().copy(this, false);
|
||||
storedAbilityForTrigger.put(stAb, trig.getOverridingAbility(), ab);
|
||||
}
|
||||
}
|
||||
result = trig.copy(this, false, false, ab);
|
||||
storedTrigger.put(stAb, str, result);
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -79,6 +79,7 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
|
||||
private FCollection<StaticAbility> staticAbilities = new FCollection<>();
|
||||
private String imageKey = "";
|
||||
private Map<String, String> sVars = Maps.newTreeMap();
|
||||
private Map<String, SpellAbility> abilityForTrigger = Maps.newHashMap();
|
||||
|
||||
private KeywordCollection cachedKeywords = new KeywordCollection();
|
||||
|
||||
@@ -732,6 +733,11 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
|
||||
setFlavorName(source.getFlavorName());
|
||||
setSVars(source.getSVars());
|
||||
|
||||
abilityForTrigger.clear();
|
||||
for (Map.Entry<String, SpellAbility> e : source.abilityForTrigger.entrySet()) {
|
||||
abilityForTrigger.put(e.getKey(), e.getValue().copy(card, lki));
|
||||
}
|
||||
|
||||
abilities.clear();
|
||||
for (SpellAbility sa : source.abilities) {
|
||||
if (sa.isIntrinsic()) {
|
||||
@@ -758,7 +764,7 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
|
||||
continue;
|
||||
}
|
||||
if (tr.isIntrinsic()) {
|
||||
triggers.add(tr.copy(card, lki));
|
||||
triggers.add(tr.copy(card, lki, false, tr.hasParam("Execute") ? abilityForTrigger.get(tr.getParam("Execute")) : null));
|
||||
}
|
||||
}
|
||||
ReplacementEffect runRE = null;
|
||||
@@ -951,6 +957,10 @@ public class CardState implements GameObject, IHasSVars, ITranslatable {
|
||||
return cloakUp;
|
||||
}
|
||||
|
||||
public SpellAbility getAbilityForTrigger(String svar) {
|
||||
return abilityForTrigger.computeIfAbsent(svar, s -> AbilityFactory.getAbility(getCard(), s, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTranslationKey() {
|
||||
String displayName = flavorName == null ? name : flavorName;
|
||||
|
||||
@@ -188,6 +188,15 @@ public class Cost implements Serializable {
|
||||
return this.isAbility;
|
||||
}
|
||||
|
||||
public final String getMaxWaterbend() {
|
||||
for (CostPart cp : this.costParts) {
|
||||
if (cp instanceof CostPartMana) {
|
||||
return ((CostPartMana) cp).getMaxWaterbend();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Cost() {
|
||||
|
||||
}
|
||||
@@ -564,6 +573,11 @@ public class Cost implements Serializable {
|
||||
return new CostRevealChosen(splitStr[0], splitStr.length > 1 ? splitStr[1] : null);
|
||||
}
|
||||
|
||||
if (parse.startsWith("Waterbend<")) {
|
||||
final String[] splitStr = abCostParse(parse, 1);
|
||||
return new CostWaterbend(splitStr[0]);
|
||||
}
|
||||
|
||||
if (parse.equals("Forage")) {
|
||||
return new CostForage();
|
||||
}
|
||||
@@ -973,6 +987,7 @@ public class Cost implements Serializable {
|
||||
} else {
|
||||
costParts.add(0, new CostPartMana(manaCost.toManaCost(), null));
|
||||
}
|
||||
getCostMana().setMaxWaterbend(mPart.getMaxWaterbend());
|
||||
} else if (part instanceof CostPutCounter || (mergeAdditional && // below usually not desired because they're from different causes
|
||||
(part instanceof CostDiscard || part instanceof CostDraw ||
|
||||
part instanceof CostAddMana || part instanceof CostPayLife ||
|
||||
|
||||
@@ -31,11 +31,13 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class CostAdjustment {
|
||||
|
||||
public static Cost adjust(final Cost cost, final SpellAbility sa, boolean effect) {
|
||||
if (sa.isTrigger() || cost == null || effect) {
|
||||
sa.setMaxWaterbend(cost);
|
||||
return cost;
|
||||
}
|
||||
|
||||
@@ -99,6 +101,9 @@ public class CostAdjustment {
|
||||
host.setState(CardStateName.Original, false);
|
||||
host.setFaceDown(false);
|
||||
}
|
||||
|
||||
sa.setMaxWaterbend(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -171,21 +176,22 @@ public class CostAdjustment {
|
||||
|
||||
// If cardsToDelveOut is null, will immediately exile the delved cards and remember them on the host card.
|
||||
// Otherwise, will return them in cardsToDelveOut and the caller is responsible for doing the above.
|
||||
public static boolean adjust(ManaCostBeingPaid cost, final SpellAbility sa, CardCollection cardsToDelveOut, boolean test) {
|
||||
if (sa.isTrigger() || sa.isReplacementAbility()) {
|
||||
public static boolean adjust(ManaCostBeingPaid cost, final SpellAbility sa, CardCollection cardsToDelveOut, boolean test, boolean effect) {
|
||||
if (effect) {
|
||||
adjustCostByWaterbend(cost, sa, test);
|
||||
}
|
||||
if (effect || sa.isTrigger() || sa.isReplacementAbility()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Game game = sa.getActivatingPlayer().getGame();
|
||||
final Card originalCard = sa.getHostCard();
|
||||
boolean isStateChangeToFaceDown = false;
|
||||
|
||||
if (sa.isSpell()) {
|
||||
if (sa.isCastFaceDown() && !originalCard.isFaceDown()) {
|
||||
// Turn face down to apply cost modifiers correctly
|
||||
originalCard.turnFaceDownNoUpdate();
|
||||
isStateChangeToFaceDown = true;
|
||||
}
|
||||
boolean isStateChangeToFaceDown = false;
|
||||
if (sa.isSpell() && sa.isCastFaceDown() && !originalCard.isFaceDown()) {
|
||||
// Turn face down to apply cost modifiers correctly
|
||||
originalCard.turnFaceDownNoUpdate();
|
||||
isStateChangeToFaceDown = true;
|
||||
}
|
||||
|
||||
CardCollection cardsOnBattlefield = new CardCollection(game.getCardsIn(ZoneType.Battlefield));
|
||||
@@ -278,17 +284,19 @@ public class CostAdjustment {
|
||||
table.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
if (sa.getHostCard().hasKeyword(Keyword.CONVOKE)) {
|
||||
adjustCostByConvokeOrImprovise(cost, sa, false, test);
|
||||
adjustCostByConvokeOrImprovise(cost, sa, false, true, test);
|
||||
}
|
||||
if (sa.getHostCard().hasKeyword(Keyword.IMPROVISE)) {
|
||||
adjustCostByConvokeOrImprovise(cost, sa, true, test);
|
||||
adjustCostByConvokeOrImprovise(cost, sa, true, false, test);
|
||||
}
|
||||
} // isSpell
|
||||
|
||||
if (sa.hasParam("TapCreaturesForMana")) {
|
||||
adjustCostByConvokeOrImprovise(cost, sa, false, test);
|
||||
adjustCostByConvokeOrImprovise(cost, sa, false, true, test);
|
||||
}
|
||||
|
||||
adjustCostByWaterbend(cost, sa, test);
|
||||
|
||||
// Reset card state (if changed)
|
||||
if (isStateChangeToFaceDown) {
|
||||
originalCard.setFaceDown(false);
|
||||
@@ -299,6 +307,13 @@ public class CostAdjustment {
|
||||
}
|
||||
// GetSpellCostChange
|
||||
|
||||
private static void adjustCostByWaterbend(ManaCostBeingPaid cost, SpellAbility sa, boolean test) {
|
||||
Integer maxWaterbend = sa.getMaxWaterbend();
|
||||
if (maxWaterbend != null && maxWaterbend > 0) {
|
||||
adjustCostByConvokeOrImprovise(cost, sa, true, true, test);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean adjustCostByAssist(ManaCostBeingPaid cost, final SpellAbility sa, boolean test) {
|
||||
// 702.132a Assist is a static ability that modifies the rules of paying for the spell with assist (see rules 601.2g-h).
|
||||
// If the total cost to cast a spell with assist includes a generic mana component, before you activate mana abilities while casting it, you may choose another player.
|
||||
@@ -321,27 +336,33 @@ public class CostAdjustment {
|
||||
return assistant.getController().helpPayForAssistSpell(cost, sa, genericLeft, requestedAmount);
|
||||
}
|
||||
|
||||
private static void adjustCostByConvokeOrImprovise(ManaCostBeingPaid cost, final SpellAbility sa, boolean improvise, boolean test) {
|
||||
if (!improvise) {
|
||||
private static void adjustCostByConvokeOrImprovise(ManaCostBeingPaid cost, final SpellAbility sa, boolean artifacts, boolean creatures, boolean test) {
|
||||
if (creatures && !artifacts) {
|
||||
sa.clearTappedForConvoke();
|
||||
}
|
||||
|
||||
final Player activator = sa.getActivatingPlayer();
|
||||
CardCollectionView untappedCards = CardLists.filter(activator.getCardsIn(ZoneType.Battlefield),
|
||||
CardPredicates.CAN_TAP);
|
||||
if (improvise) {
|
||||
|
||||
Integer maxReduction = null;
|
||||
if (artifacts && creatures) {
|
||||
maxReduction = sa.getMaxWaterbend();
|
||||
Predicate <Card> isArtifactOrCreature = card -> card.isArtifact() || card.isCreature();
|
||||
untappedCards = CardLists.filter(untappedCards, isArtifactOrCreature);
|
||||
} else if (artifacts) {
|
||||
untappedCards = CardLists.filter(untappedCards, CardPredicates.ARTIFACTS);
|
||||
} else {
|
||||
untappedCards = CardLists.filter(untappedCards, CardPredicates.CREATURES);
|
||||
}
|
||||
|
||||
Map<Card, ManaCostShard> convokedCards = activator.getController().chooseCardsForConvokeOrImprovise(sa,
|
||||
cost.toManaCost(), untappedCards, improvise);
|
||||
cost.toManaCost(), untappedCards, artifacts, creatures, maxReduction);
|
||||
|
||||
CardCollection tapped = new CardCollection();
|
||||
for (final Entry<Card, ManaCostShard> conv : convokedCards.entrySet()) {
|
||||
Card c = conv.getKey();
|
||||
if (!improvise) {
|
||||
if (creatures && !artifacts) {
|
||||
sa.addTappedForConvoke(c);
|
||||
}
|
||||
cost.decreaseShard(conv.getValue(), 1);
|
||||
|
||||
@@ -39,6 +39,8 @@ public class CostPartMana extends CostPart {
|
||||
private boolean isEnchantedCreatureCost = false;
|
||||
private boolean isCostPayAnyNumberOfTimes = false;
|
||||
|
||||
protected String maxWaterbend;
|
||||
|
||||
public int paymentOrder() { return shouldPayLast() ? 200 : 0; }
|
||||
|
||||
public boolean shouldPayLast() {
|
||||
@@ -63,6 +65,13 @@ public class CostPartMana extends CostPart {
|
||||
this.isEnchantedCreatureCost = enchantedCreatureCost;
|
||||
}
|
||||
|
||||
public String getMaxWaterbend() {
|
||||
return maxWaterbend;
|
||||
}
|
||||
public void setMaxWaterbend(String max) {
|
||||
maxWaterbend = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mana.
|
||||
*
|
||||
@@ -101,7 +110,7 @@ public class CostPartMana extends CostPart {
|
||||
public boolean isUndoable() { return true; }
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
public String toString() {
|
||||
return cost.toString();
|
||||
}
|
||||
|
||||
|
||||
18
forge-game/src/main/java/forge/game/cost/CostWaterbend.java
Normal file
18
forge-game/src/main/java/forge/game/cost/CostWaterbend.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package forge.game.cost;
|
||||
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaCostParser;
|
||||
|
||||
public class CostWaterbend extends CostPartMana {
|
||||
|
||||
public CostWaterbend(final String mana) {
|
||||
super(new ManaCost(new ManaCostParser(mana)), null);
|
||||
|
||||
maxWaterbend = mana;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
return "Waterbend " + getMana().toString();
|
||||
}
|
||||
}
|
||||
@@ -297,6 +297,7 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
case COMBAT_BEGIN:
|
||||
nCombatsThisTurn++;
|
||||
combat = new Combat(playerTurn);
|
||||
game.getBeginOfCombat().executeUntil(playerTurn);
|
||||
//PhaseUtil.verifyCombat();
|
||||
break;
|
||||
|
||||
@@ -756,7 +757,6 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
}
|
||||
}
|
||||
}
|
||||
// fire blockers declared trigger
|
||||
final Map<AbilityKey, Object> bdRunParams = AbilityKey.newMap();
|
||||
bdRunParams.put(AbilityKey.Blockers, declaredBlockers);
|
||||
bdRunParams.put(AbilityKey.Attackers, blockedAttackers);
|
||||
@@ -768,7 +768,6 @@ public class PhaseHandler implements java.io.Serializable {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Run triggers
|
||||
final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||
runParams.put(AbilityKey.Blocker, c1);
|
||||
runParams.put(AbilityKey.Attackers, combat.getAttackersBlockedBy(c1));
|
||||
|
||||
@@ -202,7 +202,7 @@ public abstract class PlayerController {
|
||||
public abstract CardCollection chooseCardsToDiscardToMaximumHandSize(int numDiscard);
|
||||
|
||||
public abstract CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave);
|
||||
public abstract Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCards, boolean improvise);
|
||||
public abstract Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(SpellAbility sa, ManaCost manaCost, CardCollectionView untappedCards, boolean artifacts, boolean creatures, Integer maxReduction);
|
||||
public abstract List<Card> chooseCardsForSplice(SpellAbility sa, List<Card> cards);
|
||||
|
||||
public abstract CardCollectionView chooseCardsToRevealFromHand(int min, int max, CardCollectionView valid);
|
||||
|
||||
@@ -144,6 +144,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
private final Supplier<CardCollection> tappedForConvoke = Suppliers.memoize(CardCollection::new);
|
||||
private Card sacrificedAsOffering;
|
||||
private Card sacrificedAsEmerge;
|
||||
private Integer maxWaterbend;
|
||||
|
||||
private AbilityManaPart manaPart;
|
||||
|
||||
@@ -2692,4 +2693,14 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getMaxWaterbend() {
|
||||
return maxWaterbend;
|
||||
}
|
||||
public void setMaxWaterbend(Cost cost) {
|
||||
if (cost == null || cost.getMaxWaterbend() == null) {
|
||||
return;
|
||||
}
|
||||
maxWaterbend = AbilityUtils.calculateAmount(getHostCard(), cost.getMaxWaterbend(), this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,14 +544,19 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
}
|
||||
|
||||
public final Trigger copy(Card newHost, boolean lki) {
|
||||
return copy(newHost, lki, false);
|
||||
return copy(newHost, lki, false, null);
|
||||
}
|
||||
public final Trigger copy(Card newHost, boolean lki, boolean keepTextChanges) {
|
||||
return copy(newHost, lki, keepTextChanges, null);
|
||||
}
|
||||
public final Trigger copy(Card newHost, boolean lki, boolean keepTextChanges, SpellAbility spellAbility) {
|
||||
final Trigger copy = (Trigger) clone();
|
||||
|
||||
copyHelper(copy, newHost, lki || keepTextChanges);
|
||||
|
||||
if (getOverridingAbility() != null) {
|
||||
if (spellAbility != null) {
|
||||
copy.setOverridingAbility(spellAbility);
|
||||
} else if (getOverridingAbility() != null) {
|
||||
copy.setOverridingAbility(getOverridingAbility().copy(newHost, lki));
|
||||
}
|
||||
|
||||
@@ -611,7 +616,11 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
public SpellAbility ensureAbility(final IHasSVars sVarHolder) {
|
||||
SpellAbility sa = getOverridingAbility();
|
||||
if (sa == null && hasParam("Execute")) {
|
||||
sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute"), sVarHolder);
|
||||
if (this.isIntrinsic() && sVarHolder instanceof CardState state) {
|
||||
sa = state.getAbilityForTrigger(getParam("Execute"));
|
||||
} else {
|
||||
sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute"), sVarHolder);
|
||||
}
|
||||
setOverridingAbility(sa);
|
||||
}
|
||||
return sa;
|
||||
|
||||
@@ -428,6 +428,10 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
game.getTriggerHandler().runTrigger(TriggerType.AbilityCast, runParams, true);
|
||||
}
|
||||
|
||||
if (sp.getMaxWaterbend() != null) {
|
||||
activator.triggerElementalBend(TriggerType.Waterbend);
|
||||
}
|
||||
|
||||
// Run Cycled triggers
|
||||
if (sp.isCycling()) {
|
||||
activator.addCycled(sp);
|
||||
|
||||
@@ -690,7 +690,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
|
||||
@Override
|
||||
public Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(SpellAbility sa, ManaCost manaCost,
|
||||
CardCollectionView untappedCards, boolean improvise) {
|
||||
CardCollectionView untappedCards, boolean artifacts, boolean creatures, Integer maxReduction) {
|
||||
// TODO: AI to choose a creature to tap would go here
|
||||
// Probably along with deciding how many creatures to tap
|
||||
return new HashMap<>();
|
||||
|
||||
@@ -450,7 +450,9 @@ public class EnemySprite extends CharacterSprite implements Steerable<Vector2> {
|
||||
.filter(paperCard -> !paperCard.isVeryBasicLand())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (paperCardList.size() < 6) {
|
||||
int uniqueRules = paperCardList.stream().map(PaperCard::getRules).collect(Collectors.toSet()).size();
|
||||
|
||||
if (uniqueRules < 4 || paperCardList.size() < 10) {
|
||||
// Player trying to cheese doppleganger and farm cards. Sorry, the fun police have arrived
|
||||
// Static rewards of 199 GP, 9 Shards, and 1 Cheese Stands Alone
|
||||
rewards.add(new Reward(199));
|
||||
@@ -466,7 +468,7 @@ public class EnemySprite extends CharacterSprite implements Steerable<Vector2> {
|
||||
if (AdventurePlayer.current().isFantasyMode()) {
|
||||
//random uncommons from deck
|
||||
List<PaperCard> uncommonCards = paperCardList.stream()
|
||||
.filter(paperCard -> CardRarity.Uncommon.equals(paperCard.getRarity()) || CardRarity.Special.equals(paperCard.getRarity()))
|
||||
.filter(paperCard -> paperCard.getRarity() == CardRarity.Uncommon || paperCard.getRarity() == CardRarity.Special)
|
||||
.collect(Collectors.toList());
|
||||
if (!uncommonCards.isEmpty()) {
|
||||
rewards.add(new Reward(Aggregates.random(uncommonCards)));
|
||||
@@ -474,7 +476,7 @@ public class EnemySprite extends CharacterSprite implements Steerable<Vector2> {
|
||||
}
|
||||
//random commons from deck
|
||||
List<PaperCard> commmonCards = paperCardList.stream()
|
||||
.filter(paperCard -> CardRarity.Common.equals(paperCard.getRarity()))
|
||||
.filter(paperCard -> paperCard.getRarity() == CardRarity.Common)
|
||||
.collect(Collectors.toList());
|
||||
if (!commmonCards.isEmpty()) {
|
||||
rewards.add(new Reward(Aggregates.random(commmonCards)));
|
||||
@@ -483,7 +485,7 @@ public class EnemySprite extends CharacterSprite implements Steerable<Vector2> {
|
||||
}
|
||||
//random rare from deck
|
||||
List<PaperCard> rareCards = paperCardList.stream()
|
||||
.filter(paperCard -> CardRarity.Rare.equals(paperCard.getRarity()) || CardRarity.MythicRare.equals(paperCard.getRarity()))
|
||||
.filter(paperCard -> paperCard.getRarity() == CardRarity.Rare || paperCard.getRarity() == CardRarity.MythicRare)
|
||||
.collect(Collectors.toList());
|
||||
if (!rareCards.isEmpty()) {
|
||||
rewards.add(new Reward(Aggregates.random(rareCards)));
|
||||
|
||||
@@ -175,17 +175,17 @@ public class AdventureEventData implements Serializable {
|
||||
private static final Predicate<CardEdition> filterStandard = FModel.getFormats().getStandard().editionLegalPredicate;
|
||||
|
||||
public static Predicate<CardEdition> selectSetPool() {
|
||||
// Should we negate any of these to avoid overlap?
|
||||
final int rollD100 = MyRandom.getRandom().nextInt(100);
|
||||
Predicate<CardEdition> rolledFilter;
|
||||
if (rollD100 < 30) {
|
||||
rolledFilter = filterStandard;
|
||||
} else if (rollD100 < 60) {
|
||||
rolledFilter = filterPioneer;
|
||||
// Remove standard from older pools because its representation is already inflated.
|
||||
rolledFilter = filterPioneer.and(filterStandard.negate());
|
||||
} else if (rollD100 < 80) {
|
||||
rolledFilter = filterModern;
|
||||
rolledFilter = filterModern.and(filterStandard.negate());
|
||||
} else {
|
||||
rolledFilter = filterVintage;
|
||||
rolledFilter = filterVintage.and(filterStandard.negate());
|
||||
}
|
||||
return rolledFilter;
|
||||
}
|
||||
@@ -195,21 +195,33 @@ public class AdventureEventData implements Serializable {
|
||||
private static CardBlock pickWeightedCardBlock() {
|
||||
CardEdition.Collection editions = FModel.getMagicDb().getEditions();
|
||||
ConfigData configData = Config.instance().getConfigData();
|
||||
Predicate<CardEdition> filter = CardEdition.Predicates.CAN_MAKE_BOOSTER.and(selectSetPool());
|
||||
Predicate<CardEdition> filter = CardEdition.Predicates.CAN_MAKE_BOOSTER;
|
||||
|
||||
if(configData.restrictedEvents != null) {
|
||||
//Temporary restriction until rewards are more diverse - don't want to award restricted cards so these editions need different rewards added.
|
||||
//Also includes sets that use conspiracy or commander drafts.
|
||||
Set<String> restrictedEvents = Set.of(configData.restrictedEvents);
|
||||
filter = filter.and((q) -> !restrictedEvents.contains(q.getCode()));
|
||||
if(configData.allowedEvents != null && configData.allowedEvents.length > 0) {
|
||||
Set<String> allowedEvents = Set.of(configData.allowedEvents);
|
||||
filter = filter.and(q -> allowedEvents.contains(q.getCode()));
|
||||
}
|
||||
if (configData.allowedEditions != null) {
|
||||
Set<String> allowed = Set.of(configData.allowedEditions);
|
||||
filter = filter.and(q -> allowed.contains(q.getCode()));
|
||||
} else {
|
||||
List<String> restrictedList = Arrays.asList(configData.restrictedEditions);
|
||||
Set<String> restricted = new HashSet<>(restrictedList); //Would use Set.of but that throws an error if there's any duplicates, and users edit these lists all the time.
|
||||
filter = filter.and(q -> !restricted.contains(q.getCode()));
|
||||
else
|
||||
{
|
||||
//The whitelist beats all other filters.
|
||||
if(configData.restrictedEvents != null) {
|
||||
//Temporary restriction until rewards are more diverse - don't want to award restricted cards so these editions need different rewards added.
|
||||
//Also includes sets that use conspiracy or commander drafts.
|
||||
Set<String> restrictedEvents = Set.of(configData.restrictedEvents);
|
||||
filter = filter.and((q) -> !restrictedEvents.contains(q.getCode()));
|
||||
}
|
||||
if (configData.allowedEditions != null && configData.allowedEditions.length > 0) {
|
||||
Set<String> allowed = Set.of(configData.allowedEditions);
|
||||
filter = filter.and(q -> allowed.contains(q.getCode()));
|
||||
} else if(configData.restrictedEditions != null) {
|
||||
List<String> restrictedList = Arrays.asList(configData.restrictedEditions);
|
||||
Set<String> restricted = new HashSet<>(restrictedList); //Would use Set.of but that throws an error if there's any duplicates, and users edit these lists all the time.
|
||||
filter = filter.and(q -> !restricted.contains(q.getCode()));
|
||||
}
|
||||
|
||||
Predicate<CardEdition> setPoolFilter = selectSetPool();
|
||||
if(editions.stream().anyMatch(setPoolFilter))
|
||||
filter = filter.and(setPoolFilter);
|
||||
}
|
||||
|
||||
List<CardEdition> allEditions = new ArrayList<>();
|
||||
|
||||
@@ -24,5 +24,6 @@ public class ConfigData {
|
||||
public String[] restrictedEditions;
|
||||
public String[] allowedEditions;
|
||||
public String[] restrictedEvents;
|
||||
public String[] allowedEvents;
|
||||
public String[] allowedJumpstart;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Agent Venom
|
||||
Variant:UniversesWithin:FlavorName:Rhilex the Accursed
|
||||
ManaCost:2 B
|
||||
Types:Legendary Creature Symbiote Soldier Hero
|
||||
PT:2/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Alien Symbiosis
|
||||
Variant:UniversesWithin:FlavorName:Aggressive Symbiosis
|
||||
ManaCost:1 B
|
||||
Types:Enchantment Aura
|
||||
K:Enchant:Creature
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Amazing Acrobatics
|
||||
Variant:UniversesWithin:FlavorName:Drix Interception
|
||||
ManaCost:1 U U
|
||||
Types:Instant
|
||||
A:SP$ Charm | MinCharmNum$ 1 | CharmNum$ 2 | Choices$ DBCounter,DBTap
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Angry Rabble
|
||||
Variant:UniversesWithin:FlavorName:Galvanized Workforce
|
||||
ManaCost:1 R
|
||||
Types:Creature Human Citizen
|
||||
PT:2/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Anti-Venom, Horrifying Healer
|
||||
Variant:UniversesWithin:FlavorName:Verilax the Havenskin
|
||||
ManaCost:W W W W W
|
||||
Types:Legendary Creature Symbiote Hero
|
||||
PT:5/5
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:U
|
||||
Types:Enchantment Aura
|
||||
K:Enchant:Creature
|
||||
SVar:AttachAILogic:Curse
|
||||
R:Event$ Untap | ActiveZones$ Battlefield | ValidCard$ Creature.EnchantedBy | ValidStepTurnToController$ You | Layer$ CantHappen | Description$ Enchanted creature doesn't untap during its controller's untap step. At the beginning of the upkeep of enchanted creature's controller, that player may discard a card at random. If the player does, untap that creature.
|
||||
R:Event$ Untap | ActiveZones$ Battlefield | ValidCard$ Creature.EnchantedBy | ValidStepTurnToController$ You | Layer$ CantHappen | Description$ Enchanted creature doesn't untap during its controller's untap step.
|
||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player.EnchantedController | TriggerZones$ Battlefield | OptionalDecider$ EnchantedController | Execute$ ApathyDiscard | TriggerDescription$ At the beginning of the upkeep of enchanted creature's controller, that player may discard a card at random. If the player does, untap that creature.
|
||||
SVar:ApathyDiscard:DB$ Discard | Defined$ TriggeredPlayer | Mode$ Random | RememberDiscarded$ True | SubAbility$ ApathyUntap
|
||||
SVar:ApathyUntap:DB$ Untap | Defined$ Enchanted | SpellDescription$ Untap enchanted creature | ConditionCheckSVar$ X | ConditionSVarCompare$ EQ1 | SubAbility$ DBCleanup
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Arachne, Psionic Weaver
|
||||
Variant:UniversesWithin:FlavorName:Yera and Oski, Weaver and Guide
|
||||
ManaCost:2 W
|
||||
Types:Legendary Creature Spider Human Hero
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Araña, Heart of the Spider
|
||||
Variant:UniversesWithin:FlavorName:Gloria, the Great Armorer
|
||||
ManaCost:1 R W
|
||||
Types:Legendary Creature Spider Human Hero
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Aunt May
|
||||
Variant:UniversesWithin:FlavorName:Zora, Spider Fancier
|
||||
ManaCost:W
|
||||
Types:Legendary Creature Human Citizen
|
||||
PT:0/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Bagel and Schmear
|
||||
Variant:UniversesWithin:FlavorName:Perfected Pastry
|
||||
ManaCost:1
|
||||
Types:Artifact Food
|
||||
A:AB$ PutCounter | PrecostDesc$ Share — | Cost$ W T Sac<1/CARDNAME> | TargetMin$ 0 | TargetMax$ 1 | ValidTgts$ Creature | TgtPrompt$ Select target creature | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBDraw | SorcerySpeed$ True | SpellDescription$ Put a +1/+1 counter on up to one target creature. Draw a card. Activate only as a sorcery.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Beetle, Legacy Criminal
|
||||
Variant:UniversesWithin:FlavorName:Arala, Hedron Scaler
|
||||
ManaCost:3 U
|
||||
Types:Legendary Creature Human Rogue Villain
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Behold the Sinister Six!
|
||||
Variant:UniversesWithin:FlavorName:Hex of Undeath
|
||||
ManaCost:6 B
|
||||
Types:Sorcery
|
||||
A:SP$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose up to six target creature cards with different names in your graveyard | ValidTgts$ Creature.YouOwn | TargetsWithDifferentNames$ True | TargetMin$ 0 | TargetMax$ 6 | SpellDescription$ Return up to six target creature cards with different names from your graveyard to the battlefield.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Biorganic Carapace
|
||||
Variant:UniversesWithin:FlavorName:Angler's Shield
|
||||
ManaCost:2 W U
|
||||
Types:Artifact Equipment
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigAttach | TriggerDescription$ When this Equipment enters, attach it to target creature you control.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Black Cat, Cunning Thief
|
||||
Variant:UniversesWithin:FlavorName:Wrench, Speedway Saboteur
|
||||
ManaCost:3 B B
|
||||
Types:Legendary Creature Human Rogue Villain
|
||||
PT:2/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Carnage, Crimson Chaos
|
||||
Variant:UniversesWithin:FlavorName:Desecrex, Gift of Servitude
|
||||
ManaCost:2 B R
|
||||
Types:Legendary Creature Symbiote Villain
|
||||
PT:4/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Chameleon, Master of Disguise
|
||||
Variant:UniversesWithin:FlavorName:Vazin, Two-Faced Trickster
|
||||
ManaCost:3 U
|
||||
Types:Legendary Creature Human Shapeshifter Villain
|
||||
PT:2/3
|
||||
|
||||
@@ -3,6 +3,6 @@ ManaCost:1 G
|
||||
Types:Sorcery
|
||||
A:SP$ Pump | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ DBDamage | AILogic$ PowerDmg | StackDescription$ {c:ThisTargetedCard} | SpellDescription$ Target creature you control
|
||||
SVar:DBDamage:DB$ DealDamage | ValidTgts$ Creature | TgtPrompt$ Select another target creature | TargetUnique$ True | AILogic$ PowerDmg | NumDmg$ X | DamageSource$ ParentTarget | ExcessSVar$ Excess | SubAbility$ DBDiscover | StackDescription$ REP another target creature_{c:ThisTargetedCard} | SpellDescription$ deals damage equal to its power to another target creature.
|
||||
SVar:DBDiscover:DB$ Discover | Num$ Excess | StackDescription$ SpellDescription | SpellDescription$ If excess damage was dealt this way, discover X, where X is that excess damage. (Exile cards from the top of your library until you exile a nonland card with that mana value or less. Cast it without paying its mana cost or put it into your hand. Put the rest on the bottom in a random order.)
|
||||
SVar:DBDiscover:DB$ Discover | Num$ Excess | ConditionCheckSVar$ Excess | StackDescription$ SpellDescription | SpellDescription$ If excess damage was dealt this way, discover X, where X is that excess damage. (Exile cards from the top of your library until you exile a nonland card with that mana value or less. Cast it without paying its mana cost or put it into your hand. Put the rest on the bottom in a random order.)
|
||||
SVar:X:ParentTargeted$CardPower
|
||||
Oracle:Target creature you control deals damage equal to its power to another target creature. If excess damage was dealt this way, discover X, where X is that excess damage. (Exile cards from the top of your library until you exile a nonland card with that mana value or less. Cast it without paying its mana cost or put it into your hand. Put the rest on the bottom in a random order.)
|
||||
|
||||
@@ -3,12 +3,8 @@ ManaCost:4 U
|
||||
Types:Enchantment
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigIncubate | TriggerDescription$ When CARDNAME enters, incubate 4. (Create an Incubator token with four +1/+1 counters on it and "{2}: Transform this artifact." It transforms into a 0/0 Phyrexian artifact creature.)
|
||||
SVar:TrigIncubate:DB$ Incubate | Amount$ 4
|
||||
T:Mode$ Transformed | ValidCard$ Permanent.YouCtrl+inZoneBattlefield | Execute$ TrigDraw | TriggerZones$ Battlefield | OptionalDecider$ You | CheckSVar$ X | SVarCompare$ LT1 | TriggerDescription$ Whenever a permanent you control transforms or a permanent you control enters transformed, you may draw a card. Do this only once each turn.
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Permanent.Transformed+YouCtrl | OptionalDecider$ You | TriggerZones$ Battlefield | Execute$ TrigDraw | Secondary$ True | CheckSVar$ X | SVarCompare$ LT1 | TriggerDescription$ Whenever a permanent you control transforms or a permanent you control enters transformed, you may draw a card. Do this only once each turn.
|
||||
SVar:TrigDraw:DB$ Draw | SubAbility$ DBLog
|
||||
SVar:DBLog:DB$ StoreSVar | SVar$ X | Type$ Number | Expression$ 1
|
||||
SVar:X:Number$0
|
||||
T:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ DBCleanup | Static$ True
|
||||
SVar:DBCleanup:DB$ StoreSVar | SVar$ X | Type$ Number | Expression$ 0
|
||||
T:Mode$ Transformed | ValidCard$ Permanent.YouCtrl+inZoneBattlefield | Execute$ TrigDraw | TriggerZones$ Battlefield | OptionalDecider$ You | ResolvedLimit$ 1 | TriggerDescription$ Whenever a permanent you control transforms or a permanent you control enters transformed, you may draw a card. Do this only once each turn.
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Permanent.Transformed+YouCtrl | OptionalDecider$ You | TriggerZones$ Battlefield | Execute$ TrigDraw | Secondary$ True | ResolvedLimit$ 1 | TriggerDescription$ Whenever a permanent you control transforms or a permanent you control enters transformed, you may draw a card. Do this only once each turn.
|
||||
SVar:TrigDraw:DB$ Draw
|
||||
DeckHas:Ability$Counters|Token & Type$Incubator|Artifact|Phyrexian
|
||||
Oracle:When Corruption of Towashi enters, incubate 4. (Create an Incubator token with four +1/+1 counters on it and "{2}: Transform this artifact." It transforms into a 0/0 Phyrexian artifact creature.)\nWhenever a permanent you control transforms or a permanent you control enters transformed, you may draw a card. Do this only once each turn.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Cosmic Spider-Man
|
||||
Variant:UniversesWithin:FlavorName:Scions of the Ur-Spider
|
||||
ManaCost:W U B R G
|
||||
Types:Legendary Creature Spider Human Hero
|
||||
PT:5/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Daily Bugle Building
|
||||
Variant:UniversesWithin:FlavorName:Fearsome Ridgeline
|
||||
ManaCost:no cost
|
||||
Types:Land
|
||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Daily Bugle Reporters
|
||||
Variant:UniversesWithin:FlavorName:Principled Referee
|
||||
ManaCost:3 W
|
||||
Types:Creature Human Citizen
|
||||
PT:2/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Damage Control Crew
|
||||
Variant:UniversesWithin:FlavorName:Selesnya Archivist
|
||||
ManaCost:3 G
|
||||
Types:Creature Human Citizen
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Doc Ock, Sinister Scientist
|
||||
Variant:UniversesWithin:FlavorName:Ozor, Chronicler of Collapse
|
||||
ManaCost:4 U
|
||||
Types:Legendary Creature Human Scientist Villain
|
||||
PT:4/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Doc Ock's Henchmen
|
||||
Variant:UniversesWithin:FlavorName:Obscura Alleylurkers
|
||||
ManaCost:2 U
|
||||
Types:Creature Human Villain
|
||||
PT:2/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Doc Ock's Tentacles
|
||||
Variant:UniversesWithin:FlavorName:Giantcraft Helm
|
||||
ManaCost:1
|
||||
Types:Artifact Equipment
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+cmcGE5 | TriggerZones$ Battlefield | Execute$ TrigAttach | OptionalDecider$ You | TriggerDescription$ Whenever a creature you control with mana value 5 or greater enters, you may attach this Equipment to it.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Doctor Octopus, Master Planner
|
||||
Variant:UniversesWithin:FlavorName:Neach, Pinnacle Pariah
|
||||
ManaCost:5 U B
|
||||
Types:Legendary Creature Human Scientist Villain
|
||||
PT:4/8
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Eddie Brock
|
||||
Variant:UniversesWithin:FlavorName:Viggo, Enforcer of Ig's Crossing
|
||||
ManaCost:2 B
|
||||
Types:Legendary Creature Human Hero Villain
|
||||
PT:3/3
|
||||
@@ -12,6 +13,7 @@ Oracle:When Eddie Brock enters, return target creature card with mana value 1 or
|
||||
ALTERNATE
|
||||
|
||||
Name:Venom, Lethal Protector
|
||||
Variant:UniversesWithin:FlavorName:Viggo, End of Ig's Crossing
|
||||
ManaCost:3 B R G
|
||||
Types:Legendary Creature Symbiote Hero Villain
|
||||
PT:5/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Electro, Assaulting Battery
|
||||
Variant:UniversesWithin:FlavorName:Bayo, Irritable Instructor
|
||||
ManaCost:1 R R
|
||||
Types:Legendary Creature Human Villain
|
||||
PT:2/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Electro's Bolt
|
||||
Variant:UniversesWithin:FlavorName:Deathflame Burst
|
||||
ManaCost:2 R
|
||||
Types:Sorcery
|
||||
A:SP$ DealDamage | ValidTgts$ Creature | NumDmg$ 4 | SpellDescription$ CARDNAME deals 4 damage to target creature.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Ezekiel Sims, Spider-Totem
|
||||
Variant:UniversesWithin:FlavorName:Orris, Last of the Web Lords
|
||||
ManaCost:4 G
|
||||
Types:Legendary Creature Spider Human Advisor
|
||||
PT:3/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Flash Thompson, Spider-Fan
|
||||
Variant:UniversesWithin:FlavorName:Basil, Cabaretti Loudmouth
|
||||
ManaCost:1 W
|
||||
Types:Legendary Creature Human Citizen
|
||||
PT:2/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Flying Octobot
|
||||
Variant:UniversesWithin:FlavorName:Vexed Bots
|
||||
ManaCost:1 U
|
||||
Types:Artifact Creature Robot Villain
|
||||
PT:1/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Friendly Neighborhood
|
||||
Variant:UniversesWithin:FlavorName:Remarkable Readings
|
||||
ManaCost:3 W
|
||||
Types:Enchantment Aura
|
||||
K:Enchant:Land
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Green Goblin, Revenant
|
||||
Variant:UniversesWithin:FlavorName:Nu and Sumi, Career Criminals
|
||||
ManaCost:3 B R
|
||||
Types:Legendary Creature Goblin Human Villain
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Guy in the Chair
|
||||
Variant:UniversesWithin:FlavorName:Eccentric Arachnologist
|
||||
ManaCost:2 G
|
||||
Types:Creature Human Advisor
|
||||
PT:2/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Gwen Stacy
|
||||
Variant:UniversesWithin:FlavorName:Nia, Skysail Storyteller
|
||||
ManaCost:1 R
|
||||
Types:Legendary Creature Human Performer Hero
|
||||
PT:2/1
|
||||
@@ -14,6 +15,7 @@ Oracle:When Gwen Stacy enters, exile the top card of your library. You may play
|
||||
ALTERNATE
|
||||
|
||||
Name:Ghost-Spider
|
||||
Variant:UniversesWithin:FlavorName:Nia, Fabled Skyclimber
|
||||
ManaCost:2 U R W
|
||||
Types:Legendary Creature Spider Human Hero
|
||||
PT:4/4
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Gwenom, Remorseless
|
||||
Variant:UniversesWithin:FlavorName:Egrix the Bile Bulwark
|
||||
ManaCost:3 B B
|
||||
Types:Legendary Creature Symbiote Spider Hero
|
||||
PT:4/4
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Heroes' Hangout
|
||||
Variant:UniversesWithin:FlavorName:Fire-Brained Scheme
|
||||
ManaCost:R
|
||||
Types:Sorcery
|
||||
A:SP$ Charm | Choices$ DBDateNight,DBPatrolNight
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Hide on the Ceiling
|
||||
Variant:UniversesWithin:FlavorName:Spectral Restitching
|
||||
ManaCost:X U
|
||||
Types:Instant
|
||||
A:SP$ ChangeZone | ValidTgts$ Artifact,Creature | TgtPrompt$ Select X target artifacts and/or creatures | TargetMin$ X | TargetMax$ X | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBDelTrig | SpellDescription$ Exile X target artifacts and/or creatures. Return the exiled cards to the battlefield under their owners' control at the beginning of the next end step.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Hobgoblin, Mantled Marauder
|
||||
Variant:UniversesWithin:FlavorName:Cam and Farrik, Havoc Duo
|
||||
ManaCost:1 R
|
||||
Types:Legendary Creature Goblin Human Villain
|
||||
PT:1/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Hot Dog Cart
|
||||
Variant:UniversesWithin:FlavorName:Treat Trolley
|
||||
ManaCost:3
|
||||
Types:Artifact
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigFood | TriggerDescription$ When this artifact enters, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this token: You gain 3 life.")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Hydro-Man, Fluid Felon
|
||||
Variant:UniversesWithin:FlavorName:Belion, the Parched
|
||||
ManaCost:U U
|
||||
Types:Legendary Creature Elemental Villain
|
||||
PT:2/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Inner Demons Gangsters
|
||||
Variant:UniversesWithin:FlavorName:Caldaia Brawlers
|
||||
ManaCost:3 B
|
||||
Types:Creature Human Rogue Villain
|
||||
PT:3/4
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Interdimensional Web Watch
|
||||
Variant:UniversesWithin:FlavorName:Reality Fulcrum
|
||||
ManaCost:4
|
||||
Types:Artifact
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When this artifact enters, exile the top two cards of your library. Until the end of your next turn, you may play those cards.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Iron Spider, Stark Upgrade
|
||||
Variant:UniversesWithin:FlavorName:Fizik, Etherium Mechanic
|
||||
ManaCost:3
|
||||
Types:Legendary Artifact Creature Spider Hero
|
||||
PT:2/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:J. Jonah Jameson
|
||||
Variant:UniversesWithin:FlavorName:Lazlo, Enthusiastic Accuser
|
||||
ManaCost:2 R
|
||||
Types:Legendary Creature Human Citizen
|
||||
PT:2/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Jackal, Genius Geneticist
|
||||
Variant:UniversesWithin:FlavorName:Druneth, Reviver of the Hive
|
||||
ManaCost:G U
|
||||
Types:Legendary Creature Human Scientist Villain
|
||||
PT:1/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Kapow!
|
||||
Variant:UniversesWithin:FlavorName:Perilous Lunge
|
||||
ManaCost:2 G
|
||||
Types:Sorcery
|
||||
A:SP$ PutCounter | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBFight | SpellDescription$ Put a +1/+1 counter on target creature you control. It fights target creature an opponent controls. (Each deals damage equal to its power to the other.)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Kraven, Proud Predator
|
||||
Variant:UniversesWithin:FlavorName:Dreadfang, Loathed by Fans
|
||||
ManaCost:1 R G
|
||||
Types:Legendary Creature Human Warrior Villain
|
||||
PT:*/4
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Kraven the Hunter
|
||||
Variant:UniversesWithin:FlavorName:Brako, Heartless Hunter
|
||||
ManaCost:1 B G
|
||||
Types:Legendary Creature Human Warrior Villain
|
||||
PT:4/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Kraven's Cats
|
||||
Variant:UniversesWithin:FlavorName:Cruel Caracals
|
||||
ManaCost:1 G
|
||||
Types:Creature Cat Villain
|
||||
PT:2/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Kraven's Last Hunt
|
||||
Variant:UniversesWithin:FlavorName:A Trail of Teacups
|
||||
ManaCost:3 G
|
||||
Types:Enchantment Saga
|
||||
K:Chapter:3:DBMill,DBPump,DBReturn
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Lady Octopus, Inspired Inventor
|
||||
Variant:UniversesWithin:FlavorName:Merata, Neuron Hacker
|
||||
ManaCost:U
|
||||
Types:Legendary Creature Human Scientist Villain
|
||||
PT:0/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Living Brain, Mechanical Marvel
|
||||
Variant:UniversesWithin:FlavorName:Error-9, Viral Node
|
||||
ManaCost:4
|
||||
Types:Legendary Artifact Creature Robot Villain
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Lizard, Connors's Curse
|
||||
Variant:UniversesWithin:FlavorName:King of the Coldblood Curse
|
||||
ManaCost:2 G G
|
||||
Types:Legendary Creature Lizard Villain
|
||||
PT:5/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Madame Web, Clairvoyant
|
||||
Variant:UniversesWithin:FlavorName:Olx, Mouth to Many Eyes
|
||||
ManaCost:4 U U
|
||||
Types:Legendary Creature Mutant Advisor
|
||||
PT:4/4
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Mary Jane Watson
|
||||
Variant:UniversesWithin:FlavorName:Demera, Soul of a Spider
|
||||
ManaCost:1 GW
|
||||
Types:Legendary Creature Human Performer
|
||||
PT:2/2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Masked Meower
|
||||
Variant:UniversesWithin:FlavorName:Skittering Kitten
|
||||
ManaCost:R
|
||||
Types:Creature Spider Cat Hero
|
||||
PT:1/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Maximum Carnage
|
||||
Variant:UniversesWithin:FlavorName:Lavabrink Repels the Magmaloth
|
||||
ManaCost:4 R
|
||||
Types:Enchantment Saga
|
||||
K:Chapter:3:DBEffect,DBMana,DBDamage
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Mechanical Mobster
|
||||
Variant:UniversesWithin:FlavorName:Data Scrubber
|
||||
ManaCost:3
|
||||
Types:Artifact Creature Human Robot Villain
|
||||
PT:2/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Miles Morales
|
||||
Variant:UniversesWithin:FlavorName:Cren, Undercity Dreamer
|
||||
ManaCost:1 G
|
||||
Types:Legendary Creature Human Citizen Hero
|
||||
PT:1/2
|
||||
@@ -11,6 +12,7 @@ Oracle:When Miles Morales enters, put a +1/+1 counter on each of up to two targe
|
||||
ALTERNATE
|
||||
|
||||
Name:Ultimate Spider-Man
|
||||
Variant:UniversesWithin:FlavorName:Cren of the Spider Brood
|
||||
ManaCost:3 R G W
|
||||
Types:Legendary Creature Spider Human Hero
|
||||
PT:4/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Mister Negative
|
||||
Variant:UniversesWithin:FlavorName:Withar, Cocoon Keeper
|
||||
ManaCost:5 W B
|
||||
Types:Legendary Creature Human Villain
|
||||
PT:5/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Molten Man, Inferno Incarnate
|
||||
Variant:UniversesWithin:FlavorName:The Infernus
|
||||
ManaCost:2 R
|
||||
Types:Legendary Creature Elemental Villain
|
||||
PT:0/0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Morbius the Living Vampire
|
||||
Variant:UniversesWithin:FlavorName:Tearle, Entropic Hunger
|
||||
ManaCost:2 U B
|
||||
Types:Legendary Creature Vampire Scientist Villain
|
||||
PT:3/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Morlun, Devourer of Spiders
|
||||
Variant:UniversesWithin:FlavorName:Luis, Pompous Pillager
|
||||
ManaCost:X B B
|
||||
Types:Legendary Creature Vampire Villain
|
||||
PT:2/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Mysterio, Master of Illusion
|
||||
Variant:UniversesWithin:FlavorName:The Watcher on the Road
|
||||
ManaCost:3 U
|
||||
Types:Legendary Creature Human Villain
|
||||
PT:3/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Mysterio's Phantasm
|
||||
Variant:UniversesWithin:FlavorName:Phantasmal Vision
|
||||
ManaCost:1 U
|
||||
Types:Creature Illusion Villain
|
||||
PT:1/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:News Helicopter
|
||||
Variant:UniversesWithin:FlavorName:Opulent Valet
|
||||
ManaCost:3
|
||||
Types:Artifact Creature Construct
|
||||
PT:1/1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Norman Osborn
|
||||
Variant:UniversesWithin:FlavorName:Goben, Gene-Splice Savant
|
||||
ManaCost:1 U
|
||||
Types:Legendary Creature Human Scientist Villain
|
||||
PT:1/1
|
||||
@@ -12,6 +13,7 @@ Oracle:Norman Osborn can't be blocked.\nWhenever Norman Osborn deals combat dama
|
||||
ALTERNATE
|
||||
|
||||
Name:Green Goblin
|
||||
Variant:UniversesWithin:FlavorName:Fleem, Goben's Creation
|
||||
ManaCost:1 U B R
|
||||
Types:Legendary Creature Goblin Human Villain
|
||||
PT:3/3
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
Name:Oasis of Renewal
|
||||
ManaCost:B G U
|
||||
Types:Legendary Enchantment
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSeekLand | TriggerDescription$ When CARDNAME enters and whenever a land card leaves your graveyard, seek a land card. This ability triggers only once each turn.
|
||||
T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Any | ValidCard$ Card.Land+YouOwn | TriggerZones$ Battlefield | Execute$ TrigSeekLand | Secondary$ True | CheckSVar$ X | SVarCompare$ LT1 | TriggerDescription$ When CARDNAME enters and whenever a land card leaves your graveyard, seek a land card. This ability triggers only once each turn.
|
||||
SVar:TrigSeekLand:DB$ Seek | Type$ Card.Land | SubAbility$ DBLogLand
|
||||
SVar:DBLogLand:DB$ StoreSVar | SVar$ X | Type$ Number | Expression$ 1
|
||||
SVar:X:Number$0
|
||||
T:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ DBLandClean | Static$ True
|
||||
SVar:DBLandClean:DB$ StoreSVar | SVar$ X | Type$ Number | Expression$ 0
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSeekNonLand | TriggerDescription$ When CARDNAME enters and whenever a nonland card leaves your graveyard, seek a nonland card. This ability triggers only once each turn.
|
||||
T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Any | ValidCard$ Card.nonLand+YouOwn | TriggerZones$ Battlefield | Execute$ TrigSeekNonLand | Secondary$ True | CheckSVar$ Y | SVarCompare$ LT1 | TriggerDescription$ When CARDNAME enters and whenever a nonland card leaves your graveyard, seek a nonland card. This ability triggers only once each turn.
|
||||
SVar:TrigSeekNonLand:DB$ Seek | Type$ Card.nonLand | SubAbility$ DBLogNonLand
|
||||
SVar:DBLogNonLand:DB$ StoreSVar | SVar$ Y | Type$ Number | Expression$ 1
|
||||
SVar:Y:Number$0
|
||||
T:Mode$ Phase | Phase$ Cleanup | TriggerZones$ Battlefield | Execute$ DBNonLandClean | Static$ True
|
||||
SVar:DBNonLandClean:DB$ StoreSVar | SVar$ Y | Type$ Number | Expression$ 0
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | ActivationLimit$ 1 | Execute$ TrigSeekLand | TriggerDescription$ When CARDNAME enters and whenever a land card leaves your graveyard, seek a land card. This ability triggers only once each turn.
|
||||
T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Any | ValidCard$ Card.Land+YouOwn | TriggerZones$ Battlefield | ActivationLimit$ 1 | Execute$ TrigSeekLand | Secondary$ True | TriggerDescription$ When CARDNAME enters and whenever a land card leaves your graveyard, seek a land card. This ability triggers only once each turn.
|
||||
SVar:TrigSeekLand:DB$ Seek | Type$ Card.Land
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | ActivationLimit$ 1 | Execute$ TrigSeekNonLand | TriggerDescription$ When CARDNAME enters and whenever a nonland card leaves your graveyard, seek a nonland card. This ability triggers only once each turn.
|
||||
T:Mode$ ChangesZone | Origin$ Graveyard | Destination$ Any | ValidCard$ Card.nonLand+YouOwn | TriggerZones$ Battlefield | ActivationLimit$ 1 | Execute$ TrigSeekNonLand | Secondary$ True | TriggerDescription$ When CARDNAME enters and whenever a nonland card leaves your graveyard, seek a nonland card. This ability triggers only once each turn.
|
||||
SVar:TrigSeekNonLand:DB$ Seek | Type$ Card.nonLand
|
||||
Oracle:When Oasis of Renewal enters and whenever a land card leaves your graveyard, seek a land card. This ability triggers only once each turn.\nWhen Oasis of Renewal enters and whenever a nonland card leaves your graveyard, seek a nonland card. This ability triggers only once each turn.
|
||||
|
||||
@@ -2,6 +2,6 @@ Name:Of One Mind
|
||||
ManaCost:2 U
|
||||
Types:Sorcery
|
||||
S:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ 2 | EffectZone$ All | IsPresent$ Creature.Human+YouCtrl | CheckSVar$ Count$Valid Creature.nonHuman+YouCtrl | Description$ CARDNAME costs {2} less to cast if you control a Human creature and a non-Human creature.
|
||||
DeckHints:Type$Human
|
||||
A:SP$ Draw | NumCards$ 2 | SpellDescription$ Draw two cards.
|
||||
DeckHints:Type$Human
|
||||
Oracle:This spell costs {2} less to cast if you control a Human creature and a non-Human creature.\nDraw two cards.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Origin of Spider-Man
|
||||
Variant:UniversesWithin:FlavorName:A Most Helpful Weaver
|
||||
ManaCost:1 W
|
||||
Types:Enchantment Saga
|
||||
K:Chapter:3:DBToken,DBPutCounter,DBPump
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Oscorp Industries
|
||||
Variant:UniversesWithin:FlavorName:Exclusive Nightclub
|
||||
ManaCost:no cost
|
||||
Types:Land
|
||||
R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplacementResult$ Updated | ReplaceWith$ ETBTapped | Description$ This land enters tapped.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Oscorp Research Team
|
||||
Variant:UniversesWithin:FlavorName:Pinnacle Research Team
|
||||
ManaCost:3 U
|
||||
Types:Creature Human Scientist
|
||||
PT:1/5
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Parker Luck
|
||||
Variant:UniversesWithin:FlavorName:Duskmourn's Claim
|
||||
ManaCost:2 B
|
||||
Types:Enchantment
|
||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | Execute$ TrigReveal | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your end step, two target players each reveal the top card of their library. They each lose life equal to the mana value of the card revealed by the other player. Then they each put the card they revealed into their hand.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Passenger Ferry
|
||||
Variant:UniversesWithin:FlavorName:Carriage of Dreams
|
||||
ManaCost:3
|
||||
Types:Artifact Vehicle
|
||||
PT:4/3
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Name:Peter Parker
|
||||
Variant:UniversesWithin:FlavorName:Surris, Spidersilk Innovator
|
||||
ManaCost:1 W
|
||||
Types:Legendary Creature Human Scientist Hero
|
||||
PT:0/1
|
||||
@@ -11,6 +12,7 @@ Oracle:When Peter Parker enters, create a 2/1 green Spider creature token with r
|
||||
ALTERNATE
|
||||
|
||||
Name:Amazing Spider-Man
|
||||
Variant:UniversesWithin:FlavorName:Surris, Silk-Tech Vanguard
|
||||
ManaCost:1 G W U
|
||||
Types:Legendary Creature Spider Human Hero
|
||||
PT:4/4
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user