From 304520473bc3a137af9fc6fe68700c76740d237e Mon Sep 17 00:00:00 2001 From: Vsevolod Kremianskii Date: Sat, 7 Nov 2020 12:43:30 +0700 Subject: [PATCH] feat: Add bare in-game options and save/load menus --- CMakeLists.txt | 4 + res/reone.xcf | Bin 279968 -> 328062 bytes src/game/game.cpp | 19 +++++ src/game/game.h | 15 ++-- src/game/gui/hud.cpp | 2 + src/game/gui/ingame/ingame.cpp | 145 +++++++++++++------------------- src/game/gui/ingame/ingame.h | 23 +++-- src/game/gui/ingame/options.cpp | 64 ++++++++++++++ src/game/gui/ingame/options.h | 42 +++++++++ src/game/gui/mainmenu.cpp | 3 +- src/game/gui/saveload.cpp | 75 +++++++++++++++++ src/game/gui/saveload.h | 51 +++++++++++ 12 files changed, 343 insertions(+), 100 deletions(-) create mode 100644 src/game/gui/ingame/options.cpp create mode 100644 src/game/gui/ingame/options.h create mode 100644 src/game/gui/saveload.cpp create mode 100644 src/game/gui/saveload.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ff85da4..5e4a35ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -362,9 +362,11 @@ set(GAME_HEADERS src/game/gui/ingame/journal.h src/game/gui/ingame/map.h src/game/gui/ingame/messages.h + src/game/gui/ingame/options.h src/game/gui/loadscreen.h src/game/gui/mainmenu.h src/game/gui/partyselect.h + src/game/gui/saveload.h src/game/gui/selectoverlay.h src/game/object/area.h src/game/object/creature.h @@ -436,9 +438,11 @@ set(GAME_SOURCES src/game/gui/ingame/journal.cpp src/game/gui/ingame/map.cpp src/game/gui/ingame/messages.cpp + src/game/gui/ingame/options.cpp src/game/gui/loadscreen.cpp src/game/gui/mainmenu.cpp src/game/gui/partyselect.cpp + src/game/gui/saveload.cpp src/game/gui/selectoverlay.cpp src/game/object/area.cpp src/game/object/creature.cpp diff --git a/res/reone.xcf b/res/reone.xcf index 59db186e15e242f016114cea071d304be07a276a..0296552a448fff205b04896149af56dd3cf360ac 100644 GIT binary patch delta 55082 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 T!8?QB-?~s;y>+4cVfViQU(ZFk delta 6900 zcmd^^36xXi6~}M#l1wt0naq+|^39rAGyA^JFjPg0*t$?x)M~L*tqP*Y{q%uV+^v9` zgVqJDR?%`qs)()1D2R$u!J~o-DB^<3unjWIQX;Q1>*UYP87Bq8(xJp^z*wNlgw1#Ru?oW0gt zIQzt9wX>^zSIl<4*yr?Zoc)0}BgFfmzr+*~=TlF{^?82PQl=d+~qTVNl-u|7|>oqoTq-E;-?=N!Mu)=NLL^sWIhH#woKI)|NVMo8BVafeuiEF_or^7bhmjMrHRO$-yYuOr?0qdsw)KU}Y+YV$ z>*@<_T|3LxcdoVd-T41)Tw-s3)^6)I``Vpfo@a0CsiKCHZxn!$m|<($ivWwZU1Yp+ zDxLJBY5bXe{b#5wKEG&w%t%OA2gwUYUpTI{@pCuSYWtb|du%NnZ)-SWYsovdM$U+< zeJw`hDto)uzTZaUz4mtFV{u(#Yuholwm)cV*FSCTT?!D8hhTb4Ks5?5dfFPJHqZ(_ z#iIohc|`ABV}$+n5KwiH$|L&v8Y44Y4H>Emf-)*0Q|%o;`p(P)o|&I6^X^{I$72sz zW!teEV&0WVf>9@S0ggAY6LiLA7JSf!9f0H9*bX}IAq(E+!8XtbX%Du7_P&=uf>(I4 z1$6!(3qE4{uo>{+L~H`>TFrt}{MZOO^$QlfF$o($7Y(uCgUMJAy3u06f23d?U~hog zAHZ6`v8h-C+OdKKk4VF6-eAEa(wR%su?lcZ2D3i{D*5Q>pjHK-UL`}L@oyE*HLw(h+!aTkf6M$8pQd9W3}=tM{L#0DL#SZHS%2=lO@){ZvFwTSx0YZKVtE(8 zWR+tYeT2s@9I3}~1#jG0hknrp^nv9#^|L1Qg06U>1ryE$J!WewdO%Ma zZbLWVB^~G@cA`P-LMPx^-RJ;)qScKSbPe^OF529S_=f3wj_xSX9j$?oDx*7E2qh{P z%2f_js!XU+=}@Oqp+TiUlS+#I={=*ed6YsheM{)R{*T^h?t4T79RrSayIx!R_&qmW zcINm_<*b1;9NM$)xw+FPcBhv?2!}s?=H>|zXCV~e$c|^sK5s4*V{GWTsiiqkj@Fx3 zM>3%jtyd?fr$aSbJ7>}r)}pm*CS7GcYjzSeqP2ChGZC6mFZ)Hr2Q8>~9N~pl)UnA4 z(2jVC2Revu=p?$J3vr4;)Ygek=*HNdK7byyJ}-e@)Ndq?LcGiLjYiY6B)VWdnUYtv z0T0`nTBF<7lPRUB2C^l#rut}jgOQobpG$^f1E`K$lWkEy%5Ka9oDJY9qd*Tvdcnfg zz8-KO-rfUF#PQuk{draw7>EyafeZ1dPNM!etpnVMcQUm;v>iOC-%V(P1jNgk`pcqL z@FLD5>qb1R1$-vzx7^K;NOzj42hy9sk9Y%9?D=Vg6b;OZZ|AxuQ09v0#0OIZ=4K@Rbmj zfc6ZrV6$TWPI!lKrNUxbsD@dv-OOeAz3^_~>Rb$iP8?yu?mXsX;eEol@~{YWlEs33 z`OFK14+`JOCzI9z&4LFPFfSI)6Rt170?_H21rIC4g3*ANlK{>aZY;!nz|11%IH4(g zT=?;~FuH1s5st3gWaLEmY%=~H-TuB2EZl!m@yGhrh`zVU2z~E=H}~1ozI*-ZF-`X; zWYT{|UV~Ur$vj4QwQw<0Z*fE*6R}u$obWo~GfchBSpivy<-(JMHwn#t7QNFbhit?u z;i2yYX<%+y1kQu29h5>67%5x&OM!`>25h;72Ng?9;8m4K

%08bWPqaR;hT+oBMkY`v-ts)M$zjx8>bs&c+r8) zM(E%sNK$)8Gx!yccr7e-@lWI!=H6>y{r2m?{l8+Xhuz9KRwZ^65WTg^$~X8BCqM+slo_onG;`lJBw{E;r*Nx`&J~kgG~y?@+2V zS~+0kM-Lw`f<~5#L{A?uPVctoul@N;KSy(!i>RO2G0g9}4)TWmonV!C!zBe|ELw+I zaG7|@IfZOFv1}GxEG{&mh)rrRi3R71Zyge5TlkvBe8Y*fp(O z7F;YwdU7fI>|hcL-Y3>Ori`6=lfi;B#H=IbZ1PLR*e6!7?+>Q1;9OY>Mn`z1*x+Qr zKU7i;rL961Tx7};Gro!{E&ZvR1+SB`D^ktn*b*tnCe(0+wl$FjXG+mlU(0peQm*50 zLLF6h`g1P}UQV)WWUsuM>SKO zsn;7UcwP&Yo_c!<3*OKQ93R;Ax>vPBf{bYY4x=T<^iTV~ubTFIb%m8cJvcrlY){~> z{81vdvNNlq#w_NVyRV%pgO@PuZ{5pY%$QG1p)ViM@!dkvH^=&Eh?m;!p-NF4@1 zpR8*!74Y0z$|LaH8cZivV+QEo4pmZCp_?{DFq1-{ITaLP=&>8iFo)s_bH=U`3OB6W zIU`}r1FQNGi`Q9JUQn&l=pe6~R?6A0hiEmls;0fo>s_pP(!$-mehnvdPI>6v7%xA& z66%h-Z05Wd)~+8IFes(qS<@GvyS*}N95Qw7X-mB~P2JAu)-R2K-=3}1tt($NdAAXo zP*2Ga=NPq=5>=}VN{fP$Z$wlU&D?A#Qz6McidCL0Bn67xlV&exBDC^I|IIV^{Qb`% zy6#Kr+<*Kdnm^z*x}HOPn<9&`G$j{sj4@Qoyc9UuSm_4NIfiPS9C}=APynJ|a~meb zA$q9V#i_`JZc0e>6Am}Dq23tuaBMQ%oj`);dpSy(@9=W6@@BvXO{hO9NTj?)@9ywJ z1Fdf-B$40+$&|(5^c1K=oE4yaM&ITLKn+VOr8XpKP=$DH21LmAF9@1YK@rW7nUwJ8 z zxlnc)tw*uJg_H6kw3-Z$ynWx<4MsI37>(@O0@XSkoRqf%~z=cOV$uZ;0g1tO= zR0r^It4f#QP`xrFs#d1o+;?~X@!rfIc6a;ljUt&?xRvvnha{!x zXrssm`#HElif_hKjI+|w&Y8|p9USnicCg^lopj%5g9VT7;xuT5g9XQQb4>I+tygHZ z_JGDe(@M1?)Jqj5tyXTjA+sBoMWW>+#zyDpmal(%7=4<={H`(fuO6;3x9DwoaUD>y)*&PPc#SF>beiFEJh{v!8!F{(S%S_V$~@wr)ApRload(); } +void Game::loadSaveLoad() { + _saveLoad.reset(new SaveLoad(this)); + _saveLoad->load(); +} + void Game::loadInGame() { _inGame.reset(new InGameMenu(this)); _inGame->load(); @@ -345,6 +353,8 @@ GUI *Game::getScreenGUI() const { return _container.get(); case GameScreen::PartySelection: return _partySelect.get(); + case GameScreen::SaveLoad: + return _saveLoad.get(); default: return nullptr; } @@ -482,6 +492,9 @@ void Game::openInGameMenu(InGameMenu::Tab tab) { case InGameMenu::Tab::Map: _inGame->openMap(); break; + case InGameMenu::Tab::Options: + _inGame->openOptions(); + break; default: break; } @@ -506,6 +519,12 @@ void Game::openPartySelection(const PartySelection::Context &ctx) { _screen = GameScreen::PartySelection; } +void Game::openSaveLoad(SaveLoad::Mode mode) { + setCursorType(CursorType::Default); + _saveLoad->setMode(mode); + _screen = GameScreen::SaveLoad; +} + void Game::scheduleModuleTransition(const string &moduleName, const string &entry) { _nextModule = moduleName; _nextEntry = entry; diff --git a/src/game/game.h b/src/game/game.h index 199762d4..d8dc7053 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -40,6 +40,7 @@ #include "gui/loadscreen.h" #include "gui/mainmenu.h" #include "gui/partyselect.h" +#include "gui/saveload.h" #include "object/module.h" #include "object/objectfactory.h" #include "object/spatial.h" @@ -74,11 +75,12 @@ public: void loadModule(const std::string &name, const std::string &entry = ""); void onCameraChanged(CameraType camera); - void openContainer(SpatialObject *container); - void openInGame(); - void openInGameMenu(InGameMenu::Tab tab); - void openMainMenu(); + void openSaveLoad(SaveLoad::Mode mode); void openPartySelection(const PartySelection::Context &ctx); + void openMainMenu(); + void openInGameMenu(InGameMenu::Tab tab); + void openInGame(); + void openContainer(SpatialObject *container); void scheduleModuleTransition(const std::string &moduleName, const std::string &entry); void startCharacterGeneration(); void startDialog(SpatialObject &owner, const std::string &resRef); @@ -133,7 +135,8 @@ private: InGameMenu, Dialog, Container, - PartySelection + PartySelection, + SaveLoad }; struct UserDefinedEvent { @@ -175,6 +178,7 @@ private: std::unique_ptr

_dialog; std::unique_ptr _container; std::unique_ptr _partySelect; + std::unique_ptr _saveLoad; // END GUI @@ -225,6 +229,7 @@ private: void loadLoadingScreen(); void loadMainMenu(); void loadPartySelection(); + void loadSaveLoad(); // END Loading diff --git a/src/game/gui/hud.cpp b/src/game/gui/hud.cpp index 88bcc3cd..af4408eb 100644 --- a/src/game/gui/hud.cpp +++ b/src/game/gui/hud.cpp @@ -193,6 +193,8 @@ void HUD::onClick(const string &control) { _game->openInGameMenu(InGameMenu::Tab::Journal); } else if (control == "BTN_MAP") { _game->openInGameMenu(InGameMenu::Tab::Map); + } else if (control == "BTN_OPT") { + _game->openInGameMenu(InGameMenu::Tab::Options); } } diff --git a/src/game/gui/ingame/ingame.cpp b/src/game/gui/ingame/ingame.cpp index 13c7d4d1..78707a46 100644 --- a/src/game/gui/ingame/ingame.cpp +++ b/src/game/gui/ingame/ingame.cpp @@ -17,6 +17,8 @@ #include "ingame.h" +#include + #include "../../game.h" using namespace std; @@ -29,6 +31,17 @@ namespace reone { namespace game { +static unordered_map g_tabTags { + { InGameMenu::Tab::Equipment, "LBLH_EQU" }, + { InGameMenu::Tab::Inventory, "LBLH_INV" }, + { InGameMenu::Tab::Character, "LBLH_CHA" }, + { InGameMenu::Tab::Abilities, "LBLH_ABI" }, + { InGameMenu::Tab::Messages, "LBLH_MSG" }, + { InGameMenu::Tab::Journal, "LBLH_JOU" }, + { InGameMenu::Tab::Map, "LBLH_MAP" }, + { InGameMenu::Tab::Options, "LBLH_OPT" } +}; + InGameMenu::InGameMenu(Game *game) : GUI(game->version(), game->options().graphics), _game(game) { @@ -48,64 +61,65 @@ void InGameMenu::load() { hideControl("BTN_MAP"); hideControl("BTN_OPT"); - setControlFocusable("LBLH_EQU", false); - setControlFocusable("LBLH_INV", false); - setControlFocusable("LBLH_CHA", false); - setControlFocusable("LBLH_ABI", false); - setControlFocusable("LBLH_MSG", false); - setControlFocusable("LBLH_JOU", false); - setControlFocusable("LBLH_MAP", false); - setControlFocusable("LBLH_OPT", false); + loadEquipment(); + loadInventory(); + loadCharacter(); + loadAbilities(); + loadMessages(); + loadJournal(); + loadMap(); + loadOptions(); - loadEquipmentMenu(); - loadInventoryMenu(); - loadCharacterMenu(); - loadAbilitiesMenu(); - loadMessagesMenu(); - loadJournalMenu(); - loadMapMenu(); + for (auto &tag : g_tabTags) { + setControlFocusable(tag.second, false); + } } -void InGameMenu::loadEquipmentMenu() { +void InGameMenu::loadEquipment() { _equip = make_unique(_game); _equip->load(); } -void InGameMenu::loadInventoryMenu() { +void InGameMenu::loadInventory() { _inventory = make_unique(_game); _inventory->load(); } -void InGameMenu::loadCharacterMenu() { +void InGameMenu::loadCharacter() { _character = make_unique(_game); _character->load(); } -void InGameMenu::loadAbilitiesMenu() { +void InGameMenu::loadAbilities() { _abilities = make_unique(_game); _abilities->load(); } -void InGameMenu::loadMessagesMenu() { +void InGameMenu::loadMessages() { _messages = make_unique(_game); _messages->load(); } -void InGameMenu::loadJournalMenu() { +void InGameMenu::loadJournal() { _journal = make_unique(_game); _journal->load(); } -void InGameMenu::loadMapMenu() { +void InGameMenu::loadMap() { _map = make_unique(_game); _map->load(); } +void InGameMenu::loadOptions() { + _options = make_unique(_game); + _options->load(); +} + bool InGameMenu::handle(const SDL_Event &event) { GUI *tabGui = getActiveTabGUI(); if (tabGui && tabGui->handle(event)) return true; - if (_tab != Tab::Map && GUI::handle(event)) return true; + if (GUI::handle(event)) return true; return false; } @@ -126,6 +140,8 @@ GUI *InGameMenu::getActiveTabGUI() const { return _journal.get(); case Tab::Map: return _map.get(); + case Tab::Options: + return _options.get(); default: return nullptr; } @@ -149,98 +165,53 @@ void InGameMenu::render() const { } void InGameMenu::openEquipment() { - setControlFocus("LBLH_EQU", true); - setControlFocus("LBLH_INV", false); - setControlFocus("LBLH_CHA", false); - setControlFocus("LBLH_ABI", false); - setControlFocus("LBLH_MSG", false); - setControlFocus("LBLH_JOU", false); - setControlFocus("LBLH_MAP", false); - setControlFocus("LBLH_OPT", false); - _equip->update(); _tab = Tab::Equipment; + updateTabButtons(); +} + +void InGameMenu::updateTabButtons() { + for (auto &tag : g_tabTags) { + setControlFocus(tag.second, tag.first == _tab); + } } void InGameMenu::openInventory() { - setControlFocus("LBLH_EQU", false); - setControlFocus("LBLH_INV", true); - setControlFocus("LBLH_CHA", false); - setControlFocus("LBLH_ABI", false); - setControlFocus("LBLH_MSG", false); - setControlFocus("LBLH_JOU", false); - setControlFocus("LBLH_MAP", false); - setControlFocus("LBLH_OPT", false); - _inventory->updatePortraits(); _tab = Tab::Inventory; + updateTabButtons(); } void InGameMenu::openCharacter() { - setControlFocus("LBLH_EQU", false); - setControlFocus("LBLH_INV", false); - setControlFocus("LBLH_CHA", true); - setControlFocus("LBLH_ABI", false); - setControlFocus("LBLH_MSG", false); - setControlFocus("LBLH_JOU", false); - setControlFocus("LBLH_MAP", false); - setControlFocus("LBLH_OPT", false); - _character->updatePortraits(); _tab = Tab::Character; + updateTabButtons(); } void InGameMenu::openAbilities() { - setControlFocus("LBLH_EQU", false); - setControlFocus("LBLH_INV", false); - setControlFocus("LBLH_CHA", false); - setControlFocus("LBLH_ABI", true); - setControlFocus("LBLH_MSG", false); - setControlFocus("LBLH_JOU", false); - setControlFocus("LBLH_MAP", false); - setControlFocus("LBLH_OPT", false); - _abilities->updatePortraits(); _tab = Tab::Abilities; + updateTabButtons(); } void InGameMenu::openMessages() { - setControlFocus("LBLH_EQU", false); - setControlFocus("LBLH_INV", false); - setControlFocus("LBLH_CHA", false); - setControlFocus("LBLH_ABI", false); - setControlFocus("LBLH_MSG", true); - setControlFocus("LBLH_JOU", false); - setControlFocus("LBLH_MAP", false); - setControlFocus("LBLH_OPT", false); - _tab = Tab::Messages; + updateTabButtons(); } void InGameMenu::openJournal() { - setControlFocus("LBLH_EQU", false); - setControlFocus("LBLH_INV", false); - setControlFocus("LBLH_CHA", false); - setControlFocus("LBLH_ABI", false); - setControlFocus("LBLH_MSG", false); - setControlFocus("LBLH_JOU", true); - setControlFocus("LBLH_MAP", false); - setControlFocus("LBLH_OPT", false); - _tab = Tab::Journal; + updateTabButtons(); } void InGameMenu::openMap() { - setControlFocus("LBLH_EQU", false); - setControlFocus("LBLH_INV", false); - setControlFocus("LBLH_CHA", false); - setControlFocus("LBLH_ABI", false); - setControlFocus("LBLH_MSG", false); - setControlFocus("LBLH_JOU", false); - setControlFocus("LBLH_MAP", true); - setControlFocus("LBLH_OPT", false); - _tab = Tab::Map; + updateTabButtons(); +} + +void InGameMenu::openOptions() { + _tab = Tab::Options; + updateTabButtons(); } void InGameMenu::onClick(const string &control) { @@ -258,6 +229,8 @@ void InGameMenu::onClick(const string &control) { openJournal(); } else if (control == "LBLH_MAP") { openMap(); + } else if (control == "LBLH_OPT") { + openOptions(); } } diff --git a/src/game/gui/ingame/ingame.h b/src/game/gui/ingame/ingame.h index 69e66720..4e510bbe 100644 --- a/src/game/gui/ingame/ingame.h +++ b/src/game/gui/ingame/ingame.h @@ -26,6 +26,7 @@ #include "journal.h" #include "map.h" #include "messages.h" +#include "options.h" namespace reone { @@ -43,7 +44,8 @@ public: Abilities, Messages, Journal, - Map + Map, + Options }; InGameMenu(Game *game); @@ -60,6 +62,7 @@ public: void openMessages(); void openJournal(); void openMap(); + void openOptions(); private: Game *_game { nullptr }; @@ -72,16 +75,20 @@ private: std::unique_ptr _messages; std::unique_ptr _journal; std::unique_ptr _map; + std::unique_ptr _options; void onClick(const std::string &control) override; - void loadCharacterMenu(); - void loadEquipmentMenu(); - void loadInventoryMenu(); - void loadAbilitiesMenu(); - void loadMessagesMenu(); - void loadJournalMenu(); - void loadMapMenu(); + void loadCharacter(); + void loadEquipment(); + void loadInventory(); + void loadAbilities(); + void loadMessages(); + void loadJournal(); + void loadMap(); + void loadOptions(); + + void updateTabButtons(); GUI *getActiveTabGUI() const; }; diff --git a/src/game/gui/ingame/options.cpp b/src/game/gui/ingame/options.cpp new file mode 100644 index 00000000..43cb0602 --- /dev/null +++ b/src/game/gui/ingame/options.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020 Vsevolod Kremianskii + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "options.h" + +#include "../../game.h" + +#include "../colors.h" + +using namespace std; + +using namespace reone::gui; +using namespace reone::resource; + +namespace reone { + +namespace game { + +OptionsMenu::OptionsMenu(Game *game) : + GUI(game->version(), game->options().graphics), + _game(game) { + + _resRef = getResRef("optionsingame"); + _backgroundType = BackgroundType::Menu; + _hasDefaultHilightColor = true; + _defaultHilightColor = getHilightColor(_version); + + if (game->version() == GameVersion::TheSithLords) { + _resolutionX = 800; + _resolutionY = 600; + } +} + +void OptionsMenu::load() { + GUI::load(); +} + +void OptionsMenu::onClick(const string &control) { + if (control == "BTN_LOADGAME") { + _game->openSaveLoad(SaveLoad::Mode::LoadFromInGame); + } else if (control == "BTN_SAVEGAME") { + _game->openSaveLoad(SaveLoad::Mode::Save); + } else if (control == "BTN_EXIT") { + _game->openInGame(); + } +} + +} // namespace game + +} // namespace reone diff --git a/src/game/gui/ingame/options.h b/src/game/gui/ingame/options.h new file mode 100644 index 00000000..3297abab --- /dev/null +++ b/src/game/gui/ingame/options.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Vsevolod Kremianskii + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "../../../gui/gui.h" + +namespace reone { + +namespace game { + +class Game; + +class OptionsMenu : public gui::GUI { +public: + OptionsMenu(Game *game); + + void load() override; + +private: + Game *_game { nullptr }; + + void onClick(const std::string &control) override; +}; + +} // namespace game + +} // namespace reone diff --git a/src/game/gui/mainmenu.cpp b/src/game/gui/mainmenu.cpp index 513c30a6..0196e89f 100644 --- a/src/game/gui/mainmenu.cpp +++ b/src/game/gui/mainmenu.cpp @@ -85,7 +85,6 @@ void MainMenu::load() { hideControl("LBL_BW"); hideControl("LBL_LUCAS"); - setControlDisabled("BTN_LOADGAME", true); setControlDisabled("BTN_MOVIES", true); setControlDisabled("BTN_OPTIONS", true); @@ -152,6 +151,8 @@ shared_ptr MainMenu::getKotorModel(SceneGraph &sceneGraph) { void MainMenu::onClick(const string &control) { if (control == "BTN_NEWGAME") { _game->startCharacterGeneration(); + } else if (control == "BTN_LOADGAME") { + _game->openSaveLoad(SaveLoad::Mode::LoadFromMainMenu); } else if (control == "BTN_EXIT") { _game->quit(); } else if (control == "BTN_WARP") { diff --git a/src/game/gui/saveload.cpp b/src/game/gui/saveload.cpp new file mode 100644 index 00000000..064297eb --- /dev/null +++ b/src/game/gui/saveload.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020 Vsevolod Kremianskii + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "saveload.h" + +#include "../game.h" + +#include "colors.h" + +using namespace std; + +using namespace reone::gui; +using namespace reone::resource; + +namespace reone { + +namespace game { + +SaveLoad::SaveLoad(Game *game) : + GUI(game->version(), game->options().graphics), + _game(game) { + + _resRef = getResRef("saveload"); + _backgroundType = BackgroundType::Menu; + _hasDefaultHilightColor = true; + _defaultHilightColor = getHilightColor(_version); + + if (game->version() == GameVersion::TheSithLords) { + _resolutionX = 800; + _resolutionY = 600; + } +} + +void SaveLoad::load() { + GUI::load(); + + disableControl("BTN_DELETE"); + disableControl("BTN_SAVELOAD"); +} + +void SaveLoad::setMode(Mode mode) { + _mode = mode; +} + +void SaveLoad::onClick(const string &control) { + if (control == "BTN_BACK") { + switch (_mode) { + case Mode::Save: + case Mode::LoadFromInGame: + _game->openInGame(); + break; + default: + _game->openMainMenu(); + break; + } + } +} + +} // namespace game + +} // namespace reone diff --git a/src/game/gui/saveload.h b/src/game/gui/saveload.h new file mode 100644 index 00000000..53fbcfd0 --- /dev/null +++ b/src/game/gui/saveload.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 Vsevolod Kremianskii + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "../../gui/gui.h" + +namespace reone { + +namespace game { + +class Game; + +class SaveLoad : public gui::GUI { +public: + enum class Mode { + Save, + LoadFromMainMenu, + LoadFromInGame + }; + + SaveLoad(Game *game); + + void load() override; + + void setMode(Mode mode); + +private: + Game *_game { nullptr }; + Mode _mode { Mode::Save }; + + void onClick(const std::string &control) override; +}; + +} // namespace game + +} // namespace reone