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 <fstream>
20 #include <sstream>
21 #include <vector>
22 #include "scene_title.h"
23 #include "audio.h"
24 #include "audio_secache.h"
25 #include "cache.h"
26 #include "game_battle.h"
27 #include "game_ineluki.h"
28 #include "game_screen.h"
29 #include "game_system.h"
30 #include "transition.h"
31 #include "input.h"
32 #include "main_data.h"
33 #include "meta.h"
34 #include "output.h"
35 #include "player.h"
36 #include "translation.h"
37 #include "scene_battle.h"
38 #include "scene_import.h"
39 #include "scene_load.h"
40 #include "window_command.h"
41 #include "baseui.h"
42 #include <lcf/reader_util.h>
43
Scene_Title()44 Scene_Title::Scene_Title() {
45 type = Scene::Title;
46 }
47
Start()48 void Scene_Title::Start() {
49 Main_Data::game_system->ResetSystemGraphic();
50
51 // Skip background image and music if not used
52 if (CheckEnableTitleGraphicAndMusic()) {
53 CreateTitleGraphic();
54 PlayTitleMusic();
55 }
56
57 CreateCommandWindow();
58 CreateTranslationWindow();
59 CreateHelpWindow();
60 }
61
CreateHelpWindow()62 void Scene_Title::CreateHelpWindow() {
63 help_window.reset(new Window_Help(0, 0, SCREEN_TARGET_WIDTH, 32));
64 help_window->SetVisible(false);
65 translate_window->SetHelpWindow(help_window.get());
66 }
67
68
Continue(SceneType prev_scene)69 void Scene_Title::Continue(SceneType prev_scene) {
70 Main_Data::game_system->ResetSystemGraphic();
71
72 if (restart_title_cache) {
73 // Clear the cache when the game returns to the title screen
74 // e.g. by pressing F12, except the Title Load menu
75 Cache::Clear();
76 AudioSeCache::Clear();
77
78 Player::ResetGameObjects();
79 Main_Data::game_ineluki->ExecuteScriptList(FileFinder::Game().FindFile("autorun.script"));
80
81 Start();
82
83 restart_title_cache = false;
84 } else if (CheckEnableTitleGraphicAndMusic()) {
85 CreateTitleGraphic();
86 }
87
88 if (prev_scene != Scene::Load && !Player::hide_title_flag) {
89 command_window->SetOpenAnimation(8);
90 }
91 }
92
TransitionIn(SceneType prev_scene)93 void Scene_Title::TransitionIn(SceneType prev_scene) {
94 if (Game_Battle::battle_test.enabled || !lcf::Data::system.show_title || Player::new_game_flag)
95 return;
96
97 if (prev_scene == Scene::Load || Player::hide_title_flag) {
98 Scene::TransitionIn(prev_scene);
99 return;
100 }
101 Transition::instance().InitShow(Transition::TransitionFadeIn, this);
102 }
103
Suspend(Scene::SceneType next_scene)104 void Scene_Title::Suspend(Scene::SceneType next_scene) {
105 // Unload title graphic to save memory
106 title.reset();
107 }
108
Update()109 void Scene_Title::Update() {
110 if (Game_Battle::battle_test.enabled) {
111 Player::SetupBattleTest();
112 return;
113 }
114
115 if (!lcf::Data::system.show_title || Player::new_game_flag) {
116 Player::SetupNewGame();
117 if (Player::debug_flag && Player::hide_title_flag) {
118 Scene::Push(std::make_shared<Scene_Load>());
119 }
120 return;
121 }
122
123 if (active_window == 0) {
124 command_window->Update();
125 } else {
126 translate_window->Update();
127 }
128
129 if (Input::IsTriggered(Input::DECISION)) {
130 if (active_window == 0) {
131 int index = command_window->GetIndex();
132 if (index == indices.new_game) { // New Game
133 CommandNewGame();
134 } else if (index == indices.continue_game) { // Load Game
135 CommandContinue();
136 } else if (index == indices.import) { // Import (multi-part games)
137 CommandImport();
138 } else if (index == indices.translate) { // Choose a Translation (Language)
139 CommandTranslation();
140 } else if (index == indices.exit) { // Exit Game
141 CommandShutdown();
142 }
143 } else if (active_window == 1) {
144 int index = translate_window->GetIndex();
145 ChangeLanguage(lang_dirs.at(index));
146 }
147 } else if (Input::IsTriggered(Input::CANCEL)) {
148 if (active_window == 1) {
149 // Switch back
150 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cancel));
151 HideTranslationWindow();
152 }
153 }
154 }
155
CreateTitleGraphic()156 void Scene_Title::CreateTitleGraphic() {
157 // Load Title Graphic
158 if (!lcf::Data::system.title_name.empty()) {
159 title.reset(new Sprite());
160 FileRequestAsync* request = AsyncHandler::RequestFile("Title", lcf::Data::system.title_name);
161 request->SetGraphicFile(true);
162 request_id = request->Bind(&Scene_Title::OnTitleSpriteReady, this);
163 request->Start();
164 } else {
165 title.reset(new Sprite());
166 title->SetBitmap(Bitmap::Create(DisplayUi->GetWidth(), DisplayUi->GetHeight(), Color(0, 0, 0, 255)));
167 }
168 }
169
RepositionWindow(Window_Command & window,bool center_vertical)170 void Scene_Title::RepositionWindow(Window_Command& window, bool center_vertical) {
171 if (!center_vertical) {
172 window.SetX(SCREEN_TARGET_WIDTH / 2 - window.GetWidth() / 2);
173 window.SetY(SCREEN_TARGET_HEIGHT * 53 / 60 - window.GetHeight());
174 } else {
175 window.SetX(SCREEN_TARGET_WIDTH / 2 - window.GetWidth() / 2);
176 window.SetY(SCREEN_TARGET_HEIGHT / 2 - window.GetHeight() / 2);
177 }
178 }
179
CreateCommandWindow()180 void Scene_Title::CreateCommandWindow() {
181 // Create Options Window
182 std::vector<std::string> options;
183 options.push_back(ToString(lcf::Data::terms.new_game));
184 options.push_back(ToString(lcf::Data::terms.load_game));
185
186 // Reset index to fix issues on reuse.
187 indices = CommandIndices();
188
189 // Set "Import" based on metadata
190 if (Player::meta->IsImportEnabled()) {
191 options.push_back(Player::meta->GetExVocabImportSaveTitleText());
192 indices.import = indices.exit;
193 indices.exit++;
194 }
195
196 // Set "Translate" based on metadata
197 if (Player::translation.HasTranslations()) {
198 options.push_back(Player::meta->GetExVocabTranslateTitleText());
199 indices.translate = indices.exit;
200 indices.exit++;
201 }
202
203 options.push_back(ToString(lcf::Data::terms.exit_game));
204
205 command_window.reset(new Window_Command(options));
206 RepositionWindow(*command_window, Player::hide_title_flag);
207
208 // Enable load game if available
209 continue_enabled = FileFinder::HasSavegame();
210 if (continue_enabled) {
211 command_window->SetIndex(1);
212 } else {
213 command_window->DisableItem(1);
214 }
215
216 // Set the number of frames for the opening animation to last
217 if (!Player::hide_title_flag) {
218 command_window->SetOpenAnimation(8);
219 }
220
221 if (Player::IsRPG2k3E() && lcf::Data::battlecommands.transparency == lcf::rpg::BattleCommands::Transparency_transparent) {
222 command_window->SetBackOpacity(128);
223 }
224
225 command_window->SetVisible(true);
226 }
227
CreateTranslationWindow()228 void Scene_Title::CreateTranslationWindow() {
229 // Build a list of 'Default' and all known languages.
230 std::vector<std::string> lang_names;
231 lang_names.push_back("Default Language");
232 lang_dirs.push_back("");
233 lang_helps.push_back("Play the game in its original language.");
234
235 // Push menu entries with the display name, but also save the directory location and help text.
236 for (const Language& lg : Player::translation.GetLanguages()) {
237 lang_names.push_back(lg.lang_name);
238 lang_dirs.push_back(lg.lang_dir);
239 lang_helps.push_back(lg.lang_desc);
240 }
241
242 translate_window.reset(new Window_Command(lang_names));
243 translate_window->UpdateHelpFn = [this](Window_Help& win, int index) {
244 if (index >= 0 && index < static_cast<int>(lang_helps.size())) {
245 win.SetText(lang_helps[index]);
246 } else {
247 win.SetText("");
248 }
249 };
250 RepositionWindow(*translate_window, Player::hide_title_flag);
251
252 if (Player::IsRPG2k3E() && lcf::Data::battlecommands.transparency == lcf::rpg::BattleCommands::Transparency_transparent) {
253 translate_window->SetBackOpacity(128);
254 }
255
256 translate_window->SetVisible(false);
257 }
258
PlayTitleMusic()259 void Scene_Title::PlayTitleMusic() {
260 // Workaround Android problem: BGM doesn't start when game is started again
261 Main_Data::game_system->BgmStop();
262 // Play BGM
263 Main_Data::game_system->BgmPlay(lcf::Data::system.title_music);
264 }
265
CheckEnableTitleGraphicAndMusic()266 bool Scene_Title::CheckEnableTitleGraphicAndMusic() {
267 return lcf::Data::system.show_title &&
268 !Player::new_game_flag &&
269 !Game_Battle::battle_test.enabled &&
270 !Player::hide_title_flag;
271 }
272
CheckValidPlayerLocation()273 bool Scene_Title::CheckValidPlayerLocation() {
274 return (lcf::Data::treemap.start.party_map_id > 0);
275 }
276
CommandNewGame()277 void Scene_Title::CommandNewGame() {
278 if (!CheckValidPlayerLocation()) {
279 Output::Warning("The game has no start location set.");
280 } else {
281 Output::Debug("Starting new game");
282 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
283 Player::SetupNewGame();
284 }
285 }
286
CommandContinue()287 void Scene_Title::CommandContinue() {
288 if (continue_enabled) {
289 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
290 } else {
291 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Buzzer));
292 return;
293 }
294
295 Scene::Push(std::make_shared<Scene_Load>());
296 }
297
CommandImport()298 void Scene_Title::CommandImport() {
299 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
300
301 Scene::Push(std::make_shared<Scene_Import>());
302 }
303
CommandTranslation()304 void Scene_Title::CommandTranslation() {
305 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
306
307 // Switch windows
308 active_window = 1;
309 command_window->SetVisible(false);
310 translate_window->SetVisible(true);
311 help_window->SetVisible(true);
312 }
313
ChangeLanguage(const std::string & lang_str)314 void Scene_Title::ChangeLanguage(const std::string& lang_str) {
315 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
316
317 // No-op?
318 if (lang_str == Player::translation.GetCurrentLanguageId()) {
319 HideTranslationWindow();
320 return;
321 }
322
323 // First change the language
324 Player::translation.SelectLanguage(lang_str);
325
326 // Now reset the scene (force asset reload)
327 Scene::Push(std::make_shared<Scene_Title>(), true);
328 }
329
HideTranslationWindow()330 void Scene_Title::HideTranslationWindow() {
331 active_window = 0;
332 command_window->SetVisible(true);
333 translate_window->SetVisible(false);
334 help_window->SetVisible(false);
335 }
336
CommandShutdown()337 void Scene_Title::CommandShutdown() {
338 Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Decision));
339 Transition::instance().InitErase(Transition::TransitionFadeOut, this);
340 Scene::Pop();
341 }
342
OnTitleSpriteReady(FileRequestResult * result)343 void Scene_Title::OnTitleSpriteReady(FileRequestResult* result) {
344 title->SetBitmap(Cache::Title(result->file));
345 }
346
OnGameStart()347 void Scene_Title::OnGameStart() {
348 restart_title_cache = true;
349 }
350