1 /*
2 * This file is part of EasyRPG Player.
3 *
4 * EasyRPG Player is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * EasyRPG Player is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 // Headers
19 #include <cassert>
20 #include "scene_menu.h"
21 #include "audio.h"
22 #include "cache.h"
23 #include "game_party.h"
24 #include "game_system.h"
25 #include "input.h"
26 #include "player.h"
27 #include "scene_debug.h"
28 #include "scene_end.h"
29 #include "scene_equip.h"
30 #include "scene_item.h"
31 #include "scene_skill.h"
32 #include "scene_order.h"
33 #include "scene_save.h"
34 #include "scene_status.h"
35 #include "bitmap.h"
36
Scene_Menu(int menu_index)37 Scene_Menu::Scene_Menu(int menu_index) :
38 menu_index(menu_index) {
39 type = Scene::Menu;
40 }
41
Start()42 void Scene_Menu::Start() {
43 CreateCommandWindow();
44
45 // Gold Window
46 gold_window.reset(new Window_Gold(0, (SCREEN_TARGET_HEIGHT-32), 88, 32));
47
48 // Status Window
49 menustatus_window.reset(new Window_MenuStatus(88, 0, (SCREEN_TARGET_WIDTH-88), SCREEN_TARGET_HEIGHT));
50 menustatus_window->SetActive(false);
51 }
52
Continue(SceneType)53 void Scene_Menu::Continue(SceneType /* prev_scene */) {
54 menustatus_window->Refresh();
55 gold_window->Refresh();
56 }
57
Update()58 void Scene_Menu::Update() {
59 command_window->Update();
60 gold_window->Update();
61 menustatus_window->Update();
62
63 if (command_window->GetActive()) {
64 UpdateCommand();
65 }
66 else if (menustatus_window->GetActive()) {
67 UpdateActorSelection();
68 }
69 }
70
CreateCommandWindow()71 void Scene_Menu::CreateCommandWindow() {
72 // Create Options Window
73 std::vector<std::string> options;
74
75 if (Player::IsRPG2k()) {
76 command_options.push_back(Item);
77 command_options.push_back(Skill);
78 command_options.push_back(Equipment);
79 command_options.push_back(Save);
80 if (Player::debug_flag) {
81 command_options.push_back(Debug);
82 }
83 command_options.push_back(Quit);
84 } else {
85 for (std::vector<int16_t>::iterator it = lcf::Data::system.menu_commands.begin();
86 it != lcf::Data::system.menu_commands.end(); ++it) {
87 command_options.push_back((CommandOptionType)*it);
88 }
89 if (Player::debug_flag) {
90 command_options.push_back(Debug);
91 }
92 command_options.push_back(Quit);
93 }
94
95 // Add all menu items
96 std::vector<CommandOptionType>::iterator it;
97 for (it = command_options.begin(); it != command_options.end(); ++it) {
98 switch(*it) {
99 case Item:
100 options.push_back(ToString(lcf::Data::terms.command_item));
101 break;
102 case Skill:
103 options.push_back(ToString(lcf::Data::terms.command_skill));
104 break;
105 case Equipment:
106 options.push_back(ToString(lcf::Data::terms.menu_equipment));
107 break;
108 case Save:
109 options.push_back(ToString(lcf::Data::terms.menu_save));
110 break;
111 case Status:
112 options.push_back(ToString(lcf::Data::terms.status));
113 break;
114 case Row:
115 options.push_back(ToString(lcf::Data::terms.row));
116 break;
117 case Order:
118 options.push_back(ToString(lcf::Data::terms.order));
119 break;
120 case Wait:
121 options.push_back(ToString(Main_Data::game_system->GetAtbMode() == lcf::rpg::SaveSystem::AtbMode_atb_wait ? lcf::Data::terms.wait_on : lcf::Data::terms.wait_off));
122 break;
123 case Debug:
124 options.push_back("Debug");
125 break;
126 default:
127 options.push_back(ToString(lcf::Data::terms.menu_quit));
128 break;
129 }
130 }
131
132 command_window.reset(new Window_Command(options, 88));
133 command_window->SetIndex(menu_index);
134
135 // Disable items
136 for (it = command_options.begin(); it != command_options.end(); ++it) {
137 switch(*it) {
138 case Save:
139 // If save is forbidden disable this item
140 if (!Main_Data::game_system->GetAllowSave()) {
141 command_window->DisableItem(it - command_options.begin());
142 }
143 case Wait:
144 case Quit:
145 case Debug:
146 break;
147 case Order:
148 if (Main_Data::game_party->GetActors().size() <= 1) {
149 command_window->DisableItem(it - command_options.begin());
150 }
151 break;
152 default:
153 if (Main_Data::game_party->GetActors().empty()) {
154 command_window->DisableItem(it - command_options.begin());
155 }
156 break;
157 }
158 }
159 }
160
UpdateCommand()161 void Scene_Menu::UpdateCommand() {
162 if (Input::IsTriggered(Input::CANCEL)) {
163 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cancel));
164 Scene::Pop();
165 } else if (Input::IsTriggered(Input::DECISION)) {
166 menu_index = command_window->GetIndex();
167
168 switch (command_options[menu_index]) {
169 case Item:
170 if (Main_Data::game_party->GetActors().empty()) {
171 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
172 } else {
173 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
174 Scene::Push(std::make_shared<Scene_Item>());
175 }
176 break;
177 case Skill:
178 case Equipment:
179 case Status:
180 case Row:
181 if (Main_Data::game_party->GetActors().empty()) {
182 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
183 } else {
184 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
185 command_window->SetActive(false);
186 menustatus_window->SetActive(true);
187 menustatus_window->SetIndex(0);
188 }
189 break;
190 case Save:
191 if (!Main_Data::game_system->GetAllowSave()) {
192 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
193 } else {
194 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
195 Scene::Push(std::make_shared<Scene_Save>());
196 }
197 break;
198 case Order:
199 if (Main_Data::game_party->GetActors().size() <= 1) {
200 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
201 } else {
202 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
203 Scene::Push(std::make_shared<Scene_Order>());
204 }
205 break;
206 case Wait:
207 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
208 Main_Data::game_system->ToggleAtbMode();
209 command_window->SetItemText(menu_index,
210 Main_Data::game_system->GetAtbMode() == lcf::rpg::SaveSystem::AtbMode_atb_wait ? lcf::Data::terms.wait_on : lcf::Data::terms.wait_off);
211 break;
212 case Debug:
213 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
214 Scene::Push(std::make_shared<Scene_Debug>());
215 break;
216 case Quit:
217 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
218 Scene::Push(std::make_shared<Scene_End>());
219 break;
220 }
221 }
222 }
223
UpdateActorSelection()224 void Scene_Menu::UpdateActorSelection() {
225 if (Input::IsTriggered(Input::CANCEL)) {
226 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cancel));
227 command_window->SetActive(true);
228 menustatus_window->SetActive(false);
229 menustatus_window->SetIndex(-1);
230 } else if (Input::IsTriggered(Input::DECISION)) {
231 switch (command_options[command_window->GetIndex()]) {
232 case Skill:
233 if (!menustatus_window->GetActor()->CanAct()) {
234 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
235 return;
236 }
237 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
238 Scene::Push(std::make_shared<Scene_Skill>(menustatus_window->GetIndex()));
239 break;
240 case Equipment:
241 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
242 Scene::Push(std::make_shared<Scene_Equip>(*menustatus_window->GetActor()));
243 break;
244 case Status:
245 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
246 Scene::Push(std::make_shared<Scene_Status>(menustatus_window->GetIndex()));
247 break;
248 case Row:
249 {
250 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
251 // Don't allow entire party in the back row.
252 const auto& actors = Main_Data::game_party->GetActors();
253 int num_in_back = 0;
254 for (auto* actor: actors) {
255 if (actor->GetBattleRow() == Game_Actor::RowType::RowType_back) {
256 ++num_in_back;
257 }
258 }
259 Game_Actor* actor = actors[menustatus_window->GetIndex()];
260 if (actor->GetBattleRow() == Game_Actor::RowType::RowType_front) {
261 if (num_in_back < int(actors.size() - 1)) {
262 actor->SetBattleRow(Game_Actor::RowType::RowType_back);
263 }
264 } else {
265 actor->SetBattleRow(Game_Actor::RowType::RowType_front);
266 }
267 menustatus_window->Refresh();
268 break;
269 }
270 default:
271 assert(false);
272 break;
273 }
274
275 command_window->SetActive(true);
276 menustatus_window->SetActive(false);
277 menustatus_window->SetIndex(-1);
278 }
279 }
280