Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Benjamin Perry
2023-04-13 14:29:58 -04:00
38 changed files with 1255 additions and 585 deletions

View File

@@ -28,10 +28,9 @@ public class CountersProliferateAi extends SpellAbilityAi {
@Override
protected boolean checkApiLogic(Player ai, SpellAbility sa) {
final List<Card> cperms = Lists.newArrayList();
final List<Player> allies = ai.getYourTeam();
boolean allyExpOrEnergy = false;
for (final Player p : allies) {
for (final Player p : ai.getYourTeam()) {
// player has experience or energy counter
if (p.getCounters(CounterEnumType.EXPERIENCE) + p.getCounters(CounterEnumType.ENERGY) >= 1) {
allyExpOrEnergy = true;
@@ -140,9 +139,16 @@ public class CountersProliferateAi extends SpellAbilityAi {
if (c.isPlaneswalker()) {
if (c.getController().isOpponentOf(ai)) {
continue;
} else {
return (T)c;
}
return (T)c;
}
if (c.isBattle()) {
if (c.getProtectingPlayer().isOpponentOf(ai)) {
// TODO in multiplayer we might sometimes want to do it anyway?
continue;
}
return (T)c;
}
final Card lki = CardUtil.getLKICopy(c);

View File

@@ -254,18 +254,26 @@ public class ForgeScript {
int y = AbilityUtils.calculateAmount(source, k[1].substring(2), spellAbility);
return Expressions.compare(sa.getTotalManaSpent(), comparator, y);
} else if (property.startsWith("ManaFrom")) {
final String fromWhat = property.substring(8);
boolean found = false;
String fromWhat = property.substring(8);
String[] parts = null;
if (fromWhat.contains("_")) {
parts = fromWhat.split("_");
fromWhat = parts[0];
}
int toFind = parts != null ? AbilityUtils.calculateAmount(source, parts[1], spellAbility) : 1;
int found = 0;
for (Mana m : sa.getPayingMana()) {
final Card manaSource = m.getSourceCard();
if (manaSource != null) {
if (manaSource.isValid(fromWhat, sourceController, source, spellAbility)) {
found = true;
break;
found++;
if (found == toFind) {
break;
}
}
}
}
return found;
return (found == toFind);
} else if (property.equals("MayPlaySource")) {
StaticAbility m = sa.getMayPlay();
if (m == null) {

View File

@@ -2939,6 +2939,12 @@ public class AbilityUtils {
la.setCardState(original);
list.add(la);
}
if (state == CardStateName.Transformed && tgtCard.isPermanent() && !tgtCard.isAura()) {
// casting defeated battle
Spell sp = new SpellPermanent(tgtCard, original);
sp.setCardState(original);
list.add(sp);
}
if (tgtCard.isModal()) {
CardState modal = tgtCard.getState(CardStateName.Modal);
Iterables.addAll(list, tgtCard.getBasicSpells(modal));

View File

@@ -17,6 +17,7 @@ import forge.game.player.PlayerController;
import forge.game.player.PlayerController.BinaryChoiceType;
import forge.game.spellability.SpellAbility;
import forge.util.CardTranslation;
import forge.util.Expressions;
import forge.util.Lang;
import forge.util.Localizer;
@@ -27,6 +28,9 @@ import forge.util.Localizer;
public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
@Override
protected String getStackDescription(SpellAbility sa) {
if (sa.hasParam("AddConditionSVar")) {
return "Add StackDescription for AddOrRemoveCounter line with condition!";
}
final StringBuilder sb = new StringBuilder();
final Player pl = sa.hasParam("DefinedPlayer") ?
AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("DefinedPlayer"), sa).getFirst()
@@ -50,7 +54,7 @@ public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) {
final Card source = sa.getHostCard();
final Game game = source.getGame();
final int counterAmount = AbilityUtils.calculateAmount(source, sa.getParam("CounterNum"), sa);
final int counterAmount = AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CounterNum", "1"), sa);
if (counterAmount <= 0) {
return;
@@ -112,7 +116,19 @@ public class CountersPutOrRemoveEffect extends SpellAbilityEffect {
params.put("CounterType", chosenType);
prompt = Localizer.getInstance().getMessage("lblWhatToDoWithTargetCounter", chosenType.getName()) + " ";
boolean putCounter = pc.chooseBinary(sa, prompt, BinaryChoiceType.AddOrRemove, params);
boolean putCounter;
if (sa.hasParam("RemoveConditionSVar")) {
final Card host = sa.getHostCard();
final int value = AbilityUtils.calculateAmount(host, sa.getParam("RemoveConditionSVar"), sa);
final String compare = sa.getParamOrDefault("RemoveConditionSVarCompare", "GE1");
final String operator = compare.substring(0, 2);
final String operand = compare.substring(2);
final int operandValue = AbilityUtils.calculateAmount(host, operand, sa);
putCounter = !Expressions.compare(value, operator, operandValue);
} else {
putCounter = pc.chooseBinary(sa, prompt, BinaryChoiceType.AddOrRemove, params);
}
if (putCounter) {
tgtCard.addCounter(chosenType, counterAmount, pl, table);

View File

@@ -290,6 +290,7 @@ public class PlayEffect extends SpellAbilityEffect {
if (!tgtCard.changeToState(CardStateName.Transformed)) {
// Failed to transform. In the future, we might need to just remove this option and continue
amount--;
System.err.println("CastTransformed failed for '" + tgtCard + "'.");
continue;
}
state = CardStateName.Transformed;

View File

@@ -1738,6 +1738,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
protectingPlayer = p;
view.updateProtectingPlayer(this);
}
public final void setSecretChosenPlayer(final Player p) {
chosenPlayer = p;
}
@@ -7117,6 +7118,10 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return getOwner().canDiscardBy(sa, effect);
}
public boolean activatedThisTurn() {
return !numberTurnActivations.isEmpty();
}
public void addAbilityActivated(SpellAbility ability) {
numberTurnActivations.add(ability);
numberGameActivations.add(ability);

View File

@@ -3932,7 +3932,7 @@ public class CardFactoryUtil {
StringBuilder chooseSB = new StringBuilder();
chooseSB.append("Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplacementResult$ Updated");
chooseSB.append(" | Description$ (As a Siege enters the battlefield, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.)");
String chooseProtector = "DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | Protect$ True | ChoiceTitle$ Choose an opponent to protect this battle | AILogic$ Curse";
String chooseProtector = "DB$ ChoosePlayer | Defined$ You | Choices$ Opponent | Protect$ True | ChoiceTitle$ Choose an opponent to protect this battle | AILogic$ Curse";
ReplacementEffect re = ReplacementHandler.parseReplacement(chooseSB.toString(), card, true);
re.setOverridingAbility(AbilityFactory.getAbility(chooseProtector, card));
@@ -3944,7 +3944,11 @@ public class CardFactoryUtil {
triggerDefeated.append(" TriggerDescription$ When CARDNAME is defeated, exile it, then cast it transformed.");
String castExileBattle = "DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True";
String castDefeatedBattle = "DB$ Play | Defined$ Remembered | WithoutManaCost$ True | CastTransformed$ True";
// note full rules text:
// When the last defense counter is removed from this permanent, exile it, then you may cast it transformed
// without paying its mana cost.
String castDefeatedBattle = "DB$ Play | Defined$ Remembered | WithoutManaCost$ True | Optional$ True | " +
"CastTransformed$ True";
Trigger defeatedTrigger = TriggerHandler.parseTrigger(triggerDefeated.toString(), card, true);
SpellAbility exileAbility = AbilityFactory.getAbility(castExileBattle, card);

View File

@@ -213,6 +213,11 @@ public class CardProperty {
return false;
}
}
} else if (property.startsWith("OppProtect")) {
if (card.getProtectingPlayer() == null
|| !sourceController.getOpponents().contains(card.getProtectingPlayer())) {
return false;
}
} else if (property.startsWith("DefendingPlayer")) {
Player p = property.endsWith("Ctrl") ? controller : card.getOwner();
if (!game.getPhaseHandler().inCombat()) {
@@ -1070,6 +1075,10 @@ public class CardProperty {
if (!property.startsWith("without") && !card.hasStartOfUnHiddenKeyword(property.substring(4))) {
return false;
}
} else if (property.startsWith("activated")) {
if (!card.activatedThisTurn()) {
return false;
}
} else if (property.startsWith("tapped")) {
if (!card.isTapped()) {
return false;
@@ -1549,6 +1558,15 @@ public class CardProperty {
return false;
}
}
if (property.equals("attackingBattle")) {
final GameEntity attacked = combat.getDefenderByAttacker(source);
if (!(attacked instanceof Card)) {
return false;
}
if (!((Card) attacked).isBattle()) {
return false;
}
}
if (property.startsWith("attackingYouOrYourPW")) {
GameEntity defender = combat.getDefenderByAttacker(card);
if (defender instanceof Card) {

View File

@@ -135,7 +135,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
public final void addAndUnfreeze(final SpellAbility ability) {
final Card source = ability.getHostCard();
if (!ability.isCopied()) {
if (!ability.isCopied() && ability.isAbility()) {
// Copied abilities aren't activated, so they shouldn't change these values
source.addAbilityActivated(ability);
ability.checkActivationResolveSubs();

View File

@@ -184,7 +184,7 @@ public class FCardImageRenderer {
if (!card.isSplitCard() && !card.isFlipCard()) {
final CardStateView state = card.getState(card.isAdventureCard() ? false : altState);
if ((state.isCreature() && !state.getKeywordKey().contains("Level up"))
|| state.isPlaneswalker() || state.getType().hasSubtype("Vehicle"))
|| state.isPlaneswalker() || state.isVehicle())
hasPTBox = true;
}
if (hasPTBox) {
@@ -294,7 +294,7 @@ public class FCardImageRenderer {
int headerHeight = NAME_SIZE + 2 * HEADER_PADDING;
int typeBoxHeight = TYPE_SIZE + 2 * TYPE_PADDING;
int ptBoxHeight = 0;
if (state.isCreature() || state.isPlaneswalker() || state.getType().hasSubtype("Vehicle")) {
if (state.isCreature() || state.isPlaneswalker() || state.isVehicle()) {
//if P/T box needed, make room for it
ptBoxHeight = headerHeight;
}
@@ -839,7 +839,7 @@ public class FCardImageRenderer {
TEXT_COLOR = Color.WHITE;
pieces.add(String.valueOf(state.getLoyalty()));
}
else if (state.getType().hasSubtype("Vehicle")) {
else if (state.isVehicle()) {
Color [] vhColor = { new Color(128, 96, 64) };
colors = vhColor;
TEXT_COLOR = Color.WHITE;

View File

@@ -19,7 +19,7 @@ public class NavArrowActor extends Actor {
if (textureAtlas.isEmpty()) {
System.out.print("NavArrow sprite not found");
}
currentAnimation = new Animation<>(0.6f, textureAtlas);
currentAnimation = new Animation<>(0.4f, textureAtlas);
}
@Override

View File

@@ -4,15 +4,15 @@ size: 50,50
format: RGBA8888
filter: Nearest,Nearest
repeat: none
right3
xy: 9,0
size: 50,50
right2
xy: 6,0
size: 50,50
right1
xy: 3,0
size: 50,50
right0
xy: 0,0
size: 50,50
right1
xy: 50,0
size: 50,50
right2
xy: 100,0
size: 50,50
right3
xy: 150,0
size: 50,50

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -120,3 +120,4 @@ Phyrexia: All Will Be One, 3/6/ONE, ONE
Phyrexia: All Will Be One Jumpstart, -/2/ONE, Meta-Choose(S(ONE Mite-y 1)Mite-y 1;S(ONE Mite-y 2)Mite-y 2;S(ONE Progress 1)Progress 1;S(ONE Progress 2)Progress 2;S(ONE Corruption 1)Corruption 1;S(ONE Corruption 2)Corruption 2;S(ONE Rebellious 1)Rebellious 1;S(ONE Rebellious 2)Rebellious 2;S(ONE Toxic 1)Toxic 1;S(ONE Toxic 2)Toxic 2)Themes
Alchemy: Phyrexia, 3/6/ONE, YONE
Shadows over Innistrad Remastered, 3/6/SIR, SIR
March of the Machine, 3/6/MOM, MOM

View File

@@ -2,7 +2,7 @@ Name:Jaddi Lifestrider
ManaCost:4 G
Types:Creature Elemental
PT:2/8
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ GuestList | TriggerDescription$ When CARDNAME enters the battlefield, you may tap any number of untapped creatures you control. You gain 2 life for each creature tapped this way.
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigJaddiLifestriderTap | TriggerDescription$ When CARDNAME enters the battlefield, you may tap any number of untapped creatures you control. You gain 2 life for each creature tapped this way.
SVar:TrigJaddiLifestriderTap:DB$ Tap | CardChoices$ Creature.YouCtrl+untapped | AnyNumber$ True | ChoiceAmount$ Count$Valid Creature.YouCtrl+untapped | RememberTapped$ True | SubAbility$ DBJaddiLifestriderGainLife
SVar:DBJaddiLifestriderGainLife:DB$ GainLife | LifeAmount$ JaddiLifestriderZ | SubAbility$ DBJaddiLifestriderCleanup
SVar:DBJaddiLifestriderCleanup:DB$ Cleanup | ClearRemembered$ True

View File

@@ -2,7 +2,7 @@ Name:Kaya, Ghost Assassin
ManaCost:2 W B
Types:Legendary Planeswalker Kaya
Loyalty:5
A:AB$ Pump | Cost$ AddCounter<0/LOYALTY> | ValidTgts$ Creature | TargetMax$ 1 | TargetMin$ 0 | Planeswalker$ True | SubAbility$ DBChoose | StackDeSpellDescription$ SpellDescription | SpellDescription$ Exile CARDNAME or up to one target creature. Return that card to the battlefield under its owner's control at the beginning of your next upkeep. You lose 2 life.
A:AB$ Pump | Cost$ AddCounter<0/LOYALTY> | ValidTgts$ Creature | TargetMax$ 1 | TargetMin$ 0 | Planeswalker$ True | SubAbility$ DBChoose | StackDescription$ SpellDescription | SpellDescription$ Exile CARDNAME or up to one target creature. Return that card to the battlefield under its owner's control at the beginning of your next upkeep. You lose 2 life.
SVar:DBChoose:DB$ GenericChoice | Choices$ DBExileSelf,DBExileTarget | Defined$ You
SVar:DBExileSelf:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBDelTrig | SpellDescription$ Exile CARDNAME
SVar:DBExileTarget:DB$ ChangeZone | Defined$ Targeted | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DBDelTrig | SpellDescription$ Exile up to one target creature
@@ -10,9 +10,10 @@ SVar:DBDelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Y
SVar:DBReturn:DB$ ChangeZone | Origin$ Exile | Defined$ DelayTriggerRememberedLKI | Destination$ Battlefield
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBLoseLife
SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 2 | Defined$ You
A:AB$ LoseLife | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | Defined$ Player.Opponent | LifeAmount$ 2 | SubAbility$ DBGainLife | SpellDescription$ Each opponent loses 2 life and you gain 2 life.
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2
A:AB$ Discard | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | Ultimate$ True | Defined$ Player.Opponent | NumCards$ 1 | Mode$ TgtChoose | SubAbility$ DBDraw | SpellDescription$ Each opponent discards a card and you draw a card.
SVar:DBDraw:DB$ Draw | Defined$ You | NumCards$ 1
A:AB$ LoseLife | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | Defined$ Opponent | LifeAmount$ 2 | SubAbility$ DBGainLife | SpellDescription$ Each opponent loses 2 life and you gain 2 life.
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 2
A:AB$ Discard | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | Ultimate$ True | Defined$ Opponent | Mode$ TgtChoose | SubAbility$ DBDraw | SpellDescription$ Each opponent discards a card and you draw a card.
SVar:DBDraw:DB$ Draw
AI:RemoveDeck:All
DeckHas:Ability$LifeGain
Oracle:[0]: Exile Kaya, Ghost Assassin or up to one target creature. Return that card to the battlefield under its owner's control at the beginning of your next upkeep. You lose 2 life.\n[-1]: Each opponent loses 2 life and you gain 2 life.\n[-2]: Each opponent discards a card and you draw a card.

View File

@@ -2,11 +2,11 @@ Name:Shape of the Wiitigo
ManaCost:3 G G G
Types:Enchantment Aura
K:Enchant creature
A:SP$ Attach | Cost$ 3 G G G | ValidTgts$ Creature | AILogic$ Pump
A:SP$ Attach | ValidTgts$ Creature | AILogic$ Pump
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigPutCounter | TriggerDescription$ When CARDNAME enters the battlefield, put six +1/+1 counters on enchanted creature.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Enchanted | CounterType$ P1P1 | CounterNum$ 6
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter2 | TriggerDescription$ At the beginning of your upkeep, put a +1/+1 counter on enchanted creature if it attacked or blocked since your last upkeep. Otherwise, remove a +1/+1 counter from it.
SVar:TrigPutCounter2:DB$ PutCounter | Defined$ Enchanted | CounterType$ P1P1 | CounterNum$ 1 | ConditionPresent$ Card.EnchantedBy+attackedOrBlockedSinceYourLastUpkeep | SubAbility$ RemCounter
SVar:RemCounter:DB$ RemoveCounter | Defined$ Enchanted | CounterType$ P1P1 | CounterNum$ 1 | ConditionPresent$ Card.EnchantedBy+attackedOrBlockedSinceYourLastUpkeep | ConditionCompare$ EQ0
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigAddOrRemoveCounter | TriggerDescription$ At the beginning of your upkeep, put a +1/+1 counter on enchanted creature if it attacked or blocked since your last upkeep. Otherwise, remove a +1/+1 counter from it.
SVar:TrigAddOrRemoveCounter:DB$ AddOrRemoveCounter | CounterType$ P1P1 | Defined$ Enchanted | RemoveConditionSVar$ Count$Valid Card.EnchantedBy+!attackedOrBlockedSinceYourLastUpkeep
SVar:SacMe:1
DeckHas:Ability$Counters
Oracle:Enchant creature\nWhen Shape of the Wiitigo enters the battlefield, put six +1/+1 counters on enchanted creature.\nAt the beginning of your upkeep, put a +1/+1 counter on enchanted creature if it attacked or blocked since your last upkeep. Otherwise, remove a +1/+1 counter from it.

View File

@@ -3,7 +3,7 @@ ManaCost:2 W
Types:Creature Human Soldier
PT:1/1
K:Double Strike
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChoose | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, you may tap any number of untapped creatures you control. CARDNAME gets +1/+1 until end of turn for each creature tapped this way.
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigTap | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, you may tap any number of untapped creatures you control. CARDNAME gets +1/+1 until end of turn for each creature tapped this way.
SVar:TrigTap:DB$ Tap | CardChoices$ Creature.YouCtrl+untapped | AnyNumber$ True | ChoiceAmount$ Count$Valid Creature.YouCtrl+untapped | RememberTapped$ True | SubAbility$ DBPump
SVar:DBPump:DB$ Pump | Defined$ Self | NumAtt$ Y | NumDef$ Y | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True

View File

@@ -4,7 +4,7 @@ Types:Legendary Planeswalker Sorin
Loyalty:3
A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | TokenAmount$ 1 | TokenScript$ b_1_1_vampire_lifelink | Planeswalker$ True | SpellDescription$ Create a 1/1 black Vampire creature token with lifelink.
A:AB$ Effect | Cost$ SubCounter<2/LOYALTY> | Name$ Emblem - Sorin, Lord of Innistrad | Image$ emblem_sorin_lord_of_innistrad | StaticAbilities$ STPump | Planeswalker$ True | Duration$ Permanent | AILogic$ Always | SpellDescription$ You get an emblem with "Creatures you control get +1/+0."
SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1
SVar:STPump:Mode$ Continuous | EffectZone$ Command | AffectedZone$ Battlefield | Affected$ Creature.YouCtrl | AddPower$ 1 | Description$ Creatures you control get +1/+0.
A:AB$ Destroy | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | ValidTgts$ Creature,Planeswalker.Other | TargetMin$ 0 | TargetMax$ 3 | TgtPrompt$ Select target creatures or other planeswalkers | RememberTargets$ True | ForgetOtherTargets$ True | SubAbility$ DBChangeZoneAll | SpellDescription$ Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control.
SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Graveyard | Destination$ Battlefield | GainControl$ True | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True

View File

@@ -5,7 +5,7 @@ PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 2/2 green Wolf creature tokens.
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ g_2_2_wolf
K:Daybound
DeckHas:Ability$Token
DeckHas:Ability$Token & Type$Wolf
AlternateMode:DoubleFaced
Oracle:When Tovolar's Huntmaster enters the battlefield, create two 2/2 green Wolf creature tokens.\nDaybound (If a player casts no spells during their own turn, it becomes night next turn.)

View File

@@ -0,0 +1,6 @@
Name:Cut Short
ManaCost:2 W
Types:Instant
K:Convoke
A:SP$ Destroy | ValidTgts$ Planeswalker.activated,Creature.tapped | TgtPrompt$ Select target planeswalker that was activated this turn or tapped creature | SpellDescription$ Destroy target planeswalker that was activated this turn or tapped creature.
Oracle:Convoke (Your creatures can help cast this spell. Each creature you tap while casting this spell pays for {1} or one mana of that creature's color.)\nDestroy target planeswalker that was activated this turn or tapped creature.

View File

@@ -8,7 +8,7 @@ T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigDraw | TriggerDescription$
SVar:TrigDraw:AB$ Draw | Cost$ X W U U | NumCards$ X
SVar:X:Count$xPaid
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of each end step, you may pay 4 life. If you do, create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the number of cards you've drawn this turn.
SVar:TrigToken:AB$ Token | Cost$ PayLife<4> | TokenAmount$ Y | TokenScript$ w_1_1_vampire_lifelink | TokenOwner$ You
SVar:TrigToken:AB$ Token | Cost$ PayLife<4> | TokenAmount$ Y | TokenScript$ w_1_1_vampire_knight_lifelink | TokenOwner$ You
SVar:Y:Count$YouDrewThisTurn
DeckHas:Ability$Token|LifeGain
SVar:HasAttackEffect:TRUE

View File

@@ -0,0 +1,12 @@
Name:Etched Host Doombringer
ManaCost:4 B
Types:Creature Phyrexian Demon
PT:3/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ When CARDNAME enters the battlefield, ABILITY
SVar:TrigCharm:DB$ Charm | Choices$ Drain,Battle
SVar:Drain:DB$ LoseLife | ValidTgts$ Opponent | LifeAmount$ 2 | SubAbility$ DBGainLife | SpellDescription$ Target opponent loses 2 life and you gain 2 life.
SVar:DBGainLife:DB$ GainLife | LifeAmount$ 2 | StackDescription$ None
SVar:Battle:DB$ AddOrRemoveCounter | ValidTgts$ Battle | RemoveConditionSVar$ Targeted$Valid Battle.OppProtect | CounterType$ DEFENSE | CounterNum$ 3 | StackDescription$ REP Choose target battle. _ & it_{c:Targeted} | SpellDescription$ Choose target battle. If an opponent protects it, remove three defense counters from it. Otherwise, put three defense counters on it.
DeckHas:Ability$LifeGain
DeckHints:Type$Battle
Oracle:When Etched Host Doombringer enters the battlefield, choose one —\n• Target opponent loses 2 life and you gain 2 life.\n• Choose target battle. If an opponent protects it, remove three defense counters from it. Otherwise, put three defense counters on it.

View File

@@ -0,0 +1,9 @@
Name:Inga and Esika
ManaCost:2 G U
Types:Legendary Creature Human God
PT:4/4
S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddAbility$ Mana | AddKeyword$ Vigilance | Description$ Creatures you control have vigilance and "{T}: Add one mana of any color. Spend this mana only to cast a creature spell."
SVar:Mana:AB$ Mana | Cost$ T | Produced$ Any | Amount$ 1 | RestrictValid$ Spell.Creature | SpellDescription$ Add one mana of any color. Spend this mana only to cast a creature spell.
T:Mode$ SpellCast | ValidCard$ Creature | ValidSA$ Spell.ManaFromCreature_3 | ValidActivatingPlayer$ You | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a creature spell, if three or more mana from creatures was spent to cast it, draw a card.
SVar:TrigDraw:DB$ Draw
Oracle:Creatures you control have vigilance and "{T}: Add one mana of any color. Spend this mana only to cast a creature spell."\nWhenever you cast a creature spell, if three or more mana from creatures was spent to cast it, draw a card.

View File

@@ -0,0 +1,22 @@
Name:Invasion of Amonkhet
ManaCost:1 U B
Types:Battle Siege
Defense:4
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigMill | TriggerDescription$ When CARDNAME enters the battlefield, each player mills three cards, then each opponent discards a card and you draw a card. (To mill three cards, a player puts the top three cards of their library into their graveyard.)
SVar:TrigMill:DB$ Mill | Defined$ Player | NumCards$ 3 | SubAbility$ DBDiscard
SVar:DBDiscard:DB$ Discard | Defined$ Opponent | Mode$ TgtChoose | SubAbility$ DBDraw
SVar:DBDraw:DB$ Draw
AlternateMode:DoubleFaced
DeckHas:Ability$Mill
Oracle:(As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.)\nWhen Invasion of Amonkhet enters the battlefield, each player mills three cards, then each opponent discards a card and you draw a card. (To mill three cards, a player puts the top three cards of their library into their graveyard.)
ALTERNATE
Name:Lazotep Convert
ManaCost:no cost
Colors:blue,black
Types:Creature Zombie
PT:4/4
K:ETBReplacement:Copy:DBCopy:Optional
SVar:DBCopy:DB$ Clone | Choices$ Creature | ChoiceZone$ Graveyard | SetPower$ 4 | SetToughness$ 4 | AddColors$ Black | AddTypes$ Zombie | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature card in a graveyard, except it's a 4/4 black Zombie in addition to its other types.
Oracle:You may have Lazotep Convert enter the battlefield as a copy of any creature card in a graveyard, except it's a 4/4 black Zombie in addition to its other types.

View File

@@ -0,0 +1,21 @@
Name:Invasion of Dominaria
ManaCost:2 W
Types:Battle Siege
Defense:5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigGainLife | TriggerDescription$ When CARDNAME enters the battlefield, you gain 4 life and draw a card.
SVar:TrigGainLife:DB$ GainLife | LifeAmount$ 4 | SubAbility$ DBDraw
SVar:DBDraw:DB$ Draw
AlternateMode:DoubleFaced
DeckHas:Ability$LifeGain
Oracle:(As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.)\nWhen Invasion of Dominaria enters the battlefield, you gain 4 life and draw a card.
ALTERNATE
Name:Serra Faithkeeper
ManaCost:no cost
Colors:white
Types:Creature Angel
PT:4/4
K:Flying
K:Vigilance
Oracle:Flying, vigilance

View File

@@ -4,7 +4,7 @@ Types:Battle Siege
Defense:5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSearch | TriggerDescription$ When CARDNAME enters the battlefield, up to two target creatures each get +2/+0 and gain vigilance and haste until end of turn.
SVar:TrigSearch:DB$ Pump | TargetMin$ 0 | TargetMax$ 2 | ValidTgts$ Creature | TgtPrompt$ Select up to two target creatures | NumAtt$ 2 | KW$ Vigilance & Haste
Oracle:(As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.) When Invasion of Kylem enters the battlefield, up to two target creatures each get +2/+0 and gain vigilance and haste until end of turn.
Oracle:(As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.)\nWhen Invasion of Kylem enters the battlefield, up to two target creatures each get +2/+0 and gain vigilance and haste until end of turn.
AlternateMode:DoubleFaced

View File

@@ -16,7 +16,6 @@ ManaCost:no cost
Colors:white,blue
Types:Legendary Planeswalker Teferi
Loyalty:4
A:SP$ PermanentNoncreature
A:AB$ Draw | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | NumCards$ 2 | SubAbility$ DBDiscard | SpellDescription$ Draw two cards.
SVar:DBDiscard:DB$ Discard | NumCards$ 2 | Mode$ TgtChoose | UnlessType$ Creature | StackDescription$ SpellDescription | SpellDescription$ Then discard two cards unless you discard a creature card.
A:AB$ Effect | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | Name$ Emblem - Teferi Akosa of Zhalfir | Image$ emblem_teferi_akosa_of_zhalfir | StaticAbilities$ STPump | Duration$ Permanent | SpellDescription$ You get an emblem with "Knights you control get +1/+0 and have ward {1}."

View File

@@ -4,9 +4,8 @@ Types:Battle Siege
Defense:3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSearch | TriggerDescription$ When CARDNAME enters the battlefield, search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.
SVar:TrigSearch:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ 2 | Shuffle$ True
Oracle:(As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.) When Invasion of Zendikar enters the battlefield, search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.
AlternateMode:DoubleFaced
Oracle:(As a Siege enters, choose an opponent to protect it. You and others can attack it. When it's defeated, exile it, then cast it transformed.)\nWhen Invasion of Zendikar enters the battlefield, search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle.
ALTERNATE
@@ -15,9 +14,8 @@ ManaCost:no cost
Colors:green
Types:Creature Elemental
PT:4/4
A:SP$ PermanentCreature
K:Vigilance
K:Haste
S:Mode$ Continuous | Affected$ Card.Self | AddType$ Land | Description$ As long as Awakened Skyclave is on the battlefield, its a land in addition to its other types.
S:Mode$ Continuous | Affected$ Card.Self | AddType$ Land | Description$ As long as CARDNAME is on the battlefield, it's a land in addition to its other types.
A:AB$ Mana | Cost$ T | Produced$ Any | SpellDescription$ Add one mana of any color.
Oracle:Vigilance, haste. \nAs long as Awakened Skyclave is on the battlefield, it's a land in addition to its other types.\n{T}: Add one mana of any color
Oracle:Vigilance, haste\nAs long as Awakened Skyclave is on the battlefield, it's a land in addition to its other types.\n{T}: Add one mana of any color.

View File

@@ -0,0 +1,11 @@
Name:Joyful Stormsculptor
ManaCost:3 U R
Types:Creature Human Shaman
PT:2/3
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 1/1 blue and red Elemental creature tokens.
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ ur_1_1_elemental
T:Mode$ SpellCast | ValidCard$ Card.withConvoke | ValidActivatingPlayer$ You | Execute$ TrigDamage | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a spell that has convoke, CARDNAME deals 1 damage to each opponent and each battle they protect.
SVar:TrigDamage:DB$ DamageAll | ValidPlayers$ Player.Opponent | ValidCards$ Battle.OppProtect | NumDmg$ 1
DeckHas:Ability$Token & Type$Elemental
DeckHints:Keyword$Convoke
Oracle:When Joyful Stormsculptor enters the battlefield, create two 1/1 blue and red Elemental creature tokens.\nWhenever you cast a spell that has convoke, Joyful Stormsculptor deals 1 damage to each opponent and each battle they protect.

View File

@@ -0,0 +1,8 @@
Name:Portent Tracker
ManaCost:1 G
Types:Creature Satyr Scout
PT:1/1
A:AB$ Untap | Cost$ T | ValidTgts$ Land | AILogic$ PoolExtraMana | SpellDescription$ Untap target land.
A:AB$ AddOrRemoveCounter | Cost$ T | ValidTgts$ Battle | RemoveConditionSVar$ Targeted$Valid Battle.OppProtect | CounterType$ DEFENSE | SorcerySpeed$ True | StackDescription$ REP Choose target battle. _ & it_{c:Targeted} & Activate only as a sorcery._ | SpellDescription$ Choose target battle. If an opponent protects it, remove a defense counter from it. Otherwise, put a defense counter on it. Activate only as a sorcery.
DeckHints:Type$Battle
Oracle:{T}: Untap target land.\n{T}: Choose target battle. If an opponent protects it, remove a defense counter from it. Otherwise, put a defense counter on it. Activate only as a sorcery.

View File

@@ -3,8 +3,9 @@ ManaCost:X X W
Types:Creature Phyrexian Cat Cleric
PT:1/2
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigIncubate | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME enters the battlefield, incubate 3 X times. (To incubate 3, create an Incubator token with three +1/+1 counters on it and "{2}: Transform this artifact." It transforms into a 0/0 Phyrexian artifact creature.)
SVar:TrigIncubate:DB$ Incubate | Amount$ 3 | Times$ Count$xPaid
SVar:TrigIncubate:DB$ Incubate | Amount$ 3 | Times$ X
A:AB$ SetState | Cost$ T | TgtPrompt$ Select target Incubator token you control | ValidTgts$ Incubator.token+YouCtrl | Mode$ Transform | SpellDescription$ Transform target Incubator token you control.
SVar:X:Count$xPaid
DeckHints:Type$Incubator
DeckHas:Ability$Token|Counters & Type$Artifact|Incubator
Oracle:When Progenitor Exarch enters the battlefield, incubate 3 X times. (To incubate 3, create an Incubator token with three +1/+1 counters on it and "{2}: Transform this artifact." It transforms into a 0/0 Phyrexian artifact creature.)\n{T}: Transform target Incubator token you control.

View File

@@ -0,0 +1,13 @@
Name:Rampaging Geoderm
ManaCost:2 R G
Types:Creature Dinosaur Beast
PT:3/3
K:Trample
K:Haste
T:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, target attacking creature gets +1/+1 until end of turn. If it's attacking a battle, put a +1/+1 counter on it instead.
SVar:TrigPump:DB$ Branch | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | BranchConditionSVar$ X | TrueSubAbility$ PutCounter | FalseSubAbility$ Pump
SVar:PutCounter:DB$ PutCounter | Defined$ Targeted | CounterType$ P1P1
SVar:Pump:DB$ Pump | Defined$ Targeted | NumAtt$ +1 | NumDef$ +1
SVar:X:Targeted$Valid Card.attackingBattle
DeckHas:Ability$Counters
Oracle:Trample, haste\nWhenever you attack, target attacking creature gets +1/+1 until end of turn. If it's attacking a battle, put a +1/+1 counter on it instead.

File diff suppressed because it is too large Load Diff

View File

@@ -3,6 +3,10 @@ Code=MOM
Date=2023-04-21
Name=March of the Machine
Type=Expansion
BoosterCovers=3
Booster=8 Common:!fromSheet("MOM lands"):fromsheet("MOM cards"), 2 Uncommon:fromSheet("MOM cards"), 1 dfc:!fromSheet("MOM battles"):fromSheet("MOM cards"), 1 UncommonRareMythic:!dfc:fromSheet("MOM cards"), 1 fromSheet("MOM battles"), 1 fromSheet("MUL cards"), 1 fromSheet("MOM lands")
Prerelease=6 Boosters, 1 RareMythic+
BoosterBox=36
ScryfallCode=MOM
[cards]
@@ -406,6 +410,71 @@ ScryfallCode=MOM
[buy a box]
387 R Omnath, Locus of All @Helge C. Balzer
[lands]
4 Plains|MOM|1
3 Plains|MOM|2
3 Plains|MOM|3
4 Island|MOM|1
3 Island|MOM|2
3 Island|MOM|3
4 Swamp|MOM|1
3 Swamp|MOM|2
3 Swamp|MOM|3
4 Mountain|MOM|1
3 Mountain|MOM|2
3 Mountain|MOM|3
4 Forest|MOM|1
3 Forest|MOM|2
3 Forest|MOM|3
5 Bloodfell Caves|MOM
5 Blossoming Sands|MOM
5 Dismal Backwater|MOM
5 Jungle Hollow|MOM
5 Rugged Highlands|MOM
5 Scoured Barrens|MOM
5 Swiftwater Cliffs|MOM
5 Thornwood Falls|MOM
5 Tranquil Cove|MOM
5 Wind-Scarred Crag|MOM
[battles]
1 Invasion of Alara|MOM
1 Invasion of Amonkhet|MOM
1 Invasion of Arcavios|MOM
1 Invasion of Azgol|MOM
1 Invasion of Belenon|MOM
1 Invasion of Dominaria|MOM
1 Invasion of Eldraine|MOM
1 Invasion of Ergamon|MOM
1 Invasion of Fiora|MOM
1 Invasion of Gobakhan|MOM
1 Invasion of Ikoria|MOM
1 Invasion of Innistrad|MOM
1 Invasion of Ixalan|MOM
1 Invasion of Kaladesh|MOM
1 Invasion of Kaldheim|MOM
1 Invasion of Kamigawa|MOM
1 Invasion of Karsus|MOM
1 Invasion of Kylem|MOM
1 Invasion of Lorwyn|MOM
1 Invasion of Mercadia|MOM
1 Invasion of Moag|MOM
1 Invasion of Muraganda|MOM
1 Invasion of New Capenna|MOM
1 Invasion of New Phyrexia|MOM
1 Invasion of Pyrulea|MOM
1 Invasion of Ravnica|MOM
1 Invasion of Regatha|MOM
1 Invasion of Segovia|MOM
1 Invasion of Shandalar|MOM
1 Invasion of Tarkir|MOM
1 Invasion of Theros|MOM
1 Invasion of Tolvada|MOM
1 Invasion of Ulgrotha|MOM
1 Invasion of Vryn|MOM
1 Invasion of Xerex|MOM
1 Invasion of Zendikar|MOM
[tokens]
b_2_2_zombie
c_1_1_a_thopter_flying

View File

@@ -4,7 +4,7 @@ Date=2023-03-21
Name=Shadows over Innistrad Remastered
Type=Online
BoosterCovers=3
Booster=10 Common:fromsheet("SIR cards"), 3 Uncommon:fromSheet("SIR cards"), 1 RareMythic:fromSheet("SIR cards"), 1 BasicLand:fromSheet("SIR cards")
Booster=9 Common:fromsheet("SIR cards"), 3 Uncommon:fromSheet("SIR cards"), 1 RareMythic:fromSheet("SIR cards"), 1 BasicLand:fromSheet("SIR cards"), 1 Any:fromSheet("SIS cards")
Prerelease=6 Boosters, 1 RareMythic+
BoosterBox=36
ScryfallCode=SIR

View File

@@ -0,0 +1,6 @@
Name:Elemental Token
ManaCost:no cost
Colors:blue,red
Types:Creature Elemental
PT:1/1
Oracle:

View File

@@ -1,6 +1,6 @@
Name:Vampire Token
Name:Vampire Knight Token
ManaCost:no cost
Types:Creature Vampire
Types:Creature Knight Vampire
Colors:white
PT:1/1
K:Lifelink