Merge branch 'master' into AFC_Cards_20210717

This commit is contained in:
Wendell Wilkerson
2021-07-18 11:53:10 -05:00
334 changed files with 245 additions and 131 deletions

View File

@@ -229,12 +229,12 @@ public class GameCopier {
private static final boolean USE_FROM_PAPER_CARD = true;
private Card createCardCopy(Game newGame, Player newOwner, Card c) {
if (c.isToken() && !c.isEmblem()) {
if (c.isToken() && !c.isImmutable()) {
Card result = new TokenInfo(c).makeOneToken(newOwner);
CardFactory.copyCopiableCharacteristics(c, result);
return result;
}
if (USE_FROM_PAPER_CARD && !c.isEmblem() && c.getPaperCard() != null) {
if (USE_FROM_PAPER_CARD && !c.isImmutable() && c.getPaperCard() != null) {
Card newCard = Card.fromPaperCard(c.getPaperCard(), newOwner);
newCard.setCommander(c.isCommander());
return newCard;

View File

@@ -58,7 +58,6 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
Conspiracy(false, "conspiracies"),
Creature(true, "creatures"),
Dungeon(false, "dungeons"),
Emblem(false, "emblems"),
Enchantment(true, "enchantments"),
Instant(false, "instants"),
Land(true, "lands"),
@@ -437,11 +436,6 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
return coreTypes.contains(CoreType.Phenomenon);
}
@Override
public boolean isEmblem() {
return coreTypes.contains(CoreType.Emblem);
}
@Override
public boolean isTribal() {
return coreTypes.contains(CoreType.Tribal);
@@ -547,7 +541,7 @@ public final class CardType implements Comparable<CardType>, CardTypeView {
if (!isInstant() && !isSorcery()) {
Iterables.removeIf(subtypes, Predicates.IS_SPELL_TYPE);
}
if (!isPlaneswalker() && !isEmblem()) {
if (!isPlaneswalker()) {
Iterables.removeIf(subtypes, Predicates.IS_WALKER_TYPE);
}
}

View File

@@ -42,7 +42,6 @@ public interface CardTypeView extends Iterable<String>, Serializable {
boolean isBasicLand();
boolean isPlane();
boolean isPhenomenon();
boolean isEmblem();
boolean isTribal();
boolean isDungeon();
CardTypeView getTypeWithChanges(Iterable<CardChangedType> changedCardTypes);

View File

@@ -153,8 +153,7 @@ public final class GameActionUtil {
final StringBuilder sb = new StringBuilder(sa.getDescription());
if (!source.equals(host)) {
sb.append(" by ");
if ((host.isEmblem() || host.getType().hasSubtype("Effect"))
&& host.getEffectSource() != null) {
if ((host.isImmutable()) && host.getEffectSource() != null) {
sb.append(host.getEffectSource());
} else {
sb.append(host);
@@ -542,7 +541,6 @@ public final class GameActionUtil {
final Card eff = new Card(game.nextCardId(), game);
eff.setTimestamp(game.getNextTimestamp());
eff.setName(sourceCard.getName() + "'s Effect");
eff.addType("Effect");
eff.setOwner(controller);
eff.setImageKey(sourceCard.getImageKey());

View File

@@ -112,9 +112,9 @@ public class AbilityUtils {
// Probably will move to One function solution sometime in the future
public static CardCollection getDefinedCards(final Card hostCard, final String def, final CardTraitBase sa) {
CardCollection cards = new CardCollection();
String defined = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self
final String[] incR = defined.split("\\.", 2);
defined = incR[0];
String changedDef = (def == null) ? "Self" : applyAbilityTextChangeEffects(def, sa); // default to Self
final String[] incR = changedDef.split("\\.", 2);
String defined = incR[0];
final Game game = hostCard.getGame();
Card c = null;
@@ -132,7 +132,7 @@ public class AbilityUtils {
}
}
else if (defined.equals("EffectSource")) {
if (hostCard.isEmblem() || hostCard.getType().hasSubtype("Effect")) {
if (hostCard.isImmutable()) {
c = findEffectRoot(hostCard);
}
}
@@ -346,6 +346,23 @@ public class AbilityUtils {
cards.add(game.getCardState(cardByID));
}
}
} else if (defined.startsWith("Valid")) {
Iterable<Card> candidates;
String validDefined;
if (defined.startsWith("Valid ")) {
candidates = game.getCardsIn(ZoneType.Battlefield);
validDefined = changedDef.substring("Valid ".length());
} else if (defined.startsWith("ValidAll ")) {
candidates = game.getCardsInGame();
validDefined = changedDef.substring("ValidAll ".length());
} else {
String[] s = changedDef.split(" ", 2);
String zone = s[0].substring("Valid".length());
candidates = game.getCardsIn(ZoneType.smartValueOf(zone));
validDefined = s[1];
}
cards.addAll(CardLists.getValidCards(candidates, validDefined.split(","), hostCard.getController(), hostCard, sa));
return cards;
} else {
CardCollection list = null;
if (sa instanceof SpellAbility) {
@@ -377,19 +394,6 @@ public class AbilityUtils {
}
}
if (defined.startsWith("Valid ")) {
String validDefined = defined.substring("Valid ".length());
list = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), validDefined.split(","), hostCard.getController(), hostCard, sa);
} else if (defined.startsWith("ValidAll ")) {
String validDefined = defined.substring("ValidAll ".length());
list = CardLists.getValidCards(game.getCardsInGame(), validDefined.split(","), hostCard.getController(), hostCard, sa);
} else if (defined.startsWith("Valid")) {
String[] s = defined.split(" ");
String zone = s[0].substring("Valid".length());
String validDefined = s[1];
list = CardLists.getValidCards(game.getCardsIn(ZoneType.smartValueOf(zone)), validDefined.split(","), hostCard.getController(), hostCard, sa);
}
if (list != null) {
cards.addAll(list);
}
@@ -421,7 +425,7 @@ public class AbilityUtils {
private static Card findEffectRoot(Card startCard) {
Card cc = startCard.getEffectSource();
if (cc != null) {
if (cc.isEmblem() || cc.getType().hasSubtype("Effect")) {
if (cc.isImmutable()) {
return findEffectRoot(cc);
}
return cc;

View File

@@ -13,7 +13,6 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import forge.GameCommand;
import forge.card.CardType;
import forge.card.MagicColor;
import forge.game.Game;
import forge.game.GameEntity;
@@ -457,25 +456,19 @@ public abstract class SpellAbilityEffect {
final Card eff = new Card(game.nextCardId(), game);
eff.setTimestamp(game.getNextTimestamp());
eff.setName(name);
eff.setColor(hostCard.determineColor().getColor());
// if name includes emblem then it should be one
eff.addType(name.startsWith("Emblem") ? "Emblem" : "Effect");
// add Planeswalker types into Emblem for fun
if (name.startsWith("Emblem") && hostCard.isPlaneswalker()) {
for (final String type : hostCard.getType().getSubtypes()) {
if (CardType.isAPlaneswalkerType(type)) {
eff.addType(type);
}
}
if (name.startsWith("Emblem")) {
eff.setEmblem(true);
// Emblem needs to be colorless
eff.setColor(MagicColor.COLORLESS);
}
eff.setOwner(controller);
eff.setSVars(sa.getSVars());
eff.setImageKey(image);
if (eff.getType().hasType(CardType.CoreType.Emblem)) {
eff.setColor(MagicColor.COLORLESS);
} else {
eff.setColor(hostCard.determineColor().getColor());
}
eff.setImmutable(true);
eff.setEffectSource(sa);

View File

@@ -190,11 +190,6 @@ public class AnimateEffect extends AnimateEffectBase {
}
}
// Restore immutable to effect
if (sa.hasParam("Immutable")) {
c.setImmutable(true);
}
game.fireEvent(new GameEventCardStatsChanged(c));
}

View File

@@ -164,14 +164,6 @@ public abstract class AnimateEffectBase extends SpellAbilityEffect {
final Trigger parsedTrigger = TriggerHandler.parseTrigger(AbilityUtils.getSVar(sa, s), c, false, sa);
addedTriggers.add(parsedTrigger);
}
if (sa.hasParam("GainsTriggeredAbilitiesOf")) {
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("GainsTriggeredAbilitiesOf"), sa);
for (final Card card : cards) {
for (Trigger t : card.getTriggers()) {
addedTriggers.add(t.copy(c, false));
}
}
}
// give replacement effects
final List<ReplacementEffect> addedReplacements = Lists.newArrayList();

View File

@@ -12,7 +12,6 @@ public class DetachedCardEffect extends Card {
card = card0;
setName(name0);
addType("Effect");
setOwner(card0.getOwner());
setImmutable(true);

View File

@@ -140,10 +140,6 @@ public class EffectEffect extends SpellAbilityEffect {
final Card eff = createEffect(sa, controller, name, image);
eff.setSetCode(sa.getHostCard().getSetCode());
eff.setRarity(sa.getHostCard().getRarity());
// For Raging River effect to add attacker "left" or "right" pile later
if (sa.hasParam("Mutable")) {
eff.setImmutable(false);
}
// Abilities and triggers work the same as they do for Token
// Grant abilities

View File

@@ -37,7 +37,7 @@ public class RegenerationEffect extends SpellAbilityEffect {
// Play the Regen sound
game.fireEvent(new GameEventCardRegenerated());
if (host.getType().hasStringType("Effect")) {
if (host.isImmutable()) {
c.subtractShield(host);
host.removeRemembered(c);
}

View File

@@ -47,7 +47,7 @@ public class ReplaceDamageEffect extends SpellAbilityEffect {
prevent -= n;
if (!StringUtils.isNumeric(varValue) && card.getSVar(varValue).startsWith("Number$")) {
if (card.getType().hasStringType("Effect") && prevent <= 0) {
if (card.isImmutable() && prevent <= 0) {
game.getAction().exile(card, null);
} else {
card.setSVar(varValue, "Number$" + prevent);

View File

@@ -45,7 +45,7 @@ public class ReplaceSplitDamageEffect extends SpellAbilityEffect {
dmg -= n;
prevent -= n;
if (card.getType().hasStringType("Effect") && prevent <= 0) {
if (card.isImmutable() && prevent <= 0) {
game.getAction().exile(card, null);
} else if (!StringUtils.isNumeric(varValue)) {
sa.setSVar(varValue, "Number$" + prevent);

View File

@@ -31,6 +31,7 @@ import forge.game.event.GameEventCardStatsChanged;
import forge.game.player.Player;
import forge.game.replacement.ReplacementType;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.Trigger;
import forge.game.zone.ZoneType;
public abstract class TokenEffectBase extends SpellAbilityEffect {
@@ -138,6 +139,15 @@ public abstract class TokenEffectBase extends SpellAbilityEffect {
tok.addEtbCounter(cType, cAmount, creator);
}
if (sa.hasParam("AddTriggersFrom")) {
final List<Card> cards = AbilityUtils.getDefinedCards(host, sa.getParam("AddTriggersFrom"), sa);
for (final Card card : cards) {
for (final Trigger trig : card.getTriggers()) {
tok.addTrigger(trig.copy(tok, false));
}
}
}
if (clone) {
tok.setCopiedPermanent(prototype);
}

View File

@@ -264,6 +264,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
// for Vanguard / Manapool / Emblems etc.
private boolean isImmutable = false;
private boolean isEmblem = false;
private int exertThisTurn = 0;
private PlayerCollection exertedByPlayer = new PlayerCollection();
@@ -4598,15 +4599,13 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
public final boolean isPermanent() {
return !isImmutable && (isInZone(ZoneType.Battlefield) || getType().isPermanent());
return !isImmutable() && (isInZone(ZoneType.Battlefield) || getType().isPermanent());
}
public final boolean isSpell() {
return (isInstant() || isSorcery() || (isAura() && !isInZone((ZoneType.Battlefield))));
}
public final boolean isEmblem() { return getType().isEmblem(); }
public final boolean isLand() { return getType().isLand(); }
public final boolean isBasicLand() { return getType().isBasicLand(); }
public final boolean isSnow() { return getType().isSnow(); }
@@ -4865,11 +4864,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
// Takes one argument like Permanent.Blue+withFlying
@Override
public final boolean isValid(final String restriction, final Player sourceController, final Card source, CardTraitBase spellAbility) {
if (isImmutable() && source != null && !source.isRemembered(this) &&
!(restriction.startsWith("Emblem") || restriction.startsWith("Effect"))) { // special case exclusion
return false;
}
// Inclusive restrictions are Card types
final String[] incR = restriction.split("\\.", 2);
@@ -4879,14 +4873,27 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
incR[0] = incR[0].substring(1); // consume negation sign
}
if (incR[0].equals("Spell") && !isSpell()) {
return testFailed;
}
if (incR[0].equals("Permanent") && !isPermanent()) {
return testFailed;
}
if (!incR[0].equals("card") && !incR[0].equals("Card") && !incR[0].equals("Spell")
&& !incR[0].equals("Permanent") && !getType().hasStringType(incR[0])) {
if (incR[0].equals("Spell")) {
if (!isSpell()) {
return testFailed;
}
} else if (incR[0].equals("Permanent")) {
if (!isPermanent()) {
return testFailed;
}
} else if (incR[0].equals("Effect")) {
if (!isImmutable()) {
return testFailed;
}
} else if (incR[0].equals("Emblem")) {
if (!isEmblem()) {
return testFailed;
}
} else if (incR[0].equals("card") || incR[0].equals("Card")) {
if (isImmutable()) {
return testFailed;
}
} else if (!getType().hasStringType(incR[0])) {
return testFailed; // Check for wrong type
}
@@ -4916,6 +4923,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
public final void setImmutable(final boolean isImmutable0) {
isImmutable = isImmutable0;
view.updateImmutable(this);
}
public final boolean isEmblem() {
return isEmblem;
}
public final void setEmblem(final boolean isEmblem0) {
isEmblem = isEmblem0;
view.updateEmblem(this);
}
/*

View File

@@ -357,7 +357,7 @@ public class CardProperty {
return false;
}
} else if (property.equals("EffectSource")) {
if (!source.isEmblem() && !source.getType().hasSubtype("Effect")) {
if (!source.isImmutable()) {
return false;
}

View File

@@ -242,6 +242,7 @@ public final class CardUtil {
newCopy.setToken(in.isToken());
newCopy.setCopiedSpell(in.isCopiedSpell());
newCopy.setImmutable(in.isImmutable());
newCopy.setEmblem(in.isEmblem());
// lock in the current P/T
newCopy.setBasePower(in.getCurrentPower());

View File

@@ -233,6 +233,20 @@ public class CardView extends GameEntityView {
set(TrackableProperty.Token, c.isToken());
}
public boolean isImmutable() {
return get(TrackableProperty.IsImmutable);
}
public void updateImmutable(Card c) {
set(TrackableProperty.IsImmutable, c.isImmutable());
}
public boolean isEmblem() {
return get(TrackableProperty.IsEmblem);
}
public void updateEmblem(Card c) {
set(TrackableProperty.IsEmblem, c.isEmblem());
}
public boolean isTokenCard() { return get(TrackableProperty.TokenCard); }
void updateTokenCard(Card c) { set(TrackableProperty.TokenCard, c.isTokenCard()); }

View File

@@ -3176,6 +3176,7 @@ public class Player extends GameEntity implements Comparable<Player> {
if (monarchEffect == null) {
monarchEffect = new Card(game.nextCardId(), null, game);
monarchEffect.setOwner(this);
monarchEffect.setImmutable(true);
if (set != null) {
monarchEffect.setImageKey("t:monarch_" + set.toLowerCase());
monarchEffect.setSetCode(set);
@@ -3183,7 +3184,6 @@ public class Player extends GameEntity implements Comparable<Player> {
monarchEffect.setImageKey("t:monarch");
}
monarchEffect.setName("The Monarch");
monarchEffect.addType("Effect");
{
final String drawTrig = "Mode$ Phase | Phase$ End of Turn | TriggerZones$ Command | " +
@@ -3280,8 +3280,7 @@ public class Player extends GameEntity implements Comparable<Player> {
blessingEffect.setOwner(this);
blessingEffect.setImageKey("t:blessing");
blessingEffect.setName("City's Blessing");
blessingEffect.addType("Effect");
blessingEffect.setImmutable(true);
blessingEffect.updateStateForView();
@@ -3353,7 +3352,6 @@ public class Player extends GameEntity implements Comparable<Player> {
keywordEffect.setOwner(this);
keywordEffect.setName("Keyword Effects");
keywordEffect.setImageKey(ImageKeys.HIDDEN_CARD);
keywordEffect.addType("Effect");
keywordEffect.updateStateForView();

View File

@@ -220,7 +220,7 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
if (hasParam("Description") && !this.isSuppressed()) {
String desc = AbilityUtils.applyDescriptionTextChangeEffects(getParam("Description"), this);
String currentName;
if (this.isIntrinsic() && !this.getHostCard().isMutated() && cardState != null) {
if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) {
currentName = cardState.getName();
}
else {

View File

@@ -95,8 +95,7 @@ public class LandAbility extends Ability {
Card source = sta.getHostCard();
if (!source.equals(getHostCard())) {
sb.append(" by ");
if ((source.isEmblem() || source.getType().hasSubtype("Effect"))
&& source.getEffectSource() != null) {
if (source.isImmutable() && source.getEffectSource() != null) {
sb.append(source.getEffectSource());
} else {
sb.append(source);

View File

@@ -854,7 +854,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
if (node.getHostCard() != null) {
String currentName;
// if alternate state is viewed while card uses original
if (node.isIntrinsic() && !node.getHostCard().isMutated() && node.cardState != null) {
if (node.isIntrinsic() && node.cardState != null && node.cardState.getCard() == node.getHostCard()) {
currentName = node.cardState.getName();
}
else {

View File

@@ -209,7 +209,7 @@ public class StaticAbility extends CardTraitBase implements IIdentifiable, Clone
public final String toString() {
if (hasParam("Description") && !this.isSuppressed()) {
String currentName;
if (this.isIntrinsic() && !this.getHostCard().isMutated() && cardState != null) {
if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) {
currentName = cardState.getName();
}
else {

View File

@@ -132,7 +132,7 @@ public abstract class Trigger extends TriggerReplacementBase {
StringBuilder sb = new StringBuilder();
String currentName;
if (this.isIntrinsic() && !this.getHostCard().isMutated() && cardState != null) {
if (this.isIntrinsic() && cardState != null && cardState.getCard() == getHostCard()) {
currentName = cardState.getName();
}
else {

View File

@@ -24,6 +24,9 @@ public enum TrackableProperty {
Controller(TrackableTypes.PlayerViewType),
Zone(TrackableTypes.EnumType(ZoneType.class)),
IsImmutable(TrackableTypes.BooleanType),
IsEmblem(TrackableTypes.BooleanType),
Flipped(TrackableTypes.BooleanType),
Facedown(TrackableTypes.BooleanType),
Foretold(TrackableTypes.BooleanType),

View File

@@ -311,7 +311,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
final CardStateView state = getCard().getCurrentState();
final CardEdition ed = FModel.getMagicDb().getEditions().get(state.getSetCode());
boolean colorIsSet = false;
if (state.getType().isEmblem() || state.getType().hasStringType("Effect")) {
if (getCard().isImmutable()) {
// Effects are drawn with orange border
g2d.setColor(Color.ORANGE);
colorIsSet = true;

View File

@@ -362,8 +362,7 @@ public class CardImageRenderer {
drawDetails(g, card, gameView, altState, x, y, w, h);
return;
}
if(card.isToken() && card.getCurrentState().getType().hasSubtype("Effect")
&& FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_IMAGES_EFFECT_CARDS)){
if(card.isImmutable() && FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DISABLE_IMAGES_EFFECT_CARDS)){
drawDetails(g, card, gameView, altState, x, y, w, h);
return;
}

View File

@@ -0,0 +1,16 @@
Name:Catti-brie of Mithral Hall
ManaCost:G W
Types:Legendary Creature Human Archer
PT:2/2
K:First Strike
K:Reach
T:Mode$ Attacks | ValidCard$ Creature.Self | Execute$ TrigPutCounter | TriggerDescription$ Whenever CARDNAME attacks, put a +1/+1 counter on it for each Equipment attached to it.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ Y
SVar:Y:Count$Valid Equipment.Attached
A:AB$ DealDamage | Cost$ 1 SubCounter<All/P1P1> | NumDmg$ X | ValidTgts$ Creature.attacking+OppCtrl,Creature.blocking+OppCtrl | TgtPrompt$ Select target attacking or blocking creature an opponent controls | SpellDescription$ It deals X damage to target attacking or blocking creature an opponent controls, where X is the number of counters removed this way.
SVar:X:SVar$CostCountersRemoved
SVar:HasAttackEffect:TRUE
SVar:EquipMe:Multiple
DeckNeeds:Type$Equipment
DeckHas:Ability$Counters
Oracle:First strike, reach\nWhenever Catti-brie of Mithral Hall attacks, put a +1/+1 counter on it for each Equipment attached to it.\n{1}, Remove all +1/+1 counters from Catti-brie: It deals X damage to target attacking or blocking creature an opponent controls, where X is the number of counters removed this way.

View File

@@ -5,9 +5,11 @@ PT:3/2
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ DBLoop | TriggerDescription$ Whenever CARDNAME attacks, choose target creature you control, then ABILITY
SVar:DBLoop:DB$ Repeat | ValidTgts$ Creature.YouCtrl | RepeatCheckSVar$ RepeatCheck | RepeatSVarCompare$ GT0 | RepeatSubAbility$ DBRollDice | RepeatOptional$ True
SVar:DBRollDice:DB$ RollDice | Sides$ 20 | ResultSubAbilities$ 1-14:DBCopy,15-20:DBCopyRepeat | SpellDescription$ roll a d20.
SVar:DBCopy:DB$ CopyPermanent | Defined$ Targeted | TokenTapped$ True | TokenAttacking$ True | NonLegendary$ True | AtEOT$ ExileCombat | SubAbility$ DBNotRepeat | SpellDescription$ 1-14 VERT Create a tapped and attacking token that's a copy of that creature, except it's not legendary and it has "Exile this creature at end of combat.
SVar:DBCopy:DB$ CopyPermanent | Defined$ Targeted | TokenTapped$ True | TokenAttacking$ True | NonLegendary$ True | AddSVars$ DelinaTrigExile | AddTriggers$ TrigPhase | SubAbility$ DBNotRepeat | SpellDescription$ 1-14 VERT Create a tapped and attacking token that's a copy of that creature, except it's not legendary and it has "Exile this creature at end of combat.
SVar:DBNotRepeat:DB$ StoreSVar | SVar$ RepeatCheck | Type$ Number | Expression$ 0
SVar:DBCopyRepeat:DB$ CopyPermanent | Defined$ Targeted | TokenTapped$ True | TokenAttacking$ True | NonLegendary$ True | AtEOT$ ExileCombat | SubAbility$ DBRepeat | SpellDescription$ 15-20 VERT Create one of those tokens. You may roll again.
SVar:DBCopyRepeat:DB$ CopyPermanent | Defined$ Targeted | TokenTapped$ True | TokenAttacking$ True | NonLegendary$ True | AddSVars$ DelinaTrigExile | AddTriggers$ TrigPhase | SubAbility$ DBRepeat | SpellDescription$ 15-20 VERT Create one of those tokens. You may roll again.
SVar:TrigPhase:Mode$ Phase | Phase$ EndCombat | TriggerZones$ Battlefield | Execute$ DelinaTrigExile | TriggerDescription$ Exile this creature at end of combat.
SVar:DelinaTrigExile:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile
SVar:DBRepeat:DB$ StoreSVar | SVar$ RepeatCheck | Type$ Number | Expression$ 1
SVar:RepeatCheck:Number$1
SVar:HasAttackEffect:TRUE

View File

@@ -5,7 +5,7 @@ PT:3/4
T:Mode$ Phase | Phase$ EndCombat | Execute$ TrigCounter | TriggerZones$ Battlefield | TriggerDescription$ At end of combat, put a paralyzation counter on each creature blocking or blocked by CARDNAME and tap those creatures. Each of those creatures doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it. Each of those creatures gains "{4}: Remove a paralyzation counter from this creature."
SVar:TrigCounter:DB$ PutCounterAll | CounterType$ PARALYZATION | CounterNum$ 1 | ValidCards$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBTap
SVar:DBTap:DB$ TapAll | ValidCards$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBEffect
SVar:DBEffect:DB$ Effect | RememberObjects$ Valid Creature.blockedBySource,Valid Creature.blockingSource | StaticAbilities$ DontUntap | Duration$ Permanent | ConditionPresent$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBAnimate | ForgetOnMoved$ Battlefield | ForgetCounter$ PARALYZATION
SVar:DBEffect:DB$ Effect | RememberObjects$ Valid Creature.blockedBySource,Creature.blockingSource | StaticAbilities$ DontUntap | Duration$ Permanent | ConditionPresent$ Creature.blockedBySource,Creature.blockingSource | SubAbility$ DBAnimate | ForgetOnMoved$ Battlefield | ForgetCounter$ PARALYZATION
SVar:DBAnimate:DB$ AnimateAll | ValidCards$ Creature.blockedBySource,Creature.blockingSource | Abilities$ ABRemoveCounter | Duration$ Permanent
SVar:ABRemoveCounter:AB$ RemoveCounter | Defined$ Self | Cost$ 4 | CounterType$ PARALYZATION | CounterNum$ 1 | SpellDescription$ Remove a paralyzation counter from this creature.
SVar:DontUntap:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Card.IsRemembered | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. | Description$ Each of those creatures doesn't untap during its controller's untap step for as long as it has a paralyzation counter on it.

View File

@@ -0,0 +1,11 @@
Name:Druid of Purification
ManaCost:3 G
Types:Creature Human Druid
PT:2/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChoice | TriggerDescription$ When CARDNAME enters the battlefield, starting with you, each player may choose an artifact or enchantment you dont control. Destroy each permanent chosen this way.
SVar:TrigChoice:DB$ RepeatEach | RepeatPlayers$ Player | StartingWithActivator$ True | RepeatSubAbility$ DBChoosePermanent | SubAbility$ DBDestroy
SVar:DBChoosePermanent:DB$ ChooseCard | Defined$ Remembered | Choices$ Artifact.YouDontCtrl,Enchantment.YouDontCtrl | Optional$ True | ChoiceTitle$ Choose an artifact or enchantment | RememberChosen$ True
SVar:DBDestroy:DB$ Destroy | Defined$ Remembered | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:Random
Oracle:When Druid of Purification enters the battlefield, starting with you, each player may choose an artifact or enchantment you don't control. Destroy each permanent chosen this way.

Some files were not shown because too many files have changed in this diff Show More