Merge branch 'Card-Forge:master' into master

This commit is contained in:
CCTV-1
2022-11-23 14:53:51 +08:00
committed by GitHub
82 changed files with 471 additions and 172 deletions

View File

@@ -2430,7 +2430,7 @@ public class GameAction {
}
if (c.isPlaneswalker()) {
int lethalPW = c.getCurrentLoyalty();
// 120.10
// CR 120.10
lethal = c.isCreature() ? Math.min(lethal, lethalPW) : lethalPW;
}
lethalDamage.put(c, lethal);
@@ -2442,6 +2442,7 @@ public class GameAction {
sourceLKI.getDamageHistory().registerDamage(e.getValue(), isCombat, sourceLKI, e.getKey(), lkiCache);
}
// CR 702.15e
if (sum > 0 && sourceLKI.hasKeyword(Keyword.LIFELINK)) {
sourceLKI.getController().gainLife(sum, sourceLKI, cause);
}

View File

@@ -302,8 +302,7 @@ public final class AbilityFactory {
}
if (spellAbility instanceof SpellApiBased && hostCard.isPermanent()) {
String desc = mapParams.containsKey("SpellDescription") ? mapParams.get("SpellDescription")
: spellAbility.getHostCard().getName();
String desc = mapParams.getOrDefault("SpellDescription", spellAbility.getHostCard().getName());
spellAbility.setDescription(desc);
} else if (mapParams.containsKey("SpellDescription")) {
spellAbility.rebuiltDescription();

View File

@@ -65,6 +65,10 @@ public class CharmEffect extends SpellAbilityEffect {
// using getCardForUi game is not set, so can't guess max charm
num = Integer.MAX_VALUE;
} else {
// fallback needed while ability building
if (sa.getActivatingPlayer() == null) {
sa.setActivatingPlayer(source.getController());
}
num = Math.min(AbilityUtils.calculateAmount(source, sa.getParamOrDefault("CharmNum", "1"), sa), list.size());
}
final int min = sa.hasParam("MinCharmNum") ? AbilityUtils.calculateAmount(source, sa.getParam("MinCharmNum"), sa) : num;

View File

@@ -320,12 +320,9 @@ public class DamageDealEffect extends DamageBaseEffect {
} else {
if (sa.hasParam("ExcessDamage") && (!sa.hasParam("ExcessDamageCondition") ||
sourceLKI.isValid(sa.getParam("ExcessDamageCondition").split(","), activationPlayer, hostCard, sa))) {
damageMap.put(sourceLKI, c, dmgToTarget);
List<GameEntity> list = Lists.newArrayList();
list.addAll(AbilityUtils.getDefinedCards(hostCard, sa.getParam("ExcessDamage"), sa));
list.addAll(AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("ExcessDamage"), sa));
List<GameEntity> list = AbilityUtils.getDefinedEntities(hostCard, sa.getParam("ExcessDamage"), sa);
if (!list.isEmpty()) {
damageMap.put(sourceLKI, list.get(0), excess);

View File

@@ -17,6 +17,7 @@ import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.TextUtil;
public abstract class DamagePreventEffectBase extends SpellAbilityEffect {
@@ -24,7 +25,7 @@ public abstract class DamagePreventEffectBase extends SpellAbilityEffect {
final Card hostCard = sa.getHostCard();
final Game game = hostCard.getGame();
final Player player = hostCard.getController();
final String name = hostCard.getName() + "'s Effect";
final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect";
final String image = hostCard.getImageKey();
StringBuilder sb = new StringBuilder("Event$ DamageDone | ActiveZones$ Command | ValidTarget$ ");
sb.append((o instanceof Card ? "Card.IsRemembered" : "Player.IsRemembered"));

View File

@@ -38,6 +38,7 @@ public class DelayedTriggerEffect extends SpellAbilityEffect {
final Card host = sa.getHostCard();
final Game game = host.getGame();
Map<String, String> mapParams = Maps.newHashMap(sa.getMapParams());
mapParams.remove("Cost");
if (mapParams.containsKey("SpellDescription")) {

View File

@@ -27,6 +27,7 @@ import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.TextUtil;
import forge.util.collect.FCollection;
@@ -113,7 +114,7 @@ public class EffectEffect extends SpellAbilityEffect {
String name = sa.getParam("Name");
if (name == null) {
name = hostCard.getName() + (sa.hasParam("Boon") ? "'s Boon" : "'s Effect");
name = CardTranslation.getTranslatedName(hostCard.getName()) + (sa.hasParam("Boon") ? "'s Boon" : "'s Effect");
}
// Unique Effects shouldn't be duplicated

View File

@@ -10,6 +10,7 @@ import forge.game.replacement.ReplacementHandler;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
public class FogEffect extends SpellAbilityEffect {
@@ -22,7 +23,7 @@ public class FogEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) {
final Card hostCard = sa.getHostCard();
final Game game = hostCard.getGame();
final String name = hostCard.getName() + "'s Effect";
final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect";
final String image = hostCard.getImageKey();
StringBuilder sb = new StringBuilder("Event$ DamageDone | ActiveZones$ Command | IsCombat$ True");
sb.append(" | Prevent$ True | Description$ Prevent all combat damage this turn.");

View File

@@ -15,6 +15,7 @@ import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
@@ -24,44 +25,44 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
// create Effect for Regeneration
final Card eff = createEffect(
sa, sa.getActivatingPlayer(), hostCard.getName() + "'s Regeneration", hostCard.getImageKey());
sa, sa.getActivatingPlayer(), CardTranslation.getTranslatedName(hostCard.getName()) + "'s Regeneration", hostCard.getImageKey());
eff.addRemembered(list);
addForgetOnMovedTrigger(eff, "Battlefield");
// build ReplacementEffect
String repeffstr = "Event$ Destroy | ActiveZones$ Command | ValidCard$ Card.IsRemembered | Regeneration$ True"
+ " | Description$ Regeneration (if creature would be destroyed, regenerate it instead)";
String effect = "DB$ Regeneration | Defined$ ReplacedCard";
String exileEff = "DB$ ChangeZone | Defined$ Self | Origin$ Command | Destination$ Exile"
+ " | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0";
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, eff, true);
SpellAbility saReg = AbilityFactory.getAbility(effect, eff);
AbilitySub saExile = (AbilitySub)AbilityFactory.getAbility(exileEff, eff);
AbilitySub saExile = (AbilitySub)AbilityFactory.getAbility(exileEff, eff);
saReg.setSubAbility(saExile);
re.setOverridingAbility(saReg);
eff.addReplacementEffect(re);
// add extra Remembered
if (sa.hasParam("RememberObjects")) {
eff.addRemembered(AbilityUtils.getDefinedObjects(hostCard, sa.getParam("RememberObjects"), sa));
}
if (sa.hasParam("RegenerationTrigger")) {
final String str = sa.getSVar(sa.getParam("RegenerationTrigger"));
SpellAbility trigSA = AbilityFactory.getAbility(str, eff);
final String trigStr = "Mode$ Regenerated | ValidCause$ Effect.Self | TriggerZones$ Command "
+ " | TriggerDescription$ " + trigSA.getDescription();
final Trigger trigger = TriggerHandler.parseTrigger(trigStr, eff, true);
trigger.setOverridingAbility(trigSA);
eff.addTrigger(trigger);
}
// Copy text changes
if (sa.isIntrinsic()) {
eff.copyChangedTextFrom(hostCard);
@@ -75,7 +76,7 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect {
game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap());
eff.updateStateForView();
game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
final GameCommand untilEOT = new GameCommand() {
private static final long serialVersionUID = 259368227093961103L;

View File

@@ -15,6 +15,7 @@ import forge.game.replacement.ReplacementLayer;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
public class SkipPhaseEffect extends SpellAbilityEffect {
@@ -58,7 +59,7 @@ public class SkipPhaseEffect extends SpellAbilityEffect {
final String duration, final String phase, final String step) {
final Card hostCard = sa.getHostCard();
final Game game = hostCard.getGame();
final String name = hostCard.getName() + "'s Effect";
final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect";
final String image = hostCard.getImageKey();
final boolean isNextThisTurn = duration != null && duration.equals("NextThisTurn");

View File

@@ -16,6 +16,7 @@ import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.util.CardTranslation;
import forge.util.Lang;
public class SkipTurnEffect extends SpellAbilityEffect {
@@ -38,7 +39,7 @@ public class SkipTurnEffect extends SpellAbilityEffect {
public void resolve(SpellAbility sa) {
final Card hostCard = sa.getHostCard();
final Game game = hostCard.getGame();
final String name = hostCard.getName() + "'s Effect";
final String name = CardTranslation.getTranslatedName(hostCard.getName()) + "'s Effect";
final String image = hostCard.getImageKey();
final int numTurns = AbilityUtils.calculateAmount(hostCard, sa.getParam("NumTurns"), sa);
String repeffstr = "Event$ BeginTurn | ActiveZones$ Command | ValidPlayer$ You " +

View File

@@ -299,7 +299,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
private Map<Long, Player> goad = Maps.newTreeMap();
private final List<GameCommand> leavePlayCommandList = Lists.newArrayList();
private final List<GameCommand> etbCommandList = Lists.newArrayList();
private final List<GameCommand> untapCommandList = Lists.newArrayList();
private final List<GameCommand> changeControllerCommandList = Lists.newArrayList();
private final List<GameCommand> unattachCommandList = Lists.newArrayList();
@@ -3265,20 +3264,24 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
return canCounter;
}
public final void addComesIntoPlayCommand(final GameCommand c) {
etbCommandList.add(c);
}
public final void runComesIntoPlayCommands() {
for (final GameCommand c : etbCommandList) {
c.run();
}
etbCommandList.clear();
}
public final void addLeavesPlayCommand(final GameCommand c) {
leavePlayCommandList.add(c);
}
public final void addUntapCommand(final GameCommand c) {
untapCommandList.add(c);
}
public final void addUnattachCommand(final GameCommand c) {
unattachCommandList.add(c);
}
public final void addFaceupCommand(final GameCommand c) {
faceupCommandList.add(c);
}
public final void addFacedownCommand(final GameCommand c) {
facedownCommandList.add(c);
}
public final void addChangeControllerCommand(final GameCommand c) {
changeControllerCommandList.add(c);
}
public final void runLeavesPlayCommands() {
for (final GameCommand c : leavePlayCommandList) {
@@ -3286,22 +3289,6 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
leavePlayCommandList.clear();
}
public final void addUntapCommand(final GameCommand c) {
untapCommandList.add(c);
}
public final void addUnattachCommand(final GameCommand c) {
unattachCommandList.add(c);
}
public final void addFaceupCommand(final GameCommand c) {
faceupCommandList.add(c);
}
public final void addFacedownCommand(final GameCommand c) {
facedownCommandList.add(c);
}
public final void runUntapCommands() {
for (final GameCommand c : untapCommandList) {
c.run();
@@ -3314,25 +3301,18 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
}
unattachCommandList.clear();
}
public final void runFaceupCommands() {
for (final GameCommand c : faceupCommandList) {
c.run();
}
faceupCommandList.clear();
}
public final void runFacedownCommands() {
for (final GameCommand c : facedownCommandList) {
c.run();
}
facedownCommandList.clear();
}
public final void addChangeControllerCommand(final GameCommand c) {
changeControllerCommandList.add(c);
}
public final void runChangeControllerCommands() {
for (final GameCommand c : changeControllerCommandList) {
c.run();
@@ -3346,16 +3326,16 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
view.updateSickness(this);
}
public final boolean isFirstTurnControlled() {
return sickness;
}
public final boolean hasSickness() {
return sickness && !hasKeyword(Keyword.HASTE);
}
public final boolean isSick() {
return sickness && isCreature() && !hasKeyword(Keyword.HASTE);
return hasSickness() && isCreature();
}
public final boolean isFirstTurnControlled() {
return sickness;
}
public boolean hasBecomeTargetThisTurn() {
@@ -5070,7 +5050,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false);
// when it doesn't exist the game will no longer see it as tapped
runUntapCommands();
// TODO need to run UntilHostLeavesPlay commands but only when worded "for as long as"
// TODO CR 702.26f need to run LeavesPlay + changeController commands but only when worded "for as long as"
}
setPhasedOut(!phasedOut);
@@ -5636,7 +5616,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
@Override
public final int addDamageAfterPrevention(final int damageIn, final Card source, final boolean isCombat, GameEntityCounterTable counterTable) {
if (damageIn <= 0) {
return 0; // Rule 119.8
return 0; // 120.8
}
// 120.1a Damage cant be dealt to an object thats neither a creature nor a planeswalker.

View File

@@ -294,6 +294,8 @@ public enum CounterEnumType {
P2P2("+2/+2", "+2/+2", 96, 226, 23),
QUEST("QUEST", 251, 189, 0),
REPRIEVE("REPR", 240, 120, 50),
RITUAL("RITUAL", 155, 17, 30),

View File

@@ -160,7 +160,7 @@ public class PlayerProperty {
return false;
}
} else if (property.equals("Defending")) {
if (!game.getCombat().getAttackersAndDefenders().values().contains(player)) {
if (game.getCombat() == null || !game.getCombat().getAttackersAndDefenders().values().contains(player)) {
return false;
}
} else if (property.equals("LostLifeThisTurn")) {

View File

@@ -29,7 +29,6 @@ public class StaticAbilityNumLoyaltyAct {
}
public static boolean applyLimitIncrease(final StaticAbility stAb, final Card card) {
if (!stAb.matchesValidParam("ValidCard", card)) {
return false;
}
@@ -58,7 +57,7 @@ public class StaticAbilityNumLoyaltyAct {
}
}
int more = AbilityUtils.calculateAmount(card, stAb.getParam("Additional"), stAb);
addl = addl + more;
addl += more;
}
}
}

View File

@@ -305,7 +305,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
return;
}
if (sp instanceof AbilityStatic) {
if (sp instanceof AbilityStatic || (sp.isTrigger() && sp.getTrigger().getOverridingAbility() instanceof AbilityStatic)) {
AbilityUtils.resolve(sp);
// AbilityStatic should do nothing below
return;

View File

@@ -36,7 +36,6 @@ public class PlayerZoneBattlefield extends PlayerZone {
private static final long serialVersionUID = 5750837078903423978L;
private boolean trigger = true;
private boolean leavesTrigger = true;
private CardCollection meldedCards = new CardCollection();
public PlayerZoneBattlefield(final ZoneType zone, final Player player) {
@@ -63,7 +62,6 @@ public class PlayerZoneBattlefield extends PlayerZone {
if (trigger) {
c.setSickness(true); // summoning sickness
c.runComesIntoPlayCommands();
}
}
@@ -72,14 +70,13 @@ public class PlayerZoneBattlefield extends PlayerZone {
public final void remove(final Card c) {
super.remove(c);
if (leavesTrigger) {
if (trigger) {
c.runLeavesPlayCommands();
}
}
public final void setTriggers(final boolean b) {
trigger = b;
leavesTrigger = b;
}
@Override

View File

@@ -73,6 +73,7 @@ public class Forge implements ApplicationListener {
public static KeyInputAdapter keyInputAdapter;
private static boolean exited;
public boolean needsUpdate = false;
public static boolean advStartup = false;
public static boolean safeToClose = true;
public static boolean magnify = false;
public static boolean magnifyToggle = true;

View File

@@ -39,12 +39,9 @@ import java.util.HashMap;
import java.util.Map;
public class AdventureDeckEditor extends TabPageScreen<AdventureDeckEditor> {
public static FSkinImage MAIN_DECK_ICON = Forge.hdbuttons ? FSkinImage.HDLIBRARY :FSkinImage.DECKLIST;
public static FSkinImage SIDEBOARD_ICON = Forge.hdbuttons ? FSkinImage.HDSIDEBOARD : FSkinImage.FLASHBACK;
private static final float HEADER_HEIGHT = Math.round(Utils.AVG_FINGER_HEIGHT * 0.8f);
private static final FileHandle tomeIcon = Config.instance().getFile("ui/tome.png");
private static Texture tomeIconTexture = tomeIcon.exists() ? new Texture(tomeIcon) : null;
private static FImage CATALOG_ICON = tomeIcon.exists() ? new FImage() {
private static final FileHandle deckIcon = Config.instance().getFile("ui/maindeck.png");
private static Texture deckTexture = deckIcon.exists() ? new Texture(deckIcon) : null;
private static FImage MAIN_DECK_ICON = deckIcon.exists() ? new FImage() {
@Override
public float getWidth() {
return 100f;
@@ -55,7 +52,40 @@ import java.util.Map;
}
@Override
public void draw(Graphics g, float x, float y, float w, float h) {
g.drawImage(tomeIconTexture, x, y, w, h);
g.drawImage(deckTexture, x, y, w, h);
}
} : Forge.hdbuttons ? FSkinImage.HDLIBRARY :FSkinImage.DECKLIST;
private static final FileHandle sideIcon = Config.instance().getFile("ui/sideboard.png");
private static Texture sideTexture = sideIcon.exists() ? new Texture(sideIcon) : null;
private static FImage SIDEBOARD_ICON = sideIcon.exists() ? new FImage() {
@Override
public float getWidth() {
return 100f;
}
@Override
public float getHeight() {
return 100f;
}
@Override
public void draw(Graphics g, float x, float y, float w, float h) {
g.drawImage(sideTexture, x, y, w, h);
}
} : Forge.hdbuttons ? FSkinImage.HDSIDEBOARD : FSkinImage.FLASHBACK;
private static final float HEADER_HEIGHT = Math.round(Utils.AVG_FINGER_HEIGHT * 0.8f);
private static final FileHandle binderIcon = Config.instance().getFile("ui/binder.png");
private static Texture binderTexture = binderIcon.exists() ? new Texture(binderIcon) : null;
private static FImage CATALOG_ICON = binderIcon.exists() ? new FImage() {
@Override
public float getWidth() {
return 100f;
}
@Override
public float getHeight() {
return 100f;
}
@Override
public void draw(Graphics g, float x, float y, float w, float h) {
g.drawImage(binderTexture, x, y, w, h);
}
} : FSkinImage.QUEST_BOX;
private static final FileHandle sellIcon = Config.instance().getFile("ui/sell.png");

View File

@@ -8,16 +8,13 @@ import forge.Graphics;
import forge.LobbyPlayer;
import forge.adventure.character.EnemySprite;
import forge.adventure.character.PlayerSprite;
import forge.adventure.data.BiomeData;
import forge.adventure.data.EffectData;
import forge.adventure.data.EnemyData;
import forge.adventure.data.ItemData;
import forge.adventure.player.AdventurePlayer;
import forge.adventure.stage.IAfterMatch;
import forge.adventure.stage.MapStage;
import forge.adventure.util.Config;
import forge.adventure.util.Current;
import forge.adventure.world.World;
import forge.assets.FBufferedImage;
import forge.assets.FSkin;
import forge.deck.Deck;
@@ -343,23 +340,6 @@ public class DuelScene extends ForgeScene {
this.AIExtras.clear();
this.playerExtras.clear();
}
public String getCurrentLocation() {
String location = "";
if(MapStage.getInstance().isInMap())
location = TileMapScene.instance().rootPoint.getData().type;
else {
World world= Current.world();
int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize()));
List<BiomeData> biomeData = Current.world().getData().GetBiomes();
try {
BiomeData data = biomeData.get(currentBiome);
location = data.name;
} catch (Exception e) {
e.printStackTrace();
}
}
return location;
}
private String selectAI(String ai) { //Decide opponent AI.
String AI = ""; //Use user settings if it's null.

View File

@@ -3,8 +3,15 @@ package forge.adventure.scene;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import forge.Forge;
import forge.adventure.character.PlayerSprite;
import forge.adventure.data.BiomeData;
import forge.adventure.stage.MapStage;
import forge.adventure.stage.WorldStage;
import forge.adventure.util.Current;
import forge.adventure.world.World;
import forge.util.TextUtil;
import java.util.List;
/**
* Game scene main over world scene
@@ -51,6 +58,24 @@ public class GameScene extends HudScene {
super.enter();
WorldStage.getInstance().handlePointsOfInterestCollision();
}
public String getAdventurePlayerLocation(boolean forHeader) {
String location = "";
if(MapStage.getInstance().isInMap()) {
location = forHeader? TileMapScene.instance().rootPoint.getData().name : TileMapScene.instance().rootPoint.getData().type;
} else {
World world= Current.world();
PlayerSprite player = WorldStage.getInstance().getPlayerSprite();
int currentBiome = World.highestBiome(world.getBiome((int) player.getX() / world.getTileSize(), (int) player.getY() / world.getTileSize()));
List<BiomeData> biomeData = Current.world().getData().GetBiomes();
try {
BiomeData data = biomeData.get(currentBiome);
location = forHeader? TextUtil.capitalize(data.name)+" Map" : data.name;
} catch (Exception e) {
e.printStackTrace();
location = "";
}
}
return location;
}
}

View File

@@ -21,6 +21,7 @@ import forge.adventure.util.Current;
import forge.adventure.world.WorldSave;
import forge.adventure.world.WorldSaveHeader;
import forge.screens.TransitionScreen;
import forge.util.TextUtil;
import java.io.File;
import java.io.FileInputStream;
@@ -42,7 +43,7 @@ public class SaveLoadScene extends UIScene {
TextraLabel header;
int currentSlot = 0, lastSelectedSlot = 0;
Image previewImage;
TextraLabel previewDate;
TextraLabel previewDate, playerLocation;
Image previewBorder;
TextraButton saveLoadButton, back;
Selectable<TextraButton> quickSave;
@@ -50,6 +51,7 @@ public class SaveLoadScene extends UIScene {
Actor lastHighlightedSave;
SelectBox difficulty;
ScrollPane scrollPane;
char ASCII_179 = '│';
private SaveLoadScene() {
super(Forge.isLandscapeMode() ? "ui/save_load.json" : "ui/save_load_portrait.json");
@@ -68,9 +70,13 @@ public class SaveLoadScene extends UIScene {
//DifficultyData difficulty1 = Config.instance().getConfigData().difficulties[difficulty.getSelectedIndex()];
return null;
});
previewImage = ui.findActor("preview");
previewDate = ui.findActor("saveDate");
playerLocation = Controls.newTextraLabel("");
playerLocation.setText("");
playerLocation.setX(previewImage.getX());
playerLocation.setY(previewImage.getY()+5);
ui.addActor(playerLocation);
header = Controls.newTextraLabel(Forge.getLocalizer().getMessage("lblSave"));
header.setAlignment(Align.center);
layout.add(header).pad(2).colspan(4).align(Align.center).expandX();
@@ -169,9 +175,19 @@ public class SaveLoadScene extends UIScene {
previewImage.setVisible(true);
previewDate.setVisible(true);
if (header.saveDate != null)
previewDate.setText(DateFormat.getDateInstance().format(header.saveDate) + "\n" + DateFormat.getTimeInstance(DateFormat.SHORT).format(header.saveDate));
previewDate.setText("{Scale=98%}"+DateFormat.getDateInstance().format(header.saveDate) + " " + DateFormat.getTimeInstance(DateFormat.SHORT).format(header.saveDate));
else
previewDate.setText("");
if (header.name.contains(Character.toString(ASCII_179))) {
String[] split = TextUtil.split(header.name, ASCII_179);
try {
playerLocation.setText(split[1]);
} catch (Exception e) {
playerLocation.setText("");
}
} else {
playerLocation.setText("");
}
}
} else {
if (previewImage != null)
@@ -239,7 +255,7 @@ public class SaveLoadScene extends UIScene {
public void save() {
if (WorldSave.getCurrentSave().save(textInput.getText(), currentSlot)) {
if (WorldSave.getCurrentSave().save(textInput.getText()+ASCII_179+GameScene.instance().getAdventurePlayerLocation(true), currentSlot)) {
updateFiles();
//ensure the dialog is hidden before switching
@@ -275,7 +291,13 @@ public class SaveLoadScene extends UIScene {
int slot = WorldSave.filenameToSlot(name.getName());
WorldSaveHeader header = (WorldSaveHeader) oos.readObject();
buttons.get(slot).actor.setText(header.name);
if (header.name.contains(Character.toString(ASCII_179))) {
String[] split = TextUtil.split(header.name, ASCII_179);
buttons.get(slot).actor.setText(split[0]);
//playerLocation.setText(split[1]);
} else {
buttons.get(slot).actor.setText(header.name);
}
previews.put(slot, header);
}

View File

@@ -111,12 +111,12 @@ public class GameHUD extends Stage {
lifePoints = ui.findActor("lifePoints");
mana = ui.findActor("mana");
money = ui.findActor("money");
mana.setText("0/0");
lifePoints.setText("20/20");
AdventurePlayer.current().onLifeChange(() -> lifePoints.setText(AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife()));
AdventurePlayer.current().onManaChange(() -> mana.setText(AdventurePlayer.current().getMana() + "/" + AdventurePlayer.current().getMaxMana()));
mana.setText("{Scale=80%}0/0");
lifePoints.setText("{Scale=80%}20/20");
AdventurePlayer.current().onLifeChange(() -> lifePoints.setText("{Scale=80%}"+AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife()));
AdventurePlayer.current().onManaChange(() -> mana.setText("{Scale=80%}"+AdventurePlayer.current().getMana() + "/" + AdventurePlayer.current().getMaxMana()));
WorldSave.getCurrentSave().getPlayer().onGoldChange(() -> money.setText(String.valueOf(AdventurePlayer.current().getGold())));
WorldSave.getCurrentSave().getPlayer().onGoldChange(() -> money.setText("{Scale=80%}"+String.valueOf(AdventurePlayer.current().getGold())));
addActor(ui);
addActor(miniMapPlayer);
console = new Console();

View File

@@ -2,7 +2,6 @@ package forge.itemmanager;
import java.util.Map.Entry;
import forge.Forge;
import forge.Graphics;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont;
@@ -49,8 +48,7 @@ public class CardManager extends ItemManager<PaperCard> {
public static void addDefaultFilters(final ItemManager<? super PaperCard> itemManager) {
itemManager.addFilter(new CardColorFilter(itemManager));
if (!Forge.isMobileAdventureMode)
itemManager.addFilter(new CardFormatFilter(itemManager));
itemManager.addFilter(new CardFormatFilter(itemManager));
itemManager.addFilter(new CardTypeFilter(itemManager));
}

View File

@@ -47,6 +47,7 @@ public abstract class FormatFilter<T extends InventoryItem> extends ItemFilter<T
}
cbxFormats.addItem(Forge.getLocalizer().getMessage("lblOtherFormats"));
cbxFormats.addItem(Forge.getLocalizer().getMessage("lblChooseSets"));
cbxFormats.setEnabled(!Forge.isMobileAdventureMode);
selectedFormat = cbxFormats.getText();
cbxFormats.setChangedHandler(new FEventHandler() {

View File

@@ -1,6 +1,9 @@
package forge.screens;
import static forge.assets.FSkin.getDefaultSkinFile;
import static forge.assets.FSkin.getSkinFile;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import forge.Forge;
import forge.Graphics;
import forge.animation.ForgeAnimation;
@@ -16,6 +19,9 @@ public class ClosingScreen extends FContainer {
private StaticAnimation staticAnimation;
private boolean restart = false;
private boolean drawStatic = false;
private FileHandle adv_logo = getSkinFile("adv_logo.png");
private FileHandle existingLogo = adv_logo.exists() ? adv_logo : getDefaultSkinFile("adv_logo.png");
private Texture logo = existingLogo.exists() && Forge.advStartup ? new Texture(existingLogo) : FSkin.getLogo();
public ClosingScreen(boolean restart0) {
bgAnimation = new BGAnimation();
@@ -48,13 +54,14 @@ public class ClosingScreen extends FContainer {
}
g.fillRect(Color.BLACK, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());
g.setAlphaComposite(1-percentage);
g.drawImage(Forge.isMobileAdventureMode ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());
g.drawImage(Forge.isMobileAdventureMode || Forge.advStartup ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());
g.setAlphaComposite(oldAlpha);
float xmod = Forge.getScreenHeight() > 2000 ? 1.5f : 1f;
if (FSkin.getLogo() != null) {
g.drawImage(FSkin.getLogo(), Forge.getScreenWidth()/2 - (FSkin.getLogo().getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkin.getLogo().getHeight()*xmod)/2, FSkin.getLogo().getWidth()*xmod, FSkin.getLogo().getHeight()*xmod);
if (logo != null) {
g.drawImage(logo, Forge.getScreenWidth()/2 - (logo.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (logo.getHeight()*xmod)/2, logo.getWidth()*xmod, logo.getHeight()*xmod);
} else {
g.drawImage(FSkinImage.LOGO,Forge.getScreenWidth()/2 - (FSkinImage.LOGO.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkinImage.LOGO.getHeight()*xmod)/1.5f, FSkinImage.LOGO.getWidth()*xmod, FSkinImage.LOGO.getHeight()*xmod);
g.drawImage(FSkinImage.LOGO, Forge.getScreenWidth()/2 - (FSkinImage.LOGO.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkinImage.LOGO.getHeight()*xmod)/1.5f, FSkinImage.LOGO.getWidth()*xmod, FSkinImage.LOGO.getHeight()*xmod);
}
}
@@ -87,12 +94,12 @@ public class ClosingScreen extends FContainer {
}
g.fillRect(Color.BLACK, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());
g.setAlphaComposite(percentage);
g.drawImage(Forge.isMobileAdventureMode ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());
g.drawImage(Forge.isMobileAdventureMode || Forge.advStartup ? FSkinTexture.ADV_BG_TEXTURE : FSkinTexture.BG_TEXTURE, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());
g.setAlphaComposite(oldAlpha);
float xmod = Forge.getScreenHeight() > 2000 ? 1.5f : 1f;
xmod *= 21-(20*percentage);
if (FSkin.getLogo() != null) {
g.drawImage(FSkin.getLogo(), Forge.getScreenWidth()/2 - (FSkin.getLogo().getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkin.getLogo().getHeight()*xmod)/2, FSkin.getLogo().getWidth()*xmod, FSkin.getLogo().getHeight()*xmod);
if (logo != null) {
g.drawImage(logo, Forge.getScreenWidth()/2 - (logo.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (logo.getHeight()*xmod)/2, logo.getWidth()*xmod, logo.getHeight()*xmod);
} else {
g.drawImage(FSkinImage.LOGO,Forge.getScreenWidth()/2 - (FSkinImage.LOGO.getWidth()*xmod)/2, Forge.getScreenHeight()/2 - (FSkinImage.LOGO.getHeight()*xmod)/1.5f, FSkinImage.LOGO.getWidth()*xmod, FSkinImage.LOGO.getHeight()*xmod);
}

View File

@@ -19,7 +19,7 @@ public class TransitionScreen extends FContainer {
Runnable runnable;
TextureRegion textureRegion;
private String message = "";
boolean matchTransition, isloading, isIntro, isFadeMusic, advStartup;
boolean matchTransition, isloading, isIntro, isFadeMusic;
public TransitionScreen(Runnable proc, TextureRegion screen, boolean enterMatch, boolean loading) {
this(proc, screen, enterMatch, loading, false, false);
@@ -43,7 +43,7 @@ public class TransitionScreen extends FContainer {
isIntro = intro;
isFadeMusic = fadeMusic;
message = loadingMessage;
advStartup = Forge.selector.equals("Adventure");
Forge.advStartup = Forge.selector.equals("Adventure");
}
public FProgressBar getProgressBar() {
@@ -111,7 +111,7 @@ public class TransitionScreen extends FContainer {
g.drawWarpImage(textureRegion, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight(), percentage);
} else if (isIntro) {
if (textureRegion != null) {
if (advStartup) {
if (Forge.advStartup) {
g.drawGrayTransitionImage(Forge.getAssets().fallback_skins().get(0), 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight(), false, percentage);
g.setAlphaComposite(1-percentage);
g.drawImage(textureRegion, 0, 0, Forge.getScreenWidth(), Forge.getScreenHeight());

View File

@@ -4,7 +4,7 @@ import java.util.*;
import java.util.Map.Entry;
import com.badlogic.gdx.math.Vector2;
import forge.adventure.scene.DuelScene;
import forge.adventure.scene.GameScene;
import forge.animation.ForgeAnimation;
import forge.assets.FImage;
import forge.card.CardImageRenderer;
@@ -807,7 +807,7 @@ public class MatchScreen extends FScreen {
FSkinTexture getBG() {
if (Forge.isMobileAdventureMode) {
//System.out.println("Adventure Location: "+DuelScene.instance().getCurrentLocation());
switch(DuelScene.instance().getCurrentLocation()) {
switch(GameScene.instance().getAdventurePlayerLocation(false)) {
case "green":
return FSkinTexture.ADV_BG_FOREST;
case "black":

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -36,8 +36,8 @@
{
"type": "Label",
"name": "saveDate",
"x": 390,
"y": 125,
"x": 370,
"y": 24,
"width": 86,
"height": 32
},

View File

@@ -36,8 +36,8 @@
{
"type": "Label",
"name": "saveDate",
"x": 70,
"y": 40,
"x": 170,
"y": 8,
"width": 96,
"height": 16
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -2,9 +2,9 @@ Name:Academy Loremaster
ManaCost:U U
Types:Creature Human Wizard
PT:2/3
T:Mode$ Phase | Phase$ Draw | ValidPlayer$ Player | TriggerZones$ Battlefield | OptionalDecider$ TriggeredPlayer | Execute$ TrigDraw | TriggerDescription$ At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast
T:Mode$ Phase | Phase$ Draw | ValidPlayer$ Player | TriggerZones$ Battlefield | OptionalDecider$ TriggeredPlayer | Execute$ TrigDraw | TriggerDescription$ At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast.
SVar:TrigDraw:DB$ Draw | NumCards$ 1 | Defined$ TriggeredPlayer | RememberDrawn$ True | SubAbility$ DBEffect
SVar:DBEffect:DB$ Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | Duration$ EndOfTurn | StaticAbilities$ RaiseCost | SubAbility$ DBCleanup | SpellDescription$ Spells they cast this turn cost {2} more to cast
SVar:RaiseCost:Mode$ RaiseCost | ValidCard$ Card.ActivePlayerCtrl | Type$ Spell | Amount$ 2 | Description$ Spells they cast this turn cost {2} more to cast
SVar:DBEffect:DB$ Effect | ConditionDefined$ Remembered | ConditionPresent$ Card | Duration$ EndOfTurn | StaticAbilities$ RaiseCost | SubAbility$ DBCleanup
SVar:RaiseCost:Mode$ RaiseCost | ValidCard$ Card.ActivePlayerCtrl | Type$ Spell | Amount$ 2 | Description$ Spells they cast this turn cost {2} more to cast.
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
Oracle:At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast
Oracle:At the beginning of each player's draw step, that player may draw an additional card. If they do, spells they cast this turn cost {2} more to cast.

View File

@@ -2,7 +2,7 @@ Name:Awakening
ManaCost:2 G G
Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | TriggerZones$ Battlefield | Execute$ TrigUntapAll | TriggerDescription$ At the beginning of each upkeep, untap all creatures and lands.
SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature,Land | SpellDescription$ untap all creatures and lands.
SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature,Land
SVar:UntapsEachTurn:Creature,Land
AI:RemoveDeck:Random
Oracle:At the beginning of each upkeep, untap all creatures and lands.

View File

@@ -5,8 +5,8 @@ PT:2/2
K:Trample
K:Haste
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | TriggerZones$ Battlefield | Execute$ TrigDiscard | TriggerDescription$ Whenever CARDNAME deals damage to a player, that player discards all the cards in their hand, then draws that many cards.
SVar:TrigDiscard:DB$ Discard | Defined$ TriggeredTarget | Mode$ Hand | RememberDiscarded$ True | SubAbility$ DBDraw | SpellDescription$ Discard hand
SVar:DBDraw:DB$ Draw | NumCards$ X | Defined$ TriggeredTarget | SubAbility$ DBCleanup | SpellDescription$ Draw that many cards
SVar:TrigDiscard:DB$ Discard | Defined$ TriggeredTarget | Mode$ Hand | RememberDiscarded$ True | SubAbility$ DBDraw
SVar:DBDraw:DB$ Draw | NumCards$ X | Defined$ TriggeredTarget | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
SVar:X:Remembered$Amount
Oracle:Trample, haste\nWhenever Barbed Shocker deals damage to a player, that player discards all the cards in their hand, then draws that many cards.

View File

@@ -2,8 +2,8 @@ Name:Bartered Cow
ManaCost:3 W
Types:Creature Ox
PT:3/3
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | TriggerController$ TriggeredCardController | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies or blocks you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
T:Mode$ Discarded | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies or blocks you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | TriggerController$ TriggeredCardController | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies or when you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
T:Mode$ Discarded | ValidCard$ Card.Self | Execute$ TrigToken | Secondary$ True | TriggerController$ TriggeredCardController | TriggerDescription$ When CARDNAME dies or when you discard it, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.")
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_a_food_sac | TokenOwner$ You
SVar:SacMe:1
SVar:DiscardMe:3

View File

@@ -3,7 +3,7 @@ ManaCost:6 U
Types:Creature Elemental
PT:5/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create two 1/1 blue Merfolk Wizard creature tokens.
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ u_1_1_merfolk_wizard | TokenOwner$ You | SpellDescription$ Create two 1/1 blue Merfolk Wizard creature tokens.
SVar:TrigToken:DB$ Token | TokenAmount$ 2 | TokenScript$ u_1_1_merfolk_wizard | TokenOwner$ You
A:AB$ Untap | Cost$ tapXType<2/Merfolk> | SubAbility$ GainShroud | SpellDescription$ Untap CARDNAME.
SVar:GainShroud:DB$ Pump | Defined$ Self | KW$ Shroud | SpellDescription$ CARDNAME gains shroud until end of turn.
Oracle:When Benthicore enters the battlefield, create two 1/1 blue Merfolk Wizard creature tokens.\nTap two untapped Merfolk you control: Untap Benthicore. It gains shroud until end of turn. (It can't be the target of spells or abilities.)

View File

@@ -4,6 +4,6 @@ Types:Legendary Creature Cyclops
PT:7/6
K:Trample
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDig | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, reveal the top three cards of your library. Put all land cards revealed this way into your hand and the rest into your graveyard.
SVar:TrigDig:DB$ Dig | DigNum$ 3 | Defined$ You | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone2$ Graveyard | SpellDescription$ Reveal the top three cards of your library. Put all land cards revealed this way into your hand and the rest into your graveyard.
SVar:TrigDig:DB$ Dig | DigNum$ 3 | Defined$ You | Reveal$ True | ChangeNum$ All | ChangeValid$ Land | DestinationZone2$ Graveyard
A:AB$ DealDamage | Cost$ Discard<1/Land> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 3 | SpellDescription$ CARDNAME deals 3 damage to any target.
Oracle:Trample\nWhenever Borborygmos Enraged deals combat damage to a player, reveal the top three cards of your library. Put all land cards revealed this way into your hand and the rest into your graveyard.\nDiscard a land card: Borborygmos Enraged deals 3 damage to any target.

View File

@@ -4,7 +4,7 @@ Types:Creature Human Pirate
PT:2/2
K:Flash
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEffect | TriggerDescription$ When CARDNAME enters the battlefield, each token that would be created under an opponent's control this turn is created under your control instead.
SVar:TrigEffect:DB$ Effect | Name$ Crafty Cutpurse Effect | ReplacementEffects$ OppCreatEnters | SpellDescription$ Each token that would be created under an opponent's control this turn is created under your control instead.
SVar:TrigEffect:DB$ Effect | Name$ Crafty Cutpurse Effect | ReplacementEffects$ OppCreatEnters
SVar:OppCreatEnters:Event$ CreateToken | ActiveZones$ Command | ValidToken$ Card.OppCtrl | ReplaceWith$ ETBYourCtrl | Layer$ Control | Description$ Each token that would be created under an opponent's control this turn is created under your control instead.
SVar:ETBYourCtrl:DB$ ReplaceToken | Type$ ReplaceController | ValidCard$ Card.OppCtrl | NewController$ You
Oracle:Flash\nWhen Crafty Cutpurse enters the battlefield, each token that would be created under an opponent's control this turn is created under your control instead.

View File

@@ -4,5 +4,6 @@ Types:Creature Zombie Beast
PT:3/3
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Creature.Other | TriggerZones$ Battlefield | OptionalDecider$ You | Execute$ TrigPutCounter | TriggerDescription$ Whenever another creature dies, you may put a +1/+1 counter on CARDNAME.
SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1
A:AB$ DealDamage | Cost$ SubCounter<1/P1P1> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ CARDNAME deals 1 damage to any target.
A:AB$ DealDamage | Cost$ SubCounter<1/P1P1> | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 1 | SpellDescription$ It deals 1 damage to any target.
DeckHas:Ability$Counters
Oracle:Whenever another creature dies, you may put a +1/+1 counter on Deathbringer Thoctar.\nRemove a +1/+1 counter from Deathbringer Thoctar: It deals 1 damage to any target.

View File

@@ -2,6 +2,6 @@ Name:Debt of Loyalty
ManaCost:1 W W
Types:Instant
A:SP$ Regenerate | Cost$ 1 W W | ValidTgts$ Creature | TgtPrompt$ Select target creature | RegenerationTrigger$ TrigGainControl | SpellDescription$ Regenerate target creature. You gain control of that creature if it regenerates this way.
SVar:TrigGainControl:ST$ GainControl | Cost$ 0 | Defined$ TriggeredCard | NewController$ You | SpellDescription$ Source controller gains control of CARDNAME if it regenerates this way.
SVar:TrigGainControl:ST$ GainControl | Cost$ 0 | Defined$ TriggeredCard | NewController$ You
AI:RemoveDeck:All
Oracle:Regenerate target creature. You gain control of that creature if it regenerates this way.

View File

@@ -2,7 +2,7 @@ Name:Deserter's Quarters
ManaCost:2
Types:Artifact
K:You may choose not to untap CARDNAME during your untap step.
A:AB$ Tap | Cost$ 6 T | ValidTgts$ Creature | RememberTapped$ True | AlwaysRemember$ True | SpellDescription$ Tap target creature. It doesn't untap during its controller's untap step for as long as Deserter's Quarters remains tapped. | StackDescription$ SpellDescription
A:AB$ Tap | Cost$ 6 T | ValidTgts$ Creature | RememberTapped$ True | AlwaysRemember$ True | SpellDescription$ Tap target creature. It doesn't untap during its controller's untap step for as long as CARDNAME remains tapped. | StackDescription$ SpellDescription
S:Mode$ Continuous | Affected$ Card.IsRemembered | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step.
T:Mode$ Untaps | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ ClearRemembered | Static$ True
SVar:ClearRemembered:DB$ Cleanup | ClearRemembered$ True

View File

@@ -4,5 +4,5 @@ Types:Creature Dragon Warrior
PT:5/3
K:Trample
T:Mode$ DamageDone | ValidSource$ Card.YouCtrl,Emblem.YouCtrl | ValidTarget$ Player | TriggerZones$ Battlefield | DamageAmount$ GE5 | Execute$ TrigDraw | TriggerDescription$ Whenever a source you control deals 5 or more damage to a player, draw a card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1 | SpellDescription$ Draw a card.
SVar:TrigDraw:DB$ Draw | NumCards$ 1
Oracle:Trample\nWhenever a source you control deals 5 or more damage to a player, draw a card.

View File

@@ -3,7 +3,7 @@ ManaCost:4 G G
Types:Legendary Creature Treefolk Wizard
PT:6/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a number of 1/1 blue Human Wizard creature tokens equal to the number of differently named lands you control.
SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ u_1_1_human_wizard | SpellDescription$ Create a number of 1/1 blue Human Wizard creature tokens equal to the number of differently named lands you control.
SVar:TrigToken:DB$ Token | TokenAmount$ X | TokenScript$ u_1_1_human_wizard
SVar:X:Count$DifferentCardNames_Land.YouCtrl+inZoneBattlefield
A:AB$ Draw | Cost$ 4 G U | NumCards$ Y | SubAbility$ PumpAll | SpellDescription$ Draw a card for each Wizard you control. They each get +1/+1 until end of turn for each card in your hand.
SVar:Y:Count$Valid Wizard.YouCtrl

View File

@@ -1,7 +1,7 @@
Name:Gate to the Aether
ManaCost:6
Types:Artifact
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigAetherDig | TriggerController$ TriggeredPlayer | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player reveals the top card of their library. If it's an artifact, creature, enchantment, or land card, the player may put it onto the battlefield.
SVar:TrigAetherDig:DB$ Dig | Defined$ TriggeredPlayer | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Artifact,Creature,Enchantment,Land
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigAetherDig | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player reveals the top card of their library. If it's an artifact, creature, enchantment, or land card, the player may put it onto the battlefield.
SVar:TrigAetherDig:DB$ Dig | Defined$ TriggeredPlayer | Choser$ TriggeredPlayer | DigNum$ 1 | Reveal$ True | DestinationZone$ Battlefield | DestinationZone2$ Library | LibraryPosition2$ 0 | ChangeNum$ 1 | Optional$ True | ChangeValid$ Artifact,Creature,Enchantment,Land
AI:RemoveDeck:Random
Oracle:At the beginning of each player's upkeep, that player reveals the top card of their library. If it's an artifact, creature, enchantment, or land card, the player may put it onto the battlefield.

View File

@@ -2,7 +2,7 @@ Name:Genesis Chamber
ManaCost:2
Types:Artifact
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken | TriggerZones$ Battlefield | Execute$ TrigToken | IsPresent$ Card.Self+untapped | TriggerDescription$ Whenever a nontoken creature enters the battlefield, if CARDNAME is untapped, that creature's controller creates a 1/1 colorless Myr artifact creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ TriggeredCardController | TokenScript$ c_1_1_a_myr | SpellDescription$ Create a 1/1 Myr artifact creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ TriggeredCardController | TokenScript$ c_1_1_a_myr
AI:RemoveDeck:Random
DeckHas:Ability$Token
Oracle:Whenever a nontoken creature enters the battlefield, if Genesis Chamber is untapped, that creature's controller creates a 1/1 colorless Myr artifact creature token.

View File

@@ -4,6 +4,6 @@ Types:Creature Shapeshifter
PT:2/2
K:Changeling
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a colorless Shapeshifter creature token with changeling.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_2_2_shapeshifter_changeling | TokenOwner$ You | SpellDescription$ Create a 2/2 colorless Shapeshifter creature token with changeling. (It has every creature type.)
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ c_2_2_shapeshifter_changeling | TokenOwner$ You
DeckHas:Ability$Token
Oracle:Changeling (This card is every creature type.)\nWhen Irregular Cohort enters the battlefield, create a 2/2 colorless Shapeshifter creature token with changeling.

View File

@@ -3,7 +3,7 @@ ManaCost:1 G
Types:Legendary Creature Human Druid
PT:1/2
T:Mode$ Drawn | ValidCard$ Card.YouCtrl | Number$ 2 | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ Whenever you draw your second card each turn, create a 2/2 green Cat creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ g_2_2_cat | SpellDescription$ Create a 2/2 green Cat creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenOwner$ You | TokenScript$ g_2_2_cat
DeckHas:Ability$Token
A:AB$ AnimateAll | Cost$ 4 G G | ValidCards$ Creature.YouCtrl | Power$ X | Toughness$ X | SpellDescription$ Until end of turn, creatures you control have base power and toughness X/X, where X is the number of cards in your hand.
SVar:X:Count$InYourHand

View File

@@ -5,6 +5,6 @@ PT:4/5
K:Kicker:5 B
K:Menace
T:Mode$ ChangesZone | ValidCard$ Card.Self+kicked | Origin$ Any | Destination$ Battlefield | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace.
SVar:TrigToken:DB$ Token | TokenAmount$ 8 | TokenScript$ b_2_2_zombie_knight_menace | TokenOwner$ You | SpellDescription$ When CARDNAME enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace.
SVar:TrigToken:DB$ Token | TokenAmount$ 8 | TokenScript$ b_2_2_zombie_knight_menace | TokenOwner$ You
DeckHas:Ability$Token
Oracle:Kicker {5}{B} (You may pay an additional {5}{B} as you cast this spell.)\nMenace\nWhen Josu Vess, Lich Knight enters the battlefield, if it was kicked, create eight 2/2 black Zombie Knight creature tokens with menace.

View File

@@ -5,6 +5,6 @@ PT:3/4
K:Flying
K:Lifelink
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn.
SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenAmount$ X | TokenScript$ w_2_2_knight_vigilance | SpellDescription$ Create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn.
SVar:TrigToken:DB$ Token | TokenOwner$ You | TokenAmount$ X | TokenScript$ w_2_2_knight_vigilance
SVar:X:TriggeredCardController$OpponentsAttackedThisTurn
Oracle:Flying, lifelink\nWhen Militant Angel enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn.

View File

@@ -6,9 +6,8 @@ T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.S
SVar:TrigDrain:DB$ LoseLife | ValidTgts$ Opponent | LifeAmount$ 2 | SubAbility$ DBGainLife
SVar:DBGainLife:DB$ GainLife | Defined$ You | LifeAmount$ 2
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigExile | OptionalDecider$ You | TriggerDescription$ At the beginning of your end step you may exile NICKNAME. If you do, return it to the battlefield under it's owner's control at the beginning of your next upkeep. It gains haste.
SVar:TrigExile:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile | SubAbility$ DBDelaytrig
SVar:DBDelaytrig:DB$ Effect | Name$ Obzedat Effect | Triggers$ TrigEOT | RememberObjects$ Self | Duration$ Permanent
SVar:TrigEOT:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ ObzedatReturn | OneOff$ True | TriggerDescription$ Return CARDNAME to the battlefield under it's owner's control. It gains haste.
SVar:ObzedatReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ Exile | Destination$ Battlefield | SubAbility$ ObzedatPump
SVar:TrigExile:DB$ ChangeZone | Defined$ Self | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | SubAbility$ DelTrig
SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ ObzedatReturn | ConditionDefined$ Remembered | ConditionPresent$ Card | RememberObjects$ Remembered | TriggerDescription$ Return CARDNAME to the battlefield under its owner's control at the beginning of the next end step.
SVar:ObzedatReturn:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Exile,Command | Destination$ Battlefield | SubAbility$ ObzedatPump
SVar:ObzedatPump:DB$ Pump | Defined$ Remembered | KW$ Haste | Duration$ Permanent
Oracle:When Obzedat, Ghost Council enters the battlefield, target opponent loses 2 life and you gain 2 life.\nAt the beginning of your end step, you may exile Obzedat. If you do, return it to the battlefield under its owner's control at the beginning of your next upkeep. It gains haste.

View File

@@ -3,7 +3,7 @@ ManaCost:1 U U
Types:Creature Djinn
PT:2/3
K:You may choose not to untap CARDNAME during your untap step.
A:AB$ GainControl | Cost$ T | ValidTgts$ Creature.powerLEX | TgtPrompt$ Select target creature with power less than or equal to Old Man's. | LoseControl$ Untap,LeavesPlay,LoseControl,StaticCommandCheck | StaticCommandCheckSVar$ Y | StaticCommandSVarCompare$ GTX | SpellDescription$ Gain control of target creature with power less than or equal to Old Man of the Sea's power for as long as Old Man of the Sea remains tapped and that creature's power remains less than or equal to Old Man of the Sea's power.
A:AB$ GainControl | Cost$ T | ValidTgts$ Creature.powerLEX | TgtPrompt$ Select target creature with power less than or equal to Old Man's. | LoseControl$ Untap,LeavesPlay,LoseControl,StaticCommandCheck | StaticCommandCheckSVar$ Y | StaticCommandSVarCompare$ GTX | SpellDescription$ Gain control of target creature with power less than or equal to CARDNAME's power for as long as CARDNAME remains tapped and that creature's power remains less than or equal to CARDNAME's power.
SVar:X:Count$CardPower
# the hostcard of SVar Y is the controlled card
SVar:Y:Count$CardPower

View File

@@ -2,7 +2,7 @@ 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 among cards in your graveyard, choose both instead.
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ Delirium — When CARDNAME enters the battlefield, ABILITY
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 of them into your hand and the rest on the bottom of your library in a random order.

View File

@@ -2,7 +2,7 @@ Name:Pure Reflection
ManaCost:2 W
Types:Enchantment
T:Mode$ SpellCast | ValidCard$ Creature | Execute$ TrigDestroy | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | TriggerDescription$ Whenever a player casts a creature spell, destroy all Reflections. Then that player creates an X/X white Reflection creature token, where X is the mana value of that spell.
SVar:TrigDestroy:DB$ DestroyAll | ValidCards$ Reflection | SubAbility$ DBToken | SpellDescription$ Destroy all Reflections
SVar:TrigDestroy:DB$ DestroyAll | ValidCards$ Reflection | SubAbility$ DBToken
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenPower$ X | TokenToughness$ X | TokenScript$ w_x_x_reflection | TokenOwner$ TriggeredActivator
SVar:X:TriggeredStackInstance$CardManaCostLKI
Oracle:Whenever a player casts a creature spell, destroy all Reflections. Then that player creates an X/X white Reflection creature token, where X is the mana value of that spell.

View File

@@ -5,7 +5,7 @@ PT:4/4
K:Partner:Krav, the Unredeemed:Krav
K:Flying
T:Mode$ Phase | Phase$ End of Turn | TriggerZones$ Battlefield | CheckSVar$ YouTeamLifeGained | SVarCompare$ GE1 | Execute$ TrigWarrior | TriggerDescription$ At the beginning of each end step, if your team gained life this turn, create two 1/1 white Warrior creature tokens.
SVar:TrigWarrior:DB$ Token | TokenAmount$ 2 | TokenScript$ w_1_1_warrior | TokenOwner$ You | SpellDescription$ Create two 1/1 white Warrior creature tokens.
SVar:TrigWarrior:DB$ Token | TokenAmount$ 2 | TokenScript$ w_1_1_warrior | TokenOwner$ You
SVar:YouTeamLifeGained:Count$LifeYourTeamGainedThisTurn
DeckHints:Name$Krav, the Unredeemed
Oracle:Partner with Krav, the Unredeemed (When this creature enters the battlefield, target player may put Krav into their hand from their library, then shuffle.)\nFlying\nAt the beginning of each end step, if your team gained life this turn, create two 1/1 white Warrior creature tokens.

View File

@@ -3,5 +3,5 @@ ManaCost:no cost
Types:Vanguard
HandLifeModifier:+1/+1
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigDmgOpp | TriggerDescription$ At the beginning of your upkeep, CARDNAME deals 1 damage to each opponent.
SVar:TrigDmgOpp:DB$ DealDamage | Defined$ Player.Opponent | NumDmg$ 1
SVar:TrigDmgOpp:DB$ DealDamage | Defined$ Opponent | NumDmg$ 1
Oracle:Hand +1, life +1\nAt the beginning of your upkeep, Rumbling Slum Avatar deals 1 damage to each opponent.

View File

@@ -5,7 +5,7 @@ PT:1/1
K:Morph:3 G G
S:Mode$ Continuous | Affected$ Creature.Saproling | AddPower$ 1 | AddToughness$ 1 | IsPresent$ Card.Self+faceUp | Description$ All Saprolings get +1/+1.
T:Mode$ TurnFaceUp | ValidCard$ Card.Self | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ When CARDNAME is turned face up, create four 1/1 green Saproling creature tokens.
SVar:TrigToken:DB$ Token | TokenAmount$ 4 | TokenScript$ g_1_1_saproling | TokenOwner$ You | SpellDescription$ Create four 1/1 green Saproling creature tokens.
SVar:TrigToken:DB$ Token | TokenAmount$ 4 | TokenScript$ g_1_1_saproling | TokenOwner$ You
SVar:PlayMain1:TRUE
DeckHints:Type$Fungus
DeckHas:Ability$Token

View File

@@ -0,0 +1,9 @@
Name:Conductor of Cacophony
ManaCost:3 B
Types:Creature Demon
PT:2/1
K:etbCounter:P1P1:2
A:AB$ DamageAll | Cost$ B SubCounter<1/P1P1> | ValidCards$ Creature.Other | ValidPlayers$ Player | NumDmg$ 1 | ValidDescription$ each other creature and each player. | SpellDescription$ It deals 1 damage to each other creature and each player.
DeckHas:Ability$Counters
DeckHints:Ability$Counters
Oracle:Conductor of Cacophony enters the battlefield with two +1/+1 counters on it.\n{B}, Remove a +1/+1 counter from Conductor of Cacophony: It deals 1 damage to each other creature and each player.

View File

@@ -0,0 +1,12 @@
Name:Distinguished Conjurer
ManaCost:1 W
Types:Creature Human Wizard
PT:1/2
T:Mode$ ChangesZone | ValidCard$ Creature.Other+YouCtrl | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigGainLife | TriggerDescription$ Whenever another creature enters the battlefield under your control, you gain 1 life.
SVar:TrigGainLife:DB$ GainLife | LifeAmount$ 1
A:AB$ ChangeZone | Cost$ 4 W T | ValidTgts$ Creature.Other+YouCtrl | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select another target creature you control | RememberChanged$ True | SubAbility$ DBReturn | SpellDescription$ Exile another target creature you control, then return it to the battlefield under its owner's control.
SVar:DBReturn:DB$ ChangeZone | Defined$ Remembered | Origin$ All | Destination$ Battlefield | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
DeckHas:Ability$LifeGain
SVar:BuffedBy:Creature
Oracle:Whenever another creature enters the battlefield under your control, you gain 1 life.\n{4}{W}, {T}: Exile another target creature you control, then return it to the battlefield under its owner's control.

View File

@@ -0,0 +1,10 @@
Name:Dutiful Replicator
ManaCost:3
Types:Artifact Creature Assembly-Worker
PT:3/2
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | TriggerZones$ Battlefield | Execute$ TrigImmediate | TriggerDescription$ When CARDNAME enters the battlefield, you may pay {1}. When you do, create a token that's a copy of target token you control not named Dutiful Replicator.
SVar:TrigImmediate:AB$ ImmediateTrigger | Cost$ 1 | Execute$ TrigClone | TriggerDescription$ When you do, create a token that's a copy of target token you control not named Dutiful Replicator.
SVar:TrigClone:DB$ CopyPermanent | ValidTgts$ Permanent.token+YouCtrl+notnamedDutiful Replicator | TgtPrompt$ Select target token you control not named Dutiful Replicator
DeckHas:Ability$Token
DeckNeeds:Ability$Token
Oracle:When Dutiful Replicator enters the battlefield, you may pay {1}. When you do, create a token that's a copy of target token you control not named Dutiful Replicator.

View File

@@ -0,0 +1,11 @@
Name:Hold for Questioning
ManaCost:3 U
Types:Enchantment Aura
K:Enchant creature or planeswalker
A:SP$ Attach | ValidTgts$ Creature,Planeswalker | TgtPrompt$ Select target creature or planeswalker | AILogic$ Curse
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Any | Destination$ Battlefield | Execute$ TrigTap | TriggerDescription$ When CARDNAME enters the battlefield, tap enchanted permanent and investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.")
SVar:TrigTap:DB$ Tap | Defined$ Enchanted | SubAbility$ DBInvestigate
SVar:DBInvestigate:DB$ Investigate
S:Mode$ Continuous | Affected$ Permanent.EnchantedBy | AddHiddenKeyword$ CARDNAME doesn't untap during your untap step. & CARDNAME's activated abilities can't be activated. | Description$ Enchanted permanent doesn't untap during its controller's untap step and its activated abilities can't be activated.
DeckHas:Ability$Investigate|Token|Sacrifice & Type$Artifact|Clue
Oracle:Enchant creature or planeswalker\nWhen Hold for Questioning enters the battlefield, tap enchanted permanent and investigate. (Create a Clue token. It's an artifact with "{2}, Sacrifice this artifact: Draw a card.")\nEnchanted permanent doesn't untap during its controller's untap step and its activated abilities can't be activated.

View File

@@ -0,0 +1,8 @@
Name:Infernal Idol
ManaCost:3
Types:Artifact
A:AB$ Mana | Cost$ T | Produced$ B | SpellDescription$ Add {B}.
A:AB$ Draw | Cost$ 1 B B T Sac<1/CARDNAME> | NumCards$ 2 | SubAbility$ DBLoseLife | SpellDescription$ You draw two cards and you lose two life.
SVar:DBLoseLife:DB$ LoseLife | LifeAmount$ 2
DeckNeeds:Color$Black
Oracle:{T}: Add {B}.\n{1}{B}{B}, {T}, Sacrifice Infernal Idol: You draw two cards and you lose two life.

View File

@@ -0,0 +1,8 @@
Name:Ingenious Leonin
ManaCost:4 W
Types:Creature Cat Soldier
PT:4/4
A:AB$ PutCounter | Cost$ 3 W | ValidTgts$ Creature.attacking+Other+YouCtrl | TgtPrompt$ Select another target attacking creature you control | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBPump | SpellDescription$ Put a +1/+1 counter on another target attacking creature you control. If that creature is a Cat, it gains first strike until end of turn.
SVar:DBPump:DB$ Pump | Defined$ Targeted | ConditionDefined$ Targeted | ConditionPresent$ Cat | KW$ First Strike | StackDesc$ If that creature is a Cat, it gains first strike until end of turn
DeckHints:Type$Cat
Oracle:{3}{W}: Put a +1/+1 counter on another target attacking creature you control. If that creature is a Cat, it gains first strike until end of turn.

View File

@@ -0,0 +1,11 @@
Name:Lita, Mechanical Engineer
ManaCost:2 W
Types:Legendary Artifact Creature Artificer
PT:3/3
K:Vigilance
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigUntap | TriggerDescription$ At the beginning of your end step, untap all artifact creatures you control.
SVar:TrigUntap:DB$ UntapAll | ValidCards$ Artifact.Creature+YouCtrl
A:AB$ Token | Cost$ 3 W T | TokenScript$ zeppelin | SpellDescription$ Create a 5/5 colorless Vehicle artifact token named Zeppelin with flying and crew 3.
DeckHas:Type$Vehicle & Ability$Token & Keyword$Flying
DeckHints:Type$Artifact
Oracle:Vigilance\nAt the beginning of your end step, untap all artifact creatures you control.\n{3}{W}, {T}: Create a 5/5 colorless Vehicle artifact token named Zeppelin with flying and crew 3.

View File

@@ -0,0 +1,10 @@
Name:Magnanimous Magistrate
ManaCost:5 W
Types:Creature Human Advisor
PT:3/4
K:etbCounter:REPR:5
T:Mode$ ChangesZone | ValidCard$ Creature.Other+nonToken+cmcGE1 | Origin$ Battlefield | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ Whenever another nontoken creature you control dies, if its mana value was 1 or greater, you may remove that many reprieve counters from CARDNAME. If you do, return that card to the battlefield under its owner's control.
SVar:TrigChangeZone:AB$ ChangeZone | Cost$ SubCounter<X/REPR> | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Battlefield
SVar:X:TriggeredCard$CardManaCost
DeckHas:Ability$Counters
Oracle:Magnanimous Magistrate enters the battlefield with five reprieve counters on it.\nWhenever another nontoken creature you control dies, if its mana value was 1 or greater, you may remove that many reprieve counters from Magnanimous Magistrate. If you do, return that card to the battlefield under its owner's control.

View File

@@ -0,0 +1,9 @@
Name:Mild-Mannered Librarian
ManaCost:G
Types:Creature Human
PT:1/1
A:AB$ Animate | Cost$ 3 G | GameActivationLimit$ 1 | Types$ Werewolf | RemoveCreatureTypes$ True | Duration$ Permanent | SubAbility$ DBCounter | SpellDescription$ CARDNAME becomes a Werewolf. Put two +1/+1 counters on it and you draw a card. Activate only once.
SVar:DBCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBDraw
SVar:DBDraw:DB$ Draw
DeckHas:Ability$Counters & Type$Werewolf
Oracle:{3}{G}: Mild-Mannered Librarian becomes a Werewolf. Put two +1/+1 counters on it and you draw a card. Activate only once.

View File

@@ -0,0 +1,9 @@
Name:Pirated Copy
ManaCost:4 U
Types:Creature Shapeshifter Pirate
PT:0/0
K:ETBReplacement:Copy:DBCopy:Optional
SVar:DBCopy:DB$ Clone | Choices$ Creature.Other | AddTypes$ Pirate | AddTriggers$ DrawTrig | SpellDescription$ You may have CARDNAME enter the battlefield as a copy of any creature on the battlefield, except it's a Pirate in addition to its other types and it has "Whenever this creature or another creature with the same name deals combat damage to a player, you draw a card."
SVar:DrawTrig:Mode$ DamageDone | ValidSource$ Card.Self,Creature.sameName | TriggerZones$ Battlefield | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigDraw | TriggerZones$ Battlefield | TriggerDescription$ Whenever this creature or another creature with the same name deals combat damage to a player, you draw a card.
SVar:TrigDraw:DB$ Draw
Oracle:You may have Pirated Copy enter the battlefield as a copy of any creature on the battlefield, except it's a Pirate in addition to its other types and it has "Whenever this creature or another creature with the same name deals combat damage to a player, you draw a card."

View File

@@ -0,0 +1,10 @@
Name:Preston, the Vanisher
ManaCost:3 W
Types:Legendary Creature Rabbit Wizard
PT:2/5
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Creature.nonToken+wasNotCast+YouCtrl | TriggerZones$ Battlefield | Execute$ TrigCopyPermanent | TriggerDescription$ Whenever another nontoken creature enters the battlefield under your control, if it wasn't cast, create a token that's a copy of that creature except it's a 0/1 white Illusion.
SVar:TrigCopyPermanent:DB$ CopyPermanent | Defined$ TriggeredCard | NumCopies$ 1 | SetColor$ White | SetCreatureTypes$ Illusion | SetPower$ 0 | SetToughness$ 1
A:AB$ ChangeZone | Cost$ 1 W Sac<5/Illusion> | ValidTgts$ Permanent.nonLand | Origin$ Battlefield | Destination$ Exile | TgtPrompt$ Select target nonland permanent | SpellDescription$ Exile target nonland permanent.
DeckHas:Ability$Token|Sacrifice & Type$Illusion
DeckHints:Type$Illusion & Ability$Graveyard
Oracle:Whenever another nontoken creature enters the battlefield under your control, if it wasn't cast, create a token that's a copy of that creature except it's a 0/1 white Illusion.\n{1}{W}, Sacrifice five Illusions: Exile target nonland permanent.

View File

@@ -0,0 +1,10 @@
Name:Primeval Herald
ManaCost:3 G
Types:Creature Elf Scout
PT:3/1
K:Trample
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChange | OptionalDecider$ You | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle.
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigChange | TriggerZones$ Battlefield | OptionalDecider$ You | Secondary$ True | TriggerDescription$ Whenever CARDNAME enters the battlefield or attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle.
SVar:TrigChange:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | Tapped$ True | ChangeType$ Land.Basic | ChangeNum$ 1 | ShuffleNonMandatory$ True
SVar:HasAttackEffect:TRUE
Oracle:Trample\nWhenever Primeval Herald enters the battlefield or attacks, you may search your library for a basic land card, put it onto the battlefield tapped, then shuffle.

View File

@@ -0,0 +1,7 @@
Name:Read the Soul
ManaCost:3 U
Types:Instant
A:SP$ Charm | Choices$ Counter,Draw | CharmNum$ 1
SVar:Counter:DB$ Counter | TargetType$ Spell | TgtPrompt$ Select target spell | ValidTgts$ Card | UnlessCost$ 4 | SpellDescription$ Counter target spell unless its controller pays {4}.
SVar:Draw:DB$ Draw | NumCards$ 2 | SpellDescription$ Draw two cards.
Oracle:Choose one —\n• Counter target spell unless its controller pays {4}.\n• Draw two cards.

View File

@@ -0,0 +1,16 @@
Name:Rodolf Duskbringer
ManaCost:5 B
Types:Legendary Creature Vampire Angel
PT:4/4
K:Flying
K:Deathtouch
K:Lifelink
T:Mode$ LifeGained | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPump | TriggerDescription$ Whenever you gain life, CARDNAME gains indestructible until end of turn.
SVar:TrigPump:DB$ Pump | Defined$ Self | KW$ Indestructible
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Battlefield | CheckSVar$ X | Execute$ TrigImmediateTrig | TriggerDescription$ At the beginning of your end step, you may pay {1}{W/B}. When you do, return target creature with mana value X or less from your graveyard to the battlefield, where X is the amount of life you gained this turn.
SVar:TrigImmediateTrig:AB$ ImmediateTrigger | Cost$ 1 WB | Execute$ TrigChangeZone | TriggerDescription$ When you do, return target creature with mana value X or less from your graveyard to the battlefield, where X is the amount of life you gained this turn.
SVar:TrigChangeZone:DB$ ChangeZone | ValidTgts$ Creature.cmcLEX+YouOwn | TgtPrompt$ Select target creature card with mana value X or less | Origin$ Graveyard | Destination$ Battlefield
SVar:X:Count$LifeYouGainedThisTurn
DeckHas:Ability$Graveyard|LifeGain & Keyword$indestructible
DeckHints:Ability$Graveyard|LifeGain|Mill
Oracle:Flying, deathtouch, lifelink\nWhenever you gain life, Rodolf Duskbringer gains indestructible until end of turn.\nAt the beginning of your end step, you may pay {1}{W/B}. When you do, return target creature with mana value X or less from your graveyard to the battlefield, where X is the amount of life you gained this turn.

View File

@@ -0,0 +1,14 @@
Name:Runadi, Behemoth Caller
ManaCost:2 G
Types:Legendary Creature Cat Shaman
PT:1/3
T:Mode$ SpellCast | ValidCard$ Creature.cmcGE5 | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ Whenever you cast a creature spell with mana value 5 or greater, that creature enters the battlefield with X additional +1/+1 counters on it, where X is its mana value minus 4.
SVar:TrigEffect:DB$ Effect | RememberObjects$ TriggeredCard | ReplacementEffects$ ETBCreat | ExileOnMoved$ Stack
SVar:ETBCreat:Event$ Moved | ValidCard$ Card.IsRemembered | Destination$ Battlefield | ReplaceWith$ DBPutP1P1 | ReplacementResult$ Updated
SVar:DBPutP1P1:DB$ PutCounter | Defined$ ReplacedCard | CounterType$ P1P1 | ETB$ True | CounterNum$ X
S:Mode$ Continuous | Affected$ Creature.YouCtrl+counters_GE3_P1P1 | AddKeyword$ Haste | Description$ Creatures you control with three or more +1/+1 counters on them have haste.
A:AB$ Mana | Cost$ T | Produced$ G | SpellDescription$ Add {G}.
SVar:X:Remembered$CardManaCost/Minus.4
DeckHas:Ability$Counters
DeckHints:Type$Tyranid|Hydra
Oracle:Whenever you cast a creature spell with mana value 5 or greater, that creature enters the battlefield with X additional +1/+1 counters on it, where X is its mana value minus 4.\nCreatures you control with three or more +1/+1 counters on them have haste.\n{T}: Add {G}.

View File

@@ -0,0 +1,8 @@
Name:Towering Gibbon
ManaCost:3 G
Types:Creature Ape
PT:*/4
K:Reach
S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | Description$ CARDNAME's power is equal to the highest mana value among creatures you control.
SVar:X:Count$Valid Creature.YouCtrl$GreatestCMC
Oracle:Reach\nTowering Gibbon's power is equal to the greatest mana value among creatures you control.

View File

@@ -0,0 +1,12 @@
Name:Zask, Skittering Swarmlord
ManaCost:3 G G
Types:Legendary Creature Insect
PT:5/5
S:Mode$ Continuous | Affected$ Land.YouOwn,Insect.YouOwn | MayPlay$ True | AffectedZone$ Graveyard | Description$ You may play lands and cast Insect spells from your graveyard.o
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Insect.YouCtrl+Other | Execute$ TrigChange | TriggerDescription$ Whenever another Insect you control dies, put it on the bottom of its owner's library, then mill two cards. (Put the top two cards of your library into your graveyard.)
SVar:TrigChange:DB$ ChangeZone | Defined$ TriggeredNewCardLKICopy | Origin$ Graveyard | Destination$ Library | LibraryPosition$ -1 | SubAbility$ DBMill
SVar:DBMill:DB$ Mill | NumCards$ 2
A:AB$ Pump | Cost$ 1 BG | ValidTgts$ Insect | NumAtt$ 1 | KW$ Deathtouch | SpellDescription$ Target Insect gets +1/+0 and gains deathtouch until end of turn.
DeckHas:Ability$Mill|Graveyard & Keyword$Deathtouch
DeckNeeds:Type$Insect
Oracle:You may play lands and cast Insect spells from your graveyard.\nWhenever another Insect you control dies, put it on the bottom of its owner's library, then mill two cards. (Put the top two cards of your library into your graveyard.)\n{1}{B/G}: Target Insect gets +1/+0 and gains deathtouch until end of turn.

View File

@@ -3,7 +3,7 @@ ManaCost:5 W
Types:Creature Giant Soldier
PT:3/6
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME enters the battlefield, create a 1/1 white Human creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenOwner$ You | SpellDescription$ Create a 1/1 white Human creature token.
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenOwner$ You
DeckHints:Type$Human
DeckHas:Ability$Token
Oracle:When Watchful Giant enters the battlefield, create a 1/1 white Human creature token.

View File

@@ -4,7 +4,7 @@ Types:Enchantment
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ Player | Execute$ TrigEvoke | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of each player's upkeep, that player reveals a card at random from their hand. If it's a land card, the player puts it onto the battlefield. Otherwise, the player casts it without paying its mana cost if able.
SVar:TrigEvoke:DB$ Reveal | Random$ True | RememberRevealed$ True | Defined$ TriggeredPlayer | SubAbility$ DBEvokeLand
SVar:DBEvokeLand:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ ValidHand Land.IsRemembered | ForgetChanged$ True | SubAbility$ DBEvokePlay
SVar:DBEvokePlay:DB$ Play | ValidZone$ Hand | Controller$ TriggeredPlayer | Defined$ Remembered | WithoutManaCost$ True | SubAbility$ DBCleanup
SVar:DBEvokePlay:DB$ Play | ValidZone$ Hand | Controller$ TriggeredPlayer | Defined$ Remembered | ValidSA$ Spell | WithoutManaCost$ True | SubAbility$ DBCleanup
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
AI:RemoveDeck:Random
Oracle:At the beginning of each player's upkeep, that player reveals a card at random from their hand. If it's a land card, the player puts it onto the battlefield. Otherwise, the player casts it without paying its mana cost if able.

View File

@@ -6,8 +6,75 @@ Type=Draft
ScryfallCode=J22
[cards]
4 U Distinguished Conjurer @Nils Hamm
5 U Ingenious Leonin @Eric Deschamps
6 M Lita, Mechanical Engineer @Bartek Fedyczak
7 U Magnanimous Magistrate @Marie Magny
8 R Preston, the Vanisher @Christina Kraus
11 U Hold for Questioning @Samuel Perin
12 M Isu the Abominable @Victor Adame Minguez
15 C Merfolk Pupil @Caroline Gariba
16 M Pirated Copy @Daarken
19 M Ashcoat of the Shadow Swarm @Christina Kraus
20 U Conductor of Cacophony @Jason A. Engle
21 C Creeping Bloodsucker @Antonio José Manzanedo
23 U Disciple of Perdition @Alix Branwyn
25 R Rodolf Duskbringer @Billy Christian
28 R Termination Facilitator @Justine Cruz
29 R Ardoz, Cobbler of War @Kev Walker
40 M Kibo, Uktabi Prince @Zoltan Boros
41 U Mild-Mannered Librarian @Justyna Gil
42 U Primeval Herald @Tatiana Kirgetova
44 R Runadi, Behemoth Caller @Billy Christian
45 C Spectral Hunt-Caller @Uriah Voth
46 U Towering Gibbon @Chris Seaman
48 C Dutiful Replicator @Alexander Forssberg
49 C Infernal Idol @Drew Tucker
50 U Instruments of War @Drew Tucker
51 U Planar Atlas @Alexander Forssberg
52 U Arrest @Katana Canata
53 R Balan, Wandering Knight @Mai Okuma
56 C Flicker of Fate
57 U King of the Pride @Inuchiyo Meimaru
62 U Mirror Image @Yukie Tajima
64 U Spectral Sailor @Fuzichoco
65 C Spellstutter Sprite
66 U Whirler Rogue @I☆LA
67 C Diabolic Edict @Tetsu Kurosawa
68 U Feast on the Fallen
70 U Oathsworn Vampire @Border
71 R Ogre Slumlord
79 M Kiki-Jiki, Mirror Breaker @Ishikawa Kenta
85 U Arlinn, Voice of the Pack @Hisashi Momose
88 C Elvish Rejuvenator @Shiramine
92 U Thrashing Brontodon @Kemonomichi
94 U Coldsteel Heart @I☆LA
95 U Magnifying Glass @Yukihiro Maruo
96 R Peacewalker Colossus @Hisashi Momose
97 M Karn Liberated @Dai-XT
117 U Blood Artist @Julie Dillon
118 U Feast of Blood @Irina Nordsol
119 U Festering Evil @Samuel Araya
126 C Renegade Demon @Alexandre Honoré
133 U Uktabi Orangutan @Milivoj Ćeran
134 R Wicked Wolf @Steve Ellis
141 M Ajani, Strength of the Pride @Chris Rallis
142 U Ajani's Pridemate @Svetlin Velinov
184 R Felidar Retreat @Ralph Horsley
208 R Leonin Warleader @Jakub Kasper
232 R Regal Caracal @Filip Burburan
259 R Trove Warden @Lars Grant-West
323 U Nezumi Bone-Reader @Leonardo Santanna
384 C Burglar Rat @Tyler Walpole
387 C Chittering Rats @Yeong-Hao Han
392 U Crypt Rats @Matt Cavotta
397 R Demon of Catastrophes @Sidharth Chaturvedi
403 R Dread Presence @Anthony Palumbo
412 C Eviscerate @Min Yum
431 R Kothophed, Soul Hoarder @Jakub Kasper
463 R Seizan, Perverter of Truth @Kev Walker
465 C Sinuous Vermin @Jason Kang
468 C Typhoid Rats @Kev Walker
481 U Ulcerate @Johann Bodin
806 R Walking Ballista @Daniel Ljunggren
835 M Kibo, Uktabi Prince @Filipe Pagliuso

View File

@@ -36,3 +36,4 @@ ScryfallCode=SLC
2020 R Shark Typhoon @Edgar Sánchez Hidalgo
2021 R Elite Spellbinder @Alexis Ziritt
2022 M Nashi, Moon Sage's Scion @Death Burger
2023 M Lotus Field @ZIUK

View File

@@ -0,0 +1,7 @@
Name:Zeppelin
ManaCost:no cost
Types:Artifact Creature
PT:5/5
K:Flying
K:Crew:3
Oracle:Flying\nCrew 3.

View File

@@ -64,8 +64,8 @@ public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyn
@Override
public final void showMessage() {
if ( FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT) &&
(card!=null) ) {
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_DETAILED_SPELLDESC_IN_PROMPT) &&
card != null) {
final StringBuilder sb = new StringBuilder();
sb.append(card.toString());
if ( (sa != null) && (!sa.toString().isEmpty()) ) { // some spell abilities have no useful string value

View File

@@ -743,13 +743,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
switch (sa.getParam("ShowCardInPrompt")) {
case "FirstRemembered":
o = sa.getHostCard().getFirstRemembered();
if (o != null && o instanceof Card) {
if (o instanceof Card) {
show = (Card)o;
}
break;
case "LastRemembered":
o = sa.getHostCard().getFirstRemembered();
if (o != null && o instanceof Card) {
if (o instanceof Card) {
show = (Card)o;
}
break;