CPreGame.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  1. /*
  2. * CPreGame.h, part of VCMI engine
  3. *
  4. * Authors: listed in file AUTHORS in main folder
  5. *
  6. * License: GNU General Public License v2.0 or later
  7. * Full text of license available in license.txt file, in main folder
  8. *
  9. */
  10. #pragma once
  11. #include "../lib/StartInfo.h"
  12. #include "../lib/FunctionList.h"
  13. #include "../lib/mapping/CMapInfo.h"
  14. #include "../lib/rmg/CMapGenerator.h"
  15. #include "windows/CWindowObject.h"
  16. class CMapInfo;
  17. class CMusicHandler;
  18. class CMapHeader;
  19. class CCampaignHeader;
  20. class CTextInput;
  21. class CCampaign;
  22. class CGStatusBar;
  23. class CTextBox;
  24. class CCampaignState;
  25. class CConnection;
  26. class JsonNode;
  27. class CMapGenOptions;
  28. class CRandomMapTab;
  29. struct CPackForSelectionScreen;
  30. struct PlayerInfo;
  31. class CMultiLineLabel;
  32. class CToggleButton;
  33. class CToggleGroup;
  34. class CTabbedInt;
  35. class IImage;
  36. class CAnimation;
  37. class CAnimImage;
  38. class CButton;
  39. class CLabel;
  40. class CSlider;
  41. namespace boost
  42. {
  43. class thread;
  44. class recursive_mutex;
  45. }
  46. enum ESortBy
  47. {
  48. _playerAm,
  49. _size,
  50. _format,
  51. _name,
  52. _viccon,
  53. _loscon,
  54. _numOfMaps,
  55. _fileName
  56. }; //_numOfMaps is for campaigns
  57. /// Class which handles map sorting by different criteria
  58. class mapSorter
  59. {
  60. public:
  61. ESortBy sortBy;
  62. bool operator()(const CMapInfo * aaa, const CMapInfo * bbb);
  63. mapSorter(ESortBy es)
  64. : sortBy(es){};
  65. };
  66. /// The main menu screens listed in the EState enum
  67. class CMenuScreen : public CIntObject
  68. {
  69. const JsonNode & config;
  70. CTabbedInt * tabs;
  71. CPicture * background;
  72. std::vector<CPicture *> images;
  73. CIntObject * createTab(size_t index);
  74. public:
  75. std::vector<std::string> menuNameToEntry;
  76. enum EState //where are we?
  77. {
  78. mainMenu,
  79. newGame,
  80. loadGame,
  81. campaignMain,
  82. saveGame,
  83. scenarioInfo,
  84. campaignList
  85. };
  86. enum EGameMode
  87. {
  88. SINGLE_PLAYER = 0,
  89. MULTI_HOT_SEAT,
  90. MULTI_NETWORK_HOST,
  91. MULTI_NETWORK_GUEST,
  92. SINGLE_CAMPAIGN
  93. };
  94. CMenuScreen(const JsonNode & configNode);
  95. void showAll(SDL_Surface * to) override;
  96. void show(SDL_Surface * to) override;
  97. void activate() override;
  98. void deactivate() override;
  99. void switchToTab(size_t index);
  100. };
  101. class CMenuEntry : public CIntObject
  102. {
  103. std::vector<CPicture *> images;
  104. std::vector<CButton *> buttons;
  105. CButton * createButton(CMenuScreen * parent, const JsonNode & button);
  106. public:
  107. CMenuEntry(CMenuScreen * parent, const JsonNode & config);
  108. };
  109. class CreditsScreen : public CIntObject
  110. {
  111. int positionCounter;
  112. CMultiLineLabel * credits;
  113. public:
  114. CreditsScreen();
  115. void show(SDL_Surface * to) override;
  116. void clickLeft(tribool down, bool previousState) override;
  117. void clickRight(tribool down, bool previousState) override;
  118. };
  119. /// Implementation of the chat box
  120. class CChatBox : public CIntObject
  121. {
  122. public:
  123. CTextBox * chatHistory;
  124. CTextInput * inputBox;
  125. CChatBox(const Rect & rect);
  126. void keyPressed(const SDL_KeyboardEvent & key) override;
  127. void addNewMessage(const std::string & text);
  128. };
  129. class InfoCard : public CIntObject
  130. {
  131. CAnimImage * victory, * loss, * sizes;
  132. std::shared_ptr<CAnimation> sFlags;
  133. public:
  134. CPicture * bg;
  135. bool network;
  136. bool chatOn; //if chat is shown, then description is hidden
  137. CTextBox * mapDescription;
  138. CChatBox * chat;
  139. CPicture * playerListBg;
  140. CToggleGroup * difficulty;
  141. void changeSelection(const CMapInfo * to);
  142. void showAll(SDL_Surface * to) override;
  143. void clickRight(tribool down, bool previousState) override;
  144. void showTeamsPopup();
  145. void toggleChat();
  146. void setChat(bool activateChat);
  147. InfoCard(bool Network = false);
  148. ~InfoCard();
  149. };
  150. /// The selection tab which is shown at the map selection screen
  151. class SelectionTab : public CIntObject
  152. {
  153. private:
  154. std::shared_ptr<CAnimation> formatIcons;
  155. void parseMaps(const std::unordered_set<ResourceID> & files);
  156. void parseGames(const std::unordered_set<ResourceID> & files, CMenuScreen::EGameMode gameMode);
  157. std::unordered_set<ResourceID> getFiles(std::string dirURI, int resType);
  158. void parseCampaigns(const std::unordered_set<ResourceID> & files);
  159. CMenuScreen::EState tabType;
  160. public:
  161. int positions; //how many entries (games/maps) can be shown
  162. CPicture * bg; //general bg image
  163. CSlider * slider;
  164. std::vector<CMapInfo> allItems;
  165. std::vector<CMapInfo *> curItems;
  166. size_t selectionPos;
  167. std::function<void(CMapInfo *)> onSelect;
  168. ESortBy sortingBy;
  169. ESortBy generalSortingBy;
  170. bool ascending;
  171. CTextInput * txt;
  172. void filter(int size, bool selectFirst = false); //0 - all
  173. void select(int position); //position: <0 - positions> position on the screen
  174. void selectAbs(int position); //position: absolute position in curItems vector
  175. int getPosition(int x, int y); //convert mouse coords to entry position; -1 means none
  176. void sliderMove(int slidPos);
  177. void sortBy(int criteria);
  178. void sort();
  179. void printMaps(SDL_Surface * to);
  180. int getLine();
  181. void selectFName(std::string fname);
  182. const CMapInfo * getSelectedMapInfo() const;
  183. void showAll(SDL_Surface * to) override;
  184. void clickLeft(tribool down, bool previousState) override;
  185. void keyPressed(const SDL_KeyboardEvent & key) override;
  186. void onDoubleClick() override;
  187. SelectionTab(CMenuScreen::EState Type, const std::function<void(CMapInfo *)> & OnSelect, CMenuScreen::EGameMode GameMode = CMenuScreen::SINGLE_PLAYER);
  188. ~SelectionTab();
  189. };
  190. /// The options tab which is shown at the map selection phase.
  191. class OptionsTab : public CIntObject
  192. {
  193. CPicture * bg;
  194. public:
  195. enum SelType
  196. {
  197. TOWN,
  198. HERO,
  199. BONUS
  200. };
  201. struct CPlayerSettingsHelper
  202. {
  203. const PlayerSettings & settings;
  204. const SelType type;
  205. CPlayerSettingsHelper(const PlayerSettings & settings, SelType type)
  206. : settings(settings), type(type)
  207. {}
  208. /// visible image settings
  209. size_t getImageIndex();
  210. std::string getImageName();
  211. std::string getName(); /// name visible in options dialog
  212. std::string getTitle(); /// title in popup box
  213. std::string getSubtitle(); /// popup box subtitle
  214. std::string getDescription(); /// popup box description, not always present
  215. };
  216. class CPregameTooltipBox : public CWindowObject, public CPlayerSettingsHelper
  217. {
  218. void genHeader();
  219. void genTownWindow();
  220. void genHeroWindow();
  221. void genBonusWindow();
  222. public:
  223. CPregameTooltipBox(CPlayerSettingsHelper & helper);
  224. };
  225. struct SelectedBox : public CIntObject, public CPlayerSettingsHelper //img with current town/hero/bonus
  226. {
  227. CAnimImage * image;
  228. CLabel * subtitle;
  229. SelectedBox(Point position, PlayerSettings & settings, SelType type);
  230. void clickRight(tribool down, bool previousState) override;
  231. void update();
  232. };
  233. struct PlayerOptionsEntry : public CIntObject
  234. {
  235. PlayerInfo & pi;
  236. PlayerSettings & s;
  237. CPicture * bg;
  238. CButton * btns[6]; //left and right for town, hero, bonus
  239. CButton * flag;
  240. SelectedBox * town;
  241. SelectedBox * hero;
  242. SelectedBox * bonus;
  243. enum
  244. {
  245. HUMAN_OR_CPU,
  246. HUMAN,
  247. CPU
  248. } whoCanPlay;
  249. PlayerOptionsEntry(OptionsTab * owner, PlayerSettings & S);
  250. void selectButtons(); //hides unavailable buttons
  251. void showAll(SDL_Surface * to) override;
  252. void update();
  253. };
  254. CSlider * turnDuration;
  255. std::set<int> usedHeroes;
  256. struct PlayerToRestore
  257. {
  258. PlayerColor color;
  259. int id;
  260. void reset() { id = -1; color = PlayerColor::CANNOT_DETERMINE; }
  261. PlayerToRestore(){ reset(); }
  262. } playerToRestore;
  263. std::map<PlayerColor, PlayerOptionsEntry *> entries; //indexed by color
  264. void nextCastle(PlayerColor player, int dir); //dir == -1 or +1
  265. void nextHero(PlayerColor player, int dir); //dir == -1 or +1
  266. void nextBonus(PlayerColor player, int dir); //dir == -1 or +1
  267. void setTurnLength(int npos);
  268. void flagPressed(PlayerColor player);
  269. void recreate();
  270. OptionsTab();
  271. ~OptionsTab();
  272. void showAll(SDL_Surface * to) override;
  273. int nextAllowedHero(PlayerColor player, int min, int max, int incl, int dir);
  274. bool canUseThisHero(PlayerColor player, int ID);
  275. };
  276. /// The random map tab shows options for generating a random map.
  277. class CRandomMapTab : public CIntObject
  278. {
  279. public:
  280. CRandomMapTab();
  281. void showAll(SDL_Surface * to) override;
  282. void updateMapInfo();
  283. CFunctionList<void(const CMapInfo *)> & getMapInfoChanged();
  284. const CMapInfo * getMapInfo() const;
  285. const CMapGenOptions & getMapGenOptions() const;
  286. void setMapGenOptions(std::shared_ptr<CMapGenOptions> opts);
  287. private:
  288. void addButtonsToGroup(CToggleGroup * group, const std::vector<std::string> & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex) const;
  289. void addButtonsWithRandToGroup(CToggleGroup * group, const std::vector<std::string> & defs, int startIndex, int endIndex, int btnWidth, int helpStartIndex, int helpRandIndex) const;
  290. void deactivateButtonsFrom(CToggleGroup * group, int startId);
  291. void validatePlayersCnt(int playersCnt);
  292. void validateCompOnlyPlayersCnt(int compOnlyPlayersCnt);
  293. std::vector<int> getPossibleMapSizes();
  294. CPicture * bg;
  295. CToggleButton * twoLevelsBtn;
  296. CToggleGroup * mapSizeBtnGroup, * playersCntGroup, * teamsCntGroup, * compOnlyPlayersCntGroup,
  297. * compOnlyTeamsCntGroup, * waterContentGroup, * monsterStrengthGroup;
  298. CButton * showRandMaps;
  299. CMapGenOptions mapGenOptions;
  300. std::unique_ptr<CMapInfo> mapInfo;
  301. CFunctionList<void(const CMapInfo *)> mapInfoChanged;
  302. };
  303. /// Interface for selecting a map.
  304. class ISelectionScreenInfo
  305. {
  306. public:
  307. CMenuScreen::EGameMode gameMode;
  308. CMenuScreen::EState screenType; //new/save/load#Game
  309. const CMapInfo * current;
  310. StartInfo sInfo;
  311. std::map<ui8, std::string> playerNames; // id of player <-> player name; 0 is reserved as ID of AI "players"
  312. ISelectionScreenInfo(const std::map<ui8, std::string> * Names = nullptr);
  313. virtual ~ISelectionScreenInfo();
  314. virtual void update(){};
  315. virtual void propagateOptions() {};
  316. virtual void postRequest(ui8 what, ui8 dir) {};
  317. virtual void postChatMessage(const std::string & txt){};
  318. void setPlayer(PlayerSettings & pset, ui8 player);
  319. void updateStartInfo(std::string filename, StartInfo & sInfo, const std::unique_ptr<CMapHeader> & mapHeader);
  320. ui8 getIdOfFirstUnallocatedPlayer(); //returns 0 if none
  321. bool isGuest() const;
  322. bool isHost() const;
  323. };
  324. /// The actual map selection screen which consists of the options and selection tab
  325. class CSelectionScreen : public CIntObject, public ISelectionScreenInfo
  326. {
  327. bool bordered;
  328. public:
  329. CPicture * bg; //general bg image
  330. InfoCard * card;
  331. OptionsTab * opt;
  332. CRandomMapTab * randMapTab;
  333. CButton * start, * back;
  334. SelectionTab * sel;
  335. CIntObject * curTab;
  336. boost::thread * serverHandlingThread;
  337. boost::recursive_mutex * mx;
  338. std::list<CPackForSelectionScreen *> upcomingPacks; //protected by mx
  339. CConnection * serv; //connection to server, used in MP mode
  340. bool ongoingClosing;
  341. ui8 myNameID; //used when networking - otherwise all player are "mine"
  342. CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EGameMode GameMode = CMenuScreen::SINGLE_PLAYER, const std::map<ui8, std::string> * Names = nullptr, const std::string & Address = "", const ui16 Port = 0);
  343. ~CSelectionScreen();
  344. void toggleTab(CIntObject * tab);
  345. void changeSelection(const CMapInfo * to);
  346. void startCampaign();
  347. void startScenario();
  348. void difficultyChange(int to);
  349. void handleConnection();
  350. void processPacks();
  351. void setSInfo(const StartInfo & si);
  352. void update() override;
  353. void propagateOptions() override;
  354. void postRequest(ui8 what, ui8 dir) override;
  355. void postChatMessage(const std::string & txt) override;
  356. void propagateNames();
  357. void showAll(SDL_Surface * to) override;
  358. };
  359. /// Save game screen
  360. class CSavingScreen : public CSelectionScreen
  361. {
  362. public:
  363. const CMapInfo * ourGame;
  364. CSavingScreen(bool hotseat = false);
  365. ~CSavingScreen();
  366. };
  367. /// Scenario information screen shown during the game (thus not really a "pre-game" but fits here anyway)
  368. class CScenarioInfo : public CIntObject, public ISelectionScreenInfo
  369. {
  370. public:
  371. CButton * back;
  372. InfoCard * card;
  373. OptionsTab * opt;
  374. CScenarioInfo(const CMapHeader * mapHeader, const StartInfo * startInfo);
  375. ~CScenarioInfo();
  376. };
  377. /// Multiplayer mode
  378. class CMultiMode : public CIntObject
  379. {
  380. public:
  381. CPicture * bg;
  382. CTextInput * txt;
  383. CButton * btns[7]; //0 - hotseat, 6 - cancel
  384. CGStatusBar * bar;
  385. CMultiMode();
  386. void openHotseat();
  387. void hostTCP();
  388. void joinTCP();
  389. };
  390. /// Hot seat player window
  391. class CHotSeatPlayers : public CIntObject
  392. {
  393. CPicture * bg;
  394. CTextBox * title;
  395. CTextInput * txt[8];
  396. CButton * ok, * cancel;
  397. CGStatusBar * bar;
  398. void onChange(std::string newText);
  399. void enterSelectionScreen();
  400. public:
  401. CHotSeatPlayers(const std::string & firstPlayer);
  402. };
  403. class CPrologEpilogVideo : public CWindowObject
  404. {
  405. CCampaignScenario::SScenarioPrologEpilog spe;
  406. int positionCounter;
  407. int voiceSoundHandle;
  408. std::function<void()> exitCb;
  409. CMultiLineLabel * text;
  410. public:
  411. CPrologEpilogVideo(CCampaignScenario::SScenarioPrologEpilog _spe, std::function<void()> callback);
  412. void clickLeft(tribool down, bool previousState) override;
  413. void show(SDL_Surface * to) override;
  414. };
  415. /// Campaign screen where you can choose one out of three starting bonuses
  416. class CBonusSelection : public CIntObject
  417. {
  418. public:
  419. CBonusSelection(const std::string & campaignFName);
  420. CBonusSelection(std::shared_ptr<CCampaignState> _ourCampaign);
  421. ~CBonusSelection();
  422. void showAll(SDL_Surface * to) override;
  423. void show(SDL_Surface * to) override;
  424. private:
  425. struct SCampPositions
  426. {
  427. std::string campPrefix;
  428. int colorSuffixLength;
  429. struct SRegionDesc
  430. {
  431. std::string infix;
  432. int xpos, ypos;
  433. };
  434. std::vector<SRegionDesc> regions;
  435. };
  436. class CRegion : public CIntObject
  437. {
  438. CBonusSelection * owner;
  439. SDL_Surface * graphics[3]; //[0] - not selected, [1] - selected, [2] - striped
  440. bool accessible; //false if region should be striped
  441. bool selectable; //true if region should be selectable
  442. int myNumber; //number of region
  443. public:
  444. std::string rclickText;
  445. CRegion(CBonusSelection * _owner, bool _accessible, bool _selectable, int _myNumber);
  446. ~CRegion();
  447. void clickLeft(tribool down, bool previousState) override;
  448. void clickRight(tribool down, bool previousState) override;
  449. void show(SDL_Surface * to) override;
  450. };
  451. void init();
  452. void loadPositionsOfGraphics();
  453. void updateStartButtonState(int selected = -1); //-1 -- no bonus is selected
  454. void updateBonusSelection();
  455. void updateCampaignState();
  456. // Event handlers
  457. void goBack();
  458. void startMap();
  459. void restartMap();
  460. void selectMap(int mapNr, bool initialSelect);
  461. void selectBonus(int id);
  462. void increaseDifficulty();
  463. void decreaseDifficulty();
  464. // GUI components
  465. SDL_Surface * background;
  466. CButton * startB, * restartB, * backB;
  467. CTextBox * campaignDescription, * mapDescription;
  468. std::vector<SCampPositions> campDescriptions;
  469. std::vector<CRegion *> regions;
  470. CRegion * highlightedRegion;
  471. CToggleGroup * bonuses;
  472. std::array<CAnimImage *, 5> diffPics; //pictures of difficulties, user-selectable (or not if campaign locks this)
  473. CButton * diffLb, * diffRb; //buttons for changing difficulty
  474. CAnimImage * sizes; //icons of map sizes
  475. std::shared_ptr<CAnimation> sFlags;
  476. // Data
  477. std::shared_ptr<CCampaignState> ourCampaign;
  478. int selectedMap;
  479. boost::optional<int> selectedBonus;
  480. StartInfo startInfo;
  481. std::unique_ptr<CMapHeader> ourHeader;
  482. };
  483. /// Campaign selection screen
  484. class CCampaignScreen : public CIntObject
  485. {
  486. public:
  487. enum CampaignStatus
  488. {
  489. DEFAULT = 0,
  490. ENABLED,
  491. DISABLED,
  492. COMPLETED
  493. }; // the status of the campaign
  494. private:
  495. /// A button which plays a video when you move the mouse cursor over it
  496. class CCampaignButton : public CIntObject
  497. {
  498. private:
  499. CLabel * hoverLabel;
  500. CampaignStatus status;
  501. std::string campFile; // the filename/resourcename of the campaign
  502. std::string video; // the resource name of the video
  503. std::string hoverText;
  504. void clickLeft(tribool down, bool previousState) override;
  505. void hover(bool on) override;
  506. public:
  507. CCampaignButton(const JsonNode & config);
  508. void show(SDL_Surface * to) override;
  509. };
  510. std::vector<CCampaignButton *> campButtons;
  511. std::vector<CPicture *> images;
  512. CButton * createExitButton(const JsonNode & button);
  513. public:
  514. enum CampaignSet
  515. {
  516. ROE,
  517. AB,
  518. SOD,
  519. WOG
  520. };
  521. CCampaignScreen(const JsonNode & config);
  522. void showAll(SDL_Surface * to) override;
  523. };
  524. /// Manages the configuration of pregame GUI elements like campaign screen, main menu, loading screen,...
  525. class CGPreGameConfig
  526. {
  527. public:
  528. static CGPreGameConfig & get();
  529. const JsonNode & getConfig() const;
  530. const JsonNode & getCampaigns() const;
  531. private:
  532. CGPreGameConfig();
  533. const JsonNode campaignSets;
  534. const JsonNode config;
  535. };
  536. /// Handles background screen, loads graphics for victory/loss condition and random town or hero selection
  537. class CGPreGame : public CIntObject, public IUpdateable
  538. {
  539. void loadGraphics();
  540. void disposeGraphics();
  541. CGPreGame(); //Use createIfNotPresent
  542. public:
  543. CMenuScreen * menu;
  544. std::shared_ptr<CAnimation> victoryIcons, lossIcons;
  545. ~CGPreGame();
  546. void update() override;
  547. void openSel(CMenuScreen::EState type, CMenuScreen::EGameMode gameMode = CMenuScreen::SINGLE_PLAYER);
  548. void openCampaignScreen(std::string name);
  549. static CGPreGame * create();
  550. void removeFromGui();
  551. static void showLoadingScreen(std::function<void()> loader);
  552. };
  553. class CLoadingScreen : public CWindowObject
  554. {
  555. boost::thread loadingThread;
  556. std::string getBackground();
  557. public:
  558. CLoadingScreen(std::function<void()> loader);
  559. ~CLoadingScreen();
  560. void showAll(SDL_Surface * to) override;
  561. };
  562. /// Simple window to enter the server's address.
  563. class CSimpleJoinScreen : public CIntObject
  564. {
  565. CPicture * bg;
  566. CTextBox * title;
  567. CButton * ok, * cancel;
  568. CGStatusBar * bar;
  569. CTextInput * address;
  570. CTextInput * port;
  571. void enterSelectionScreen(CMenuScreen::EGameMode mode);
  572. void onChange(const std::string & newText);
  573. public:
  574. CSimpleJoinScreen(CMenuScreen::EGameMode mode);
  575. };
  576. extern ISelectionScreenInfo * SEL;
  577. extern CGPreGame * CGP;