mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-15 02:08:00 +00:00
Merge branch 'Card-Forge:master' into adventureupdatee
This commit is contained in:
@@ -163,6 +163,7 @@ public enum SpellApiToAi {
|
||||
.put(ApiType.Sacrifice, SacrificeAi.class)
|
||||
.put(ApiType.SacrificeAll, SacrificeAllAi.class)
|
||||
.put(ApiType.Scry, ScryAi.class)
|
||||
.put(ApiType.Seek, AlwaysPlayAi.class)
|
||||
.put(ApiType.SetInMotion, AlwaysPlayAi.class)
|
||||
.put(ApiType.SetLife, LifeSetAi.class)
|
||||
.put(ApiType.SetState, SetStateAi.class)
|
||||
|
||||
@@ -26,7 +26,7 @@ public class CharmAi extends SpellAbilityAi {
|
||||
@Override
|
||||
protected boolean checkApiLogic(Player ai, SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa);
|
||||
List<AbilitySub> choices = CharmEffect.makePossibleOptions(sa, false);
|
||||
|
||||
final int num;
|
||||
final int min;
|
||||
|
||||
@@ -380,6 +380,8 @@ public final class GameActionUtil {
|
||||
return costs;
|
||||
}
|
||||
|
||||
sa.clearPipsToReduce();
|
||||
|
||||
Card source = sa.getHostCard();
|
||||
final Game game = source.getGame();
|
||||
boolean lkicheck = false;
|
||||
|
||||
@@ -166,7 +166,14 @@ public class GameEntityCounterTable extends ForwardingTable<Optional<Player>, Ga
|
||||
for (Map.Entry<Optional<Player>, Map<CounterType, Integer>> e : values.entrySet()) {
|
||||
boolean remember = cause != null && cause.hasParam("RememberPut");
|
||||
for (Map.Entry<CounterType, Integer> ec : e.getValue().entrySet()) {
|
||||
gm.getKey().addCounterInternal(ec.getKey(), ec.getValue(), e.getKey().orNull(), true, result, runParams);
|
||||
Integer value = ec.getValue();
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
if (cause != null && cause.hasParam("MaxFromEffect")) {
|
||||
value = Math.min(value, Integer.parseInt(cause.getParam("MaxFromEffect")) - gm.getKey().getCounters(ec.getKey()));
|
||||
}
|
||||
gm.getKey().addCounterInternal(ec.getKey(), value, e.getKey().orNull(), true, result, runParams);
|
||||
if (remember && ec.getValue() >= 1) {
|
||||
cause.getHostCard().addRemembered(gm.getKey());
|
||||
}
|
||||
|
||||
@@ -166,7 +166,13 @@ public class AbilityUtils {
|
||||
if (defined.startsWith("TopThird")) {
|
||||
int third = defined.contains("RoundedDown") ? (int) Math.floor(libSize / 3.0)
|
||||
: (int) Math.ceil(libSize / 3.0);
|
||||
for (int i=0; i<third; i++) {
|
||||
for (int i = 0; i < third; i++) {
|
||||
cards.add(lib.get(i));
|
||||
}
|
||||
} else if (defined.startsWith("Top_")) {
|
||||
String[] parts = defined.split("_");
|
||||
int amt = AbilityUtils.calculateAmount(hostCard, parts[1], sa);
|
||||
for (int i = 0; i < amt; i++) {
|
||||
cards.add(lib.get(i));
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -162,6 +162,7 @@ public enum ApiType {
|
||||
Sacrifice (SacrificeEffect.class),
|
||||
SacrificeAll (SacrificeAllEffect.class),
|
||||
Scry (ScryEffect.class),
|
||||
Seek (SeekEffect.class),
|
||||
SetInMotion (SetInMotionEffect.class),
|
||||
SetLife (LifeSetEffect.class),
|
||||
SetState (SetStateEffect.class),
|
||||
|
||||
@@ -20,7 +20,7 @@ import forge.util.collect.FCollection;
|
||||
|
||||
public class CharmEffect extends SpellAbilityEffect {
|
||||
|
||||
public static List<AbilitySub> makePossibleOptions(final SpellAbility sa) {
|
||||
public static List<AbilitySub> makePossibleOptions(final SpellAbility sa, boolean forDesc) {
|
||||
final Card source = sa.getHostCard();
|
||||
List<String> restriction = null;
|
||||
|
||||
@@ -29,16 +29,19 @@ public class CharmEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
List<AbilitySub> choices = Lists.newArrayList(sa.getAdditionalAbilityList("Choices"));
|
||||
List<AbilitySub> toRemove = Lists.newArrayList();
|
||||
for (AbilitySub ch : choices) {
|
||||
// 603.3c If one of the modes would be illegal, that mode can't be chosen.
|
||||
if ((ch.usesTargeting() && ch.isTrigger() && ch.getMinTargets() > 0 &&
|
||||
ch.getTargetRestrictions().getNumCandidates(ch, true) == 0) ||
|
||||
(restriction != null && restriction.contains(ch.getDescription()))) {
|
||||
toRemove.add(ch);
|
||||
|
||||
if (!forDesc) {
|
||||
List<AbilitySub> toRemove = Lists.newArrayList();
|
||||
for (AbilitySub ch : choices) {
|
||||
// 603.3c If one of the modes would be illegal, that mode can't be chosen.
|
||||
if ((ch.usesTargeting() && ch.isTrigger() && ch.getMinTargets() > 0 &&
|
||||
ch.getTargetRestrictions().getNumCandidates(ch, true) == 0) ||
|
||||
(restriction != null && restriction.contains(ch.getDescription()))) {
|
||||
toRemove.add(ch);
|
||||
}
|
||||
}
|
||||
choices.removeAll(toRemove);
|
||||
}
|
||||
choices.removeAll(toRemove);
|
||||
|
||||
int indx = 0;
|
||||
// set CharmOrder
|
||||
@@ -52,7 +55,7 @@ public class CharmEffect extends SpellAbilityEffect {
|
||||
public static String makeFormatedDescription(SpellAbility sa) {
|
||||
Card source = sa.getHostCard();
|
||||
|
||||
List<AbilitySub> list = CharmEffect.makePossibleOptions(sa);
|
||||
List<AbilitySub> list = CharmEffect.makePossibleOptions(sa, true);
|
||||
final int num;
|
||||
boolean additionalDesc = sa.hasParam("AdditionalDescription");
|
||||
boolean optional = sa.hasParam("Optional");
|
||||
@@ -166,7 +169,7 @@ public class CharmEffect extends SpellAbilityEffect {
|
||||
//this resets all previous choices
|
||||
sa.setSubAbility(null);
|
||||
|
||||
List<AbilitySub> choices = makePossibleOptions(sa);
|
||||
List<AbilitySub> choices = makePossibleOptions(sa, false);
|
||||
|
||||
// Entwine does use all Choices
|
||||
if (sa.isEntwine()) {
|
||||
|
||||
@@ -258,7 +258,7 @@ public class CopyPermanentEffect extends TokenEffectBase {
|
||||
game.updateCombatForView();
|
||||
game.fireEvent(new GameEventCombatChanged());
|
||||
}
|
||||
} // end resolve
|
||||
}
|
||||
|
||||
public static Card getProtoType(final SpellAbility sa, final Card original, final Player newOwner) {
|
||||
final Card host = sa.getHostCard();
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package forge.game.ability.effects;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.*;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Aggregates;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SeekEffect extends SpellAbilityEffect {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.game.ability.SpellAbilityEffect#getStackDescription(forge.game.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected String getStackDescription(SpellAbility sa) {
|
||||
return sa.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
final Card source = sa.getHostCard();
|
||||
final Game game = source.getGame();
|
||||
|
||||
List<String> seekTypes = Lists.newArrayList();
|
||||
if (sa.hasParam("Types")) {
|
||||
seekTypes.addAll(Arrays.asList(sa.getParam("Types").split(",")));
|
||||
} else {
|
||||
seekTypes.add(sa.getParamOrDefault("Type", "Card"));
|
||||
}
|
||||
|
||||
int seekNum = AbilityUtils.calculateAmount(source, sa.getParamOrDefault("Num", "1"), sa);
|
||||
if (seekNum <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CardZoneTable triggerList = new CardZoneTable();
|
||||
CardCollectionView lastStateBattlefield = game.copyLastStateBattlefield();
|
||||
CardCollectionView lastStateGraveyard = game.copyLastStateGraveyard();
|
||||
|
||||
for (Player seeker : getTargetPlayers(sa)) {
|
||||
if (!seeker.isInGame()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CardCollection soughtCards = new CardCollection();
|
||||
|
||||
for (String seekType : seekTypes) {
|
||||
CardCollection pool;
|
||||
if (sa.hasParam("DefinedCards")) {
|
||||
pool = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa);
|
||||
} else {
|
||||
pool = new CardCollection(seeker.getCardsIn(ZoneType.Library));
|
||||
}
|
||||
if (!seekType.equals("Card")) {
|
||||
pool = CardLists.getValidCards(pool, seekType, source.getController(), source, sa);
|
||||
}
|
||||
if (pool.isEmpty()) {
|
||||
continue; // can't find if nothing to seek
|
||||
}
|
||||
|
||||
for (final Card c : Aggregates.random(pool, seekNum)) {
|
||||
|
||||
Map<AbilityKey, Object> moveParams = AbilityKey.newMap();
|
||||
moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield);
|
||||
moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard);
|
||||
Card movedCard = game.getAction().moveToHand(c, sa, moveParams);
|
||||
ZoneType resultZone = movedCard.getZone().getZoneType();
|
||||
if (!resultZone.equals(ZoneType.Library)) { // as long as it moved we add to triggerList
|
||||
triggerList.put(ZoneType.Library, movedCard.getZone().getZoneType(), movedCard);
|
||||
}
|
||||
if (resultZone.equals(ZoneType.Hand)) { // if it went to hand as planned, consider it "sought"
|
||||
soughtCards.add(movedCard);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!soughtCards.isEmpty()) {
|
||||
if (sa.hasParam("RememberFound")) {
|
||||
source.addRemembered(soughtCards);
|
||||
}
|
||||
if (sa.hasParam("ImprintFound")) {
|
||||
source.addImprintedCards(soughtCards);
|
||||
}
|
||||
game.getTriggerHandler().runTrigger(TriggerType.SeekAll, AbilityKey.mapFromPlayer(seeker), false);
|
||||
}
|
||||
}
|
||||
triggerList.triggerChangesZoneAll(game, sa);
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public class UntapEffect extends SpellAbilityEffect {
|
||||
* whether the untapping is mandatory.
|
||||
*/
|
||||
private static void untapChoose(final SpellAbility sa, final boolean mandatory) {
|
||||
final int num = Integer.parseInt(sa.getParam("Amount"));
|
||||
final int num = AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa);
|
||||
final String valid = sa.getParam("UntapType");
|
||||
|
||||
for (final Player p : AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa)) {
|
||||
|
||||
@@ -526,7 +526,7 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
|
||||
if (state == CardStateName.FaceDown) {
|
||||
view.updateHiddenId(game.nextHiddenCardId());
|
||||
}
|
||||
game.fireEvent(new GameEventCardStatsChanged(this)); //ensure stats updated for new characteristics
|
||||
game.fireEvent(new GameEventCardStatsChanged(this, true)); //ensure stats updated for new characteristics
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import forge.card.CardType;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
@@ -106,11 +105,7 @@ public class CostDiscard extends CostPartWithList {
|
||||
desc.append("card");
|
||||
}
|
||||
else {
|
||||
if (this.getTypeDescription() == null) {
|
||||
desc.append(CardType.CoreType.isValidEnum(this.getType()) ? this.getType().toLowerCase() : this.getType());
|
||||
} else {
|
||||
desc.append(this.getTypeDescription());
|
||||
}
|
||||
desc.append(this.getDescriptiveType());
|
||||
desc.append(" card");
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package forge.game.cost;
|
||||
|
||||
import forge.card.CardType;
|
||||
import forge.game.Game;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
@@ -85,10 +84,7 @@ public class CostExile extends CostPartWithList {
|
||||
@Override
|
||||
public final String toString() {
|
||||
final Integer i = this.convertAmount();
|
||||
String desc = this.getTypeDescription() == null ? this.getType() : this.getTypeDescription();
|
||||
if (CardType.CoreType.isValidEnum(desc)) {
|
||||
desc = desc.toLowerCase();
|
||||
}
|
||||
String desc = this.getDescriptiveType();
|
||||
String origin = this.from.name().toLowerCase();
|
||||
|
||||
if (this.payCostFromSource()) {
|
||||
|
||||
@@ -15,8 +15,14 @@ import forge.game.card.Card;
|
||||
public class GameEventCardStatsChanged extends GameEvent {
|
||||
|
||||
public final Collection<Card> cards;
|
||||
public boolean transform = false;
|
||||
public GameEventCardStatsChanged(Card affected) {
|
||||
this(affected, false);
|
||||
}
|
||||
|
||||
public GameEventCardStatsChanged(Card affected, boolean isTransform) {
|
||||
cards = Arrays.asList(affected);
|
||||
transform = isTransform;
|
||||
}
|
||||
|
||||
public GameEventCardStatsChanged(Collection<Card> affected) {
|
||||
|
||||
@@ -404,10 +404,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
}
|
||||
|
||||
public boolean canPlayWithOptionalCost(OptionalCostValue opt) {
|
||||
SpellAbility saOpt = GameActionUtil.addOptionalCosts(this, Lists.newArrayList(opt));
|
||||
boolean result = saOpt.canPlay();
|
||||
saOpt.clearPipsToReduce();
|
||||
return result;
|
||||
return GameActionUtil.addOptionalCosts(this, Lists.newArrayList(opt)).canPlay();
|
||||
}
|
||||
|
||||
public boolean isPossible() {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package forge.game.trigger;
|
||||
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Localizer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class TriggerSeekAll extends Trigger {
|
||||
|
||||
public TriggerSeekAll(Map<String, String> params, Card host, boolean intrinsic) {
|
||||
super(params, host, intrinsic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performTest(Map<AbilityKey, Object> runParams) {
|
||||
if (!matchesValidParam("ValidPlayer", runParams.get(AbilityKey.Player))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTriggeringObjects(SpellAbility sa, Map<AbilityKey, Object> runParams) {
|
||||
sa.setTriggeringObjectsFrom(runParams, AbilityKey.Player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getImportantStackObjects(SpellAbility sa) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(Localizer.getInstance().getMessage("lblPlayer")).append(": ");
|
||||
sb.append(sa.getTriggeringObject(AbilityKey.Player));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -104,6 +104,7 @@ public enum TriggerType {
|
||||
Sacrificed(TriggerSacrificed.class),
|
||||
Scry(TriggerScry.class),
|
||||
SearchedLibrary(TriggerSearchedLibrary.class),
|
||||
SeekAll(TriggerSeekAll.class),
|
||||
SetInMotion(TriggerSetInMotion.class),
|
||||
Shuffled(TriggerShuffled.class),
|
||||
Specializes(TriggerSpecializes.class),
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Clipboard;
|
||||
import forge.adventure.scene.*;
|
||||
import forge.adventure.stage.GameHUD;
|
||||
import forge.adventure.util.Config;
|
||||
import forge.adventure.world.WorldSave;
|
||||
import forge.animation.ForgeAnimation;
|
||||
@@ -340,6 +341,7 @@ public class Forge implements ApplicationListener {
|
||||
try {
|
||||
Config.instance().loadResources();
|
||||
SpellSmithScene.instance().loadEditions();
|
||||
GameHUD.getInstance().stopAudio();
|
||||
if (startScene) {
|
||||
MusicPlaylist.invalidateMusicPlaylist();
|
||||
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS);
|
||||
|
||||
@@ -18,6 +18,8 @@ import forge.deck.DeckProxy;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.sound.SoundEffectType;
|
||||
import forge.sound.SoundSystem;
|
||||
import forge.util.ItemPool;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -516,6 +518,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
||||
public void takeGold(int price) {
|
||||
gold -= price;
|
||||
onGoldChangeList.emit();
|
||||
//play sfx
|
||||
SoundSystem.instance.play(SoundEffectType.CoinsDrop, false);
|
||||
}
|
||||
public void addShards(int number) {
|
||||
takeShards(-number);
|
||||
@@ -523,6 +527,8 @@ public class AdventurePlayer implements Serializable, SaveFileContent {
|
||||
public void takeShards(int number) {
|
||||
shards -= number;
|
||||
onShardsChangeList.emit();
|
||||
//play sfx
|
||||
SoundSystem.instance.play(SoundEffectType.TakeShard, false);
|
||||
}
|
||||
|
||||
public void setShards(int number) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import forge.adventure.data.EffectData;
|
||||
import forge.adventure.data.EnemyData;
|
||||
import forge.adventure.data.ItemData;
|
||||
import forge.adventure.player.AdventurePlayer;
|
||||
import forge.adventure.stage.GameHUD;
|
||||
import forge.adventure.stage.IAfterMatch;
|
||||
import forge.adventure.util.Config;
|
||||
import forge.adventure.util.Current;
|
||||
@@ -67,6 +68,8 @@ public class DuelScene extends ForgeScene {
|
||||
Deck playerDeck;
|
||||
boolean chaosBattle = false;
|
||||
boolean callbackExit = false;
|
||||
boolean arenaBattleChallenge = false;
|
||||
boolean isArena = false;
|
||||
private LoadingOverlay matchOverlay;
|
||||
List<IPaperCard> playerExtras = new ArrayList<>();
|
||||
List<IPaperCard> AIExtras = new ArrayList<>();
|
||||
@@ -138,7 +141,13 @@ public class DuelScene extends ForgeScene {
|
||||
|
||||
void afterGameEnd(String enemyName, boolean winner, boolean showOverlay, boolean alternate) {
|
||||
Runnable runnable = () -> Gdx.app.postRunnable(()-> {
|
||||
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS); //start background music
|
||||
if (GameScene.instance().isNotInWorldMap()) {
|
||||
SoundSystem.instance.pause();
|
||||
GameHUD.getInstance().playAudio();
|
||||
} else {
|
||||
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS);
|
||||
SoundSystem.instance.resume();
|
||||
}
|
||||
dungeonEffect = null;
|
||||
callbackExit = false;
|
||||
Forge.clearTransitionScreen();
|
||||
@@ -192,6 +201,7 @@ public class DuelScene extends ForgeScene {
|
||||
|
||||
@Override
|
||||
public void enter() {
|
||||
GameHUD.getInstance().unloadAudio();
|
||||
Set<GameType> appliedVariants = new HashSet<>();
|
||||
appliedVariants.add(GameType.Constructed);
|
||||
AdventurePlayer advPlayer = Current.player();
|
||||
@@ -267,6 +277,7 @@ public class DuelScene extends ForgeScene {
|
||||
addEffects(humanPlayer, playerEffects);
|
||||
|
||||
currentEnemy = enemy.getData();
|
||||
boolean bossBattle = currentEnemy.boss;
|
||||
for (int i = 0; i < 8 && currentEnemy != null; i++) {
|
||||
Deck deck = null;
|
||||
|
||||
@@ -278,6 +289,8 @@ public class DuelScene extends ForgeScene {
|
||||
}
|
||||
this.AIExtras = aiCards;
|
||||
deck = deckProxy.getDeck();
|
||||
} else if (this.arenaBattleChallenge) {
|
||||
deck = Aggregates.random(DeckProxy.getAllGeneticAIDecks()).getDeck();
|
||||
} else {
|
||||
deck = currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().isUsingCustomDeck() || Current.player().getDifficulty().name.equalsIgnoreCase("Hard"));
|
||||
}
|
||||
@@ -332,7 +345,7 @@ public class DuelScene extends ForgeScene {
|
||||
rules.setWarnAboutAICards(false);
|
||||
|
||||
hostedMatch.setEndGameHook(() -> DuelScene.this.GameEnd());
|
||||
hostedMatch.startMatch(rules, appliedVariants, players, guiMap);
|
||||
hostedMatch.startMatch(rules, appliedVariants, players, guiMap, bossBattle ? MusicPlaylist.BOSS : MusicPlaylist.MATCH);
|
||||
MatchController.instance.setGameView(hostedMatch.getGameView());
|
||||
boolean showMessages = enemy.getData().copyPlayerDeck && Current.player().isUsingCustomDeck();
|
||||
if (chaosBattle || showMessages) {
|
||||
@@ -376,8 +389,15 @@ public class DuelScene extends ForgeScene {
|
||||
}
|
||||
|
||||
public void initDuels(PlayerSprite playerSprite, EnemySprite enemySprite) {
|
||||
initDuels(playerSprite, enemySprite, false);
|
||||
}
|
||||
public void initDuels(PlayerSprite playerSprite, EnemySprite enemySprite, boolean isArena) {
|
||||
this.player = playerSprite;
|
||||
this.enemy = enemySprite;
|
||||
this.isArena = isArena;
|
||||
this.arenaBattleChallenge = isArena
|
||||
&& (Current.player().getDifficulty().name.equalsIgnoreCase("Hard")
|
||||
|| Current.player().getDifficulty().name.equalsIgnoreCase("Insane"));
|
||||
this.playerDeck = (Deck) Current.player().getSelectedDeck().copyTo("PlayerDeckCopy");
|
||||
this.chaosBattle = this.enemy.getData().copyPlayerDeck && Current.player().isFantasyMode();
|
||||
this.AIExtras.clear();
|
||||
|
||||
@@ -64,14 +64,13 @@ public class GameScene extends HudScene {
|
||||
} else {
|
||||
World world = Current.world();
|
||||
//this gets the name of the layer... this shoud be based on boundaries...
|
||||
int currentBiome = World.highestBiome(world.getBiome((int) stage.getPlayerSprite().getX() / world.getTileSize(), (int) stage.getPlayerSprite().getY() / world.getTileSize()));
|
||||
int currentBiome = World.highestBiome(world.getBiomeMapXY((int) stage.getPlayerSprite().getX() / world.getTileSize(), (int) stage.getPlayerSprite().getY() / world.getTileSize()));
|
||||
List<BiomeData> biomeData = world.getData().GetBiomes();
|
||||
if (biomeData.size() <= currentBiome) //on roads....
|
||||
if (biomeData.size() <= currentBiome) //shouldn't be the case but default to waste
|
||||
if (skipRoads) {
|
||||
location = forHeader ? "Waste Map" : "waste";
|
||||
} else {
|
||||
//current workaround to get the POI town name
|
||||
location = WorldStage.getInstance().getBoundary();
|
||||
location = "";
|
||||
}
|
||||
else {
|
||||
BiomeData data = biomeData.get(currentBiome);
|
||||
|
||||
@@ -24,6 +24,7 @@ import forge.localinstance.properties.ForgePreferences;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
import forge.screens.TransitionScreen;
|
||||
import forge.sound.SoundSystem;
|
||||
import forge.util.NameGenerator;
|
||||
|
||||
import java.util.Random;
|
||||
@@ -190,7 +191,7 @@ public class NewGameScene extends UIScene {
|
||||
}
|
||||
Runnable runnable = () -> {
|
||||
started = false;
|
||||
FModel.getPreferences().setPref(ForgePreferences.FPref.UI_ENABLE_MUSIC, false);
|
||||
//FModel.getPreferences().setPref(ForgePreferences.FPref.UI_ENABLE_MUSIC, false);
|
||||
WorldSave.generateNewWorld(selectedName.getText(),
|
||||
gender.getCurrentIndex() == 0,
|
||||
race.getCurrentIndex(),
|
||||
@@ -200,6 +201,7 @@ public class NewGameScene extends UIScene {
|
||||
modes.get(mode.getCurrentIndex()), colorId.getCurrentIndex(),
|
||||
editionIds[starterEdition.getCurrentIndex()], 0);//maybe replace with enum
|
||||
GamePlayerUtil.getGuiPlayer().setName(selectedName.getText());
|
||||
SoundSystem.instance.changeBackgroundTrack();
|
||||
Forge.switchScene(GameScene.instance());
|
||||
};
|
||||
Forge.setTransitionScreen(new TransitionScreen(runnable, null, false, true, "Generating World..."));
|
||||
|
||||
@@ -146,13 +146,15 @@ public class RewardScene extends UIScene {
|
||||
showLootOrDone();
|
||||
return true;
|
||||
}
|
||||
switch (type) {
|
||||
case Shop:
|
||||
doneButton.setText(Forge.getLocalizer().getMessage("lblLeave"));
|
||||
break;
|
||||
case Loot:
|
||||
doneButton.setText(Forge.getLocalizer().getMessage("lblDone"));
|
||||
break;
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case Shop:
|
||||
doneButton.setText(Forge.getLocalizer().getMessage("lblLeave"));
|
||||
break;
|
||||
case Loot:
|
||||
doneButton.setText(Forge.getLocalizer().getMessage("lblDone"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
shown = false;
|
||||
clearGenerated();
|
||||
|
||||
@@ -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.sound.SoundSystem;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
import java.io.File;
|
||||
@@ -217,6 +218,7 @@ public class SaveLoadScene extends UIScene {
|
||||
try {
|
||||
Forge.setTransitionScreen(new TransitionScreen(() -> {
|
||||
if (WorldSave.load(currentSlot)) {
|
||||
SoundSystem.instance.changeBackgroundTrack();
|
||||
Forge.switchScene(GameScene.instance());
|
||||
} else {
|
||||
Forge.clearTransitionScreen();
|
||||
@@ -236,6 +238,7 @@ public class SaveLoadScene extends UIScene {
|
||||
Current.player().updateDifficulty(Config.instance().getConfigData().difficulties[difficulty.getSelectedIndex()]);
|
||||
Current.player().setWorldPosY((int) (WorldSave.getCurrentSave().getWorld().getData().playerStartPosY * WorldSave.getCurrentSave().getWorld().getData().height * WorldSave.getCurrentSave().getWorld().getTileSize()));
|
||||
Current.player().setWorldPosX((int) (WorldSave.getCurrentSave().getWorld().getData().playerStartPosX * WorldSave.getCurrentSave().getWorld().getData().width * WorldSave.getCurrentSave().getWorld().getTileSize()));
|
||||
SoundSystem.instance.changeBackgroundTrack();
|
||||
Forge.switchScene(GameScene.instance());
|
||||
} else {
|
||||
Forge.clearTransitionScreen();
|
||||
|
||||
@@ -10,6 +10,7 @@ import forge.adventure.util.Config;
|
||||
import forge.adventure.util.Controls;
|
||||
import forge.adventure.world.WorldSave;
|
||||
import forge.screens.TransitionScreen;
|
||||
import forge.sound.SoundSystem;
|
||||
|
||||
/**
|
||||
* First scene after the splash screen
|
||||
@@ -20,7 +21,6 @@ public class StartScene extends UIScene {
|
||||
TextraButton saveButton, resumeButton, continueButton;
|
||||
|
||||
|
||||
|
||||
public StartScene() {
|
||||
super(Forge.isLandscapeMode() ? "ui/start_menu.json" : "ui/start_menu_portrait.json");
|
||||
ui.onButtonPress("Start", StartScene.this::NewGame);
|
||||
@@ -31,7 +31,7 @@ public class StartScene extends UIScene {
|
||||
ui.onButtonPress("Continue", StartScene.this::Continue);
|
||||
ui.onButtonPress("Settings", StartScene.this::settings);
|
||||
ui.onButtonPress("Exit", StartScene.this::Exit);
|
||||
ui.onButtonPress("Switch", Forge::switchToClassic);
|
||||
ui.onButtonPress("Switch", StartScene.this::switchToClassic);
|
||||
|
||||
|
||||
saveButton = ui.findActor("Save");
|
||||
@@ -43,8 +43,8 @@ public class StartScene extends UIScene {
|
||||
}
|
||||
|
||||
public static StartScene instance() {
|
||||
if(object==null)
|
||||
object=new StartScene();
|
||||
if (object == null)
|
||||
object = new StartScene();
|
||||
return object;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ public class StartScene extends UIScene {
|
||||
try {
|
||||
Forge.setTransitionScreen(new TransitionScreen(() -> {
|
||||
if (WorldSave.load(WorldSave.filenameToSlot(lastActiveSave))) {
|
||||
SoundSystem.instance.changeBackgroundTrack();
|
||||
Forge.switchScene(GameScene.instance());
|
||||
} else {
|
||||
Forge.clearTransitionScreen();
|
||||
@@ -100,17 +101,22 @@ public class StartScene extends UIScene {
|
||||
}
|
||||
|
||||
public boolean Exit() {
|
||||
Dialog dialog = prepareDialog(Forge.getLocalizer().getMessage("lblExitForge"), ButtonOk|ButtonAbort,()->Forge.exit(true));
|
||||
dialog.text( Controls.newLabel(Forge.getLocalizer().getMessage("lblAreYouSureYouWishExitForge")));
|
||||
Dialog dialog = prepareDialog(Forge.getLocalizer().getMessage("lblExitForge"), ButtonOk | ButtonAbort, () -> Forge.exit(true));
|
||||
dialog.text(Controls.newLabel(Forge.getLocalizer().getMessage("lblAreYouSureYouWishExitForge")));
|
||||
showDialog(dialog);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void switchToClassic() {
|
||||
GameHUD.getInstance().stopAudio();
|
||||
Forge.switchToClassic();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enter() {
|
||||
boolean hasSaveButton = WorldSave.getCurrentSave().getWorld().getData() != null;
|
||||
if (hasSaveButton) {
|
||||
TileMapScene scene = TileMapScene.instance();
|
||||
TileMapScene scene = TileMapScene.instance();
|
||||
hasSaveButton = !scene.currentMap().isInMap() || scene.isAutoHealLocation();
|
||||
}
|
||||
saveButton.setVisible(hasSaveButton);
|
||||
@@ -130,10 +136,9 @@ public class StartScene extends UIScene {
|
||||
}
|
||||
|
||||
|
||||
if(Forge.createNewAdventureMap)
|
||||
{
|
||||
if (Forge.createNewAdventureMap) {
|
||||
this.NewGame();
|
||||
GameStage.maximumScrollDistance=4f;
|
||||
GameStage.maximumScrollDistance = 4f;
|
||||
}
|
||||
|
||||
super.enter();
|
||||
|
||||
@@ -19,6 +19,8 @@ import com.github.tommyettinger.textra.TextraLabel;
|
||||
import forge.Forge;
|
||||
import forge.adventure.stage.GameHUD;
|
||||
import forge.adventure.util.*;
|
||||
import forge.sound.SoundEffectType;
|
||||
import forge.sound.SoundSystem;
|
||||
|
||||
/**
|
||||
* Base class for an GUI scene where the elements are loaded from a json file
|
||||
@@ -27,86 +29,83 @@ public class UIScene extends Scene {
|
||||
protected UIActor ui;
|
||||
|
||||
|
||||
public static class Selectable<T extends Actor>
|
||||
{
|
||||
public static class Selectable<T extends Actor> {
|
||||
public T actor;
|
||||
public float getY()
|
||||
{
|
||||
Actor act=actor;
|
||||
float y=0;
|
||||
while (act!=null)
|
||||
{
|
||||
y+=act.getY();
|
||||
act=act.getParent();
|
||||
|
||||
public float getY() {
|
||||
Actor act = actor;
|
||||
float y = 0;
|
||||
while (act != null) {
|
||||
y += act.getY();
|
||||
act = act.getParent();
|
||||
}
|
||||
return y;
|
||||
}
|
||||
public float getX()
|
||||
{
|
||||
Actor act=actor;
|
||||
float x=0;
|
||||
while (act!=null)
|
||||
{
|
||||
x+=act.getX();
|
||||
act=act.getParent();
|
||||
|
||||
public float getX() {
|
||||
Actor act = actor;
|
||||
float x = 0;
|
||||
while (act != null) {
|
||||
x += act.getX();
|
||||
act = act.getParent();
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
public Selectable(T newActor) {
|
||||
actor=newActor;
|
||||
actor = newActor;
|
||||
}
|
||||
|
||||
public void onSelect(UIScene scene)
|
||||
{
|
||||
public void onSelect(UIScene scene) {
|
||||
}
|
||||
public void onDeSelect()
|
||||
{
|
||||
|
||||
public void onDeSelect() {
|
||||
//actor.fire(UIScene.eventExit());
|
||||
}
|
||||
public void onPressDown(UIScene scene)
|
||||
{
|
||||
if(actor instanceof TextField)
|
||||
{
|
||||
scene.requestTextInput(((TextField) actor).getText(),text-> ((TextField) actor).setText(text));
|
||||
|
||||
public void onPressDown(UIScene scene) {
|
||||
if (actor instanceof TextField) {
|
||||
scene.requestTextInput(((TextField) actor).getText(), text -> ((TextField) actor).setText(text));
|
||||
|
||||
}
|
||||
actor.fire(UIScene.eventTouchDown());
|
||||
}
|
||||
public void onPressUp()
|
||||
{
|
||||
|
||||
public void onPressUp() {
|
||||
actor.fire(UIScene.eventTouchUp());
|
||||
}
|
||||
|
||||
public float yDiff(Selectable finalOne) {
|
||||
return Math.abs(finalOne.getY()-getY());
|
||||
return Math.abs(finalOne.getY() - getY());
|
||||
}
|
||||
|
||||
public float xDiff(Selectable finalOne) {
|
||||
return Math.abs(finalOne.getX()-getX());
|
||||
return Math.abs(finalOne.getX() - getX());
|
||||
}
|
||||
}
|
||||
static final public int ButtonYes=0x1;
|
||||
static final public int ButtonNo=0x2;
|
||||
static final public int ButtonOk=0x4;
|
||||
static final public int ButtonAbort=0x8;
|
||||
|
||||
static final public int ButtonYes = 0x1;
|
||||
static final public int ButtonNo = 0x2;
|
||||
static final public int ButtonOk = 0x4;
|
||||
static final public int ButtonAbort = 0x8;
|
||||
|
||||
public Dialog prepareDialog(String header, int buttons, Runnable onOkOrYes) {
|
||||
Dialog dialog =new Dialog(header, Controls.getSkin())
|
||||
{
|
||||
protected void result(Object object)
|
||||
{
|
||||
if(onOkOrYes!=null&&object!=null&&object.equals(true))
|
||||
Dialog dialog = new Dialog(header, Controls.getSkin()) {
|
||||
protected void result(Object object) {
|
||||
SoundSystem.instance.play(SoundEffectType.ButtonPress, false);
|
||||
if (onOkOrYes != null && object != null && object.equals(true))
|
||||
onOkOrYes.run();
|
||||
this.hide();
|
||||
removeDialog();
|
||||
}
|
||||
};
|
||||
if((buttons&ButtonYes)!=0)
|
||||
if ((buttons & ButtonYes) != 0)
|
||||
dialog.button(Forge.getLocalizer().getMessage("lblYes"), true);
|
||||
if((buttons&ButtonNo)!=0)
|
||||
if ((buttons & ButtonNo) != 0)
|
||||
dialog.button(Forge.getLocalizer().getMessage("lblNo"), false);
|
||||
if((buttons&ButtonOk)!=0)
|
||||
if ((buttons & ButtonOk) != 0)
|
||||
dialog.button(Forge.getLocalizer().getMessage("lblOk"), true);
|
||||
if((buttons&ButtonAbort)!=0)
|
||||
if ((buttons & ButtonAbort) != 0)
|
||||
dialog.button(Forge.getLocalizer().getMessage("lblAbort"), false);
|
||||
|
||||
dialog.setMovable(false);
|
||||
@@ -114,16 +113,16 @@ public class UIScene extends Scene {
|
||||
dialog.setResizable(false);
|
||||
return dialog;
|
||||
}
|
||||
public void showDialog(Dialog dialog)
|
||||
{
|
||||
|
||||
public void showDialog(Dialog dialog) {
|
||||
stage.addActor(dialog);
|
||||
possibleSelectionStack.add(new Array<>());
|
||||
addToSelectable(dialog.getContentTable());
|
||||
addToSelectable(dialog.getButtonTable());
|
||||
dialog.getColor().a=0;
|
||||
dialog.getColor().a = 0;
|
||||
stage.setKeyboardFocus(dialog);
|
||||
stage.setScrollFocus(dialog);
|
||||
for(Dialog otherDialogs:dialogs)
|
||||
for (Dialog otherDialogs : dialogs)
|
||||
otherDialogs.hide();
|
||||
dialogs.add(dialog);
|
||||
selectFirst();
|
||||
@@ -145,41 +144,42 @@ public class UIScene extends Scene {
|
||||
//possibleSelection=keyboardDialog.keys();
|
||||
}
|
||||
|
||||
public Array< Array<Selectable>> possibleSelectionStack=new Array<>();
|
||||
public Array< Dialog> dialogs=new Array<>();
|
||||
public Array<Selectable> getPossibleSelection()
|
||||
{
|
||||
if(possibleSelectionStack.isEmpty())
|
||||
public Array<Array<Selectable>> possibleSelectionStack = new Array<>();
|
||||
public Array<Dialog> dialogs = new Array<>();
|
||||
|
||||
public Array<Selectable> getPossibleSelection() {
|
||||
if (possibleSelectionStack.isEmpty())
|
||||
possibleSelectionStack.add(ui.selectActors);
|
||||
return possibleSelectionStack.get(possibleSelectionStack.size-1);
|
||||
return possibleSelectionStack.get(possibleSelectionStack.size - 1);
|
||||
}
|
||||
|
||||
protected Stage stage;
|
||||
|
||||
String uiFile;
|
||||
public static InputEvent eventTouchUp()
|
||||
{
|
||||
|
||||
public static InputEvent eventTouchUp() {
|
||||
InputEvent event = new InputEvent();
|
||||
event.setPointer(-1);
|
||||
event.setType(InputEvent.Type.touchUp);
|
||||
return event;
|
||||
}
|
||||
public static InputEvent eventTouchDown()
|
||||
{
|
||||
|
||||
public static InputEvent eventTouchDown() {
|
||||
InputEvent event = new InputEvent();
|
||||
event.setPointer(-1);
|
||||
event.setType(InputEvent.Type.touchDown);
|
||||
return event;
|
||||
}
|
||||
public static InputEvent eventExit()
|
||||
{
|
||||
|
||||
public static InputEvent eventExit() {
|
||||
|
||||
InputEvent event = new InputEvent();
|
||||
event.setPointer(-1);
|
||||
event.setType(InputEvent.Type.exit);
|
||||
return event;
|
||||
}
|
||||
public static InputEvent eventEnter()
|
||||
{
|
||||
|
||||
public static InputEvent eventEnter() {
|
||||
InputEvent event = new InputEvent();
|
||||
event.setPointer(-1);
|
||||
event.setType(InputEvent.Type.enter);
|
||||
@@ -188,26 +188,30 @@ public class UIScene extends Scene {
|
||||
|
||||
@Override
|
||||
public boolean buttonUp(Controller controller, int keycode) {
|
||||
return stage.keyUp(KeyBinding.controllerButtonToKey(controller,keycode));
|
||||
return stage.keyUp(KeyBinding.controllerButtonToKey(controller, keycode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean buttonDown(Controller controller, int keycode) {
|
||||
return stage.keyDown(KeyBinding.controllerButtonToKey(controller,keycode));
|
||||
return stage.keyDown(KeyBinding.controllerButtonToKey(controller, keycode));
|
||||
}
|
||||
|
||||
protected void addToSelectable(Table table) {
|
||||
for(Cell cell:table.getCells())
|
||||
{
|
||||
if(cell.getActor()!=null&&cell.getActor().getClass()!=Actor.class&&!(cell.getActor()instanceof Label)&&!(cell.getActor()instanceof TextraLabel))
|
||||
for (Cell cell : table.getCells()) {
|
||||
if (cell.getActor() != null && cell.getActor().getClass() != Actor.class && !(cell.getActor() instanceof Label) && !(cell.getActor() instanceof TextraLabel))
|
||||
getPossibleSelection().add(new Selectable(cell.getActor()));
|
||||
}
|
||||
}
|
||||
|
||||
protected void addToSelectable(Button button)//prevent to addToSelectable(Table) fallback
|
||||
{
|
||||
{
|
||||
getPossibleSelection().add(new Selectable(button));
|
||||
}
|
||||
|
||||
protected void addToSelectable(Actor button) {
|
||||
getPossibleSelection().add(new Selectable(button));
|
||||
}
|
||||
|
||||
protected void addToSelectable(Selectable selectable) {
|
||||
getPossibleSelection().add(selectable);
|
||||
}
|
||||
@@ -222,14 +226,16 @@ public class UIScene extends Scene {
|
||||
stage = new Stage(new ScalingViewport(Scaling.stretch, getIntendedWidth(), getIntendedHeight())) {
|
||||
@Override
|
||||
public boolean keyUp(int keycode) {
|
||||
keyReleased(keycode);
|
||||
keyReleased(keycode);
|
||||
return super.keyUp(keycode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyDown(int keyCode) {
|
||||
keyPressed(keyCode);
|
||||
keyPressed(keyCode);
|
||||
return super.keyDown(keyCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseMoved(int screenX, int screenY) {
|
||||
pointerMoved(screenX, screenY);
|
||||
@@ -237,9 +243,8 @@ public class UIScene extends Scene {
|
||||
}
|
||||
};
|
||||
ui = new UIActor(Config.instance().getFile(uiFile));
|
||||
for(Actor actor:ui.getChildren())
|
||||
{
|
||||
if(actor instanceof ScrollPane)
|
||||
for (Actor actor : ui.getChildren()) {
|
||||
if (actor instanceof ScrollPane)
|
||||
stage.setScrollFocus(actor);
|
||||
}
|
||||
possibleSelectionStack.add(ui.selectActors);
|
||||
@@ -249,21 +254,17 @@ public class UIScene extends Scene {
|
||||
|
||||
private void removeDialog() {
|
||||
|
||||
if(!dialogs.isEmpty())
|
||||
{
|
||||
dialogs.get(dialogs.size-1).remove();
|
||||
dialogs.removeIndex(dialogs.size-1);
|
||||
if (!dialogs.isEmpty()) {
|
||||
dialogs.get(dialogs.size - 1).remove();
|
||||
dialogs.removeIndex(dialogs.size - 1);
|
||||
|
||||
if(!dialogs.isEmpty())
|
||||
dialogs.get(dialogs.size-1).show(stage);
|
||||
if (!dialogs.isEmpty())
|
||||
dialogs.get(dialogs.size - 1).show(stage);
|
||||
}
|
||||
if(possibleSelectionStack.isEmpty())
|
||||
{
|
||||
if (possibleSelectionStack.isEmpty()) {
|
||||
getPossibleSelection();
|
||||
}
|
||||
else
|
||||
{
|
||||
possibleSelectionStack.removeIndex(possibleSelectionStack.size-1);
|
||||
} else {
|
||||
possibleSelectionStack.removeIndex(possibleSelectionStack.size - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,92 +296,80 @@ public class UIScene extends Scene {
|
||||
Forge.switchToLast();
|
||||
return true;
|
||||
}
|
||||
public Selectable getSelected()
|
||||
{
|
||||
for(Selectable selectable: getPossibleSelection())
|
||||
{
|
||||
if(stage.getKeyboardFocus()==selectable.actor)
|
||||
|
||||
public Selectable getSelected() {
|
||||
for (Selectable selectable : getPossibleSelection()) {
|
||||
if (stage.getKeyboardFocus() == selectable.actor)
|
||||
return selectable;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public boolean keyReleased(int keycode)
|
||||
{
|
||||
|
||||
public boolean keyReleased(int keycode) {
|
||||
|
||||
ui.pressUp(keycode);
|
||||
if(!dialogShowing())
|
||||
{
|
||||
Button pressedButton=ui.buttonPressed(keycode);
|
||||
if(pressedButton!=null)
|
||||
{
|
||||
if(pressedButton.isVisible())
|
||||
if (!dialogShowing()) {
|
||||
Button pressedButton = ui.buttonPressed(keycode);
|
||||
if (pressedButton != null) {
|
||||
if (pressedButton.isVisible())
|
||||
pressedButton.fire(eventTouchUp());
|
||||
}
|
||||
}
|
||||
if(KeyBinding.Use.isPressed(keycode)){
|
||||
if(getSelected()!=null)
|
||||
if (KeyBinding.Use.isPressed(keycode)) {
|
||||
if (getSelected() != null)
|
||||
getSelected().onPressUp();//order is important, this might remove a dialog
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean keyPressed(int keycode) {
|
||||
Selectable selection=getSelected();
|
||||
Selectable selection = getSelected();
|
||||
ui.pressDown(keycode);
|
||||
if(stage.getKeyboardFocus() instanceof SelectBox)
|
||||
{
|
||||
SelectBox box=(SelectBox) stage.getKeyboardFocus();
|
||||
if(box.getScrollPane().hasParent())
|
||||
{
|
||||
if(KeyBinding.Use.isPressed(keycode))
|
||||
{
|
||||
if (stage.getKeyboardFocus() instanceof SelectBox) {
|
||||
SelectBox box = (SelectBox) stage.getKeyboardFocus();
|
||||
if (box.getScrollPane().hasParent()) {
|
||||
if (KeyBinding.Use.isPressed(keycode)) {
|
||||
box.getSelection().choose(box.getList().getSelected());
|
||||
box.getScrollPane().hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(KeyBinding.Use.isPressed(keycode)){
|
||||
if(selection!=null)
|
||||
if (KeyBinding.Use.isPressed(keycode)) {
|
||||
if (selection != null)
|
||||
selection.onPressDown(this);
|
||||
|
||||
}
|
||||
if(KeyBinding.ScrollUp.isPressed(keycode))
|
||||
{
|
||||
Actor focus=stage.getScrollFocus();
|
||||
if(focus!=null&&focus instanceof ScrollPane)
|
||||
{
|
||||
ScrollPane scroll=((ScrollPane)focus);
|
||||
scroll.setScrollY(scroll.getScrollY()-20);
|
||||
if (KeyBinding.ScrollUp.isPressed(keycode)) {
|
||||
Actor focus = stage.getScrollFocus();
|
||||
if (focus != null && focus instanceof ScrollPane) {
|
||||
ScrollPane scroll = ((ScrollPane) focus);
|
||||
scroll.setScrollY(scroll.getScrollY() - 20);
|
||||
}
|
||||
}
|
||||
if(KeyBinding.ScrollDown.isPressed(keycode))
|
||||
{
|
||||
Actor focus=stage.getScrollFocus();
|
||||
if(focus!=null&&focus instanceof ScrollPane)
|
||||
{
|
||||
ScrollPane scroll=((ScrollPane)focus);
|
||||
scroll.setScrollY(scroll.getScrollY()+20);
|
||||
if (KeyBinding.ScrollDown.isPressed(keycode)) {
|
||||
Actor focus = stage.getScrollFocus();
|
||||
if (focus != null && focus instanceof ScrollPane) {
|
||||
ScrollPane scroll = ((ScrollPane) focus);
|
||||
scroll.setScrollY(scroll.getScrollY() + 20);
|
||||
}
|
||||
}
|
||||
if(KeyBinding.Down.isPressed(keycode))
|
||||
if (KeyBinding.Down.isPressed(keycode))
|
||||
selectNextDown();
|
||||
if(KeyBinding.Up.isPressed(keycode))
|
||||
if (KeyBinding.Up.isPressed(keycode))
|
||||
selectNextUp();
|
||||
if(!(stage.getKeyboardFocus() instanceof Selector)&&!(stage.getKeyboardFocus() instanceof TextField)&&!(stage.getKeyboardFocus() instanceof Slider))
|
||||
{
|
||||
if(KeyBinding.Right.isPressed(keycode))
|
||||
if (!(stage.getKeyboardFocus() instanceof Selector) && !(stage.getKeyboardFocus() instanceof TextField) && !(stage.getKeyboardFocus() instanceof Slider)) {
|
||||
if (KeyBinding.Right.isPressed(keycode))
|
||||
selectNextRight();
|
||||
if(KeyBinding.Left.isPressed(keycode))
|
||||
if (KeyBinding.Left.isPressed(keycode))
|
||||
selectNextLeft();
|
||||
}
|
||||
if(!dialogShowing())
|
||||
{
|
||||
Button pressedButton=ui.buttonPressed(keycode);
|
||||
if(pressedButton!=null)
|
||||
{
|
||||
if(pressedButton.isVisible())
|
||||
if (!dialogShowing()) {
|
||||
Button pressedButton = ui.buttonPressed(keycode);
|
||||
if (pressedButton != null) {
|
||||
if (pressedButton.isVisible())
|
||||
pressedButton.fire(eventTouchDown());
|
||||
}
|
||||
}
|
||||
@@ -396,11 +385,13 @@ public class UIScene extends Scene {
|
||||
public void disconnected(final Controller controller) {
|
||||
ui.controllerDisconnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connected(final Controller controller) {
|
||||
selectFirst();
|
||||
ui.controllerConnected();
|
||||
}
|
||||
|
||||
public boolean pointerMoved(int screenX, int screenY) {
|
||||
unselectActors();
|
||||
return false;
|
||||
@@ -417,152 +408,128 @@ public class UIScene extends Scene {
|
||||
}
|
||||
}, 0.10f);
|
||||
}
|
||||
|
||||
public void unselectActors() {
|
||||
for (Selectable selectable : getPossibleSelection()) {
|
||||
selectable.onDeSelect();
|
||||
selectable.onDeSelect();
|
||||
}
|
||||
}
|
||||
Array<Selectable> visibleSelection()
|
||||
{
|
||||
Array<Selectable> selectables=new Array<>();
|
||||
|
||||
Array<Selectable> visibleSelection() {
|
||||
Array<Selectable> selectables = new Array<>();
|
||||
for (Selectable selectable : getPossibleSelection()) {
|
||||
if(selectable.actor.isVisible())
|
||||
{
|
||||
if(selectable.actor instanceof Button)
|
||||
{
|
||||
if(!((Button)selectable.actor).isDisabled())
|
||||
if (selectable.actor.isVisible()) {
|
||||
if (selectable.actor instanceof Button) {
|
||||
if (!((Button) selectable.actor).isDisabled())
|
||||
selectables.add(selectable);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
selectables.add(selectable);
|
||||
}
|
||||
}
|
||||
}
|
||||
return selectables;
|
||||
}
|
||||
|
||||
public void selectNextDown() {
|
||||
if(getSelected()==null)
|
||||
{
|
||||
if (getSelected() == null) {
|
||||
selectFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
Selectable current =getSelected();
|
||||
Array<Selectable> candidates=new Array<>();
|
||||
for(Selectable selectable:visibleSelection())
|
||||
{
|
||||
if(selectable.xDiff(current)<0.1&&selectable!=current)
|
||||
} else {
|
||||
Selectable current = getSelected();
|
||||
Array<Selectable> candidates = new Array<>();
|
||||
for (Selectable selectable : visibleSelection()) {
|
||||
if (selectable.xDiff(current) < 0.1 && selectable != current)
|
||||
candidates.add(selectable);
|
||||
}
|
||||
if(candidates.isEmpty())
|
||||
if (candidates.isEmpty())
|
||||
candidates.addAll(visibleSelection());
|
||||
Selectable finalOne=null;
|
||||
Selectable fallback=null;
|
||||
for(Selectable candidate:candidates)
|
||||
{
|
||||
if(fallback==null||candidate.getY()>fallback.getY())
|
||||
fallback=candidate;
|
||||
if(candidate.getY()<current.getY()&&(finalOne==null||current.yDiff(candidate)<current.yDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
Selectable finalOne = null;
|
||||
Selectable fallback = null;
|
||||
for (Selectable candidate : candidates) {
|
||||
if (fallback == null || candidate.getY() > fallback.getY())
|
||||
fallback = candidate;
|
||||
if (candidate.getY() < current.getY() && (finalOne == null || current.yDiff(candidate) < current.yDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne==null)
|
||||
for(Selectable candidate:visibleSelection())
|
||||
{
|
||||
if(candidate.getY()<current.getY()&&(finalOne==null||current.yDiff(candidate)<current.yDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
if (finalOne == null)
|
||||
for (Selectable candidate : visibleSelection()) {
|
||||
if (candidate.getY() < current.getY() && (finalOne == null || current.yDiff(candidate) < current.yDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne!=null)
|
||||
if (finalOne != null)
|
||||
selectActor(finalOne);
|
||||
else if(fallback!=null)
|
||||
else if (fallback != null)
|
||||
selectActor(fallback);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void selectNextLeft() {
|
||||
if(getSelected()==null)
|
||||
{
|
||||
if (getSelected() == null) {
|
||||
selectFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
Selectable current =getSelected();
|
||||
Array<Selectable> candidates=new Array<>();
|
||||
for(Selectable selectable:visibleSelection())
|
||||
{
|
||||
if(selectable.yDiff(current)<0.1&&selectable!=current)
|
||||
} else {
|
||||
Selectable current = getSelected();
|
||||
Array<Selectable> candidates = new Array<>();
|
||||
for (Selectable selectable : visibleSelection()) {
|
||||
if (selectable.yDiff(current) < 0.1 && selectable != current)
|
||||
candidates.add(selectable);
|
||||
}
|
||||
if(candidates.isEmpty())
|
||||
if (candidates.isEmpty())
|
||||
candidates.addAll(visibleSelection());
|
||||
Selectable finalOne=null;
|
||||
Selectable fallback=null;
|
||||
for(Selectable candidate:candidates)
|
||||
{
|
||||
if(fallback==null||candidate.getX()>fallback.getX())
|
||||
fallback=candidate;
|
||||
if(candidate.getX()<current.getX()&&(finalOne==null||current.xDiff(candidate)<current.xDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
Selectable finalOne = null;
|
||||
Selectable fallback = null;
|
||||
for (Selectable candidate : candidates) {
|
||||
if (fallback == null || candidate.getX() > fallback.getX())
|
||||
fallback = candidate;
|
||||
if (candidate.getX() < current.getX() && (finalOne == null || current.xDiff(candidate) < current.xDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne==null)
|
||||
for(Selectable candidate:visibleSelection())
|
||||
{
|
||||
if(candidate.getX()<current.getX()&&(finalOne==null||current.xDiff(candidate)<current.xDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
if (finalOne == null)
|
||||
for (Selectable candidate : visibleSelection()) {
|
||||
if (candidate.getX() < current.getX() && (finalOne == null || current.xDiff(candidate) < current.xDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne!=null)
|
||||
if (finalOne != null)
|
||||
selectActor(finalOne);
|
||||
else if(fallback!=null)
|
||||
else if (fallback != null)
|
||||
selectActor(fallback);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void selectNextRight() {
|
||||
if(getSelected()==null)
|
||||
{
|
||||
if (getSelected() == null) {
|
||||
selectFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
Selectable current =getSelected();
|
||||
Array<Selectable> candidates=new Array<>();
|
||||
for(Selectable selectable:visibleSelection())
|
||||
{
|
||||
if(selectable.yDiff(current)<0.1&&selectable!=current)
|
||||
} else {
|
||||
Selectable current = getSelected();
|
||||
Array<Selectable> candidates = new Array<>();
|
||||
for (Selectable selectable : visibleSelection()) {
|
||||
if (selectable.yDiff(current) < 0.1 && selectable != current)
|
||||
candidates.add(selectable);
|
||||
}
|
||||
if(candidates.isEmpty())
|
||||
if (candidates.isEmpty())
|
||||
candidates.addAll(visibleSelection());
|
||||
Selectable finalOne=null;
|
||||
Selectable fallback=null;
|
||||
for(Selectable candidate:candidates)
|
||||
{
|
||||
if(fallback==null||candidate.getX()<fallback.getX())
|
||||
fallback=candidate;
|
||||
if(candidate.getX()>current.getX()&&(finalOne==null||current.xDiff(candidate)<current.xDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
Selectable finalOne = null;
|
||||
Selectable fallback = null;
|
||||
for (Selectable candidate : candidates) {
|
||||
if (fallback == null || candidate.getX() < fallback.getX())
|
||||
fallback = candidate;
|
||||
if (candidate.getX() > current.getX() && (finalOne == null || current.xDiff(candidate) < current.xDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne==null)
|
||||
for(Selectable candidate:visibleSelection())
|
||||
{
|
||||
if(candidate.getX()>current.getX()&&(finalOne==null||current.xDiff(candidate)<current.xDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
if (finalOne == null)
|
||||
for (Selectable candidate : visibleSelection()) {
|
||||
if (candidate.getX() > current.getX() && (finalOne == null || current.xDiff(candidate) < current.xDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne!=null)
|
||||
if (finalOne != null)
|
||||
selectActor(finalOne);
|
||||
else if(fallback!=null)
|
||||
else if (fallback != null)
|
||||
selectActor(fallback);
|
||||
|
||||
}
|
||||
@@ -571,43 +538,35 @@ public class UIScene extends Scene {
|
||||
|
||||
public void selectNextUp() {
|
||||
|
||||
if(getSelected()==null)
|
||||
{
|
||||
if (getSelected() == null) {
|
||||
selectFirst();
|
||||
}
|
||||
else
|
||||
{
|
||||
Selectable current =getSelected();
|
||||
Array<Selectable> candidates=new Array<>();
|
||||
for(Selectable selectable:visibleSelection())
|
||||
{
|
||||
if(selectable.xDiff(current)<0.1&&selectable!=current)
|
||||
} else {
|
||||
Selectable current = getSelected();
|
||||
Array<Selectable> candidates = new Array<>();
|
||||
for (Selectable selectable : visibleSelection()) {
|
||||
if (selectable.xDiff(current) < 0.1 && selectable != current)
|
||||
candidates.add(selectable);
|
||||
}
|
||||
if(candidates.isEmpty())
|
||||
if (candidates.isEmpty())
|
||||
candidates.addAll(visibleSelection());
|
||||
Selectable finalOne=null;
|
||||
Selectable fallback=null;
|
||||
for(Selectable candidate:candidates)
|
||||
{
|
||||
if(fallback==null||candidate.getY()<fallback.getY())
|
||||
fallback=candidate;
|
||||
if(candidate.getY()>current.getY()&&(finalOne==null||current.yDiff(candidate)<current.yDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
Selectable finalOne = null;
|
||||
Selectable fallback = null;
|
||||
for (Selectable candidate : candidates) {
|
||||
if (fallback == null || candidate.getY() < fallback.getY())
|
||||
fallback = candidate;
|
||||
if (candidate.getY() > current.getY() && (finalOne == null || current.yDiff(candidate) < current.yDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne==null)//allowAllNow
|
||||
for(Selectable candidate:visibleSelection())
|
||||
{
|
||||
if(candidate.getY()>current.getY()&&(finalOne==null||current.yDiff(candidate)<current.yDiff(finalOne)))
|
||||
{
|
||||
finalOne=candidate;
|
||||
if (finalOne == null)//allowAllNow
|
||||
for (Selectable candidate : visibleSelection()) {
|
||||
if (candidate.getY() > current.getY() && (finalOne == null || current.yDiff(candidate) < current.yDiff(finalOne))) {
|
||||
finalOne = candidate;
|
||||
}
|
||||
}
|
||||
if(finalOne!=null)
|
||||
if (finalOne != null)
|
||||
selectActor(finalOne);
|
||||
else if(fallback!=null)
|
||||
else if (fallback != null)
|
||||
selectActor(fallback);
|
||||
|
||||
}
|
||||
@@ -615,22 +574,18 @@ public class UIScene extends Scene {
|
||||
|
||||
private void selectFirst() {
|
||||
|
||||
Selectable result=null;
|
||||
for(Selectable candidate: getPossibleSelection())
|
||||
{
|
||||
if(result==null|| candidate.getY()>result.getY())
|
||||
{
|
||||
result=candidate;
|
||||
Selectable result = null;
|
||||
for (Selectable candidate : getPossibleSelection()) {
|
||||
if (result == null || candidate.getY() > result.getY()) {
|
||||
result = candidate;
|
||||
}
|
||||
}
|
||||
selectActor(result);
|
||||
}
|
||||
ScrollPane scrollPaneOfActor(Actor actor)
|
||||
{
|
||||
while (actor!=null)
|
||||
{
|
||||
if(actor.getParent() instanceof ScrollPane)
|
||||
{
|
||||
|
||||
ScrollPane scrollPaneOfActor(Actor actor) {
|
||||
while (actor != null) {
|
||||
if (actor.getParent() instanceof ScrollPane) {
|
||||
return (ScrollPane) actor.getParent();
|
||||
}
|
||||
actor = actor.getParent();
|
||||
@@ -641,16 +596,16 @@ public class UIScene extends Scene {
|
||||
public void selectActor(Selectable actor) {
|
||||
|
||||
|
||||
unselectActors();
|
||||
if(actor==null)return;
|
||||
stage.setKeyboardFocus(actor.actor);
|
||||
ScrollPane scrollPane=scrollPaneOfActor(actor.actor);
|
||||
if(scrollPane!=null)
|
||||
{
|
||||
scrollPane.scrollTo(actor.actor.getX(),actor.actor.getY(),actor.actor.getWidth(),actor.actor.getHeight(),false,false);
|
||||
}
|
||||
actor.onSelect(this);
|
||||
unselectActors();
|
||||
if (actor == null) return;
|
||||
stage.setKeyboardFocus(actor.actor);
|
||||
ScrollPane scrollPane = scrollPaneOfActor(actor.actor);
|
||||
if (scrollPane != null) {
|
||||
scrollPane.scrollTo(actor.actor.getX(), actor.actor.getY(), actor.actor.getWidth(), actor.actor.getHeight(), false, false);
|
||||
}
|
||||
actor.onSelect(this);
|
||||
}
|
||||
|
||||
Image screenImage;
|
||||
TextureRegion backgroundTexture;
|
||||
|
||||
@@ -659,6 +614,7 @@ public class UIScene extends Scene {
|
||||
stage.cancelTouchFocus();
|
||||
return super.leave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enter() {
|
||||
if (screenImage != null) {
|
||||
@@ -674,6 +630,7 @@ public class UIScene extends Scene {
|
||||
Gdx.input.setInputProcessor(stage);
|
||||
super.enter();
|
||||
}
|
||||
|
||||
public TextureRegion getUIBackground() {
|
||||
try {
|
||||
Actor a = ui.getChild(0);
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.adventure.stage;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input;
|
||||
import com.badlogic.gdx.audio.Music;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
@@ -33,8 +35,11 @@ import forge.adventure.world.WorldSave;
|
||||
import forge.deck.Deck;
|
||||
import forge.gui.FThreads;
|
||||
import forge.gui.GuiBase;
|
||||
import forge.localinstance.properties.ForgePreferences;
|
||||
import forge.model.FModel;
|
||||
import forge.sound.MusicPlaylist;
|
||||
import forge.sound.SoundSystem;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
/**
|
||||
* Stage to handle everything rendered in the HUD
|
||||
@@ -275,7 +280,10 @@ public class GameHUD extends Stage {
|
||||
updatelife = false;
|
||||
lifePoints.setText("[%95][+Life]" + lifepointsTextColor + " " + AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife());
|
||||
}
|
||||
updateMusic();
|
||||
if (!GameScene.instance().isNotInWorldMap())
|
||||
updateMusic();
|
||||
else
|
||||
SoundSystem.instance.pause();
|
||||
}
|
||||
|
||||
Texture miniMapTexture;
|
||||
@@ -301,7 +309,122 @@ public class GameHUD extends Stage {
|
||||
} else {
|
||||
deckActor.setColor(menuActor.getColor());
|
||||
}
|
||||
updateMusic();
|
||||
if (GameScene.instance().isNotInWorldMap()) {
|
||||
SoundSystem.instance.pause();
|
||||
playAudio();
|
||||
} else {
|
||||
unloadAudio();
|
||||
SoundSystem.instance.resume(); // resume World BGM
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<FileHandle, Music> audio = null;
|
||||
|
||||
public void playAudio() {
|
||||
switch (GameScene.instance().getAdventurePlayerLocation(false, false)) {
|
||||
case "capital":
|
||||
case "town":
|
||||
setAudio(MusicPlaylist.TOWN);
|
||||
break;
|
||||
case "dungeon":
|
||||
case "cave":
|
||||
setAudio(MusicPlaylist.CAVE);
|
||||
break;
|
||||
case "castle":
|
||||
setAudio(MusicPlaylist.CASTLE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (audio != null) {
|
||||
audio.getRight().setLooping(true);
|
||||
audio.getRight().play();
|
||||
audio.getRight().setVolume(FModel.getPreferences().getPrefInt(ForgePreferences.FPref.UI_VOL_MUSIC) / 100f);
|
||||
}
|
||||
}
|
||||
|
||||
public void fadeAudio(float value) {
|
||||
if (audio != null) {
|
||||
audio.getRight().setVolume((FModel.getPreferences().getPrefInt(ForgePreferences.FPref.UI_VOL_MUSIC) * value) / 100f);
|
||||
}
|
||||
}
|
||||
|
||||
float fade = 1f;
|
||||
|
||||
void fadeIn() {
|
||||
if (fade >= 1f)
|
||||
return;
|
||||
for (int i = 10; i > 1; i--) {
|
||||
float delay = i * 0.1f;
|
||||
Timer.schedule(new Timer.Task() {
|
||||
@Override
|
||||
public void run() {
|
||||
fade += 0.1f;
|
||||
if (fade > 1f)
|
||||
fade = 1f;
|
||||
fadeAudio(fade);
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
}
|
||||
|
||||
void fadeOut() {
|
||||
for (int i = 10; i > 1; i--) {
|
||||
float delay = i * 0.1f;
|
||||
Timer.schedule(new Timer.Task() {
|
||||
@Override
|
||||
public void run() {
|
||||
fade -= 0.1f;
|
||||
if (fade < 0.1f)
|
||||
fade = 0.1f;
|
||||
fadeAudio(fade);
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopAudio() {
|
||||
if (audio != null) {
|
||||
audio.getRight().stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void pauseMusic() {
|
||||
if (audio != null) {
|
||||
audio.getRight().pause();
|
||||
}
|
||||
SoundSystem.instance.pause();
|
||||
}
|
||||
|
||||
public void unloadAudio() {
|
||||
if (audio != null) {
|
||||
audio.getRight().setOnCompletionListener(null);
|
||||
audio.getRight().stop();
|
||||
Forge.getAssets().manager().unload(audio.getLeft().path());
|
||||
}
|
||||
audio = null;
|
||||
currentAudioPlaylist = null;
|
||||
}
|
||||
|
||||
private MusicPlaylist currentAudioPlaylist = null;
|
||||
|
||||
private void setAudio(MusicPlaylist playlist) {
|
||||
if (playlist.equals(currentAudioPlaylist))
|
||||
return;
|
||||
unloadAudio();
|
||||
audio = getMusic(playlist);
|
||||
}
|
||||
|
||||
private Pair<FileHandle, Music> getMusic(MusicPlaylist playlist) {
|
||||
FileHandle file = Gdx.files.absolute(playlist.getNewRandomFilename());
|
||||
Music music = Forge.getAssets().getMusic(file);
|
||||
if (music != null) {
|
||||
currentAudioPlaylist = playlist;
|
||||
return Pair.of(file, music);
|
||||
} else {
|
||||
currentAudioPlaylist = null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void openDeck() {
|
||||
@@ -580,17 +703,6 @@ public class GameHUD extends Stage {
|
||||
case "white":
|
||||
changeBGM(MusicPlaylist.WHITE);
|
||||
break;
|
||||
case "capital":
|
||||
case "town":
|
||||
changeBGM(MusicPlaylist.TOWN);
|
||||
break;
|
||||
case "dungeon":
|
||||
case "cave":
|
||||
changeBGM(MusicPlaylist.CAVE);
|
||||
break;
|
||||
case "castle":
|
||||
changeBGM(MusicPlaylist.CASTLE);
|
||||
break;
|
||||
case "waste":
|
||||
changeBGM(MusicPlaylist.MENUS);
|
||||
break;
|
||||
@@ -598,7 +710,6 @@ public class GameHUD extends Stage {
|
||||
break;
|
||||
}
|
||||
}
|
||||
float fade = 1f;
|
||||
|
||||
void changeBGM(MusicPlaylist playlist) {
|
||||
if (!playlist.equals(SoundSystem.instance.getCurrentPlaylist())) {
|
||||
|
||||
@@ -63,30 +63,6 @@ public class MapSprite extends Actor {
|
||||
return actorGroup;
|
||||
}
|
||||
|
||||
public static String getBoundaryName(int chunkX, int chunkY) {
|
||||
String boundary = "";
|
||||
List<PointOfInterest> poi = WorldSave.getCurrentSave().getWorld().getPointsOfInterest(chunkX, chunkY);
|
||||
|
||||
for (PointOfInterest p : poi) {
|
||||
if ("town".equalsIgnoreCase(p.getData().type)) {
|
||||
if (p.getData().name.startsWith("Waste"))
|
||||
boundary = "waste";
|
||||
else if (p.getData().name.startsWith("Plains"))
|
||||
boundary = "white";
|
||||
else if (p.getData().name.startsWith("Forest"))
|
||||
boundary = "green";
|
||||
else if (p.getData().name.startsWith("Island"))
|
||||
boundary = "blue";
|
||||
else if (p.getData().name.startsWith("Mountain"))
|
||||
boundary = "red";
|
||||
else if (p.getData().name.startsWith("Swamp"))
|
||||
boundary = "black";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return boundary;
|
||||
}
|
||||
|
||||
//BitmapFont font;
|
||||
@Override
|
||||
public void draw(Batch batch, float parentAlpha) {
|
||||
|
||||
@@ -294,12 +294,6 @@ public class WorldStage extends GameStage implements SaveFileContent {
|
||||
background.loadChunk(pos.x, pos.y);
|
||||
handlePointsOfInterestCollision();
|
||||
}
|
||||
public String getBoundary() {
|
||||
if (background == null)
|
||||
return "";
|
||||
GridPoint2 pos = background.translateFromWorldToChunk(player.getX(), player.getY());
|
||||
return MapSprite.getBoundaryName(pos.x, pos.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leave() {
|
||||
|
||||
@@ -648,7 +648,9 @@ public class CardUtil {
|
||||
FileHandle handle = Config.instance().getFile(path);
|
||||
if (handle.exists())
|
||||
return generateDeck(json.fromJson(GeneratedDeckData.class, handle), starterEdition, discourageDuplicates);
|
||||
return null;
|
||||
Deck deck = DeckgenUtil.getRandomOrPreconOrThemeDeck(colors, true, false, true);
|
||||
System.err.println("Error loading JSON: " + handle.path() + "\nGenerating random deck: "+deck.getName());
|
||||
return deck;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ import com.github.tommyettinger.textra.TypingLabel;
|
||||
import forge.Forge;
|
||||
import forge.adventure.player.AdventurePlayer;
|
||||
import forge.card.ColorSet;
|
||||
import forge.sound.SoundEffectType;
|
||||
import forge.sound.SoundSystem;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -52,6 +54,13 @@ public class Controls {
|
||||
static class TextButtonFix extends TextraButton {
|
||||
public TextButtonFix(@Null String text) {
|
||||
super(text == null ? "NULL" : text, Controls.getSkin(), Controls.getTextraFont());
|
||||
addListener(new ClickListener(){
|
||||
@Override
|
||||
public void clicked(InputEvent event, float x, float y) {
|
||||
super.clicked(event, x, y);
|
||||
SoundSystem.instance.play(SoundEffectType.ButtonPress, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,6 +83,7 @@ public class Controls {
|
||||
getTextraLabel().setWidth(getTextraLabel().layout.getWidth() + (getTextraLabel().style != null && getTextraLabel().style.background != null ? getTextraLabel().style.background.getLeftWidth() + getTextraLabel().style.background.getRightWidth() : 0.0F));
|
||||
layout();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static public TextraButton newTextButton(String text) {
|
||||
|
||||
@@ -15,11 +15,11 @@ import forge.Forge;
|
||||
import forge.adventure.character.EnemySprite;
|
||||
import forge.adventure.data.DialogData;
|
||||
import forge.adventure.player.AdventurePlayer;
|
||||
import forge.adventure.stage.GameHUD;
|
||||
import forge.adventure.stage.MapStage;
|
||||
import forge.card.ColorSet;
|
||||
import forge.localinstance.properties.ForgePreferences;
|
||||
import forge.model.FModel;
|
||||
import forge.sound.SoundSystem;
|
||||
import forge.util.Localizer;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
@@ -196,7 +196,7 @@ public class MapDialog {
|
||||
fade += 0.1f;
|
||||
if (fade > 1f)
|
||||
fade = 1f;
|
||||
SoundSystem.instance.fadeModifier(fade);
|
||||
GameHUD.getInstance().fadeAudio(fade);
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
@@ -211,7 +211,7 @@ public class MapDialog {
|
||||
fade -= 0.1f;
|
||||
if (fade < 0.1f)
|
||||
fade = 0.1f;
|
||||
SoundSystem.instance.fadeModifier(fade);
|
||||
GameHUD.getInstance().fadeAudio(fade);
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ import forge.card.CardRenderer;
|
||||
import forge.game.card.CardView;
|
||||
import forge.gui.GuiBase;
|
||||
import forge.item.PaperCard;
|
||||
import forge.sound.SoundEffectType;
|
||||
import forge.sound.SoundSystem;
|
||||
import forge.util.ImageFetcher;
|
||||
import forge.util.ImageUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -593,6 +595,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
|
||||
return;
|
||||
clicked = true;
|
||||
flipProcess = 0;
|
||||
SoundSystem.instance.play(SoundEffectType.FlipCard, false);
|
||||
}
|
||||
|
||||
public void sold() {
|
||||
@@ -608,7 +611,7 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb
|
||||
super.act(delta);
|
||||
if (clicked) {
|
||||
if (flipProcess < 1)
|
||||
flipProcess += delta * 1.5;
|
||||
flipProcess += delta * 2.4;
|
||||
else
|
||||
flipProcess = 1;
|
||||
|
||||
|
||||
@@ -238,6 +238,14 @@ public class World implements Disposable, SaveFileContent {
|
||||
}
|
||||
}
|
||||
|
||||
public long getBiomeMapXY(int x, int y) {
|
||||
try {
|
||||
return biomeMap[x][height - y - 1] & (~(0b1<<data.GetBiomes().size()));
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
return biomeMap[biomeMap.length - 1][biomeMap[biomeMap.length - 1].length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStructure(int x, int y) {
|
||||
try {
|
||||
return (terrainMap[x][height - y - 1] & ~isStructureBit) != 0;
|
||||
|
||||
@@ -558,7 +558,8 @@ public class Assets implements Disposable {
|
||||
|
||||
@Override
|
||||
public synchronized void unload(String fileName) {
|
||||
super.unload(fileName);
|
||||
if (isLoaded(fileName))
|
||||
super.unload(fileName);
|
||||
if (memoryPerFile.containsKey(fileName)) {
|
||||
memoryPerFile.remove(fileName);
|
||||
cardArtCache().clear();
|
||||
|
||||
@@ -236,6 +236,8 @@ public class CardImageRenderer {
|
||||
g.drawOutlinedText(artist, TEXT_FONT, Color.WHITE, Color.DARK_GRAY, x + (TYPE_FONT.getCapHeight() / 2), y + (TYPE_FONT.getCapHeight() / 2), w, h, false, Align.left, false);
|
||||
}
|
||||
private static void drawOutlineColor(Graphics g, ColorSet colors, float x, float y, float w, float h) {
|
||||
if (colors == null)
|
||||
return;
|
||||
switch (colors.countColors()) {
|
||||
case 0:
|
||||
g.drawRect(BORDER_THICKNESS*2, Color.valueOf("#A0A6A4"), x, y, w, h);
|
||||
@@ -264,7 +266,8 @@ public class CardImageRenderer {
|
||||
fillColorBackground(g, colors, x, y, w, h);
|
||||
g.setAlphaComposite(oldAlpha);
|
||||
//draw outline color here
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
if (state != null)
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
|
||||
|
||||
float padding = h / 8;
|
||||
@@ -450,7 +453,8 @@ public class CardImageRenderer {
|
||||
fillColorBackground(g, colors, x, y, w, h);
|
||||
g.setAlphaComposite(oldAlpha);
|
||||
//draw outline color here
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
if (state != null)
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
|
||||
|
||||
float padding = h / 8;
|
||||
@@ -619,7 +623,8 @@ public class CardImageRenderer {
|
||||
}
|
||||
}
|
||||
//draw outline color here
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
if (state != null)
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
|
||||
|
||||
if (!onTop) {
|
||||
@@ -738,7 +743,8 @@ public class CardImageRenderer {
|
||||
|
||||
fillColorBackground(g, colors, x, y, w, h);
|
||||
//draw outline color here
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
if (state != null)
|
||||
drawOutlineColor(g, state.getColors(), x, y, w, h);
|
||||
g.drawRect(BORDER_THICKNESS, Color.BLACK, x, y, w, h);
|
||||
|
||||
if (noText)
|
||||
|
||||
@@ -30,7 +30,8 @@ public class AudioMusic implements IAudioMusic {
|
||||
public void pause() {
|
||||
if (music == null)
|
||||
return;
|
||||
music.pause();
|
||||
if (music.isPlaying())
|
||||
music.pause();
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Enchantment
|
||||
S:Mode$ ReduceCost | ValidCard$ Card | ValidSpell$ Activated.Equip | Activator$ You | Amount$ 1 | EffectZone$ Command | Description$ Equip costs you pay cost {1} less.
|
||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Secondary$ True | Execute $ TrigConjure | TriggerDescription$ At the beginning of your upkeep or when an equipped creature you control attacks, conjure a card from Nahiri's Spellbook into your hand.
|
||||
T:Mode$ Attacks | ValidCard$ Creature.YouCtrl+equipped | TriggerZones$ Command | Execute$ TrigConjure | TriggerDescription$ At the beginning of your upkeep or when an equipped creature you control attacks, conjure a card from Nahiri's Spellbook into your hand.
|
||||
SVar:TrigConjure:DB$ MakeCard | Zone$ Hand | Conjure$ True | AtRandom$ True | Spellbook$ Stoneforge Mystic,Danitha; Benalia's Hope,Ardenn, Intrepid Archaeologist,Open the Armory,Stone Haven Outfitter,Argentum Armor,Sword of the Animist,Masterwork of Ingenuity,Kaldra Compleat,Armored Skyhunter,Lion Sash,Relic Seeker,Esper Sentinel,Forgeborn Phoenix,Foundry Beetle,Inchblade Companion,Komainu Battle Armor,Luxior;Giada's Gift,Mace of Disruption,Nettlecyst,Shadowspear,Seraphic Greatsword,Soulstealer Axe,Sword of Body and Mind,Sword of Fire and Ice,Junkyard Scrapper,Soulstealer Axe,Sword of Feast and Famine,Expedition Supplier,Foundry Beetle,Armory Automaton,Bladegraft Aspirant,Dancing Sword,Jor Kadeen; First Goldwarden,Akiri; Fearless Voyager,Acclaimed Contender,Embercleave,Puresteel Paladin,Champion of the Flame,Tiana; Ship's Caretaker,Reyav; Master Smith,Sigarda's Aid,Armored Skyhunter,Bruenor Battlehammer,Halvar; God of Battle,Wyleth; Soul of Steel,Koll; the Forgemaster,Valduk; Keeper of the Flame,Fervent Champion,Cloudsteel Kirin,Leonin Shikari,Balan; Wandering Knight,Kor Duelist,Leonin Abunas,Zamriel;Seraph of Steel,Auriok Steelshaper
|
||||
SVar:TrigConjure:DB$ MakeCard | Zone$ Hand | Conjure$ True | AtRandom$ True | Spellbook$ Stoneforge Mystic,Danitha; Benalia's Hope,Ardenn; Intrepid Archaeologist,Open the Armory,Stone Haven Outfitter,Argentum Armor,Sword of the Animist,Masterwork of Ingenuity,Kaldra Compleat,Armored Skyhunter,Lion Sash,Relic Seeker,Esper Sentinel,Forgeborn Phoenix,Foundry Beetle,Inchblade Companion,Komainu Battle Armor,Luxior;Giada's Gift,Mace of Disruption,Nettlecyst,Shadowspear,Seraphic Greatsword,Soulstealer Axe,Sword of Body and Mind,Sword of Fire and Ice,Junkyard Scrapper,Soulstealer Axe,Sword of Feast and Famine,Expedition Supplier,Foundry Beetle,Armory Automaton,Bladegraft Aspirant,Dancing Sword,Jor Kadeen; First Goldwarden,Akiri; Fearless Voyager,Acclaimed Contender,Embercleave,Puresteel Paladin,Champion of the Flame,Tiana; Ship's Caretaker,Reyav; Master Smith,Sigarda's Aid,Armored Skyhunter,Bruenor Battlehammer,Halvar; God of Battle,Wyleth; Soul of Steel,Koll; the Forgemaster,Valduk; Keeper of the Flame,Fervent Champion,Cloudsteel Kirin,Leonin Shikari,Balan; Wandering Knight,Kor Duelist,Leonin Abunas,Zamriel; Seraph of Steel,Auriok Steelshaper
|
||||
T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, create a 1/1 white Kor Soldier creature token
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_kor_soldier
|
||||
Oracle:Equip costs you pay cost {1} less.\nAt the beginning of your upkeep or whenever an equipped creature you control attacks, conjure a card from Nahiri's Spellbook into your hand\nAt the beginning of your end step, create a 1/1 white Kor Soldier creature token.
|
||||
12
forge-gui/res/adventure/Shandalar/decks/fungus.json
Normal file
12
forge-gui/res/adventure/Shandalar/decks/fungus.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name":"Fungus",
|
||||
"template":
|
||||
{
|
||||
"count":60,
|
||||
"colors":["Green","Black"],
|
||||
"tribe":"Fungus",
|
||||
"tribeCards":1.0,
|
||||
"tribeSynergyCards":0.2,
|
||||
"rares":0.2
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,13 @@
|
||||
"height": 4300,
|
||||
"width": 2
|
||||
},
|
||||
"activeFile": "",
|
||||
"activeFile": "map/cave_6.tmx",
|
||||
"automapping.whileDrawing": false,
|
||||
"expandedProjectPaths": [
|
||||
"tileset",
|
||||
"map/main_story",
|
||||
"map",
|
||||
"obj"
|
||||
"obj",
|
||||
"map/main_story",
|
||||
"tileset"
|
||||
],
|
||||
"file.lastUsedOpenFilter": "All Files (*)",
|
||||
"fileStates": {
|
||||
@@ -110,24 +110,24 @@
|
||||
"scale": 3,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 279.5,
|
||||
"y": 217.5
|
||||
"x": 240,
|
||||
"y": 136.16666666666663
|
||||
}
|
||||
},
|
||||
"map/castle_plains_2.tmx": {
|
||||
"scale": 1.5,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 359.66666666666663,
|
||||
"y": 295.33333333333326
|
||||
"x": 240,
|
||||
"y": 136.33333333333334
|
||||
}
|
||||
},
|
||||
"map/castle_plains_3.tmx": {
|
||||
"scale": 2,
|
||||
"selectedLayer": 4,
|
||||
"selectedLayer": 3,
|
||||
"viewCenter": {
|
||||
"x": 240,
|
||||
"y": 136
|
||||
"y": 136.25
|
||||
}
|
||||
},
|
||||
"map/catlair_1.tmx": {
|
||||
@@ -174,8 +174,8 @@
|
||||
"scale": 4,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 240,
|
||||
"y": 239.875
|
||||
"x": 187.5,
|
||||
"y": 316.625
|
||||
}
|
||||
},
|
||||
"map/cave_1.tmx": {
|
||||
@@ -428,8 +428,8 @@
|
||||
"scale": 2,
|
||||
"selectedLayer": 4,
|
||||
"viewCenter": {
|
||||
"x": 240.25,
|
||||
"y": 136
|
||||
"x": 135,
|
||||
"y": 119.75
|
||||
}
|
||||
},
|
||||
"map/cave_20.tmx": {
|
||||
@@ -1356,16 +1356,19 @@
|
||||
"scale": 2,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 240.25,
|
||||
"y": 136
|
||||
"x": 240,
|
||||
"y": 136.25
|
||||
}
|
||||
},
|
||||
"map/cave_4.tmx": {
|
||||
"scale": 1,
|
||||
"selectedLayer": 2,
|
||||
"expandedObjectLayers": [
|
||||
4
|
||||
],
|
||||
"scale": 2,
|
||||
"selectedLayer": 3,
|
||||
"viewCenter": {
|
||||
"x": 220,
|
||||
"y": 135
|
||||
"x": 145,
|
||||
"y": 151.75
|
||||
}
|
||||
},
|
||||
"map/cave_5.tmx": {
|
||||
@@ -1373,15 +1376,15 @@
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 232,
|
||||
"y": 136
|
||||
"y": 136.25
|
||||
}
|
||||
},
|
||||
"map/cave_6.tmx": {
|
||||
"scale": 2,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 232,
|
||||
"y": 136
|
||||
"x": 337,
|
||||
"y": 152.75
|
||||
}
|
||||
},
|
||||
"map/cave_6N1.tmx": {
|
||||
@@ -3206,10 +3209,10 @@
|
||||
4
|
||||
],
|
||||
"scale": 2,
|
||||
"selectedLayer": 4,
|
||||
"selectedLayer": 0,
|
||||
"viewCenter": {
|
||||
"x": 390.5,
|
||||
"y": 221.75
|
||||
"x": 329.5,
|
||||
"y": 204.25
|
||||
}
|
||||
},
|
||||
"map/yule_town.tmx": {
|
||||
@@ -3251,22 +3254,31 @@
|
||||
"map.tileWidth": 16,
|
||||
"map.width": 90,
|
||||
"openFiles": [
|
||||
"map/xira.tmx",
|
||||
"map/castle_plains_1.tmx",
|
||||
"map/castle_plains_2.tmx",
|
||||
"map/castle_plains_3.tmx",
|
||||
"map/cave_2.tmx",
|
||||
"map/cave_3.tmx",
|
||||
"map/cave_4.tmx",
|
||||
"map/cave_5.tmx",
|
||||
"map/cave_6.tmx"
|
||||
],
|
||||
"project": "main.tiled-project",
|
||||
"property.type": "string",
|
||||
"recentFiles": [
|
||||
"map/main_story/templeofchandra.tmx",
|
||||
"map/tibalt.tmx",
|
||||
"map/tibalt_f1.tmx",
|
||||
"map/xira.tmx",
|
||||
"map/nahiricave.tmx",
|
||||
"map/nahiri.tmx",
|
||||
"map/grolnok.tmx",
|
||||
"map/tibalt_f2.tmx",
|
||||
"map/cursed_swamp.tmx",
|
||||
"map/slobad_factory.tmx",
|
||||
"map/main_story/blue_castle_f1.tmx",
|
||||
"map/kiora_island.tmx"
|
||||
"map/castle_plains_1.tmx",
|
||||
"map/castle_plains_2.tmx",
|
||||
"map/castle_plains_3.tmx",
|
||||
"map/cave_2.tmx",
|
||||
"map/cave_3.tmx",
|
||||
"map/cave_4.tmx",
|
||||
"map/cave_5.tmx",
|
||||
"map/cave_6.tmx",
|
||||
"map/cave_1..tmx",
|
||||
"map/main_story/templeofchandra.tmx",
|
||||
"map/tibalt.tmx"
|
||||
],
|
||||
"resizeMap.removeObjects": true,
|
||||
"textEdit.monospace": true
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<tileset firstgid="10113" source="../tileset/buildings.tsx"/>
|
||||
<layer id="11" name="Collision" width="40" height="26">
|
||||
<data encoding="base64" compression="zlib">
|
||||
eJzVlUkOgCAMRdl6Me9/JFcmhkCHP2hswgp++0pbOI8xzh+tlb2lj3SIVbURRyevbtz7LGORPspJ4b+i/ZIv85P1oKK2We9UOJ+aiI+ZlZ3fynxX+Jxs816kc/KtajHzIf5Ud6c2BZ8rN0fvKQydLSbeM+7M4GBD3l12ddm6+VffPwVfplH1DlNf9M9C4nT/N3aeunF2nNFfhDJltXfNDcOInGHjZ+cqewo+5/2z86uu/8p/961w9ucuhnsxDBe0OnBV
|
||||
eJzVl11uwkAMhHnMPsBtegWKckDOgNqehjOgwjHIKrLqjDz+WZUHRhopJNn1F6/3h2Pb7Y5v5NPi7+nPXZX2uq12tq2WfuYpionfg0IO65nV1sqdvh9pTr53a1sjQ+a7Ti3XZoSPSWLflbN8+NviiPgidhy/DB/jxVhz8+tAP2Pv4Liz2hQei81jZHPCm6OePD6PDd+NYjCmbL4rfJU84JhafDh/u9j6lGWTa0vn/WqMgzG99ZGpwhf18XGoxa6yZfis2rweVr+Sy1tTIr5MPN0f67vCZvWB7BHTf9tbVzSflY8Kl9SD5VG+aNwz+cvUqWbFfrJ8LHcsjrBpXabVkTAXbMxG1h3Nqpku6twYcbJ9ITN3qvJq65PUDzLgPTlXjKwrFcYMX/fXkuufactm7ZeZ+Jb6WEv/3p7LWHueZnXNpM+60XpiKbsPsxpj7YULc47nzJHcix7kO3/b9n+AZdZOz03L7DvRjO3V9sYt8hMoNu4z
|
||||
</data>
|
||||
</layer>
|
||||
<layer id="8" name="Background" width="40" height="26">
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -130,7 +130,7 @@ WalkDown
|
||||
xy: 144, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 160, 0
|
||||
xy: 160, 16
|
||||
size: 16, 16
|
||||
WalkDown
|
||||
xy: 176, 16
|
||||
|
||||
@@ -351,7 +351,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 6
|
||||
"addMaxCount": 6,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -1241,12 +1245,16 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 3,
|
||||
"count": 1,
|
||||
"colors": [
|
||||
"Green"
|
||||
],
|
||||
@@ -1330,7 +1338,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 5,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -2830,7 +2842,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 5,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
@@ -3366,7 +3382,7 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -3397,7 +3413,7 @@
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 1,
|
||||
"count": 3,
|
||||
"count": 1,
|
||||
"colors": [
|
||||
"Blue"
|
||||
],
|
||||
@@ -4153,7 +4169,7 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -4471,7 +4487,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -4519,7 +4539,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 5,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -4643,7 +4667,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -5087,7 +5115,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 8,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -6524,7 +6556,7 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -6755,7 +6787,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 6,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
@@ -6794,7 +6830,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
@@ -6802,23 +6842,6 @@
|
||||
"count": 10,
|
||||
"addMaxCount": 90
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 0.5,
|
||||
"count": 2,
|
||||
"colors": [
|
||||
"Green"
|
||||
],
|
||||
"rarity": [
|
||||
"Mythic Rare"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"probability": 1,
|
||||
@@ -7303,7 +7326,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 8,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -7349,7 +7376,7 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -8432,7 +8459,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 4
|
||||
"addMaxCount": 4,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
@@ -9187,7 +9218,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 8,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -9866,7 +9901,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 3,
|
||||
"addMaxCount": 7
|
||||
"addMaxCount": 6,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "gold",
|
||||
@@ -10194,7 +10233,11 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 8,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -10716,7 +10759,7 @@
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 2,
|
||||
"addMaxCount": 8
|
||||
"addMaxCount": 4
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
@@ -11219,18 +11262,11 @@
|
||||
{
|
||||
"type": "deckCard",
|
||||
"probability": 1,
|
||||
"count": 1,
|
||||
"addMaxCount": 4,
|
||||
"count": 2,
|
||||
"addMaxCount": 8,
|
||||
"rarity": [
|
||||
"common",
|
||||
"uncommon"
|
||||
],
|
||||
"cardTypes": [
|
||||
"Creature",
|
||||
"Artifact",
|
||||
"Enchantment",
|
||||
"Instant",
|
||||
"Sorcery"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
"Fox",
|
||||
"Frost Titan",
|
||||
"Griffin",
|
||||
"Horse",
|
||||
"Horseman",
|
||||
"Human",
|
||||
"Human elite",
|
||||
|
||||
BIN
forge-gui/res/adventure/music/boss/boss1.mp3
Normal file
BIN
forge-gui/res/adventure/music/boss/boss1.mp3
Normal file
Binary file not shown.
BIN
forge-gui/res/adventure/music/boss/boss2.mp3
Normal file
BIN
forge-gui/res/adventure/music/boss/boss2.mp3
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -119,3 +119,4 @@ Dominaria Remastered, 3/6/DMR, DMR
|
||||
Phyrexia: All Will Be One, 3/6/ONE, ONE
|
||||
Phyrexia: All Will Be One Jumpstart, -/2/ONE, Meta-Choose(S(ONE Mite-y 1)Mite-y 1;S(ONE Mite-y 2)Mite-y 2;S(ONE Progress 1)Progress 1;S(ONE Progress 2)Progress 2;S(ONE Corruption 1)Corruption 1;S(ONE Corruption 2)Corruption 2;S(ONE Rebellious 1)Rebellious 1;S(ONE Rebellious 2)Rebellious 2;S(ONE Toxic 1)Toxic 1;S(ONE Toxic 2)Toxic 2)Themes
|
||||
Alchemy: Phyrexia, 3/6/ONE, YONE
|
||||
Shadows over Innistrad Remastered, 3/6/SIR, SIR
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Goblin Artificer
|
||||
PT:1/2
|
||||
S:Mode$ Continuous | Affected$ Creature.modified+YouCtrl | AddKeyword$ Menace | Description$ Modified creatures you control have menace.
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, you may discard a card. If you do, seek a card with mana value equal to that card's mana value.
|
||||
SVar:TrigSeek:AB$ ChangeZone | Cost$ Discard<1/Card> | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.cmcEQX | ChangeNum$ 1
|
||||
SVar:TrigSeek:AB$ Seek | Cost$ Discard<1/Card> | Type$ Card.cmcEQX
|
||||
SVar:X:Discarded$CardManaCost
|
||||
DeckHas:Ability$Discard & Keyword$Menace
|
||||
DeckHints:Type$Equipment|Aura & Ability$Counters
|
||||
|
||||
@@ -3,6 +3,8 @@ ManaCost:R G W
|
||||
Types:Creature Elf Druid
|
||||
PT:3/4
|
||||
T:Mode$ ChangesZoneAll | ValidCards$ Creature.Other+YouCtrl | Destination$ Battlefield | TriggerZones$ Battlefield | ActivationLimit$ 1 | Execute$ TrigSeek | TriggerDescription$ Alliance — Whenever one or more other creatures enter the battlefield under your control, seek a land card, then put it onto the battlefield tapped. This ability triggers only once each turn.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Land | ChangeNum$ 1 | Tapped$ True
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Land | RememberFound$ True | SubAbility$ DBPut
|
||||
SVar:DBPut:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ Remembered | Tapped$ True | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:BuffedBy:Creature
|
||||
Oracle:Alliance — Whenever one or more other creatures enter the battlefield under your control, seek a land card, then put it onto the battlefield tapped. This ability triggers only once each turn.
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
Name:Bounty of the Deep
|
||||
ManaCost:2 U
|
||||
Types:Sorcery
|
||||
A:SP$ Branch | BranchConditionSVar$ X | BranchConditionSVarCompare$ GE1 | TrueSubAbility$ Seek2NonLand | FalseSubAbility$ Seek1Land | StackDescription$ SpellDescription | SpellDescription$ If you have no land cards in your hand, seek a land card and a nonland card. Otherwise, seek two nonland cards.
|
||||
SVar:Seek1Land:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.Land | ChangeNum$ 1 | SubAbility$ Seek1NonLand
|
||||
SVar:Seek1NonLand:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.nonLand | ChangeNum$ 1
|
||||
SVar:Seek2NonLand:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.nonLand | ChangeNum$ 2
|
||||
A:SP$ Branch | BranchConditionSVar$ X | BranchConditionSVarCompare$ GE1 | TrueSubAbility$ Seek2 | FalseSubAbility$ Seek1 | StackDescription$ SpellDescription | SpellDescription$ If you have no land cards in your hand, seek a land card and a nonland card. Otherwise, seek two nonland cards.
|
||||
SVar:Seek1:DB$ Seek | Types$ Card.Land,Card.nonLand
|
||||
SVar:Seek2:DB$ Seek | Type$ Card.nonLand | Num$ 2
|
||||
SVar:X:Count$ValidHand Land.YouCtrl
|
||||
Oracle:If you have no land cards in your hand, seek a land card and a nonland card. Otherwise, seek two nonland cards.
|
||||
|
||||
@@ -2,7 +2,9 @@ Name:Cabaretti Revels
|
||||
ManaCost:R R G
|
||||
Types:Enchantment
|
||||
T:Mode$ SpellCast | ValidCard$ Creature | ValidActivatingPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSeek | TriggerDescription$ Whenever you cast a creature spell, seek a creature card with lesser mana value, then put it onto the battlefield.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Creature.cmcLTX
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Creature.cmcLTX | RememberFound$ True | SubAbility$ DBPut
|
||||
SVar:DBPut:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ Remembered | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:X:TriggeredCard$CardManaCost
|
||||
SVar:BuffedBy:Creature
|
||||
Oracle:Whenever you cast a creature spell, seek a creature card with lesser mana value, then put it onto the battlefield.
|
||||
|
||||
@@ -5,9 +5,9 @@ PT:4/5
|
||||
K:Flying
|
||||
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCharm | TriggerDescription$ Whenever CARDNAME attacks or dies, ABILITY
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigCharm | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or dies, ABILITY
|
||||
SVar:TrigCharm:DB$ Charm | CharmNum$ 2 | Choices$ DiscardSeek,DamageTreasures,DamagePump | AdditionalDescription$ Each mode must target a different player.
|
||||
SVar:DiscardSeek:DB$ Discard | ValidTgts$ Player | TargetUnique$ True | TgtPrompt$ Select target player to discard hand and seek | Mode$ Hand | RememberDiscarded$ True | SubAbility$ DBSeek | SpellDescription$ Target player discards all cards in their hand, then seeks that many nonland cards.
|
||||
SVar:DBSeek:DB$ ChangeZone | Defined$ ParentTarget | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ X | ChangeType$ Card.nonLand | SubAbility$ DBCleanup
|
||||
SVar:TrigCharm:DB$ Charm | CharmNum$ 2 | Choices$ DiscardSeek,DamageTreasures,DamagePump | AdditionalDescription$ . Each mode must target a different player.
|
||||
SVar:DiscardSeek:DB$ Discard | ValidTgts$ Player | TargetUnique$ True | Mode$ Hand | RememberDiscarded$ True | SubAbility$ DBSeek | SpellDescription$ Target player discards all cards in their hand, then seeks that many nonland cards.
|
||||
SVar:DBSeek:DB$ Seek | Defined$ Targeted | Num$ X | Type$ Card.nonLand | SubAbility$ DBCleanup
|
||||
SVar:DamageTreasures:DB$ DealDamage | ValidTgts$ Player | TargetUnique$ True | TgtPrompt$ Select target player to take 2 damage and create two Treasures | NumDmg$ 2 | SubAbility$ DBToken | SpellDescription$ CARDNAME deals 2 damage to target player and they create two Treasure tokens.
|
||||
SVar:DBToken:DB$ Token | TokenScript$ c_a_treasure_sac | TokenAmount$ 2 | TokenOwner$ ParentTarget
|
||||
SVar:DamagePump:DB$ DamageAll | ValidTgts$ Player | TargetUnique$ True | NumDmg$ 2 | RememberDamaged$ True | ValidCards$ Creature | ValidDescription$ each creature target player controls. | SubAbility$ DBEffect | SpellDescription$ CARDNAME deals 2 damage to each creature target player controls. Those creatures perpetually get +2/+0.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
Name:Choice of Fortunes
|
||||
ManaCost:2 U
|
||||
Types:Sorcery
|
||||
A:SP$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card | ChangeNum$ 2 | RememberChanged$ True | SubAbility$ DBShuffle | StackDescription$ SpellDescription | SpellDescription$ Seek two cards.
|
||||
A:SP$ Seek | Num$ 2 | RememberFound$ True | SubAbility$ DBShuffle | SpellDescription$ Seek two cards.
|
||||
SVar:DBShuffle:DB$ ChangeZone | Optional$ True | Defined$ Remembered | Origin$ Hand | Destination$ Library | Shuffle$ True | ForgetChanged$ True | SubAbility$ DBSeek | StackDescription$ SpellDescription | SpellDescription$ You may shuffle them into your library.
|
||||
SVar:DBSeek:DB$ ChangeZone | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card | ChangeNum$ 2 | SubAbility$ DBCleanup | StackDescription$ SpellDescription | SpellDescription$ If you do, seek two cards.
|
||||
SVar:DBSeek:DB$ Seek | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | Num$ 2 | SubAbility$ DBCleanup | SpellDescription$ If you do, seek two cards.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | SubAbility$ DBEffect
|
||||
SVar:DBEffect:DB$ Effect | StaticAbilities$ STHandSize | Duration$ Permanent | SpellDescription$ You have no maximum hand size for the rest of the game.
|
||||
SVar:STHandSize:Mode$ Continuous | EffectZone$ Command | Affected$ You | SetMaxHandSize$ Unlimited | Description$ You have no maximum hand size for the rest of the game.
|
||||
|
||||
@@ -5,8 +5,8 @@ PT:3/3
|
||||
T:Mode$ Phase | Phase$ End of Turn | OptionalDecider$ You | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigToken | TriggerDescription$ At the beginning of your end step, you may discard a card. If you do, create a Treasure token and choose ambitious or expedient. If you chose ambitious, seek a card with greater mana value than the discarded card. If you chose expedient, seek a card with lesser mana value than the discarded card.
|
||||
SVar:TrigToken:AB$ Token | Cost$ Discard<1/Card> | TokenScript$ c_a_treasure_sac | SubAbility$ DBChoose
|
||||
SVar:DBChoose:DB$ GenericChoice | Choices$ Ambitious,Expedient | Defined$ You | AILogic$ Random
|
||||
SVar:Ambitious:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.cmcGTX | ChangeNum$ 1 | SpellDescription$ Ambitious - Seek a card with greater mana value than the discarded card.
|
||||
SVar:Expedient:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.cmcLTX | ChangeNum$ 1 | SpellDescription$ Expedient - Seek a card with lesser mana value than the discarded card.
|
||||
SVar:Ambitious:DB$ Seek | Type$ Card.cmcGTX | SpellDescription$ Ambitious - Seek a card with greater mana value than the discarded card.
|
||||
SVar:Expedient:DB$ Seek | Type$ Card.cmcLTX | SpellDescription$ Expedient - Seek a card with lesser mana value than the discarded card.
|
||||
DeckHas:Ability$Sacrifice|Token|Discard & Type$Treasure|Artifact
|
||||
SVar:X:Discarded$CardManaCost
|
||||
Oracle:At the beginning of your end step, you may discard a card. If you do, create a Treasure token and choose ambitious or expedient. If you chose ambitious, seek a card with greater mana value than the discarded card. If you chose expedient, seek a card with lesser mana value than the discarded card.
|
||||
|
||||
@@ -8,7 +8,7 @@ T:Mode$ Drawn | ValidCard$ Card.YouOwn+Dragon | TriggerZones$ Battlefield | Exec
|
||||
SVar:DBEffect:DB$ Effect | StaticAbilities$ PerpetualP1P1 | RememberObjects$ TriggeredCard | Name$ Darigaaz's Whelp's Perpetual Effect | Duration$ Permanent
|
||||
SVar:PerpetualP1P1:Mode$ Continuous | Affected$ Card.IsRemembered | AddPower$ 1 | AddToughness$ 1 | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ This card perpetually gets +1/+1.
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self+kicked | Execute$ TrigSeek | TriggerDescription$ When this creature enters the battlefield, if it was kicked, seek a Dragon card. CARDNAME and that Dragon card each perpetually get +1/+1.
|
||||
SVar:TrigSeek:DB$ ChangeZone | RememberChanged$ True | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.Dragon | SubAbility$ DBEffectBis
|
||||
SVar:TrigSeek:DB$ Seek | RememberFound$ True | Type$ Card.Dragon | SubAbility$ DBEffectBis
|
||||
SVar:DBEffectBis:DB$ Effect | StaticAbilities$ PerpetualP1P1Bis | RememberObjects$ Remembered | Name$ Darigaaz's Whelp's Perpetual Effect | Duration$ Permanent | SubAbility$ DBCleanup
|
||||
SVar:PerpetualP1P1Bis:Mode$ Continuous | Affected$ Card.IsRemembered,Card.EffectSource | AddPower$ 1 | AddToughness$ 1 | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ CARDNAME and the conjured Dragon card each perpetually get +1/+1.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
|
||||
@@ -5,6 +5,6 @@ PT:2/1
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigConnive | TriggerDescription$ When CARDNAME enters the battlefield, it connives. (Draw a card, then discard a card. If you discarded a nonland card, put a +1/+1 counter on this creature.)
|
||||
SVar:TrigConnive:DB$ Connive
|
||||
T:Mode$ DiscardedAll | ValidPlayer$ You | ValidCard$ Card | TriggerZones$ Battlefield | Execute$ TrigSeek | ActivationLimit$ 1 | TriggerDescription$ Whenever you discard one or more cards, seek a card that shares a card type with one of the discarded cards. This ability triggers only once each turn.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.sharesCardTypeWith TriggeredCards | ChangeNum$ 1
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Card.sharesCardTypeWith TriggeredCards
|
||||
DeckHas:Ability$Discard|Counters
|
||||
Oracle:When Diviner of Fates enters the battlefield, it connives.\nWhenever you discard one or more cards, seek a card that shares a card type with one of the discarded cards. This ability triggers only once each turn.
|
||||
|
||||
@@ -4,5 +4,5 @@ Types:Creature Shapeshifter
|
||||
PT:2/2
|
||||
K:Changeling
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, seek a creature card of the most prevalent creature type in your library.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.Creature+MostProminentCreatureTypeInLibrary | ChangeNum$ 1
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Card.Creature+MostProminentCreatureTypeInLibrary
|
||||
Oracle:Changeling\nWhen Faceless Agent enters the battlefield, seek a creature card of the most prevalent creature type in your library.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Faith Unbroken
|
||||
ManaCost:3 W
|
||||
Types:Enchantment Aura
|
||||
K:Enchant creature you control
|
||||
A:SP$ Attach | Cost$ 3 W | ValidTgts$ Creature | AILogic$ Pump
|
||||
A:SP$ Attach | Cost$ 3 W | ValidTgts$ Creature.YouCtrl | AILogic$ Pump
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, exile target creature an opponent controls until CARDNAME leaves the battlefield.
|
||||
SVar:TrigExile:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature.OppCtrl | TgtPrompt$ Select target creature an opponent controls | Duration$ UntilHostLeavesPlay
|
||||
SVar:PlayMain1:TRUE
|
||||
|
||||
@@ -3,10 +3,9 @@ ManaCost:1 R
|
||||
Types:Creature Human Wizard
|
||||
PT:2/2
|
||||
K:Prowess
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | CheckSVar$ Z | SVarCompare$ GE20 | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if there are twenty or more instant and/or sorcery cards among cards in your graveyard, hand, and library, you may discard a card. If you do, seek an instant or sorcery card.
|
||||
SVar:TrigSeek:AB$ ChangeZone | Cost$ Discard<1/Card> | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Instant,Sorcery
|
||||
SVar:X:Count$ValidGraveyard Instant.YouOwn,Sorcery.YouOwn
|
||||
SVar:Y:Count$ValidLibrary Instant.YouOwn,Sorcery.YouOwn/Plus.X
|
||||
SVar:Z:Count$ValidHand Instant.YouOwn,Sorcery.YouOwn/Plus.Y
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | CheckSVar$ X | SVarCompare$ GE20 | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if there are twenty or more instant and/or sorcery cards among cards in your graveyard, hand, and library, you may discard a card. If you do, seek an instant or sorcery card.
|
||||
SVar:TrigSeek:AB$ Seek | Cost$ Discard<1/Card> | Type$ Instant,Sorcery
|
||||
SVar:X:Count$ValidGraveyard,Library,Hand Instant.YouOwn,Sorcery.YouOwn
|
||||
DeckNeeds:Type$Instant|Sorcery
|
||||
DeckHas:Ability$Discard
|
||||
Oracle:When Frenzied Geistblaster enters the battlefield, if there are twenty or more instant and/or sorcery cards among cards in your graveyard, hand, and library, you may discard a card. If you do, seek an instant or sorcery card.
|
||||
|
||||
@@ -7,7 +7,7 @@ SVar:DBRandom:DB$ ChooseCard | Defined$ You | Choices$ Elf.YouOwn | ChoiceZone$
|
||||
SVar:DBEffect:DB$ Effect | RememberObjects$ Targeted | StaticAbilities$ PerpetualP1P1 | Name$ Freyalise, Skyshroud Partisan's Perpetual Effect | Duration$ Permanent | SubAbility$ DBCleanup
|
||||
SVar:PerpetualP1P1:Mode$ Continuous | Affected$ Card.IsRemembered,Card.ChosenCard | AddPower$ 1 | AddToughness$ 1 | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ The target Elf and randomly chosen card perpetually get +1/+1.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True
|
||||
A:AB$ ChangeZone | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.Elf | ChangeNum$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek an Elf card.
|
||||
A:AB$ Seek | Cost$ SubCounter<1/LOYALTY> | Planeswalker$ True | Type$ Card.Elf | StackDescription$ REP Seek_{p:You} seeks | SpellDescription$ Seek an Elf card.
|
||||
A:AB$ MakeCard | Conjure$ True | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | Name$ Regal Force | Zone$ Battlefield | SpellDescription$ Conjure a Regal Force card onto the battlefield.
|
||||
DeckNeeds:Type$Elf
|
||||
Oracle:[+1]: Choose up to one target Elf. Untap it. It and a random Elf creature card in your hand each perpetually gets +1/+1.\n[-1]: Seek an Elf card.\n[-6]: Conjure a Regal Force card onto the battlefield.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Gate of the Black Dragon
|
||||
ManaCost:no cost
|
||||
Types:Land Swamp Gate
|
||||
K:CARDNAME enters the battlefield tapped.
|
||||
A:AB$ ChangeZone | Cost$ 3 B T | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
A:AB$ Seek | Cost$ 3 B T | Type$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ {p:You} seeks a nonland card. | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
Text:{T}: Add {B}.
|
||||
DeckHints:Type$Gate
|
||||
Oracle:Gate of the Black Dragon enters the battlefield tapped.\n{3}{B}, {T}: Seek a nonland card. Activate only once.\n{T}: Add {B}.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Gate to Manorborn
|
||||
ManaCost:no cost
|
||||
Types:Land Forest Gate
|
||||
K:CARDNAME enters the battlefield tapped.
|
||||
A:AB$ ChangeZone | Cost$ 3 G T | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
A:AB$ Seek | Cost$ 3 G T | Type$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ {p:You} seeks a nonland card. | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
Text:{T}: Add {G}.
|
||||
DeckHints:Type$Gate
|
||||
Oracle:Gate to Manorborn enters the battlefield tapped.\n{3}{G}, {T}: Seek a nonland card. Activate only once.\n{T}: Add {G}.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Gate to Seatower
|
||||
ManaCost:no cost
|
||||
Types:Land Island Gate
|
||||
K:CARDNAME enters the battlefield tapped.
|
||||
A:AB$ ChangeZone | Cost$ 3 U T | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
A:AB$ Seek | Cost$ 3 U T | Type$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ {p:You} seeks a nonland card. | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
Text:{T}: Add {U}.
|
||||
DeckHints:Type$Gate
|
||||
Oracle:Gate to Seatower enters the battlefield tapped.\n{3}{U}, {T}: Seek a nonland card. Activate only once.\n{T}: Add {U}.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Gate to the Citadel
|
||||
ManaCost:no cost
|
||||
Types:Land Plains Gate
|
||||
K:CARDNAME enters the battlefield tapped.
|
||||
A:AB$ ChangeZone | Cost$ 3 W T | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
A:AB$ Seek | Cost$ 3 W T | Type$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ {p:You} seeks a nonland card. | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
Text:{T}: Add {W}.
|
||||
DeckHints:Type$Gate
|
||||
Oracle:Gate to the Citadel enters the battlefield tapped.\n{3}{W}, {T}: Seek a nonland card. Activate only once.\n{T}: Add {W}.
|
||||
|
||||
@@ -2,7 +2,7 @@ Name:Gate to Tumbledown
|
||||
ManaCost:no cost
|
||||
Types:Land Mountain Gate
|
||||
K:CARDNAME enters the battlefield tapped.
|
||||
A:AB$ ChangeZone | Cost$ 3 R T | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
A:AB$ Seek | Cost$ 3 R T | Type$ Card.nonLand | GameActivationLimit$ 1 | StackDescription$ {p:You} seeks a nonland card. | SpellDescription$ Seek a nonland card. Activate only once.
|
||||
Text:{T}: Add {R}.
|
||||
DeckHints:Type$Gate
|
||||
Oracle:Gate to Tumbledown enters the battlefield tapped.\n{3}{R}, {T}: Seek a nonland card. Activate only once.\n{T}: Add {R}.
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Creature Wolf
|
||||
PT:5/4
|
||||
K:Trample
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When CARDNAME dies, seek a permanent card with mana value equal to the number of lands you control.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.Permanent+cmcEQX | ChangeNum$ 1
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Card.Permanent+cmcEQX
|
||||
SVar:X:Count$Valid Land.YouCtrl
|
||||
SVar:NeedsToPlayVar:X GE4
|
||||
SVar:BuffedBy:Land
|
||||
|
||||
@@ -4,8 +4,9 @@ Types:Creature Human Wizard
|
||||
PT:2/2
|
||||
K:Prowess
|
||||
T:Mode$ Phase | Phase$ Main1 | PreCombatMain$ True | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigSeek | TriggerDescription$ At the beginning of your precombat main phase, you may discard a card. If you do, seek a card with greater mana value and exile it. Until the end of your next turn, you may play the exiled card.
|
||||
SVar:TrigSeek:AB$ ChangeZone | Cost$ Discard<1/Card> | Origin$ Library | Destination$ Exile | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.cmcGTX | ChangeNum$ 1 | RememberChanged$ True | SubAbility$ DBEffect
|
||||
SVar:TrigSeek:AB$ Seek | Cost$ Discard<1/Card> | Type$ Card.cmcGTX | RememberFound$ True | SubAbility$ DBExile
|
||||
SVar:X:Discarded$CardManaCost
|
||||
SVar:DBExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | Defined$ Remembered | SubAbility$ DBEffect
|
||||
SVar:DBEffect:DB$ Effect | RememberObjects$ Remembered | StaticAbilities$ MayPlay | Duration$ UntilTheEndOfYourNextTurn | ForgetOnMoved$ Exile | SubAbility$ DBCleanup
|
||||
SVar:MayPlay:Mode$ Continuous | Affected$ Card.IsRemembered | MayPlay$ True | EffectZone$ Command | AffectedZone$ Exile | Description$ Until the end of your next turn, you may play the exiled card.
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
|
||||
@@ -4,11 +4,13 @@ Types:Legendary Creature Frog Horror
|
||||
PT:6/6
|
||||
K:Menace
|
||||
T:Mode$ Phase | Phase$ BeginCombat | TriggerZones$ Battlefield | Execute$ TrigSac | IsPresent$ Card.Self+untapped | TriggerDescription$ At the beginning of each combat, if CARDNAME is untapped, any opponent may sacrifice a nontoken creature. If they do, tap CARDNAME, then seek a land card and put it onto the battlefield tapped.
|
||||
SVar:TrigSac:DB$ Sacrifice | Defined$ Opponent | Amount$ 1 | SacValid$ Creature.nonToken | RememberSacrificed$ True | Optional$ True | AILogic$ DesecrationDemon | SubAbility$ DBTap
|
||||
SVar:DBTap:DB$ Tap | Defined$ Self | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBSeek
|
||||
SVar:DBSeek:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Land | ChangeNum$ 1 | ConditionCheckSVar$ X | ConditionSVarCompare$ GE1 | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:TrigSac:DB$ Sacrifice | Defined$ Opponent | Amount$ 1 | SacValid$ Creature.nonToken | RememberSacrificed$ True | Optional$ True | AILogic$ DesecrationDemon | SubAbility$ DBBranch
|
||||
SVar:DBBranch:DB$ Branch | BranchConditionSVar$ X | TrueSubAbility$ DBTap
|
||||
SVar:X:Remembered$Amount
|
||||
SVar:DBTap:DB$ Tap | SubAbility$ DBSeek
|
||||
SVar:DBSeek:DB$ Seek | Type$ Card.Land | ImprintFound$ True | SubAbility$ DBPut
|
||||
SVar:DBPut:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | Defined$ Imprinted | Tapped$ True | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearImprinted$ True
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | Execute$ TrigEffect | TriggerDescription$ Whenever a land enters the battlefield under your control, it perpetually gains "{B}{G}, {T}, Sacrifice this land: Draw a card."
|
||||
SVar:TrigEffect:DB$ Effect | RememberObjects$ TriggeredCard | StaticAbilities$ PerpetualStatic | Name$ Gitrog, Horror of Zhava's Perpetual Effect | Duration$ Permanent | SubAbility$ DBCleanup
|
||||
SVar:PerpetualStatic:Mode$ Continuous | Affected$ Card.IsRemembered | AddAbility$ PerpetualSacDraw | EffectZone$ All | Description$ This land card perpetually gains "{B}{G}, {T}, Sacrifice this land: Draw a card."
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:R
|
||||
Types:Creature Goblin
|
||||
PT:1/1
|
||||
T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ DBSeek | TriggerDescription$ When CARDNAME dies, seek a creature card with mana value 3 or less. That card perpetually gains haste, "This spell costs {1} less to cast," and "At the beginning of your end step, sacrifice this creature."
|
||||
SVar:DBSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Creature.cmcLE3+YouOwn | RememberChanged$ True | SubAbility$ DBEffect
|
||||
SVar:DBSeek:DB$ Seek | Type$ Creature.cmcLE3+YouOwn | RememberFound$ True | SubAbility$ DBEffect
|
||||
SVar:DBEffect:DB$ Effect | StaticAbilities$ PerpetualAbility | RememberObjects$ Remembered | Triggers$ Update | Name$ Goblin Trapfinder's Perpetual Effect | Duration$ Permanent
|
||||
SVar:PerpetualAbility:Mode$ Continuous | Affected$ Card.IsRemembered | AddTrigger$ TrigSac | AddStaticAbility$ PerpetualReduceCost | AddKeyword$ Haste | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ This card perpetually gains haste, "This spell costs {1} less to cast," and "At the beginning of your end step, sacrifice this creature."
|
||||
SVar:PerpetualReduceCost:Mode$ ReduceCost | ValidCard$ Card.Self | Type$ Spell | Amount$ 1 | EffectZone$ All | Description$ This spell costs {1} less to cast.
|
||||
|
||||
@@ -3,6 +3,7 @@ ManaCost:3 G G
|
||||
Types:Creature Elemental
|
||||
PT:6/6
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, seek a land card.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Land | ChangeNum$ 1
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Card.Land
|
||||
A:AB$ MakeCard | Cost$ Discard<1/Land/land> | Conjure$ True | Name$ Hollowhenge Beast | Zone$ Hand | AdditionalActivationZone$ Graveyard | StackDescription$ Conjure a card named Hollowhenge Beast into your hand. | SpellDescription$ Conjure a card named Hollowhenge Beast into your hand. You may also activate this ability while CARDNAME is in your graveyard.
|
||||
DeckHas:Ability$Discard
|
||||
Oracle:When Hollowhenge Wrangler enters the battlefield, seek a land card.\nDiscard a land card: Conjure a card named Hollowhenge Beast into your hand. You may also activate this ability while Hollowhenge Wrangler is in your graveyard.
|
||||
|
||||
@@ -3,13 +3,11 @@ ManaCost:3 W
|
||||
Types:Creature Human Cleric
|
||||
PT:3/3
|
||||
K:Vigilance
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.wasCast+Self | CheckSVar$ Z | SVarCompare$ GE20 | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it and there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Library | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Creature.YouOwn+cmcLE3 | ChangeNum$ 2 | RememberChanged$ True | SubAbility$ DBChangeZone1
|
||||
SVar:DBChangeZone1:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | ChangeType$ Creature.IsRemembered | ChangeNum$ 1 | Mandatory$ True | NoLooking$ True | SelectPrompt$ Select a card for the battlefield | Shuffle$ True | SubAbility$ DBChangeZone2 | StackDescription$ None
|
||||
SVar:DBChangeZone2:DB$ ChangeZone | Origin$ Library | Destination$ Library | ChangeType$ Creature.IsRemembered | Mandatory$ True | NoLooking$ True | StackDescription$ None | SubAbility$ DBCleanup
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.wasCast+Self | CheckSVar$ X | SVarCompare$ GE20 | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it and there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library.
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Creature.YouOwn+cmcLE3 | Num$ 2 | RememberFound$ True | SubAbility$ DBChangeZone1
|
||||
SVar:DBChangeZone1:DB$ ChangeZone | Origin$ Hand | Destination$ Battlefield | ChangeType$ Creature.IsRemembered | ChangeNum$ 1 | Mandatory$ True | SelectPrompt$ Select a card for the battlefield | SubAbility$ DBChangeZone2
|
||||
SVar:DBChangeZone2:DB$ ChangeZone | Origin$ Hand | Destination$ Library | ChangeType$ Creature.IsRemembered | Mandatory$ True | Shuffle$ True | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
SVar:X:Count$ValidGraveyard Creature.YouOwn+cmcLE3
|
||||
SVar:Y:Count$ValidLibrary Creature.YouOwn+cmcLE3/Plus.X
|
||||
SVar:Z:Count$ValidHand Creature.YouOwn+cmcLE3/Plus.Y
|
||||
SVar:X:Count$ValidGraveyard,Library,Hand Creature.YouOwn+cmcLE3
|
||||
DeckNeeds:Type$Creature
|
||||
Oracle:Vigilance\nWhen Inquisitor Captain enters the battlefield, if you cast it and there are twenty or more creature cards with mana value 3 or less among cards in your graveyard, hand, and library, seek two creature cards with mana value 3 or less. Put one of them onto the battlefield and shuffle the other into your library.
|
||||
|
||||
@@ -5,6 +5,6 @@ PT:3/3
|
||||
K:Ninjutsu:1 G
|
||||
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | CombatDamage$ True | Execute$ TrigChoose | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, choose land or nonland. Seek a permanent card of the chosen type.
|
||||
SVar:TrigChoose:DB$ ChooseType | Type$ Card | ValidTypes$ Land,Nonland | SubAbility$ DBSeek
|
||||
SVar:DBSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.ChosenType | ChangeNum$ 1 | SubAbility$ DBCleanup
|
||||
SVar:DBSeek:DB$ Seek | Type$ Card.Permanent+ChosenType | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearChosenType$ True
|
||||
Oracle:Ninjutsu {1}{G}\nWhenever Jukai Liberator deals combat damage to a player, choose land or nonland. Seek a permanent card of the chosen type.
|
||||
|
||||
@@ -5,7 +5,9 @@ PT:4/3
|
||||
K:Haste
|
||||
T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigCounter | TriggerZones$ Battlefield | TriggerDescription$ Whenever CARDNAME attacks, put a flame counter on it, then seek a card with mana value equal to the number of flame counters on it and exile that card face down.
|
||||
SVar:TrigCounter:DB$ PutCounter | CounterType$ FLAME | CounterNum$ 1 | ValidCards$ Self | SubAbility$ DBSeek
|
||||
SVar:DBSeek:DB$ ChangeZone | Origin$ Library | Destination$ Exile | ExileFaceDown$ True | AtRandom$ True | NoShuffle$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Card.cmcEQX+YouOwn | RememberChanged$ True
|
||||
SVar:DBSeek:DB$ Seek | Type$ Card.cmcEQX+YouOwn | ImprintFound$ True | SubAbility$ DBExile
|
||||
SVar:DBExile:DB$ ChangeZone | Origin$ Hand | Destination$ Exile | Defined$ Imprinted | ExileFaceDown$ True | Mandatory$ True | SubAbility$ DBClearImprinted
|
||||
SVar:DBClearImprinted:DB$ Cleanup | ClearImprinted$ True
|
||||
T:Mode$ ChangesZone | ValidCard$ Card.Self | Origin$ Battlefield | Destination$ Graveyard | Execute$ TrigReturn | TriggerDescription$ When NICKNAME dies, put the cards exiled with it into their owner's hand. At the beginning of the end step of your next turn, discard those cards.
|
||||
SVar:TrigReturn:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered+ExiledWithSource | Origin$ Exile | Destination$ Hand | SubAbility$ DBDelay
|
||||
SVar:DBDelay:DB$ DelayedTrigger | DelayedTriggerDefinedPlayer$ You | Mode$ Phase | Phase$ End of Turn | Execute$ TrigDiscardExiled | RememberObjects$ Remembered | TriggerDescription$ At the beginning of the end step of your next turn, discard those cards.
|
||||
@@ -16,4 +18,5 @@ T:Mode$ ChangesZone | Origin$ Exile | Destination$ Any | Static$ True | ValidCar
|
||||
SVar:DBForget:DB$ Pump | ForgetObjects$ TriggeredCard
|
||||
SVar:X:Count$CardCounters.FLAME
|
||||
SVar:HasAttackEffect:TRUE
|
||||
DeckHas:Ability$Discard
|
||||
Oracle:Haste\nWhenever Kardum, Patron of Flames attacks, put a flame counter on it, then seek a card with mana value equal to the number of flame counters on it and exile that card face down.\nWhen Kardum dies, put all cards you own exiled with it into your hand. At the beginning of the end step of your next turn, discard those cards.
|
||||
|
||||
@@ -39,7 +39,7 @@ SVar:TrigReturn:DB$ ChangeZone | Origin$ Graveyard | Destination$ Battlefield |
|
||||
SVar:DBEffect:DB$ Effect | RememberObjects$ TriggeredCard | StaticAbilities$ PerpetualStatic | Duration$ Permanent
|
||||
SVar:PerpetualStatic:Mode$ Continuous | Affected$ Card.IsRemembered | AddKeyword$ CARDNAME can't block. | EffectZone$ Command | AffectedZone$ Battlefield,Hand,Graveyard,Exile,Stack,Library,Command | Description$ It perpetually gains "This creature can't block."
|
||||
T:Mode$ Specializes | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When this card specializes from any zone, seek an instant or sorcery card with mana value 3 or less. Until end of turn, you may cast that card without paying its mana cost.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 1 | ChangeType$ Instant.cmcLE3,Sorcery.cmcLE3 | RememberChanged$ True
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Instant.cmcLE3,Sorcery.cmcLE3 | RememberFound$ True | SubAbility$ DBEffect
|
||||
SVar:DBEffect:DB$ Effect | StaticAbilities$ MayPlay | RememberObjects$ Remembered | ForgetOnMoved$ Hand | SubAbility$ DBCleanup
|
||||
SVar:MayPlay:Mode$ Continuous | Affected$ Card.IsRemembered+nonLand | MayPlayWithoutManaCost$ True | EffectZone$ Command | AffectedZone$ Hand
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True
|
||||
|
||||
@@ -2,6 +2,6 @@ Name:Kindred Denial
|
||||
ManaCost:2 U U
|
||||
Types:Instant
|
||||
A:SP$ Counter | TargetType$ Spell | ValidTgts$ Card | TgtPrompt$ Select target spell | RememberCounteredCMC$ True | SubAbility$ DBSeek | SpellDescription$ Counter target spell.
|
||||
SVar:DBSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.cmcEQX | ChangeNum$ 1 | StackDescription$ SpellDescription | SpellDescription$ Seek a card with the same mana value as that spell.
|
||||
SVar:DBSeek:DB$ Seek | Type$ Card.cmcEQX | StackDescription$ REP Seek_{p:You} seeks | SpellDescription$ Seek a card with the same mana value as that spell.
|
||||
SVar:X:Count$RememberedNumber
|
||||
Oracle:Counter target spell. Seek a card with the same mana value as that spell.
|
||||
|
||||
@@ -36,10 +36,10 @@ Types:Legendary Creature Tiefling Cleric
|
||||
PT:3/4
|
||||
K:Vigilance
|
||||
T:Mode$ Specializes | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When this creature specializes, seek three nonland permanent cards. Choose one of those cards and shuffle the rest into your library.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeNum$ 3 | ChangeType$ Permanent.nonLand | RememberChanged$ True | SubAbility$ DBChooseCard
|
||||
SVar:TrigSeek:DB$ Seek | Num$ 3 | ChangeType$ Card.Permanent+nonLand | RememberFound$ True | SubAbility$ DBChooseCard
|
||||
SVar:DBChooseCard:DB$ ChooseCard | ChoiceZone$ Hand | Choices$ Card.IsRemembered | ForgetChosen$ True | SubAbility$ DBShuffle
|
||||
SVar:DBShuffle:DB$ ChangeZone | Origin$ Hand | Destination$ Library | Defined$ Remembered | Shuffle$ True | SubAbility$ DBClearChosen
|
||||
SVar:DBClearChosen:DB$ Cleanup | ClearChosenCard$ True
|
||||
SVar:DBShuffle:DB$ ChangeZone | Origin$ Hand | Destination$ Library | Defined$ Remembered | Shuffle$ True | SubAbility$ DBCleanup
|
||||
SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True | ClearChosenCard$ True
|
||||
Oracle:Vigilance\nWhen this creature specializes, seek three nonland permanent cards. Choose one of those cards and shuffle the rest into your library.
|
||||
|
||||
SPECIALIZE:BLACK
|
||||
|
||||
@@ -22,7 +22,7 @@ PT:3/6
|
||||
K:Double Strike
|
||||
T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigSeek | TriggerDescription$ When this creature enters the battlefield or specializes, seek a nonland permanent card with mana value 3 or less.
|
||||
T:Mode$ Specializes | ValidCard$ Card.Self | Execute$ TrigSeek | Secondary$ True | TriggerDescription$ When this creature enters the battlefield or specializes, seek a nonland permanent card with mana value 3 or less.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Permanent.nonLand+cmcLE3
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Card.Permanent+nonLand+cmcLE3
|
||||
Oracle:Double strike\nWhen this creature enters the battlefield or specializes, seek a nonland permanent card with mana value 3 or less.
|
||||
|
||||
SPECIALIZE:BLUE
|
||||
|
||||
@@ -4,7 +4,7 @@ Types:Legendary Creature Human Druid
|
||||
PT:2/2
|
||||
K:Specialize:3:Wild Shape:Activate only if you control six or more lands.:IsPresent$ Land.YouCtrl | PresentCompare$ GE6
|
||||
T:Mode$ ChangesZone | ValidCard$ Card.wasCastByYou+Self | Destination$ Battlefield | Execute$ TrigSeek | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it, seek a land card with a basic land type.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Land.hasABasicLandType | ChangeNum$ 1
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Land.hasABasicLandType
|
||||
AlternateMode:Specialize
|
||||
Oracle:Wild Shape — Specialize {3}. Activate only if you control six or more lands.\nWhen Lukamina, Moon Druid enters the battlefield, if you cast it, seek a land card with a basic land type.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Name:Norn's Disassembly
|
||||
ManaCost:W
|
||||
Types:Enchantment
|
||||
A:AB$ ChangeZone | Cost$ 1 W Sac<1/Permanent.Historic/Historic permanent> | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.Historic | ChangeNum$ 1 | SpellDescription$ Seek a historic card.
|
||||
A:AB$ Seek | Cost$ 1 W Sac<1/Permanent.Historic/historic permanent> | Type$ Card.Historic | StackDescription$ REP Seek_{p:You} seeks | SpellDescription$ Seek a historic card.
|
||||
DeckHas:Ability$Sacrifice
|
||||
DeckNeeds:Type$Legendary|Artifact|Planeswalker
|
||||
Oracle:{1}{W}, Sacrifice a historic permanent: Seek a historic card.
|
||||
|
||||
@@ -5,6 +5,6 @@ PT:4/4
|
||||
K:Flying
|
||||
K:Ward:2
|
||||
T:Mode$ DamageDone | ValidSource$ Card.Self | ValidTarget$ Player | Execute$ TrigSeek | CombatDamage$ True | TriggerDescription$ Whenever CARDNAME deals combat damage to a player, seek a card with mana value equal to the number of cards in your hand.
|
||||
SVar:TrigSeek:DB$ ChangeZone | Origin$ Library | Destination$ Hand | AtRandom$ True | NoShuffle$ True | Mandatory$ True | NoLooking$ True | NoReveal$ True | ChangeType$ Card.cmcEQX | ChangeNum$ 1
|
||||
SVar:TrigSeek:DB$ Seek | Type$ Card.cmcEQX
|
||||
SVar:X:Count$InYourHand
|
||||
Oracle:Flying\nWard {2}\nWhenever Obsessive Collector deals combat damage to a player, seek a card with mana value equal to the number of cards in your hand.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user