From 695b446c604a1251b022d98aa2f7d3dc4e9c3965 Mon Sep 17 00:00:00 2001 From: Sol Date: Wed, 22 May 2013 03:12:54 +0000 Subject: [PATCH] - Added the capability to play Challenges vs predetermined decks (along with a few other related options to disallow specific quest mode things) - Added Sorin vs Tibalt, and Tibalt vs Sorin as examples of Challenges that force you to use a specific Deck. (They seemed to be the best duel deck compatibility for the AI). --- .gitattributes | 2 + res/quest/challenges/Sorin vs Tibalt.dck | 56 ++++++++++++++++ res/quest/challenges/Tibalt vs Sorin.dck | 56 ++++++++++++++++ src/main/java/forge/game/GameNew.java | 5 +- src/main/java/forge/game/MatchController.java | 9 ++- .../gui/home/quest/SSubmenuQuestUtil.java | 38 ++++++++--- .../java/forge/quest/QuestEventChallenge.java | 66 +++++++++++++++++++ .../forge/quest/io/QuestChallengeReader.java | 18 +++++ 8 files changed, 239 insertions(+), 11 deletions(-) create mode 100644 res/quest/challenges/Sorin vs Tibalt.dck create mode 100644 res/quest/challenges/Tibalt vs Sorin.dck diff --git a/.gitattributes b/.gitattributes index b1384ff6bd9..5a4d978992e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -12816,12 +12816,14 @@ res/quest/challenges/Private[!!-~]Domain.dck -text res/quest/challenges/Quest[!!-~]for[!!-~]Ula's[!!-~]Temple.dck -text res/quest/challenges/Reactor[!!-~]Meltdown.dck -text res/quest/challenges/Repressed[!!-~]Magic.dck -text +res/quest/challenges/Sorin[!!-~]vs[!!-~]Tibalt.dck -text res/quest/challenges/The[!!-~]Backlash[!!-~]Machine.dck -text res/quest/challenges/The[!!-~]Court[!!-~]Jester.dck -text res/quest/challenges/The[!!-~]Desert[!!-~]Caravan.dck -text res/quest/challenges/The[!!-~]King's[!!-~]Contest.dck -text res/quest/challenges/The[!!-~]Pied[!!-~]Piper.dck -text res/quest/challenges/The[!!-~]Torpor[!!-~]Orb.dck -text +res/quest/challenges/Tibalt[!!-~]vs[!!-~]Sorin.dck -text res/quest/challenges/Zombie[!!-~]Attack!.dck -text res/quest/duels/Abraham[!!-~]Lincoln[!!-~]3.dck -text res/quest/duels/Air-Walker[!!-~]2.dck -text diff --git a/res/quest/challenges/Sorin vs Tibalt.dck b/res/quest/challenges/Sorin vs Tibalt.dck new file mode 100644 index 00000000000..e9250b9f620 --- /dev/null +++ b/res/quest/challenges/Sorin vs Tibalt.dck @@ -0,0 +1,56 @@ +[quest] +id=29 +AILife=20 +HumanLife=20 +HumanDeck=Tibalt vs Sorin.dck +UseBazaar=False +ForceAnte=False +Repeat=false +Wins=20 +Card Reward=2 random rares +Credit Reward=200 +[metadata] +Name=quest29 +Title=Tibalt (vs Sorin) +Difficulty=hard +Description=Play as Sorin vs Tibalt the Pain Mage. NOTE: This challenge uses a preselected deck and ignores specific Bazaar settings. +Icon=Tibalt.jpg +Deck Type=constructed +[main] +14 Mountain +6 Swamp +2 Ashmouth Hound +1 Coal Stoker +1 Corpse Connoisseur +1 Gang of Devils +1 Goblin Arsonist +1 Hellrider +2 Hellspark Elemental +1 Lavaborn Muse +1 Mad Prophet +1 Reassembling Skeleton +1 Scorched Rusalka +1 Scourge Devil +1 Shambling Remains +1 Skirsdag Cultist +2 Vithian Stinger +1 Sulfuric Vortex +1 Blazing Salvo +1 Flame Javelin +1 Geistflame +1 Strangling Soot +1 Terminate +2 Akoum Refuge +2 Rakdos Carnarium +1 Tibalt, the Fiend-Blooded +1 Blightning +1 Breaking Point +2 Browbeat +1 Bump in the Night +1 Devil's Play +1 Faithless Looting +1 Flame Slash +1 Pyroclasm +1 Recoup +1 Torrent of Souls +[sideboard] diff --git a/res/quest/challenges/Tibalt vs Sorin.dck b/res/quest/challenges/Tibalt vs Sorin.dck new file mode 100644 index 00000000000..1fc3cd8f790 --- /dev/null +++ b/res/quest/challenges/Tibalt vs Sorin.dck @@ -0,0 +1,56 @@ +[quest] +id=28 +AILife=20 +HumanLife=20 +HumanDeck=Sorin vs Tibalt.dck +UseBazaar=False +ForceAnte=False +Repeat=false +Wins=20 +Card Reward=2 random rares +Credit Reward=200 +[metadata] +Name=quest28 +Title=Sorin (vs Tibalt) +Difficulty=medium +Description=Play as Tibalt vs Sorin, Lord of Innistrad. NOTE: This challenge uses a preselected deck and ignores specific Bazaar settings. +Icon=Sorin.jpg +Deck Type=constructed +[main] +9 Plains +12 Swamp +1 Bloodrage Vampire +1 Butcher of Malakir +1 Child of Night +2 Doomed Traveler +2 Duskhunter Bat +1 Fiend Hunter +1 Gatekeeper of Malakir +1 Mausoleum Guard +1 Mesmeric Fiend +1 Phantom General +1 Revenant Patriarch +1 Sengir Vampire +1 Twilight Drover +1 Vampire Lacerator +1 Vampire Nighthawk +1 Vampire Outcasts +1 Wall of Omens +1 Field of Souls +1 Mark of the Vampire +1 Mortify +1 Sorin's Thirst +1 Unmake +1 Urge to Feed +1 Vampire's Bite +1 Zealous Persecution +2 Evolving Wilds +2 Tainted Field +1 Sorin, Lord of Innistrad +1 Absorb Vis +1 Ancient Craving +1 Death Grasp +1 Decompose +1 Lingering Souls +2 Spectral Procession +[sideboard] diff --git a/src/main/java/forge/game/GameNew.java b/src/main/java/forge/game/GameNew.java index d615256d471..9ac6d45bf46 100644 --- a/src/main/java/forge/game/GameNew.java +++ b/src/main/java/forge/game/GameNew.java @@ -215,8 +215,9 @@ public class GameNew { * * TODO: Accept something like match state as parameter. Match should be aware of players, * their decks and other special starting conditions. + * @param forceAnte Forces ante on or off no matter what your preferences */ - public static void newGame(final GameState game, final boolean canRandomFoil) { + public static void newGame(final GameState game, final boolean canRandomFoil, Boolean forceAnte) { Card.resetUniqueNumber(); // need this code here, otherwise observables fail @@ -225,7 +226,7 @@ public class GameNew { trigHandler.clearDelayedTrigger(); // friendliness - boolean useAnte = preferences.getPrefBoolean(FPref.UI_ANTE); + boolean useAnte = forceAnte != null ? forceAnte : preferences.getPrefBoolean(FPref.UI_ANTE); final Set rAICards = new HashSet(); Map> removedAnteCards = new HashMap>(); diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index d44622fc2b5..ebad6c7d366 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -50,6 +50,8 @@ public class MatchController { private int gamesPerMatch = 3; private int gamesToWinMatch = 2; + + private Boolean forceAnte = false; private GameState currentGame = null; @@ -66,6 +68,11 @@ public class MatchController { players.putAll(map); gameType = type; } + + public MatchController(GameType type, Map map, Boolean forceAnte) { + this(type, map); + this.forceAnte = forceAnte; + } /** * Gets the games played. @@ -145,7 +152,7 @@ public class MatchController { attachUiToMatch(this, FControl.SINGLETON_INSTANCE.getLobby().getGuiPlayer()); final boolean canRandomFoil = Singletons.getModel().getPreferences().getPrefBoolean(FPref.UI_RANDOM_FOIL) && gameType == GameType.Constructed; - GameNew.newGame(currentGame, canRandomFoil); + GameNew.newGame(currentGame, canRandomFoil, this.forceAnte); currentGame.setAge(GameAge.Mulligan); } catch (Exception e) { diff --git a/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java b/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java index a55de271d4f..d0e75cde073 100644 --- a/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java +++ b/src/main/java/forge/gui/home/quest/SSubmenuQuestUtil.java @@ -353,7 +353,15 @@ public class SSubmenuQuestUtil { } final QuestController qData = Singletons.getModel().getQuest(); - Deck deck = SSubmenuQuestUtil.getCurrentDeck(); + Deck deck = null; + if (event instanceof QuestEventChallenge) { + // Predefined HumanDeck + deck = ((QuestEventChallenge) event).getHumanDeck(); + } + if (deck == null) { + // If no predefined Deck, use the Player's Deck + deck = SSubmenuQuestUtil.getCurrentDeck(); + } if (deck == null) { String msg = "Please select a Quest Deck."; JOptionPane.showMessageDialog(null, msg, "No Deck", JOptionPane.ERROR_MESSAGE); @@ -393,23 +401,37 @@ public class SSubmenuQuestUtil { worker.execute(); int extraLifeHuman = 0; + Integer lifeHuman = null; + boolean useBazaar = true; + Boolean forceAnte = false; int lifeAI = 20; if (event instanceof QuestEventChallenge) { lifeAI = ((QuestEventChallenge) event).getAILife(); + lifeHuman = ((QuestEventChallenge) event).getHumanLife(); if (qData.getAssets().hasItem(QuestItemType.ZEPPELIN)) { extraLifeHuman = 3; } + + useBazaar = ((QuestEventChallenge) event).isUseBazaar(); + forceAnte = ((QuestEventChallenge) event).isForceAnte(); } - PlayerStartConditions humanStart = new PlayerStartConditions(SSubmenuQuestUtil.getCurrentDeck()); - humanStart.setStartingLife(qData.getAssets().getLife(qData.getMode()) + extraLifeHuman); - humanStart.setCardsOnBattlefield(QuestUtil.getHumanStartingCards(qData, event)); - + PlayerStartConditions humanStart = new PlayerStartConditions(deck); PlayerStartConditions aiStart = new PlayerStartConditions(event.getEventDeck()); - aiStart.setStartingLife(lifeAI); - aiStart.setCardsOnBattlefield(QuestUtil.getComputerStartingCards(event)); + if (lifeHuman != null) { + humanStart.setStartingLife(lifeHuman); + } else { + humanStart.setStartingLife(qData.getAssets().getLife(qData.getMode()) + extraLifeHuman); + } + + if (useBazaar) { + humanStart.setCardsOnBattlefield(QuestUtil.getHumanStartingCards(qData, event)); + aiStart.setStartingLife(lifeAI); + aiStart.setCardsOnBattlefield(QuestUtil.getComputerStartingCards(event)); + } + MatchStartHelper msh = new MatchStartHelper(); msh.addPlayer(Singletons.getControl().getLobby().getQuestPlayer(), humanStart); @@ -417,7 +439,7 @@ public class SSubmenuQuestUtil { aiPlayer.setIconImageKey(event.getIconImageKey()); msh.addPlayer(aiPlayer, aiStart); - final MatchController mc = new MatchController(GameType.Quest, msh.getPlayerMap()); + final MatchController mc = new MatchController(GameType.Quest, msh.getPlayerMap(), forceAnte); FThreads.invokeInEdtLater(new Runnable(){ @Override public void run() { diff --git a/src/main/java/forge/quest/QuestEventChallenge.java b/src/main/java/forge/quest/QuestEventChallenge.java index ed96c7802b0..2b0318bc273 100644 --- a/src/main/java/forge/quest/QuestEventChallenge.java +++ b/src/main/java/forge/quest/QuestEventChallenge.java @@ -22,6 +22,8 @@ import java.util.List; import com.google.common.base.Function; +import forge.deck.Deck; + /** *

* QuestQuest class. @@ -47,12 +49,18 @@ public class QuestEventChallenge extends QuestEvent { /** The ai life. */ private int aiLife = 25; + private Integer humanLife = null; + /** The credits reward. */ private int creditsReward = 100; /** The repeatable. */ private boolean repeatable = false; + private boolean useBazaar = true; + + private Boolean forceAnte = null; + /** The wins reqd. */ private int winsReqd = 20; @@ -63,6 +71,8 @@ public class QuestEventChallenge extends QuestEvent { /** The ai extra cards. */ private List aiExtraCards = new ArrayList(); + private Deck humanDeck = null; + /** * Instantiates a new quest challenge. */ @@ -248,4 +258,60 @@ public class QuestEventChallenge extends QuestEvent { public void setHumanExtraCards(final List humanExtraCards0) { this.humanExtraCards = humanExtraCards0; } + + /** + * @return the humanLife + */ + public Integer getHumanLife() { + return humanLife; + } + + /** + * @param humanLife the humanLife to set + */ + public void setHumanLife(Integer humanLife) { + this.humanLife = humanLife; + } + + /** + * @return the useBazaar + */ + public boolean isUseBazaar() { + return useBazaar; + } + + /** + * @param useBazaar the useBazaar to set + */ + public void setUseBazaar(boolean useBazaar) { + this.useBazaar = useBazaar; + } + + /** + * @return the forceAnte + */ + public Boolean isForceAnte() { + return forceAnte; + } + + /** + * @param forceAnte the forceAnte to set + */ + public void setForceAnte(Boolean forceAnte) { + this.forceAnte = forceAnte; + } + + /** + * @return the humanDeck + */ + public Deck getHumanDeck() { + return humanDeck; + } + + /** + * @param humanDeck the humanDeck to set + */ + public void setHumanDeck(Deck humanDeck) { + this.humanDeck = humanDeck; + } } diff --git a/src/main/java/forge/quest/io/QuestChallengeReader.java b/src/main/java/forge/quest/io/QuestChallengeReader.java index 99dcfc8e15a..ba5911647ac 100644 --- a/src/main/java/forge/quest/io/QuestChallengeReader.java +++ b/src/main/java/forge/quest/io/QuestChallengeReader.java @@ -9,6 +9,7 @@ import java.util.Map; import forge.ImageCache; import forge.deck.Deck; import forge.deck.io.DeckSerializer; +import forge.properties.NewConstants; import forge.quest.QuestEventChallenge; import forge.quest.QuestEventDifficulty; import forge.util.FileSection; @@ -38,6 +39,23 @@ public class QuestChallengeReader extends StorageReaderFolder