From ab622322b9ba647aa810e182c7fc2c1c0f877e89 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Sun, 22 May 2022 20:58:07 +0800 Subject: [PATCH] added chaos battle on adventure - mimic (Doppelganger) will use random quest challenge decks on chaos mode. winning the challenge grants 1 life, random amount of gold, 2 rares, 2 uncommons and 3 common cards. --- .../forge/game/player/RegisteredPlayer.java | 9 ++- .../adventure/character/EnemySprite.java | 59 ++++++++++++++++--- .../src/forge/adventure/scene/DuelScene.java | 50 +++++++++++++--- .../src/forge/adventure/stage/MapStage.java | 28 ++++----- .../src/forge/adventure/stage/WorldStage.java | 22 +++---- .../src/main/java/forge/deck/DeckProxy.java | 12 ++++ .../src/main/java/forge/deck/DeckgenUtil.java | 2 +- 7 files changed, 135 insertions(+), 47 deletions(-) diff --git a/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java b/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java index 08ff4bca196..805c7973e49 100644 --- a/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java +++ b/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java @@ -5,6 +5,7 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.LobbyPlayer; @@ -26,6 +27,7 @@ public class RegisteredPlayer { private int startingLife = 20; private int startingHand = 7; private Iterable cardsOnBattlefield = null; + private Iterable extraCardsOnBattlefield = null; private Iterable schemes = null; private Iterable planes = null; private Iterable conspiracies = null; @@ -48,7 +50,8 @@ public class RegisteredPlayer { return startingLife; } public final Iterable getCardsOnBattlefield() { - return cardsOnBattlefield == null ? EmptyList : cardsOnBattlefield; + return Iterables.concat(cardsOnBattlefield == null ? EmptyList : cardsOnBattlefield, + extraCardsOnBattlefield == null ? EmptyList : extraCardsOnBattlefield); } public final void setStartingLife(int startingLife) { @@ -59,6 +62,10 @@ public class RegisteredPlayer { this.cardsOnBattlefield = cardsOnTable; } + public final void addExtraCardsOnBattlefield(Iterable extraCardsonTable) { + this.extraCardsOnBattlefield = extraCardsonTable; + } + public int getStartingHand() { return startingHand; } diff --git a/forge-gui-mobile/src/forge/adventure/character/EnemySprite.java b/forge-gui-mobile/src/forge/adventure/character/EnemySprite.java index b0e8aed9e76..1a873fe741e 100644 --- a/forge-gui-mobile/src/forge/adventure/character/EnemySprite.java +++ b/forge-gui-mobile/src/forge/adventure/character/EnemySprite.java @@ -12,9 +12,17 @@ import forge.Forge; import forge.adventure.data.EffectData; import forge.adventure.data.EnemyData; import forge.adventure.data.RewardData; +import forge.adventure.player.AdventurePlayer; import forge.adventure.util.Current; import forge.adventure.util.MapDialog; import forge.adventure.util.Reward; +import forge.card.CardRarity; +import forge.item.PaperCard; +import forge.util.Aggregates; +import forge.util.MyRandom; + +import java.util.List; +import java.util.stream.Collectors; /** * EnemySprite @@ -55,14 +63,51 @@ public class EnemySprite extends CharacterSprite { public Array getRewards() { Array ret=new Array<>(); - if(data.rewards != null) { //Collect standard rewards. - for (RewardData rdata : data.rewards) { - ret.addAll(rdata.generate(false, (Current.latestDeck() != null ? Current.latestDeck().getMain().toFlatList() : null))); + //Collect custom rewards for chaos battles + if (data.copyPlayerDeck && AdventurePlayer.current().isFantasyMode()) { + if (Current.latestDeck() != null) { + List paperCardList = Current.latestDeck().getMain().toFlatList().stream() + .filter(paperCard -> !paperCard.isVeryBasicLand() && !paperCard.getName().startsWith("Mox")) + .collect(Collectors.toList()); + //random uncommons from deck + List uncommonCards = paperCardList.stream() + .filter(paperCard -> CardRarity.Uncommon.equals(paperCard.getRarity()) || CardRarity.Special.equals(paperCard.getRarity())) + .collect(Collectors.toList()); + if (!uncommonCards.isEmpty()) { + ret.add(new Reward(Aggregates.random(uncommonCards))); + ret.add(new Reward(Aggregates.random(uncommonCards))); + } + //random commons from deck + List commmonCards = paperCardList.stream() + .filter(paperCard -> CardRarity.Common.equals(paperCard.getRarity())) + .collect(Collectors.toList()); + if (!commmonCards.isEmpty()) { + ret.add(new Reward(Aggregates.random(commmonCards))); + ret.add(new Reward(Aggregates.random(commmonCards))); + ret.add(new Reward(Aggregates.random(commmonCards))); + } + //random rare from deck + List rareCards = paperCardList.stream() + .filter(paperCard -> CardRarity.Rare.equals(paperCard.getRarity()) || CardRarity.MythicRare.equals(paperCard.getRarity())) + .collect(Collectors.toList()); + if (!rareCards.isEmpty()) { + ret.add(new Reward(Aggregates.random(rareCards))); + ret.add(new Reward(Aggregates.random(rareCards))); + } } - } - if(rewards != null) { //Collect additional rewards. - for(RewardData rdata:rewards) { - ret.addAll(rdata.generate(false,(Current.latestDeck()!=null? Current.latestDeck().getMain().toFlatList():null))); + int val = ((MyRandom.getRandom().nextInt(2)+1)*100)+(MyRandom.getRandom().nextInt(101)); + ret.add(new Reward(val)); + ret.add(new Reward(Reward.Type.Life, 1)); + } else { + if(data.rewards != null) { //Collect standard rewards. + for (RewardData rdata : data.rewards) { + ret.addAll(rdata.generate(false, (Current.latestDeck() != null ? Current.latestDeck().getMain().toFlatList() : null))); + } + } + if(rewards != null) { //Collect additional rewards. + for(RewardData rdata:rewards) { + ret.addAll(rdata.generate(false,(Current.latestDeck()!=null? Current.latestDeck().getMain().toFlatList():null))); + } } } return ret; diff --git a/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java b/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java index 92bb004a26d..3da65271f0a 100644 --- a/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java +++ b/forge-gui-mobile/src/forge/adventure/scene/DuelScene.java @@ -13,11 +13,13 @@ import forge.adventure.util.Config; import forge.adventure.util.Current; import forge.assets.FSkin; import forge.deck.Deck; +import forge.deck.DeckProxy; import forge.game.GameRules; import forge.game.GameType; import forge.game.player.Player; import forge.game.player.RegisteredPlayer; import forge.gamemodes.match.HostedMatch; +import forge.gamemodes.quest.QuestUtil; import forge.gui.interfaces.IGuiGame; import forge.item.IPaperCard; import forge.player.GamePlayerUtil; @@ -27,6 +29,8 @@ import forge.screens.match.MatchController; import forge.sound.MusicPlaylist; import forge.sound.SoundSystem; import forge.trackable.TrackableCollection; +import forge.util.Aggregates; +import org.apache.commons.lang3.tuple.Pair; import java.util.*; @@ -42,6 +46,11 @@ public class DuelScene extends ForgeScene { PlayerSprite player; RegisteredPlayer humanPlayer; private EffectData dungeonEffect; + Deck playerDeck, enemyDeck; + boolean chaosBattle = false; + List playerExtras = new ArrayList<>(); + List AIExtras = new ArrayList<>(); + public DuelScene() { @@ -101,7 +110,6 @@ public class DuelScene extends ForgeScene { AdventurePlayer advPlayer = Current.player(); List players = new ArrayList<>(); - Deck playerDeck=(Deck)AdventurePlayer.current().getSelectedDeck().copyTo("PlayerDeckCopy"); int missingCards= Config.instance().getConfigData().minDeckSize-playerDeck.getMain().countAll(); if( missingCards > 0 ) //Replace unknown cards for a Wastes. playerDeck.getMain().add("Wastes",missingCards); @@ -111,7 +119,6 @@ public class DuelScene extends ForgeScene { playerObject.setAvatarIndex(90001); humanPlayer.setPlayer(playerObject); humanPlayer.setStartingLife(advPlayer.getLife()); - Deck enemyDeck = ( enemy.getData().copyPlayerDeck ? playerDeck : enemy.getData().generateDeck(Current.player().isFantasyMode())); 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)); @@ -162,6 +169,12 @@ 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); + } + players.add(humanPlayer); players.add(aiPlayer); @@ -204,12 +217,33 @@ public class DuelScene extends ForgeScene { return MatchController.getView(); } - public void setEnemy(EnemySprite data) { - this.enemy = data; - } - - public void setPlayer(PlayerSprite sprite) { - this.player = sprite; + public void initDuels(PlayerSprite playerSprite, EnemySprite enemySprite) { + this.player = playerSprite; + 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()); + } } private String selectAI(String ai) { //Decide opponent AI. diff --git a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java index 23c007addad..3425e728d67 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/MapStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/MapStage.java @@ -32,6 +32,7 @@ import forge.adventure.scene.RewardScene; import forge.adventure.scene.SceneType; import forge.adventure.util.*; import forge.adventure.world.WorldSave; +import forge.gui.FThreads; import forge.screens.TransitionScreen; import forge.sound.SoundEffectType; import forge.sound.SoundSystem; @@ -574,23 +575,18 @@ public class MapStage extends GameStage { Gdx.input.vibrate(50); Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); SoundSystem.instance.play(SoundEffectType.ManaBurn, false); - if (!isLoadingMatch) { - isLoadingMatch = true; - Forge.setTransitionScreen(new TransitionScreen(new Runnable() { - @Override - public void run() { + FThreads.invokeInEdtNowOrLater(() -> { + if (!isLoadingMatch) { + isLoadingMatch = true; + Forge.setTransitionScreen(new TransitionScreen(() -> { + DuelScene duelScene = ((DuelScene) SceneType.DuelScene.instance); + duelScene.initDuels(player, mob); Forge.clearTransitionScreen(); - } - }, ScreenUtils.getFrameBufferTexture(), true, false)); - } - startPause(0.3f, new Runnable() { - @Override - public void run() { - DuelScene S = ((DuelScene) SceneType.DuelScene.instance); - S.setEnemy(mob); - S.setPlayer(player); - if(isInMap && effect != null) S.setDungeonEffect(effect); - Forge.switchScene(SceneType.DuelScene.instance); + startPause(0.3f, () -> { + if(isInMap && effect != null) duelScene.setDungeonEffect(effect); + Forge.switchScene(SceneType.DuelScene.instance); + }); + }, ScreenUtils.getFrameBufferTexture(), true, false)); } }); } diff --git a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java index 1a7e41c8274..73b2b1a9dad 100644 --- a/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java +++ b/forge-gui-mobile/src/forge/adventure/stage/WorldStage.java @@ -22,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.gui.FThreads; import forge.screens.TransitionScreen; import forge.sound.SoundEffectType; import forge.sound.SoundSystem; @@ -86,22 +87,15 @@ public class WorldStage extends GameStage implements SaveFileContent { Gdx.input.vibrate(50); Forge.setCursor(null, Forge.magnifyToggle ? "1" : "2"); SoundSystem.instance.play(SoundEffectType.ManaBurn, false); - Forge.setTransitionScreen(new TransitionScreen(new Runnable() { - @Override - public void run() { + FThreads.invokeInEdtNowOrLater(() -> { + Forge.setTransitionScreen(new TransitionScreen(() -> { + ((DuelScene) SceneType.DuelScene.instance).initDuels(player, mob); Forge.clearTransitionScreen(); - } - }, ScreenUtils.getFrameBufferTexture(), true, false)); - startPause(0.3f, new Runnable() { - @Override - public void run() { - ((DuelScene) SceneType.DuelScene.instance).setEnemy(currentMob); - ((DuelScene) SceneType.DuelScene.instance).setPlayer(player); - Forge.switchScene(SceneType.DuelScene.instance); - } + startPause(0.3f, () -> Forge.switchScene(SceneType.DuelScene.instance)); + }, ScreenUtils.getFrameBufferTexture(), true, false)); + currentMob = mob; + WorldSave.getCurrentSave().autoSave(); }); - currentMob = mob; - WorldSave.getCurrentSave().autoSave(); break; } } diff --git a/forge-gui/src/main/java/forge/deck/DeckProxy.java b/forge-gui/src/main/java/forge/deck/DeckProxy.java index ce464a15591..0b7e30a18a0 100644 --- a/forge-gui/src/main/java/forge/deck/DeckProxy.java +++ b/forge-gui/src/main/java/forge/deck/DeckProxy.java @@ -23,6 +23,8 @@ import forge.util.BinaryUtil; import forge.util.IHasName; import forge.util.storage.IStorage; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import java.util.*; import java.util.Map.Entry; @@ -563,6 +565,16 @@ public class DeckProxy implements InventoryItem { return decks; } + public static Map, List>> getAllQuestChallenges() { + final Map, List>> deckMap = new HashMap<>(); + final QuestController quest = FModel.getQuest(); + for (final QuestEvent e : quest.getChallenges()) { + Pair, List> extras = new ImmutablePair<>(e.getHumanExtraCards(), e.getAiExtraCards()); + deckMap.put(new DeckProxy(e.getEventDeck(), "Quest Event", null, null), extras); + } + return deckMap; + } + public static List getNonEasyQuestDuelDecks() { final List decks = new ArrayList<>(); final QuestController quest = FModel.getQuest(); diff --git a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java index 6e9fb625b6c..1954e470bbc 100644 --- a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java +++ b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java @@ -441,7 +441,7 @@ public class DeckgenUtil { advPrecons.addAll(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons())); } if (advThemes.isEmpty()) { - advThemes.addAll(DeckProxy.getAllThemeDecks()); + advThemes.addAll(DeckProxy.getAllPreconstructedDecks(QuestController.getPrecons())); advThemes.addAll(DeckProxy.getNonEasyQuestDuelDecks()); } if (!colors.isEmpty()) {