diff --git a/forge-gui-mobile/src/forge/adventure/character/CharacterSprite.java b/forge-gui-mobile/src/forge/adventure/character/CharacterSprite.java index 8197085fffd..d4b988ca42b 100644 --- a/forge-gui-mobile/src/forge/adventure/character/CharacterSprite.java +++ b/forge-gui-mobile/src/forge/adventure/character/CharacterSprite.java @@ -19,7 +19,7 @@ public class CharacterSprite extends MapActor { private Animation currentAnimation = null; private AnimationTypes currentAnimationType = AnimationTypes.Idle; private AnimationDirections currentAnimationDir = AnimationDirections.None; - private Sprite avatar; + private Array avatar=new Array<>(); public boolean hidden = false; public CharacterSprite(int id,String path) { @@ -45,7 +45,7 @@ public class CharacterSprite extends MapActor { animations.clear(); for (AnimationTypes stand : AnimationTypes.values()) { if (stand == AnimationTypes.Avatar) { - avatar = atlas.createSprite(stand.toString()); + avatar.addAll(atlas.createSprites(stand.toString())); continue; } HashMap> dirs = new HashMap<>(); @@ -227,7 +227,10 @@ public class CharacterSprite extends MapActor { } public Sprite getAvatar() { - return avatar; + return avatar.first(); + } + public Sprite getAvatar(int index) { + return avatar.get(index); } public enum AnimationTypes { diff --git a/forge-gui-mobile/src/forge/adventure/data/EnemyData.java b/forge-gui-mobile/src/forge/adventure/data/EnemyData.java index b7321491e94..b4cb9db9622 100644 --- a/forge-gui-mobile/src/forge/adventure/data/EnemyData.java +++ b/forge-gui-mobile/src/forge/adventure/data/EnemyData.java @@ -24,6 +24,9 @@ public class EnemyData { public String[] equipment; public String colors = ""; + public EnemyData nextEnemy; + public int teamNumber=-1; + public EnemyData() { } public EnemyData(EnemyData enemyData) { name = enemyData.name; diff --git a/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java b/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java index 20dcc49108e..3535f7451d1 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java @@ -9,6 +9,7 @@ import forge.LobbyPlayer; import forge.adventure.character.EnemySprite; import forge.adventure.character.PlayerSprite; import forge.adventure.data.EffectData; +import forge.adventure.data.EnemyData; import forge.adventure.data.ItemData; import forge.adventure.player.AdventurePlayer; import forge.adventure.util.Config; @@ -51,7 +52,7 @@ public class DuelScene extends ForgeScene { PlayerSprite player; RegisteredPlayer humanPlayer; private EffectData dungeonEffect; - Deck playerDeck, enemyDeck; + Deck playerDeck; boolean chaosBattle = false; boolean callbackExit = false; List playerExtras = new ArrayList<>(); @@ -134,7 +135,7 @@ public class DuelScene extends ForgeScene { changeStartCards+= data.changeStartCards; startCards.addAll(data.startBattleWithCards()); } - player.setCardsOnBattlefield(startCards); + player.addExtraCardsOnBattlefield(startCards); player.setStartingLife(Math.max(1,lifeMod+player.getStartingLife())); player.setStartingHand(player.getStartingHand()+changeStartCards); } @@ -154,25 +155,41 @@ public class DuelScene extends ForgeScene { int missingCards= Config.instance().getConfigData().minDeckSize-playerDeck.getMain().countAll(); if( missingCards > 0 ) //Replace unknown cards for a Wastes. playerDeck.getMain().add("Wastes",missingCards); - humanPlayer = RegisteredPlayer.forVariants(2, appliedVariants,playerDeck, null, false, null, null); - LobbyPlayer playerObject = GamePlayerUtil.getGuiPlayer(); - FSkin.getAvatars().put(90001, advPlayer.avatar()); - playerObject.setAvatarIndex(90001); - humanPlayer.setPlayer(playerObject); - humanPlayer.setStartingLife(advPlayer.getLife()); - Current.setLatestDeck(enemyDeck); - RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(2, appliedVariants, Current.latestDeck(), null, false, null, null); - LobbyPlayer enemyPlayer = GamePlayerUtil.createAiPlayer(this.enemy.getData().name, selectAI(this.enemy.getData().ai)); - if(!enemy.nameOverride.isEmpty()) enemyPlayer.setName(enemy.nameOverride); //Override name if defined in the map. - FSkin.getAvatars().put(90000, this.enemy.getAvatar()); - enemyPlayer.setAvatarIndex(90000); + int playerCount=1; + EnemyData currentEnemy=enemy.getData(); + for(int i=0;i<8&¤tEnemy!=null;i++) + { + playerCount++; + currentEnemy=currentEnemy.nextEnemy; + } - aiPlayer.setPlayer(enemyPlayer); - aiPlayer.setStartingLife(Math.round((float)enemy.getData().life*advPlayer.getDifficulty().enemyLifeFactor)); + humanPlayer = RegisteredPlayer.forVariants(playerCount, appliedVariants,playerDeck, null, false, null, null); + LobbyPlayer playerObject = GamePlayerUtil.getGuiPlayer(); + FSkin.getAvatars().put(90000, advPlayer.avatar()); + playerObject.setAvatarIndex(90000); + humanPlayer.setPlayer(playerObject); + humanPlayer.setTeamNumber(0); + humanPlayer.setStartingLife(advPlayer.getLife()); Array playerEffects = new Array<>(); Array oppEffects = new Array<>(); + + Map, List>> deckProxyMapMap = null; + DeckProxy deckProxy =null; + if(chaosBattle) + { + deckProxyMapMap = DeckProxy.getAllQuestChallenges(); + List decks = new ArrayList<>(deckProxyMapMap.keySet()); + deckProxy = Aggregates.random(decks); + //playerextras + List playerCards = new ArrayList<>(); + for (String s : deckProxyMapMap.get(deckProxy).getLeft()) { + playerCards.add(QuestUtil.readExtraCard(s)); + } + humanPlayer.addExtraCardsOnBattlefield(playerCards); + } + //Collect and add items effects first. for(String playerItem:advPlayer.getEquippedItems()) { ItemData item=ItemData.getItem(playerItem); @@ -183,13 +200,6 @@ public class DuelScene extends ForgeScene { System.err.printf("Item %s not found.", playerItem); } } - if(enemy.getData().equipment!=null) { - for(String oppItem:enemy.getData().equipment) { - ItemData item=ItemData.getItem(oppItem); - oppEffects.add(item.effect); - if(item.effect.opponent !=null) playerEffects.add(item.effect.opponent); - } - } //Collect and add player blessings. if(advPlayer.getBlessing() != null){ @@ -212,16 +222,62 @@ public class DuelScene extends ForgeScene { } addEffects(humanPlayer,playerEffects); - addEffects(aiPlayer,oppEffects); - //add extra cards for challenger mode - if (chaosBattle) { - humanPlayer.addExtraCardsOnBattlefield(playerExtras); - aiPlayer.addExtraCardsOnBattlefield(AIExtras); + currentEnemy=enemy.getData(); + for(int i=0;i<8&¤tEnemy!=null;i++) + { + Deck deck=null; + + if (this.chaosBattle) { //random challenge for chaos mode + //aiextras + List aiCards = new ArrayList<>(); + for (String s : deckProxyMapMap.get(deck).getRight()) { + aiCards.add(QuestUtil.readExtraCard(s)); + } + this.AIExtras = aiCards; + deck = deckProxy.getDeck(); + } else { + deck=currentEnemy.copyPlayerDeck ? this.playerDeck : currentEnemy.generateDeck(Current.player().isFantasyMode(), Current.player().getDifficulty().name.equalsIgnoreCase("Hard")); + } + RegisteredPlayer aiPlayer = RegisteredPlayer.forVariants(playerCount, appliedVariants, deck, null, false, null, null); + + LobbyPlayer enemyPlayer = GamePlayerUtil.createAiPlayer(currentEnemy.name, selectAI(currentEnemy.ai)); + if(!enemy.nameOverride.isEmpty()) enemyPlayer.setName(enemy.nameOverride); //Override name if defined in the map.(only supported for 1 enemy atm) + FSkin.getAvatars().put(90001+i, enemy.getAvatar(i)); + enemyPlayer.setAvatarIndex(90001+i); + aiPlayer.setPlayer(enemyPlayer); + aiPlayer.setTeamNumber(currentEnemy.teamNumber); + aiPlayer.setStartingLife(Math.round((float)currentEnemy.life*advPlayer.getDifficulty().enemyLifeFactor)); + + Array equipmentEffects = new Array<>(); + if(currentEnemy.equipment!=null) { + for(String oppItem:currentEnemy.equipment) { + ItemData item=ItemData.getItem(oppItem); + equipmentEffects.add(item.effect); + if(item.effect.opponent !=null) playerEffects.add(item.effect.opponent); + } + } + addEffects(aiPlayer,oppEffects); + addEffects(aiPlayer,equipmentEffects); + + + //add extra cards for challenger mode + if (chaosBattle) { + aiPlayer.addExtraCardsOnBattlefield(AIExtras); + } + + players.add(aiPlayer); + + + + Current.setLatestDeck(deck); + + currentEnemy=currentEnemy.nextEnemy; } + + players.add(humanPlayer); - players.add(aiPlayer); final Map guiMap = new HashMap<>(); guiMap.put(humanPlayer, MatchController.instance); @@ -253,7 +309,7 @@ public class DuelScene extends ForgeScene { "It's all or nothing!","It's all on the line!","You can't back down now!","Do you have what it takes?","What will happen next?", "Don't blink!","You can't lose here!","There's no turning back!","It's all or nothing now!"); String message = Aggregates.random(list); - FThreads.delayInEDT(600, () -> FThreads.invokeInEdtNowOrLater(() -> FOptionPane.showMessageDialog(message, aiPlayer.getPlayer().getName(), new FBufferedImage(120, 120) { + FThreads.delayInEDT(600, () -> FThreads.invokeInEdtNowOrLater(() -> FOptionPane.showMessageDialog(message, enemy.getName(), new FBufferedImage(120, 120) { @Override protected void draw(Graphics g, float w, float h) { if (FSkin.getAvatars().get(90000) != null) @@ -285,34 +341,11 @@ public class DuelScene extends ForgeScene { this.enemy = enemySprite; this.playerDeck = (Deck)AdventurePlayer.current().getSelectedDeck().copyTo("PlayerDeckCopy"); this.chaosBattle = this.enemy.getData().copyPlayerDeck && Current.player().isFantasyMode(); - if (this.chaosBattle) { //random challenge for chaos mode - Map, List>> deckProxyMapMap = DeckProxy.getAllQuestChallenges(); - List decks = new ArrayList<>(deckProxyMapMap.keySet()); - DeckProxy deck = Aggregates.random(decks); - //playerextras - List playerCards = new ArrayList<>(); - for (String s : deckProxyMapMap.get(deck).getLeft()) { - playerCards.add(QuestUtil.readExtraCard(s)); - } - this.playerExtras = playerCards; - //aiextras - List aiCards = new ArrayList<>(); - for (String s : deckProxyMapMap.get(deck).getRight()) { - aiCards.add(QuestUtil.readExtraCard(s)); - } - this.AIExtras = aiCards; - this.enemyDeck = deck.getDeck(); - } else { - this.AIExtras.clear(); - this.playerExtras.clear(); - this.enemyDeck = this.enemy.getData().copyPlayerDeck ? this.playerDeck : this.enemy.getData().generateDeck(Current.player().isFantasyMode(), Current.player().getDifficulty().name.equalsIgnoreCase("Hard")); - } - } - public Deck getPlayerDeck() { - return this.playerDeck; - } - public Deck getEnemyDeck() { - return this.enemyDeck; + + + this.AIExtras.clear(); + this.playerExtras.clear(); + } private String selectAI(String ai) { //Decide opponent AI. diff --git a/forge-gui-mobile/src/forge/adventure/stage/ConsoleCommandInterpreter.java b/forge-gui-mobile/src/forge/adventure/stage/ConsoleCommandInterpreter.java index 245dfec284c..35e9463de0e 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/ConsoleCommandInterpreter.java +++ b/forge-gui-mobile/src/forge/adventure/stage/ConsoleCommandInterpreter.java @@ -117,6 +117,13 @@ public class ConsoleCommandInterpreter { WorldStage.getInstance().GetPlayer().setPosition(poi.getPosition()); return "Teleported to " + s[0] + "(" + poi.getPosition() + ")"; }); + registerCommand(new String[]{"spawn","enemy"}, s -> { + if(s.length<1) return "Command needs 1 parameter: enemy name."; + + if(WorldStage.getInstance().spawn(s[0])) + return "Spawn " + s[0]; + return "Can not find enemy "+s[0]; + }); registerCommand(new String[]{"give", "gold"}, s -> { if(s.length<1) return "Command needs 1 parameter: Amount."; int amount; diff --git a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java index 6c07f0c094b..7f09143041a 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java @@ -202,6 +202,10 @@ public class WorldStage extends GameStage implements SaveFileContent { return WorldSave.getCurrentSave().getWorld().collidingTile(boundingRect); } + public boolean spawn(String enemy) + { + return spawn(WorldData.getEnemy(enemy)); + } private void HandleMonsterSpawn(float delta) { World world = WorldSave.getCurrentSave().getWorld(); @@ -223,8 +227,12 @@ public class WorldStage extends GameStage implements SaveFileContent { if (list == null) return; EnemyData enemyData = data.getEnemy( 1.0f ); + spawn(enemyData); + } + + private boolean spawn(EnemyData enemyData) { if (enemyData == null) - return; + return false; EnemySprite sprite = new EnemySprite(enemyData); float unit = Scene.getIntendedHeight() / 6f; Vector2 spawnPos = new Vector2(1, 1); @@ -242,11 +250,12 @@ public class WorldStage extends GameStage implements SaveFileContent { { enemies.add(Pair.of(globalTimer,sprite)); foregroundSprites.addActor(sprite); - return; + return true; } int g=0; } } + return false; } @Override diff --git a/forge-gui/res/adventure/Shandalar/sprites/goblin_group.atlas b/forge-gui/res/adventure/Shandalar/sprites/goblin_group.atlas new file mode 100644 index 00000000000..38564aede93 --- /dev/null +++ b/forge-gui/res/adventure/Shandalar/sprites/goblin_group.atlas @@ -0,0 +1,75 @@ + +goblin_group.png +size: 64,96 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +Avatar + xy: 0, 0 + size: 16, 16 +Avatar + xy: 16, 0 + size: 16, 16 +Avatar + xy: 32, 0 + size: 16, 16 +Idle + xy: 0, 16 + size: 32, 16 +Idle + xy: 32, 16 + size: 32, 16 +Idle + xy: 64, 16 + size: 32, 16 +Idle + xy: 96, 16 + size: 32, 16 +Walk + xy: 0, 32 + size: 32, 16 +Walk + xy: 32, 32 + size: 32, 16 +Walk + xy: 64, 32 + size: 32, 16 +Walk + xy: 96, 32 + size: 32, 16 +Attack + xy: 0, 48 + size: 32, 16 +Attack + xy: 32, 48 + size: 32, 16 +Attack + xy: 64, 48 + size: 32, 16 +Attack + xy: 96, 48 + size: 32, 16 +Hit + xy: 0, 64 + size: 32, 16 +Hit + xy: 32, 64 + size: 32, 16 +Hit + xy: 64, 64 + size: 32, 16 +Hit + xy: 96, 64 + size: 32, 16 +Death + xy: 0, 80 + size: 32, 16 +Death + xy: 32, 80 + size: 32, 16 +Death + xy: 64, 80 + size: 32, 16 +Death + xy: 96, 80 + size: 32, 16 \ No newline at end of file diff --git a/forge-gui/res/adventure/Shandalar/sprites/goblin_group.png b/forge-gui/res/adventure/Shandalar/sprites/goblin_group.png new file mode 100644 index 00000000000..548c62dfaac Binary files /dev/null and b/forge-gui/res/adventure/Shandalar/sprites/goblin_group.png differ diff --git a/forge-gui/res/adventure/Shandalar/world/enemies.json b/forge-gui/res/adventure/Shandalar/world/enemies.json index ca225ead54a..4dbbbef3314 100644 --- a/forge-gui/res/adventure/Shandalar/world/enemies.json +++ b/forge-gui/res/adventure/Shandalar/world/enemies.json @@ -3547,5 +3547,56 @@ "Black Lotus" ], "colors": "BGRUW" +}, +{ + "name": "Goblin pack", + "sprite": "sprites/goblin_group.atlas", + "deck": "decks/goblin_bad.json", + "ai": "", + "teamNumber" :1, + "spawnRate": 1, + "difficulty": 0.1, + "speed": 27, + "life": 8, + "rewards": [ + { + "type": "deckCard", + "probability": 1, + "count": 2, + "addMaxCount": 4 + }, + { + "type": "gold", + "probability": 0.7, + "count": 10, + "addMaxCount": 90 + }, + { + "type": "card", + "probability": 0.5, + "count": 3, + "colors": [ + "Red" + ], + "rarity": [ + "Rare" + ] + } + ], + "colors": "R", + "nextEnemy": { + "name": "Goblin", + "teamNumber" :1, + "deck": "decks/goblin_bad.json", + "ai": "", + "life": 8, + "nextEnemy": { + "name": "Goblin", + "teamNumber" :1, + "deck": "decks/goblin_bad.json", + "ai": "", + "life": 8 + } + } } ] \ No newline at end of file