From b54cd071b6aa8ec2f096d061263fb36dc131bdb5 Mon Sep 17 00:00:00 2001 From: Rob Schnautz Date: Sun, 25 Mar 2018 20:41:31 +0000 Subject: [PATCH 01/16] Brawl deck included for testing purposes --- forge-gui/tools/Hautli Crüe.dck | 44 +++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 forge-gui/tools/Hautli Crüe.dck diff --git a/forge-gui/tools/Hautli Crüe.dck b/forge-gui/tools/Hautli Crüe.dck new file mode 100644 index 00000000000..ff88d7970ff --- /dev/null +++ b/forge-gui/tools/Hautli Crüe.dck @@ -0,0 +1,44 @@ +[metadata] +Name=Huatli Crüe +[Commander] +1 Huatli, Radiant Champion +[Main] +1 Adanto Vanguard +1 Adorned Pouncer +1 Aerial Responder +1 Ajani Unyielding +1 Baffling End +1 Bellowing Aegisaur +1 Bishop of Rebirth +1 Bishop's Soldier +1 Cartouche of Solidarity +1 Cast Out +1 Devoted Crop-Mate +1 Fairgrounds Warden +9 Forest +1 Fumigate +1 Growing Rites of Itlimoc +1 Jadelight Ranger +1 Kinjalli's Sunwing +1 Legion's Landing +1 Majestic Myriarch +1 Merfolk Branchwalker +1 Narnam Renegade +1 Oath of Ajani +1 Oketra the True +1 Oketra's Monument +13 Plains +1 Pride of Conquerors +1 Renegade Rallier +1 Resilient Khenra +1 Rishkar, Peema Renegade +1 Sacred Cat +1 Scattered Groves +1 Servo Exhibition +1 Shapers' Sanctuary +1 Skymarcher Aspirant +1 Slaughter the Strong +1 Sram's Expertise +1 Sunpetal Grove +1 Tendershoot Dryad +1 Vizier of Deferment From d7dcc2ae21fc6d65836d6346f1b86874cbc44e73 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 23 Feb 2022 08:00:14 +0800 Subject: [PATCH 02/16] update viewport and hud button bounds --- .../src/forge/adventure/scene/ForgeScene.java | 19 ++----------------- .../src/forge/adventure/stage/GameHUD.java | 15 +++++++++------ .../src/forge/adventure/stage/WorldStage.java | 12 +++++++++++- .../forge/screens/match/MatchController.java | 2 +- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/forge-gui-mobile/src/forge/adventure/scene/ForgeScene.java b/forge-gui-mobile/src/forge/adventure/scene/ForgeScene.java index 5082457fd8f..8cfcac18847 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/ForgeScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/ForgeScene.java @@ -2,14 +2,12 @@ package forge.adventure.scene; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.utils.ScreenUtils; import forge.Forge; import forge.animation.ForgeAnimation; import forge.assets.ImageCache; import forge.gamemodes.match.LobbySlotType; import forge.interfaces.IUpdateable; import forge.screens.FScreen; -import forge.screens.TransitionScreen; import forge.toolbox.FDisplayObject; import forge.toolbox.FOverlay; @@ -68,21 +66,8 @@ public abstract class ForgeScene extends Scene implements IUpdateable { if(getScreen()!=null) getScreen().setSize(Forge.getScreenWidth(), Forge.getScreenHeight()); - if (this instanceof DuelScene) { - Runnable runnable = new Runnable() { - @Override - public void run() { - Forge.clearTransitionScreen(); - Forge.openScreen(getScreen()); - Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); - Gdx.input.setInputProcessor(Forge.getInputProcessor()); - } - }; - Forge.setTransitionScreen(new TransitionScreen(runnable, ScreenUtils.getFrameBufferTexture(), true, false)); - } else { - Forge.openScreen(getScreen()); - Gdx.input.setInputProcessor(Forge.getInputProcessor()); - } + Forge.openScreen(getScreen()); + Gdx.input.setInputProcessor(Forge.getInputProcessor()); } public abstract FScreen getScreen(); diff --git a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java index 0407761e4f3..8f7738c512a 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java +++ b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java @@ -13,10 +13,10 @@ import com.badlogic.gdx.scenes.scene2d.ui.Touchpad.TouchpadStyle; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; -import com.badlogic.gdx.utils.viewport.FitViewport; +import com.badlogic.gdx.utils.Scaling; +import com.badlogic.gdx.utils.viewport.ScalingViewport; import forge.Forge; import forge.adventure.player.AdventurePlayer; -import forge.adventure.scene.Scene; import forge.adventure.scene.SceneType; import forge.adventure.util.Config; import forge.adventure.util.Current; @@ -46,7 +46,7 @@ public class GameHUD extends Stage { float TOUCHPAD_KNOB_MIN_WIDTH = 40f; private GameHUD(GameStage gameStage) { - super(new FitViewport(Scene.GetIntendedWidth(), Scene.GetIntendedHeight()), gameStage.getBatch()); + super(new ScalingViewport(Scaling.fillX, 480f, 270f), gameStage.getBatch()); instance = this; this.gameStage = gameStage; @@ -193,10 +193,11 @@ public class GameHUD extends Stage { float deckY = ui.findActor("deck").getY(); float deckR = ui.findActor("deck").getRight(); float deckT = ui.findActor("deck").getTop(); + float deckOriginX = ui.findActor("deck").getOriginX(); //deck button bounds if (c.x>=deckX&&c.x<=deckR&&c.y>=deckY&&c.y<=deckT) { openDeck(); - stageToScreenCoordinates(c2.set(deckX, deckY)); + stageToScreenCoordinates(c2.set(deckOriginX, deckY)); return super.touchDown((int)c2.x, (int)c2.y, pointer, button); } @@ -204,10 +205,11 @@ public class GameHUD extends Stage { float menuY = ui.findActor("menu").getY(); float menuR = ui.findActor("menu").getRight(); float menuT = ui.findActor("menu").getTop(); + float menuOriginX = ui.findActor("menu").getOriginX(); //menu button bounds if (c.x>=menuX&&c.x<=menuR&&c.y>=menuY&&c.y<=menuT) { menu(); - stageToScreenCoordinates(c2.set(menuX, menuY)); + stageToScreenCoordinates(c2.set(menuOriginX, menuY)); return super.touchDown((int)c2.x, (int)c2.y, pointer, button); } @@ -215,10 +217,11 @@ public class GameHUD extends Stage { float statsY = ui.findActor("statistic").getY(); float statsR = ui.findActor("statistic").getRight(); float statsT = ui.findActor("statistic").getTop(); + float statsOriginX = ui.findActor("statistic").getOriginX(); //stats button bounds if (c.x>=statsX&&c.x<=statsR&&c.y>=statsY&&c.y<=statsT) { statistic(); - stageToScreenCoordinates(c2.set(statsX, statsY)); + stageToScreenCoordinates(c2.set(statsOriginX, statsY)); return super.touchDown((int)c2.x, (int)c2.y, pointer, button); } diff --git a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java index 3271c556226..f4ce00f966e 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java @@ -1,8 +1,10 @@ package forge.adventure.stage; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.utils.ScreenUtils; import com.badlogic.gdx.utils.viewport.Viewport; import forge.Forge; import forge.adventure.character.CharacterSprite; @@ -20,6 +22,7 @@ import forge.adventure.util.SaveFileContent; import forge.adventure.util.SaveFileData; import forge.adventure.world.World; import forge.adventure.world.WorldSave; +import forge.screens.TransitionScreen; import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; @@ -76,10 +79,17 @@ public class WorldStage extends GameStage implements SaveFileContent { if (player.collideWith(mob)) { player.setAnimation(CharacterSprite.AnimationTypes.Attack); mob.setAnimation(CharacterSprite.AnimationTypes.Attack); + Gdx.input.vibrate(50); + Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); + Forge.setTransitionScreen(new TransitionScreen(new Runnable() { + @Override + public void run() { + Forge.clearTransitionScreen(); + } + }, ScreenUtils.getFrameBufferTexture(), true, false)); startPause(1, new Runnable() { @Override public void run() { - ((DuelScene) SceneType.DuelScene.instance).setEnemy(currentMob); ((DuelScene) SceneType.DuelScene.instance).setPlayer(player); Forge.switchScene(SceneType.DuelScene.instance); diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index dc11c7310e1..e70ea8653ed 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -312,10 +312,10 @@ public class MatchController extends AbstractGuiGame { public void run() { Forge.clearTransitionScreen(); Forge.clearCurrentScreen(); - Forge.setCursor(null, "0"); } }; Forge.setTransitionScreen(new TransitionScreen(runnable, ScreenUtils.getFrameBufferTexture(), false, false)); + Forge.setCursor(null, "0"); return; } if (hasLocalPlayers() || getGameView().isMatchOver()) { From 2936380bb8699db35461b2297a92eeaadd1ad8e3 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 23 Feb 2022 13:31:51 +0800 Subject: [PATCH 03/16] update player name when loading save and starting match - todo update some mobile layout --- .../forge/adventure/scene/NewGameScene.java | 6 +- .../src/forge/adventure/scene/StartScene.java | 3 +- .../src/forge/adventure/util/UIActor.java | 3 + .../src/forge/adventure/world/WorldSave.java | 2 + forge-gui-mobile/src/forge/card/CardZoom.java | 2 +- .../screens/constructed/LobbyScreen.java | 4 + .../Shandalar/ui/new_game_mobile.json | 163 ++++++++++++++++++ 7 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json diff --git a/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java b/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java index e41c377a99d..8bc8b18f47f 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java @@ -14,6 +14,7 @@ import forge.adventure.util.Config; import forge.adventure.util.Selector; import forge.adventure.world.WorldSave; import forge.deck.Deck; +import forge.gui.GuiBase; import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; import forge.player.GamePlayerUtil; @@ -36,10 +37,13 @@ public class NewGameScene extends UIScene { private Selector difficulty; public NewGameScene() { - super("ui/new_game.json"); + super(GuiBase.isAndroid() ? "ui/new_game_mobile.json" : "ui/new_game.json"); } public boolean start() { + if(selectedName.getText().isEmpty()) { + selectedName.setText(NameGenerator.getRandomName("Any", "Any", "")); + } Runnable runnable = new Runnable() { @Override public void run() { diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index 2cfb2468317..25da4401dfe 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -37,7 +37,8 @@ public class StartScene extends UIScene { } public boolean Resume() { - Forge.switchToLast(); + //Forge.switchToLast(); + Forge.switchScene(SceneType.GameScene.instance); return true; } diff --git a/forge-gui-mobile/src/forge/adventure/util/UIActor.java b/forge-gui-mobile/src/forge/adventure/util/UIActor.java index 31aa69cf44a..7d02320d897 100644 --- a/forge-gui-mobile/src/forge/adventure/util/UIActor.java +++ b/forge-gui-mobile/src/forge/adventure/util/UIActor.java @@ -137,6 +137,9 @@ public class UIActor extends Group { case "text": newActor.setText(property.value.toString()); break; + case "align": + newActor.setAlignment(((Float) property.value).intValue()); + break; } } } diff --git a/forge-gui-mobile/src/forge/adventure/world/WorldSave.java b/forge-gui-mobile/src/forge/adventure/world/WorldSave.java index 21d5e67bec3..4f2f5f4bf14 100644 --- a/forge-gui-mobile/src/forge/adventure/world/WorldSave.java +++ b/forge-gui-mobile/src/forge/adventure/world/WorldSave.java @@ -9,6 +9,7 @@ import forge.adventure.util.SaveFileData; import forge.adventure.util.SignalList; import forge.deck.Deck; import forge.localinstance.properties.ForgeProfileProperties; +import forge.player.GamePlayerUtil; import java.io.File; import java.io.FileInputStream; @@ -69,6 +70,7 @@ public class WorldSave { currentSave.header = (WorldSaveHeader) oos.readObject(); SaveFileData mainData=(SaveFileData)oos.readObject(); currentSave.player.load(mainData.readSubData("player")); + GamePlayerUtil.getGuiPlayer().setName(currentSave.player.getName()); currentSave.world.load(mainData.readSubData("world")); WorldStage.getInstance().load(mainData.readSubData("worldStage")); diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index 112747c94aa..1bcf288c1e0 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -284,7 +284,7 @@ public class CardZoom extends FOverlay { cardHeight = FCardPanel.ASPECT_RATIO * cardWidth; boolean rotateSplit = FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ROTATE_SPLIT_CARDS); - if (currentCard.isSplitCard() && rotateSplit) { + if (currentCard != null && currentCard.isSplitCard() && rotateSplit) { // card will be rotated. Make sure that the height does not exceed the width of the view if (cardHeight > Gdx.graphics.getWidth()) { diff --git a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java index 7350f457952..7d1555cd531 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java +++ b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import forge.player.GamePlayerUtil; import org.apache.commons.lang3.StringUtils; import com.badlogic.gdx.Gdx; @@ -326,6 +327,9 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { //TODO: Investigate why AI names cannot be overriden? updateName(i, getPlayerName(i)); + if(i == 0 && Forge.isMobileAdventureMode) { + updateName(0, GamePlayerUtil.getGuiPlayer().getName()); + } } FThreads.invokeInBackgroundThread(new Runnable() { //must call startGame in background thread in case there are alerts @Override diff --git a/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json b/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json new file mode 100644 index 00000000000..3a750c995e7 --- /dev/null +++ b/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json @@ -0,0 +1,163 @@ +{ + "width": 480, + "height": 270, + "yDown": true, + "elements": [ + { + "type": "Image", + "image": "ui/title_bg.png", + "width": 480, + "height": 270 + }, + { + "type": "Scroll", + "style": "paper", + "x": 112, + "y": 10, + "width": 256, + "height": 250 + }, + { + "type": "Label", + "text": "Create a Character", + "width": 128, + "height": 32, + "font": "blackbig", + "x": 160, + "y": 16 + }, + { + "type": "Label", + "text": "Avatar:", + "width": 128, + "height": 32, + "x": 160, + "y": 58 + }, + { + "type": "Label", + "text": "Name:", + "width": 128, + "height": 32, + "x": 160, + "y": 90 + }, + { + "type": "Label", + "text": "Race:", + "width": 128, + "height": 32, + "x": 160, + "y": 124 + }, + { + "type": "Label", + "text": "Gender:", + "width": 128, + "height": 32, + "x": 160, + "y": 154 + }, + { + "type": "Label", + "text": "Difficulty:", + "width": 128, + "height": 32, + "x": 160, + "y": 186 + }, + { + "type": "Label", + "text": "Deck:", + "width": 128, + "height": 32, + "x": 160, + "y": 218 + }, + { + "type": "ImageButton", + "name": "leftAvatar", + "style": "leftarrow", + "width": 16, + "height": 16, + "x": 220, + "y": 64 + }, + { + "type": "Image", + "name": "avatarPreview", + "width": 48, + "height": 48, + "x": 252, + "y": 48 + }, + { + "type": "ImageButton", + "name": "rightAvatar", + "style": "rightarrow", + "width": 16, + "height": 16, + "x": 316, + "y": 64 + }, + { + "type": "TextField", + "name": "nameField", + "align": 1, + "width": 112, + "height": 16, + "x": 220, + "y": 96 + }, + { + "type": "Selector", + "name": "race", + "width": 112, + "height": 16, + "x": 220, + "y": 128 + }, + { + "type": "Selector", + "name": "gender", + "width": 112, + "height": 16, + "x": 220, + "y": 160 + }, + { + "type": "Selector", + "name": "difficulty", + "width": 112, + "height": 16, + "x": 220, + "y": 192 + }, + { + "type": "Selector", + "name": "deck", + "width": 112, + "height": 16, + "x": 220, + "y": 224 + }, + { + "type": "TextButton", + "name": "back", + "text": "Back", + "width": 44, + "height": 44, + "x": 38, + "y": 212 + }, + { + "type": "TextButton", + "name": "start", + "text": "Start", + "width": 44, + "height": 44, + "x": 400, + "y": 212 + } + ] +} \ No newline at end of file From 3d8648f7d84040823769e87bbca94d4a4aab99d1 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 23 Feb 2022 14:00:48 +0800 Subject: [PATCH 04/16] update start menu --- .../src/forge/adventure/scene/StartScene.java | 3 +- .../Shandalar/ui/new_game_mobile.json | 4 +- .../adventure/Shandalar/ui/start_menu.json | 115 +++++++++--------- .../Shandalar/ui/start_menu_mobile.json | 67 ++++++++++ 4 files changed, 127 insertions(+), 62 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/start_menu_mobile.json diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index 25da4401dfe..9e87855cc45 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.Input; import com.badlogic.gdx.scenes.scene2d.Actor; import forge.Forge; import forge.adventure.world.WorldSave; +import forge.gui.GuiBase; /** * First scene after the splash screen @@ -16,7 +17,7 @@ public class StartScene extends UIScene { public StartScene() { - super("ui/start_menu.json"); + super(GuiBase.isAndroid() ? "ui/start_menu_mobile.json" : "ui/start_menu.json"); } public boolean NewGame() { diff --git a/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json b/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json index 3a750c995e7..681f1017add 100644 --- a/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json +++ b/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json @@ -146,7 +146,7 @@ "name": "back", "text": "Back", "width": 44, - "height": 44, + "height": 30, "x": 38, "y": 212 }, @@ -155,7 +155,7 @@ "name": "start", "text": "Start", "width": 44, - "height": 44, + "height": 30, "x": 400, "y": 212 } diff --git a/forge-gui/res/adventure/Shandalar/ui/start_menu.json b/forge-gui/res/adventure/Shandalar/ui/start_menu.json index 23de9e0047a..f2f375a7eab 100644 --- a/forge-gui/res/adventure/Shandalar/ui/start_menu.json +++ b/forge-gui/res/adventure/Shandalar/ui/start_menu.json @@ -1,70 +1,67 @@ { - "width": 480, - "height": 270, - "yDown": true, - "elements":[ + "width": 480, + "height": 270, + "yDown": true, + "elements": [ { - "type" : "Image", - "image":"ui/title_bg.png", + "type": "Image", + "image": "ui/title_bg.png", "width": 480, "height": 270 - } - , + }, { - "type" : "TextButton", - "name" : "Start" , - "text" : "New Game", - "width": 120, - "height": 30, - "x": 20, - "y": 20 - } , + "type": "TextButton", + "name": "Start", + "text": "New Game", + "width": 120, + "height": 30, + "x": 20, + "y": 20 + }, { - "type" : "TextButton", - "name" : "Load" , - "text" : "Load", - "width": 120, - "height": 30, - "x": 20, - "y": 60 - } , + "type": "TextButton", + "name": "Load", + "text": "Load", + "width": 120, + "height": 30, + "x": 20, + "y": 60 + }, { - "type" : "TextButton", - "name" : "Save" , - "text" : "Save", - "width": 120, - "height": 30, - "x": 20, - "y": 100 - }, + "type": "TextButton", + "name": "Save", + "text": "Save", + "width": 120, + "height": 30, + "x": 20, + "y": 100 + }, { - "type" : "TextButton", - "name" : "Resume" , - "text" : "Resume", - "width": 120, - "height": 30, - "x": 20, - "y": 140 - } , + "type": "TextButton", + "name": "Resume", + "text": "Resume", + "width": 120, + "height": 30, + "x": 20, + "y": 140 + }, { - "type" : "TextButton", - "name" : "Settings" , - "text" : "Settings", - "width": 120, - "height": 30, - "x": 20, - "y": 180 - } , + "type": "TextButton", + "name": "Settings", + "text": "Settings", + "width": 120, + "height": 30, + "x": 20, + "y": 180 + }, { - "type" : "TextButton", - "name" : "Exit" , - "text" : "Exit", - "width": 120, - "height": 30, - "x": 20, - "y": 220 - } - ] - - + "type": "TextButton", + "name": "Exit", + "text": "Exit", + "width": 120, + "height": 30, + "x": 20, + "y": 220 + } + ] } \ No newline at end of file diff --git a/forge-gui/res/adventure/Shandalar/ui/start_menu_mobile.json b/forge-gui/res/adventure/Shandalar/ui/start_menu_mobile.json new file mode 100644 index 00000000000..d130042cef9 --- /dev/null +++ b/forge-gui/res/adventure/Shandalar/ui/start_menu_mobile.json @@ -0,0 +1,67 @@ +{ + "width": 480, + "height": 270, + "yDown": true, + "elements": [ + { + "type": "Image", + "image": "ui/title_bg.png", + "width": 480, + "height": 270 + }, + { + "type": "TextButton", + "name": "Start", + "text": "New Game", + "width": 160, + "height": 30, + "x": 160, + "y": 20 + }, + { + "type": "TextButton", + "name": "Load", + "text": "Load", + "width": 160, + "height": 30, + "x": 160, + "y": 60 + }, + { + "type": "TextButton", + "name": "Save", + "text": "Save", + "width": 160, + "height": 30, + "x": 160, + "y": 100 + }, + { + "type": "TextButton", + "name": "Resume", + "text": "Resume", + "width": 160, + "height": 30, + "x": 160, + "y": 140 + }, + { + "type": "TextButton", + "name": "Settings", + "text": "Settings", + "width": 160, + "height": 30, + "x": 160, + "y": 180 + }, + { + "type": "TextButton", + "name": "Exit", + "text": "Exit", + "width": 160, + "height": 30, + "x": 160, + "y": 220 + } + ] +} \ No newline at end of file From dc4eed4b0877cf1967db4faca7521164c0d15996 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 23 Feb 2022 14:06:30 +0800 Subject: [PATCH 05/16] Revert "Brawl deck included for testing purposes" This reverts commit b54cd071b6aa8ec2f096d061263fb36dc131bdb5. --- forge-gui/tools/Hautli Crüe.dck | 44 --------------------------------- 1 file changed, 44 deletions(-) delete mode 100644 forge-gui/tools/Hautli Crüe.dck diff --git a/forge-gui/tools/Hautli Crüe.dck b/forge-gui/tools/Hautli Crüe.dck deleted file mode 100644 index ff88d7970ff..00000000000 --- a/forge-gui/tools/Hautli Crüe.dck +++ /dev/null @@ -1,44 +0,0 @@ -[metadata] -Name=Huatli Crüe -[Commander] -1 Huatli, Radiant Champion -[Main] -1 Adanto Vanguard -1 Adorned Pouncer -1 Aerial Responder -1 Ajani Unyielding -1 Baffling End -1 Bellowing Aegisaur -1 Bishop of Rebirth -1 Bishop's Soldier -1 Cartouche of Solidarity -1 Cast Out -1 Devoted Crop-Mate -1 Fairgrounds Warden -9 Forest -1 Fumigate -1 Growing Rites of Itlimoc -1 Jadelight Ranger -1 Kinjalli's Sunwing -1 Legion's Landing -1 Majestic Myriarch -1 Merfolk Branchwalker -1 Narnam Renegade -1 Oath of Ajani -1 Oketra the True -1 Oketra's Monument -13 Plains -1 Pride of Conquerors -1 Renegade Rallier -1 Resilient Khenra -1 Rishkar, Peema Renegade -1 Sacred Cat -1 Scattered Groves -1 Servo Exhibition -1 Shapers' Sanctuary -1 Skymarcher Aspirant -1 Slaughter the Strong -1 Sram's Expertise -1 Sunpetal Grove -1 Tendershoot Dryad -1 Vizier of Deferment From aa0fca7b68989e38f3d17e8db4805e324146f1ab Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 23 Feb 2022 16:09:55 +0800 Subject: [PATCH 06/16] update new game, save load and settings --- .../forge/adventure/scene/NewGameScene.java | 19 +++--- .../forge/adventure/scene/SaveLoadScene.java | 37 +++++++----- .../forge/adventure/scene/SettingsScene.java | 37 +++++++----- .../Shandalar/ui/new_game_mobile.json | 8 +-- .../Shandalar/ui/save_load_mobile.json | 60 +++++++++++++++++++ .../Shandalar/ui/settings_mobile.json | 30 ++++++++++ 6 files changed, 145 insertions(+), 46 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/save_load_mobile.json create mode 100644 forge-gui/res/adventure/Shandalar/ui/settings_mobile.json diff --git a/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java b/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java index 8bc8b18f47f..86af79d70b1 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/NewGameScene.java @@ -41,7 +41,7 @@ public class NewGameScene extends UIScene { } public boolean start() { - if(selectedName.getText().isEmpty()) { + if (selectedName.getText().isEmpty()) { selectedName.setText(NameGenerator.getRandomName("Any", "Any", "")); } Runnable runnable = new Runnable() { @@ -53,7 +53,7 @@ public class NewGameScene extends UIScene { race.getCurrentIndex(), avatarIndex, deck.getCurrentIndex(), - Config.instance().getConfigData().difficulties[difficulty.getCurrentIndex()],0); + Config.instance().getConfigData().difficulties[difficulty.getCurrentIndex()], 0); GamePlayerUtil.getGuiPlayer().setName(selectedName.getText()); Forge.clearTransitionScreen(); Forge.switchScene(SceneType.GameScene.instance); @@ -82,7 +82,7 @@ public class NewGameScene extends UIScene { return NewGameScene.this.updateAvatar(); } }); - Random rand=new Random(); + Random rand = new Random(); deck = ui.findActor("deck"); @@ -104,18 +104,17 @@ public class NewGameScene extends UIScene { difficulty = ui.findActor("difficulty"); Array diffList = new Array<>(starterDeck.length); - int i=0; - int startingDifficulty=0; - for (DifficultyData diff : Config.instance().getConfigData().difficulties) - { - if(diff.startingDifficulty) - startingDifficulty=i; + int i = 0; + int startingDifficulty = 0; + for (DifficultyData diff : Config.instance().getConfigData().difficulties) { + if (diff.startingDifficulty) + startingDifficulty = i; diffList.add(diff.name); i++; } difficulty.setTextList(diffList); difficulty.setCurrentIndex(startingDifficulty); - avatarIndex=rand.nextInt(); + avatarIndex = rand.nextInt(); gender.setCurrentIndex(rand.nextInt()); deck.setCurrentIndex(rand.nextInt()); race.setCurrentIndex(rand.nextInt()); diff --git a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java index 069e0823247..e0b22e71375 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java @@ -20,6 +20,7 @@ import forge.Forge; import forge.adventure.util.Controls; import forge.adventure.world.WorldSave; import forge.adventure.world.WorldSaveHeader; +import forge.gui.GuiBase; import forge.screens.TransitionScreen; import java.io.File; @@ -30,7 +31,6 @@ import java.util.zip.InflaterInputStream; /** * Scene to load and save the game. - * */ public class SaveLoadScene extends UIScene { private final IntMap buttons = new IntMap<>(); @@ -43,17 +43,16 @@ public class SaveLoadScene extends UIScene { Label header; int currentSlot = -3; Image previewImage; + Image previewBorder; TextButton saveLoadButton; TextButton quickSave; TextButton autoSave; public SaveLoadScene() { - super("ui/save_load.json"); + super(GuiBase.isAndroid() ? "ui/save_load_mobile.json" : "ui/save_load.json"); } - - private TextButton addSaveSlot(String name, int i) { layout.add(Controls.newLabel(name)).colspan(1).align(Align.right).expandX(); layout.add(Controls.newLabel(" ")); @@ -88,9 +87,16 @@ public class SaveLoadScene extends UIScene { if (header.preview != null) { previewImage.setDrawable(new TextureRegionDrawable(new Texture(header.preview))); previewImage.layout(); + previewImage.setVisible(true); + previewBorder.setVisible(true); } + } else { + if (previewImage != null) + previewImage.setVisible(false); + if (previewBorder != null) + previewBorder.setVisible(false); } - for (IntMap.Entry butt : new IntMap.Entries (buttons)) { + for (IntMap.Entry butt : new IntMap.Entries(buttons)) { butt.value.setColor(defColor); } if (buttons.containsKey(slot)) { @@ -123,18 +129,16 @@ public class SaveLoadScene extends UIScene { } @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { - back(); + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE) { + back(); } return true; } + public void save() { dialog.hide(); - if( WorldSave.getCurrentSave().save(textInput.getText(), currentSlot)) - { + if (WorldSave.getCurrentSave().save(textInput.getText(), currentSlot)) { updateFiles(); Forge.switchScene(SceneType.GameScene.instance); } @@ -147,7 +151,7 @@ public class SaveLoadScene extends UIScene { File f = new File(WorldSave.getSaveDir()); f.mkdirs(); File[] names = f.listFiles(); - if(names==null) + if (names == null) throw new RuntimeException("Can not find save directory"); previews.clear(); for (File name : names) { @@ -159,7 +163,7 @@ public class SaveLoadScene extends UIScene { ObjectInputStream oos = new ObjectInputStream(inf)) { - int slot=WorldSave.filenameToSlot(name.getName()); + int slot = WorldSave.filenameToSlot(name.getName()); WorldSaveHeader header = (WorldSaveHeader) oos.readObject(); buttons.get(slot).setText(header.name); previews.put(slot, header); @@ -222,12 +226,13 @@ public class SaveLoadScene extends UIScene { })).align(Align.left); previewImage = ui.findActor("preview"); + previewBorder = ui.findActor("preview_border"); header = Controls.newLabel("Save"); header.setHeight(header.getHeight() * 2); layout.add(header).colspan(3).align(Align.center).expand(); layout.row(); - autoSave=addSaveSlot("Auto save", WorldSave.AUTO_SAVE_SLOT); - quickSave=addSaveSlot("Quick save", WorldSave.QUICK_SAVE_SLOT); + autoSave = addSaveSlot("Auto save", WorldSave.AUTO_SAVE_SLOT); + quickSave = addSaveSlot("Quick save", WorldSave.QUICK_SAVE_SLOT); for (int i = 1; i < 11; i++) addSaveSlot("Slot:" + i, i); diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index f0489a92478..49f69083871 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -37,7 +37,7 @@ public class SettingsScene extends UIScene { private Table settingGroup; public SettingsScene() { - super("ui/settings.json"); + super(GuiBase.isAndroid() ? "ui/settings_mobile.json" : "ui/settings.json"); } @@ -63,18 +63,18 @@ public class SettingsScene extends UIScene { } @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE) { back(); } return true; } + public boolean back() { Forge.switchToLast(); return true; } + private void addInputField(String name, ForgePreferences.FPref pref) { @@ -91,6 +91,7 @@ public class SettingsScene extends UIScene { addLabel(name); settingGroup.add(box).align(Align.right); } + private void addCheckBox(String name, ForgePreferences.FPref pref) { @@ -107,9 +108,10 @@ public class SettingsScene extends UIScene { addLabel(name); settingGroup.add(box).align(Align.right); } - private void addSettingSlider(String name, ForgePreferences.FPref pref, int min,int max) { - Slider slide = Controls.newSlider(min,max, 1, false); + private void addSettingSlider(String name, ForgePreferences.FPref pref, int min, int max) { + + Slider slide = Controls.newSlider(min, max, 1, false); slide.setValue(Preference.getPrefInt(pref)); slide.addListener(new ChangeListener() { @Override @@ -121,6 +123,7 @@ public class SettingsScene extends UIScene { addLabel(name); settingGroup.add(slide).align(Align.right); } + private void addSettingField(String name, boolean value, ChangeListener change) { CheckBox box = Controls.newCheckBox(""); @@ -129,6 +132,7 @@ public class SettingsScene extends UIScene { addLabel(name); settingGroup.add(box).align(Align.right); } + private void addSettingField(String name, int value, ChangeListener change) { @@ -145,14 +149,15 @@ public class SettingsScene extends UIScene { addLabel(name); settingGroup.add(text).align(Align.right); } - void addLabel( String name) - { - Label label = new Label(name, Controls.GetSkin().get("white",Label.LabelStyle.class)); + void addLabel(String name) { + + Label label = new Label(name, Controls.GetSkin().get("white", Label.LabelStyle.class)); settingGroup.row().space(5); settingGroup.add(label).align(Align.left).fillX(); } + @Override public void resLoaded() { super.resLoaded(); @@ -165,7 +170,7 @@ public class SettingsScene extends UIScene { SelectBox plane = Controls.newComboBox(Config.instance().getAllAdventures(), Config.instance().getSettingData().plane, new Function() { @Override public Void apply(Object o) { - Config.instance().getSettingData().plane= (String) o; + Config.instance().getSettingData().plane = (String) o; Config.instance().saveSettings(); return null; } @@ -177,7 +182,7 @@ public class SettingsScene extends UIScene { SelectBox videomode = Controls.newComboBox(new String[]{"720p", "768p", "900p", "1080p"}, Config.instance().getSettingData().videomode, new Function() { @Override public Void apply(Object o) { - String mode = (String)o; + String mode = (String) o; if (mode == null) mode = "720p"; Config.instance().getSettingData().videomode = mode; @@ -209,7 +214,7 @@ public class SettingsScene extends UIScene { @Override public void changed(ChangeEvent event, Actor actor) { boolean value = ((CheckBox) actor).isChecked(); - Config.instance().getSettingData().fullScreen=value; + Config.instance().getSettingData().fullScreen = value; Config.instance().saveSettings(); //update if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_FULLSCREEN_MODE) != value) { @@ -220,10 +225,10 @@ public class SettingsScene extends UIScene { }); } addCheckBox(localizer.getMessage("lblCardName"), ForgePreferences.FPref.UI_OVERLAY_CARD_NAME); - addSettingSlider(localizer.getMessage("cbAdjustMusicVolume"), ForgePreferences.FPref.UI_VOL_MUSIC,0,100); - addSettingSlider(localizer.getMessage("cbAdjustSoundsVolume"), ForgePreferences.FPref.UI_VOL_SOUNDS, 0,100); + addSettingSlider(localizer.getMessage("cbAdjustMusicVolume"), ForgePreferences.FPref.UI_VOL_MUSIC, 0, 100); + addSettingSlider(localizer.getMessage("cbAdjustSoundsVolume"), ForgePreferences.FPref.UI_VOL_SOUNDS, 0, 100); addCheckBox(localizer.getMessage("lblManaCost"), ForgePreferences.FPref.UI_OVERLAY_CARD_MANA_COST); - addCheckBox(localizer.getMessage("lblPowerOrToughness"), ForgePreferences.FPref.UI_OVERLAY_CARD_POWER); + addCheckBox(localizer.getMessage("lblPowerOrToughness"), ForgePreferences.FPref.UI_OVERLAY_CARD_POWER); addCheckBox(localizer.getMessage("lblCardID"), ForgePreferences.FPref.UI_OVERLAY_CARD_ID); addCheckBox(localizer.getMessage("lblAbilityIcon"), ForgePreferences.FPref.UI_OVERLAY_ABILITY_ICONS); addCheckBox(localizer.getMessage("cbImageFetcher"), ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER); diff --git a/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json b/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json index 681f1017add..d285e213c54 100644 --- a/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json +++ b/forge-gui/res/adventure/Shandalar/ui/new_game_mobile.json @@ -145,18 +145,18 @@ "type": "TextButton", "name": "back", "text": "Back", - "width": 44, + "width": 48, "height": 30, - "x": 38, + "x": 36, "y": 212 }, { "type": "TextButton", "name": "start", "text": "Start", - "width": 44, + "width": 48, "height": 30, - "x": 400, + "x": 398, "y": 212 } ] diff --git a/forge-gui/res/adventure/Shandalar/ui/save_load_mobile.json b/forge-gui/res/adventure/Shandalar/ui/save_load_mobile.json new file mode 100644 index 00000000000..f04fe6a9c60 --- /dev/null +++ b/forge-gui/res/adventure/Shandalar/ui/save_load_mobile.json @@ -0,0 +1,60 @@ +{ + "width": 480, + "height": 270, + "yDown": true, + "elements": [ + { + "type": "Image", + "image": "ui/title_bg.png", + "width": 480, + "height": 270 + }, + { + "type": "Scroll", + "name": "saveSlots", + "x": 25, + "y": 18, + "width": 430, + "height": 235 + }, + { + "type": "Image", + "name" : "preview_border", + "image": "ui/avatarhud.png", + "width": 96, + "height": 54, + "x": 350, + "y": 26 + }, + { + "type": "Image", + "name": "preview", + "width": 86, + "height": 48, + "x": 356, + "y": 29 + }, + { + "type": "TextButton", + "name": "return", + "text": "Back", + "width": 48, + "height": 30, + "x": 36, + "y": 212 + }, + { + "type": "TextButton", + "name": "save", + "text": "saveLoad", + "width": 48, + "height": 30, + "x": 398, + "y": 212 + }, + { + "type": "Table", + "font": "default" + } + ] +} \ No newline at end of file diff --git a/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json b/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json new file mode 100644 index 00000000000..66acc70e657 --- /dev/null +++ b/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json @@ -0,0 +1,30 @@ +{ + "width": 480, + "height": 270, + "yDown": true, + "elements": [ + { + "type": "Image", + "image": "ui/title_bg.png", + "width": 480, + "height": 270 + }, + { + "type": "Scroll", + "name": "settings", + "x": 25, + "y": 18, + "width": 430, + "height": 235 + }, + { + "type": "ImageButton", + "name": "return", + "style": "leftarrow", + "width": 32, + "height": 32, + "x": 25, + "y": 220 + } + ] +} \ No newline at end of file From 802f9837bdea5ef7e2566d36c556334c4d4f0ff2 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 23 Feb 2022 21:22:07 +0800 Subject: [PATCH 07/16] update settings check box and back button --- .../forge/adventure/scene/SettingsScene.java | 27 +++++++++++++++---- .../src/forge/adventure/util/Controls.java | 6 +++-- .../Shandalar/ui/settings_mobile.json | 6 ++--- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index 49f69083871..f39abcf6039 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; +import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; import com.badlogic.gdx.scenes.scene2d.ui.SelectBox; @@ -15,6 +16,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.ui.TextField; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.utils.Align; +import com.badlogic.gdx.utils.Scaling; import forge.Forge; import forge.adventure.util.Config; import forge.adventure.util.Controls; @@ -93,9 +95,12 @@ public class SettingsScene extends UIScene { } private void addCheckBox(String name, ForgePreferences.FPref pref) { - - CheckBox box = Controls.newCheckBox(""); + if (GuiBase.isAndroid()) { + box.getImage().setScaling(Scaling.fill); + box.getImageCell().size(12, 12); + box.getImageCell().pad(2); + } box.setChecked(Preference.getPrefBoolean(pref)); box.addListener(new ChangeListener() { @Override @@ -110,7 +115,6 @@ public class SettingsScene extends UIScene { } private void addSettingSlider(String name, ForgePreferences.FPref pref, int min, int max) { - Slider slide = Controls.newSlider(min, max, 1, false); slide.setValue(Preference.getPrefInt(pref)); slide.addListener(new ChangeListener() { @@ -127,6 +131,11 @@ public class SettingsScene extends UIScene { private void addSettingField(String name, boolean value, ChangeListener change) { CheckBox box = Controls.newCheckBox(""); + if (GuiBase.isAndroid()) { + box.getImage().setScaling(Scaling.fill); + box.getImageCell().size(12, 12); + box.getImageCell().pad(2); + } box.setChecked(value); box.addListener(change); addLabel(name); @@ -176,7 +185,7 @@ public class SettingsScene extends UIScene { } }); addLabel("Plane"); - settingGroup.add(plane).align(Align.right); + settingGroup.add(plane).align(Align.right).pad(2); if (!GuiBase.isAndroid()) { SelectBox videomode = Controls.newComboBox(new String[]{"720p", "768p", "900p", "1080p"}, Config.instance().getSettingData().videomode, new Function() { @@ -209,7 +218,7 @@ public class SettingsScene extends UIScene { } }); addLabel("Video Mode (Restart to apply)"); - settingGroup.add(videomode).align(Align.right); + settingGroup.add(videomode).align(Align.right).pad(2); addSettingField("Fullscreen", Config.instance().getSettingData().fullScreen, new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { @@ -250,6 +259,14 @@ public class SettingsScene extends UIScene { settingGroup.row(); + if (GuiBase.isAndroid()) { + ImageButton back = ui.findActor("return"); + back.getImage().setScaling(Scaling.fill); + back.getImageCell().size(12, 12); + back.getImageCell().pad(2); + back.getImage().setFillParent(true); + } + ui.onButtonPress("return", new Runnable() { @Override public void run() { diff --git a/forge-gui-mobile/src/forge/adventure/util/Controls.java b/forge-gui-mobile/src/forge/adventure/util/Controls.java index aab97b4cc1f..2ed943b6e58 100644 --- a/forge-gui-mobile/src/forge/adventure/util/Controls.java +++ b/forge-gui-mobile/src/forge/adventure/util/Controls.java @@ -15,6 +15,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.TextField; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.utils.Align; import java.util.function.Function; @@ -30,8 +31,8 @@ public class Controls { } static public SelectBox newComboBox(String[] text, String item, Function func) { - SelectBox ret = new SelectBox(GetSkin()); + ret.getStyle().listStyle.selection.setTopHeight(4); ret.setItems(text); ret.addListener(new ChangeListener() { @Override @@ -44,8 +45,9 @@ public class Controls { } }); func.apply(item); - + ret.getList().setAlignment(Align.center); ret.setSelected(item); + ret.setAlignment(Align.right); return ret; } diff --git a/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json b/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json index 66acc70e657..ffeb2ec7c5a 100644 --- a/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json +++ b/forge-gui/res/adventure/Shandalar/ui/settings_mobile.json @@ -21,10 +21,8 @@ "type": "ImageButton", "name": "return", "style": "leftarrow", - "width": 32, - "height": 32, - "x": 25, - "y": 220 + "x": 32, + "y": 230 } ] } \ No newline at end of file From 94594673e038bb27b576ced06c74e1bd6e98bc66 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 24 Feb 2022 02:07:35 +0800 Subject: [PATCH 08/16] update --- .../forge/adventure/scene/SaveLoadScene.java | 13 ++---- .../forge/adventure/scene/SettingsScene.java | 19 ++------ .../res/adventure/Shandalar/ui/blank.png | Bin 0 -> 1369 bytes .../Shandalar/ui/new_game_mobile.json | 44 +++++++++--------- .../Shandalar/ui/save_load_mobile.json | 32 ++++++++----- .../Shandalar/ui/settings_mobile.json | 14 +++--- 6 files changed, 58 insertions(+), 64 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/blank.png diff --git a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java index e0b22e71375..ae0222fa8ae 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java @@ -54,8 +54,7 @@ public class SaveLoadScene extends UIScene { private TextButton addSaveSlot(String name, int i) { - layout.add(Controls.newLabel(name)).colspan(1).align(Align.right).expandX(); - layout.add(Controls.newLabel(" ")); + layout.add(Controls.newLabel(name)).align(Align.left).pad(4, 10, 4, 15); TextButton button = Controls.newTextButton("..."); button.addListener(new ClickListener() { @Override @@ -68,7 +67,7 @@ public class SaveLoadScene extends UIScene { } } }); - layout.add(button).colspan(2).align(Align.left).expandX(); + layout.add(button).align(Align.left).expandX(); buttons.put(i, button); layout.row(); return button; @@ -88,13 +87,10 @@ public class SaveLoadScene extends UIScene { previewImage.setDrawable(new TextureRegionDrawable(new Texture(header.preview))); previewImage.layout(); previewImage.setVisible(true); - previewBorder.setVisible(true); } } else { if (previewImage != null) previewImage.setVisible(false); - if (previewBorder != null) - previewBorder.setVisible(false); } for (IntMap.Entry butt : new IntMap.Entries(buttons)) { butt.value.setColor(defColor); @@ -229,7 +225,8 @@ public class SaveLoadScene extends UIScene { previewBorder = ui.findActor("preview_border"); header = Controls.newLabel("Save"); header.setHeight(header.getHeight() * 2); - layout.add(header).colspan(3).align(Align.center).expand(); + header.setAlignment(Align.center); + layout.add(header).pad(2).colspan(4).align(Align.center).expand(); layout.row(); autoSave = addSaveSlot("Auto save", WorldSave.AUTO_SAVE_SLOT); quickSave = addSaveSlot("Quick save", WorldSave.QUICK_SAVE_SLOT); @@ -249,8 +246,8 @@ public class SaveLoadScene extends UIScene { SaveLoadScene.this.back(); } }); - defColor = saveLoadButton.getColor(); + defColor = saveLoadButton.getColor(); ScrollPane scrollPane = ui.findActor("saveSlots"); scrollPane.setActor(layout); diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index f39abcf6039..64f067ee035 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -99,7 +99,7 @@ public class SettingsScene extends UIScene { if (GuiBase.isAndroid()) { box.getImage().setScaling(Scaling.fill); box.getImageCell().size(12, 12); - box.getImageCell().pad(2); + box.getImageCell().pad(2, 2, 2, 10); } box.setChecked(Preference.getPrefBoolean(pref)); box.addListener(new ChangeListener() { @@ -134,7 +134,7 @@ public class SettingsScene extends UIScene { if (GuiBase.isAndroid()) { box.getImage().setScaling(Scaling.fill); box.getImageCell().size(12, 12); - box.getImageCell().pad(2); + box.getImageCell().pad(2, 2, 2, 10); } box.setChecked(value); box.addListener(change); @@ -143,8 +143,6 @@ public class SettingsScene extends UIScene { } private void addSettingField(String name, int value, ChangeListener change) { - - TextField text = Controls.newTextField(String.valueOf(value)); text.setTextFieldFilter(new TextField.TextFieldFilter() { @Override @@ -153,18 +151,14 @@ public class SettingsScene extends UIScene { } }); text.addListener(change); - - addLabel(name); settingGroup.add(text).align(Align.right); } void addLabel(String name) { - Label label = new Label(name, Controls.GetSkin().get("white", Label.LabelStyle.class)); - settingGroup.row().space(5); - settingGroup.add(label).align(Align.left).fillX(); + settingGroup.add(label).align(Align.left).pad(2,2, 2, 5); } @Override @@ -259,13 +253,6 @@ public class SettingsScene extends UIScene { settingGroup.row(); - if (GuiBase.isAndroid()) { - ImageButton back = ui.findActor("return"); - back.getImage().setScaling(Scaling.fill); - back.getImageCell().size(12, 12); - back.getImageCell().pad(2); - back.getImage().setFillParent(true); - } ui.onButtonPress("return", new Runnable() { @Override diff --git a/forge-gui/res/adventure/Shandalar/ui/blank.png b/forge-gui/res/adventure/Shandalar/ui/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..a81df58420200ac087ba9b0907a112e726e8abe9 GIT binary patch literal 1369 zcmbVMzi!h&7&jFI6qNylRG5srfWY>}antxzQ-!!Ck#GrVq=t>l`I1 z`P>qGms;I#u$+$?j}l3`a5;U?NUvV6O48Zyey1zC?tM&opb?Mvm^KX}Kugl*)-)pY zfC;(B27YKOKR$d?WZ$!u{dE_)QJoF_#!<}nj&?ir=zv}{r7=;O* z+DgWYVW0li6*+^516!%33gxcblIuKXaz#TbMaYmhEUi>A%N2B6HjsgIWay=`ib@!5 zV8f8}M*(fI*T-#VC)WihTNw%wVO^h0CfcN|@pzz@EXztc3_}Hkn#@8$rfQh1Ef^e@ z(AbZJ&qFz7Bt1SBwgQ&UT?nFrHcav`LBRAWiS&|&QkOEIM+;mujz^htkLqm10v3t{ zu%!YEQF7e^ek^Se6zD{3AA&`>Z^xpO&MabjnZSQ9e6~Le*<&R@6S$zdKCA091w_-ACLjlqi~REb6wmF6G1}CnvSi2shaP5V3b)d zSteCYv*)RnWv;8$Dx>N;?N=%kl?_Du3wejrahkz}y!W5-4`LrWh>T9pQ)CF&`H06Z z_aMsUw0^TX!VN!xWX-{nE1wI1GYxTTCE06f=y4Ft}ovP**NSHJEOf pnog~=dX=^w8lRu9?!0+_UHaPA-+p}g Date: Thu, 24 Feb 2022 02:29:13 +0800 Subject: [PATCH 09/16] update deck selector --- .../adventure/scene/DeckSelectScene.java | 40 ++++------ .../adventure/Shandalar/ui/deck_selector.json | 75 +++++++++---------- .../Shandalar/ui/deck_selector_mobile.json | 48 ++++++++++++ 3 files changed, 99 insertions(+), 64 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/deck_selector_mobile.json diff --git a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java index a2eb0805322..487530958e8 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java @@ -16,6 +16,7 @@ import forge.Forge; import forge.adventure.player.AdventurePlayer; import forge.adventure.util.Controls; import forge.adventure.util.Current; +import forge.gui.GuiBase; public class DeckSelectScene extends UIScene { private final IntMap buttons = new IntMap<>(); @@ -27,19 +28,16 @@ public class DeckSelectScene extends UIScene { int currentSlot = 0; public DeckSelectScene() { - super("ui/deck_selector.json"); + super(GuiBase.isAndroid() ? "ui/deck_selector_mobile.json" : "ui/deck_selector.json"); } - - - private TextButton addDeckSlot(String name, int i) { TextButton button = Controls.newTextButton("-"); button.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { try { - if(!button.isDisabled()) + if (!button.isDisabled()) select(i); } catch (Exception e) { e.printStackTrace(); @@ -47,12 +45,11 @@ public class DeckSelectScene extends UIScene { } }); - layout.add(Controls.newLabel(name)).expandX(); - layout.add(button).expandX(); + layout.add(Controls.newLabel(name)).expandX().pad(2); + layout.add(button).expandX().pad(2); buttons.put(i, button); layout.row(); return button; - } public void back() { @@ -62,7 +59,7 @@ public class DeckSelectScene extends UIScene { public boolean select(int slot) { currentSlot = slot; - for (IntMap.Entry butt : new IntMap.Entries (buttons)) { + for (IntMap.Entry butt : new IntMap.Entries(buttons)) { butt.value.setColor(defColor); } if (buttons.containsKey(slot)) { @@ -75,23 +72,19 @@ public class DeckSelectScene extends UIScene { } - @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE) { back(); } return true; } + @Override public void enter() { select(Current.player().getSelectedDeckIndex()); - for(int i=0;i Date: Thu, 24 Feb 2022 03:18:51 +0800 Subject: [PATCH 10/16] update stats --- .../adventure/scene/PlayerStatisticScene.java | 68 ++++---- .../res/adventure/Shandalar/ui/statistic.json | 145 ++++++++++-------- 2 files changed, 116 insertions(+), 97 deletions(-) diff --git a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java index 6d8aa3ebf39..188992d9377 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java @@ -13,17 +13,19 @@ import forge.adventure.data.EnemyData; import forge.adventure.data.WorldData; import forge.adventure.util.Controls; import forge.adventure.util.Current; +import forge.player.GamePlayerUtil; import org.apache.commons.lang3.tuple.Pair; import java.util.Map; -public class PlayerStatisticScene extends UIScene { +public class PlayerStatisticScene extends UIScene { Image avatar; Label totalWins; Label totalLoss; Label lossWinRatio; + Label playerName; private Table enemiesGroup; public PlayerStatisticScene() { @@ -37,64 +39,63 @@ public class PlayerStatisticScene extends UIScene { @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE) { back(); } return true; } + public boolean back() { Forge.switchToLast(); return true; } + @Override public void enter() { super.enter(); enemiesGroup.clear(); - enemiesGroup.add("Avatar").align(Align.center).space(3,10,3,10); - enemiesGroup.add("Name").fillX().align(Align.center).fillX().space(3,10,3,60); - enemiesGroup.add(("Win")).align(Align.center).space(3,5,3,5); - enemiesGroup.add(("/")).align(Align.center).space(3,5,3,5); - enemiesGroup.add("Loss").align(Align.center).space(3,5,3,5); + enemiesGroup.add("Avatar").align(Align.center).space(3, 10, 3, 10); + enemiesGroup.add("Name").fillX().align(Align.center).fillX().space(3, 10, 3, 60); + enemiesGroup.add(("Win")).align(Align.center).space(3, 5, 3, 5); + enemiesGroup.add(("/")).align(Align.center).space(3, 5, 3, 5); + enemiesGroup.add("Loss").align(Align.center).space(3, 5, 3, 5); enemiesGroup.row().space(8); - if(avatar!=null) - { + if (playerName != null) { + playerName.setText(GamePlayerUtil.getGuiPlayer().getName()); + } + if (avatar != null) { avatar.setDrawable(new TextureRegionDrawable(Current.player().avatar())); } - if(totalWins!=null) - { + if (totalWins != null) { totalWins.setText(Current.player().getStatistic().totalWins()); } - if(totalLoss!=null) - { + if (totalLoss != null) { totalLoss.setText(Current.player().getStatistic().totalLoss()); } - if(lossWinRatio!=null) - { + if (lossWinRatio != null) { lossWinRatio.setText(Float.toString(Current.player().getStatistic().winLossRatio())); } - for(Map.Entry> entry : Current.player().getStatistic().getWinLossRecord().entrySet()) - { - EnemyData data=WorldData.getEnemy(entry.getKey()); - if(data==null)continue; - Image enemyImage=new Image(); + for (Map.Entry> entry : Current.player().getStatistic().getWinLossRecord().entrySet()) { + EnemyData data = WorldData.getEnemy(entry.getKey()); + if (data == null) continue; + Image enemyImage = new Image(); enemyImage.setDrawable(new TextureRegionDrawable(new EnemySprite(data).getAvatar())); - enemyImage.setSize(8,8); + enemyImage.setSize(8, 8); - enemiesGroup.add(enemyImage).align(Align.center).space(3,10,3,10); - enemiesGroup.add((data.name)).fillX().align(Align.center).fillX().space(3,10,3,10); - enemiesGroup.add((entry.getValue().getLeft().toString())).space(3,2,3,2); - enemiesGroup.add(("/")).align(Align.center).space(3,2,3,2); - enemiesGroup.add((entry.getValue().getRight().toString())).align(Align.center).space(0,2,0,2); + enemiesGroup.add(enemyImage).align(Align.center).space(3, 10, 3, 10); + enemiesGroup.add((data.name)).fillX().align(Align.center).fillX().space(3, 10, 3, 10); + enemiesGroup.add((entry.getValue().getLeft().toString())).space(3, 2, 3, 2); + enemiesGroup.add(("/")).align(Align.center).space(3, 2, 3, 2); + enemiesGroup.add((entry.getValue().getRight().toString())).align(Align.center).space(0, 2, 0, 2); enemiesGroup.row().space(8); } } + @Override public void resLoaded() { super.resLoaded(); @@ -107,11 +108,12 @@ public class PlayerStatisticScene extends UIScene { PlayerStatisticScene.this.back(); } }); - avatar=ui.findActor("avatar"); + avatar = ui.findActor("avatar"); + playerName = ui.findActor("playerName"); - totalWins=ui.findActor("totalWins"); - totalLoss=ui.findActor("totalLoss"); - lossWinRatio=ui.findActor("lossWinRatio"); + totalWins = ui.findActor("totalWins"); + totalLoss = ui.findActor("totalLoss"); + lossWinRatio = ui.findActor("lossWinRatio"); ScrollPane scrollPane = ui.findActor("enemies"); scrollPane.setActor(enemiesGroup); diff --git a/forge-gui/res/adventure/Shandalar/ui/statistic.json b/forge-gui/res/adventure/Shandalar/ui/statistic.json index 729111c988d..ca037ed2028 100644 --- a/forge-gui/res/adventure/Shandalar/ui/statistic.json +++ b/forge-gui/res/adventure/Shandalar/ui/statistic.json @@ -9,92 +9,109 @@ "width": 480, "height": 270 }, + { + "type": "Scroll", + "style": "paper", + "x": 300, + "y": 18, + "width": 160, + "height": 180 + }, { "type": "Scroll", "name": "enemies", - "x": 206, - "y": 10, + "x": 15, + "y": 18, "width": 256, "height": 235 }, { "type": "Image", "name": "avatar", - "x": 10, - "y": 10, + "x": 350, + "y": 28, "width": 64, "height": 64 }, - { - "type": "Label", - "name": "totalWins", - "x": 90, - "y": 84, - "width": 80, - "height": 24, - "font": "default" - }, - { - "type": "Label", - "text": "Win:", - "x": 10, - "y": 84, - "width": 80, - "height": 24, - "font": "default" - }, - { - "type": "Label", - "name": "totalLoss", - "x": 90, - "y": 104, - "width": 80, - "height": 24, - "font": "default" - }, - { - "type": "Label", - "text": "Loss:", - "x": 10, - "y": 104, - "width": 80, - "height": 24, - "font": "default" - }, - { - "type": "Label", - "name": "lossWinRatio", - "x": 90, - "y": 124, - "width": 80, - "height": 24, - "font": "default" - }, - { - "type": "Label", - "text": "Win Loss Ratio:", - "x": 10, - "y": 124, - "width": 80, - "height": 24, - "font": "default" - }, { "type": "Image", "image": "ui/avatarhud.png", - "x": 10, - "y": 10, + "x": 350, + "y": 28, "width": 64, "height": 64 }, + { + "type": "Label", + "name": "playerName", + "x": 330, + "y": 90, + "width": 80, + "height": 24, + "font": "black" + }, + { + "type": "Label", + "name": "totalWins", + "x": 410, + "y": 114, + "width": 80, + "height": 24, + "font": "black" + }, + { + "type": "Label", + "text": "Win:", + "x": 330, + "y": 114, + "width": 80, + "height": 24, + "font": "black" + }, + { + "type": "Label", + "name": "totalLoss", + "x": 410, + "y": 134, + "width": 80, + "height": 24, + "font": "black" + }, + { + "type": "Label", + "text": "Loss:", + "x": 330, + "y": 134, + "width": 80, + "height": 24, + "font": "black" + }, + { + "type": "Label", + "name": "lossWinRatio", + "x": 410, + "y": 154, + "width": 80, + "height": 24, + "font": "black" + }, + { + "type": "Label", + "text": "Win Loss Ratio:", + "x": 330, + "y": 154, + "width": 80, + "height": 24, + "font": "black" + }, { "type": "TextButton", "name": "return", "text": "Back", - "width": 48, - "height": 16, - "x": 15, - "y": 250 + "width": 100, + "height": 30, + "x": 335, + "y": 212 }, { "type": "Table", From ede766fc561cee140db0379d29ec574d04aed352 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 24 Feb 2022 04:17:00 +0800 Subject: [PATCH 11/16] update inn and deck select scene --- .../adventure/scene/DeckSelectScene.java | 2 + .../src/forge/adventure/scene/InnScene.java | 21 +++----- .../adventure/scene/PlayerStatisticScene.java | 2 + .../src/forge/adventure/scene/StartScene.java | 2 + forge-gui/res/adventure/Shandalar/ui/heal.png | Bin 0 -> 13013 bytes forge-gui/res/adventure/Shandalar/ui/inn.json | 48 +++++++++++++----- .../res/adventure/Shandalar/ui/leave.png | Bin 0 -> 14464 bytes forge-gui/res/adventure/Shandalar/ui/sell.png | Bin 0 -> 12825 bytes 8 files changed, 50 insertions(+), 25 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/heal.png create mode 100644 forge-gui/res/adventure/Shandalar/ui/leave.png create mode 100644 forge-gui/res/adventure/Shandalar/ui/sell.png diff --git a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java index 487530958e8..b067f78cde1 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java @@ -14,6 +14,7 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.IntMap; import forge.Forge; import forge.adventure.player.AdventurePlayer; +import forge.adventure.stage.GameHUD; import forge.adventure.util.Controls; import forge.adventure.util.Current; import forge.gui.GuiBase; @@ -53,6 +54,7 @@ public class DeckSelectScene extends UIScene { } public void back() { + GameHUD.getInstance().getTouchpad().setVisible(false); Forge.switchScene(SceneType.GameScene.instance); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/InnScene.java b/forge-gui-mobile/src/forge/adventure/scene/InnScene.java index f1c0b60282a..062f582b987 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/InnScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/InnScene.java @@ -8,30 +8,27 @@ import forge.adventure.util.Current; /** * Scene for the Inn in towns - * */ -public class InnScene extends UIScene { +public class InnScene extends UIScene { - public InnScene() - { + public InnScene() { super("ui/inn.json"); } - public void done() - { + public void done() { GameHUD.getInstance().getTouchpad().setVisible(false); Forge.switchToLast(); } - public void heal() - { + + public void heal() { Current.player().heal(); } @Override public void act(float delta) { - stage.act(delta); } + @Override public void resLoaded() { super.resLoaded(); @@ -61,10 +58,8 @@ public class InnScene extends UIScene { } @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE) { done(); } return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java index 188992d9377..96da3b9f8a4 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java @@ -11,6 +11,7 @@ import forge.Forge; import forge.adventure.character.EnemySprite; import forge.adventure.data.EnemyData; import forge.adventure.data.WorldData; +import forge.adventure.stage.GameHUD; import forge.adventure.util.Controls; import forge.adventure.util.Current; import forge.player.GamePlayerUtil; @@ -47,6 +48,7 @@ public class PlayerStatisticScene extends UIScene { } public boolean back() { + GameHUD.getInstance().getTouchpad().setVisible(false); Forge.switchToLast(); return true; } diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index 9e87855cc45..062a403be05 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.scenes.scene2d.Actor; import forge.Forge; +import forge.adventure.stage.GameHUD; import forge.adventure.world.WorldSave; import forge.gui.GuiBase; @@ -39,6 +40,7 @@ public class StartScene extends UIScene { public boolean Resume() { //Forge.switchToLast(); + GameHUD.getInstance().getTouchpad().setVisible(false); Forge.switchScene(SceneType.GameScene.instance); return true; } diff --git a/forge-gui/res/adventure/Shandalar/ui/heal.png b/forge-gui/res/adventure/Shandalar/ui/heal.png new file mode 100644 index 0000000000000000000000000000000000000000..1c9d64492230934aa95f73dd5c3fb679e26afc9b GIT binary patch literal 13013 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 z z=TWRo%_3D`C)Co!sv~Je4lEB&0qHQw&669W^~}h#2^OEpKa_Wjx&XPiRL77U5(qxn zVV`Z+sR`eT;jgqenMA(W0U4*N6QVI#hkr(|6Le?54En&M3n3f6msa3f+-WwT>qsbS z3H5zkH;XvehMd=RfE;i*7S{^{wkU6RuGYW0JnwIMO8fiiO)%5fyS2n@PW_b4e9Fd- z5`jlRHXFdFldXo#+P^z^vv)9@H>KwlnM=i7kP&R6U^MGDOS#Xv^H=I{h5$KNfrNd0 zrV#W&2lYyusWO{4^J8*^g3zqF9O6rnk#uPsT;h!JxP&->COdN}l9i_7vU@aZCBVT! z=~?V9%LU7@#-|*P@+PXaQZgG(WjWG1JTB-)#7aJ+@OEqO9W(f(@SfxJm4~if;FV9C z$6Xwp|5UjalhX0WZbL^(*IUPu`w3Us5ezDf0dm^voBP(Cfz*{$rmHmRPF}63Y-6}j z$Wl_CM%_KqWA+i+0F&3Nd$}+cXKw7p_9iMf6=f_&)alHRB?>~*>R$9-_&1Te9V%; zUHsX@x&AwW;e>4?INdeSH&Vg+m*~0k#J~;8au%imHud#M z8|H}>jyGF2l00IaHQuB=gxk8U9F0nnX0FOoSV`IDi%X)bg^N$=8sYE-=cqnbtdff1 z$*}v3W>`TMeL)VaS%>w_qNWj3dD$C5!8)cCeKQ>|d_J?A$K3F(pjNKI#4v)FmC(L) zH8pNkZ$+Ht-f2OL4&GE&P(&y2-nnPgiG*$7UhACd?do6*i;Cjv*;AM{zd9J(OmVyB z)%I2}s-N8(Nj0hx_7b8IQ9X7o?E?eY#3iey;@O8vEpbIMEo9DO;B$aH8043lxJkON z;Z{~x7Vf~FAWRS;i_VzxmhI;fI8}Kam3W(zN88&cGQ!DKjT%?_O*+ zn^eDKngGd#X6ww9)qVTYmF8=F?I#{j7!03o8(e(anyWU%tIFNNl^R)1gq;jnGVoUq zQ0zZIB?XAW7WFsYbq}?V87|n+@S+&(bds+rl4$G4=)V!nDQBjWuY&AkX{Dvr51m#i zCFReLa>dY*Somr1Y}ua^HQK1~jvUydzp~Sk{!zVhg%nfN>wOt+I z2KyM5cOHJTw74o+3VIpKVByp2egx|#T)$Cd3g)-$@rTT`nS!CHa(Ib~1#K4cls zO{avbekeD?0C;l8@W$dEH7S`6E?TaXmBTJ2l4e8-UncxZmZ$9Z#Ubx%?z1fUW4< oaSCE*EMj{sVrQ(x%K0i1lU{zlm{NK5pFf@`$*IfMOTP~JUj_oq6aWAK literal 0 HcmV?d00001 diff --git a/forge-gui/res/adventure/Shandalar/ui/inn.json b/forge-gui/res/adventure/Shandalar/ui/inn.json index 9ef4fa3469e..e3f29ce23e8 100644 --- a/forge-gui/res/adventure/Shandalar/ui/inn.json +++ b/forge-gui/res/adventure/Shandalar/ui/inn.json @@ -9,32 +9,56 @@ "width": 480, "height": 270 }, + { + "type": "Image", + "image": "ui/heal.png", + "x": 60, + "y": 85, + "width": 100, + "height": 100 + }, { "type": "TextButton", "name": "heal", "text": "Heal", - "width": 48, - "height": 16, - "x": 420, - "y": 10 + "width": 100, + "height": 30, + "x": 60, + "y": 200 + }, + { + "type": "Image", + "image": "ui/sell.png", + "x": 190, + "y": 85, + "width": 100, + "height": 100 }, { "type": "TextButton", "name": "sell", "text": "Sell cards", - "width": 48, - "height": 16, - "x": 420, - "y": 34 + "width": 100, + "height": 30, + "x": 190, + "y": 200 + }, + { + "type": "Image", + "image": "ui/leave.png", + "x": 320, + "y": 85, + "width": 100, + "height": 100 }, { "type": "TextButton", "name": "done", "text": "Leave", - "width": 48, - "height": 16, - "x": 420, - "y": 58 + "width": 100, + "height": 30, + "x": 320, + "y": 200 } ] } \ No newline at end of file diff --git a/forge-gui/res/adventure/Shandalar/ui/leave.png b/forge-gui/res/adventure/Shandalar/ui/leave.png new file mode 100644 index 0000000000000000000000000000000000000000..7c13521c224e3834ec60b20fd12c4cf130d10435 GIT binary patch literal 14464 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 Pe*|SE6(!2WzWDtw#Ln5b literal 0 HcmV?d00001 diff --git a/forge-gui/res/adventure/Shandalar/ui/sell.png b/forge-gui/res/adventure/Shandalar/ui/sell.png new file mode 100644 index 0000000000000000000000000000000000000000..bfb51706ea6a2bed9a5eaaa60124f4631a8781c2 GIT binary patch literal 12825 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 Date: Thu, 24 Feb 2022 08:16:59 +0800 Subject: [PATCH 12/16] update stage and cleanup --- forge-gui-mobile/src/forge/Forge.java | 5 +- .../adventure/scene/AdventureDeckEditor.java | 2 +- .../adventure/scene/DeckSelectScene.java | 4 +- .../src/forge/adventure/scene/GameScene.java | 1 + .../forge/adventure/scene/SettingsScene.java | 1 - .../src/forge/adventure/stage/MapStage.java | 4 + .../src/forge/deck/FDeckEditor.java | 172 ++++++++---------- 7 files changed, 91 insertions(+), 98 deletions(-) diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index b295d5c4382..10ac4ea26e2 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -17,8 +17,10 @@ import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Clipboard; import com.badlogic.gdx.utils.ScreenUtils; import forge.adventure.scene.ForgeScene; +import forge.adventure.scene.GameScene; import forge.adventure.scene.Scene; import forge.adventure.scene.SceneType; +import forge.adventure.stage.MapStage; import forge.adventure.util.Config; import forge.animation.ForgeAnimation; import forge.assets.AssetsDownloader; @@ -887,7 +889,6 @@ public class Forge implements ApplicationListener { } public static boolean switchScene(Scene newScene) { - if (currentScene != null) { if (!currentScene.leave()) return false; @@ -895,6 +896,8 @@ public class Forge implements ApplicationListener { } storeScreen(); sceneWasSwapped =true; + if (newScene instanceof GameScene) + MapStage.getInstance().clearIsInMap(); currentScene = newScene; currentScene.enter(); return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java b/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java index 6fc9f8687d2..59c8e12b192 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java +++ b/forge-gui-mobile/src/forge/adventure/scene/AdventureDeckEditor.java @@ -54,8 +54,8 @@ import java.util.Map; private static ItemPool decksUsingMyCards=new ItemPool<>(InventoryItem.class); public static void leave() { AdventurePlayer.current().getNewCards().clear(); - Forge.switchScene(SceneType.DeckSelectScene.instance); Forge.clearCurrentScreen(); + Forge.switchToLast(); } @Override diff --git a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java index b067f78cde1..1adb3cc029e 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java @@ -14,7 +14,6 @@ import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.IntMap; import forge.Forge; import forge.adventure.player.AdventurePlayer; -import forge.adventure.stage.GameHUD; import forge.adventure.util.Controls; import forge.adventure.util.Current; import forge.gui.GuiBase; @@ -54,8 +53,7 @@ public class DeckSelectScene extends UIScene { } public void back() { - GameHUD.getInstance().getTouchpad().setVisible(false); - Forge.switchScene(SceneType.GameScene.instance); + Forge.switchToLast(); } public boolean select(int slot) { diff --git a/forge-gui-mobile/src/forge/adventure/scene/GameScene.java b/forge-gui-mobile/src/forge/adventure/scene/GameScene.java index b2c5cf1c7bb..1bf76d24a2a 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/GameScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/GameScene.java @@ -50,5 +50,6 @@ public class GameScene extends HudScene { Forge.clearCurrentScreen(); super.enter(); } + } diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index 64f067ee035..44fd18d5180 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -7,7 +7,6 @@ import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.CheckBox; -import com.badlogic.gdx.scenes.scene2d.ui.ImageButton; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; import com.badlogic.gdx.scenes.scene2d.ui.SelectBox; diff --git a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java index 886f80f53fa..fa1192eabc5 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java @@ -58,6 +58,10 @@ public class MapStage extends GameStage { private final Vector2 oldPosition3=new Vector2(); private final Vector2 oldPosition4=new Vector2(); + public void clearIsInMap() { + isInMap = false; + } + public MapLayer getSpriteLayer() { diff --git a/forge-gui-mobile/src/forge/deck/FDeckEditor.java b/forge-gui-mobile/src/forge/deck/FDeckEditor.java index ebcd835c019..74bb5b70f29 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckEditor.java +++ b/forge-gui-mobile/src/forge/deck/FDeckEditor.java @@ -15,7 +15,6 @@ import forge.card.CardEdition; import forge.deck.io.DeckPreferences; import forge.gamemodes.limited.BoosterDraft; import forge.gamemodes.planarconquest.ConquestUtil; -import forge.gui.FThreads; import forge.gui.GuiBase; import forge.gui.card.CardPreferences; import forge.item.PaperCard; @@ -32,7 +31,6 @@ import forge.menu.FMenuItem; import forge.menu.FPopupMenu; import forge.model.FModel; import forge.screens.FScreen; -import forge.screens.LoadingOverlay; import forge.screens.TabPageScreen; import forge.toolbox.*; import forge.toolbox.FEvent.FEventHandler; @@ -1134,97 +1132,87 @@ public class FDeckEditor extends TabPageScreen { @Override public void refresh() { - FThreads.invokeInEdtLater(new Runnable() { - @Override - public void run() { - LoadingOverlay.show(Localizer.getInstance().getMessage("lblLoading"), new Runnable() { - @Override - public void run() { - Predicate additionalFilter = null; - final EditorType editorType = parentScreen.getEditorType(); - final Localizer localizer = Localizer.getInstance(); - switch (editorType) { - case Archenemy: - cardManager.setPool(FModel.getArchenemyCards(), true); - break; - case Planechase: - cardManager.setPool(FModel.getPlanechaseCards(), true); - break; - case Quest: - final ItemPool questPool = new ItemPool<>(PaperCard.class); - questPool.addAll(FModel.getQuest().getCards().getCardpool()); - // remove bottom cards that are in the deck from the card pool - questPool.removeAll(parentScreen.getDeck().getMain()); - // remove sideboard cards from the catalog - questPool.removeAll(parentScreen.getDeck().getOrCreate(DeckSection.Sideboard)); - cardManager.setPool(questPool); - break; - case PlanarConquest: - cardManager.setPool(ConquestUtil.getAvailablePool(parentScreen.getDeck())); - break; - case QuestCommander: - case Commander: - case Oathbreaker: - case TinyLeaders: - case Brawl: - final List commanders = parentScreen.getDeck().getCommanders(); - if (commanders.isEmpty()) { - //if no commander set for deck, only show valid commanders - switch (editorType) { - case Commander: - case QuestCommander: - additionalFilter = DeckFormat.Commander.isLegalCommanderPredicate(); - cardManager.setCaption(localizer.getMessage("lblCommanders")); - break; - case Oathbreaker: - additionalFilter = DeckFormat.Oathbreaker.isLegalCommanderPredicate(); - cardManager.setCaption(localizer.getMessage("lblOathbreakers")); - break; - case TinyLeaders: - additionalFilter = DeckFormat.TinyLeaders.isLegalCommanderPredicate(); - cardManager.setCaption(localizer.getMessage("lblCommanders")); - break; - case Brawl: - additionalFilter = DeckFormat.Brawl.isLegalCommanderPredicate(); - cardManager.setCaption(localizer.getMessage("lblCommanders")); - break; - default: - // Do nothing - } - } else { - //if a commander has been set, only show cards that match its color identity - switch (editorType) { - case Commander: - case QuestCommander: - additionalFilter = DeckFormat.Commander.isLegalCardForCommanderPredicate(commanders); - break; - case Oathbreaker: - additionalFilter = DeckFormat.Oathbreaker.isLegalCardForCommanderPredicate(commanders); - break; - case TinyLeaders: - additionalFilter = DeckFormat.TinyLeaders.isLegalCardForCommanderPredicate(commanders); - break; - case Brawl: - additionalFilter = DeckFormat.Brawl.isLegalCardForCommanderPredicate(commanders); - break; - default: - // Do nothing - } - cardManager.setCaption(localizer.getMessage("lblCards")); - } - // fall through to below - default: - if (cardManager.getWantUnique()) { - cardManager.setPool(editorType.applyCardFilter(FModel.getUniqueCardsNoAlt(), additionalFilter), true); - } else { - cardManager.setPool(editorType.applyCardFilter(FModel.getAllCardsNoAlt(), additionalFilter), true); - } - break; - } + Predicate additionalFilter = null; + final EditorType editorType = parentScreen.getEditorType(); + final Localizer localizer = Localizer.getInstance(); + switch (editorType) { + case Archenemy: + cardManager.setPool(FModel.getArchenemyCards(), true); + break; + case Planechase: + cardManager.setPool(FModel.getPlanechaseCards(), true); + break; + case Quest: + final ItemPool questPool = new ItemPool<>(PaperCard.class); + questPool.addAll(FModel.getQuest().getCards().getCardpool()); + // remove bottom cards that are in the deck from the card pool + questPool.removeAll(parentScreen.getDeck().getMain()); + // remove sideboard cards from the catalog + questPool.removeAll(parentScreen.getDeck().getOrCreate(DeckSection.Sideboard)); + cardManager.setPool(questPool); + break; + case PlanarConquest: + cardManager.setPool(ConquestUtil.getAvailablePool(parentScreen.getDeck())); + break; + case QuestCommander: + case Commander: + case Oathbreaker: + case TinyLeaders: + case Brawl: + final List commanders = parentScreen.getDeck().getCommanders(); + if (commanders.isEmpty()) { + //if no commander set for deck, only show valid commanders + switch (editorType) { + case Commander: + case QuestCommander: + additionalFilter = DeckFormat.Commander.isLegalCommanderPredicate(); + cardManager.setCaption(localizer.getMessage("lblCommanders")); + break; + case Oathbreaker: + additionalFilter = DeckFormat.Oathbreaker.isLegalCommanderPredicate(); + cardManager.setCaption(localizer.getMessage("lblOathbreakers")); + break; + case TinyLeaders: + additionalFilter = DeckFormat.TinyLeaders.isLegalCommanderPredicate(); + cardManager.setCaption(localizer.getMessage("lblCommanders")); + break; + case Brawl: + additionalFilter = DeckFormat.Brawl.isLegalCommanderPredicate(); + cardManager.setCaption(localizer.getMessage("lblCommanders")); + break; + default: + // Do nothing } - }); - } - }); + } else { + //if a commander has been set, only show cards that match its color identity + switch (editorType) { + case Commander: + case QuestCommander: + additionalFilter = DeckFormat.Commander.isLegalCardForCommanderPredicate(commanders); + break; + case Oathbreaker: + additionalFilter = DeckFormat.Oathbreaker.isLegalCardForCommanderPredicate(commanders); + break; + case TinyLeaders: + additionalFilter = DeckFormat.TinyLeaders.isLegalCardForCommanderPredicate(commanders); + break; + case Brawl: + additionalFilter = DeckFormat.Brawl.isLegalCardForCommanderPredicate(commanders); + break; + default: + // Do nothing + } + cardManager.setCaption(localizer.getMessage("lblCards")); + } + // fall through to below + default: + if (cardManager.getWantUnique()) { + cardManager.setPool(editorType.applyCardFilter(FModel.getUniqueCardsNoAlt(), additionalFilter), true); + } else { + cardManager.setPool(editorType.applyCardFilter(FModel.getAllCardsNoAlt(), additionalFilter), true); + } + break; + } } @Override From 5a9322c0ee1ee9c18b4820eb7004217d91c24210 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Thu, 24 Feb 2022 08:26:18 +0800 Subject: [PATCH 13/16] fix resume --- forge-gui-mobile/src/forge/adventure/scene/StartScene.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index 062a403be05..0b470677c2f 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -39,9 +39,8 @@ public class StartScene extends UIScene { } public boolean Resume() { - //Forge.switchToLast(); + Forge.switchToLast(); GameHUD.getInstance().getTouchpad().setVisible(false); - Forge.switchScene(SceneType.GameScene.instance); return true; } From 0ec1e7a25a0d8c45355013c42826565b87a05c88 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Fri, 25 Feb 2022 18:14:12 +0800 Subject: [PATCH 14/16] update RewardScene --- .../forge/adventure/scene/RewardScene.java | 248 ++++++++---------- .../adventure/Shandalar/ui/items_mobile.json | 29 ++ 2 files changed, 137 insertions(+), 140 deletions(-) create mode 100644 forge-gui/res/adventure/Shandalar/ui/items_mobile.json diff --git a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java index 21cd76c8220..ede92f2119e 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java @@ -18,87 +18,78 @@ import forge.adventure.util.Reward; import forge.adventure.util.RewardActor; import forge.adventure.world.WorldSave; import forge.assets.ImageCache; +import forge.gui.GuiBase; /** * Displays the rewards of a fight or a treasure */ -public class RewardScene extends UIScene { +public class RewardScene extends UIScene { private TextButton doneButton; - public enum Type - { + public enum Type { Shop, Loot - } + Type type; - Array generated =new Array<>(); - static public final float CARD_WIDTH =550f; - static public final float CARD_HEIGHT =400f; - static public final float CARD_WIDTH_TO_HEIGHT =CARD_WIDTH/CARD_HEIGHT; - public RewardScene() - { - super("ui/items.json"); + Array generated = new Array<>(); + static public final float CARD_WIDTH = 550f; + static public final float CARD_HEIGHT = 400f; + static public final float CARD_WIDTH_TO_HEIGHT = CARD_WIDTH / CARD_HEIGHT; + + public RewardScene() { + super(GuiBase.isAndroid() ? "ui/items_mobile.json" : "ui/items.json"); } - boolean doneClicked=false; - float flipCountDown=1.0f; - public boolean done() - { + boolean doneClicked = false; + float flipCountDown = 1.0f; + + public boolean done() { GameHUD.getInstance().getTouchpad().setVisible(false); - if(doneClicked) + if (doneClicked) return true; - if(type==Type.Loot) - { + if (type == Type.Loot) { - boolean wait=false; - for(Actor actor: new Array.ArrayIterator<>(generated)) - { - if(!(actor instanceof RewardActor)) - { + boolean wait = false; + for (Actor actor : new Array.ArrayIterator<>(generated)) { + if (!(actor instanceof RewardActor)) { continue; } - RewardActor reward=(RewardActor) actor; + RewardActor reward = (RewardActor) actor; AdventurePlayer.current().addReward(reward.getReward()); - if(!reward.isFlipped()) - { + if (!reward.isFlipped()) { wait = true; reward.flip(); } } - if(wait) - { - flipCountDown=3.0f; - doneClicked=true; - } - else - { + if (wait) { + flipCountDown = 3.0f; + doneClicked = true; + } else { Forge.switchToLast(); } - } - else - { + } else { Forge.switchToLast(); } return true; } + @Override public void act(float delta) { stage.act(delta); ImageCache.allowSingleLoad(); - if(doneClicked) - { - if(type==Type.Loot) - flipCountDown-=Gdx.graphics.getDeltaTime(); - if(flipCountDown<=0) - { + if (doneClicked) { + if (type == Type.Loot) + flipCountDown -= Gdx.graphics.getDeltaTime(); + if (flipCountDown <= 0) { Forge.switchToLast(); } } } + @Override public void resLoaded() { super.resLoaded(); @@ -108,56 +99,49 @@ public class RewardScene extends UIScene { RewardScene.this.done(); } }); - doneButton=ui.findActor("done"); + doneButton = ui.findActor("done"); } @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE) { done(); } return true; } - public void loadRewards(Array newRewards, Type type, ShopActor shopActor) - { - this.type=type; - doneClicked=false; + public void loadRewards(Array newRewards, Type type, ShopActor shopActor) { + this.type = type; + doneClicked = false; - - - for(Actor actor: new Array.ArrayIterator<>(generated)) - { + for (Actor actor : new Array.ArrayIterator<>(generated)) { actor.remove(); - if(actor instanceof RewardActor) - { - ((RewardActor)actor).dispose(); + if (actor instanceof RewardActor) { + ((RewardActor) actor).dispose(); } } generated.clear(); - Actor card=ui.findActor("cards"); + Actor card = ui.findActor("cards"); - // card.setDrawable(new TextureRegionDrawable(new Texture(Res.CurrentRes.GetFile("ui/transition.png")))); + // card.setDrawable(new TextureRegionDrawable(new Texture(Res.CurrentRes.GetFile("ui/transition.png")))); - float targetWidth = card.getWidth(); + float targetWidth = card.getWidth(); float targetHeight = card.getHeight(); - float xOff = card.getX(); + float xOff = card.getX(); float yOff = card.getY(); - int numberOfRows=0; - float cardWidth=0; - float cardHeight=0; - float bestCardHeight=0; - int numberOfColumns=0; - float targetArea=targetHeight*targetWidth; - float oldCardArea=0; - float newArea=0; + int numberOfRows = 0; + float cardWidth = 0; + float cardHeight = 0; + float bestCardHeight = 0; + int numberOfColumns = 0; + float targetArea = targetHeight * targetWidth; + float oldCardArea = 0; + float newArea = 0; switch (type) { case Shop: @@ -167,89 +151,74 @@ public class RewardScene extends UIScene { doneButton.setText("Take all"); break; } - for(int h=1;holdCardArea&&newArea<=targetArea&&rows*cardHeight oldCardArea && newArea <= targetArea && rows * cardHeight < targetHeight && cols * cardWidth < targetWidth) { + oldCardArea = newArea; + numberOfRows = rows; + numberOfColumns = cols; + bestCardHeight = h; } } - cardHeight=bestCardHeight; - cardWidth=bestCardHeight/ CARD_WIDTH_TO_HEIGHT; + cardHeight = bestCardHeight; + cardWidth = bestCardHeight / CARD_WIDTH_TO_HEIGHT; - yOff+=(targetHeight-(cardHeight*numberOfRows))/2f; - xOff+=(targetWidth-(cardWidth*numberOfColumns))/2f; - float spacing=2; - int i=0; - for(Reward reward:new Array.ArrayIterator<>(newRewards)) - { - boolean skipCard=false; - if(type==Type.Shop) - { - if(shopActor.getMapStage().getChanges().wasCardBought(shopActor.getObjectID(),i)) - { - skipCard=true; + yOff += (targetHeight - (cardHeight * numberOfRows)) / 2f; + xOff += (targetWidth - (cardWidth * numberOfColumns)) / 2f; + float spacing = 2; + int i = 0; + for (Reward reward : new Array.ArrayIterator<>(newRewards)) { + boolean skipCard = false; + if (type == Type.Shop) { + if (shopActor.getMapStage().getChanges().wasCardBought(shopActor.getObjectID(), i)) { + skipCard = true; } } - - int currentRow=(i/numberOfColumns); - float lastRowXAdjust=0; - if(currentRow==numberOfRows-1) - { - int lastRowCount=newRewards.size%numberOfColumns; - if(lastRowCount!=0) - lastRowXAdjust=((numberOfColumns*cardWidth)-(lastRowCount*cardWidth))/2; + int currentRow = (i / numberOfColumns); + float lastRowXAdjust = 0; + if (currentRow == numberOfRows - 1) { + int lastRowCount = newRewards.size % numberOfColumns; + if (lastRowCount != 0) + lastRowXAdjust = ((numberOfColumns * cardWidth) - (lastRowCount * cardWidth)) / 2; } - RewardActor actor=new RewardActor(reward,type==Type.Loot); - actor.setBounds(lastRowXAdjust+xOff+cardWidth*(i%numberOfColumns)+spacing,yOff+cardHeight*currentRow+spacing,cardWidth-spacing*2,cardHeight-spacing*2); + RewardActor actor = new RewardActor(reward, type == Type.Loot); + actor.setBounds(lastRowXAdjust + xOff + cardWidth * (i % numberOfColumns) + spacing, yOff + cardHeight * currentRow + spacing, cardWidth - spacing * 2, cardHeight - spacing * 2); - if(type==Type.Shop) - { - if(currentRow!=((i+1)/numberOfColumns)) - yOff+=doneButton.getHeight(); + if (type == Type.Shop) { + if (currentRow != ((i + 1) / numberOfColumns)) + yOff += doneButton.getHeight(); - TextButton buyCardButton=new BuyButton(shopActor.getObjectID(),i,shopActor.getMapStage().getChanges(),actor,doneButton); + TextButton buyCardButton = new BuyButton(shopActor.getObjectID(), i, shopActor.getMapStage().getChanges(), actor, doneButton); generated.add(buyCardButton); - if(!skipCard) - { + if (!skipCard) { stage.addActor(buyCardButton); } } generated.add(actor); - if(!skipCard) - { + if (!skipCard) { stage.addActor(actor); } i++; } updateBuyButtons(); - } private void updateBuyButtons() { - - for(Actor actor: new Array.ArrayIterator<>(generated)) - { - if(actor instanceof BuyButton) - { - ((BuyButton)actor).update(); + for (Actor actor : new Array.ArrayIterator<>(generated)) { + if (actor instanceof BuyButton) { + ((BuyButton) actor).update(); } } } @@ -260,28 +229,28 @@ public class RewardScene extends UIScene { private final PointOfInterestChanges changes; RewardActor reward; int price; - void update(){ - setDisabled(WorldSave.getCurrentSave().getPlayer().getGold()< price); + + void update() { + setDisabled(WorldSave.getCurrentSave().getPlayer().getGold() < price); } + public BuyButton(int id, int i, PointOfInterestChanges ch, RewardActor actor, TextButton style) { - super("",style.getStyle()); + super("", style.getStyle()); this.objectID = id; this.index = i; this.changes = ch; - reward=actor; + reward = actor; setHeight(style.getHeight()); setWidth(actor.getWidth()); setX(actor.getX()); - setY(actor.getY()-getHeight()); - price= CardUtil.getCardPrice(actor.getReward().getCard()); - setText("Buy for "+price); - addListener(new ClickListener(){ - + setY(actor.getY() - getHeight()); + price = CardUtil.getCardPrice(actor.getReward().getCard()); + setText("Buy for " + price); + addListener(new ClickListener() { @Override - public void clicked (InputEvent event, float x, float y) { - if(Current.player().getGold()>= price) - { - changes.buyCard(objectID,index); + public void clicked(InputEvent event, float x, float y) { + if (Current.player().getGold() >= price) { + changes.buyCard(objectID, index); Current.player().takeGold(price); Current.player().addReward(reward.getReward()); setDisabled(true); @@ -289,7 +258,6 @@ public class RewardScene extends UIScene { remove(); updateBuyButtons(); } - } }); } diff --git a/forge-gui/res/adventure/Shandalar/ui/items_mobile.json b/forge-gui/res/adventure/Shandalar/ui/items_mobile.json new file mode 100644 index 00000000000..75bd6ed37d6 --- /dev/null +++ b/forge-gui/res/adventure/Shandalar/ui/items_mobile.json @@ -0,0 +1,29 @@ +{ + "width": 480, + "height": 270, + "yDown": true, + "elements": [ + { + "type": "Image", + "name": "lastScreen", + "width": 480, + "height": 270 + }, + { + "name": "cards", + "x": 5, + "y": 5, + "width": 405, + "height": 265 + }, + { + "type": "TextButton", + "name": "done", + "text": "Take all", + "width": 48, + "height": 30, + "x": 420, + "y": 120 + } + ] +} \ No newline at end of file From 14d71ad278d86ac7fa85b2a2d97ce91cc04afeb6 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sat, 26 Feb 2022 11:56:25 +0800 Subject: [PATCH 15/16] pull from master --- .../src/main/java/forge/ai/GameState.java | 2 +- .../src/main/java/forge/game/GameAction.java | 197 ++++++++---------- .../main/java/forge/game/GameActionUtil.java | 2 +- .../src/main/java/forge/game/Match.java | 5 +- .../game/ability/SpellAbilityEffect.java | 8 +- .../game/ability/effects/AddTurnEffect.java | 3 +- .../game/ability/effects/BalanceEffect.java | 4 +- .../ability/effects/ChangeZoneEffect.java | 9 +- .../effects/DamagePreventEffectBase.java | 3 +- .../game/ability/effects/DiscardEffect.java | 7 +- .../game/ability/effects/DrawEffect.java | 7 +- .../game/ability/effects/EffectEffect.java | 8 +- .../game/ability/effects/EncodeEffect.java | 9 +- .../game/ability/effects/ExploreEffect.java | 8 +- .../forge/game/ability/effects/FogEffect.java | 3 +- .../game/ability/effects/LearnEffect.java | 8 +- .../game/ability/effects/MakeCardEffect.java | 10 +- .../game/ability/effects/MillEffect.java | 8 +- .../ability/effects/PlaneswalkEffect.java | 4 +- .../game/ability/effects/PlayEffect.java | 18 +- .../ability/effects/RegenerateBaseEffect.java | 3 +- .../ability/effects/SetInMotionEffect.java | 2 +- .../game/ability/effects/SkipPhaseEffect.java | 3 +- .../game/ability/effects/SkipTurnEffect.java | 3 +- .../game/ability/effects/SubgameEffect.java | 5 +- .../game/ability/effects/SurveilEffect.java | 8 +- .../game/ability/effects/VentureEffect.java | 14 +- .../ability/effects/ZoneExchangeEffect.java | 10 +- .../main/java/forge/game/cost/CostDraw.java | 8 +- .../main/java/forge/game/cost/CostMill.java | 8 +- .../java/forge/game/cost/CostSacrifice.java | 8 +- .../java/forge/game/phase/PhaseHandler.java | 6 +- .../main/java/forge/game/player/Player.java | 75 +++++-- .../forge/game/trigger/TriggerHandler.java | 16 +- forge-gui/res/cardsfolder/t/tomb_tyrant.txt | 2 +- .../res/editions/Secret Lair Drop Series.txt | 1 + .../forge/player/PlayerControllerHuman.java | 8 +- 37 files changed, 307 insertions(+), 196 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index d441ab10721..f7defad4a36 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -1250,7 +1250,7 @@ public abstract class GameState { } if (cardsWithoutETBTrigs.contains(c)) { - p.getGame().getAction().moveTo(ZoneType.Battlefield, c, null); + p.getGame().getAction().moveTo(ZoneType.Battlefield, c, null, null); } else { p.getZone(ZoneType.Hand).add(c); p.getGame().getAction().moveToPlay(c, null, null); diff --git a/forge-game/src/main/java/forge/game/GameAction.java b/forge-game/src/main/java/forge/game/GameAction.java index f9cd5adae81..4d93d16a262 100644 --- a/forge-game/src/main/java/forge/game/GameAction.java +++ b/forge-game/src/main/java/forge/game/GameAction.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.Set; import forge.util.*; + import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -202,6 +203,16 @@ public class GameAction { lastKnownInfo = (Card) cause.getReplacingObject(AbilityKey.CardLKI); } } + CardCollectionView lastBattlefield = null; + if (params != null) { + lastBattlefield = (CardCollectionView) params.get(AbilityKey.LastStateBattlefield); + } + if (lastBattlefield == null && cause != null) { + lastBattlefield = cause.getLastStateBattlefield(); + } + if (lastBattlefield == null) { + lastBattlefield = game.getLastStateBattlefield(); + } if (c.isSplitCard()) { boolean resetToOriginal = false; @@ -254,7 +265,6 @@ public class GameAction { // if from Battlefield to Graveyard and Card does exist in LastStateBattlefield // use that instead if (fromBattlefield) { - CardCollectionView lastBattlefield = game.getLastStateBattlefield(); int idx = lastBattlefield.indexOf(c); if (idx != -1) { lastKnownInfo = lastBattlefield.get(idx); @@ -577,7 +587,10 @@ public class GameAction { } game.getTriggerHandler().clearActiveTriggers(copied, null); - game.getTriggerHandler().registerActiveLTBTrigger(lastKnownInfo); + // register all LTB trigger from last state battlefield + for (Card lki : lastBattlefield) { + game.getTriggerHandler().registerActiveLTBTrigger(lki); + } game.getTriggerHandler().registerActiveTrigger(copied, false); table.replaceCounterEffect(game, null, true); @@ -705,7 +718,7 @@ public class GameAction { } public final Card moveTo(final Zone zoneTo, Card c, SpellAbility cause) { - return moveTo(zoneTo, c, cause, null); + return moveTo(zoneTo, c, cause, AbilityKey.newMap()); } public final Card moveTo(final Zone zoneTo, Card c, SpellAbility cause, Map params) { // FThreads.assertExecutedByEdt(false); // This code must never be executed from EDT, @@ -713,14 +726,14 @@ public class GameAction { return moveTo(zoneTo, c, null, cause, params); } public final Card moveTo(final Zone zoneTo, Card c, Integer position, SpellAbility cause) { - return moveTo(zoneTo, c, position, cause, null); + return moveTo(zoneTo, c, position, cause, AbilityKey.newMap()); } - public final Card moveTo(final ZoneType name, final Card c, SpellAbility cause) { - return moveTo(name, c, 0, cause); + public final Card moveTo(final ZoneType name, final Card c, SpellAbility cause, Map params) { + return moveTo(name, c, 0, cause, params); } public final Card moveTo(final ZoneType name, final Card c, final int libPosition, SpellAbility cause) { - return moveTo(name, c, libPosition, cause, null); + return moveTo(name, c, libPosition, cause, AbilityKey.newMap()); } public final Card moveTo(final ZoneType name, final Card c, final int libPosition, SpellAbility cause, Map params) { // Call specific functions to set PlayerZone, then move onto moveTo @@ -786,7 +799,7 @@ public class GameAction { if (maingameCard.getZone().is(ZoneType.Stack)) { game.getMaingame().getStack().remove(maingameCard); } - game.getMaingame().getAction().moveTo(ZoneType.Subgame, maingameCard, null); + game.getMaingame().getAction().moveTo(ZoneType.Subgame, maingameCard, null, params); } } @@ -816,7 +829,10 @@ public class GameAction { } public final Card moveToStack(final Card c, SpellAbility cause) { - return moveToStack(c, cause, null); + Map params = AbilityKey.newMap(); + params.put(AbilityKey.LastStateBattlefield, game.getLastStateBattlefield()); + params.put(AbilityKey.LastStateGraveyard, game.getLastStateGraveyard()); + return moveToStack(c, cause, params); } public final Card moveToStack(final Card c, SpellAbility cause, Map params) { Card result = moveTo(game.getStackZone(), c, cause, params); @@ -833,7 +849,7 @@ public class GameAction { } public final Card moveToGraveyard(final Card c, SpellAbility cause) { - return moveToGraveyard(c, cause, null); + return moveToGraveyard(c, cause, AbilityKey.newMap()); } public final Card moveToGraveyard(final Card c, SpellAbility cause, Map params) { final PlayerZone grave = c.getOwner().getZone(ZoneType.Graveyard); @@ -842,7 +858,7 @@ public class GameAction { } public final Card moveToHand(final Card c, SpellAbility cause) { - return moveToHand(c, cause, null); + return moveToHand(c, cause, AbilityKey.newMap()); } public final Card moveToHand(final Card c, SpellAbility cause, Map params) { final PlayerZone hand = c.getOwner().getZone(ZoneType.Hand); @@ -859,14 +875,14 @@ public class GameAction { } public final Card moveToBottomOfLibrary(final Card c, SpellAbility cause) { - return moveToBottomOfLibrary(c, cause, null); + return moveToBottomOfLibrary(c, cause, AbilityKey.newMap()); } public final Card moveToBottomOfLibrary(final Card c, SpellAbility cause, Map params) { return moveToLibrary(c, -1, cause, params); } public final Card moveToLibrary(final Card c, SpellAbility cause) { - return moveToLibrary(c, cause, null); + return moveToLibrary(c, cause, AbilityKey.newMap()); } public final Card moveToLibrary(final Card c, SpellAbility cause, Map params) { return moveToLibrary(c, 0, cause, params); @@ -1229,7 +1245,12 @@ public class GameAction { // do this multiple times, sometimes creatures/permanents will survive when they shouldn't boolean orderedDesCreats = false; boolean orderedNoRegCreats = false; + boolean orderedSacrificeList = false; CardCollection cardsToUpdateLKI = new CardCollection(); + + Map mapParams = AbilityKey.newMap(); + mapParams.put(AbilityKey.LastStateBattlefield, game.getLastStateBattlefield()); + mapParams.put(AbilityKey.LastStateGraveyard, game.getLastStateGraveyard()); for (int q = 0; q < 9; q++) { checkStaticAbilities(false, affectedCards, CardCollection.EMPTY); boolean checkAgain = false; @@ -1253,16 +1274,14 @@ public class GameAction { } } } - CardCollection noRegCreats = null; + CardCollection noRegCreats = new CardCollection(); CardCollection desCreats = null; CardCollection unAttachList = new CardCollection(); + CardCollection sacrificeList = new CardCollection(); for (final Card c : game.getCardsIn(ZoneType.Battlefield)) { if (c.isCreature()) { // Rule 704.5f - Put into grave (no regeneration) for toughness <= 0 if (c.getNetToughness() <= 0) { - if (noRegCreats == null) { - noRegCreats = new CardCollection(); - } noRegCreats.add(c); checkAgain = true; } else if (c.hasKeyword("CARDNAME can't be destroyed by lethal damage unless lethal damage dealt by a single source is marked on it.")) { @@ -1306,7 +1325,7 @@ public class GameAction { } } - checkAgain |= stateBasedAction_Saga(c, table); + checkAgain |= stateBasedAction_Saga(c, sacrificeList); checkAgain |= stateBasedAction704_attach(c, unAttachList); // Attachment checkAgain |= stateBasedAction704_5r(c); // annihilate +1/+1 counters with -1/-1 ones @@ -1336,9 +1355,6 @@ public class GameAction { // cleanup aura if (c.isAura() && c.isInPlay() && !c.isEnchanting()) { - if (noRegCreats == null) { - noRegCreats = new CardCollection(); - } noRegCreats.add(c); checkAgain = true; } @@ -1351,28 +1367,46 @@ public class GameAction { // cleanup aura if (u.isAura() && u.isInPlay() && !u.isEnchanting()) { - if (noRegCreats == null) { - noRegCreats = new CardCollection(); - } noRegCreats.add(u); checkAgain = true; } } + for (Player p : game.getPlayers()) { + if (handleLegendRule(p, noRegCreats)) { + checkAgain = true; + } + + if ((game.getRules().hasAppliedVariant(GameType.Commander) + || game.getRules().hasAppliedVariant(GameType.Brawl) + || game.getRules().hasAppliedVariant(GameType.Planeswalker)) && !checkAgain) { + for (final Card c : p.getCardsIn(ZoneType.Graveyard).threadSafeIterable()) { + checkAgain |= stateBasedAction903_9a(c); + } + for (final Card c : p.getCardsIn(ZoneType.Exile).threadSafeIterable()) { + checkAgain |= stateBasedAction903_9a(c); + } + } + + if (handlePlaneswalkerRule(p, noRegCreats)) { + checkAgain = true; + } + } + // 704.5m World rule + checkAgain |= handleWorldRule(noRegCreats); // only check static abilities once after destroying all the creatures // (e.g. helpful for Erebos's Titan and another creature dealing lethal damage to each other simultaneously) setHoldCheckingStaticAbilities(true); - if (noRegCreats != null) { - if (noRegCreats.size() > 1 && !orderedNoRegCreats) { - noRegCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, noRegCreats, ZoneType.Graveyard, null); - orderedNoRegCreats = true; - } - for (Card c : noRegCreats) { - c.updateWasDestroyed(true); - sacrificeDestroy(c, null, table, null); - } + if (noRegCreats.size() > 1 && !orderedNoRegCreats) { + noRegCreats = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, noRegCreats, ZoneType.Graveyard, null); + orderedNoRegCreats = true; } + for (Card c : noRegCreats) { + c.updateWasDestroyed(true); + sacrificeDestroy(c, null, table, mapParams); + } + if (desCreats != null) { if (desCreats.size() > 1 && !orderedDesCreats) { desCreats = CardLists.filter(desCreats, CardPredicates.Presets.CAN_BE_DESTROYED); @@ -1382,39 +1416,24 @@ public class GameAction { orderedDesCreats = true; } for (Card c : desCreats) { - destroy(c, null, true, table, null); + destroy(c, null, true, table, mapParams); } } + + if (sacrificeList.size() > 1 && !orderedSacrificeList) { + sacrificeList = (CardCollection) GameActionUtil.orderCardsByTheirOwners(game, sacrificeList, ZoneType.Graveyard, null); + orderedSacrificeList = true; + } + for (Card c : sacrificeList) { + c.updateWasDestroyed(true); + sacrifice(c, null, true, table, mapParams); + } setHoldCheckingStaticAbilities(false); if (game.getTriggerHandler().runWaitingTriggers()) { checkAgain = true; } - for (Player p : game.getPlayers()) { - if (handleLegendRule(p, table)) { - checkAgain = true; - } - - if ((game.getRules().hasAppliedVariant(GameType.Commander) - || game.getRules().hasAppliedVariant(GameType.Brawl) - || game.getRules().hasAppliedVariant(GameType.Planeswalker)) && !checkAgain) { - Iterable cards = p.getCardsIn(ZoneType.Graveyard).threadSafeIterable(); - for (final Card c : cards) { - checkAgain |= stateBasedAction903_9a(c); - } - cards = p.getCardsIn(ZoneType.Exile).threadSafeIterable(); - for (final Card c : cards) { - checkAgain |= stateBasedAction903_9a(c); - } - } - - if (handlePlaneswalkerRule(p, table)) { - checkAgain = true; - } - } - // 704.5m World rule - checkAgain |= handleWorldRule(table); if (game.getCombat() != null) { game.getCombat().removeAbsentCombatants(); @@ -1459,7 +1478,7 @@ public class GameAction { game.runSBACheckedCommands(); } - private boolean stateBasedAction_Saga(Card c, CardZoneTable table) { + private boolean stateBasedAction_Saga(Card c, CardCollection sacrificeList) { boolean checkAgain = false; if (!c.getType().hasSubtype("Saga")) { return false; @@ -1472,7 +1491,7 @@ public class GameAction { } if (!game.getStack().hasSourceOnStack(c, SpellAbilityPredicates.isChapter())) { // needs to be effect, because otherwise it might be a cost? - sacrifice(c, null, true, table, null); + sacrificeList.add(c); checkAgain = true; } return checkAgain; @@ -1653,57 +1672,28 @@ public class GameAction { game.getStack().clearSimultaneousStack(); } - private boolean handlePlaneswalkerRule(Player p, CardZoneTable table) { + private boolean handlePlaneswalkerRule(Player p, CardCollection noRegCreats) { // get all Planeswalkers final List list = p.getPlaneswalkersInPlay(); boolean recheck = false; - //final Multimap uniqueWalkers = ArrayListMultimap.create(); // Not used as of Ixalan - for (Card c : list) { if (c.getCounters(CounterEnumType.LOYALTY) <= 0) { - //for animation - c.updateWasDestroyed(true); - sacrificeDestroy(c, null, table, null); - // Play the Destroy sound - game.fireEvent(new GameEventCardDestroyed()); + noRegCreats.add(c); recheck = true; } - - /* -- Not used as of Ixalan -- - for (final String type : c.getType()) { - if (CardType.isAPlaneswalkerType(type)) { - uniqueWalkers.put(type, c); - } - }*/ } - /* -- Not used as of Ixalan -- - for (String key : uniqueWalkers.keySet()) { - Collection duplicates = uniqueWalkers.get(key); - if (duplicates.size() < 2) { - continue; - } - - recheck = true; - - Card toKeep = p.getController().chooseSingleEntityForEffect(new CardCollection(duplicates), new AbilitySub(ApiType.InternalLegendaryRule, null, null, null), "You have multiple planeswalkers of type \""+key+"\"in play.\n\nChoose one to stay on battlefield (the rest will be moved to graveyard)"); - for (Card c: duplicates) { - if (c != toKeep) { - moveToGraveyard(c, null); - } - } - } - */ return recheck; } - private boolean handleLegendRule(Player p, CardZoneTable table) { + private boolean handleLegendRule(Player p, CardCollection noRegCreats) { final List a = CardLists.getType(p.getCardsIn(ZoneType.Battlefield), "Legendary"); if (a.isEmpty() || game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noLegendRule)) { return false; } boolean recheck = false; + // TODO legend rule exception into static ability List yamazaki = CardLists.getKeyword(a, "Legend rule doesn't apply to CARDNAME."); a.removeAll(yamazaki); @@ -1715,6 +1705,8 @@ public class GameAction { } } + // TODO handle Spy Kit + for (String name : uniqueLegends.keySet()) { Collection cc = uniqueLegends.get(name); if (cc.size() < 2) { @@ -1725,20 +1717,14 @@ public class GameAction { Card toKeep = p.getController().chooseSingleEntityForEffect(new CardCollection(cc), new SpellAbility.EmptySa(ApiType.InternalLegendaryRule, new Card(-1, game), p), "You have multiple legendary permanents named \""+name+"\" in play.\n\nChoose the one to stay on battlefield (the rest will be moved to graveyard)", null); - for (Card c: cc) { - if (c != toKeep) { - //for animation - c.updateWasDestroyed(true); - sacrificeDestroy(c, null, table, null); - } - } - game.fireEvent(new GameEventCardDestroyed()); + cc.remove(toKeep); + noRegCreats.addAll(cc); } return recheck; } - private boolean handleWorldRule(CardZoneTable table) { + private boolean handleWorldRule(CardCollection noRegCreats) { final List worlds = CardLists.getType(game.getCardsIn(ZoneType.Battlefield), "World"); if (worlds.size() <= 1) { return false; @@ -1762,12 +1748,7 @@ public class GameAction { worlds.removeAll(toKeep); } - for (Card c : worlds) { - //for animation - c.updateWasDestroyed(true); - sacrificeDestroy(c, null, table, null); - game.fireEvent(new GameEventCardDestroyed()); - } + noRegCreats.addAll(worlds); return true; } diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 81fbbc77dfd..0370d3fcfac 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -691,7 +691,7 @@ public final class GameActionUtil { // TODO: Add targeting to the effect so it knows who it's dealing with game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, null); + game.getAction().moveTo(ZoneType.Command, eff, null, null); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); return eff; diff --git a/forge-game/src/main/java/forge/game/Match.java b/forge-game/src/main/java/forge/game/Match.java index b7468054fd4..32329b57858 100644 --- a/forge-game/src/main/java/forge/game/Match.java +++ b/forge-game/src/main/java/forge/game/Match.java @@ -7,6 +7,7 @@ import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckFormat; import forge.deck.DeckSection; +import forge.game.ability.AbilityKey; import forge.game.card.Card; import forge.game.card.CardCollectionView; import forge.game.event.Event; @@ -80,7 +81,7 @@ public class Match { Multimap list = game.chooseCardsForAnte(rules.getMatchAnteRarity()); for (Entry kv : list.entries()) { Player p = kv.getKey(); - game.getAction().moveTo(ZoneType.Ante, kv.getValue(), null); + game.getAction().moveTo(ZoneType.Ante, kv.getValue(), null, AbilityKey.newMap()); game.getGameLog().add(GameLogEntryType.ANTE, p + " anted " + kv.getValue()); } game.fireEvent(new GameEventAnteCardsSelected(list)); @@ -303,7 +304,7 @@ public class Match { // Create an effect that lets you cast your companion from your sideboard if (companion != null) { PlayerZone commandZone = player.getZone(ZoneType.Command); - companion = game.getAction().moveTo(ZoneType.Command, companion, null); + companion = game.getAction().moveTo(ZoneType.Command, companion, null, AbilityKey.newMap()); commandZone.add(Player.createCompanionEffect(game, companion)); player.updateZoneForView(commandZone); diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 9dbed5e6b24..27d34292b56 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -435,7 +435,7 @@ public abstract class SpellAbilityEffect { // TODO: Add targeting to the effect so it knows who it's dealing with game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, null); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } @@ -553,7 +553,7 @@ public abstract class SpellAbilityEffect { // TODO: Add targeting to the effect so it knows who it's dealing with game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, null); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } @@ -685,13 +685,13 @@ public abstract class SpellAbilityEffect { }; } - protected static void discard(SpellAbility sa, CardZoneTable table, final boolean effect, Map discardedMap) { + protected static void discard(SpellAbility sa, CardZoneTable table, final boolean effect, Map discardedMap, Map params) { Set discarders = discardedMap.keySet(); for (Player p : discarders) { final CardCollection discardedByPlayer = new CardCollection(); for (Card card : Lists.newArrayList(discardedMap.get(p))) { // without copying will get concurrent modification exception if (card == null) { continue; } - if (p.discard(card, sa, effect, table) != null) { + if (p.discard(card, sa, effect, table, params) != null) { discardedByPlayer.add(card); if (sa.hasParam("RememberDiscarded")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/AddTurnEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AddTurnEffect.java index 71cd3c5b321..34861a8e750 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AddTurnEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AddTurnEffect.java @@ -4,6 +4,7 @@ import java.util.List; import forge.game.Game; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -84,7 +85,7 @@ public class AddTurnEffect extends SpellAbilityEffect { eff.addStaticAbility(stEffect); game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java index 0622cbd6f8a..a726d0a47ee 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/BalanceEffect.java @@ -49,6 +49,8 @@ public class BalanceEffect extends SpellAbilityEffect { } Map params = AbilityKey.newMap(); + params.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + params.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); CardZoneTable table = new CardZoneTable(); for (int i = 0; i < players.size(); i++) { Player p = players.get(i); @@ -67,7 +69,7 @@ public class BalanceEffect extends SpellAbilityEffect { } if (zone.equals(ZoneType.Hand)) { - discard(sa, table, true, discardedMap); + discard(sa, table, true, discardedMap, params); } table.triggerChangesZoneAll(game, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index c76f0ae1c7a..351367581a6 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -620,7 +620,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { } } - Map moveParams = Maps.newEnumMap(AbilityKey.class); + Map moveParams = AbilityKey.newMap(); moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard); if (sa.isReplacementAbility()) { @@ -699,7 +699,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect { gameCard.setExiledWith(host); gameCard.setExiledBy(host.getController()); } - movedCard = game.getAction().moveTo(destination, gameCard, sa); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); + moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard); + movedCard = game.getAction().moveTo(destination, gameCard, sa, moveParams); if (ZoneType.Hand.equals(destination) && ZoneType.Command.equals(originZone.getZoneType())) { StringBuilder sb = new StringBuilder(); sb.append(movedCard.getName()).append(" has moved from Command Zone to ").append(player).append("'s hand."); @@ -1210,7 +1213,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { for (final Card c : chosenCards) { Card movedCard = null; final Zone originZone = game.getZoneOf(c); - Map moveParams = Maps.newEnumMap(AbilityKey.class); + Map moveParams = AbilityKey.newMap(); moveParams.put(AbilityKey.FoundSearchingLibrary, searchedLibrary); moveParams.put(AbilityKey.LastStateBattlefield, lastStateBattlefield); moveParams.put(AbilityKey.LastStateGraveyard, lastStateGraveyard); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java index a0499a41be6..cdecd9ce083 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DamagePreventEffectBase.java @@ -6,6 +6,7 @@ import forge.GameCommand; import forge.game.Game; import forge.game.GameObject; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -65,7 +66,7 @@ public abstract class DamagePreventEffectBase extends SpellAbilityEffect { } game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java index f66fe752f83..fce8c6cf64c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DiscardEffect.java @@ -9,6 +9,7 @@ import com.google.common.collect.Maps; import forge.game.Game; import forge.game.GameActionUtil; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -287,7 +288,11 @@ public class DiscardEffect extends SpellAbilityEffect { discardedMap.put(p, toBeDiscarded); } - discard(sa, table, true, discardedMap); + Map params = AbilityKey.newMap(); + params.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + params.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); + + discard(sa, table, true, discardedMap, params); // run trigger if something got milled table.triggerChangesZoneAll(game, sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java index bd14ab704cb..f14adfc3cc2 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DrawEffect.java @@ -1,7 +1,9 @@ package forge.game.ability.effects; import java.util.List; +import java.util.Map; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -52,6 +54,9 @@ public class DrawEffect extends SpellAbilityEffect { final boolean upto = sa.hasParam("Upto"); final boolean optional = sa.hasParam("OptionalDecider") || upto; + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); for (final Player p : getDefinedPlayersOrTargeted(sa)) { // TODO can this be removed? @@ -80,7 +85,7 @@ public class DrawEffect extends SpellAbilityEffect { actualNum = p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyCardDoYouWantDraw"), 0, actualNum); } - final CardCollectionView drawn = p.drawCards(actualNum, sa); + final CardCollectionView drawn = p.drawCards(actualNum, sa, moveParams); if (sa.hasParam("Reveal")) { if (sa.getParam("Reveal").equals("All")) { p.getGame().getAction().reveal(drawn, p, false); diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java index 66d595cab19..58af067e77e 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java @@ -2,6 +2,7 @@ package forge.game.ability.effects; import java.util.EnumSet; import java.util.List; +import java.util.Map; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -12,6 +13,7 @@ import forge.card.CardRarity; import forge.game.Game; import forge.game.GameObject; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -136,6 +138,10 @@ public class EffectEffect extends SpellAbilityEffect { image = hostCard.getImageKey(); } + Map params = AbilityKey.newMap(); + params.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + params.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); + for (Player controller : effectOwner) { final Card eff = createEffect(sa, controller, name, image); eff.setSetCode(sa.getHostCard().getSetCode()); @@ -322,7 +328,7 @@ public class EffectEffect extends SpellAbilityEffect { // TODO: Add targeting to the effect so it knows who it's dealing with game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, params); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); //if (effectTriggers != null) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java index 314468cad29..05beb40e92d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/EncodeEffect.java @@ -1,7 +1,10 @@ package forge.game.ability.effects; +import java.util.Map; + import forge.game.Game; import forge.game.GameLogEntryType; +import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardCollectionView; @@ -49,8 +52,12 @@ public class EncodeEffect extends SpellAbilityEffect { return; } + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); + // move host card to exile - Card movedCard = game.getAction().moveTo(ZoneType.Exile, host, sa); + Card movedCard = game.getAction().moveTo(ZoneType.Exile, host, sa, moveParams); // choose a creature Card choice = player.getController().chooseSingleEntityForEffect(choices, sa, Localizer.getInstance().getMessage("lblChooseACreatureYouControlToEncode") + " ", true, null); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ExploreEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ExploreEffect.java index 3299cef13a1..36170ceab0d 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ExploreEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ExploreEffect.java @@ -1,6 +1,7 @@ package forge.game.ability.effects; import java.util.List; +import java.util.Map; import com.google.common.collect.Lists; @@ -48,6 +49,9 @@ public class ExploreEffect extends SpellAbilityEffect { GameEntityCounterTable table = new GameEntityCounterTable(); final CardZoneTable triggerList = new CardZoneTable(); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); for (final Card c : getTargetCards(sa)) { // revealed land card boolean revealedLand = false; @@ -59,7 +63,7 @@ public class ExploreEffect extends SpellAbilityEffect { final Card r = top.getFirst(); final Zone originZone = game.getZoneOf(r); if (r.isLand()) { - movedCard = game.getAction().moveTo(ZoneType.Hand, r, sa); + movedCard = game.getAction().moveTo(ZoneType.Hand, r, sa, moveParams); revealedLand = true; } else { // TODO find better way to choose optional send away @@ -67,7 +71,7 @@ public class ExploreEffect extends SpellAbilityEffect { ZoneType.Graveyard, Lists.newArrayList(ZoneType.Library), sa, top, null, Localizer.getInstance().getMessage("lblPutThisCardToYourGraveyard"), true, pl); if (choosen != null) { - movedCard = game.getAction().moveTo(ZoneType.Graveyard, choosen, sa); + movedCard = game.getAction().moveTo(ZoneType.Graveyard, choosen, sa, moveParams); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java index 7db93850abe..335e8eeb3b7 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FogEffect.java @@ -2,6 +2,7 @@ package forge.game.ability.effects; import forge.GameCommand; import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.replacement.ReplacementEffect; @@ -32,7 +33,7 @@ public class FogEffect extends SpellAbilityEffect { eff.addReplacementEffect(re); game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); diff --git a/forge-game/src/main/java/forge/game/ability/effects/LearnEffect.java b/forge-game/src/main/java/forge/game/ability/effects/LearnEffect.java index 207b8606f54..68d89b805d2 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/LearnEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/LearnEffect.java @@ -1,6 +1,9 @@ package forge.game.ability.effects; +import java.util.Map; + import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardZoneTable; @@ -18,8 +21,11 @@ public class LearnEffect extends SpellAbilityEffect { final Card source = sa.getHostCard(); final Game game = source.getGame(); CardZoneTable table = new CardZoneTable(); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); for (Player p : getTargetPlayers(sa)) { - p.learnLesson(sa, table); + p.learnLesson(sa, table, moveParams); } table.triggerChangesZoneAll(game, sa); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java index a36c38d4507..5d32044542b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MakeCardEffect.java @@ -1,7 +1,10 @@ package forge.game.ability.effects; +import java.util.Map; + import forge.StaticData; import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -13,6 +16,9 @@ import forge.game.zone.ZoneType; public class MakeCardEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); for (final Player player : getTargetPlayers(sa)) { final Card source = sa.getHostCard(); final Game game = player.getGame(); @@ -43,13 +49,13 @@ public class MakeCardEffect extends SpellAbilityEffect { if (!sa.hasParam("NotToken")) { card.setTokenCard(true); } - game.getAction().moveTo(ZoneType.None, card, sa); + game.getAction().moveTo(ZoneType.None, card, sa, moveParams); cards.add(card); amount--; } for (final Card c : cards) { - game.getAction().moveTo(zone, c, sa); + game.getAction().moveTo(zone, c, sa, moveParams); if (sa.hasParam("RememberMade")) { sa.getHostCard().addRemembered(c); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/MillEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MillEffect.java index d9c2ff553fa..21bb6d86db3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MillEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MillEffect.java @@ -1,7 +1,10 @@ package forge.game.ability.effects; +import java.util.Map; + import forge.game.Game; import forge.game.GameLogEntryType; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -35,6 +38,9 @@ public class MillEffect extends SpellAbilityEffect { } final CardZoneTable table = new CardZoneTable(); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); for (final Player p : getTargetPlayers(sa)) { if (!sa.usesTargeting() || p.canBeTargetedBy(sa)) { @@ -45,7 +51,7 @@ public class MillEffect extends SpellAbilityEffect { continue; } } - final CardCollectionView milled = p.mill(numCards, destination, bottom, sa, table); + final CardCollectionView milled = p.mill(numCards, destination, bottom, sa, table, moveParams); // Reveal the milled cards, so players don't have to manually inspect the // graveyard to figure out which ones were milled. if (!facedown && reveal) { // do not reveal when exiling face down diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlaneswalkEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlaneswalkEffect.java index dc3bc6970ed..caac7f2b2c3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlaneswalkEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlaneswalkEffect.java @@ -18,9 +18,9 @@ public class PlaneswalkEffect extends SpellAbilityEffect { } if (sa.hasParam("Defined")) { CardCollectionView destinations = AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam("Defined"), sa); - sa.getActivatingPlayer().planeswalkTo(destinations); + sa.getActivatingPlayer().planeswalkTo(sa, destinations); } else { - sa.getActivatingPlayer().planeswalk(); + sa.getActivatingPlayer().planeswalk(sa); } } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java index 3b20b103075..dc6f8f64b63 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PlayEffect.java @@ -19,6 +19,7 @@ import forge.StaticData; import forge.card.CardRulesPredicates; import forge.game.Game; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -216,6 +217,11 @@ public class PlayEffect extends SpellAbilityEffect { boolean singleOption = tgtCards.size() == 1 && amount == 1 && optional; Map params = hasTotalCMCLimit ? new HashMap<>() : null; + + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); + while (!tgtCards.isEmpty() && amount > 0 && totalCMCLimit >= 0) { if (hasTotalCMCLimit) { // filter out cards with mana value greater than limit @@ -376,12 +382,12 @@ public class PlayEffect extends SpellAbilityEffect { // can't be done later if (sa.hasParam("ReplaceGraveyard")) { - addReplaceGraveyardEffect(tgtCard, sa, sa.getParam("ReplaceGraveyard")); + addReplaceGraveyardEffect(tgtCard, sa, sa.getParam("ReplaceGraveyard"), moveParams); } // For Illusionary Mask effect if (sa.hasParam("ReplaceIlluMask")) { - addIllusionaryMaskReplace(tgtCard, sa); + addIllusionaryMaskReplace(tgtCard, sa, moveParams); } tgtSA.setSVar("IsCastFromPlayEffect", "True"); @@ -420,7 +426,7 @@ public class PlayEffect extends SpellAbilityEffect { } // end resolve - protected void addReplaceGraveyardEffect(Card c, SpellAbility sa, String zone) { + protected void addReplaceGraveyardEffect(Card c, SpellAbility sa, String zone, Map moveParams) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); final Player controller = sa.getActivatingPlayer(); @@ -461,12 +467,12 @@ public class PlayEffect extends SpellAbilityEffect { // TODO: Add targeting to the effect so it knows who it's dealing with game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, moveParams); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } - protected void addIllusionaryMaskReplace(Card c, SpellAbility sa) { + protected void addIllusionaryMaskReplace(Card c, SpellAbility sa, Map moveParams) { final Card hostCard = sa.getHostCard(); final Game game = hostCard.getGame(); final Player controller = sa.getActivatingPlayer(); @@ -497,7 +503,7 @@ public class PlayEffect extends SpellAbilityEffect { addExileOnCounteredTrigger(eff); game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, moveParams); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java index 82bbb917667..2ed822bb1d4 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RegenerateBaseEffect.java @@ -3,6 +3,7 @@ package forge.game.ability.effects; import forge.GameCommand; import forge.game.Game; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -71,7 +72,7 @@ public abstract class RegenerateBaseEffect extends SpellAbilityEffect { c.addShield(eff); } game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); diff --git a/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java index 2943b46b509..f471abd7c01 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SetInMotionEffect.java @@ -41,7 +41,7 @@ public class SetInMotionEffect extends SpellAbilityEffect { } game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, controller.getActiveScheme(), null); + game.getAction().moveTo(ZoneType.Command, controller.getActiveScheme(), null, AbilityKey.newMap()); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); // Run triggers diff --git a/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java index 43d6c2b5631..a589a52d2c4 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SkipPhaseEffect.java @@ -5,6 +5,7 @@ import java.util.List; import forge.GameCommand; import forge.game.Game; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.player.Player; @@ -115,7 +116,7 @@ public class SkipPhaseEffect extends SpellAbilityEffect { eff.addReplacementEffect(re); game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java index 4f64e1d89d2..0d81ed142ca 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SkipTurnEffect.java @@ -4,6 +4,7 @@ import java.util.List; import forge.game.Game; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -61,7 +62,7 @@ public class SkipTurnEffect extends SpellAbilityEffect { eff.addReplacementEffect(re); game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, eff, sa); + game.getAction().moveTo(ZoneType.Command, eff, sa, AbilityKey.newMap()); eff.updateStateForView(); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/SubgameEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SubgameEffect.java index 7ec64259baf..51bcf22dba2 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SubgameEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SubgameEffect.java @@ -9,6 +9,7 @@ import com.google.common.collect.Lists; import forge.card.MagicColor; import forge.game.Game; import forge.game.GameOutcome; +import forge.game.ability.AbilityKey; import forge.game.ability.ApiType; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -127,7 +128,7 @@ public class SubgameEffect extends SpellAbilityEffect { // Create an effect that lets you cast your companion from your sideboard if (companion != null) { PlayerZone commandZone = player.getZone(ZoneType.Command); - companion = subgame.getAction().moveTo(ZoneType.Command, companion, null); + companion = subgame.getAction().moveTo(ZoneType.Command, companion, null, AbilityKey.newMap()); commandZone.add(Player.createCompanionEffect(subgame, companion)); player.updateZoneForView(commandZone); @@ -242,7 +243,7 @@ public class SubgameEffect extends SpellAbilityEffect { } } for (final Card card : movedCommanders) { - maingame.getAction().moveTo(ZoneType.Library, card, null); + maingame.getAction().moveTo(ZoneType.Library, card, null, AbilityKey.newMap()); } player.shuffle(sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java index 1ddc7776ea3..b148a44af13 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SurveilEffect.java @@ -1,5 +1,8 @@ package forge.game.ability.effects; +import java.util.Map; + +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.CardZoneTable; @@ -34,6 +37,9 @@ public class SurveilEffect extends SpellAbilityEffect { boolean isOptional = sa.hasParam("Optional"); CardZoneTable table = new CardZoneTable(); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); for (final Player p : getTargetPlayers(sa)) { if (!sa.usesTargeting() || p.canBeTargetedBy(sa)) { @@ -41,7 +47,7 @@ public class SurveilEffect extends SpellAbilityEffect { continue; } - p.surveil(num, sa, table); + p.surveil(num, sa, table, moveParams); } } table.triggerChangesZoneAll(sa.getHostCard().getGame(), sa); diff --git a/forge-game/src/main/java/forge/game/ability/effects/VentureEffect.java b/forge-game/src/main/java/forge/game/ability/effects/VentureEffect.java index c13a27706ff..01009a820de 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/VentureEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/VentureEffect.java @@ -27,7 +27,7 @@ import forge.util.Localizer; public class VentureEffect extends SpellAbilityEffect { - private Card getDungeonCard(SpellAbility sa, Player player) { + private Card getDungeonCard(SpellAbility sa, Player player, Map moveParams) { final Game game = player.getGame(); CardCollectionView commandCards = player.getCardsIn(ZoneType.Command); @@ -50,7 +50,7 @@ public class VentureEffect extends SpellAbilityEffect { Card dungeon = player.getController().chooseDungeon(player, dungeonCards, message); game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); - game.getAction().moveTo(ZoneType.Command, dungeon, sa); + game.getAction().moveTo(ZoneType.Command, dungeon, sa, moveParams); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); return dungeon; @@ -85,13 +85,13 @@ public class VentureEffect extends SpellAbilityEffect { } } - private void ventureIntoDungeon(SpellAbility sa, Player player) { + private void ventureIntoDungeon(SpellAbility sa, Player player, Map moveParams) { if (StaticAbilityCantVenture.cantVenture(player)) { return; } final Game game = player.getGame(); - Card dungeon = getDungeonCard(sa, player); + Card dungeon = getDungeonCard(sa, player, moveParams); String room = dungeon.getCurrentRoom(); String nextRoom = null; @@ -117,9 +117,13 @@ public class VentureEffect extends SpellAbilityEffect { @Override public void resolve(SpellAbility sa) { + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); + for (final Player p : getTargetPlayers(sa)) { if (!sa.usesTargeting() || p.canBeTargetedBy(sa)) { - ventureIntoDungeon(sa, p); + ventureIntoDungeon(sa, p, moveParams); } } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ZoneExchangeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ZoneExchangeEffect.java index 694fa05e8aa..280d5360963 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ZoneExchangeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ZoneExchangeEffect.java @@ -1,6 +1,9 @@ package forge.game.ability.effects; +import java.util.Map; + import forge.game.Game; +import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; @@ -87,8 +90,11 @@ public class ZoneExchangeEffect extends SpellAbilityEffect { object1.unattachFromEntity(c); object2.attachToEntity(c); } + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); // Exchange Zone - game.getAction().moveTo(zone2, object1, sa); - game.getAction().moveTo(zone1, object2, sa); + game.getAction().moveTo(zone2, object1, sa, moveParams); + game.getAction().moveTo(zone1, object2, sa, moveParams); } } diff --git a/forge-game/src/main/java/forge/game/cost/CostDraw.java b/forge-game/src/main/java/forge/game/cost/CostDraw.java index 6885be83ebe..8a5c77f0287 100644 --- a/forge-game/src/main/java/forge/game/cost/CostDraw.java +++ b/forge-game/src/main/java/forge/game/cost/CostDraw.java @@ -17,6 +17,9 @@ */ package forge.game.cost; +import java.util.Map; + +import forge.game.ability.AbilityKey; import forge.game.card.Card; import forge.game.player.Player; import forge.game.player.PlayerCollection; @@ -94,8 +97,11 @@ public class CostDraw extends CostPart { */ @Override public final boolean payAsDecided(final Player ai, final PaymentDecision decision, SpellAbility ability, final boolean effect) { + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, ability.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, ability.getLastStateGraveyard()); for (final Player p : decision.players) { - p.drawCards(decision.c, ability); + p.drawCards(decision.c, ability, moveParams); } return true; } diff --git a/forge-game/src/main/java/forge/game/cost/CostMill.java b/forge-game/src/main/java/forge/game/cost/CostMill.java index eb184a618d1..69091a6f337 100644 --- a/forge-game/src/main/java/forge/game/cost/CostMill.java +++ b/forge-game/src/main/java/forge/game/cost/CostMill.java @@ -17,6 +17,9 @@ */ package forge.game.cost; +import java.util.Map; + +import forge.game.ability.AbilityKey; import forge.game.card.CardCollection; import forge.game.card.CardZoneTable; import forge.game.player.Player; @@ -88,7 +91,10 @@ public class CostMill extends CostPart { @Override public final boolean payAsDecided(final Player ai, final PaymentDecision decision, SpellAbility ability, final boolean effect) { CardZoneTable table = new CardZoneTable(); - ability.getPaidHash().put("Milled", (CardCollection) ai.mill(decision.c, ZoneType.Graveyard, false, ability, table)); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, ai.getGame().getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, ai.getGame().getLastStateGraveyard()); + ability.getPaidHash().put("Milled", (CardCollection) ai.mill(decision.c, ZoneType.Graveyard, false, ability, table, moveParams)); table.triggerChangesZoneAll(ai.getGame(), ability); return true; } diff --git a/forge-game/src/main/java/forge/game/cost/CostSacrifice.java b/forge-game/src/main/java/forge/game/cost/CostSacrifice.java index 2577ecb0957..ec48bb0d976 100644 --- a/forge-game/src/main/java/forge/game/cost/CostSacrifice.java +++ b/forge-game/src/main/java/forge/game/cost/CostSacrifice.java @@ -19,8 +19,11 @@ package forge.game.cost; import forge.card.CardType; +import java.util.Map; + import com.google.common.collect.Iterables; +import forge.game.ability.AbilityKey; import forge.game.card.Card; import forge.game.card.CardCollectionView; import forge.game.card.CardLists; @@ -133,7 +136,10 @@ public class CostSacrifice extends CostPartWithList { @Override protected Card doPayment(SpellAbility ability, Card targetCard, final boolean effect) { // no table there, it is already handled by CostPartWithList - return targetCard.getGame().getAction().sacrifice(targetCard, ability, effect, null, null); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, ability.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, ability.getLastStateGraveyard()); + return targetCard.getGame().getAction().sacrifice(targetCard, ability, effect, null, moveParams); } /* (non-Javadoc) diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index 17cfd4e139e..3f4022e6590 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -393,11 +393,15 @@ public class PhaseHandler implements java.io.Serializable { int numDiscard = playerTurn.isUnlimitedHandSize() || handSize <= max || handSize == 0 ? 0 : handSize - max; if (numDiscard > 0) { + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, game.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, game.getLastStateGraveyard()); + final CardZoneTable table = new CardZoneTable(); final CardCollection discarded = new CardCollection(); boolean firstDiscarded = playerTurn.getNumDiscardedThisTurn() == 0; for (Card c : playerTurn.getController().chooseCardsToDiscardToMaximumHandSize(numDiscard)) { - if (playerTurn.discard(c, null, false, table) != null) { + if (playerTurn.discard(c, null, false, table, moveParams) != null) { discarded.add(c); } } diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 2c63761879c..49dcbf8959d 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -326,10 +326,14 @@ public class Player extends GameEntity implements Comparable { return; } + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, game.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, game.getLastStateGraveyard()); + game.getTriggerHandler().suppressMode(TriggerType.ChangesZone); activeScheme = getZone(ZoneType.SchemeDeck).get(0); // gameAction moveTo ? - game.getAction().moveTo(ZoneType.Command, activeScheme, null); + game.getAction().moveTo(ZoneType.Command, activeScheme, null, moveParams); game.getTriggerHandler().clearSuppression(TriggerType.ChangesZone); // Run triggers @@ -1101,10 +1105,13 @@ public class Player extends GameEntity implements Comparable { return true; } - public void surveil(int num, SpellAbility cause, CardZoneTable table) { + public void surveil(int num, SpellAbility cause, CardZoneTable table, Map params) { final Map repParams = AbilityKey.mapFromAffected(this); repParams.put(AbilityKey.Source, cause); repParams.put(AbilityKey.SurveilNum, num); + if (params != null) { + repParams.putAll(params); + } switch (getGame().getReplacementHandler().run(ReplacementType.Surveil, repParams)) { case NotReplaced: @@ -1133,7 +1140,7 @@ public class Player extends GameEntity implements Comparable { if (toGrave != null) { for (Card c : toGrave) { ZoneType oZone = c.getZone().getZoneType(); - Card moved = getGame().getAction().moveToGraveyard(c, cause); + Card moved = getGame().getAction().moveToGraveyard(c, cause, params); table.put(oZone, moved.getZone().getZoneType(), moved); numToGrave++; } @@ -1142,7 +1149,7 @@ public class Player extends GameEntity implements Comparable { if (toTop != null) { Collections.reverse(toTop); // the last card in list will become topmost in library, have to revert thus. for (Card c : toTop) { - getGame().getAction().moveToLibrary(c, cause); + getGame().getAction().moveToLibrary(c, cause, params); numToTop++; } } @@ -1152,6 +1159,9 @@ public class Player extends GameEntity implements Comparable { surveilThisTurn++; final Map runParams = AbilityKey.mapFromPlayer(this); runParams.put(AbilityKey.NumThisTurn, surveilThisTurn); + if (params != null) { + runParams.putAll(params); + } getGame().getTriggerHandler().runTrigger(TriggerType.Surveil, runParams, false); } @@ -1176,13 +1186,13 @@ public class Player extends GameEntity implements Comparable { } public final CardCollectionView drawCard() { - return drawCards(1, null); + return drawCards(1, null, AbilityKey.newMap()); } public final CardCollectionView drawCards(final int n) { - return drawCards(n, null); + return drawCards(n, null, AbilityKey.newMap()); } - public final CardCollectionView drawCards(final int n, SpellAbility cause) { + public final CardCollectionView drawCards(final int n, SpellAbility cause, Map params) { final CardCollection drawn = new CardCollection(); if (n <= 0) { return drawn; @@ -1191,6 +1201,9 @@ public class Player extends GameEntity implements Comparable { // Replacement effects final Map repRunParams = AbilityKey.mapFromAffected(this); repRunParams.put(AbilityKey.Number, n); + if (params != null) { + repRunParams.putAll(params); + } if (game.getReplacementHandler().run(ReplacementType.DrawCards, repRunParams) != ReplacementResult.NotReplaced) { return drawn; @@ -1204,7 +1217,7 @@ public class Player extends GameEntity implements Comparable { if (gameStarted && !canDraw()) { return drawn; } - drawn.addAll(doDraw(toReveal, cause)); + drawn.addAll(doDraw(toReveal, cause, params)); } // reveal multiple drawn cards when playing with the top of the library revealed @@ -1219,13 +1232,16 @@ public class Player extends GameEntity implements Comparable { /** * @return a CardCollectionView of cards actually drawn */ - private CardCollectionView doDraw(Map revealed, SpellAbility cause) { + private CardCollectionView doDraw(Map revealed, SpellAbility cause, Map params) { final CardCollection drawn = new CardCollection(); final PlayerZone library = getZone(ZoneType.Library); // Replacement effects Map repParams = AbilityKey.mapFromAffected(this); repParams.put(AbilityKey.Cause, cause); + if (params != null) { + repParams.putAll(params); + } if (game.getReplacementHandler().run(ReplacementType.Draw, repParams) != ReplacementResult.NotReplaced) { return drawn; } @@ -1246,7 +1262,7 @@ public class Player extends GameEntity implements Comparable { } } - c = game.getAction().moveToHand(c, cause); + c = game.getAction().moveToHand(c, cause, params); drawn.add(c); for (Player p : pList) { @@ -1267,6 +1283,9 @@ public class Player extends GameEntity implements Comparable { view.updateNumDrawnThisTurn(this); final Map runParams = AbilityKey.mapFromPlayer(this); + if (params != null) { + runParams.putAll(params); + } // CR 121.8 card was drawn as part of another sa (e.g. paying with Chromantic Sphere), hide it temporarily if (game.getTopLibForPlayer(this) != null && getPaidForSA() != null && cause != null && getPaidForSA() != cause.getRootAbility()) { @@ -1414,9 +1433,6 @@ public class Player extends GameEntity implements Comparable { numRollsThisTurn++; } - public final Card discard(final Card c, final SpellAbility sa, final boolean effect, CardZoneTable table) { - return discard(c, sa, effect, table, null); - } public final Card discard(final Card c, final SpellAbility sa, final boolean effect, CardZoneTable table, Map params) { if (!c.canBeDiscardedBy(sa, effect)) { return null; @@ -1575,13 +1591,16 @@ public class Player extends GameEntity implements Comparable { } public final CardCollectionView mill(int n, final ZoneType destination, - final boolean bottom, SpellAbility sa, CardZoneTable table) { + final boolean bottom, SpellAbility sa, CardZoneTable table, Map params) { final CardCollectionView lib = getCardsIn(ZoneType.Library); final CardCollection milled = new CardCollection(); // Replacement effects final Map repRunParams = AbilityKey.mapFromAffected(this); repRunParams.put(AbilityKey.Number, n); + if (params != null) { + repRunParams.putAll(params); + } if (destination == ZoneType.Graveyard && !bottom) { switch (getGame().getReplacementHandler().run(ReplacementType.Mill, repRunParams)) { @@ -1618,7 +1637,7 @@ public class Player extends GameEntity implements Comparable { for (Card m : milledView) { final ZoneType origin = m.getZone().getZoneType(); - final Card d = game.getAction().moveTo(destination, m, sa); + final Card d = game.getAction().moveTo(destination, m, sa, params); if (d.getZone().is(destination)) { table.put(origin, d.getZone().getZoneType(), d); } @@ -2580,21 +2599,25 @@ public class Player extends GameEntity implements Comparable { * Takes the top plane of the planar deck and put it face up in the command zone. * Then runs triggers. */ - public void planeswalk() { - planeswalkTo(new CardCollection(getZone(ZoneType.PlanarDeck).get(0))); + public void planeswalk(SpellAbility sa) { + planeswalkTo(sa, new CardCollection(getZone(ZoneType.PlanarDeck).get(0))); } /** * Puts the planes in the argument and puts them face up in the command zone. * Then runs triggers. */ - public void planeswalkTo(final CardCollectionView destinations) { + public void planeswalkTo(SpellAbility sa, final CardCollectionView destinations) { System.out.println(getName() + ": planeswalk to " + destinations.toString()); currentPlanes.addAll(destinations); game.getView().updatePlanarPlayer(getView()); + Map moveParams = AbilityKey.newMap(); + moveParams.put(AbilityKey.LastStateBattlefield, sa.getLastStateBattlefield()); + moveParams.put(AbilityKey.LastStateGraveyard, sa.getLastStateGraveyard()); + for (Card c : currentPlanes) { - game.getAction().moveTo(ZoneType.Command,c, null); + game.getAction().moveTo(ZoneType.Command, c, sa, moveParams); //getZone(ZoneType.PlanarDeck).remove(c); //getZone(ZoneType.Command).add(c); } @@ -3414,10 +3437,13 @@ public class Player extends GameEntity implements Comparable { } } - public void learnLesson(SpellAbility sa, CardZoneTable table) { + public void learnLesson(SpellAbility sa, CardZoneTable table, Map params) { // Replacement effects Map repParams = AbilityKey.mapFromAffected(this); repParams.put(AbilityKey.Cause, sa); + if (params != null) { + repParams.putAll(params); + } if (game.getReplacementHandler().run(ReplacementType.Learn, repParams) != ReplacementResult.NotReplaced) { return; } @@ -3438,11 +3464,11 @@ public class Player extends GameEntity implements Comparable { } if (c.isInZone(ZoneType.Sideboard)) { // Sideboard Lesson to Hand game.getAction().reveal(new CardCollection(c), c.getOwner(), true); - Card moved = game.getAction().moveTo(ZoneType.Hand, c, sa); + Card moved = game.getAction().moveTo(ZoneType.Hand, c, sa, params); table.put(ZoneType.Sideboard, ZoneType.Hand, moved); } else if (c.isInZone(ZoneType.Hand)) { // Discard and Draw boolean firstDiscard = getNumDiscardedThisTurn() == 0; - if (discard(c, sa, true, table) != null) { + if (discard(c, sa, true, table, params) != null) { // Change this if something would make multiple player learn at the same time // Discard Trigger outside Effect @@ -3450,9 +3476,12 @@ public class Player extends GameEntity implements Comparable { runParams.put(AbilityKey.Cards, new CardCollection(c)); runParams.put(AbilityKey.Cause, sa); runParams.put(AbilityKey.FirstTime, firstDiscard); + if (params != null) { + runParams.putAll(params); + } getGame().getTriggerHandler().runTrigger(TriggerType.DiscardedAll, runParams, false); - for (Card d : drawCards(1, sa)) { + for (Card d : drawCards(1, sa, params)) { table.put(ZoneType.Library, ZoneType.Hand, d); // does a ChangesZoneAll care about moving from Library to Hand } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 69b1be0d2b7..3187ab21a96 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -44,7 +44,8 @@ import io.sentry.Sentry; import io.sentry.event.BreadcrumbBuilder; public class TriggerHandler { - private final List suppressedModes = Collections.synchronizedList(new ArrayList<>()); + private final Set suppressedModes = Collections.synchronizedSet(EnumSet.noneOf(TriggerType.class)); + private boolean allSuppressed = false; private final List activeTriggers = Collections.synchronizedList(new ArrayList<>()); private final List delayedTriggers = Collections.synchronizedList(new ArrayList<>()); @@ -106,18 +107,15 @@ public class TriggerHandler { } public final void setSuppressAllTriggers(final boolean suppress) { - for (TriggerType t : TriggerType.values()) { - if (suppress) { - suppressMode(t); - } else { - clearSuppression(t); - } - } + allSuppressed = suppress; } public final void clearSuppression(final TriggerType mode) { suppressedModes.remove(mode); } + public boolean isTriggerSuppressed(final TriggerType mode) { + return allSuppressed || suppressedModes.contains(mode); + } public static Trigger parseTrigger(final String trigParse, final Card host, final boolean intrinsic) { return parseTrigger(trigParse, host, intrinsic, host.getCurrentState()); @@ -252,7 +250,7 @@ public class TriggerHandler { } public final void runTrigger(final TriggerType mode, final Map runParams, boolean holdTrigger) { - if (suppressedModes.contains(mode)) { + if (isTriggerSuppressed(mode)) { return; } diff --git a/forge-gui/res/cardsfolder/t/tomb_tyrant.txt b/forge-gui/res/cardsfolder/t/tomb_tyrant.txt index dcaa579b57d..999ec22aca1 100644 --- a/forge-gui/res/cardsfolder/t/tomb_tyrant.txt +++ b/forge-gui/res/cardsfolder/t/tomb_tyrant.txt @@ -3,7 +3,7 @@ ManaCost:3 B Types:Creature Zombie Noble PT:3/3 S:Mode$ Continuous | Affected$ Zombie.Other+YouCtrl | AddPower$ 1 | AddToughness$ 1 | Description$ Other Zombies you control get +1/+1. -A:AB$ ChangeZone | Cost$ 2 B T Sac<1/Creature/creature> | ChangeType$ Zombie.Creature.YouOwn | Origin$ Graveyard | Destination$ Battlefield | AtRandom$ True | CheckSVar$ X | SVarCompare$ GE3 | PlayerTurn$ True | Hidden$ True | StackDescription$ Return a Zombie creature card at random from your graveyard to the battlefield. | SpellDescription$ Return a Zombie creature card at random from your graveyard to the battlefield. Activate only during your turn and only if there are at least three Zombie creature cards in your graveyard. +A:AB$ ChangeZone | Cost$ 2 B T Sac<1/Creature/creature> | ChangeType$ Zombie.YouOwn | Origin$ Graveyard | Destination$ Battlefield | AtRandom$ True | CheckSVar$ X | SVarCompare$ GE3 | PlayerTurn$ True | Hidden$ True | StackDescription$ Return a Zombie creature card at random from your graveyard to the battlefield. | SpellDescription$ Return a Zombie creature card at random from your graveyard to the battlefield. Activate only during your turn and only if there are at least three Zombie creature cards in your graveyard. SVar:X:Count$ValidGraveyard Creature.Zombie+YouCtrl DeckNeeds:Type$Zombie DeckHas:Ability$Graveyard diff --git a/forge-gui/res/editions/Secret Lair Drop Series.txt b/forge-gui/res/editions/Secret Lair Drop Series.txt index 9ac5878e7af..92a71fdc2dd 100644 --- a/forge-gui/res/editions/Secret Lair Drop Series.txt +++ b/forge-gui/res/editions/Secret Lair Drop Series.txt @@ -363,6 +363,7 @@ ScryfallCode=SLD 383★ R Krark's Thumb @Wooden Cyclops 384 R Swamp @Jeanne D'Angelo 385 R Island @Jeanne D'Angelo +386 R Island @Jeanne D'Angelo 396 M Tamiyo, the Moon Sage @Uta Natsume 397 M Ajani, Mentor of Heroes @Uta Natsume 398 M Angrath, the Flame-Chained @Uta Natsume diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 1b652bb756c..979949f9546 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -2803,7 +2803,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont } } } - getGame().getAction().moveTo(targetZone, forgeCard, null); + getGame().getAction().moveTo(targetZone, forgeCard, null, AbilityKey.newMap()); if (forgeCard.isCreature()) { forgeCard.setSickness(lastSummoningSickness); } @@ -2858,7 +2858,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont getGame().getAction().moveToBottomOfLibrary(forgeCard, null); } } else { - getGame().getAction().moveTo(targetZone, forgeCard, null); + getGame().getAction().moveTo(targetZone, forgeCard, null, AbilityKey.newMap()); } lastAdded = f; @@ -2898,7 +2898,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (c == null) { continue; } - if (getGame().getAction().moveTo(ZoneType.Exile, c, null) != null) { + if (getGame().getAction().moveTo(ZoneType.Exile, c, null, AbilityKey.newMap()) != null) { StringBuilder sb = new StringBuilder(); sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats."); getGame().getGameLog().add(GameLogEntryType.DISCARD, sb.toString()); @@ -2937,7 +2937,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (c == null) { continue; } - if (getGame().getAction().moveTo(ZoneType.Exile, c, null) != null) { + if (getGame().getAction().moveTo(ZoneType.Exile, c, null, AbilityKey.newMap()) != null) { StringBuilder sb = new StringBuilder(); sb.append(p).append(" exiles ").append(c).append(" due to Dev Cheats."); getGame().getGameLog().add(GameLogEntryType.ZONE_CHANGE, sb.toString()); From 9c72cd22790b7aabb88380cfae14a0e6d88a016d Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sat, 26 Feb 2022 11:58:51 +0800 Subject: [PATCH 16/16] update touch controls --- forge-gui-mobile/src/forge/Forge.java | 2 +- .../adventure/scene/DeckSelectScene.java | 2 +- .../src/forge/adventure/scene/InnScene.java | 2 +- .../adventure/scene/PlayerStatisticScene.java | 4 +- .../forge/adventure/scene/RewardScene.java | 2 +- .../forge/adventure/scene/SaveLoadScene.java | 4 +- .../forge/adventure/scene/SettingsScene.java | 4 +- .../src/forge/adventure/scene/StartScene.java | 19 ++-- .../src/forge/adventure/stage/GameHUD.java | 93 +++++++++++++------ 9 files changed, 86 insertions(+), 46 deletions(-) diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 10ac4ea26e2..ea4ea90af7d 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -1023,7 +1023,7 @@ public class Forge implements ApplicationListener { return fling(0,1000); } if(keyCode == Keys.BACK){ - if (destroyThis) + if ((destroyThis && !isMobileAdventureMode)||(splashScreen != null && splashScreen.isShowModeSelector())) exitAnimation(false); else if(onHomeScreen() && isLandscapeMode()) back(); diff --git a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java index 1adb3cc029e..89218d8c31f 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DeckSelectScene.java @@ -74,7 +74,7 @@ public class DeckSelectScene extends UIScene { @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/InnScene.java b/forge-gui-mobile/src/forge/adventure/scene/InnScene.java index 062f582b987..2d536ba4b10 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/InnScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/InnScene.java @@ -59,7 +59,7 @@ public class InnScene extends UIScene { @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { done(); } return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java index 96da3b9f8a4..9062073a3e3 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/PlayerStatisticScene.java @@ -41,7 +41,7 @@ public class PlayerStatisticScene extends UIScene { @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } return true; @@ -92,7 +92,7 @@ public class PlayerStatisticScene extends UIScene { enemiesGroup.add((data.name)).fillX().align(Align.center).fillX().space(3, 10, 3, 10); enemiesGroup.add((entry.getValue().getLeft().toString())).space(3, 2, 3, 2); enemiesGroup.add(("/")).align(Align.center).space(3, 2, 3, 2); - enemiesGroup.add((entry.getValue().getRight().toString())).align(Align.center).space(0, 2, 0, 2); + enemiesGroup.add((entry.getValue().getRight().toString())).align(Align.center).space(3, 2, 3, 2); enemiesGroup.row().space(8); } diff --git a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java index ede92f2119e..9744f3fa39c 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/RewardScene.java @@ -104,7 +104,7 @@ public class RewardScene extends UIScene { @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { done(); } return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java index ae0222fa8ae..18716fcf5c7 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SaveLoadScene.java @@ -60,7 +60,7 @@ public class SaveLoadScene extends UIScene { @Override public void clicked(InputEvent event, float x, float y) { try { - if(!button.isDisabled()) + if (!button.isDisabled()) select(i); } catch (Exception e) { e.printStackTrace(); @@ -126,7 +126,7 @@ public class SaveLoadScene extends UIScene { @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } return true; diff --git a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java index 44fd18d5180..81970e041f9 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/SettingsScene.java @@ -65,7 +65,7 @@ public class SettingsScene extends UIScene { @Override public boolean keyPressed(int keycode) { - if (keycode == Input.Keys.ESCAPE) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { back(); } return true; @@ -157,7 +157,7 @@ public class SettingsScene extends UIScene { void addLabel(String name) { Label label = new Label(name, Controls.GetSkin().get("white", Label.LabelStyle.class)); settingGroup.row().space(5); - settingGroup.add(label).align(Align.left).pad(2,2, 2, 5); + settingGroup.add(label).align(Align.left).pad(2, 2, 2, 5); } @Override diff --git a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java index 0b470677c2f..9b58e216194 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/StartScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/StartScene.java @@ -16,11 +16,11 @@ public class StartScene extends UIScene { Actor saveButton; Actor resumeButton; - public StartScene() - { + public StartScene() { super(GuiBase.isAndroid() ? "ui/start_menu_mobile.json" : "ui/start_menu.json"); } + public boolean NewGame() { Forge.switchScene(SceneType.NewGameScene.instance); return true; @@ -57,9 +57,9 @@ public class StartScene extends UIScene { @Override public void enter() { - boolean hasSaveButton=WorldSave.getCurrentSave().getWorld().getData() != null; - if(hasSaveButton) - hasSaveButton=!((TileMapScene)SceneType.TileMapScene.instance).currentMap().isInMap(); + boolean hasSaveButton = WorldSave.getCurrentSave().getWorld().getData() != null; + if (hasSaveButton) + hasSaveButton = !((TileMapScene) SceneType.TileMapScene.instance).currentMap().isInMap(); saveButton.setVisible(hasSaveButton); resumeButton.setVisible(WorldSave.getCurrentSave().getWorld().getData() != null); Gdx.input.setInputProcessor(stage); //Start taking input from the ui @@ -72,15 +72,14 @@ public class StartScene extends UIScene { } @Override - public boolean keyPressed(int keycode) - { - if (keycode == Input.Keys.ESCAPE) - { - if(WorldSave.getCurrentSave().getWorld().getData() != null) + public boolean keyPressed(int keycode) { + if (keycode == Input.Keys.ESCAPE || keycode == Input.Keys.BACK) { + if (WorldSave.getCurrentSave().getWorld().getData() != null) Resume(); } return true; } + @Override public void resLoaded() { super.resLoaded(); diff --git a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java index 8f7738c512a..19a4fd5bd9f 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java +++ b/forge-gui-mobile/src/forge/adventure/stage/GameHUD.java @@ -4,15 +4,19 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.EventListener; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.Skin; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.Touchpad; import com.badlogic.gdx.scenes.scene2d.ui.Touchpad.TouchpadStyle; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Scaling; import com.badlogic.gdx.utils.viewport.ScalingViewport; import forge.Forge; @@ -36,6 +40,10 @@ public class GameHUD extends Stage { private final Label lifePoints; private final Label money; private Image miniMap; + private TextButton deckActor, menuActor, statsActor; + private boolean deckPressed = false; + private boolean menuPressed = false; + private boolean statsPressed = false; private UIActor ui; private Touchpad touchpad; private TouchpadStyle touchpadStyle; @@ -52,7 +60,9 @@ public class GameHUD extends Stage { ui = new UIActor(Config.instance().getFile(GuiBase.isAndroid() ? "ui/hud_mobile.json" : "ui/hud.json")); miniMap = ui.findActor("map"); - + deckActor = ui.findActor("deck"); + menuActor = ui.findActor("menu"); + statsActor = ui.findActor("statistic"); miniMapPlayer = new Image(new Texture(Config.instance().getFile("ui/minimap_player.png"))); //create touchpad skin @@ -148,6 +158,13 @@ public class GameHUD extends Stage { touchpad.setVisible(false); MapStage.getInstance().GetPlayer().setMovementDirection(Vector2.Zero); WorldStage.getInstance().GetPlayer().setMovementDirection(Vector2.Zero); + //simulate button + checkButtonState(deckActor, pointer); + checkButtonState(menuActor, pointer); + checkButtonState(statsActor, pointer); + deckPressed = false; + menuPressed = false; + statsPressed = false; return super.touchUp(screenX, screenY, pointer, button); } @@ -181,7 +198,6 @@ public class GameHUD extends Stage { boolean setPosition(int screenX, int screenY, int pointer, int button) { Vector2 c=new Vector2(); - Vector2 c2=new Vector2(); Vector2 touch =new Vector2(); screenToStageCoordinates(touch.set(screenX, screenY)); screenToStageCoordinates(c.set(screenX, screenY)); @@ -189,40 +205,40 @@ public class GameHUD extends Stage { float x=(c.x-miniMap.getX())/miniMap.getWidth(); float y=(c.y-miniMap.getY())/miniMap.getHeight(); - float deckX = ui.findActor("deck").getX(); - float deckY = ui.findActor("deck").getY(); - float deckR = ui.findActor("deck").getRight(); - float deckT = ui.findActor("deck").getTop(); - float deckOriginX = ui.findActor("deck").getOriginX(); + float deckX = deckActor.getX(); + float deckY = deckActor.getY(); + float deckR = deckActor.getRight(); + float deckT = deckActor.getTop(); + float deckOriginX = deckActor.getOriginX(); //deck button bounds if (c.x>=deckX&&c.x<=deckR&&c.y>=deckY&&c.y<=deckT) { - openDeck(); - stageToScreenCoordinates(c2.set(deckOriginX, deckY)); - return super.touchDown((int)c2.x, (int)c2.y, pointer, button); + if (pointer < 1) + deckPressed = true; + return true; } - float menuX = ui.findActor("menu").getX(); - float menuY = ui.findActor("menu").getY(); - float menuR = ui.findActor("menu").getRight(); - float menuT = ui.findActor("menu").getTop(); - float menuOriginX = ui.findActor("menu").getOriginX(); + float menuX = menuActor.getX(); + float menuY = menuActor.getY(); + float menuR = menuActor.getRight(); + float menuT = menuActor.getTop(); + float menuOriginX = menuActor.getOriginX(); //menu button bounds if (c.x>=menuX&&c.x<=menuR&&c.y>=menuY&&c.y<=menuT) { - menu(); - stageToScreenCoordinates(c2.set(menuOriginX, menuY)); - return super.touchDown((int)c2.x, (int)c2.y, pointer, button); + if (pointer < 1) + menuPressed = true; + return true; } - float statsX = ui.findActor("statistic").getX(); - float statsY = ui.findActor("statistic").getY(); - float statsR = ui.findActor("statistic").getRight(); - float statsT = ui.findActor("statistic").getTop(); - float statsOriginX = ui.findActor("statistic").getOriginX(); + float statsX = statsActor.getX(); + float statsY = statsActor.getY(); + float statsR = statsActor.getRight(); + float statsT = statsActor.getTop(); + float statsOriginX = statsActor.getOriginX(); //stats button bounds if (c.x>=statsX&&c.x<=statsR&&c.y>=statsY&&c.y<=statsT) { - statistic(); - stageToScreenCoordinates(c2.set(statsOriginX, statsY)); - return super.touchDown((int)c2.x, (int)c2.y, pointer, button); + if (pointer < 1) + statsPressed = true; + return true; } float uiX = ui.findActor("gamehud").getX(); @@ -264,6 +280,28 @@ public class GameHUD extends Stage { } return super.touchDown(screenX, screenY, pointer, button); } + void checkButtonState(Actor actor, int pointer) { + Array listeners = actor.getListeners(); + for(int i=0;i listeners = actor.getListeners(); + for(int i=0;i