diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index 65a7571eafb..c23d24e7299 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -35,16 +35,11 @@ import forge.util.TextUtil; import forge.util.collect.FCollectionView; public class AiCostDecision extends CostDecisionMakerBase { - private final SpellAbility ability; - private final Card source; - private final CardCollection discarded; private final CardCollection tapped; public AiCostDecision(Player ai0, SpellAbility sa, final boolean effect) { - super(ai0, effect); - ability = sa; - source = ability.getHostCard(); + super(ai0, effect, sa, sa.getHostCard()); discarded = new CardCollection(); tapped = new CardCollection(); diff --git a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java index 79de3c099e3..b1e981d9d6a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CharmAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CharmAi.java @@ -26,7 +26,7 @@ public class CharmAi extends SpellAbilityAi { @Override protected boolean checkApiLogic(Player ai, SpellAbility sa) { final Card source = sa.getHostCard(); - List choices = CharmEffect.makePossibleOptions(sa, false); + List choices = CharmEffect.makePossibleOptions(sa); final int num; final int min; diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index e9551be1576..4c7fa6d0a43 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -943,7 +943,6 @@ public class Game { public GameStage getAge() { return age; } - public void setAge(GameStage value) { age = value; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java index 5b0233df5b1..6a0a2447686 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CharmEffect.java @@ -20,7 +20,7 @@ import forge.util.collect.FCollection; public class CharmEffect extends SpellAbilityEffect { - public static List makePossibleOptions(final SpellAbility sa, boolean forDesc) { + public static List makePossibleOptions(final SpellAbility sa) { final Card source = sa.getHostCard(); List restriction = null; @@ -30,7 +30,7 @@ public class CharmEffect extends SpellAbilityEffect { List choices = Lists.newArrayList(sa.getAdditionalAbilityList("Choices")); - if (!forDesc) { + if (source.getZone() != null) { List toRemove = Lists.newArrayList(); for (AbilitySub ch : choices) { // 603.3c If one of the modes would be illegal, that mode can't be chosen. @@ -55,7 +55,7 @@ public class CharmEffect extends SpellAbilityEffect { public static String makeFormatedDescription(SpellAbility sa) { Card source = sa.getHostCard(); - List list = CharmEffect.makePossibleOptions(sa, true); + List list = CharmEffect.makePossibleOptions(sa); final int num; boolean additionalDesc = sa.hasParam("AdditionalDescription"); boolean optional = sa.hasParam("Optional"); @@ -169,7 +169,7 @@ public class CharmEffect extends SpellAbilityEffect { //this resets all previous choices sa.setSubAbility(null); - List choices = makePossibleOptions(sa, false); + List choices = makePossibleOptions(sa); // Entwine does use all Choices if (sa.isEntwine()) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java index 50d96bd6367..b219dda5505 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/CountersPutEffect.java @@ -176,7 +176,6 @@ public class CountersPutEffect extends SpellAbilityEffect { final Player activator = sa.getActivatingPlayer(); final PlayerController pc = activator.getController(); final boolean etbcounter = sa.hasParam("ETB"); - final int max = sa.hasParam("MaxFromEffect") ? Integer.parseInt(sa.getParam("MaxFromEffect")) : -1; boolean existingCounter = sa.hasParam("CounterType") && sa.getParam("CounterType").equals("ExistingCounter"); boolean eachExistingCounter = sa.hasParam("EachExistingCounter"); @@ -453,10 +452,6 @@ public class CountersPutEffect extends SpellAbilityEffect { } counterAmount = sa.usesTargeting() && sa.isDividedAsYouChoose() ? sa.getDividedValue(gameCard) : counterAmount; - if (max != -1) { - counterAmount = Math.max(Math.min(max - gameCard.getCounters(counterType), counterAmount), - 0); - } if (sa.hasParam("UpTo")) { int min = AbilityUtils.calculateAmount(card, sa.getParamOrDefault("UpToMin", "0"), sa); Map params = Maps.newHashMap(); diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 44bf5eaf15e..d82fbd469d0 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -526,7 +526,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars { if (state == CardStateName.FaceDown) { view.updateHiddenId(game.nextHiddenCardId()); } - game.fireEvent(new GameEventCardStatsChanged(this, true)); //ensure stats updated for new characteristics + game.fireEvent(new GameEventCardStatsChanged(this)); //ensure stats updated for new characteristics } } return true; @@ -1427,6 +1427,10 @@ public class Card extends GameEntity implements Comparable, IHasSVars { @Override public void addCounterInternal(final CounterType counterType, final int n, final Player source, final boolean fireEvents, GameEntityCounterTable table, Map params) { int addAmount = n; + // Rules say it is only a SBA, but is it checked there too? + if (counterType.is(CounterEnumType.DREAM) && hasKeyword("CARDNAME can't have more than seven dream counters on it.")) { + addAmount = Math.min(addAmount, 7 - getCounters(CounterEnumType.DREAM)); + } if (addAmount <= 0 || !canReceiveCounters(counterType)) { // As per rule 107.1b return; @@ -7115,8 +7119,12 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public void resetChosenModeTurn() { + boolean updateView = !chosenModesTurn.isEmpty() || !chosenModesTurnStatic.isEmpty(); chosenModesTurn.clear(); chosenModesTurnStatic.clear(); + if (updateView) { + updateAbilityTextForView(); + } } public int getPlaneswalkerAbilityActivated() { diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index f588ba131f1..e184ad6b358 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -984,11 +984,24 @@ public class CardProperty { if (card.getTurnInZone() <= sourceController.getLastTurnNr()) { return false; } - } else if (property.equals("ThisTurnEntered")) { + } else if (property.startsWith("ThisTurnEntered")) { // only check if it entered the Zone this turn if (card.getTurnInZone() != game.getPhaseHandler().getTurn()) { return false; } + if (!property.equals("ThisTurnEntered")) { // to confirm specific zones / player + final boolean your = property.contains("Your"); + final ZoneType where = ZoneType.smartValueOf(property.substring(your ? 19 : 15)); + final Zone z = sourceController.getZone(where); + if (!z.getCardsAddedThisTurn(null).contains(card)) { + return false; + } + if (your) { // for corner cases of controlling other player + if (!card.getOwner().equals(sourceController)) { + return false; + } + } + } } else if (property.equals("NotThisTurnEntered")) { // only check if it entered the Zone this turn if (card.getTurnInZone() == game.getPhaseHandler().getTurn()) { diff --git a/forge-game/src/main/java/forge/game/cost/CostDecisionMakerBase.java b/forge-game/src/main/java/forge/game/cost/CostDecisionMakerBase.java index a5cf64503b1..eeec65b2208 100644 --- a/forge-game/src/main/java/forge/game/cost/CostDecisionMakerBase.java +++ b/forge-game/src/main/java/forge/game/cost/CostDecisionMakerBase.java @@ -1,15 +1,23 @@ package forge.game.cost; +import forge.game.card.Card; import forge.game.player.Player; +import forge.game.spellability.SpellAbility; public abstract class CostDecisionMakerBase implements ICostVisitor { protected final Player player; + protected final SpellAbility ability; + protected final Card source; private boolean effect; - public CostDecisionMakerBase(Player player0, boolean effect0) { + + public CostDecisionMakerBase(Player player0, boolean effect0, SpellAbility ability0, Card source0) { player = player0; effect = effect0; + ability = ability0; + source = source0; } + public Player getPlayer() { return player; } public abstract boolean paysRightAfterDecision(); public boolean isEffect() { diff --git a/forge-game/src/main/java/forge/game/event/GameEventCardStatsChanged.java b/forge-game/src/main/java/forge/game/event/GameEventCardStatsChanged.java index ad05e05753c..f4bdcd33184 100644 --- a/forge-game/src/main/java/forge/game/event/GameEventCardStatsChanged.java +++ b/forge-game/src/main/java/forge/game/event/GameEventCardStatsChanged.java @@ -22,7 +22,9 @@ public class GameEventCardStatsChanged extends GameEvent { public GameEventCardStatsChanged(Card affected, boolean isTransform) { cards = Arrays.asList(affected); - transform = isTransform; + //the transform should only fire once so the flip effect sound will trigger once every transformation... + // disable for now + transform = false; } public GameEventCardStatsChanged(Collection affected) { diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml index c6ef544b56d..59fb125d1d2 100644 --- a/forge-gui-mobile/pom.xml +++ b/forge-gui-mobile/pom.xml @@ -57,7 +57,7 @@ com.github.tommyettinger textratypist - 0.7.9 + 0.8.1 com.badlogicgames.gdx-controllers diff --git a/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java b/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java index e5c6a6233a8..a893ef2d979 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/ArenaScene.java @@ -2,6 +2,7 @@ package forge.adventure.scene; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureAtlas; +import com.badlogic.gdx.scenes.scene2d.Action; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.actions.Actions; @@ -55,6 +56,7 @@ public class ArenaScene extends UIScene implements IAfterMatch { final Sprite edgeM; final Sprite edgeWin; final Sprite edgeWinM; + boolean enable = true; boolean arenaStarted = false; private ArenaScene() { @@ -76,6 +78,8 @@ public class ArenaScene extends UIScene implements IAfterMatch { goldLabel = ui.findActor("gold"); ui.onButtonPress("done", () -> { + if (!enable) + return; if (!arenaStarted) ArenaScene.this.done(); else @@ -107,6 +111,8 @@ public class ArenaScene extends UIScene implements IAfterMatch { } private void startButton() { + if (!enable) + return; if (roundsWon == 0) { Dialog startDialog = prepareDialog(Forge.getLocalizer().getMessage("lblStart"), ButtonYes | ButtonNo, () -> startArena()); startDialog.text("Do you want to go into the Arena?"); @@ -119,6 +125,7 @@ public class ArenaScene extends UIScene implements IAfterMatch { int roundsWon = 0; private void startArena() { + enable = false; goldLabel.setVisible(false); arenaStarted = true; startButton.setText("[%80]" + Forge.getLocalizer().getMessage("lblContinue")); @@ -132,6 +139,7 @@ public class ArenaScene extends UIScene implements IAfterMatch { @Override public void setWinner(boolean winner) { + enable = false; Array winners = new Array<>(); Array winnersEnemies = new Array<>(); for (int i = 0; i < fighters.size - 2; i += 2) { @@ -189,7 +197,15 @@ public class ArenaScene extends UIScene implements IAfterMatch { } if (Forge.isLandscapeMode()) { actor.toFront(); - actor.addAction(Actions.sequence(Actions.moveBy(0f, gridSize * 2f, 1), Actions.moveBy((float) (gridSize * stepsToTheSide * (leftPlayer ? 1 : -1)), 0f, 1))); + actor.addAction(Actions.sequence(Actions.moveBy(0f, gridSize * 2f, 1), Actions.moveBy((float) (gridSize * stepsToTheSide * (leftPlayer ? 1 : -1)), 0f, 1), new Action() { + @Override + public boolean act(float v) { + enable = true; + return true; + } + })); + } else { + enable = true; } } diff --git a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java index d24d5cc4d77..5efa7f9a3bc 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java +++ b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java @@ -8,15 +8,9 @@ import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.scenes.scene2d.Action; -import com.badlogic.gdx.scenes.scene2d.Actor; -import com.badlogic.gdx.scenes.scene2d.InputEvent; -import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.*; import com.badlogic.gdx.scenes.scene2d.actions.Actions; -import com.badlogic.gdx.scenes.scene2d.ui.Button; -import com.badlogic.gdx.scenes.scene2d.ui.Dialog; -import com.badlogic.gdx.scenes.scene2d.ui.Image; -import com.badlogic.gdx.scenes.scene2d.ui.Touchpad; +import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; @@ -48,20 +42,11 @@ public class GameHUD extends Stage { static public GameHUD instance; private final GameStage gameStage; - private final Image avatar; - private final Image miniMapPlayer; - private final TextraLabel lifePoints; - private final TextraLabel money; - private final TextraLabel shards; + private final Image avatar, miniMapPlayer; + private final TextraLabel lifePoints, money, shards, keys; private final Image miniMap, gamehud, mapborder, avatarborder, blank; - private final InputEvent eventTouchDown; - private final InputEvent eventTouchUp; - private final TextraButton deckActor; - private final TextraButton openMapActor; - private final TextraButton menuActor; - private final TextraButton statsActor; - private final TextraButton inventoryActor; - private final TextraButton exitToWorldMapActor; + private final InputEvent eventTouchDown, eventTouchUp; + private final TextraButton deckActor, openMapActor, menuActor, statsActor, inventoryActor, exitToWorldMapActor; public final UIActor ui; private final Touchpad touchpad; private final Console console; @@ -73,8 +58,10 @@ public class GameHUD extends Stage { private final Dialog dialog; private boolean dialogOnlyInput; private final Array dialogButtonMap = new Array<>(); + private final Array questKeys = new Array<>(); private String lifepointsTextColor = ""; - TextraButton selectedKey; + private TextraButton selectedKey; + private final ScrollPane scrollPane; private GameHUD(GameStage gameStage) { super(new ScalingViewport(Scaling.stretch, Scene.getIntendedWidth(), Scene.getIntendedHeight()), gameStage.getBatch()); @@ -137,6 +124,11 @@ public class GameHUD extends Stage { shards.setText("[%95][+Shards] 0"); money.setText("[%95][+Gold] "); lifePoints.setText("[%95][+Life] 20/20"); + keys = Controls.newTextraLabel(""); + scrollPane = new ScrollPane(keys); + scrollPane.setPosition(2, 2); + scrollPane.setStyle(Controls.getSkin().get("transluscent", ScrollPane.ScrollPaneStyle.class)); + addActor(scrollPane); AdventurePlayer.current().onLifeChange(() -> lifePoints.setText("[%95][+Life]" + lifepointsTextColor + " " + AdventurePlayer.current().getLife() + "/" + AdventurePlayer.current().getMaxLife())); AdventurePlayer.current().onShardsChange(() -> shards.setText("[%95][+Shards] " + AdventurePlayer.current().getShards())); @@ -291,6 +283,7 @@ public class GameHUD extends Stage { Pixmap miniMapToolTipPixmap; public void enter() { + questKeys.clear(); if (miniMapTexture != null) miniMapTexture.dispose(); miniMapTexture = new Texture(WorldSave.getCurrentSave().getWorld().getBiomeImage()); @@ -304,6 +297,28 @@ public class GameHUD extends Stage { miniMap.setDrawable(new TextureRegionDrawable(miniMapTexture)); avatar.setDrawable(new TextureRegionDrawable(Current.player().avatar())); Deck deck = AdventurePlayer.current().getSelectedDeck(); + if (AdventurePlayer.current().hasItem("Red Key")) + questKeys.add("[+RedKey]"); + if (AdventurePlayer.current().hasItem("Green Key")) + questKeys.add("[+GreenKey]"); + if (AdventurePlayer.current().hasItem("Blue Key")) + questKeys.add("[+BlueKey]"); + if (AdventurePlayer.current().hasItem("Black Key")) + questKeys.add("[+BlackKey]"); + if (AdventurePlayer.current().hasItem("White Key")) + questKeys.add("[+WhiteKey]"); + if (AdventurePlayer.current().hasItem("Strange Key")) + questKeys.add("[+StrangeKey]"); + if (!questKeys.isEmpty()) { + keys.setText(String.join("\n", questKeys)); + scrollPane.setSize(keys.getWidth() + 8, keys.getHeight() + 5); + scrollPane.layout(); + keys.layout(); + scrollPane.getColor().a = opacity; + } else { + keys.setText(""); + scrollPane.getColor().a = 0; + } if (deck == null || deck.isEmpty() || deck.getMain().toFlatList().size() < 30) { deckActor.setColor(Color.RED); } else { diff --git a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java index bcf23d849cb..d6b53cbc300 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java @@ -306,7 +306,7 @@ public class MapStage extends GameStage { dialog.getContentTable().add(group).height(100).width(100).center(); dialog.getContentTable().add().row(); } else { - TypingLabel label = Controls.newTypingLabel("[%125]"+Controls.colorIdToTypingString(DeckProxy.getColorIdentity(deck)).toUpperCase()+"\n[%]"+deck.getName()); + TypingLabel label = Controls.newTypingLabel("[%120]"+Controls.colorIdToTypingString(DeckProxy.getColorIdentity(deck)).toUpperCase()+"\n[%]"+deck.getName()); label.skipToTheEnd(); label.setAlignment(Align.center); dialog.getContentTable().add(label).align(Align.center); diff --git a/forge-gui-mobile/src/forge/adventure/util/DrawOnPixmap.java b/forge-gui-mobile/src/forge/adventure/util/DrawOnPixmap.java index 481a400f71e..2d7918e8a8d 100644 --- a/forge-gui-mobile/src/forge/adventure/util/DrawOnPixmap.java +++ b/forge-gui-mobile/src/forge/adventure/util/DrawOnPixmap.java @@ -8,6 +8,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.glutils.FrameBuffer; import com.badlogic.gdx.math.Matrix4; import com.badlogic.gdx.utils.Align; +import com.github.tommyettinger.textra.TextraLabel; /* Class to draw directly on a pixmap @@ -26,7 +27,6 @@ public abstract class DrawOnPixmap { on.drawPixmap(textureData.consumePixmap(), x, y, from.getRegionX(), from.getRegionY(), from.getRegionWidth(), from.getRegionHeight()); } - public static void drawText(Pixmap drawingMap, String itemText, int x, int y, float width, boolean bigText, Color color) { //used for big numbers on Gold/Life for reward... BitmapFont font = bigText ? Controls.getBitmapFont("big") : Controls.getBitmapFont("default"); @@ -59,4 +59,37 @@ public abstract class DrawOnPixmap { if (bigText) //don't know why this is needed to circumvent bug getting default size for the same pixelfont Controls.getBitmapFont("default"); } + + public static void drawText(Pixmap drawingMap, TextraLabel itemText, int modX, int modY) { + FrameBuffer frameBuffer = new FrameBuffer(Pixmap.Format.RGB888, drawingMap.getWidth(), drawingMap.getHeight(), false); + SpriteBatch batch = new SpriteBatch(); + + frameBuffer.begin(); + + Gdx.gl.glClearColor(0, 0, 0, 0); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + Matrix4 matrix = new Matrix4(); + matrix.setToOrtho2D(0, drawingMap.getHeight(), drawingMap.getWidth(), -drawingMap.getHeight()); + batch.setProjectionMatrix(matrix); + + batch.begin(); + //Rendering ends here. Create a new Pixmap to Texture with mipmaps, otherwise will render as full black. + Texture texture = new Texture(drawingMap); + batch.draw(texture, 0, 0); + itemText.setWrap(true); + itemText.setAlignment(1); + itemText.setWidth(texture.getWidth()); + itemText.setHeight(texture.getHeight()); + itemText.setX(itemText.getX()+modX); + itemText.setY(itemText.getY()+modY); + itemText.draw(batch, 1); + batch.end(); + Pixmap pixmap = Pixmap.createFromFrameBuffer(0, 0, drawingMap.getWidth(), drawingMap.getHeight()); + drawingMap.drawPixmap(pixmap, 0, 0); + frameBuffer.end(); + texture.dispose(); + batch.dispose(); + pixmap.dispose(); + } } diff --git a/forge-gui-mobile/src/forge/adventure/util/KeyBinding.java b/forge-gui-mobile/src/forge/adventure/util/KeyBinding.java index 14fd8c908f3..55a267ceacd 100644 --- a/forge-gui-mobile/src/forge/adventure/util/KeyBinding.java +++ b/forge-gui-mobile/src/forge/adventure/util/KeyBinding.java @@ -44,13 +44,13 @@ public enum KeyBinding { public String getLabelText(boolean pressed) { if(Controllers.getCurrent()!=null) { - return "[%125][+"+controllerPrefix+Input.Keys.toString(bindingController).replace(" Button","")+(pressed?"_pressed]":"]"); + return "[%120][+"+controllerPrefix+Input.Keys.toString(bindingController).replace(" Button","")+(pressed?"_pressed]":"]"); } else { if(GuiBase.isAndroid()) return ""; - return "[%125][+"+Input.Keys.toString(binding)+(pressed?"_pressed]":"]"); + return "[%120][+"+Input.Keys.toString(binding)+(pressed?"_pressed]":"]"); } } diff --git a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java index 71ae37acca7..0ffe1813b26 100644 --- a/forge-gui-mobile/src/forge/adventure/util/RewardActor.java +++ b/forge-gui-mobile/src/forge/adventure/util/RewardActor.java @@ -305,7 +305,8 @@ public class RewardActor extends Actor implements Disposable, ImageFetcher.Callb DrawOnPixmap.draw(drawingMap, backSprite); Sprite item = atlas.createSprite(reward.type.toString()); DrawOnPixmap.draw(drawingMap, (int) ((backSprite.getWidth() / 2f) - item.getWidth() / 2f), (int) ((backSprite.getHeight() / 4f) * 1f), item); - DrawOnPixmap.drawText(drawingMap, String.valueOf(reward.getCount()), 0, (int) ((backSprite.getHeight() / 4f) * 2f) - 1, backSprite.getWidth(), true, Color.WHITE); + //DrawOnPixmap.drawText(drawingMap, String.valueOf(reward.getCount()), 0, (int) ((backSprite.getHeight() / 4f) * 2f) - 1, backSprite.getWidth(), true, Color.WHITE); + DrawOnPixmap.drawText(drawingMap, Controls.newTextraLabel("[%200]"+reward.getCount()), 0, -10); setItemTooltips(item, backSprite, atlas); image = new Texture(drawingMap); diff --git a/forge-gui-mobile/src/forge/assets/Assets.java b/forge-gui-mobile/src/forge/assets/Assets.java index 394e517e81f..e78dfa80284 100644 --- a/forge-gui-mobile/src/forge/assets/Assets.java +++ b/forge-gui-mobile/src/forge/assets/Assets.java @@ -339,8 +339,10 @@ public class Assets implements Disposable { textrafonts = new ObjectMap<>(); if (!textrafonts.containsKey("textrafont")) { Font font = new Font(bitmapFont, 0f, 2f, 0f, 0f); - font.addAtlas(item_atlas, 0f, 0f, 0f); - font.addAtlas(pixelmana_atlas, 0f, -12f, 0f); + font.addAtlas(item_atlas, 0f, 4f, 0f); + //problematic atlas since some buttons are small, and this is too big for some buttons, need a way to enable + //this via property + //font.addAtlas(pixelmana_atlas, -90f, 20f, 0f); font.integerPosition = false; textrafonts.put("textrafont", font); } @@ -352,7 +354,7 @@ public class Assets implements Disposable { textrafonts = new ObjectMap<>(); if (!textrafonts.containsKey("keysfont")) { Font font = new Font(bitmapFont); - font.addAtlas(keys_atlas); + font.addAtlas(keys_atlas, 0f, 4f, 0f); font.integerPosition = false; textrafonts.put("keysfont", font); } @@ -364,7 +366,7 @@ public class Assets implements Disposable { textrafonts = new ObjectMap<>(); if (!textrafonts.containsKey(name)) { Font font = new Font(bitmapFont); - font.addAtlas(items_atlas); + font.addAtlas(items_atlas, 0f, 4f, 0f); font.integerPosition = false; textrafonts.put(name, font); } diff --git a/forge-gui-mobile/src/forge/screens/SplashScreen.java b/forge-gui-mobile/src/forge/screens/SplashScreen.java index aa764e4b458..11ed0c23358 100644 --- a/forge-gui-mobile/src/forge/screens/SplashScreen.java +++ b/forge-gui-mobile/src/forge/screens/SplashScreen.java @@ -239,7 +239,10 @@ public class SplashScreen extends FContainer { } void drawTransition(Graphics g, boolean openAdventure, float percentage) { - TextureRegion tr = new TextureRegion(Forge.getAssets().fallback_skins().get("title")); + Texture t = Forge.getAssets().fallback_skins().get("title"); + TextureRegion tr = null; + if (t != null) + tr = new TextureRegion(t); float oldAlpha = g.getfloatAlphaComposite(); g.setAlphaComposite(percentage); if (openAdventure) { diff --git a/forge-gui/res/adventure/Shandalar/custom_cards/garruk_boss_effect_phasetwo.txt b/forge-gui/res/adventure/Shandalar/custom_cards/garruk_boss_effect_phasetwo.txt index cd9d4a38064..4c2b8af9eb9 100644 --- a/forge-gui/res/adventure/Shandalar/custom_cards/garruk_boss_effect_phasetwo.txt +++ b/forge-gui/res/adventure/Shandalar/custom_cards/garruk_boss_effect_phasetwo.txt @@ -3,7 +3,7 @@ ManaCost:no cost Types:Enchantment S:Mode$ Continuous | EffectZone$ Command | Affected$ Card.Self | AffectedZone$ Command | RemoveAllAbilities$ True | IsPresent$ Card.namedGarruk's Boss Effect Phase One | PresentZone$ Command | PresentCompare$ EQ1 S:Mode$ Continuous | EffectZone$ Command | Affected$ Forest.YouCtrl | AddType$ Swamp | Description$ Each Forest you control is a Swamp in addition to its other land types. -S:Mode$ Continuous | Affected$ Beast.YouCtrl | AddPower$ 3 | AddToughness 3 | AddKeyword$ Trample & Deathtouch | Description$ Beast creatures you control get +3/+3 and have trample and Deathtouch +S:Mode$ Continuous | Affected$ Beast.YouCtrl | AddPower$ 3 | AddToughness$ 3 | AddKeyword$ Trample & Deathtouch | Description$ Beast creatures you control get +3/+3 and have trample and Deathtouch T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | PresentZone$ Command | Execute$ TrigConjure | TriggerDescription$ At the beginning of your upkeep, conjure a card of Garruk Phase 2's Spellbook into your hand. SVar:TrigConjure:DB$ MakeCard | Conjure$ True | Zone$ Hand | AtRandom$ True | Spellbook$ Garruk; Apex Predator,Garruk; Cursed Huntsman,Garruk Relentless,In Garruk's Wake,Rampaging Baloths,Manglehorn,Elder Gargaroth,Gemrazer,Thragtusk,Sawtusk Demolisher,Avenger of Zendikar,Soul of the Harvest,Kogla; the Titan Ape, Terastodon, Bane of Progress T:Mode$ SpellCast | ValidCard$ Card.nonCreature | ValidActivatingPlayer$ Player.Opponent | Execute$ DBEffect | TriggerZones$ Command | TriggerDescription$ Whenever an opponent casts a noncreature spell,perpetually increase the power and toughness of creatures you control and creature cards in your hand, library, and graveyard by 1. @@ -13,4 +13,4 @@ SVar:Update:Mode$ ChangesZone | Origin$ Any | Destination$ Any | Static$ True | SVar:DBUpdate:DB$ UpdateRemember T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | TriggerZones$ Command | Execute$ TrigReanimate | TriggerDescription$ At the beginning of your end step, return a random creature card from your graveyard to the battlefield. It gains "If this creature would leave the battlefield, exile it instead". SVar:TrigReanimate:DB$ ChangeZone | ChangeType$ Creature.YouOwn | ChangeNum$ 1 | Hidden$ True | Origin$ Graveyard | AtRandom$ True | Destination$ Battlefield | LeaveBattlefield$ Exile -Oracle:Each Forest you control is a Swamp in addition to its other land types.\nBeast creatures you control get +3/+3 and have trample and Deathtouch\nAt the beginning of your upkeep, conjure a card of Garruk spellbook into your hand.\nWhenever an opponent casts a noncreature spell, perpetually increase the power and toughness of creatures you control and creature cards in your hand, library, and graveyard by 1. At the beginning of your end step, return a random creature card from your graveyard to the battlefield. That creature gains "If this creature would leave the battlefield, exile it instead". \ No newline at end of file +Oracle:Each Forest you control is a Swamp in addition to its other land types.\nBeast creatures you control get +3/+3 and have trample and Deathtouch\nAt the beginning of your upkeep, conjure a card of Garruk spellbook into your hand.\nWhenever an opponent casts a noncreature spell, perpetually increase the power and toughness of creatures you control and creature cards in your hand, library, and graveyard by 1. At the beginning of your end step, return a random creature card from your graveyard to the battlefield. That creature gains "If this creature would leave the battlefield, exile it instead". diff --git a/forge-gui/res/adventure/Shandalar/custom_cards/tibalt_boss_effect.txt b/forge-gui/res/adventure/Shandalar/custom_cards/tibalt_boss_effect.txt index ef550405f25..2fd7bec2202 100644 --- a/forge-gui/res/adventure/Shandalar/custom_cards/tibalt_boss_effect.txt +++ b/forge-gui/res/adventure/Shandalar/custom_cards/tibalt_boss_effect.txt @@ -9,8 +9,8 @@ SVar:TrigRollDice:DB$ RollDice | Sides$ 20 | ResultSubAbilities$ 1-5:DBConjureSm SVar:DBConjureSmall:DB$ MakeCard | Conjure$ True | AtRandom$ True | Spellbook$ Chained Brute,Big Spender,Devilish Valet,Gibbering Fiend,Hobblefiend,Footlight Fiend,Forge Devil,Festival Crasher,Hulking Devil,Mayhem Devil,Spiteful Prankster,Vexing Devil,Wildfire Devil | Zone$ Battlefield | SpellDescription$ Conjure a random Devil unto the battlefield. SVar:DBRandomLoot:DB$ Draw | Defined$ Player | NumCards$ 3 | SubAbility$ DBDiscard3 | SpellDescription$ Each player draws three cards, then discards three cards at random. SVar:DBDiscard3:DB$ Discard | Defined$ Player | Mode$ Random | NumCards$ 3 -SVar:DBDamage:DB$ DealDamage | NumDmg$ 7 | ValidTgts$ Creature | TargetsAtRandom$ True | SubAbility$ DBChangeZone | SpellDescription$ Tibalt deals seven damage to a creature chosen at random. Then Tibalt returns a random creature card to the battlefield -SVar:DBChangeZone:DB$ ChangeZone | ChangeType$ Creature | ChangeNum$ 1 | Hidden$ True | Origin$ Graveyard | AtRandom$ True | Destination$ Battlefield +SVar:DBDamage:DB$ DealDamage | NumDmg$ 7 | ValidTgts$ Creature,Player,Planeswalker | TargetsAtRandom$ True | SubAbility$ DBChangeZone | SpellDescription$ Tibalt deals seven damage to a creature chosen at random. Then Tibalt returns a random creature card to the battlefield +SVar:DBChangeZone:DB$ ChangeZone | ChangeType$ Creature | ChangeNum$ 1 | GainControl$ True | Hidden$ True | Origin$ Graveyard | AtRandom$ True | Destination$ Battlefield SVar:DBCast:DB$ Play | AnySupportedCard$ Names:Hellion Eruption,Insurrection,Warp World,Shahrazad,Possibility Storm,Scrambleverse | RandomCopied$ True | CopyCard$ True | WithoutManaCost$ True | SpellDescription$ Cast a copy of one of the following cards chosen at random—Hellion Eruption, Insurrection, Warp World, Shahrazad, Possibility Storm, Scrambleverse. SVar:DBWheel:DB$ Discard | Mode$ Hand | Defined$ Player | SubAbility$ DBEachDraw | SpellDescription$ Each player discards their hand, then draws seven cards. SVar:DBEachDraw:DB$ Draw | Defined$ Player | NumCards$ 7 diff --git a/forge-gui/res/adventure/Shandalar/custom_cards/xira_boss_effect.txt b/forge-gui/res/adventure/Shandalar/custom_cards/xira_boss_effect.txt index 4b0d5022d9d..50a25a59d82 100644 --- a/forge-gui/res/adventure/Shandalar/custom_cards/xira_boss_effect.txt +++ b/forge-gui/res/adventure/Shandalar/custom_cards/xira_boss_effect.txt @@ -2,7 +2,7 @@ Name:Xira's Boss Effect ManaCost:no cost Colors:black,green,red Types:Enchantment -S:Mode$ Continuous | Affected$ Insect.YouCtrl | EffectZone$ Command | AddPower$ 1 | AddToughness 1 | AddKeyword$ Double Team | Description$ Nontoken insects you control have +1/+1 and Double Team. +S:Mode$ Continuous | Affected$ Insect.YouCtrl | EffectZone$ Command | AddPower$ 1 | AddToughness$ 1 | AddKeyword$ Double Team | Description$ Nontoken insects you control have +1/+1 and Double Team. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Command | Execute$ PutCounterAll | TriggerDescription$ At the beginning of your upkeep, put an egg counter on each nontoken creature. SVar:PutCounterAll:DB$ PutCounterAll | ValidCards$ Creature.nonToken | CounterType$ EGG | CounterNum$ 1 T:Mode$ ChangesZone | Origin$ Battlefield | TriggerZones$ Command | Destination$ Graveyard | ValidCard$ Creature.counters_GE1_EGG+OppCtrl | Execute$ TrigDraw | TriggerDescription$ Whenever a creature with an egg counter on it dies, draw a card and create X 1/1 black Insect creature token with flying where X is the amount of Egg counters on that creature. diff --git a/forge-gui/res/adventure/Shandalar/custom_cards/xiras_hive.txt b/forge-gui/res/adventure/Shandalar/custom_cards/xiras_hive.txt index e0db7f5df71..f8ae5a8b47d 100644 --- a/forge-gui/res/adventure/Shandalar/custom_cards/xiras_hive.txt +++ b/forge-gui/res/adventure/Shandalar/custom_cards/xiras_hive.txt @@ -5,7 +5,7 @@ Types:Creature Insect PT:0/2 K:Defender K:Reach -S:Mode$ Continuous | Affected$ Insect.YouCtrl+nonToken | EffectZone$ Battlefield | AddPower$ 1 | AddToughness 1 | AddKeyword$ Double Team | Description$ Nontoken Insects you control have +1/+1 and double team. +S:Mode$ Continuous | Affected$ Insect.YouCtrl+nonToken | EffectZone$ Battlefield | AddPower$ 1 | AddToughness$ 1 | AddKeyword$ Double Team | Description$ Nontoken Insects you control have +1/+1 and double team. T:Mode$ DamageDone | ActivationLimit$ 1 | ValidSource$ Card.OppCtrl,Emblem.OppCtrl | ValidTarget$ You | TriggerZones$ Battlefield | Execute$ TrigCounter | TriggerDescription$ When a source an opponent controls deals damage to you for the first time each turn, put an egg counter on CARDNAME. SVar:TrigCounter:DB$ PutCounter | CounterType$ EGG | CounterNum$ 1 T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Self | Execute$ TrigToken | TriggerDescription$ When CARDNAME dies, create X 1/1 black Insect tokens for each egg counter on CARDNAME. diff --git a/forge-gui/res/adventure/Shandalar/maps/map/tibalt.tmx b/forge-gui/res/adventure/Shandalar/maps/map/tibalt.tmx index 26539e20456..a1a661608bc 100644 --- a/forge-gui/res/adventure/Shandalar/maps/map/tibalt.tmx +++ b/forge-gui/res/adventure/Shandalar/maps/map/tibalt.tmx @@ -136,7 +136,7 @@ - + @@ -144,10 +144,5 @@ - - - - - diff --git a/forge-gui/res/adventure/Shandalar/maps/map/tibalt_f1.tmx b/forge-gui/res/adventure/Shandalar/maps/map/tibalt_f1.tmx index da9c46af1f7..425f3be0984 100644 --- a/forge-gui/res/adventure/Shandalar/maps/map/tibalt_f1.tmx +++ b/forge-gui/res/adventure/Shandalar/maps/map/tibalt_f1.tmx @@ -93,7 +93,7 @@ - + diff --git a/forge-gui/res/adventure/music/black/black1.mp3 b/forge-gui/res/adventure/Shandalar/music/black/black1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/black/black1.mp3 rename to forge-gui/res/adventure/Shandalar/music/black/black1.mp3 diff --git a/forge-gui/res/adventure/music/blue/blue1.mp3 b/forge-gui/res/adventure/Shandalar/music/blue/blue1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/blue/blue1.mp3 rename to forge-gui/res/adventure/Shandalar/music/blue/blue1.mp3 diff --git a/forge-gui/res/adventure/music/boss/boss1.mp3 b/forge-gui/res/adventure/Shandalar/music/boss/boss1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/boss/boss1.mp3 rename to forge-gui/res/adventure/Shandalar/music/boss/boss1.mp3 diff --git a/forge-gui/res/adventure/music/boss/boss2.mp3 b/forge-gui/res/adventure/Shandalar/music/boss/boss2.mp3 similarity index 100% rename from forge-gui/res/adventure/music/boss/boss2.mp3 rename to forge-gui/res/adventure/Shandalar/music/boss/boss2.mp3 diff --git a/forge-gui/res/adventure/music/castle/castle1.mp3 b/forge-gui/res/adventure/Shandalar/music/castle/castle1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/castle/castle1.mp3 rename to forge-gui/res/adventure/Shandalar/music/castle/castle1.mp3 diff --git a/forge-gui/res/adventure/music/cave/cave1.mp3 b/forge-gui/res/adventure/Shandalar/music/cave/cave1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/cave/cave1.mp3 rename to forge-gui/res/adventure/Shandalar/music/cave/cave1.mp3 diff --git a/forge-gui/res/adventure/music/green/green1.mp3 b/forge-gui/res/adventure/Shandalar/music/green/green1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/green/green1.mp3 rename to forge-gui/res/adventure/Shandalar/music/green/green1.mp3 diff --git a/forge-gui/res/adventure/music/match/match1.mp3 b/forge-gui/res/adventure/Shandalar/music/match/match1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/match/match1.mp3 rename to forge-gui/res/adventure/Shandalar/music/match/match1.mp3 diff --git a/forge-gui/res/adventure/music/match/match2.mp3 b/forge-gui/res/adventure/Shandalar/music/match/match2.mp3 similarity index 100% rename from forge-gui/res/adventure/music/match/match2.mp3 rename to forge-gui/res/adventure/Shandalar/music/match/match2.mp3 diff --git a/forge-gui/res/adventure/music/match/match3.mp3 b/forge-gui/res/adventure/Shandalar/music/match/match3.mp3 similarity index 100% rename from forge-gui/res/adventure/music/match/match3.mp3 rename to forge-gui/res/adventure/Shandalar/music/match/match3.mp3 diff --git a/forge-gui/res/adventure/music/menus/menu1.mp3 b/forge-gui/res/adventure/Shandalar/music/menus/menu1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/menus/menu1.mp3 rename to forge-gui/res/adventure/Shandalar/music/menus/menu1.mp3 diff --git a/forge-gui/res/adventure/music/red/red1.mp3 b/forge-gui/res/adventure/Shandalar/music/red/red1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/red/red1.mp3 rename to forge-gui/res/adventure/Shandalar/music/red/red1.mp3 diff --git a/forge-gui/res/adventure/music/town/town1.mp3 b/forge-gui/res/adventure/Shandalar/music/town/town1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/town/town1.mp3 rename to forge-gui/res/adventure/Shandalar/music/town/town1.mp3 diff --git a/forge-gui/res/adventure/music/white/white1.mp3 b/forge-gui/res/adventure/Shandalar/music/white/white1.mp3 similarity index 100% rename from forge-gui/res/adventure/music/white/white1.mp3 rename to forge-gui/res/adventure/Shandalar/music/white/white1.mp3 diff --git a/forge-gui/res/adventure/Shandalar/skin/ui_skin.atlas b/forge-gui/res/adventure/Shandalar/skin/ui_skin.atlas index 62959ab3e2e..68915e0c981 100644 --- a/forge-gui/res/adventure/Shandalar/skin/ui_skin.atlas +++ b/forge-gui/res/adventure/Shandalar/skin/ui_skin.atlas @@ -260,6 +260,15 @@ thinwindow orig: 16, 16 offset: 0, 0 index: -1 +transwindow + rotate: false + xy: 305, 415 + size: 16, 16 + split: 2, 2, 2, 2 + pad: 0, 0, 0, 0 + orig: 16, 16 + offset: 0, 0 + index: -1 uncheck rotate: false xy: 293, 375 diff --git a/forge-gui/res/adventure/Shandalar/skin/ui_skin.json b/forge-gui/res/adventure/Shandalar/skin/ui_skin.json index 562c914a4d3..a1a02a7ac15 100644 --- a/forge-gui/res/adventure/Shandalar/skin/ui_skin.json +++ b/forge-gui/res/adventure/Shandalar/skin/ui_skin.json @@ -166,6 +166,26 @@ "playMode": 2, "crushMode": 0 }, + "transwindow10Patch": { + "region": "transwindow", + "horizontalStretchAreas": [ 2, 13 ], + "verticalStretchAreas": [ 2, 13 ], + "tiling": true, + "minWidth": 16, + "minHeight": 16, + "rightWidth": 4, + "leftWidth": 4, + "bottomHeight": 4, + "topHeight": 4, + "offsetX": 0, + "offsetY": 0, + "offsetXspeed": 0, + "offsetYspeed": 0, + "frameDuration": 0.03, + "regions": [], + "playMode": 2, + "crushMode": 0 + }, "pressed10Patch": { "region": "pressed", "horizontalStretchAreas": [ 3, 10 ], @@ -443,6 +463,9 @@ "gold": { "background": "9patch4" }, + "transluscent": { + "background": "transwindow10Patch" + }, "nobg": { "background": "transparent" } @@ -549,6 +572,11 @@ "background": "paper10Patch", "titleFont": "default" }, + "transluscent": { + "parent": "default", + "background": "transwindow10Patch", + "titleFont": "default" + }, "gold": { "background": "TenPatchGold", "titleFont": "default" diff --git a/forge-gui/res/adventure/Shandalar/ui/hud.json b/forge-gui/res/adventure/Shandalar/ui/hud.json index 2555f1fd592..b4d5f2a283e 100644 --- a/forge-gui/res/adventure/Shandalar/ui/hud.json +++ b/forge-gui/res/adventure/Shandalar/ui/hud.json @@ -86,7 +86,7 @@ "type": "TextButton", "name": "exittoworldmap", "style":"menu", - "text": "[%125][+ExitToWorldMap]", + "text": "[%120][+ExitToWorldMap]", "binding": "ExitToWorldMap", "width": 48, "height": 36, @@ -97,7 +97,7 @@ "type": "TextButton", "name": "deck", "style":"menu", - "text": "[%125][+Deck]", + "text": "[%120][+Deck]", "binding": "Deck", "width": 48, "height": 36, @@ -108,7 +108,7 @@ "type": "TextButton", "name": "inventory", "style":"menu", - "text": "[%125][+Item]", + "text": "[%120][+Item]", "binding": "Inventory", "width": 48, "height": 36, @@ -120,7 +120,7 @@ "type": "TextButton", "name": "statistic", "style":"menu", - "text": "[%125][+Status]", + "text": "[%120][+Status]", "binding": "Status", "width": 48, "height": 36, @@ -131,7 +131,7 @@ "type": "TextButton", "name": "menu", "style":"menu", - "text": "[%125][+Menu]", + "text": "[%120][+Menu]", "binding": "Menu", "width": 48, "height": 36, diff --git a/forge-gui/res/adventure/Shandalar/ui/hud_landscape.json b/forge-gui/res/adventure/Shandalar/ui/hud_landscape.json index 2c1c193490b..20ea9b51bb9 100644 --- a/forge-gui/res/adventure/Shandalar/ui/hud_landscape.json +++ b/forge-gui/res/adventure/Shandalar/ui/hud_landscape.json @@ -86,7 +86,7 @@ "type": "TextButton", "name": "deck", "style":"menu", - "text": "[%125][+Deck]", + "text": "[%120][+Deck]", "binding": "Deck", "width": 64, "height": 36, @@ -97,7 +97,7 @@ "type": "TextButton", "name": "inventory", "style":"menu", - "text": "[%125][+Item]", + "text": "[%120][+Item]", "binding": "Inventory", "width": 64, "height": 36, @@ -109,7 +109,7 @@ "type": "TextButton", "name": "statistic", "style":"menu", - "text": "[%125][+Status]", + "text": "[%120][+Status]", "binding": "Status", "width": 64, "height": 36, @@ -120,7 +120,7 @@ "type": "TextButton", "name": "menu", "style":"menu", - "text": "[%125][+Menu]", + "text": "[%120][+Menu]", "binding": "Menu", "width": 64, "height": 36, @@ -141,7 +141,7 @@ "type": "TextButton", "name": "exittoworldmap", "style":"menu", - "text": "[%125][+ExitToWorldMap]", + "text": "[%120][+ExitToWorldMap]", "binding": "ExitToWorldMap", "width": 64, "height": 32, diff --git a/forge-gui/res/adventure/Shandalar/ui/hud_portrait.json b/forge-gui/res/adventure/Shandalar/ui/hud_portrait.json index 0dd7a2c6bab..2d5bb2578aa 100644 --- a/forge-gui/res/adventure/Shandalar/ui/hud_portrait.json +++ b/forge-gui/res/adventure/Shandalar/ui/hud_portrait.json @@ -85,7 +85,7 @@ "type": "TextButton", "name": "deck", "style":"menu", - "text": "[%125][+Deck]", + "text": "[%120][+Deck]", "binding": "Deck", "width": 64, "height": 32, @@ -96,7 +96,7 @@ "type": "TextButton", "name": "inventory", "style":"menu", - "text": "[%125][+Item]", + "text": "[%120][+Item]", "binding": "Inventory", "width": 64, "height": 32, @@ -108,7 +108,7 @@ "type": "TextButton", "name": "statistic", "style":"menu", - "text": "[%125][+Status]", + "text": "[%120][+Status]", "binding": "Status", "width": 64, "height": 32, @@ -119,7 +119,7 @@ "type": "TextButton", "name": "menu", "style":"menu", - "text": "[%125][+Menu]", + "text": "[%120][+Menu]", "binding": "Menu", "width": 64, "height": 32, @@ -140,7 +140,7 @@ "type": "TextButton", "name": "exittoworldmap", "style":"menu", - "text": "[%125][+ExitToWorldMap]", + "text": "[%120][+ExitToWorldMap]", "binding": "ExitToWorldMap", "width": 64, "height": 32, diff --git a/forge-gui/res/adventure/Shandalar/ui/statistic.json b/forge-gui/res/adventure/Shandalar/ui/statistic.json index dedab76f2b1..2a0886907b2 100644 --- a/forge-gui/res/adventure/Shandalar/ui/statistic.json +++ b/forge-gui/res/adventure/Shandalar/ui/statistic.json @@ -130,7 +130,7 @@ { "type": "TextButton", "name": "toggleAward", - "text": "[%125][+AWARD]", + "text": "[%120][+AWARD]", "width": 30, "height": 30, "x": 315, diff --git a/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json b/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json index bbcde956d2d..ba4ec5ebe02 100644 --- a/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json +++ b/forge-gui/res/adventure/Shandalar/ui/statistic_portrait.json @@ -121,7 +121,7 @@ { "type": "TextButton", "name": "toggleAward", - "text": "[%125][+AWARD]", + "text": "[%120][+AWARD]", "width": 30, "height": 30, "x": 5, diff --git a/forge-gui/res/cardsfolder/c/cruel_grimnarch.txt b/forge-gui/res/cardsfolder/c/cruel_grimnarch.txt index d1e78e163d4..d929dfe32d9 100644 --- a/forge-gui/res/cardsfolder/c/cruel_grimnarch.txt +++ b/forge-gui/res/cardsfolder/c/cruel_grimnarch.txt @@ -2,7 +2,7 @@ Name:Cruel Grimnarch ManaCost:5 B Types:Creature Phyrexian Cleric PT:5/5 -K:Deatchtouch +K:Deathtouch T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigDiscard | TriggerDescription$ When CARDNAME enters the battlefield, each opponent discards a card. For each opponent who can't, you gain 4 life. SVar:TrigDiscard:DB$ Discard | Mode$ TgtChoose | Defined$ Player.Opponent | NumCards$ 1 | RememberDiscarded$ True | SubAbility$ DBRepeat SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Player.Opponent | RepeatSubAbility$ DBGainLife | SubAbility$ DBCleanup @@ -10,4 +10,4 @@ SVar:DBGainLife:DB$ GainLife | LifeAmount$ 4 | ConditionCheckSVar$ X | Conditio SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:Remembered$Valid Card.nonLand+RememberedPlayerOwn DeckHas:Ability$Discard -Oracle:Deathtouch\nWhen Cruel Grimnarch enters the battlefield, each opponent discards a card. For each opponent who can't, you gain 4 life \ No newline at end of file +Oracle:Deathtouch\nWhen Cruel Grimnarch enters the battlefield, each opponent discards a card. For each opponent who can't, you gain 4 life diff --git a/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt b/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt index b8b0beb1359..21d2dcd68ee 100644 --- a/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt +++ b/forge-gui/res/cardsfolder/l/lazav_dimir_mastermind.txt @@ -3,6 +3,6 @@ ManaCost:U U B B Types:Legendary Creature Shapeshifter PT:3/3 K:Hexproof -T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.nonToken+OppOwn | TriggerZones$ Battlefield | Execute$ LazavCopy | OptionalDecider$ You | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card, except its name is Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it has hexproof and this ability. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Graveyard | ValidCard$ Creature.nonToken+OppOwn | TriggerZones$ Battlefield | Execute$ LazavCopy | OptionalDecider$ You | TriggerDescription$ Whenever a creature card is put into an opponent's graveyard from anywhere, you may have CARDNAME become a copy of that card, except its name is Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it has hexproof and this ability. SVar:LazavCopy:DB$ Clone | Defined$ TriggeredCard | NewName$ Lazav, Dimir Mastermind | AddTypes$ Legendary | AddKeywords$ Hexproof | GainThisAbility$ True | Optional$ True | AddSVars$ LazavCopy | AILogic$ IfDefinedCreatureIsBetter Oracle:Hexproof\nWhenever a creature card is put into an opponent's graveyard from anywhere, you may have Lazav, Dimir Mastermind become a copy of that card, except its name is Lazav, Dimir Mastermind, it's legendary in addition to its other types, and it has hexproof and this ability. diff --git a/forge-gui/res/cardsfolder/r/rasputin_dreamweaver.txt b/forge-gui/res/cardsfolder/r/rasputin_dreamweaver.txt index 4937323a179..8478b31d247 100644 --- a/forge-gui/res/cardsfolder/r/rasputin_dreamweaver.txt +++ b/forge-gui/res/cardsfolder/r/rasputin_dreamweaver.txt @@ -4,9 +4,9 @@ Types:Legendary Creature Human Wizard PT:4/1 K:etbCounter:DREAM:7 K:CARDNAME can't have more than seven dream counters on it. -A:AB$ Mana | Cost$ SubCounter<1/DREAM> | Produced$ C | SpellDescription$ Add {C}. -A:AB$ PreventDamage | Cost$ SubCounter<1/DREAM> | Defined$ Self | Amount$ 1 | SpellDescription$ Prevent the next 1 damage that would be dealt to CARDNAME this turn. -T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | IsPresent$ Card.Self+startedTheTurnUntapped | TriggerDescription$ At the beginning of your upkeep, if CARDNAME started the turn untapped, put a dream counter on it. +A:AB$ Mana | Cost$ SubCounter<1/DREAM/NICKNAME> | Produced$ C | SpellDescription$ Add {C}. +A:AB$ PreventDamage | Cost$ SubCounter<1/DREAM/NICKNAME> | Defined$ Self | Amount$ 1 | SpellDescription$ Prevent the next 1 damage that would be dealt to NICKNAME this turn. +T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigPutCounter | IsPresent$ Card.Self+startedTheTurnUntapped | TriggerDescription$ At the beginning of your upkeep, if NICKNAME started the turn untapped, put a dream counter on it. SVar:TrigPutCounter:DB$ PutCounter | Defined$ Self | CounterType$ DREAM | CounterNum$ 1 DeckHas:Ability$Counters Oracle:Rasputin Dreamweaver enters the battlefield with seven dream counters on it.\nRemove a dream counter from Rasputin: Add {C}.\nRemove a dream counter from Rasputin: Prevent the next 1 damage that would be dealt to Rasputin this turn.\nAt the beginning of your upkeep, if Rasputin started the turn untapped, put a dream counter on it.\nRasputin can't have more than seven dream counters on it. diff --git a/forge-gui/res/cardsfolder/t/titania_voice_of_gaea_titania_gaea_incarnate.txt b/forge-gui/res/cardsfolder/t/titania_voice_of_gaea_titania_gaea_incarnate.txt index 62c422f60c4..5e147c85245 100644 --- a/forge-gui/res/cardsfolder/t/titania_voice_of_gaea_titania_gaea_incarnate.txt +++ b/forge-gui/res/cardsfolder/t/titania_voice_of_gaea_titania_gaea_incarnate.txt @@ -5,7 +5,7 @@ PT:3/4 K:Reach T:Mode$ ChangesZoneAll | ValidCards$ Land.YouOwn+nonToken | Origin$ Any | Destination$ Graveyard | TriggerZones$ Battlefield | Execute$ TrigLifegain | TriggerDescription$ Whenever one or more land cards are put into your graveyard from anywhere, you gain 2 life. SVar:TrigLifegain:DB$ GainLife | LifeAmount$ 2 -T:Mode$ Phase | Phase$ Upkeep | CheckSVar$ X | SVarCompare$ GE4 | IsPresent$ Card.Self+YouOwn | IsPresent2$ Land.YouCtrl+YouOwn+namedArgoth; Sanctum of Nature | ValidPlayer$ You | Execute$ Meld | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, if you both own and control CARDNAME and a land named Argoth, Sanctum of Nature, exile them, then meld them into Titania, Gaea Incarnate. +T:Mode$ Phase | Phase$ Upkeep | CheckSVar$ X | SVarCompare$ GE4 | IsPresent$ Card.Self+YouOwn | IsPresent2$ Land.YouCtrl+YouOwn+namedArgoth; Sanctum of Nature | ValidPlayer$ You | Execute$ Meld | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, if there are four or more land cards in your graveyard and you both own and control CARDNAME and a land named Argoth, Sanctum of Nature, exile them, then meld them into Titania, Gaea Incarnate. SVar:Meld:DB$ Meld | Name$ Titania, Gaea Incarnate | Primary$ Titania, Voice of Gaea | Secondary$ Argoth, Sanctum of Nature | SecondaryType$ Land DeckHints:Name$Argoth, Sanctum of Nature MeldPair:Argoth, Sanctum of Nature diff --git a/forge-gui/res/cardsfolder/upcoming/archangel_elspeth.txt b/forge-gui/res/cardsfolder/upcoming/archangel_elspeth.txt new file mode 100644 index 00000000000..c2c464d7ad2 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/archangel_elspeth.txt @@ -0,0 +1,10 @@ +Name:Archangel Elspeth +ManaCost:2 W W +Types:Legendary Planeswalker Elspeth +Loyalty:4 +A:AB$ Token | Cost$ AddCounter<1/LOYALTY> | Planeswalker$ True | TokenScript$ w_1_1_soldier_lifelink | SpellDescription$ Create a 1/1 white Soldier creature token with lifelink. +A:AB$ PutCounter | Cost$ SubCounter<2/LOYALTY> | Planeswalker$ True | CounterType$ P1P1 | CounterNum$ 2 | ValidTgts$ Creature | SubAbility$ DBAnimate | SpellDescription$ Put two +1/+1 counters on target creature. +SVar:DBAnimate:DB$ Animate | Defined$ Targeted | Types$ Angel | Keywords$ Flying | Duration$ Permanent | StackDescription$ SpellDescription | SpellDescription$ It becomes an Angel in addition to its other types and gains flying. +A:AB$ ChangeZoneAll | Cost$ SubCounter<6/LOYALTY> | Planeswalker$ True | Ultimate$ True | Origin$ Graveyard | Destination$ Battlefield | ChangeType$ Permanent.nonLand+YouOwn+cmcLE3 | SpellDescription$ Return all nonland permanent cards with mana value 3 or less from your graveyard to the battlefield. +DeckHas:Ability$Token|LifeGain|Counters|Graveyard & Type$Soldier|Angel +Oracle:[+1]: Create a 1/1 white Soldier creature token with lifelink.\n[-2]: Put two +1/+1 counters on target creature. It becomes an Angel in addition to its other types and gains flying.\n[-6]: Return all nonland permanent cards with mana value 3 or less from your graveyard to the battlefield. diff --git a/forge-gui/res/cardsfolder/upcoming/quicksilver_servitor.txt b/forge-gui/res/cardsfolder/upcoming/quicksilver_servitor.txt new file mode 100644 index 00000000000..609172b0a5f --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/quicksilver_servitor.txt @@ -0,0 +1,10 @@ +Name:Quicksilver Servitor +ManaCost:2 U +Types:Creature Phyrexian Cleric +PT:3/3 +K:Ward:2 +T:Mode$ SpellCast | ValidCard$ Card.ThisTurnEnteredYourHand | ValidActivatingPlayer$ You | Execute$ TrigProliferate | TriggerZones$ Battlefield | TriggerDescription$ Whenever you cast a spell from among cards put into your hand this turn, proliferate. +SVar:TrigProliferate:DB$ Proliferate +DeckHas:Ability$Proliferate +DeckNeeds:Ability$Counters +Oracle:Ward {2}\nWhenever you cast a spell from among cards put into your hand this turn, proliferate. diff --git a/forge-gui/res/cardsfolder/v/venerated_rotpriest.txt b/forge-gui/res/cardsfolder/v/venerated_rotpriest.txt index 1be66c0a610..04ccf2ebf14 100644 --- a/forge-gui/res/cardsfolder/v/venerated_rotpriest.txt +++ b/forge-gui/res/cardsfolder/v/venerated_rotpriest.txt @@ -3,7 +3,7 @@ ManaCost:G Types:Creature Phyrexian Druid PT:1/2 K:Toxic:1 -T:Mode$ BecomesTarget | ValidTarget$ Creature.YouCtrl | ValidSource$ Spell | TriggerZones$ Battlefield | Execute$ TrigPoison | TriggerDescription$ Whenever a creature you control becomes the target of a spell, target opponent gets a poison counter. +T:Mode$ BecomesTarget | ValidTarget$ Creature.YouCtrl+inZoneBattlefield | ValidSource$ Spell | TriggerZones$ Battlefield | Execute$ TrigPoison | TriggerDescription$ Whenever a creature you control becomes the target of a spell, target opponent gets a poison counter. SVar:TrigPoison:DB$ Poison | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | Num$ 1 DeckHas:Ability$Counters DeckHints:Type$Aura diff --git a/forge-gui/res/editions/March of the Machine.txt b/forge-gui/res/editions/March of the Machine.txt index 8718dae384c..76cbf48cbd8 100644 --- a/forge-gui/res/editions/March of the Machine.txt +++ b/forge-gui/res/editions/March of the Machine.txt @@ -12,6 +12,7 @@ ScryfallCode=MOM 67 C Moment of Truth @Rovina Cai 94 R Breach the Multiverse @Liiga Smilshkalne 134 M Chandra, Hope's Beacon @Kieran Yanner +217 M Wrenn and Realmbreaker @Cristi Balanescu 222 R Drana and Linvala @Raluca Marinescu 225 R Ghalta and Mavren @Zezhou Chen 249 R Omnath, Locus of All @Bryan Sola @@ -33,7 +34,9 @@ ScryfallCode=MOM 313 R Omnath, Locus of All @Jessica Rossier 316 M Thalia and The Gitrog Monster @Sami Makkonen 317 R Yargle and Multani @Lisa Heidhoff +320 M Archangel Elspeth @Denys Tsiperko 321 M Chandra, Hope's Beacon @Randy Vargas +322 M Wrenn and Realmbreaker @Jehan Choo 339 M Jin-Gitaxias @Julian Kok Joon Wen 352 R Faerie Mastermind @Joshua Raphael 358 R Breach the Multiverse @Liiga Smilshkalne diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index 9228a73b41b..8f3a7a2df9d 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -896,6 +896,12 @@ ScryfallCode=SLD 1234 R Azusa, Lost but Seeking @Tsubonari 1235 R Teysa Karlov @Tsubonari 1236 R Paradise Mantle @Tsubonari +1237 R Xenk, Paladin Unbroken @Tatiana Vetrova & Jason Li +1238 R Simon, Wild Magic Sorcerer @Shuangcheng Leng +1239 R Forge, Neverwinter Charlatan @Liangliang Zhang +1240 R Holga, Relentless Rager @Yang Luo +1241 R Doric, Nature's Warden @Oiya Zhang & Liangliang Zhang +1242 R Edgin, Larcenous Lutenist @Wenfei Ye 1243 R Ugin, the Ineffable @Sansyu 1244 M Sorin, Imperious Bloodlord @Showichi Furumi 1245 M Sarkhan, Dragonsoul @Miyuki Aramaki diff --git a/forge-gui/res/editions/Store Championships.txt b/forge-gui/res/editions/Store Championships.txt index e6b52c08c16..2f643881cdc 100644 --- a/forge-gui/res/editions/Store Championships.txt +++ b/forge-gui/res/editions/Store Championships.txt @@ -11,7 +11,7 @@ ScryfallCode=SCH 3 R Dark Confidant @Livia Prima 4 R Spell Pierce @Andrew Mar 5 R Gilded Goose @Chris Seaman -6 C Omnath, Locus of Creation @John Tedrick +6 M Omnath, Locus of Creation @John Tedrick 7 R Annex Sentry @Sam Guay 8 R Memory Deluge @Sam Guay -9 M Koth, Fire of Resistance @Kieran Yanner +9 R Koth, Fire of Resistance @Kieran Yanner diff --git a/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java index d98b1516eb8..d2224eec428 100644 --- a/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java +++ b/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java @@ -32,6 +32,7 @@ public final class ForgeConstants { public static final String RES_DIR = ASSETS_DIR + "res" + PATH_SEPARATOR; public static final String ADVENTURE_DIR = RES_DIR + "adventure" + PATH_SEPARATOR; + public static final String ADVENTURE_DEFAULT_PLANE_DIR = ADVENTURE_DIR + "Shandalar" + PATH_SEPARATOR; public static final String LISTS_DIR = RES_DIR + "lists" + PATH_SEPARATOR; public static final String SETLOOKUP_DIR = RES_DIR + "setlookup" + PATH_SEPARATOR; public static final String KEYWORD_LIST_FILE = LISTS_DIR + "NonStackingKWList.txt"; @@ -84,7 +85,7 @@ public final class ForgeConstants { public static final String AI_PROFILE_DIR = RES_DIR + "ai" + PATH_SEPARATOR; public static final String SOUND_DIR = RES_DIR + "sound" + PATH_SEPARATOR; public static final String MUSIC_DIR = RES_DIR + "music" + PATH_SEPARATOR; - public static final String ADVENTURE_MUSIC_DIR = ADVENTURE_DIR + "music" + PATH_SEPARATOR; + public static final String ADVENTURE_MUSIC_DIR = ADVENTURE_DEFAULT_PLANE_DIR + "music" + PATH_SEPARATOR; public static final String LANG_DIR = RES_DIR + "languages" + PATH_SEPARATOR; public static final String EFFECTS_DIR = RES_DIR + "effects" + PATH_SEPARATOR; public static final String PUZZLE_DIR = RES_DIR + "puzzle" + PATH_SEPARATOR; diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index e867b8a4d7b..165c10c5f92 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -47,20 +47,16 @@ import forge.util.collect.FCollectionView; public class HumanCostDecision extends CostDecisionMakerBase { private final PlayerControllerHuman controller; - private final SpellAbility ability; - private final Card source; private String orString = null; private boolean mandatory; - public HumanCostDecision(final PlayerControllerHuman controller, final Player p, final SpellAbility sa, final boolean effect, final Card source) { - this(controller, p, sa, effect, source, null); + public HumanCostDecision(final PlayerControllerHuman controller, final Player p, final SpellAbility sa, final boolean effect) { + this(controller, p, sa, effect, sa.getHostCard(), null); } public HumanCostDecision(final PlayerControllerHuman controller, final Player p, final SpellAbility sa, final boolean effect, final Card source, final String orString) { - super(p, effect); + super(p, effect, sa, source); this.controller = controller; - ability = sa; mandatory = sa.getPayCosts().isMandatory(); - this.source = source; this.orString = orString; } diff --git a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java index 40a0e80cba8..84b01c9b273 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java +++ b/forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java @@ -165,7 +165,7 @@ public class HumanPlaySpellAbility { && ability.canCastTiming(human) && ability.checkRestrictions(human) && ability.isLegalAfterStack() - && (isFree || payment.payCost(new HumanCostDecision(controller, human, ability, false, ability.getHostCard()))); + && (isFree || payment.payCost(new HumanCostDecision(controller, human, ability, false))); game.clearTopLibsCast(ability);