mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Merge branch 'Card-Forge:master' into master
This commit is contained in:
@@ -807,8 +807,9 @@ public class AiController {
|
||||
// Account for possible Ward after the spell is fully targeted
|
||||
// TODO: ideally, this should be done while targeting, so that a different target can be preferred if the best
|
||||
// one is warded and can't be paid for. (currently it will be stuck with the target until it could pay)
|
||||
if (sa.usesTargeting() && (!sa.isSpell() || CardFactoryUtil.isCounterable(host))) {
|
||||
for (Card tgt : sa.getTargets().getTargetCards()) {
|
||||
if (!sa.isSpell() || CardFactoryUtil.isCounterable(host)) {
|
||||
for (TargetChoices tc : sa.getAllTargetChoices()) {
|
||||
for (Card tgt : tc.getTargetCards()) {
|
||||
// TODO some older cards don't use the keyword, so check for trigger instead
|
||||
if (tgt.hasKeyword(Keyword.WARD) && tgt.isInPlay() && tgt.getController().isOpponentOf(host.getController())) {
|
||||
int amount = 0;
|
||||
@@ -827,6 +828,7 @@ public class AiController {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check if some target raised cost
|
||||
if (oldCMC > -1) {
|
||||
@@ -1332,10 +1334,7 @@ public class AiController {
|
||||
if (sa == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<SpellAbility> abilities = Lists.newArrayList();
|
||||
abilities.add(sa);
|
||||
return abilities;
|
||||
return Lists.newArrayList(sa);
|
||||
}
|
||||
|
||||
public List<SpellAbility> chooseSpellAbilityToPlay() {
|
||||
|
||||
@@ -1720,16 +1720,12 @@ public class ComputerUtil {
|
||||
return threatened;
|
||||
}
|
||||
} else {
|
||||
objects = topStack.getTargets();
|
||||
final List<GameObject> canBeTargeted = new ArrayList<>();
|
||||
for (Object o : objects) {
|
||||
if (o instanceof GameEntity) {
|
||||
final GameEntity ge = (GameEntity) o;
|
||||
for (GameEntity ge : topStack.getTargets().getTargetEntities()) {
|
||||
if (ge.canBeTargetedBy(topStack)) {
|
||||
canBeTargeted.add(ge);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (canBeTargeted.isEmpty()) {
|
||||
return threatened;
|
||||
}
|
||||
|
||||
@@ -1865,7 +1865,6 @@ public class ComputerUtilCard {
|
||||
*/
|
||||
public static boolean canPumpAgainstRemoval(Player ai, SpellAbility sa) {
|
||||
final List<GameObject> objects = ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa, true);
|
||||
final CardCollection threatenedTargets = new CardCollection();
|
||||
|
||||
if (!sa.usesTargeting()) {
|
||||
final List<Card> cards = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa);
|
||||
@@ -1877,14 +1876,11 @@ public class ComputerUtilCard {
|
||||
// For pumps without targeting restrictions, just return immediately until this is fleshed out.
|
||||
return false;
|
||||
}
|
||||
CardCollection targetables = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa);
|
||||
|
||||
targetables = ComputerUtil.getSafeTargets(ai, sa, targetables);
|
||||
for (final Card c : targetables) {
|
||||
if (objects.contains(c)) {
|
||||
threatenedTargets.add(c);
|
||||
}
|
||||
}
|
||||
CardCollection threatenedTargets = CardLists.getTargetableCards(ai.getCardsIn(ZoneType.Battlefield), sa);
|
||||
threatenedTargets = ComputerUtil.getSafeTargets(ai, sa, threatenedTargets);
|
||||
threatenedTargets.retainAll(objects);
|
||||
|
||||
if (!threatenedTargets.isEmpty()) {
|
||||
sortByEvaluateCreature(threatenedTargets);
|
||||
for (Card c : threatenedTargets) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.google.common.base.Predicates;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.ai.ability.AnimateAi;
|
||||
import forge.ai.ability.FightAi;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.MagicColor;
|
||||
import forge.card.mana.ManaCost;
|
||||
@@ -79,6 +80,49 @@ import java.util.List;
|
||||
*/
|
||||
public class SpecialCardAi {
|
||||
|
||||
// Arena and Magus of the Arena
|
||||
public static class Arena {
|
||||
public static boolean consider(final Player ai, final SpellAbility sa) {
|
||||
final Game game = ai.getGame();
|
||||
|
||||
if (!game.getPhaseHandler().is(PhaseType.END_OF_TURN) || game.getPhaseHandler().getNextTurn() != ai) {
|
||||
return false; // at opponent's EOT only, to conserve mana
|
||||
}
|
||||
|
||||
CardCollection aiCreatures = ai.getCreaturesInPlay();
|
||||
if (aiCreatures.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Player opp : ai.getOpponents()) {
|
||||
CardCollection oppCreatures = opp.getCreaturesInPlay();
|
||||
if (oppCreatures.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Card aiCreature : aiCreatures) {
|
||||
boolean canKillAll = true;
|
||||
for (Card oppCreature : oppCreatures) {
|
||||
if (FightAi.canKill(oppCreature, aiCreature, 0)) {
|
||||
canKillAll = false;
|
||||
break;
|
||||
}
|
||||
if (!FightAi.canKill(aiCreature, oppCreature, 0)) {
|
||||
canKillAll = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (canKillAll) {
|
||||
sa.getTargets().clear();
|
||||
sa.getTargets().add(aiCreature);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return sa.isTargetNumberValid();
|
||||
}
|
||||
}
|
||||
|
||||
// Black Lotus and Lotus Bloom
|
||||
public static class BlackLotus {
|
||||
public static boolean consider(final Player ai, final SpellAbility sa, final ManaCostBeingPaid cost) {
|
||||
|
||||
@@ -30,7 +30,6 @@ public class FightAi extends SpellAbilityAi {
|
||||
|
||||
// everything is defined or targeted above, can't do anything there unless a specific logic is set
|
||||
if (sa.hasParam("Defined") && !sa.usesTargeting()) {
|
||||
// TODO extend Logic for cards like Arena
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -292,10 +292,6 @@ public class PumpAi extends PumpAiBase {
|
||||
if (numDefense.contains("X") && sa.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
int xPay = ComputerUtilCost.getMaxXValue(sa, ai, sa.isTrigger());
|
||||
if (sourceName.equals("Necropolis Fiend")) {
|
||||
xPay = Math.min(xPay, sa.getActivatingPlayer().getCardsIn(ZoneType.Graveyard).size());
|
||||
sa.setSVar("X", Integer.toString(xPay));
|
||||
}
|
||||
sa.setXManaCostPaid(xPay);
|
||||
defense = xPay;
|
||||
if (numDefense.equals("-X")) {
|
||||
|
||||
@@ -46,8 +46,11 @@ public class TapAi extends TapAiBase {
|
||||
final Card source = sa.getHostCard();
|
||||
final Cost abCost = sa.getPayCosts();
|
||||
|
||||
if ("GoblinPolkaBand".equals(sa.getParam("AILogic"))) {
|
||||
final String aiLogic = sa.getParamOrDefault("AILogic", "");
|
||||
if ("GoblinPolkaBand".equals(aiLogic)) {
|
||||
return SpecialCardAi.GoblinPolkaBand.consider(ai, sa);
|
||||
} else if ("Arena".equals(aiLogic)) {
|
||||
return SpecialCardAi.Arena.consider(ai, sa);
|
||||
}
|
||||
|
||||
if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source, sa)) {
|
||||
|
||||
@@ -325,6 +325,15 @@ public abstract class TapAiBase extends SpellAbilityAi {
|
||||
@Override
|
||||
public boolean chkAIDrawback(SpellAbility sa, Player ai) {
|
||||
final Card source = sa.getHostCard();
|
||||
final boolean oppTargetsChoice = sa.hasParam("TargetingPlayer");
|
||||
|
||||
if (oppTargetsChoice && sa.getActivatingPlayer().equals(ai) && !sa.isTrigger()) {
|
||||
// canPlayAI (sa activated by ai)
|
||||
Player targetingPlayer = AbilityUtils.getDefinedPlayers(source, sa.getParam("TargetingPlayer"), sa).get(0);
|
||||
sa.setTargetingPlayer(targetingPlayer);
|
||||
sa.getTargets().clear();
|
||||
return targetingPlayer.getController().chooseTargetsFor(sa);
|
||||
}
|
||||
|
||||
boolean randomReturn = true;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.util;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.Normalizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -42,6 +43,10 @@ public class TextUtil {
|
||||
return Normalizer.normalize(text, Normalizer.Form.NFD);
|
||||
|
||||
}
|
||||
private static final DecimalFormat df = new DecimalFormat("#.##");
|
||||
public static String decimalFormat(float value) {
|
||||
return df.format(value);
|
||||
}
|
||||
/**
|
||||
* Safely converts an object to a String.
|
||||
*
|
||||
|
||||
@@ -1252,6 +1252,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
player.shuffle(sa);
|
||||
}
|
||||
|
||||
if (sa.hasParam("Reorder")) {
|
||||
chosenCards = new CardCollection(decider.getController().orderMoveToZoneList(chosenCards, destination, sa));
|
||||
}
|
||||
|
||||
// remove Controlled While Searching
|
||||
if (controlTimestamp != null) {
|
||||
player.removeController(controlTimestamp);
|
||||
|
||||
@@ -32,6 +32,7 @@ import forge.localinstance.achievements.CardActivationAchievements;
|
||||
import forge.localinstance.achievements.PlaneswalkerAchievements;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
import forge.util.TextUtil;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -216,7 +217,7 @@ public class PlayerStatisticScene extends UIScene {
|
||||
totalLoss.setText(String.valueOf(Current.player().getStatistic().totalLoss()));
|
||||
}
|
||||
if (lossWinRatio != null) {
|
||||
lossWinRatio.setText(Float.toString(Current.player().getStatistic().winLossRatio()));
|
||||
lossWinRatio.setText(TextUtil.decimalFormat(Current.player().getStatistic().winLossRatio()));
|
||||
}
|
||||
if (eventMatchWins != null) {
|
||||
eventMatchWins.setText(String.valueOf(Current.player().getStatistic().eventWins()));
|
||||
|
||||
@@ -12,5 +12,5 @@ ALTERNATE
|
||||
Name:Explosive Crystal
|
||||
ManaCost:4 R
|
||||
Types:Sorcery Adventure
|
||||
A:SP$ DealDamage | ValidTgts$ Any to distribute damage to | NumDmg$ 4 | TargetMin$ 0 | TargetMax$ 4 | DividedAsYouChoose$ 4 | SpellDescription$ CARDNAME deals 4 damage divided as you choose among any number of targets.
|
||||
A:SP$ DealDamage | ValidTgts$ Any | NumDmg$ 4 | TargetMin$ 0 | TargetMax$ 4 | DividedAsYouChoose$ 4 | SpellDescription$ CARDNAME deals 4 damage divided as you choose among any number of targets.
|
||||
Oracle:Explosive Crystal deals 4 damage divided as you choose among any number of targets.
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
Name:Arena
|
||||
ManaCost:no cost
|
||||
Types:Land
|
||||
A:AB$ Tap | Cost$ 3 T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ DBTap | AlwaysRemember$ True | SpellDescription$ Tap target creature you control and target creature of an opponent's choice they control. Those creatures fight each other. (Each deals damage equal to its power to the other.)
|
||||
SVar:DBTap:DB$ Tap | TargetingPlayer$ Player.Opponent | TargetingPlayerControls$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature you control | SubAbility$ DBFight | AlwaysRemember$ True
|
||||
SVar:DBFight:DB$ Fight | Defined$ Remembered | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
AI:RemoveDeck:All
|
||||
A:AB$ Tap | Cost$ 3 T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ DBTap | AILogic$ Arena | SpellDescription$ Tap target creature you control and target creature of an opponent's choice they control. Those creatures fight each other. (Each deals damage equal to its power to the other.)
|
||||
SVar:DBTap:DB$ Tap | TargetingPlayer$ Player.Opponent | TargetingPlayerControls$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature you control | SubAbility$ DBFight
|
||||
SVar:DBFight:DB$ Fight | Defined$ Targeted
|
||||
Oracle:{3}, {T}: Tap target creature you control and target creature of an opponent's choice they control. Those creatures fight each other. (Each deals damage equal to its power to the other.)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Name:Congregation at Dawn
|
||||
ManaCost:G G W
|
||||
Types:Instant
|
||||
A:SP$ ChangeZone | Cost$ G G W | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | ChangeType$ Creature | ChangeNum$ 3 | SpellDescription$ Search your library for up to three creature cards, reveal them, then shuffle and put those cards on top in any order.
|
||||
A:SP$ ChangeZone | Cost$ G G W | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | ChangeType$ Creature | ChangeNum$ 3 | Reorder$ True | SpellDescription$ Search your library for up to three creature cards, reveal them, then shuffle and put those cards on top in any order.
|
||||
Oracle:Search your library for up to three creature cards, reveal them, then shuffle and put those cards on top in any order.
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:2 R
|
||||
Types:Creature Dwarf
|
||||
PT:2/2
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZone | TriggerDescription$ When CARDNAME enters the battlefield, search your library for any number of Dwarf cards, reveal them, then shuffle and put those cards on top in any order.
|
||||
SVar:TrigChangeZone:DB$ ChangeZone | ChangeNum$ X | ChangeType$ Dwarf | Origin$ Library | Destination$ Library | LibraryPosition$ 0
|
||||
SVar:TrigChangeZone:DB$ ChangeZone | ChangeNum$ X | ChangeType$ Dwarf | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | Reorder$ True
|
||||
SVar:X:Count$InYourLibrary.Dwarf
|
||||
AI:RemoveDeck:All
|
||||
DeckNeeds:Type$Dwarf
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:1 R
|
||||
Types:Creature Goblin
|
||||
PT:1/1
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeZone | TriggerDescription$ When CARDNAME enters the battlefield, search your library for any number of Goblin cards, reveal them, then shuffle and put those cards on top in any order.
|
||||
SVar:TrigChangeZone:DB$ ChangeZone | ChangeNum$ X | ChangeType$ Goblin | Origin$ Library | Destination$ Library | LibraryPosition$ 0
|
||||
SVar:TrigChangeZone:DB$ ChangeZone | ChangeNum$ X | ChangeType$ Goblin | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | Reorder$ True
|
||||
SVar:X:Count$InYourLibrary.Goblin
|
||||
DeckNeeds:Type$Goblin
|
||||
#TODO: The AI generally is able to use this card, but will basically place all of its goblins on top of the library in no specific order, which is not very smart. Might need some improvement before RemoveDeck is removed. Currently adding a restriction to at least only play it if the AI has enough lands out on the battlefield already.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Insidious Dreams
|
||||
ManaCost:3 B
|
||||
Types:Instant
|
||||
A:SP$ ChangeZone | Cost$ 3 B Discard<X/Card> | Origin$ Library | Destination$ Library | ChangeType$ Card | ChangeNum$ X | LibraryPosition$ 0 | Mandatory$ True | SpellDescription$ Search your library for X cards, then shuffle and put those cards on top in any order.
|
||||
A:SP$ ChangeZone | Cost$ 3 B Discard<X/Card> | Origin$ Library | Destination$ Library | ChangeType$ Card | ChangeNum$ X | LibraryPosition$ 0 | Mandatory$ True | Reorder$ True | SpellDescription$ Search your library for X cards, then shuffle and put those cards on top in any order.
|
||||
SVar:X:Count$xPaid
|
||||
AI:RemoveDeck:All
|
||||
Oracle:As an additional cost to cast this spell, discard X cards.\nSearch your library for X cards, then shuffle and put those cards on top in any order.
|
||||
|
||||
@@ -7,7 +7,7 @@ SVar:CheckLifePaid:DB$ StoreSVar | SVar$ LifePaid | Type$ Number | Expression$ 1
|
||||
SVar:DBResetRem:DB$ Cleanup | ClearRemembered$ True | SubAbility$ GoToBottom
|
||||
SVar:GoToBottom:DB$ Dig | DigNum$ 5 | ChangeNum$ All | DestinationZone$ Library | LibraryPosition$ -1 | NoLooking$ True | SubAbility$ DBLookAgain | StackDescription$ None
|
||||
SVar:DBLookAgain:DB$ PeekAndReveal | PeekAmount$ 5 | NoReveal$ True | RememberPeeked$ True | StackDescription$ None
|
||||
SVar:DBShuffle:DB$ ChangeZone | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | ChangeType$ Card.IsRemembered | ChangeNum$ 5 | SubAbility$ DBReset | Hidden$ True | SelectPrompt$ Pick 1 on the top of library | Mandatory$ True | NoReveal$ True | NoLooking$ True | StackDescription$ None
|
||||
SVar:DBShuffle:DB$ ChangeZone | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | ChangeType$ Card.IsRemembered | ChangeNum$ 5 | SubAbility$ DBReset | Hidden$ True | SelectPrompt$ Pick 1 on the top of library | Mandatory$ True | NoReveal$ True | NoLooking$ True | Reorder$ True | StackDescription$ None
|
||||
SVar:DBReset:DB$ StoreSVar | SVar$ LifePaid | Type$ Number | Expression$ 0 | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:LifePaid:Number$0
|
||||
|
||||
@@ -2,9 +2,7 @@ Name:Magus of the Arena
|
||||
ManaCost:4 R R
|
||||
Types:Creature Human Wizard
|
||||
PT:5/5
|
||||
A:AB$ Tap | Cost$ 3 T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ DBTap | AlwaysRemember$ True | SpellDescription$ Tap target creature you control and target creature of an opponent's choice they control. Those creatures fight each other. (Each deals damage equal to its power to the other.)
|
||||
SVar:DBTap:DB$ Tap | TargetingPlayer$ Player.Opponent | TargetingPlayerControls$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature you control | SubAbility$ DBFight | AlwaysRemember$ True
|
||||
SVar:DBFight:DB$ Fight | Defined$ Remembered | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
AI:RemoveDeck:All
|
||||
A:AB$ Tap | Cost$ 3 T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ DBTap | AILogic$ Arena | SpellDescription$ Tap target creature you control and target creature of an opponent's choice they control. Those creatures fight each other. (Each deals damage equal to its power to the other.)
|
||||
SVar:DBTap:DB$ Tap | TargetingPlayer$ Player.Opponent | TargetingPlayerControls$ True | ValidTgts$ Creature | TgtPrompt$ Select target creature you control | SubAbility$ DBFight
|
||||
SVar:DBFight:DB$ Fight | Defined$ Targeted
|
||||
Oracle:{3}, {T}: Tap target creature you control and target creature of an opponent's choice they control. Those creatures fight each other. (Each deals damage equal to its power to the other.)
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Nova Pentacle
|
||||
ManaCost:4
|
||||
Types:Artifact
|
||||
A:AB$ ChooseSource | Cost$ 3 T | Choices$ Card,Emblem | AILogic$ NeedsPrevention | SubAbility$ DBEffect | SpellDescription$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead.
|
||||
SVar:DBEffect:DB$ Effect | TargetingPlayer$ Player.Opponent | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect the damage to | ReplacementEffects$ SelflessDamage | ExileOnMoved$ Battlefield | RememberObjects$ Targeted | ExileOnMoved$ Battlefield | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem
|
||||
SVar:DBEffect:DB$ Effect | TargetingPlayer$ Player.Opponent | ValidTgts$ Creature | TgtPrompt$ Select target creature to redirect the damage to | ReplacementEffects$ SelflessDamage | ExileOnMoved$ Battlefield | RememberObjects$ Targeted | SubAbility$ DBCleanup | ConditionDefined$ ChosenCard | ConditionPresent$ Card,Emblem
|
||||
SVar:SelflessDamage:Event$ DamageDone | ValidTarget$ You | ValidSource$ Card.ChosenCardStrict,Emblem.ChosenCard | ReplaceWith$ SelflessDmg | DamageTarget$ Remembered | Description$ The next time a source of your choice would deal damage to you this turn, that damage is dealt to target creature of an opponent's choice instead.
|
||||
SVar:SelflessDmg:DB$ ReplaceEffect | VarName$ Affected | VarValue$ Remembered | VarType$ Card | SubAbility$ ExileEffect
|
||||
SVar:ExileEffect:DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Scouting Trek
|
||||
ManaCost:1 G
|
||||
Types:Sorcery
|
||||
A:SP$ ChangeZone | Cost$ 1 G | ChangeNum$ X | ChangeType$ Land.Basic | Origin$ Library | Destination$ Library | LibraryPosition$ 0 | SpellDescription$ Search your library for any number of basic land cards, reveal those cards, then shuffle and put them on top.
|
||||
A:SP$ ChangeZone | Cost$ 1 G | ChangeNum$ X | ChangeType$ Land.Basic | Origin$ Library | Destination$ Library | Reorder$ True | LibraryPosition$ 0 | SpellDescription$ Search your library for any number of basic land cards, reveal those cards, then shuffle and put them on top.
|
||||
SVar:X:Count$InYourLibrary.Land.Basic
|
||||
AI:RemoveDeck:All
|
||||
Oracle:Search your library for any number of basic land cards, reveal those cards, then shuffle and put them on top.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Ulvenwald Tracker
|
||||
ManaCost:G
|
||||
Types:Creature Human Shaman
|
||||
PT:1/1
|
||||
A:AB$ Pump | Cost$ 1 G T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ TrackerFight | StackDescription$ None
|
||||
SVar:TrackerFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature | TargetUnique$ True | TgtPrompt$ Select another target creature | SpellDescription$ Target creature you control fights another target creature.
|
||||
A:AB$ Pump | Cost$ 1 G T | ValidTgts$ Creature.YouCtrl | TgtPrompt$ Select target creature you control | SubAbility$ TrackerFight | StackDescription$ None | SpellDescription$ Target creature you control fights another target creature.
|
||||
SVar:TrackerFight:DB$ Fight | Defined$ ParentTarget | ValidTgts$ Creature | TargetUnique$ True | TgtPrompt$ Select another target creature
|
||||
AI:RemoveDeck:All
|
||||
Oracle:{1}{G}, {T}: Target creature you control fights another target creature.
|
||||
|
||||
Reference in New Issue
Block a user