mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-12 16:58:57 +00:00
Merge remote-tracking branch 'upstream/master' into fix-deck-editor-custom-editions-image-view
This commit is contained in:
@@ -787,7 +787,8 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
case "BetterTgtThanRemembered":
|
case "BetterTgtThanRemembered":
|
||||||
if (source.getRememberedCount() > 0) {
|
if (source.getRememberedCount() > 0) {
|
||||||
Card rem = (Card) source.getFirstRemembered();
|
Card rem = (Card) source.getFirstRemembered();
|
||||||
if (!rem.isInZone(ZoneType.Battlefield)) {
|
// avoid pumping opponent creature
|
||||||
|
if (!rem.isInZone(ZoneType.Battlefield) || rem.getController().isOpponentOf(source.getController())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for (Card c : source.getController().getCreaturesInPlay()) {
|
for (Card c : source.getController().getCreaturesInPlay()) {
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ public class CharmAi extends SpellAbilityAi {
|
|||||||
if (AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
|
if (AiPlayDecision.WillPlay == aic.canPlaySa(sub)) {
|
||||||
chosenList.add(sub);
|
chosenList.add(sub);
|
||||||
if (chosenList.size() == min) {
|
if (chosenList.size() == min) {
|
||||||
break; // enough choices
|
break; // enough choices
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ public class LifeLoseAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||||
|
|
||||||
final PlayerCollection tgtPlayers = getPlayers(ai, sa);
|
final PlayerCollection tgtPlayers = getPlayers(ai, sa);
|
||||||
|
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
@@ -127,6 +126,7 @@ public class LifeLoseAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final PlayerCollection tgtPlayers = getPlayers(ai, sa);
|
final PlayerCollection tgtPlayers = getPlayers(ai, sa);
|
||||||
|
// TODO: check against the amount we could obtain when multiple activations are possible
|
||||||
PlayerCollection filteredPlayer = tgtPlayers
|
PlayerCollection filteredPlayer = tgtPlayers
|
||||||
.filter(Predicates.and(PlayerPredicates.isOpponentOf(ai), PlayerPredicates.lifeLessOrEqualTo(amount)));
|
.filter(Predicates.and(PlayerPredicates.isOpponentOf(ai), PlayerPredicates.lifeLessOrEqualTo(amount)));
|
||||||
// killing opponents asap
|
// killing opponents asap
|
||||||
|
|||||||
@@ -532,8 +532,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
|
|||||||
|
|
||||||
protected boolean containsNonCombatKeyword(final List<String> keywords) {
|
protected boolean containsNonCombatKeyword(final List<String> keywords) {
|
||||||
for (final String keyword : keywords) {
|
for (final String keyword : keywords) {
|
||||||
// since most keywords are combat relevant check for those that are
|
// since most keywords are combat relevant check for those that are not
|
||||||
// not
|
|
||||||
if (keyword.endsWith("This card doesn't untap during your next untap step.")
|
if (keyword.endsWith("This card doesn't untap during your next untap step.")
|
||||||
|| keyword.endsWith("Shroud") || keyword.endsWith("Hexproof")) {
|
|| keyword.endsWith("Shroud") || keyword.endsWith("Hexproof")) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -194,10 +194,15 @@ public final class CardEdition implements Comparable<CardEdition> { // immutable
|
|||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
String nonNumeric = sortableCollNr.replaceAll("[0-9]", "");
|
String nonNumeric = sortableCollNr.replaceAll("[0-9]", "");
|
||||||
String onlyNumeric = sortableCollNr.replaceAll("[^0-9]", "");
|
String onlyNumeric = sortableCollNr.replaceAll("[^0-9]", "");
|
||||||
if (sortableCollNr.startsWith(onlyNumeric)) // e.g. 12a, 37+, 2018f,
|
try {
|
||||||
sortableCollNr = String.format("%05d", Integer.parseInt(onlyNumeric)) + nonNumeric;
|
collNr = Integer.parseInt(onlyNumeric);
|
||||||
|
} catch (NumberFormatException exon) {
|
||||||
|
collNr = 0; // this is the case of ONLY-letters collector numbers
|
||||||
|
}
|
||||||
|
if ((collNr > 0) && (sortableCollNr.startsWith(onlyNumeric))) // e.g. 12a, 37+, 2018f,
|
||||||
|
sortableCollNr = String.format("%05d", collNr) + nonNumeric;
|
||||||
else // e.g. WS6, S1
|
else // e.g. WS6, S1
|
||||||
sortableCollNr = nonNumeric + String.format("%05d", Integer.parseInt(onlyNumeric));
|
sortableCollNr = nonNumeric + String.format("%05d", collNr);
|
||||||
}
|
}
|
||||||
return sortableCollNr;
|
return sortableCollNr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2131,25 +2131,19 @@ public class GameAction {
|
|||||||
|
|
||||||
public void dealDamage(final boolean isCombat, final CardDamageMap damageMap, final CardDamageMap preventMap,
|
public void dealDamage(final boolean isCombat, final CardDamageMap damageMap, final CardDamageMap preventMap,
|
||||||
final GameEntityCounterTable counterTable, final SpellAbility cause) {
|
final GameEntityCounterTable counterTable, final SpellAbility cause) {
|
||||||
CardDamageMap replaceDamageMap = new CardDamageMap(damageMap);
|
// Clear assigned damage if is combat
|
||||||
// Run replacement effect for each entity dealt damage
|
|
||||||
// TODO: List all possible replacement effects and run them in APNAP order.
|
|
||||||
// TODO: To handle "Prevented this way" and abilities like "Phantom Nomad", should buffer the replaced SA
|
|
||||||
// and only run them after all prevention and redirection effects are processed.
|
|
||||||
for (Map.Entry<GameEntity, Map<Card, Integer>> et : damageMap.columnMap().entrySet()) {
|
for (Map.Entry<GameEntity, Map<Card, Integer>> et : damageMap.columnMap().entrySet()) {
|
||||||
final GameEntity ge = et.getKey();
|
final GameEntity ge = et.getKey();
|
||||||
if (isCombat && ge instanceof Card) {
|
if (isCombat && ge instanceof Card) {
|
||||||
((Card) ge).clearAssignedDamage();
|
((Card) ge).clearAssignedDamage();
|
||||||
}
|
}
|
||||||
for (Map.Entry<Card, Integer> e : et.getValue().entrySet()) {
|
|
||||||
if (e.getValue() > 0) {
|
|
||||||
ge.replaceDamage(e.getValue(), e.getKey(), isCombat, replaceDamageMap, preventMap, counterTable, cause);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run replacement effect for each entity dealt damage
|
||||||
|
game.getReplacementHandler().runReplaceDamage(isCombat, damageMap, preventMap, counterTable, cause);
|
||||||
|
|
||||||
// Actually deal damage according to replaced damage map
|
// Actually deal damage according to replaced damage map
|
||||||
for (Map.Entry<Card, Map<GameEntity, Integer>> et : replaceDamageMap.rowMap().entrySet()) {
|
for (Map.Entry<Card, Map<GameEntity, Integer>> et : damageMap.rowMap().entrySet()) {
|
||||||
final Card sourceLKI = et.getKey();
|
final Card sourceLKI = et.getKey();
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
for (Map.Entry<GameEntity, Integer> e : et.getValue().entrySet()) {
|
for (Map.Entry<GameEntity, Integer> e : et.getValue().entrySet()) {
|
||||||
@@ -2168,9 +2162,8 @@ public class GameAction {
|
|||||||
preventMap.triggerPreventDamage(isCombat);
|
preventMap.triggerPreventDamage(isCombat);
|
||||||
preventMap.clear();
|
preventMap.clear();
|
||||||
|
|
||||||
replaceDamageMap.triggerDamageDoneOnce(isCombat, game);
|
damageMap.triggerDamageDoneOnce(isCombat, game);
|
||||||
damageMap.clear();
|
damageMap.clear();
|
||||||
replaceDamageMap.clear();
|
|
||||||
|
|
||||||
counterTable.triggerCountersPutAll(game);
|
counterTable.triggerCountersPutAll(game);
|
||||||
counterTable.clear();
|
counterTable.clear();
|
||||||
|
|||||||
@@ -23,13 +23,11 @@ import com.google.common.collect.Iterables;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import forge.game.ability.AbilityKey;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardDamageMap;
|
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardPredicates;
|
import forge.game.card.CardPredicates;
|
||||||
import forge.game.card.CounterEnumType;
|
import forge.game.card.CounterEnumType;
|
||||||
@@ -67,43 +65,6 @@ public abstract class GameEntity extends GameObject implements IIdentifiable {
|
|||||||
getView().updateName(this);
|
getView().updateName(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// final Iterable<Card> source
|
|
||||||
public void replaceDamage(final int damage, final Card source, final boolean isCombat,
|
|
||||||
final CardDamageMap damageMap, final CardDamageMap preventMap, GameEntityCounterTable counterTable, final SpellAbility cause) {
|
|
||||||
boolean prevention = source.canDamagePrevented(isCombat) && (cause == null || !cause.hasParam("NoPrevention"));
|
|
||||||
|
|
||||||
// Replacement effects
|
|
||||||
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(this);
|
|
||||||
repParams.put(AbilityKey.DamageSource, source);
|
|
||||||
repParams.put(AbilityKey.DamageAmount, damage);
|
|
||||||
repParams.put(AbilityKey.IsCombat, isCombat);
|
|
||||||
repParams.put(AbilityKey.NoPreventDamage, !prevention);
|
|
||||||
repParams.put(AbilityKey.DamageMap, damageMap);
|
|
||||||
repParams.put(AbilityKey.PreventMap, preventMap);
|
|
||||||
repParams.put(AbilityKey.CounterTable, counterTable);
|
|
||||||
if (cause != null) {
|
|
||||||
repParams.put(AbilityKey.Cause, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (getGame().getReplacementHandler().run(ReplacementType.DamageDone, repParams)) {
|
|
||||||
case NotReplaced:
|
|
||||||
break;
|
|
||||||
case Updated:
|
|
||||||
int newDamage = (int) repParams.get(AbilityKey.DamageAmount);
|
|
||||||
GameEntity newTarget = (GameEntity) repParams.get(AbilityKey.Affected);
|
|
||||||
// check if this is still the affected card or player
|
|
||||||
if (this.equals(newTarget)) {
|
|
||||||
damageMap.put(source, this, newDamage - damage);
|
|
||||||
} else {
|
|
||||||
damageMap.remove(source, this);
|
|
||||||
damageMap.put(source, newTarget, newDamage);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
damageMap.remove(source, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function handles damage after replacement and prevention effects are applied
|
// This function handles damage after replacement and prevention effects are applied
|
||||||
public abstract int addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat, GameEntityCounterTable counterTable);
|
public abstract int addDamageAfterPrevention(final int damage, final Card source, final boolean isCombat, GameEntityCounterTable counterTable);
|
||||||
|
|
||||||
|
|||||||
@@ -96,12 +96,14 @@ public enum AbilityKey {
|
|||||||
PayingMana("PayingMana"),
|
PayingMana("PayingMana"),
|
||||||
Phase("Phase"),
|
Phase("Phase"),
|
||||||
Player("Player"),
|
Player("Player"),
|
||||||
|
PreventedAmount("PreventedAmount"),
|
||||||
PreventMap("PreventMap"),
|
PreventMap("PreventMap"),
|
||||||
Prevention("Prevention"),
|
Prevention("Prevention"),
|
||||||
Produced("Produced"),
|
Produced("Produced"),
|
||||||
Regeneration("Regeneration"),
|
Regeneration("Regeneration"),
|
||||||
ReplacementEffect("ReplacementEffect"),
|
ReplacementEffect("ReplacementEffect"),
|
||||||
ReplacementResult("ReplacementResult"),
|
ReplacementResult("ReplacementResult"),
|
||||||
|
ReplacementResultMap("ReplacementResultMap"),
|
||||||
Result("Result"),
|
Result("Result"),
|
||||||
Scheme("Scheme"),
|
Scheme("Scheme"),
|
||||||
Source("Source"),
|
Source("Source"),
|
||||||
|
|||||||
@@ -16,13 +16,11 @@ public class AddTurnEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getStackDescription(SpellAbility sa) {
|
protected String getStackDescription(SpellAbility sa) {
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
final int numTurns = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumTurns"), sa);
|
final int numTurns = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("NumTurns"), sa);
|
||||||
|
|
||||||
List<Player> tgtPlayers = getTargetPlayers(sa);
|
List<Player> tgtPlayers = getTargetPlayers(sa);
|
||||||
|
|
||||||
|
|
||||||
for (final Player player : tgtPlayers) {
|
for (final Player player : tgtPlayers) {
|
||||||
sb.append(player).append(" ");
|
sb.append(player).append(" ");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,13 +31,12 @@ public class ManaEffect extends SpellAbilityEffect {
|
|||||||
@Override
|
@Override
|
||||||
public void resolve(SpellAbility sa) {
|
public void resolve(SpellAbility sa) {
|
||||||
final Card card = sa.getHostCard();
|
final Card card = sa.getHostCard();
|
||||||
|
|
||||||
AbilityManaPart abMana = sa.getManaPart();
|
AbilityManaPart abMana = sa.getManaPart();
|
||||||
|
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
||||||
|
|
||||||
// Spells are not undoable
|
// Spells are not undoable
|
||||||
sa.setUndoable(sa.isAbility() && sa.isUndoable());
|
sa.setUndoable(sa.isAbility() && sa.isUndoable() && tgtPlayers.size() < 2);
|
||||||
|
|
||||||
final List<Player> tgtPlayers = getTargetPlayers(sa);
|
|
||||||
final boolean optional = sa.hasParam("Optional");
|
final boolean optional = sa.hasParam("Optional");
|
||||||
final Game game = sa.getActivatingPlayer().getGame();
|
final Game game = sa.getActivatingPlayer().getGame();
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,12 @@ import java.util.Map;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameLogEntryType;
|
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardDamageMap;
|
|
||||||
import forge.game.replacement.ReplacementResult;
|
import forge.game.replacement.ReplacementResult;
|
||||||
import forge.game.replacement.ReplacementType;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.util.TextUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles two kinds of prevention effect:
|
* This class handles two kinds of prevention effect:
|
||||||
@@ -37,8 +32,6 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
|
Map<AbilityKey, Object> originalParams = (Map<AbilityKey, Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
|
||||||
Map<AbilityKey, Object> params = AbilityKey.newMap(originalParams);
|
|
||||||
|
|
||||||
Integer dmg = (Integer) sa.getReplacingObject(AbilityKey.DamageAmount);
|
Integer dmg = (Integer) sa.getReplacingObject(AbilityKey.DamageAmount);
|
||||||
|
|
||||||
String varValue = sa.getParamOrDefault("Amount", "1");
|
String varValue = sa.getParamOrDefault("Amount", "1");
|
||||||
@@ -59,21 +52,6 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
// Set PreventedDamage SVar
|
// Set PreventedDamage SVar
|
||||||
card.setSVar("PreventedDamage", "Number$" + n);
|
card.setSVar("PreventedDamage", "Number$" + n);
|
||||||
|
|
||||||
Card sourceLKI = (Card) sa.getReplacingObject(AbilityKey.Source);
|
|
||||||
GameEntity target = (GameEntity) sa.getReplacingObject(AbilityKey.Target);
|
|
||||||
|
|
||||||
// Set prevent map entry
|
|
||||||
CardDamageMap preventMap = (CardDamageMap) originalParams.get(AbilityKey.PreventMap);
|
|
||||||
preventMap.put(sourceLKI, target, n);
|
|
||||||
|
|
||||||
// Following codes are commented out since DamagePrevented trigger is currently not used by any Card.
|
|
||||||
// final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
|
||||||
// runParams.put(AbilityKey.DamageTarget, target);
|
|
||||||
// runParams.put(AbilityKey.DamageAmount, dmg);
|
|
||||||
// runParams.put(AbilityKey.DamageSource, sourceLKI);
|
|
||||||
// runParams.put(AbilityKey.IsCombatDamage, originalParams.get(AbilityKey.IsCombat));
|
|
||||||
// game.getTriggerHandler().runTrigger(TriggerType.DamagePrevented, runParams, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no damage for original target anymore
|
// no damage for original target anymore
|
||||||
@@ -81,33 +59,8 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
|
|||||||
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
|
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
params.put(AbilityKey.DamageAmount, dmg);
|
originalParams.put(AbilityKey.DamageAmount, dmg);
|
||||||
|
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
|
||||||
// need to log Updated events there, or the log is wrong order
|
|
||||||
String message = sa.getReplacementEffect().toString();
|
|
||||||
if ( !StringUtils.isEmpty(message)) {
|
|
||||||
message = TextUtil.fastReplace(message, "CARDNAME", card.getName());
|
|
||||||
game.getGameLog().add(GameLogEntryType.EFFECT_REPLACED, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
//try to call replacementHandler with new Params
|
|
||||||
final ReplacementType event = sa.getReplacementEffect().getMode();
|
|
||||||
ReplacementResult result = game.getReplacementHandler().run(event, params);
|
|
||||||
switch (result) {
|
|
||||||
case NotReplaced:
|
|
||||||
case Updated: {
|
|
||||||
for (Map.Entry<AbilityKey, Object> e : params.entrySet()) {
|
|
||||||
originalParams.put(e.getKey(), e.getValue());
|
|
||||||
}
|
|
||||||
// effect was updated
|
|
||||||
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// effect was replaced with something else
|
|
||||||
originalParams.put(AbilityKey.ReplacementResult, result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ public class ReplaceEffect extends SpellAbilityEffect {
|
|||||||
params.put(AbilityKey.EffectOnly, true);
|
params.put(AbilityKey.EffectOnly, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (retype == ReplacementType.DamageDone) {
|
||||||
|
for (Map.Entry<AbilityKey, Object> e : params.entrySet()) {
|
||||||
|
originalParams.put(e.getKey(), e.getValue());
|
||||||
|
}
|
||||||
|
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// need to log Updated events there, or the log is wrong order
|
// need to log Updated events there, or the log is wrong order
|
||||||
String message = sa.getReplacementEffect().toString();
|
String message = sa.getReplacementEffect().toString();
|
||||||
if ( !StringUtils.isEmpty(message)) {
|
if ( !StringUtils.isEmpty(message)) {
|
||||||
|
|||||||
@@ -7,15 +7,12 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameEntityCounterTable;
|
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardDamageMap;
|
|
||||||
import forge.game.replacement.ReplacementResult;
|
import forge.game.replacement.ReplacementResult;
|
||||||
import forge.game.replacement.ReplacementType;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
||||||
@@ -30,19 +27,13 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ReplacementType event = sa.getReplacementEffect().getMode();
|
|
||||||
|
|
||||||
String varValue = sa.getParamOrDefault("VarName", "1");
|
String varValue = sa.getParamOrDefault("VarName", "1");
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<AbilityKey, Object> originalParams = (Map<AbilityKey , Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
|
Map<AbilityKey, Object> originalParams = (Map<AbilityKey , Object>) sa.getReplacingObject(AbilityKey.OriginalParams);
|
||||||
Map<AbilityKey, Object> params = AbilityKey.newMap(originalParams);
|
|
||||||
|
|
||||||
Integer dmg = (Integer) sa.getReplacingObject(AbilityKey.DamageAmount);
|
Integer dmg = (Integer) sa.getReplacingObject(AbilityKey.DamageAmount);
|
||||||
|
|
||||||
|
|
||||||
int prevent = AbilityUtils.calculateAmount(card, varValue, sa);
|
int prevent = AbilityUtils.calculateAmount(card, varValue, sa);
|
||||||
|
|
||||||
List<GameObject> list = AbilityUtils.getDefinedObjects(card, sa.getParam("DamageTarget"), sa);
|
List<GameObject> list = AbilityUtils.getDefinedObjects(card, sa.getParam("DamageTarget"), sa);
|
||||||
|
|
||||||
if (prevent > 0 && list.size() > 0 && list.get(0) instanceof GameEntity) {
|
if (prevent > 0 && list.size() > 0 && list.get(0) instanceof GameEntity) {
|
||||||
@@ -56,18 +47,10 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
|||||||
sa.setSVar(varValue, "Number$" + prevent);
|
sa.setSVar(varValue, "Number$" + prevent);
|
||||||
card.updateAbilityTextForView();
|
card.updateAbilityTextForView();
|
||||||
}
|
}
|
||||||
|
|
||||||
Card sourceLKI = (Card) sa.getReplacingObject(AbilityKey.Source);
|
|
||||||
GameEntity target = (GameEntity) sa.getReplacingObject(AbilityKey.Target);
|
|
||||||
|
|
||||||
GameEntity obj = (GameEntity) list.get(0);
|
GameEntity obj = (GameEntity) list.get(0);
|
||||||
boolean isCombat = (Boolean) originalParams.get(AbilityKey.IsCombat);
|
originalParams.put(AbilityKey.Affected, obj);
|
||||||
CardDamageMap damageMap = (CardDamageMap) originalParams.get(AbilityKey.DamageMap);
|
originalParams.put(AbilityKey.DamageAmount, n);
|
||||||
CardDamageMap preventMap = (CardDamageMap) originalParams.get(AbilityKey.PreventMap);
|
|
||||||
GameEntityCounterTable counterTable = (GameEntityCounterTable) originalParams.get(AbilityKey.CounterTable);
|
|
||||||
SpellAbility cause = (SpellAbility) originalParams.get(AbilityKey.Cause);
|
|
||||||
damageMap.put(sourceLKI, obj, n);
|
|
||||||
obj.replaceDamage(n, sourceLKI, isCombat, damageMap, preventMap, counterTable, cause);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// no damage for original target anymore
|
// no damage for original target anymore
|
||||||
@@ -75,25 +58,7 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
|
|||||||
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
|
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
params.put(AbilityKey.DamageAmount, dmg);
|
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
|
||||||
|
|
||||||
//try to call replacementHandler with new Params
|
|
||||||
ReplacementResult result = game.getReplacementHandler().run(event, params);
|
|
||||||
switch (result) {
|
|
||||||
case NotReplaced:
|
|
||||||
case Updated: {
|
|
||||||
for (Map.Entry<AbilityKey, Object> e : params.entrySet()) {
|
|
||||||
originalParams.put(e.getKey(), e.getValue());
|
|
||||||
}
|
|
||||||
// effect was updated
|
|
||||||
originalParams.put(AbilityKey.ReplacementResult, ReplacementResult.Updated);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// effect was replaced with something else
|
|
||||||
originalParams.put(AbilityKey.ReplacementResult, result);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,4 +67,3 @@ public class SkipTurnEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3232,8 +3232,17 @@ public class CardFactoryUtil {
|
|||||||
if (keyword.startsWith("Affinity")) {
|
if (keyword.startsWith("Affinity")) {
|
||||||
final String[] k = keyword.split(":");
|
final String[] k = keyword.split(":");
|
||||||
final String t = k[1];
|
final String t = k[1];
|
||||||
|
String d = "";
|
||||||
|
if (k.length > 2) {
|
||||||
|
final StringBuilder s = new StringBuilder();
|
||||||
|
s.append(k[2]).append("s");
|
||||||
|
d = s.toString();
|
||||||
|
}
|
||||||
|
|
||||||
String desc = "Artifact".equals(t) ? "artifacts" : CardType.getPluralType(t);
|
String desc = "Artifact".equals(t) ? "artifacts" : CardType.getPluralType(t);
|
||||||
|
if (!d.isEmpty()) {
|
||||||
|
desc = d;
|
||||||
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ AffinityX | EffectZone$ All");
|
sb.append("Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ AffinityX | EffectZone$ All");
|
||||||
sb.append("| Description$ Affinity for ").append(desc);
|
sb.append("| Description$ Affinity for ").append(desc);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public enum Keyword {
|
|||||||
UNDEFINED("", SimpleKeyword.class, false, ""),
|
UNDEFINED("", SimpleKeyword.class, false, ""),
|
||||||
ABSORB("Absorb", KeywordWithAmount.class, false, "If a source would deal damage to this creature, prevent %d of that damage."),
|
ABSORB("Absorb", KeywordWithAmount.class, false, "If a source would deal damage to this creature, prevent %d of that damage."),
|
||||||
ADAPT("Adapt", KeywordWithCostAndAmount.class, false, "If this creature has no +1/+1 counters on it, put {%2$d:+1/+1 counter} on it."),
|
ADAPT("Adapt", KeywordWithCostAndAmount.class, false, "If this creature has no +1/+1 counters on it, put {%2$d:+1/+1 counter} on it."),
|
||||||
AFFINITY("Affinity", KeywordWithType.class, false, "This spell costs you {1} less to cast for each %s you control."),
|
AFFINITY("Affinity", KeywordWithType.class, false, "This spell costs {1} less to cast for each %s you control."),
|
||||||
AFFLICT("Afflict", KeywordWithAmount.class, false, "Whenever this creature becomes blocked, defending player loses %d life."),
|
AFFLICT("Afflict", KeywordWithAmount.class, false, "Whenever this creature becomes blocked, defending player loses %d life."),
|
||||||
AFTERLIFE("Afterlife", KeywordWithAmount.class, false, "When this creature dies, create {%1$d:1/1 white and black Spirit creature token} with flying."),
|
AFTERLIFE("Afterlife", KeywordWithAmount.class, false, "When this creature dies, create {%1$d:1/1 white and black Spirit creature token} with flying."),
|
||||||
AFTERMATH("Aftermath", SimpleKeyword.class, false, "Cast this spell only from your graveyard. Then exile it."),
|
AFTERMATH("Aftermath", SimpleKeyword.class, false, "Cast this spell only from your graveyard. Then exile it."),
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ public class KeywordWithType extends KeywordInstance<KeywordWithType> {
|
|||||||
type = details.toLowerCase();
|
type = details.toLowerCase();
|
||||||
} else if (details.contains(":")) {
|
} else if (details.contains(":")) {
|
||||||
type = details.split(":")[0];
|
type = details.split(":")[0];
|
||||||
|
if (this.toString().startsWith("Affinity")) {
|
||||||
|
type = details.split(":")[1];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
type = details;
|
type = details;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ public class ReplaceProduceMana extends ReplacementEffect {
|
|||||||
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
|
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!matchesValidParam("ValidActivator", runParams.get(AbilityKey.Activator))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!matchesValidParam("ValidAbility", runParams.get(AbilityKey.AbilityMana))) {
|
if (!matchesValidParam("ValidAbility", runParams.get(AbilityKey.AbilityMana))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -58,7 +61,6 @@ public class ReplaceProduceMana extends ReplacementEffect {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
|
public void setReplacingObjects(Map<AbilityKey, Object> runParams, SpellAbility sa) {
|
||||||
sa.setReplacingObject(AbilityKey.Mana, runParams.get(AbilityKey.Mana));
|
sa.setReplacingObject(AbilityKey.Mana, runParams.get(AbilityKey.Mana));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.replacement;
|
package forge.game.replacement;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -30,6 +33,7 @@ import com.google.common.collect.Sets;
|
|||||||
import forge.game.CardTraitBase;
|
import forge.game.CardTraitBase;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityCounterTable;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
import forge.game.IHasSVars;
|
import forge.game.IHasSVars;
|
||||||
import forge.game.ability.AbilityFactory;
|
import forge.game.ability.AbilityFactory;
|
||||||
@@ -45,6 +49,8 @@ import forge.game.card.CardUtil;
|
|||||||
import forge.game.keyword.KeywordInterface;
|
import forge.game.keyword.KeywordInterface;
|
||||||
import forge.game.keyword.KeywordsChange;
|
import forge.game.keyword.KeywordsChange;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerCollection;
|
||||||
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -58,6 +64,10 @@ public class ReplacementHandler {
|
|||||||
private final Game game;
|
private final Game game;
|
||||||
|
|
||||||
private Set<ReplacementEffect> hasRun = Sets.newHashSet();
|
private Set<ReplacementEffect> hasRun = Sets.newHashSet();
|
||||||
|
|
||||||
|
// List of all replacement effect candidates for DamageDone event, in APNAP order
|
||||||
|
private final List<Map<ReplacementEffect, List<Map<AbilityKey, Object>>>> replaceDamageList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ReplacementHandler.
|
* ReplacementHandler.
|
||||||
* @param gameState
|
* @param gameState
|
||||||
@@ -281,24 +291,6 @@ public class ReplacementHandler {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putPreventMapEntry(final Map<AbilityKey, Object> runParams) {
|
|
||||||
Card sourceLKI = (Card) runParams.get(AbilityKey.DamageSource);
|
|
||||||
GameEntity target = (GameEntity) runParams.get(AbilityKey.Affected);
|
|
||||||
Integer damage = (Integer) runParams.get(AbilityKey.DamageAmount);
|
|
||||||
|
|
||||||
// Set prevent map entry
|
|
||||||
CardDamageMap preventMap = (CardDamageMap) runParams.get(AbilityKey.PreventMap);
|
|
||||||
preventMap.put(sourceLKI, target, damage);
|
|
||||||
|
|
||||||
// Following codes are commented out since DamagePrevented trigger is currently not used by any Card.
|
|
||||||
// final Map<AbilityKey, Object> trigParams = AbilityKey.newMap();
|
|
||||||
// trigParams.put(AbilityKey.DamageTarget, target);
|
|
||||||
// trigParams.put(AbilityKey.DamageAmount, damage);
|
|
||||||
// trigParams.put(AbilityKey.DamageSource, sourceLKI);
|
|
||||||
// trigParams.put(AbilityKey.IsCombatDamage, runParams.get(AbilityKey.IsCombat));
|
|
||||||
// game.getTriggerHandler().runTrigger(TriggerType.DamagePrevented, trigParams, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Runs a single replacement effect.
|
* Runs a single replacement effect.
|
||||||
@@ -368,14 +360,21 @@ public class ReplacementHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapParams.containsKey("Prevent") && mapParams.get("Prevent").equals("True")) {
|
boolean isPrevent = mapParams.containsKey("Prevent") && mapParams.get("Prevent").equals("True");
|
||||||
if (replacementEffect.getMode() == ReplacementType.DamageDone) {
|
if (isPrevent || mapParams.containsKey("PreventionEffect")) {
|
||||||
if (Boolean.TRUE.equals(runParams.get(AbilityKey.NoPreventDamage))) {
|
if (Boolean.TRUE.equals(runParams.get(AbilityKey.NoPreventDamage))) {
|
||||||
return ReplacementResult.NotReplaced;
|
// If can't prevent damage, result is not replaced
|
||||||
|
// But still put "prevented" amount for buffered SA
|
||||||
|
if (mapParams.containsKey("AlwaysReplace")) {
|
||||||
|
runParams.put(AbilityKey.PreventedAmount, runParams.get(AbilityKey.DamageAmount));
|
||||||
|
} else {
|
||||||
|
runParams.put(AbilityKey.PreventedAmount, 0);
|
||||||
}
|
}
|
||||||
putPreventMapEntry(runParams);
|
return ReplacementResult.NotReplaced;
|
||||||
|
}
|
||||||
|
if (isPrevent) {
|
||||||
|
return ReplacementResult.Prevented; // Nothing should replace the event.
|
||||||
}
|
}
|
||||||
return ReplacementResult.Prevented; // Nothing should replace the event.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapParams.containsKey("Skip")) {
|
if (mapParams.containsKey("Skip")) {
|
||||||
@@ -384,25 +383,19 @@ public class ReplacementHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean cantPreventDamage = (replacementEffect.getMode() == ReplacementType.DamageDone
|
|
||||||
&& mapParams.containsKey("PreventionEffect")
|
|
||||||
&& Boolean.TRUE.equals(runParams.get(AbilityKey.NoPreventDamage)));
|
|
||||||
|
|
||||||
Player player = host.getController();
|
Player player = host.getController();
|
||||||
|
|
||||||
if (!cantPreventDamage || mapParams.containsKey("AlwaysReplace")) {
|
if (effectSA != null) {
|
||||||
player.getController().playSpellAbilityNoStack(effectSA, true);
|
ApiType apiType = effectSA.getApi();
|
||||||
if (replacementEffect.getMode() == ReplacementType.DamageDone
|
if (replacementEffect.getMode() != ReplacementType.DamageDone ||
|
||||||
&& effectSA.getApi() != ApiType.ReplaceDamage && !cantPreventDamage) {
|
(apiType == ApiType.ReplaceDamage || apiType == ApiType.ReplaceSplitDamage || apiType == ApiType.ReplaceEffect)) {
|
||||||
putPreventMapEntry(runParams);
|
player.getController().playSpellAbilityNoStack(effectSA, true);
|
||||||
|
} else {
|
||||||
|
// The SA if buffered, but replacement result should be set to Replaced
|
||||||
|
runParams.put(AbilityKey.ReplacementResult, ReplacementResult.Replaced);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If can't prevent damage, result is not replaced
|
|
||||||
if (cantPreventDamage) {
|
|
||||||
return ReplacementResult.NotReplaced;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the spellability is a replace effect then its some new logic
|
// if the spellability is a replace effect then its some new logic
|
||||||
// if ReplacementResult is set in run params use that instead
|
// if ReplacementResult is set in run params use that instead
|
||||||
if (runParams.containsKey(AbilityKey.ReplacementResult)) {
|
if (runParams.containsKey(AbilityKey.ReplacementResult)) {
|
||||||
@@ -412,6 +405,322 @@ public class ReplacementHandler {
|
|||||||
return ReplacementResult.Replaced;
|
return ReplacementResult.Replaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getPossibleReplaceDamageList(PlayerCollection players, final boolean isCombat, final CardDamageMap damageMap, final SpellAbility cause) {
|
||||||
|
for (Map.Entry<GameEntity, Map<Card, Integer>> et : damageMap.columnMap().entrySet()) {
|
||||||
|
final GameEntity target = et.getKey();
|
||||||
|
int playerIndex = (target instanceof Player ? players.indexOf(((Player) target)) :
|
||||||
|
players.indexOf(((Card) target).getController()));
|
||||||
|
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> replaceCandidateMap = replaceDamageList.get(playerIndex);
|
||||||
|
for (Map.Entry<Card, Integer> e : et.getValue().entrySet()) {
|
||||||
|
Card source = e.getKey();
|
||||||
|
Integer damage = e.getValue();
|
||||||
|
if (damage > 0) {
|
||||||
|
boolean prevention = source.canDamagePrevented(isCombat) &&
|
||||||
|
(cause == null || !cause.hasParam("NoPrevention"));
|
||||||
|
final Map<AbilityKey, Object> repParams = AbilityKey.mapFromAffected(target);
|
||||||
|
repParams.put(AbilityKey.DamageSource, source);
|
||||||
|
repParams.put(AbilityKey.DamageAmount, damage);
|
||||||
|
repParams.put(AbilityKey.IsCombat, isCombat);
|
||||||
|
repParams.put(AbilityKey.NoPreventDamage, !prevention);
|
||||||
|
if (cause != null) {
|
||||||
|
repParams.put(AbilityKey.Cause, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ReplacementEffect> reList = getReplacementList(ReplacementType.DamageDone, repParams, ReplacementLayer.Other);
|
||||||
|
for (ReplacementEffect re : reList) {
|
||||||
|
if (!replaceCandidateMap.containsKey(re)) {
|
||||||
|
replaceCandidateMap.put(re, new ArrayList<>());
|
||||||
|
}
|
||||||
|
List<Map<AbilityKey, Object>> runParamList = replaceCandidateMap.get(re);
|
||||||
|
runParamList.add(repParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runSingleReplaceDamageEffect(ReplacementEffect re, Map<AbilityKey, Object> runParams, Map<ReplacementEffect, List<Map<AbilityKey, Object>>> replaceCandidateMap,
|
||||||
|
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> executedDamageMap, Player decider, final CardDamageMap damageMap, final CardDamageMap preventMap) {
|
||||||
|
List<Map<AbilityKey, Object>> executedParamList = executedDamageMap.get(re);
|
||||||
|
ApiType apiType = re.getOverridingAbility() != null ? re.getOverridingAbility().getApi() : null;
|
||||||
|
Card source = (Card) runParams.get(AbilityKey.DamageSource);
|
||||||
|
GameEntity target = (GameEntity) runParams.get(AbilityKey.Affected);
|
||||||
|
int damage = (int) runParams.get(AbilityKey.DamageAmount);
|
||||||
|
Map<String, String> mapParams = re.getMapParams();
|
||||||
|
|
||||||
|
ReplacementResult res = executeReplacement(runParams, re, decider, game);
|
||||||
|
GameEntity newTarget = (GameEntity) runParams.get(AbilityKey.Affected);
|
||||||
|
int newDamage = (int) runParams.get(AbilityKey.DamageAmount);
|
||||||
|
|
||||||
|
// ReplaceSplitDamage will split the damage event into two event, so need to create run params for old event
|
||||||
|
// (original run params is changed for new event)
|
||||||
|
Map<AbilityKey, Object> oldParams = null;
|
||||||
|
|
||||||
|
if (res != ReplacementResult.NotReplaced) {
|
||||||
|
// Remove this event from other possible replacers
|
||||||
|
Iterator<Map.Entry<ReplacementEffect, List<Map<AbilityKey, Object>>>> itr = replaceCandidateMap.entrySet().iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
Map.Entry<ReplacementEffect, List<Map<AbilityKey, Object>>> entry = itr.next();
|
||||||
|
if (entry.getKey() == re) continue;
|
||||||
|
if (entry.getValue().contains(runParams)) {
|
||||||
|
entry.getValue().remove(runParams);
|
||||||
|
if (entry.getValue().isEmpty()) {
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add updated event to possible replacers
|
||||||
|
if (res == ReplacementResult.Updated || apiType == ApiType.ReplaceSplitDamage) {
|
||||||
|
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> newReplaceCandidateMap = replaceCandidateMap;
|
||||||
|
if (!target.equals(newTarget)) {
|
||||||
|
PlayerCollection players = game.getPlayersInTurnOrder();
|
||||||
|
int playerIndex = (newTarget instanceof Player ? players.indexOf(((Player) newTarget)) :
|
||||||
|
players.indexOf(((Card) newTarget).getController()));
|
||||||
|
newReplaceCandidateMap = replaceDamageList.get(playerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ReplacementEffect> reList = getReplacementList(ReplacementType.DamageDone, runParams, ReplacementLayer.Other);
|
||||||
|
for (ReplacementEffect newRE : reList) {
|
||||||
|
// Skip if this has already been executed by given replacement effect
|
||||||
|
if (executedDamageMap.containsKey(newRE) && executedDamageMap.get(newRE).contains(runParams)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!newReplaceCandidateMap.containsKey(newRE)) {
|
||||||
|
newReplaceCandidateMap.put(newRE, new ArrayList<>());
|
||||||
|
}
|
||||||
|
List<Map<AbilityKey, Object>> runParamList = newReplaceCandidateMap.get(newRE);
|
||||||
|
runParamList.add(runParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add old updated event too for ReplaceSplitDamage
|
||||||
|
if (apiType == ApiType.ReplaceSplitDamage && res == ReplacementResult.Updated) {
|
||||||
|
oldParams = AbilityKey.newMap(runParams);
|
||||||
|
oldParams.put(AbilityKey.Affected, target);
|
||||||
|
oldParams.put(AbilityKey.DamageAmount, damage - newDamage);
|
||||||
|
List<ReplacementEffect> reList = getReplacementList(ReplacementType.DamageDone, oldParams, ReplacementLayer.Other);
|
||||||
|
for (ReplacementEffect newRE : reList) {
|
||||||
|
if (!replaceCandidateMap.containsKey(newRE)) {
|
||||||
|
replaceCandidateMap.put(newRE, new ArrayList<>());
|
||||||
|
}
|
||||||
|
List<Map<AbilityKey, Object>> runParamList = replaceCandidateMap.get(newRE);
|
||||||
|
runParamList.add(oldParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<ReplacementEffect, ReplacementResult> resultMap = (Map<ReplacementEffect, ReplacementResult>) runParams.get(AbilityKey.ReplacementResultMap);
|
||||||
|
resultMap.put(re, res);
|
||||||
|
|
||||||
|
// Update damage map and prevent map
|
||||||
|
switch (res) {
|
||||||
|
case NotReplaced:
|
||||||
|
break;
|
||||||
|
case Updated:
|
||||||
|
// check if this is still the affected card or player
|
||||||
|
if (target.equals(newTarget)) {
|
||||||
|
damageMap.put(source, target, newDamage - damage);
|
||||||
|
} else if (apiType == ApiType.ReplaceSplitDamage) {
|
||||||
|
damageMap.put(source, target, -newDamage);
|
||||||
|
}
|
||||||
|
if (!target.equals(newTarget)) {
|
||||||
|
if (apiType != ApiType.ReplaceSplitDamage) {
|
||||||
|
damageMap.remove(source, target);
|
||||||
|
}
|
||||||
|
damageMap.put(source, newTarget, newDamage);
|
||||||
|
}
|
||||||
|
if (apiType == ApiType.ReplaceDamage) {
|
||||||
|
preventMap.put(source, target, damage - newDamage);
|
||||||
|
// Record prevented amount
|
||||||
|
runParams.put(AbilityKey.PreventedAmount, damage - newDamage);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
damageMap.remove(source, target);
|
||||||
|
if (apiType == ApiType.ReplaceDamage ||
|
||||||
|
(mapParams.containsKey("Prevent") && mapParams.get("Prevent").equals("True")) ||
|
||||||
|
mapParams.containsKey("PreventionEffect")) {
|
||||||
|
preventMap.put(source, target, damage);
|
||||||
|
// Record prevented amount
|
||||||
|
runParams.put(AbilityKey.PreventedAmount, damage);
|
||||||
|
}
|
||||||
|
if (apiType == ApiType.ReplaceSplitDamage) {
|
||||||
|
damageMap.put(source, newTarget, newDamage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put run params into executed param list so this replacement effect won't handle them again
|
||||||
|
// (For example, if the damage is redirected back)
|
||||||
|
executedParamList.add(runParams);
|
||||||
|
if (apiType == ApiType.ReplaceSplitDamage) {
|
||||||
|
executedParamList.add(oldParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log the replacement effect
|
||||||
|
if (res != ReplacementResult.NotReplaced) {
|
||||||
|
String message = re.getDescription();
|
||||||
|
if ( !StringUtils.isEmpty(message)) {
|
||||||
|
if (re.getHostCard() != null) {
|
||||||
|
message = TextUtil.fastReplace(message, "CARDNAME", re.getHostCard().getName());
|
||||||
|
}
|
||||||
|
game.getGameLog().add(GameLogEntryType.EFFECT_REPLACED, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeReplaceDamageBufferedSA(Map<ReplacementEffect, List<Map<AbilityKey, Object>>> executedDamageMap) {
|
||||||
|
for (Map.Entry<ReplacementEffect, List<Map<AbilityKey, Object>>> entry : executedDamageMap.entrySet()) {
|
||||||
|
ReplacementEffect re = entry.getKey();
|
||||||
|
if (re.getOverridingAbility() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SpellAbility bufferedSA = re.getOverridingAbility();
|
||||||
|
ApiType apiType = bufferedSA.getApi();
|
||||||
|
if (apiType == ApiType.ReplaceDamage || apiType == ApiType.ReplaceSplitDamage || apiType == ApiType.ReplaceEffect) {
|
||||||
|
bufferedSA = bufferedSA.getSubAbility();
|
||||||
|
if (bufferedSA == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Map<AbilityKey, Object>> executedParamList = entry.getValue();
|
||||||
|
if (executedParamList.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> mapParams = re.getMapParams();
|
||||||
|
boolean isPrevention = (mapParams.containsKey("Prevent") && mapParams.get("Prevent").equals("True")) || mapParams.containsKey("PreventionEffect");
|
||||||
|
boolean executePerSource = (mapParams.containsKey("ExecuteMode") && mapParams.get("ExecuteMode").equals("PerSource"));
|
||||||
|
boolean executePerTarget = (mapParams.containsKey("ExecuteMode") && mapParams.get("ExecuteMode").equals("PerTarget"));
|
||||||
|
|
||||||
|
while (!executedParamList.isEmpty()) {
|
||||||
|
Map<AbilityKey, Object> runParams = AbilityKey.newMap();
|
||||||
|
List<Card> damageSourceList = new ArrayList<>();
|
||||||
|
List<GameEntity> affectedList = new ArrayList<>();
|
||||||
|
int damageSum = 0;
|
||||||
|
|
||||||
|
Iterator<Map<AbilityKey, Object>> itr = executedParamList.iterator();
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
Map<AbilityKey, Object> executedParams = itr.next();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<ReplacementEffect, ReplacementResult> resultMap = (Map<ReplacementEffect, ReplacementResult>) executedParams.get(AbilityKey.ReplacementResultMap);
|
||||||
|
ReplacementResult res = resultMap.get(re);
|
||||||
|
if (res == ReplacementResult.NotReplaced && (!isPrevention || Boolean.FALSE.equals(executedParams.get(AbilityKey.NoPreventDamage)))) {
|
||||||
|
itr.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Card source = (Card) executedParams.get(AbilityKey.DamageSource);
|
||||||
|
if (executePerSource && !damageSourceList.isEmpty() && !damageSourceList.contains(source)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GameEntity target = (GameEntity) executedParams.get(AbilityKey.Affected);
|
||||||
|
if (executePerTarget && !affectedList.isEmpty() && !affectedList.contains(target)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
itr.remove();
|
||||||
|
int damage = (int) executedParams.get(isPrevention ? AbilityKey.PreventedAmount : AbilityKey.DamageAmount);
|
||||||
|
if (!damageSourceList.contains(source)) {
|
||||||
|
damageSourceList.add(source);
|
||||||
|
}
|
||||||
|
if (!affectedList.contains(target)) {
|
||||||
|
affectedList.add(target);
|
||||||
|
}
|
||||||
|
damageSum += damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damageSum > 0) {
|
||||||
|
runParams.put(AbilityKey.DamageSource, (damageSourceList.size() > 1 ? damageSourceList : damageSourceList.get(0)));
|
||||||
|
runParams.put(AbilityKey.Affected, (affectedList.size() > 1 ? affectedList : affectedList.get(0)));
|
||||||
|
runParams.put(AbilityKey.DamageAmount, damageSum);
|
||||||
|
|
||||||
|
re.setReplacingObjects(runParams, re.getOverridingAbility());
|
||||||
|
bufferedSA.setActivatingPlayer(re.getHostCard().getController());
|
||||||
|
AbilityUtils.resolve(bufferedSA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runReplaceDamage(final boolean isCombat, final CardDamageMap damageMap, final CardDamageMap preventMap,
|
||||||
|
final GameEntityCounterTable counterTable, final SpellAbility cause) {
|
||||||
|
PlayerCollection players = game.getPlayersInTurnOrder();
|
||||||
|
for (int i = 0; i < players.size(); i++) {
|
||||||
|
replaceDamageList.add(new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map of all executed replacement effect for DamageDone event, including run params
|
||||||
|
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> executedDamageMap = new HashMap<>();
|
||||||
|
|
||||||
|
// First, gather all possible replacement effects
|
||||||
|
getPossibleReplaceDamageList(players, isCombat, damageMap, cause);
|
||||||
|
|
||||||
|
// Next, handle replacement effects in APNAP order
|
||||||
|
// Handle "Prevented this way" and abilities like "Phantom Nomad", by buffer the replaced SA
|
||||||
|
// and only run them after all prevention and redirection effects are processed.
|
||||||
|
while (true) {
|
||||||
|
Player decider = null;
|
||||||
|
Map<ReplacementEffect, List<Map<AbilityKey, Object>>> replaceCandidateMap = null;
|
||||||
|
for (int i = 0; i < players.size(); i++) {
|
||||||
|
if (replaceDamageList.get(i).isEmpty()) continue;
|
||||||
|
decider = players.get(i);
|
||||||
|
replaceCandidateMap = replaceDamageList.get(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (replaceCandidateMap == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ReplacementEffect> possibleReplacers = new ArrayList<>(replaceCandidateMap.keySet());
|
||||||
|
ReplacementEffect chosenRE = decider.getController().chooseSingleReplacementEffect(Localizer.getInstance().getMessage("lblChooseFirstApplyReplacementEffect"), possibleReplacers);
|
||||||
|
List<Map<AbilityKey, Object>> runParamList = replaceCandidateMap.get(chosenRE);
|
||||||
|
|
||||||
|
if (!executedDamageMap.containsKey(chosenRE)) {
|
||||||
|
executedDamageMap.put(chosenRE, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run all possible events for chosen replacement effect
|
||||||
|
chosenRE.setHasRun(true);
|
||||||
|
SpellAbility effectSA = chosenRE.getOverridingAbility();
|
||||||
|
SpellAbility bufferedSA = effectSA;
|
||||||
|
boolean needRestoreSubSA = false;
|
||||||
|
if (effectSA != null) {
|
||||||
|
ApiType apiType = effectSA.getApi();
|
||||||
|
// Temporary remove sub ability from ReplaceDamage, ReplaceSplitDamage and ReplaceEffect API so they could be run later
|
||||||
|
if (apiType == ApiType.ReplaceDamage || apiType == ApiType.ReplaceSplitDamage || apiType == ApiType.ReplaceEffect) {
|
||||||
|
bufferedSA = effectSA.getSubAbility();
|
||||||
|
if (bufferedSA != null) {
|
||||||
|
needRestoreSubSA = true;
|
||||||
|
effectSA.setSubAbility(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map<AbilityKey, Object> runParams : runParamList) {
|
||||||
|
if (!runParams.containsKey(AbilityKey.ReplacementResultMap)) {
|
||||||
|
Map<ReplacementEffect, ReplacementResult> resultMap = new HashMap<>();
|
||||||
|
runParams.put(AbilityKey.ReplacementResultMap, resultMap);
|
||||||
|
}
|
||||||
|
runSingleReplaceDamageEffect(chosenRE, runParams, replaceCandidateMap, executedDamageMap, decider, damageMap, preventMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore temporary removed SA
|
||||||
|
if (needRestoreSubSA) {
|
||||||
|
effectSA.setSubAbility((AbilitySub)bufferedSA);
|
||||||
|
}
|
||||||
|
chosenRE.setHasRun(false);
|
||||||
|
replaceCandidateMap.remove(chosenRE);
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceDamageList.clear();
|
||||||
|
|
||||||
|
// Finally, run all buffered SA to finish the replacement processing
|
||||||
|
executeReplaceDamageBufferedSA(executedDamageMap);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Creates an instance of the proper replacement effect object based on raw
|
* Creates an instance of the proper replacement effect object based on raw
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import forge.gui.framework.DragTab;
|
|||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
import forge.gui.framework.IVDoc;
|
import forge.gui.framework.IVDoc;
|
||||||
import forge.screens.workshop.controllers.CCardScript;
|
import forge.screens.workshop.controllers.CCardScript;
|
||||||
|
import forge.toolbox.FScrollPane;
|
||||||
import forge.toolbox.FTextPane;
|
import forge.toolbox.FTextPane;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
@@ -32,6 +33,7 @@ public enum VCardScript implements IVDoc<CCardScript> {
|
|||||||
private final DragTab tab = new DragTab(Localizer.getInstance().getMessage("lblCardScript"));
|
private final DragTab tab = new DragTab(Localizer.getInstance().getMessage("lblCardScript"));
|
||||||
|
|
||||||
private final FTextPane txtScript = new FTextPane();
|
private final FTextPane txtScript = new FTextPane();
|
||||||
|
private final FScrollPane scrollScript;
|
||||||
private final StyledDocument doc;
|
private final StyledDocument doc;
|
||||||
private final Style error;
|
private final Style error;
|
||||||
|
|
||||||
@@ -41,6 +43,7 @@ public enum VCardScript implements IVDoc<CCardScript> {
|
|||||||
txtScript.setFocusable(true);
|
txtScript.setFocusable(true);
|
||||||
doc = new DefaultStyledDocument();
|
doc = new DefaultStyledDocument();
|
||||||
txtScript.setDocument(doc);
|
txtScript.setDocument(doc);
|
||||||
|
scrollScript = new FScrollPane(txtScript, true);
|
||||||
error = doc.addStyle("error", null);
|
error = doc.addStyle("error", null);
|
||||||
error.addAttribute(StyleConstants.Background, Color.red);
|
error.addAttribute(StyleConstants.Background, Color.red);
|
||||||
error.addAttribute(StyleConstants.Bold, Boolean.valueOf(true));
|
error.addAttribute(StyleConstants.Bold, Boolean.valueOf(true));
|
||||||
@@ -107,6 +110,6 @@ public enum VCardScript implements IVDoc<CCardScript> {
|
|||||||
public void populate() {
|
public void populate() {
|
||||||
JPanel body = parentCell.getBody();
|
JPanel body = parentCell.getBody();
|
||||||
body.setLayout(new MigLayout("insets 1, gap 0, wrap"));
|
body.setLayout(new MigLayout("insets 1, gap 0, wrap"));
|
||||||
body.add(txtScript, "w 100%, h 100%");
|
body.add(scrollScript, "w 100%, h 100%");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2166,4 +2166,149 @@ public class GameSimulatorTest extends SimulationTestCase {
|
|||||||
assertEquals(true, simGoblin.isRed() && simGoblin.isBlack());
|
assertEquals(true, simGoblin.isRed() && simGoblin.isBlack());
|
||||||
assertEquals(true, simGoblin.getType().hasSubtype("Zombie"));
|
assertEquals(true, simGoblin.getType().hasSubtype("Zombie"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCantBePrevented() {
|
||||||
|
String polukranosCardName = "Polukranos, Unchained";
|
||||||
|
String hydraCardName = "Phyrexian Hydra";
|
||||||
|
String leylineCardName = "Leyline of Punishment";
|
||||||
|
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
|
||||||
|
Card polukranos = addCard(polukranosCardName, p);
|
||||||
|
polukranos.addCounter(CounterEnumType.P1P1, 6, p, false, null);
|
||||||
|
addCard(hydraCardName, p);
|
||||||
|
addCard(leylineCardName, p);
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
addCard("Mountain", p);
|
||||||
|
}
|
||||||
|
Card pyroCard = addCardToZone("Pyroclasm", p, ZoneType.Hand);
|
||||||
|
SpellAbility pyroSA = pyroCard.getFirstSpellAbility();
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
sim.simulateSpellAbility(pyroSA);
|
||||||
|
Game simGame = sim.getSimulatedGameState();
|
||||||
|
Card simPolukranos = findCardWithName(simGame, polukranosCardName);
|
||||||
|
Card simHydra = findCardWithName(simGame, hydraCardName);
|
||||||
|
|
||||||
|
assertTrue(simPolukranos.hasCounters());
|
||||||
|
assertEquals(4, simPolukranos.getCounters(CounterEnumType.P1P1));
|
||||||
|
assertEquals(2, simPolukranos.getDamage());
|
||||||
|
|
||||||
|
assertFalse(simHydra.hasCounters());
|
||||||
|
assertEquals(2, simHydra.getDamage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAlphaBrawl() {
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p1 = game.getPlayers().get(0);
|
||||||
|
Player p2 = game.getPlayers().get(1);
|
||||||
|
|
||||||
|
String nishobaName = "Phantom Nishoba";
|
||||||
|
String capridorName = "Stormwild Capridor";
|
||||||
|
String pridemateName = "Ajani's Pridemate";
|
||||||
|
String indestructibilityName = "Indestructibility";
|
||||||
|
String bearName = "Runeclaw Bear";
|
||||||
|
String alphaBrawlName = "Alpha Brawl";
|
||||||
|
|
||||||
|
// enough to cast Alpha Brawl
|
||||||
|
for (int i = 0; i < 8; ++i) {
|
||||||
|
addCard("Mountain", p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Card nishoba = addCard(nishobaName, p1);
|
||||||
|
nishoba.addCounter(CounterEnumType.P1P1, 7, p1, false, null);
|
||||||
|
addCard(capridorName, p1);
|
||||||
|
Card pridemate = addCard(pridemateName, p1);
|
||||||
|
Card indestructibility = addCard(indestructibilityName, p1);
|
||||||
|
indestructibility.attachToEntity(pridemate);
|
||||||
|
addCard(bearName, p1);
|
||||||
|
|
||||||
|
Card alphaBrawl = addCardToZone(alphaBrawlName, p2, ZoneType.Hand);
|
||||||
|
SpellAbility alphaBrawlSA = alphaBrawl.getFirstSpellAbility();
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p2);
|
||||||
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p2);
|
||||||
|
alphaBrawlSA.setTargetCard(nishoba);
|
||||||
|
sim.simulateSpellAbility(alphaBrawlSA);
|
||||||
|
Game simGame = sim.getSimulatedGameState();
|
||||||
|
Card simNishoba = findCardWithName(simGame, nishobaName);
|
||||||
|
Card simCapridor = findCardWithName(simGame, capridorName);
|
||||||
|
Card simPridemate = findCardWithName(simGame, pridemateName);
|
||||||
|
Card simBear = findCardWithName(simGame, bearName);
|
||||||
|
|
||||||
|
// bear is destroyed
|
||||||
|
assertNull(simBear);
|
||||||
|
|
||||||
|
assertNotNull(simNishoba);
|
||||||
|
assertTrue(simNishoba.hasCounters());
|
||||||
|
// Damage prevented and only 1 +1/+1 counter is removed
|
||||||
|
assertEquals(0, simNishoba.getDamage());
|
||||||
|
assertTrue(simNishoba.hasCounters());
|
||||||
|
assertEquals(6, simNishoba.getCounters(CounterEnumType.P1P1));
|
||||||
|
assertEquals(6, simNishoba.getToughnessBonusFromCounters());
|
||||||
|
assertEquals(6, simNishoba.getPowerBonusFromCounters());
|
||||||
|
|
||||||
|
assertNotNull(simCapridor);
|
||||||
|
// Damage prevented and that many +1/+1 counters are put
|
||||||
|
assertEquals(0, simCapridor.getDamage());
|
||||||
|
assertTrue(simCapridor.hasCounters());
|
||||||
|
assertEquals(7, simCapridor.getCounters(CounterEnumType.P1P1));
|
||||||
|
assertEquals(7, simCapridor.getToughnessBonusFromCounters());
|
||||||
|
assertEquals(7, simCapridor.getPowerBonusFromCounters());
|
||||||
|
|
||||||
|
assertNotNull(simPridemate);
|
||||||
|
assertEquals(7, simPridemate.getDamage());
|
||||||
|
// Life gain only triggered once
|
||||||
|
assertTrue(simPridemate.hasCounters());
|
||||||
|
assertEquals(1, simPridemate.getCounters(CounterEnumType.P1P1));
|
||||||
|
assertEquals(1, simPridemate.getToughnessBonusFromCounters());
|
||||||
|
assertEquals(1, simPridemate.getPowerBonusFromCounters());
|
||||||
|
|
||||||
|
// 2 times 7 damage with life gain = 14 + 20 = 34 (damage to Stormwild Capridor is prevented)
|
||||||
|
assertEquals(34, simGame.getPlayers().get(0).getLife());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testGlarecaster() {
|
||||||
|
String glarecasterName = "Glarecaster";
|
||||||
|
|
||||||
|
Game game = initAndCreateGame();
|
||||||
|
Player p = game.getPlayers().get(0);
|
||||||
|
Player p2 = game.getPlayers().get(1);
|
||||||
|
|
||||||
|
Card glarecaster = addCard(glarecasterName, p);
|
||||||
|
// enough to activate Glarecaster and cast Inferno
|
||||||
|
for (int i = 0; i < 7; ++i) {
|
||||||
|
addCard("Plains", p);
|
||||||
|
addCard("Mountain", p);
|
||||||
|
}
|
||||||
|
Card infernoCard = addCardToZone("Inferno", p, ZoneType.Hand);
|
||||||
|
SpellAbility infernoSA = infernoCard.getFirstSpellAbility();
|
||||||
|
|
||||||
|
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||||
|
game.getAction().checkStateEffects(true);
|
||||||
|
|
||||||
|
SpellAbility saGlarecaster = findSAWithPrefix(glarecaster, "{5}{W}");
|
||||||
|
assertNotNull(saGlarecaster);
|
||||||
|
saGlarecaster.getTargets().add(p2);
|
||||||
|
|
||||||
|
GameSimulator sim = createSimulator(game, p);
|
||||||
|
int score = sim.simulateSpellAbility(saGlarecaster).value;
|
||||||
|
assertTrue(score > 0);
|
||||||
|
sim.simulateSpellAbility(infernoSA);
|
||||||
|
Game simGame = sim.getSimulatedGameState();
|
||||||
|
Card simGlarecaster = findCardWithName(simGame, glarecasterName);
|
||||||
|
|
||||||
|
assertNotNull(simGlarecaster);
|
||||||
|
assertEquals(0, simGlarecaster.getDamage());
|
||||||
|
|
||||||
|
// 6 * 3 = 18 damage are all dealt to p2
|
||||||
|
assertEquals(20, simGame.getPlayers().get(0).getLife());
|
||||||
|
assertEquals(2, simGame.getPlayers().get(1).getLife());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ ManaCost:5 W
|
|||||||
Types:Instant
|
Types:Instant
|
||||||
A:SP$ Effect | Cost$ 5 W | ValidTgts$ Creature | ReplacementEffects$ ChannelHarmRep | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | AILogic$ Fog | SpellDescription$ Prevent all damage that would be dealt to you and permanents you control this turn by sources you don't control. If damage is prevented this way, you may have CARDNAME deal that much damage to target creature.
|
A:SP$ Effect | Cost$ 5 W | ValidTgts$ Creature | ReplacementEffects$ ChannelHarmRep | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | AILogic$ Fog | SpellDescription$ Prevent all damage that would be dealt to you and permanents you control this turn by sources you don't control. If damage is prevented this way, you may have CARDNAME deal that much damage to target creature.
|
||||||
SVar:ChannelHarmRep:Event$ DamageDone | ActiveZones$ Command | ValidTarget$ You,Permanent.YouCtrl | ValidSource$ Card.YouDontCtrl,Emblem.YouDontCtrl | ReplaceWith$ DamageSourceInstead | PreventionEffect$ True | Description$ Prevent all damage that would be dealt to you and permanents you control this turn by sources you don't control. If damage is prevented this way, you may have EFFECTHOST deal that much damage to target creature.
|
SVar:ChannelHarmRep:Event$ DamageDone | ActiveZones$ Command | ValidTarget$ You,Permanent.YouCtrl | ValidSource$ Card.YouDontCtrl,Emblem.YouDontCtrl | ReplaceWith$ DamageSourceInstead | PreventionEffect$ True | Description$ Prevent all damage that would be dealt to you and permanents you control this turn by sources you don't control. If damage is prevented this way, you may have EFFECTHOST deal that much damage to target creature.
|
||||||
SVar:DamageSourceInstead:DB$ DealDamage | NumDmg$ X | Defined$ Remembered | DamageSouce$ EffectSource | OptionalDecider$ You
|
SVar:DamageSourceInstead:DB$ DealDamage | NumDmg$ X | Defined$ Remembered | DamageSource$ EffectSource | OptionalDecider$ You
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/channel_harm.jpg
|
|
||||||
Oracle:Prevent all damage that would be dealt to you and permanents you control this turn by sources you don't control. If damage is prevented this way, you may have Channel Harm deal that much damage to target creature.
|
Oracle:Prevent all damage that would be dealt to you and permanents you control this turn by sources you don't control. If damage is prevented this way, you may have Channel Harm deal that much damage to target creature.
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ Name:Comeuppance
|
|||||||
ManaCost:3 W
|
ManaCost:3 W
|
||||||
Types:Instant
|
Types:Instant
|
||||||
A:SP$ Effect | Cost$ 3 W | ReplacementEffects$ RPrevent
|
A:SP$ Effect | Cost$ 3 W | ReplacementEffects$ RPrevent
|
||||||
SVar:RPrevent:Event$ DamageDone | ValidSource$ Card.YouDontCtrl,Emblem.YouDontCtrl | ValidTarget$ You,Planeswalker.YouCtrl | ReplaceWith$ DamageCreature | PreventionEffect$ True | Description$ Prevent all damage that would be dealt to you and planeswalkers you control this turn by sources you don't control. If damage from a creature source is prevented this way, CARDNAME deals that much damage to that creature. If damage from a noncreature source is prevented this way, CARDNAME deals that much damage to the source's controller.
|
SVar:RPrevent:Event$ DamageDone | ValidSource$ Card.YouDontCtrl,Emblem.YouDontCtrl | ValidTarget$ You,Planeswalker.YouCtrl | ReplaceWith$ DamageCreature | PreventionEffect$ True | ExecuteMode$ PerSource | Description$ Prevent all damage that would be dealt to you and planeswalkers you control this turn by sources you don't control. If damage from a creature source is prevented this way, CARDNAME deals that much damage to that creature. If damage from a noncreature source is prevented this way, CARDNAME deals that much damage to the source's controller.
|
||||||
SVar:DamageCreature:DB$ DealDamage | Defined$ ReplacedSource | DamageSource$ EffectSource | NumDmg$ X | ConditionDefined$ ReplacedSource | ConditionPresent$ Card.Creature | ConditionCompare$ GE1 | SubAbility$ DamageNonCreature
|
SVar:DamageCreature:DB$ DealDamage | Defined$ ReplacedSource | DamageSource$ EffectSource | NumDmg$ X | ConditionDefined$ ReplacedSource | ConditionPresent$ Card.Creature | ConditionCompare$ GE1 | SubAbility$ DamageNonCreature
|
||||||
SVar:DamageNonCreature:DB$ DealDamage | Defined$ ReplacedSourceController | DamageSource$ EffectSource | NumDmg$ X | ConditionDefined$ ReplacedSource | ConditionPresent$ Card.nonCreature | ConditionCompare$ GE1
|
SVar:DamageNonCreature:DB$ DealDamage | Defined$ ReplacedSourceController | DamageSource$ EffectSource | NumDmg$ X | ConditionDefined$ ReplacedSource | ConditionPresent$ Card.nonCreature | ConditionCompare$ GE1
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/comeuppance.jpg
|
|
||||||
Oracle:Prevent all damage that would be dealt to you and planeswalkers you control this turn by sources you don't control. If damage from a creature source is prevented this way, Comeuppance deals that much damage to that creature. If damage from a noncreature source is prevented this way, Comeuppance deals that much damage to the source's controller.
|
Oracle:Prevent all damage that would be dealt to you and planeswalkers you control this turn by sources you don't control. If damage from a creature source is prevented this way, Comeuppance deals that much damage to that creature. If damage from a noncreature source is prevented this way, Comeuppance deals that much damage to the source's controller.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
Name:Crumbling Sanctuary
|
Name:Crumbling Sanctuary
|
||||||
ManaCost:5
|
ManaCost:5
|
||||||
Types:Artifact
|
Types:Artifact
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Player | ReplaceWith$ ExileTop | Description$ If damage would be dealt to a player, that player exiles that many cards from the top of their library instead.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Player | ReplaceWith$ ExileTop | ExecuteMode$ PerTarget | Description$ If damage would be dealt to a player, that player exiles that many cards from the top of their library instead.
|
||||||
SVar:ExileTop:DB$ Dig | Defined$ ReplacedTarget | DigNum$ X | ChangeNum$ All | DestinationZone$ Exile
|
SVar:ExileTop:DB$ Dig | Defined$ ReplacedTarget | DigNum$ X | ChangeNum$ All | DestinationZone$ Exile
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
SVar:NonStackingEffect:True
|
SVar:NonStackingEffect:True
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Deep Water
|
|||||||
ManaCost:U U
|
ManaCost:U U
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
A:AB$ Effect | Cost$ U | ReplacementEffects$ ReplaceU | SpellDescription$ Until end of turn, if you tap a land you control for mana, it produces {U} instead of any other type.
|
A:AB$ Effect | Cost$ U | ReplacementEffects$ ReplaceU | SpellDescription$ Until end of turn, if you tap a land you control for mana, it produces {U} instead of any other type.
|
||||||
SVar:ReplaceU:Event$ ProduceMana | ActiveZones$ Command | ValidPlayer$ You | ValidCard$ Land.YouCtrl | ValidAbility$ Activated.hasTapCost | ReplaceWith$ ProduceU | Description$ If you tap a land you control for mana, it produces U instead of any other type.
|
SVar:ReplaceU:Event$ ProduceMana | ActiveZones$ Command | ValidActivator$ You | ValidCard$ Land.YouCtrl | ValidAbility$ Activated.hasTapCost | ReplaceWith$ ProduceU | Description$ If you tap a land you control for mana, it produces U instead of any other type.
|
||||||
SVar:ProduceU:DB$ ReplaceMana | ReplaceType$ U
|
SVar:ProduceU:DB$ ReplaceMana | ReplaceType$ U
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
AI:RemoveDeck:Random
|
AI:RemoveDeck:Random
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ ManaCost:3 B
|
|||||||
Types:Creature Human Pirate
|
Types:Creature Human Pirate
|
||||||
PT:3/3
|
PT:3/3
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME enters the battlefield, destroy target creature an opponent controls that was dealt damage this turn.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDestroy | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME enters the battlefield, destroy target creature an opponent controls that was dealt damage this turn.
|
||||||
SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Creature.OppCtrl+wasDealtDamageThisTurn | TgtPrompt$ Select target creature tan opponent controls that was dealt damage this turn.
|
SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Creature.OppCtrl+wasDealtDamageThisTurn | TgtPrompt$ Select target creature an opponent controls that was dealt damage this turn.
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/fathom_fleet_cutthroat.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/fathom_fleet_cutthroat.jpg
|
||||||
Oracle:When Fathom Fleet Cutthroat enters the battlefield, destroy target creature an opponent controls that was dealt damage this turn.
|
Oracle:When Fathom Fleet Cutthroat enters the battlefield, destroy target creature an opponent controls that was dealt damage this turn.
|
||||||
@@ -3,7 +3,7 @@ ManaCost:G
|
|||||||
Types:Creature Human Spellshaper
|
Types:Creature Human Spellshaper
|
||||||
PT:1/1
|
PT:1/1
|
||||||
A:AB$ Effect | Cost$ G T Discard<1/Card> | ReplacementEffects$ HarvestReplacement | AILogic$ Never | Stackable$ False | SpellDescription$ Until end of turn, if you tap a land for mana, it produces one mana of a color of your choice instead of any other type and amount.
|
A:AB$ Effect | Cost$ G T Discard<1/Card> | ReplacementEffects$ HarvestReplacement | AILogic$ Never | Stackable$ False | SpellDescription$ Until end of turn, if you tap a land for mana, it produces one mana of a color of your choice instead of any other type and amount.
|
||||||
SVar:HarvestReplacement:Event$ ProduceMana | ActiveZones$ Command | ValidPlayer$ You | ValidCard$ Land | ValidAbility$ Activated.hasTapCost | ReplaceWith$ HarvestProduce | Description$ If you tap a land for mana, it produces one mana of a color of your choice instead of any other type and amount.
|
SVar:HarvestReplacement:Event$ ProduceMana | ActiveZones$ Command | ValidActivator$ You | ValidCard$ Land | ValidAbility$ Activated.hasTapCost | ReplaceWith$ HarvestProduce | Description$ If you tap a land for mana, it produces one mana of a color of your choice instead of any other type and amount.
|
||||||
SVar:HarvestProduce:DB$ ReplaceMana | ReplaceMana$ Any
|
SVar:HarvestProduce:DB$ ReplaceMana | ReplaceMana$ Any
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
SVar:NonStackingEffect:True
|
SVar:NonStackingEffect:True
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Ironscale Hydra
|
|||||||
ManaCost:3 G G
|
ManaCost:3 G G
|
||||||
Types:Creature Hydra
|
Types:Creature Hydra
|
||||||
PT:5/5
|
PT:5/5
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ValidSource$ Creature | IsCombat$ True | ReplaceWith$ Counters | PreventionEffect$ True | AlwaysReplace$ True | Description$ If a creature would deal combat damage to CARDNAME, prevent that damage and put a +1/+1 counter on CARDNAME.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ValidSource$ Creature | IsCombat$ True | ReplaceWith$ Counters | PreventionEffect$ True | AlwaysReplace$ True | ExecuteMode$ PerSource | Description$ If a creature would deal combat damage to CARDNAME, prevent that damage and put a +1/+1 counter on CARDNAME.
|
||||||
SVar:Counters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
SVar:Counters:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
||||||
DeckHas:Ability$Counters
|
DeckHas:Ability$Counters
|
||||||
Oracle:If a creature would deal combat damage to Ironscale Hydra, prevent that damage and put a +1/+1 counter on Ironscale Hydra.
|
Oracle:If a creature would deal combat damage to Ironscale Hydra, prevent that damage and put a +1/+1 counter on Ironscale Hydra.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Name:Mana Reflection
|
Name:Mana Reflection
|
||||||
ManaCost:4 G G
|
ManaCost:4 G G
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
R:Event$ ProduceMana | ActiveZones$ Battlefield | ValidPlayer$ You | ValidCard$ Permanent | ValidAbility$ Activated.hasTapCost | ReplaceWith$ ProduceTwice | Description$ If you tap a permanent for mana, it produces twice as much of that mana instead.
|
R:Event$ ProduceMana | ActiveZones$ Battlefield | ValidActivator$ You | ValidCard$ Permanent | ValidAbility$ Activated.hasTapCost | ReplaceWith$ ProduceTwice | Description$ If you tap a permanent for mana, it produces twice as much of that mana instead.
|
||||||
SVar:ProduceTwice:DB$ ReplaceMana | ReplaceAmount$ 2
|
SVar:ProduceTwice:DB$ ReplaceMana | ReplaceAmount$ 2
|
||||||
Oracle:If you tap a permanent for mana, it produces twice as much of that mana instead.
|
Oracle:If you tap a permanent for mana, it produces twice as much of that mana instead.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Nine Lives
|
|||||||
ManaCost:1 W W
|
ManaCost:1 W W
|
||||||
Types:Enchantment
|
Types:Enchantment
|
||||||
K:Hexproof
|
K:Hexproof
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Card,Emblem | ValidTarget$ You | PreventionEffect$ True | ReplaceWith$ AddCounters | AlwaysReplace$ True | Description$ If a source would deal damage to you, prevent that damage and put an incarnation counter on CARDNAME.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Card,Emblem | ValidTarget$ You | PreventionEffect$ True | ReplaceWith$ AddCounters | AlwaysReplace$ True | ExecuteMode$ PerSource | Description$ If a source would deal damage to you, prevent that damage and put an incarnation counter on CARDNAME.
|
||||||
SVar:AddCounters:DB$ PutCounter | Defined$ Self | CounterType$ INCARNATION | CounterNum$ 1
|
SVar:AddCounters:DB$ PutCounter | Defined$ Self | CounterType$ INCARNATION | CounterNum$ 1
|
||||||
T:Mode$ Always | TriggerZones$ Battlefield | IsPresent$ Card.Self+counters_GE9_INCARNATION | Execute$ TrigExile | TriggerDescription$ When there are nine or more incarnation counters on CARDNAME, exile it.
|
T:Mode$ Always | TriggerZones$ Battlefield | IsPresent$ Card.Self+counters_GE9_INCARNATION | Execute$ TrigExile | TriggerDescription$ When there are nine or more incarnation counters on CARDNAME, exile it.
|
||||||
SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ Self
|
SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | Defined$ Self
|
||||||
|
|||||||
@@ -3,6 +3,6 @@ ManaCost:4 G G G
|
|||||||
Types:Enchantment Creature Elemental
|
Types:Enchantment Creature Elemental
|
||||||
PT:5/5
|
PT:5/5
|
||||||
K:Trample
|
K:Trample
|
||||||
R:Event$ ProduceMana | ActiveZones$ Battlefield | ValidCard$ Permanent.YouCtrl | ValidAbility$ Activated.hasTapCost | ReplaceWith$ ProduceThrice | Description$ If you tap a permanent for mana, it produces three times as much of that mana instead.
|
R:Event$ ProduceMana | ActiveZones$ Battlefield | ValidActivator$ You | ValidCard$ Permanent | ValidAbility$ Activated.hasTapCost | ReplaceWith$ ProduceThrice | Description$ If you tap a permanent for mana, it produces three times as much of that mana instead.
|
||||||
SVar:ProduceThrice:DB$ ReplaceMana | ReplaceAmount$ 3
|
SVar:ProduceThrice:DB$ ReplaceMana | ReplaceAmount$ 3
|
||||||
Oracle:Trample\nIf you tap a permanent for mana, it produces three times as much of that mana instead.
|
Oracle:Trample\nIf you tap a permanent for mana, it produces three times as much of that mana instead.
|
||||||
|
|||||||
@@ -6,12 +6,11 @@ K:Defender
|
|||||||
K:Bushido:1
|
K:Bushido:1
|
||||||
A:AB$ ChooseSource | Cost$ T | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage this turn, that damage is dealt to CARDNAME instead.
|
A:AB$ ChooseSource | Cost$ T | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage this turn, that damage is dealt to CARDNAME instead.
|
||||||
SVar:DBEffect:DB$ Effect | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | Duration$ UntilHostLeavesPlayOrEOT | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | ConditionCompare$ GE1
|
SVar:DBEffect:DB$ Effect | ReplacementEffects$ SelflessDamage | Triggers$ OutOfSight | Duration$ UntilHostLeavesPlayOrEOT | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem | ConditionCompare$ GE1
|
||||||
SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ EffectSource | Description$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to EFFECTSOURCE instead.
|
SVar:SelflessDamage:Event$ DamageDone | ValidSource$ Card.ChosenCard,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ EffectSource | Description$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to EFFECTSOURCE instead.
|
||||||
SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ EffectSource | VarType$ Card | SubAbility$ ExileEffect
|
SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ EffectSource | VarType$ Card | SubAbility$ ExileEffect
|
||||||
SVar:OutOfSight:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Defined$ ChosenCard | Execute$ ExileEffect | Static$ True
|
SVar:OutOfSight:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | Defined$ ChosenCard | Execute$ ExileEffect | Static$ True
|
||||||
SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile | Static$ True
|
SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile | Static$ True
|
||||||
SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True
|
SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True
|
||||||
A:AB$ PreventDamage | Cost$ 1 W | Defined$ Self | Amount$ 1 | SpellDescription$ Prevent the next 1 damage that would be dealt to CARDNAME this turn.
|
A:AB$ PreventDamage | Cost$ 1 W | Defined$ Self | Amount$ 1 | SpellDescription$ Prevent the next 1 damage that would be dealt to CARDNAME this turn.
|
||||||
AI:RemoveDeck:All
|
AI:RemoveDeck:All
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/opal_eye_kondas_yojimbo.jpg
|
|
||||||
Oracle:Defender (This creature can't attack.)\nBushido 1 (Whenever this creature blocks or becomes blocked, it gets +1/+1 until end of turn.)\n{T}: The next time a source of your choice would deal damage this turn, that damage is dealt to Opal-Eye, Konda's Yojimbo instead.\n{1}{W}: Prevent the next 1 damage that would be dealt to Opal-Eye this turn.
|
Oracle:Defender (This creature can't attack.)\nBushido 1 (Whenever this creature blocks or becomes blocked, it gets +1/+1 until end of turn.)\n{T}: The next time a source of your choice would deal damage this turn, that damage is dealt to Opal-Eye, Konda's Yojimbo instead.\n{1}{W}: Prevent the next 1 damage that would be dealt to Opal-Eye this turn.
|
||||||
|
|||||||
@@ -3,13 +3,6 @@ ManaCost:1 W
|
|||||||
Types:Creature Spirit Nomad
|
Types:Creature Spirit Nomad
|
||||||
PT:0/0
|
PT:0/0
|
||||||
K:etbCounter:P1P1:2
|
K:etbCounter:P1P1:2
|
||||||
T:Mode$ Phase | Static$ True | Phase$ First Strike Damage | Execute$ DBCleanup
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ReplaceWith$ DBRemoveCounters | PreventionEffect$ True | AlwaysReplace$ True | Description$ If damage would be dealt to CARDNAME, prevent that damage. Remove a +1/+1 counter from CARDNAME.
|
||||||
T:Mode$ Phase | Static$ True | Phase$ EndCombat | Execute$ DBCleanup
|
|
||||||
R:Event$ DamageDone | IsCombat$ True | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ReplaceWith$ DBRemoveCountersInCombat | PreventionEffect$ True | AlwaysReplace$ True | Description$ If damage would be dealt to CARDNAME, prevent that damage. Remove a +1/+1 counter from CARDNAME.
|
|
||||||
R:Event$ DamageDone | IsCombat$ False | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ReplaceWith$ DBRemoveCounters | PreventionEffect$ True | AlwaysReplace$ True | Secondary$ True | Description$ If damage would be dealt to CARDNAME, prevent that damage. Remove a +1/+1 counter from CARDNAME.
|
|
||||||
SVar:DBRemoveCountersInCombat:DB$ RemoveCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | ConditionCheckSVar$ TimesFlagged | ConditionSVarCompare$ EQ0 | SubAbility$ DBFlagRemoveCounters
|
|
||||||
SVar:DBFlagRemoveCounters:DB$ StoreSVar | SVar$ TimesFlagged | Type$ CountSVar | Expression$ TimesFlagged/Plus.1
|
|
||||||
SVar:DBRemoveCounters:DB$ RemoveCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
SVar:DBRemoveCounters:DB$ RemoveCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
|
||||||
SVar:TimesFlagged:Number$0
|
|
||||||
SVar:DBCleanup:DB$ StoreSVar | SVar$ TimesFlagged | Type$ Number | Expression$ 0
|
|
||||||
Oracle:Phantom Nomad enters the battlefield with two +1/+1 counters on it.\nIf damage would be dealt to Phantom Nomad, prevent that damage. Remove a +1/+1 counter from Phantom Nomad.
|
Oracle:Phantom Nomad enters the battlefield with two +1/+1 counters on it.\nIf damage would be dealt to Phantom Nomad, prevent that damage. Remove a +1/+1 counter from Phantom Nomad.
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ ManaCost:R
|
|||||||
Types:Creature Human Wizard
|
Types:Creature Human Wizard
|
||||||
PT:1/2
|
PT:1/2
|
||||||
K:Prowess
|
K:Prowess
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Creature.OppCtrl | ReplaceWith$ Counters | IsCombat$ False | Description$ If a source you control would deal noncombat damage to a creature an opponent controls, put that many -1/-1 counters on that creature instead.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Creature.OppCtrl | ReplaceWith$ Counters | IsCombat$ False | ExecuteMode$ PerTarget | Description$ If a source you control would deal noncombat damage to a creature an opponent controls, put that many -1/-1 counters on that creature instead.
|
||||||
SVar:Counters:DB$PutCounter | Defined$ ReplacedTarget | CounterType$ M1M1 | CounterNum$ X
|
SVar:Counters:DB$PutCounter | Defined$ ReplacedTarget | CounterType$ M1M1 | CounterNum$ X
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
DeckHas:Ability$Counters
|
DeckHas:Ability$Counters
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/soul_scar_mage.jpg
|
|
||||||
Oracle:Prowess\nIf a source you control would deal noncombat damage to a creature an opponent controls, put that many -1/-1 counters on that creature instead.
|
Oracle:Prowess\nIf a source you control would deal noncombat damage to a creature an opponent controls, put that many -1/-1 counters on that creature instead.
|
||||||
@@ -3,8 +3,7 @@ ManaCost:2 WU WU
|
|||||||
Types:Creature Bird Spirit
|
Types:Creature Bird Spirit
|
||||||
PT:4/3
|
PT:4/3
|
||||||
K:Flying
|
K:Flying
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ReplaceWith$ DBDraw | PreventionEffect$ True | Description$ If a source would deal damage to CARDNAME, prevent that damage. The source's controller draws cards equal to the damage prevented this way.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Card.Self | ReplaceWith$ DBDraw | PreventionEffect$ True | ExecuteMode$ PerSource | Description$ If a source would deal damage to CARDNAME, prevent that damage. The source's controller draws cards equal to the damage prevented this way.
|
||||||
SVar:DBDraw:DB$ Draw | NumCards$ X | Defined$ ReplacedSourceController
|
SVar:DBDraw:DB$ Draw | NumCards$ X | Defined$ ReplacedSourceController
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/swans_of_bryn_argoll.jpg
|
|
||||||
Oracle:Flying\nIf a source would deal damage to Swans of Bryn Argoll, prevent that damage. The source's controller draws cards equal to the damage prevented this way.
|
Oracle:Flying\nIf a source would deal damage to Swans of Bryn Argoll, prevent that damage. The source's controller draws cards equal to the damage prevented this way.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:3 U U B B
|
|||||||
Types:Legendary Creature Vampire
|
Types:Legendary Creature Vampire
|
||||||
PT:5/5
|
PT:5/5
|
||||||
K:Flying
|
K:Flying
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | IsCombat$ True | ValidSource$ Card.Self | ValidTarget$ Opponent | ReplaceWith$ CountersAndMill | Description$ If CARDNAME would deal combat damage to a player, instead put that many +1/+1 counters on Szadek and that player mills that many cards.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | IsCombat$ True | ValidSource$ Card.Self | ValidTarget$ Player | ReplaceWith$ CountersAndMill | ExecuteMode$ PerTarget | Description$ If CARDNAME would deal combat damage to a player, instead put that many +1/+1 counters on Szadek and that player mills that many cards.
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
SVar:CountersAndMill:DB$ PutCounter | Defined$ Self | CounterNum$ X | CounterType$ P1P1 | SubAbility$ Mill
|
SVar:CountersAndMill:DB$ PutCounter | Defined$ Self | CounterNum$ X | CounterType$ P1P1 | SubAbility$ Mill
|
||||||
SVar:Mill:DB$ Mill | Defined$ ReplacedTarget | NumCards$ X
|
SVar:Mill:DB$ Mill | Defined$ ReplacedTarget | NumCards$ X
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ Name:Undead Alchemist
|
|||||||
ManaCost:3 U
|
ManaCost:3 U
|
||||||
Types:Creature Zombie
|
Types:Creature Zombie
|
||||||
PT:4/2
|
PT:4/2
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Creature.Zombie+YouCtrl | ValidTarget$ Opponent | ReplaceWith$ Mill | IsCombat$ True | Description$ If a Zombie you control would deal combat damage to a player, instead that player mills that many cards.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidSource$ Creature.Zombie+YouCtrl | ValidTarget$ Player | ReplaceWith$ Mill | IsCombat$ True | ExecuteMode$ PerTarget | Description$ If a Zombie you control would deal combat damage to a player, instead that player mills that many cards.
|
||||||
SVar:Mill:DB$ Mill | Defined$ ReplacedTarget | NumCards$ X
|
SVar:Mill:DB$ Mill | Defined$ ReplacedTarget | NumCards$ X
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+OppOwn | Origin$ Library | Destination$ Graveyard | Execute$ ExileAndToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from their library, exile that card and create a 2/2 black Zombie creature token.
|
T:Mode$ ChangesZone | ValidCard$ Creature.nonToken+OppOwn | Origin$ Library | Destination$ Graveyard | Execute$ ExileAndToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from their library, exile that card and create a 2/2 black Zombie creature token.
|
||||||
|
|||||||
9
forge-gui/res/cardsfolder/upcoming/abiding_grace.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/abiding_grace.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Abiding Grace
|
||||||
|
ManaCost:2 W
|
||||||
|
Types:Enchantment
|
||||||
|
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigCharm | TriggerDescription$ At the beginning of your end step, ABILITY
|
||||||
|
SVar:TrigCharm:DB$ Charm | Choices$ DBGainLife,DBChangeZone | CharmNum$ 1
|
||||||
|
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 1 | SpellDescription$ You gain 1 life.
|
||||||
|
SVar:DBChangeZone:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card with mana value 1 in your graveyard | ValidTgts$ Creature.cmcEQ1+YouCtrl | SpellDescription$ Return target creature card with mana value 1 from your graveyard to the battlefield.
|
||||||
|
DeckHas:Ability$LifeGain
|
||||||
|
Oracle:At the beginning of your end step, choose one —\n• You gain 1 life.\n• Return target creature card with mana value 1 from your graveyard to the battlefield.
|
||||||
10
forge-gui/res/cardsfolder/upcoming/aeve_progenitor_ooze.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/aeve_progenitor_ooze.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Aeve, Progenitor Ooze
|
||||||
|
ManaCost:2 G G G
|
||||||
|
Types:Legendary Creature Ooze
|
||||||
|
PT:2/2
|
||||||
|
K:Storm
|
||||||
|
S:Mode$ Continuous | Affected$ Card.token+Self | RemoveType$ Legendary | Description$ CARDNAME is not legendary if it's a token.
|
||||||
|
K:etbCounter:P1P1:X:no condition:CARDNAME enters the battlefield with a +1/+1 counter on it for each other Ooze you control.
|
||||||
|
SVar:X:Count$LastStateBattlefield Ooze.YouCtrl+Other
|
||||||
|
DeckHas:Ability$Counters
|
||||||
|
Oracle:Storm (When you cast this spell, copy it for each spell cast before it this turn. The copies become tokens.)\nAeve, Progenitor Ooze is not legendary if it's a token.\nAeve enters the battlefield with a +1/+1 counter on it for each other Ooze you control.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/altar_of_the_goyf.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/altar_of_the_goyf.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Altar of the Goyf
|
||||||
|
ManaCost:5
|
||||||
|
Types:Tribal Artifact Lhurgoyf
|
||||||
|
T:Mode$ Attacks | ValidCard$ Creature.YouCtrl | Alone$ True | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever a creature you control attacks alone, it gets +X/+X until end of turn, where X is the number of card types among cards in all graveyards.
|
||||||
|
SVar:TrigPump:DB$ Pump | Defined$ TriggeredAttacker | NumAtt$ +X | NumDef$ +X
|
||||||
|
S:Mode$ Continuous | Affected$ Creature.Lhurgoyf+YouCtrl | AddKeyword$ Trample | Description$ Lhurgoyf creatures you control have trample.
|
||||||
|
SVar:X:Count$CardTypes.Graveyard
|
||||||
|
SVar:PlayMain1:TRUE
|
||||||
|
Oracle:Whenever a creature you control attacks alone, it gets +X/+X until end of turn, where X is the number of card types among cards in all graveyards.\nLhurgoyf creatures you control have trample.
|
||||||
11
forge-gui/res/cardsfolder/upcoming/arcbound_shikari.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/arcbound_shikari.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Name:Arcbound Shikari
|
||||||
|
ManaCost:1 R W
|
||||||
|
Types:Artifact Creature Cat Soldier
|
||||||
|
PT:0/0
|
||||||
|
K:First Strike
|
||||||
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigPutCounter | TriggerDescription$ When CARDNAME enters the battlefield, put a +1/+1 counter on each other artifact creature you control.
|
||||||
|
SVar:TrigPutCounter:DB$ PutCounterAll | ValidCards$ Creature.Artifact+Other+YouCtrl | CounterType$ P1P1 | CounterNum$ 1
|
||||||
|
K:Modular:2
|
||||||
|
DeckHas:Ability$Counters
|
||||||
|
SVar:PlayMain1:TRUE
|
||||||
|
Oracle:First strike\nWhen Arcbound Shikari enters the battlefield, put a +1/+1 counter on each other artifact creature you control.\nModular 2 (This creature enters the battlefield with two +1/+1 counters on it. When it does, you may put its counters on target artifact creature.)
|
||||||
14
forge-gui/res/cardsfolder/upcoming/archon_of_cruelty.txt
Normal file
14
forge-gui/res/cardsfolder/upcoming/archon_of_cruelty.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Name:Archon of Cruelty
|
||||||
|
ManaCost:6 B B
|
||||||
|
Types:Creature Archon
|
||||||
|
PT:6/6
|
||||||
|
K:Flying
|
||||||
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigSac | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, target opponent sacrifices a creature or planeswalker, discards a card, and loses 3 life. You draw a card and gain 3 life.
|
||||||
|
T:Mode$ Attacks | ValidCard$ Card.Self | Secondary$ True | Execute$ TrigSac | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, target opponent sacrifices a creature or planeswalker, discards a card, and loses 3 life. You draw a card and gain 3 life.
|
||||||
|
SVar:TrigSac:DB$ Sacrifice | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | SacValid$ Creature,Planeswalker | SacMessage$ creature or planeswalker | SubAbility$ DBDiscard
|
||||||
|
SVar:DBDiscard:DB$ Discard | Defined$ Targeted | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBLoseLife
|
||||||
|
SVar:DBLoseLife:DB$ LoseLife | Defined$ Targeted | LifeAmount$ 3 | SubAbility$ DBDraw
|
||||||
|
SVar:DBDraw:DB$ Draw | SubAbility$ DBGainLife
|
||||||
|
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 3
|
||||||
|
DeckHas:Ability$LifeGain
|
||||||
|
Oracle:Flying\nWhenever Archon of Cruelty enters the battlefield or attacks, target opponent sacrifices a creature or planeswalker, discards a card, and loses 3 life. You draw a card and gain 3 life.
|
||||||
8
forge-gui/res/cardsfolder/upcoming/batterbone.txt
Normal file
8
forge-gui/res/cardsfolder/upcoming/batterbone.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Batterbone
|
||||||
|
ManaCost:2
|
||||||
|
Types:Artifact Equipment
|
||||||
|
K:Living Weapon
|
||||||
|
K:Equip:5
|
||||||
|
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 1 | AddToughness$ 1 | AddKeyword$ Vigilance & Lifelink | Description$ Equipped creature gets +1/+1 and has vigilance and lifelink.
|
||||||
|
DeckHas:Ability$LifeGain & Ability$Token
|
||||||
|
Oracle:Living weapon (When this Equipment enters the battlefield, create a 0/0 black Phyrexian Germ creature token, then attach this to it.)\nEquipped creature gets +1/+1 and has vigilance and lifelink.\nEquip {5}
|
||||||
10
forge-gui/res/cardsfolder/upcoming/bottle_golems.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/bottle_golems.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Bottle Golems
|
||||||
|
ManaCost:4
|
||||||
|
Types:Artifact Creature Golem
|
||||||
|
PT:3/3
|
||||||
|
K:Trample
|
||||||
|
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigSac | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, you gain life equal to its power.
|
||||||
|
SVar:TrigSac:DB$GainLife | Defined$ TriggeredCardController | LifeAmount$ XPower
|
||||||
|
SVar:XPower:TriggeredCard$CardPower
|
||||||
|
DeckHas:Ability$LifeGain
|
||||||
|
Oracle:Trample\nWhen Bottle Golems dies, you gain life equal to its power.
|
||||||
7
forge-gui/res/cardsfolder/upcoming/chatterstorm.txt
Normal file
7
forge-gui/res/cardsfolder/upcoming/chatterstorm.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Chatterstorm
|
||||||
|
ManaCost:1 G
|
||||||
|
Types:Sorcery
|
||||||
|
K:Storm
|
||||||
|
A:SP$ Token | Cost$ 1 G | TokenAmount$ 1 | TokenScript$ g_1_1_squirrel | TokenOwner$ You | SpellDescription$ Create a 1/1 green Squirrel creature token.
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:Create a 1/1 green Squirrel creature token.\nStorm (When you cast this spell, copy it for each spell cast before it this turn.)
|
||||||
11
forge-gui/res/cardsfolder/upcoming/drey_keeper.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/drey_keeper.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Name:Drey Keeper
|
||||||
|
ManaCost:3 B G
|
||||||
|
Types:Creature Elf Druid
|
||||||
|
PT:2/2
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 1/1 green Squirrel creature tokens.
|
||||||
|
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ g_1_1_squirrel | TokenOwner$ You
|
||||||
|
A:AB$ PumpAll | Cost$ 3 B | ValidCards$ Squirrel.YouCtrl | NumAtt$ +1 | KW$ Menace | SpellDescription$ Squirrels you control get +1/+0 and gain menace until end of turn.
|
||||||
|
SVar:PlayMain1:TRUE
|
||||||
|
DeckNeeds:Type$Squirrel
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:When Drey Keeper enters the battlefield, create two 1/1 green Squirrel creature tokens.\n{3}{B}: Squirrels you control get +1/+0 and gain menace until end of turn.
|
||||||
10
forge-gui/res/cardsfolder/upcoming/endurance.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/endurance.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Endurance
|
||||||
|
ManaCost:1 G G
|
||||||
|
Types:Creature Elemental Incarnation
|
||||||
|
PT:3/4
|
||||||
|
K:Flash
|
||||||
|
K:Reach
|
||||||
|
K:Evoke:ExileFromHand<1/Card.Green+Other>
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigBottom | TriggerDescription$ When CARDNAME enters the battlefield, up to one target player puts all the cards from their graveyard on the bottom of their library in a random order.
|
||||||
|
SVar:TrigBottom:DB$ ChangeZoneAll | ValidTgts$ Player | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select up to one target player | ChangeType$ Card | Origin$ Graveyard | Destination$ Library | Reveal$ False | RandomOrder$ True
|
||||||
|
Oracle:Flash\nReach\nWhen Endurance enters the battlefield, up to one target player puts all the cards from their graveyard on the bottom of their library in a random order.\nEvoke — Exile a green card from your hand.
|
||||||
12
forge-gui/res/cardsfolder/upcoming/fae_offering.txt
Normal file
12
forge-gui/res/cardsfolder/upcoming/fae_offering.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Fae Offering
|
||||||
|
ManaCost:2 G
|
||||||
|
Types:Enchantment
|
||||||
|
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ Z | SVarCompare$ GE2 | Execute$ TrigTokenClue | TriggerDescription$ At the beginning of each end step, if you cast a creature and non-creature spell this turn, create a Clue token, a Food token, and a Treasure token.
|
||||||
|
SVar:TrigTokenClue:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_clue_draw | TokenOwner$ You | SubAbility$ TrigTokenFood
|
||||||
|
SVar:TrigTokenFood:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_food_sac | TokenOwner$ You | SubAbility$ TrigTokenTreasure
|
||||||
|
SVar:TrigTokenTreasure:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_treasure_sac | TokenOwner$ You
|
||||||
|
SVar:X:Count$ThisTurnCast_Creature.YouCtrl/LimitMax.1
|
||||||
|
SVar:Y:Count$ThisTurnCast_Card.nonCreature+YouCtrl/LimitMax.1
|
||||||
|
SVar:Z:SVar$X/Plus.Y
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:At the beginning of each end step, if you cast a creature and non-creature spell this turn, create a Clue token, a Food token, and a Treasure token.
|
||||||
16
forge-gui/res/cardsfolder/upcoming/fast_furious.txt
Normal file
16
forge-gui/res/cardsfolder/upcoming/fast_furious.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
Name:Fast
|
||||||
|
ManaCost:2 R
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ Discard | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBDraw | SpellDescription$ Discard a card, then draw two cards.
|
||||||
|
SVar:DBDraw:DB$ Draw | NumCards$ 2
|
||||||
|
DeckHas:Ability$Discard
|
||||||
|
AlternateMode:Split
|
||||||
|
Oracle:Discard a card, then draw two cards.
|
||||||
|
|
||||||
|
ALTERNATE
|
||||||
|
|
||||||
|
Name:Furious
|
||||||
|
ManaCost:3 R R
|
||||||
|
Types:Sorcery
|
||||||
|
A:SP$ DamageAll | ValidCards$ Creature.withoutFlying | NumDmg$ 3 | ValidDescription$ each creature without flying | SpellDescription$ CARDNAME deals 3 damage to each creature without flying.
|
||||||
|
Oracle:Furious deals 3 damage to each creature without flying.
|
||||||
11
forge-gui/res/cardsfolder/upcoming/gaeas_will.txt
Normal file
11
forge-gui/res/cardsfolder/upcoming/gaeas_will.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Name:Gaea's Will
|
||||||
|
ManaCost:no cost
|
||||||
|
Types:Sorcery
|
||||||
|
Colors:green
|
||||||
|
K:Suspend:4:G
|
||||||
|
A:SP$ Effect | Cost$ 0 | Name$ Yawgmoth's Will Effect | ReplacementEffects$ GraveToExile | StaticAbilities$ STPlay | AILogic$ YawgmothsWill | AINoRecursiveCheck$ True | SpellDescription$ Until end of turn, you may play lands and cast spells from your graveyard. If a card would be put into your graveyard from anywhere this turn, exile that card instead.
|
||||||
|
SVar:STPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.YouCtrl | AffectedZone$ Graveyard | MayPlay$ True | Description$ You may play cards from your graveyard.
|
||||||
|
SVar:GraveToExile:Event$ Moved | ActiveZones$ Command | Destination$ Graveyard | ValidCard$ Card.nonToken+YouOwn | ReplaceWith$ Exile | Description$ If a card would be put into your graveyard from anywhere, exile it instead.
|
||||||
|
SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard
|
||||||
|
SVar:PlayMain1:ALWAYS
|
||||||
|
Oracle:Suspend 4 — {G}\nUntil end of turn, you may play lands and cast spells from your graveyard.\nIf a card would be put into your graveyard from anywhere this turn, exile that card instead.
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
Name:General Ferrous Rokiric
|
||||||
|
ManaCost:1 R W
|
||||||
|
Types:Legendary Creature Human Soldier
|
||||||
|
PT:3/1
|
||||||
|
K:Hexproof:Card.MonoColor:monocolored
|
||||||
|
T:Mode$ SpellCast | ValidCard$ Card.MultiColor | ValidActivatingPlayer$ You | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a multicolored spell, create a 4/4 red and white Golem creature token.
|
||||||
|
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ rw_4_4_golem
|
||||||
|
AI:RemoveDeck:Random
|
||||||
|
SVar:BuffedBy:Card.MultiColor
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:Hexproof from monocolored (This creature can't be the target of monocolored spells or abilities your opponents control.)\nWhenever you cast a multicolored spell, create a 4/4 red and white Golem creature token.
|
||||||
14
forge-gui/res/cardsfolder/upcoming/geyadrone_dihada.txt
Normal file
14
forge-gui/res/cardsfolder/upcoming/geyadrone_dihada.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Name:Geyadrone Dihada
|
||||||
|
ManaCost:1 U B R
|
||||||
|
Types:Legendary Planeswalker Dihada
|
||||||
|
Loyalty:4
|
||||||
|
S:Mode$ Continuous | Affected$ Card.Self | AddKeyword$ Protection:Permanent.counters_GE1_CORRUPTION:Protection from permanents with corruption counters on them | Description$ Protection from permanents with corruption counters on them
|
||||||
|
A:AB$ Pump | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Choose up to one other target creature or planeswalker | ValidTgts$ Creature.Other,Planeswalker.Other | SubAbility$ DBLoseLife | SpellDescription$ Each opponent loses 2 life and you gain 2 life. Put a corruption counter on up to one other target creature or planeswalker.
|
||||||
|
SVar:DBLoseLife:DB$ LoseLife | Defined$ Player.Opponent | LifeAmount$ 2 | SubAbility$ DBGainLife
|
||||||
|
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2 | SubAbility$ DBPutCounter
|
||||||
|
SVar:DBPutCounter:DB$ PutCounter | Defined$ Targeted | CounterType$ CORRUPTION | CounterNum$ 1
|
||||||
|
A:AB$ GainControl | Cost$ SubCounter<3/LOYALTY> | Planeswalker$ True | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | LoseControl$ EOT | Untap$ True | AddKWs$ Haste | SubAbility$ DBPutCounter | SpellDescription$ Gain control of target creature or planeswalker until end of turn. Untap it and put a corruption counter on it. It gains haste until end of turn.
|
||||||
|
SVar:DBPutCounter:DB$PutCounter | Defined$ Targeted | CounterType$ CORRUPTION | CounterNum$ 1
|
||||||
|
A:AB$ GainControl | Cost$ SubCounter<7/LOYALTY> | Planeswalker$ True | Ultimate$ True | AllValid$ Permanent.counters_GE1_CORRUPTION | SpellDescription$ Gain control of each permanent with a corruption counter on it.
|
||||||
|
DeckHas:Ability$LifeGain
|
||||||
|
Oracle:Protection from permanents with corruption counters on them\n[+1]: Each opponent loses 2 life and you gain 2 life. Put a corruption counter on up to one other target creature or planeswalker.\n[−3]: Gain control of target creature or planeswalker until end of turn. Untap it and put a corruption counter on it. It gains haste until end of turn.\n[−7]: Gain control of each permanent with a corruption counter on it.
|
||||||
10
forge-gui/res/cardsfolder/upcoming/glinting_creeper.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/glinting_creeper.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Glinting Creeper
|
||||||
|
ManaCost:4 G
|
||||||
|
Types:Creature Plant
|
||||||
|
PT:0/0
|
||||||
|
K:etbCounter:P1P1:Y:no Condition:Converge — CARDNAME enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.
|
||||||
|
K:CantBeBlockedBy Creature.powerLE2
|
||||||
|
SVar:X:Count$Converge
|
||||||
|
SVar:Y:SVar$X/Twice
|
||||||
|
DeckHints:Ability$Counters
|
||||||
|
Oracle:Converge — Glinting Creeper enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it.\nGlinting Creeper can't be blocked by creautures with power 2 or less.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/herd_baloth.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/herd_baloth.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Herd Baloth
|
||||||
|
ManaCost:3 G G
|
||||||
|
Types:Creature Beast
|
||||||
|
PT:4/4
|
||||||
|
T:Mode$ CounterAddedOnce | ValidCard$ Card.Self | TriggerZones$ Battlefield | CounterType$ P1P1 | Execute$ TrigToken | OptionalDecider$ You | TriggerDescription$ Whenever one or more +1/+1 counters are put on CARDNAME, you may create a 4/4 green Beast creature token.
|
||||||
|
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ g_4_4_beast | TokenOwner$ You
|
||||||
|
DeckHints:Ability$Counters
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:Whenever one or more +1/+1 counters are put on Herd Baloth, you may create a 4/4 green Beast creature token.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/ignoble_hierarch.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/ignoble_hierarch.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Ignoble Hierarch
|
||||||
|
ManaCost:G
|
||||||
|
Types:Creature Goblin Shaman
|
||||||
|
PT:0/1
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}.
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ R | SpellDescription$ Add {R}.
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}.
|
||||||
|
K:Exalted
|
||||||
|
Oracle:Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.)\n{T}: Add {B}, {R}, or {G}.
|
||||||
6
forge-gui/res/cardsfolder/upcoming/jade_avenger.txt
Normal file
6
forge-gui/res/cardsfolder/upcoming/jade_avenger.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Name:Jade Avenger
|
||||||
|
ManaCost:1 G
|
||||||
|
Types:Creature Frog Samurai
|
||||||
|
PT:2/2
|
||||||
|
K:Bushido:2
|
||||||
|
Oracle:Bushido 2 (Whenever this creature blocks or becomes blocked, it gets +2/+2 until end of turn.)
|
||||||
@@ -2,9 +2,9 @@ Name:Junk Winder
|
|||||||
ManaCost:5 U U
|
ManaCost:5 U U
|
||||||
Types:Creature Serpent
|
Types:Creature Serpent
|
||||||
PT:5/6
|
PT:5/6
|
||||||
K:Affinity:Permanent.token
|
K:Affinity:Permanent.token:token
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Permanent.token+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigTap | TriggerDescription$ Whenever a token enters the battlefield under your control, tap target nonland permanent an opponent controls. It doesn't untap during its controller's next untap step.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Permanent.token+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigTap | TriggerDescription$ Whenever a token enters the battlefield under your control, tap target nonland permanent an opponent controls. It doesn't untap during its controller's next untap step.
|
||||||
SVar:TrigTap:DB$ Tap | ValidTgts$ Permanent.nonLand+OppCtrl | TgtPrompt$ Choose target nonland permanent an opponent controls | SubAbility$ DBPump
|
SVar:TrigTap:DB$ Tap | ValidTgts$ Permanent.nonLand+OppCtrl | TgtPrompt$ Choose target nonland permanent an opponent controls | SubAbility$ DBPump
|
||||||
SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ HIDDEN This card doesn't untap during your next untap step. | Permanent$ True
|
SVar:DBPump:DB$ Pump | Defined$ Targeted | KW$ HIDDEN This card doesn't untap during your next untap step. | Duration$ Permanent
|
||||||
DeckNeeds:Ability$Token
|
DeckNeeds:Ability$Token
|
||||||
Oracle:Affinity for tokens (This spell costs {1} less to cast for each token you control.)\nWhenever a token enters the battlefield under your control, tap target nonland permanent an opponent controls. It doesn't untap during its controller's next untap step.
|
Oracle:Affinity for tokens (This spell costs {1} less to cast for each token you control.)\nWhenever a token enters the battlefield under your control, tap target nonland permanent an opponent controls. It doesn't untap during its controller's next untap step.
|
||||||
|
|||||||
15
forge-gui/res/cardsfolder/upcoming/lonis_cryptozoologist.txt
Normal file
15
forge-gui/res/cardsfolder/upcoming/lonis_cryptozoologist.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
Name:Lonis, Cryptozoologist
|
||||||
|
ManaCost:G U
|
||||||
|
Types:Legendary Creature Snake Elf Scout
|
||||||
|
PT:1/2
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.YouCtrl+nonToken+Other | TriggerZones$ Battlefield | Execute$ TrigInvestigate | TriggerDescription$ Whenever another nontoken creature enters the battlefield under your control, investigate. (Create a colorless Clue artifact token with "{2}, Sacrifice this artifact: Draw a card.")
|
||||||
|
SVar:TrigInvestigate:DB$ Investigate
|
||||||
|
A:AB$ Dig | Cost$ T Sac<X/Clue> | ValidTgts$ Player.Opponent | TgtPrompt$ Select target opponent | Reveal$ True | NoMove$ True | DigNum$ X | RememberRevealed$ True | DestinationZone$ Library | SubAbility$ PickOne | SpellDescription$ Target opponent reveals the top X cards of their library. You may put a nonland permanent card with mana value X or less from among them onto the battlefield under your control. That player puts the rest on the bottom of their library in a random order.
|
||||||
|
SVar:PickOne:DB$ ChooseCard | Defined$ You | Amount$ 1 | Mandatory$ True | ChoiceTitle$ Choose a nonland permanent to put on the battlefield under your control | Choices$ Permanent.nonLand+cmcLEX+IsRemembered | ChoiceZone$ Library | SubAbility$ MoveChosen
|
||||||
|
SVar:MoveChosen:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | GainControl$ True | Defined$ ChosenCard | SubAbility$ DBBottom
|
||||||
|
SVar:DBBottom:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Library | Destination$ Library | LibraryPosition$ -1 | RandomOrder$ True | SubAbility$ DBCleanup
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
SVar:X:Count$xPaid
|
||||||
|
DeckHints:Ability$Investigate
|
||||||
|
DeckHas:Ability$Investigate & Ability$Token
|
||||||
|
Oracle:Whenever another nontoken creature enters the battlefield under your control, investigate. (Create a colorless Clue artifact token with "{2}, Sacrifice this artifact: Draw a card.")\n{T}, Sacrifice X Clues: Target opponent reveals the top X cards of their library. You may put a nonland permanent card with mana value X or less from among them onto the battlefield under your control. That player puts the rest on the bottom of their library in a random order.
|
||||||
6
forge-gui/res/cardsfolder/upcoming/lose_focus.txt
Normal file
6
forge-gui/res/cardsfolder/upcoming/lose_focus.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Name:Lose Focus
|
||||||
|
ManaCost:1 U
|
||||||
|
Types:Instant
|
||||||
|
K:Replicate:U
|
||||||
|
A:SP$ Counter | Cost$ 1 U | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 2 | SpellDescription$ Counter target spell unless its controller pays {2}.
|
||||||
|
Oracle:Replicate {U} (When you cast this spell, copy it for each time you paid its replicate cost. You may choose new targets for the copies.)\nCounter target spell unless its controller pays {2}.
|
||||||
7
forge-gui/res/cardsfolder/upcoming/moderation.txt
Normal file
7
forge-gui/res/cardsfolder/upcoming/moderation.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Moderation
|
||||||
|
ManaCost:1 W U
|
||||||
|
Types:Enchantment
|
||||||
|
S:Mode$ CantBeCast | ValidCard$ Card | Caster$ You | NumLimitEachTurn$ 1 | Description$ You can't cast more than one spell each turn.
|
||||||
|
T:Mode$ SpellCast | ValidActivatingPlayer$ You | Execute$ TrigDraw | TriggerDescription$ Whenever you cast a spell, draw a card.
|
||||||
|
SVar:TrigDraw:DB$ Draw | NumCards$ 1
|
||||||
|
Oracle:You can't cast more than one spell each turn.\nWhenever you cast a spell, draw a card.
|
||||||
8
forge-gui/res/cardsfolder/upcoming/monoskelion.txt
Normal file
8
forge-gui/res/cardsfolder/upcoming/monoskelion.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Monoskelion
|
||||||
|
ManaCost:2
|
||||||
|
Types:Artifact Creature Construct
|
||||||
|
PT:1/1
|
||||||
|
K:etbCounter:P1P1:1
|
||||||
|
A:AB$ DealDamage | AILogic$ Triskelion | Cost$ SubCounter<1/P1P1> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target.
|
||||||
|
DeckHas:Ability$Counters
|
||||||
|
Oracle:Monoskelion enters the battlefield with a +1/+1 counter on it.\nRemove a +1/+1 counter from Monoskelion: It deals 1 damage to any target.
|
||||||
12
forge-gui/res/cardsfolder/upcoming/nettlecyst.txt
Normal file
12
forge-gui/res/cardsfolder/upcoming/nettlecyst.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Nettlecyst
|
||||||
|
ManaCost:3
|
||||||
|
Types:Artifact Equipment
|
||||||
|
K:Living Weapon
|
||||||
|
K:Equip:2
|
||||||
|
S:Mode$ Continuous | Affected$ Card.EquippedBy | AddPower$ X | AddToughness$ X | Description$ Equipped creature gets +1/+1 for each artifact and/or enchantment you control.
|
||||||
|
SVar:X:Count$Valid Artifact.YouCtrl,Enchantment.YouCtrl
|
||||||
|
SVar:NeedsToPlayVar:X GE1
|
||||||
|
SVar:BuffedBy:Artifact,Enchantment
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
DeckHints:Type$Artifact|Enchantment
|
||||||
|
Oracle:Living weapon (When this Equipment enters the battlefield, create a 0/0 black Germ creature token, then attach this to it.)\nEquipped creature gets +1/+1 for each artifact and/or enchantment you control.\nEquip {2}
|
||||||
9
forge-gui/res/cardsfolder/upcoming/orchard_strider.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/orchard_strider.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Orchard Strider
|
||||||
|
ManaCost:4 G G
|
||||||
|
Types:Creature Treefolk
|
||||||
|
PT:6/4
|
||||||
|
T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two Food tokens. (They're artifacts with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
|
||||||
|
SVar:TrigToken:DB$ Token | TokenScript$ c_a_food_sac | TokenAmount$ 2
|
||||||
|
K:TypeCycling:Basic:1 G
|
||||||
|
DeckHas:Ability$Token & Ability$LifeGain
|
||||||
|
Oracle:When Orchard Strider enters the battlefield, create two Food tokens. (They're artifacts with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")\nBasic landcycling {1}{G} ({1}{G}, Discard this card: Search your library for a basic land card, reveal it, put it into your hand, then shuffle.)
|
||||||
10
forge-gui/res/cardsfolder/upcoming/piru_the_volatile.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/piru_the_volatile.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Piru, the Volatile
|
||||||
|
ManaCost:2 R R W W B B
|
||||||
|
Types:Legendary Creature Elder Dragon
|
||||||
|
PT:7/7
|
||||||
|
K:Flying
|
||||||
|
K:Lifelink
|
||||||
|
K:UpkeepCost:R W B
|
||||||
|
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigDamage | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies, it deals 7 damage to each nonlegendary creature.
|
||||||
|
SVar:TrigDamage:DB$ DamageAll | ValidCards$ Creature.nonLegendary | NumDmg$ 7 | ValidDescription$ each nonlegendary creature.
|
||||||
|
Oracle:Flying, lifelink\nAt the beginning of your upkeep, sacrifice Piru, the Volatile unless you pay {R}{W}{B}.\nWhen Piru dies, it deals 7 damage to each nonlegendary creature.
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Priest of Fell Rites
|
||||||
|
ManaCost:W B
|
||||||
|
Types:Creature Human Warlock
|
||||||
|
PT:2/2
|
||||||
|
A:AB$ ChangeZone | Cost$ T PayLife<3> Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Battlefield | TgtPrompt$ Choose target creature card in your graveyard | ValidTgts$ Creature.YouCtrl | SorcerySpeed$ True | SpellDescription$ Return target creature card from your graveyard to the battlefield.
|
||||||
|
K:Unearth:3 W B
|
||||||
|
Oracle:{T}, Pay 3 life, Sacrifice Priest of Fell Rites: Return target creature card from your graveyard to the battlefield. Activate only as a sorcery.\nUnearth {3}{W}{B} ({3}{W}{B}: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a sorcery.)
|
||||||
12
forge-gui/res/cardsfolder/upcoming/prophetic_titan.txt
Normal file
12
forge-gui/res/cardsfolder/upcoming/prophetic_titan.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Prophetic Titan
|
||||||
|
ManaCost:4 U R
|
||||||
|
Types:Creature Giant Wizard
|
||||||
|
PT:4/4
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ Delirium — When CARDNAME enters the battlefield, choose one. If there are four or more card types in your graveyard, choose both.
|
||||||
|
SVar:TrigCharm:DB$ Charm | CharmNum$ X | Choices$ DBDealDamage,DBDig | AdditionalDescription$ If there are four or more card types in your graveyard, choose both.
|
||||||
|
SVar:DBDealDamage:DB$ DealDamage | ValidTgts$ Creature,Planeswalker,Player | TgtPrompt$ Select any target | NumDmg$ 4 | SpellDescription$ CARDNAME deals 4 damage to any target.
|
||||||
|
SVar:DBDig:DB$ Dig | DigNum$ 4 | RestRandomOrder$ True | SpellDescription$ Look at the top four cards of your library. Put one in your hand and the rest on the bottom of your library in a random order.
|
||||||
|
SVar:X:Count$Compare Y GE4.2.1
|
||||||
|
SVar:Y:Count$CardControllerTypes.Graveyard
|
||||||
|
SVar:PlayMain1:TRUE
|
||||||
|
Oracle:Delirium — When Prophetic Titan enters the battlefield, choose one. If there are four or more card types in your graveyard, choose both.\n• Prophetic Titan deals 4 damage to any target.\n• Look at the top four cards of your library. Put one in your hand and the rest on the bottom of your library in a random order.
|
||||||
7
forge-gui/res/cardsfolder/upcoming/rift_sower.txt
Normal file
7
forge-gui/res/cardsfolder/upcoming/rift_sower.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Rift Sower
|
||||||
|
ManaCost:2 G
|
||||||
|
Types:Creature Elf Druid
|
||||||
|
PT:1/3
|
||||||
|
K:Suspend:2:G
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color.
|
||||||
|
Oracle:{T}: Add one mana of any color.\nSuspend 2—{G} (Rather than cast this card from your hand, you may pay {G} and exile it with two time counters on it. At the beginning of your upkeep, remove a time counter. When the last is removed, cast it without paying its mana cost.)
|
||||||
16
forge-gui/res/cardsfolder/upcoming/road_ruin.txt
Normal file
16
forge-gui/res/cardsfolder/upcoming/road_ruin.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
Name:Road
|
||||||
|
ManaCost:2 G
|
||||||
|
AlternateMode: Split
|
||||||
|
Types:Instant
|
||||||
|
A:SP$ ChangeZone | Cost$ 2 G | Origin$ Library | Destination$ Battlefield | ChangeType$ Land.Basic | ChangeNum$ 1 | Tapped$ True | SpellDescription$ Search your library for a basic land card, put it onto the battlefield tapped, then shuffle.
|
||||||
|
Oracle:Search your library for a basic land card, put it onto the battlefield tapped, then shuffle.
|
||||||
|
|
||||||
|
ALTERNATE
|
||||||
|
|
||||||
|
Name:Ruin
|
||||||
|
ManaCost:1 R R
|
||||||
|
Types:Sorcery
|
||||||
|
K:Aftermath
|
||||||
|
A:SP$ DealDamage | Cost$ 1 R R | ValidTgts$ Creature | TgtPrompt$ Select target creature | NumDmg$ X | SpellDescription$ CARDNAME deals damage to target creature equal to the number of lands you control.
|
||||||
|
SVar:X:Count$TypeYouCtrl.Land
|
||||||
|
Oracle:Ruin deals damage to target creature equal to the number of lands you control.
|
||||||
12
forge-gui/res/cardsfolder/upcoming/sanctifier_en_vec.txt
Normal file
12
forge-gui/res/cardsfolder/upcoming/sanctifier_en_vec.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Sanctifier en-Vec
|
||||||
|
ManaCost:W W
|
||||||
|
Types:Creature Human Cleric
|
||||||
|
PT:2/2
|
||||||
|
K:Protection from black
|
||||||
|
K:Protection from red
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZoneAll | TriggerDescription$ When CARDNAME enters the battlefield, exile all cards that are black or red from all graveyards.
|
||||||
|
SVar:TrigChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Card.Black,Card.Red | Origin$ Graveyard | Destination$ Exile
|
||||||
|
R:Event$ Moved | ActiveZones$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Black,Card.Red | ReplaceWith$ Exile | Description$ If a black or red permanent, spell, or card not on the battlefield would be put into a graveyard, exile it instead.
|
||||||
|
SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard
|
||||||
|
SVar:NonStackingEffect:True
|
||||||
|
Oracle:Protection from black and from red\nWhen Sanctifier en-Vec enters the battlefield, exile all cards that are black or red from all graveyards.\nIf a black or red permanent, spell, or card not on the battlefield would be put into a graveyard, exile it instead.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/sanctuary_raptor.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/sanctuary_raptor.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Sanctuary Raptor
|
||||||
|
ManaCost:3
|
||||||
|
Types:Artifact Creature Bird
|
||||||
|
PT:2/1
|
||||||
|
K:Flying
|
||||||
|
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigPump | IsPresent$ Permanent.token+YouCtrl | PresentCompare$ GE3 | TriggerDescription$ Whenever CARDNAME attacks, if you control three or more tokens, CARDNAME gets +2/+0 and gains first strike until end of turn.
|
||||||
|
SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 2 | KW$ First Strike
|
||||||
|
DeckHints:Ability$Token
|
||||||
|
Oracle:Whenever Sanctuary Raptor attacks, if you control three or more tokens, Sanctuary Raptor gets +2/+0 and gains first strike until end of turn.
|
||||||
7
forge-gui/res/cardsfolder/upcoming/sanctum_weaver.txt
Normal file
7
forge-gui/res/cardsfolder/upcoming/sanctum_weaver.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Sanctum Weaver
|
||||||
|
ManaCost:1 G
|
||||||
|
Types:Enchantment Creature Dryad
|
||||||
|
PT:0/2
|
||||||
|
A:AB$ Mana | Cost$ T | Produced$ Any | Amount$ X | SpellDescription$ Add X mana of any one color, where X is the number of enchantments you control.
|
||||||
|
SVar:X:Count$Valid Enchantment.YouCtrl
|
||||||
|
Oracle:{T}: Add X mana of any one color, where X is the number of enchantments you control.
|
||||||
10
forge-gui/res/cardsfolder/upcoming/scurry_oak.txt
Normal file
10
forge-gui/res/cardsfolder/upcoming/scurry_oak.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Name:Scurry Oak
|
||||||
|
ManaCost:2 G
|
||||||
|
Types:Creature Treefolk
|
||||||
|
PT:1/2
|
||||||
|
K:Evolve
|
||||||
|
T:Mode$ CounterAddedOnce | ValidCard$ Card.Self | TriggerZones$ Battlefield | CounterType$ P1P1 | OptionalDecider$ You | Execute$ TrigSquirrel | TriggerDescription$ Whenever one or more +1/+1 counters are put on CARDNAME, you may create a 1/1 green Squirrel creature token.
|
||||||
|
SVar:TrigSquirrel:DB$ Token | TokenAmount$ 1 | TokenScript$ g_1_1_squirrel | TokenOwner$ You
|
||||||
|
DeckHints:Ability$Counters
|
||||||
|
DeckHas:Ability$Token & Ability$Counters
|
||||||
|
Oracle:Evolve (Whenever a creature enters the battlefield under your control, if that creature has greater power or toughness than this creature, put a +1/+1 counter on this creature.)\nWhenever one or more +1/+1 counters are put on Scurry Oak, you may create a 1/1 green Squirrel creature token.
|
||||||
8
forge-gui/res/cardsfolder/upcoming/shattered_ego.txt
Normal file
8
forge-gui/res/cardsfolder/upcoming/shattered_ego.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Shattered Ego
|
||||||
|
ManaCost:U
|
||||||
|
Types:Enchantment Aura
|
||||||
|
K:Enchant creature
|
||||||
|
A:SP$ Attach | Cost$ U | ValidTgts$ Creature | AILogic$ Curse
|
||||||
|
S:Mode$ Continuous | Affected$ Creature.EnchantedBy | AddPower$ -3 | Description$ Enchanted creature gets -3/-0.
|
||||||
|
A:AB$ ChangeZone | Cost$ 3 U U | Defined$ Enchanted | Origin$ Battlefield | Destination$ Library | LibraryPosition$ 2 | SpellDescription$ Put enchanted creature into its owner's library third from the top.
|
||||||
|
Oracle:Enchant creature\nEnchanted creature gets -3/-0.\n{3}{U}{U}: Put enchanted creature into its owner's library third from the top.
|
||||||
12
forge-gui/res/cardsfolder/upcoming/steel_dromedary.txt
Normal file
12
forge-gui/res/cardsfolder/upcoming/steel_dromedary.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Steel Dromedary
|
||||||
|
ManaCost:3
|
||||||
|
Types:Artifact Creature Camel
|
||||||
|
PT:2/2
|
||||||
|
K:ETBReplacement:Other:CamelTapped
|
||||||
|
SVar:CamelTapped:DB$ Tap | Defined$ Self | ETB$ True | SubAbility$ DBAddCounter | SpellDescription$ CARDNAME enters the battlefield tapped with two +1/+1 counters on it.
|
||||||
|
SVar:DBAddCounter:DB$ PutCounter | ETB$ True | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2
|
||||||
|
S:Mode$ Continuous | Affected$ Card.Self+counters_GE1_P1P1 | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. | Description$ As long as there are +1/+1 counters on CARDNAME, it doesn't untap during your untap step.
|
||||||
|
T:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigMoveCounter | TriggerDescription$ At the beginning of combat on your turn, you may move a +1/+1 counter from CARDNAME onto another target creature.
|
||||||
|
SVar:TrigMoveCounter:DB$ MoveCounter | ValidTgts$ Creature.Other | TgtPrompt$ Select another target creature | Source$ Self | CounterType$ P1P1 | CounterNum$ 1
|
||||||
|
DeckHas:Ability$Counters
|
||||||
|
Oracle:Steel Dromedary enters the battlefield tapped with two +1/+1 counters on it.\nAs long as there are +1/+1 counters on Steel Dromedary, it doesn't untap during your untap step.\nAt the beginning of combat on your turn, you may move a +1/+1 counter from Steel Dromedary onto another target creature.
|
||||||
7
forge-gui/res/cardsfolder/upcoming/strike_it_rich.txt
Normal file
7
forge-gui/res/cardsfolder/upcoming/strike_it_rich.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Strike It Rich
|
||||||
|
ManaCost:R
|
||||||
|
Types:Sorcery
|
||||||
|
K:Flashback:2 R
|
||||||
|
A:SP$ Token | TokenScript$ c_a_treasure_sac | SpellDescription$ Create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")
|
||||||
|
DeckHas:Ability$Token & Ability$Sacrifice
|
||||||
|
Oracle:Create a Treasure token. (It's an artifact with "{T}, Sacrifice this artifact: Add one mana of any color.")\nFlashback {2}{R} (You may cast this card from your graveyard for its flashback cost. Then exile it.)
|
||||||
6
forge-gui/res/cardsfolder/upcoming/sudden_edict.txt
Normal file
6
forge-gui/res/cardsfolder/upcoming/sudden_edict.txt
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
Name:Sudden Edict
|
||||||
|
ManaCost:1 B
|
||||||
|
Types:Instant
|
||||||
|
K:Split second
|
||||||
|
A:SP$ Sacrifice | Cost$ 1 B | ValidTgts$ Player | SacValid$ Creature | SacMessage$ Creature | SpellDescription$ Target player sacrifices a creature.
|
||||||
|
Oracle:Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.)\nTarget player sacrifices a creature.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
Name:Sword of Hearth and Home
|
||||||
|
ManaCost:3
|
||||||
|
Types:Artifact Equipment
|
||||||
|
K:Equip:2
|
||||||
|
S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddToughness$ 2 | AddSVar$ SwordOfHearthAndHomeCE | AddKeyword$ Protection from green & Protection from white | Description$ Equipped creature gets +2/+2 and has protection from green and from white.
|
||||||
|
T:Mode$ DamageDone | ValidSource$ Creature.EquippedBy | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigBlink | TriggerZones$ Battlefield | TriggerDescription$ Whenever equipped creature deals combat damage to a player, exile up to one target creature you own, then search your library for a basic land card. Put both cards onto the battlefield under your control, then shuffle.
|
||||||
|
SVar:TrigBlink:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | ValidTgts$ Creature.YouOwn | TargetMin$ 0 | TargetMax$ 1 | TgtPrompt$ Select target creature you own | SubAbility$ DBLand
|
||||||
|
SVar:DBLand:DB$ ChangeZone | Origin$ Library | Destination$ Library | ChangeType$ Land.Basic | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ DBReturn
|
||||||
|
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Destination$ Battlefield | GainControl$ True | SubAbility$ DBCleanup
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
SVar:SwordOfHearthAndHomeCE:SVar:MustBeBlocked:AttackingPlayerConservative
|
||||||
|
Oracle:Equipped creature gets +2/+2 and has protection from green and from white.\nWhenever equipped creature deals combat damage to a player, exile up to one target creature you own, then search your library for a basic land card. Put both cards onto the battlefield under your control, then shuffle.\nEquip {2}
|
||||||
7
forge-gui/res/cardsfolder/upcoming/sylvan_anthem.txt
Normal file
7
forge-gui/res/cardsfolder/upcoming/sylvan_anthem.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Name:Sylvan Anthem
|
||||||
|
ManaCost:G G
|
||||||
|
Types:Enchantment
|
||||||
|
S:Mode$ Continuous | Affected$ Creature.Green+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Green creatures you control get +1/+1.
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.Green+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigScry | TriggerDescription$ Whenever a green creature enters the battlefield under your control, scry 1. (Look at the top card of your library. You may put that card on the bottom of your library.)
|
||||||
|
SVar:TrigScry:DB$ Scry | ScryNum$ 1
|
||||||
|
Oracle:Green creatures you control get +1/+1.\nWhenever a green creature enters the battlefield under your control, scry 1.
|
||||||
14
forge-gui/res/cardsfolder/upcoming/territorial_kavu.txt
Normal file
14
forge-gui/res/cardsfolder/upcoming/territorial_kavu.txt
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Name:Territorial Kavu
|
||||||
|
ManaCost:R G
|
||||||
|
Types:Creature Kavu
|
||||||
|
PT:*/*
|
||||||
|
S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | SetToughness$ X | Description$ Domain — CARDNAME's power and toughness are each equal to the number of basic land types among lands you control.
|
||||||
|
SVar:X:Count$Domain
|
||||||
|
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ Whenever CARDNAME attacks, ABILITY
|
||||||
|
SVar:TrigCharm:DB$ Charm | Choices$ DBDiscard,DBExile
|
||||||
|
SVar:DBDiscard:DB$ Discard | NumCards$ 1 | Mode$ TgtChoose | RememberDiscarded$ True | SubAbility$ DBDraw | SpellDescription$ Discard a card. If you do, draw a card.
|
||||||
|
SVar:DBDraw:DB$ Draw | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ GE1 | SubAbility$ DBCleanup
|
||||||
|
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||||
|
SVar:DBExile:DB$ ChangeZone | ValidTgts$ Card | TgtPrompt$ Select up to one target card in a graveyard | TargetMin$ 0 | TargetMax$ 1 | Origin$ Graveyard | Destination$ Exile | SpellDescription$ Exile up to one target card from a graveyard.
|
||||||
|
DeckHas:Ability$Discard
|
||||||
|
Oracle:Domain — Territorial Kavu's power and toughness are each equal to the number of basic land types among lands you control.\nWhenever Territorial Kavu attacks, choose one —\n• Discard a card. If you do, draw a card.\n• Exile up to one target card from a graveyard.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/thraben_watcher.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/thraben_watcher.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Thraben Watcher
|
||||||
|
ManaCost:2 W W
|
||||||
|
Types:Creature Angel
|
||||||
|
PT:2/2
|
||||||
|
K:Flying
|
||||||
|
K:Vigilance
|
||||||
|
S:Mode$ Continuous | Affected$ Creature.nonToken+Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | AddKeyword$ Vigilance | Description$ Other nontoken creatures you control get +1/+1 and have vigilance.
|
||||||
|
SVar:PlayMain1:TRUE
|
||||||
|
Oracle:Flying, vigilance\nOther nontoken creatures you control get +1/+1 and have vigilance.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/timeless_witness.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/timeless_witness.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Timeless Witness
|
||||||
|
ManaCost:2 G G
|
||||||
|
Types:Creature Human Shaman
|
||||||
|
PT:2/1
|
||||||
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZone | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield, you may return target card from your graveyard to your hand.
|
||||||
|
SVar:TrigChangeZone:DB$ChangeZone | Origin$ Graveyard | Destination$ Hand | ValidTgts$ Card.YouCtrl
|
||||||
|
K:Eternalize:5 G G
|
||||||
|
DeckHas:Ability$Token
|
||||||
|
Oracle:When Eternal Witness enters the battlefield, you may return target card from your graveyard to your hand.\nEternalize {5}{G}{G} ({5}{G}{G}, Exile this card from your graveyard: Create a token that's a copy of it, except it's a 4/4 black Zombie Human Shaman with no mana cost. Eternalize only as a sorcery.)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
Name:Tormod's Cryptkeeper
|
||||||
|
ManaCost:3
|
||||||
|
Types:Artifact Creature Golem
|
||||||
|
PT:3/2
|
||||||
|
K:Vigilance
|
||||||
|
A:AB$ ChangeZoneAll | Cost$ T Sac<1/CARDNAME> | Origin$ Graveyard | Destination$ Exile | ValidTgts$ Player | TgtPrompt$ Select target player | ChangeType$ Card | SpellDescription$ Exile all cards from target player's graveyard.
|
||||||
|
AI:RemoveDeck:Random
|
||||||
|
Oracle:Vigilance\n{T}, Sacrifice Tormod's Cryptkeeper: Exile all cards from target player's graveyard.
|
||||||
9
forge-gui/res/cardsfolder/upcoming/urban_daggertooth.txt
Normal file
9
forge-gui/res/cardsfolder/upcoming/urban_daggertooth.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Name:Urban Daggertooth
|
||||||
|
ManaCost:2 G G
|
||||||
|
Types:Creature Dinosaur
|
||||||
|
PT:4/3
|
||||||
|
K:Vigilance
|
||||||
|
T:Mode$ DamageDoneOnce | Execute$ TrigProliferate | ValidTarget$ Card.Self | TriggerZones$ Battlefield | TriggerDescription$ Enrage — Whenever CARDNAME is dealt damage, proliferate.
|
||||||
|
SVar:TrigProliferate:DB$Proliferate
|
||||||
|
SVar:HasCombatEffect:TRUE
|
||||||
|
Oracle:Enrage — Whenever Urban Daggertooth is dealt damage, proliferate. (Choose any number of permanents and/or players, then give each another counter of each kind already there.)
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Name:Yavimaya, Cradle of Growth
|
||||||
|
ManaCost:no cost
|
||||||
|
Types:Legendary Land
|
||||||
|
S:Mode$ Continuous | Affected$ Land | AddType$ Forest | Description$ Each land is a Forest in addition to its other land types.
|
||||||
|
AI:RemoveDeck:Random
|
||||||
|
Oracle:Each land is a Forest in addition to its other land types.
|
||||||
@@ -3,10 +3,9 @@ ManaCost:3 G G G
|
|||||||
Types:Creature Elemental Incarnation
|
Types:Creature Elemental Incarnation
|
||||||
PT:6/6
|
PT:6/6
|
||||||
K:Trample
|
K:Trample
|
||||||
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Creature.YouCtrl+Other | ReplaceWith$ Counters | PreventionEffect$ True | Description$ If damage would be dealt to another creature you control, prevent that damage. Put a +1/+1 counter on that creature for each 1 damage prevented this way.
|
R:Event$ DamageDone | ActiveZones$ Battlefield | ValidTarget$ Creature.YouCtrl+Other | ReplaceWith$ Counters | PreventionEffect$ True | ExecuteMode$ PerTarget | Description$ If damage would be dealt to another creature you control, prevent that damage. Put a +1/+1 counter on that creature for each 1 damage prevented this way.
|
||||||
SVar:Counters:DB$PutCounter | Defined$ ReplacedTarget | CounterType$ P1P1 | CounterNum$ X
|
SVar:Counters:DB$PutCounter | Defined$ ReplacedTarget | CounterType$ P1P1 | CounterNum$ X
|
||||||
SVar:X:ReplaceCount$DamageAmount
|
SVar:X:ReplaceCount$DamageAmount
|
||||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.Self | Execute$ TrigShuffle | TriggerDescription$ When CARDNAME is put into a graveyard from anywhere, shuffle it into its owner's library.
|
T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.Self | Execute$ TrigShuffle | TriggerDescription$ When CARDNAME is put into a graveyard from anywhere, shuffle it into its owner's library.
|
||||||
SVar:TrigShuffle:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | Shuffle$ True | Defined$ TriggeredCardLKICopy
|
SVar:TrigShuffle:DB$ ChangeZone | Origin$ Graveyard | Destination$ Library | Shuffle$ True | Defined$ TriggeredCardLKICopy
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/vigor.jpg
|
|
||||||
Oracle:Trample\nIf damage would be dealt to another creature you control, prevent that damage. Put a +1/+1 counter on that creature for each 1 damage prevented this way.\nWhen Vigor is put into a graveyard from anywhere, shuffle it into its owner's library.
|
Oracle:Trample\nIf damage would be dealt to another creature you control, prevent that damage. Put a +1/+1 counter on that creature for each 1 damage prevented this way.\nWhen Vigor is put into a graveyard from anywhere, shuffle it into its owner's library.
|
||||||
|
|||||||
@@ -320,6 +320,7 @@ Dack
|
|||||||
Dakkon
|
Dakkon
|
||||||
Daretti
|
Daretti
|
||||||
Davriel
|
Davriel
|
||||||
|
Dihada
|
||||||
Domri
|
Domri
|
||||||
Dovin
|
Dovin
|
||||||
Duck
|
Duck
|
||||||
|
|||||||
Reference in New Issue
Block a user