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 <cstdlib>
20 #include <algorithm>
21 #include <iomanip>
22 #include <iostream>
23 #include <sstream>
24 #include <cassert>
25 #include "audio.h"
26 #include "game_map.h"
27 #include "game_battle.h"
28 #include "game_event.h"
29 #include "game_player.h"
30 #include "game_switches.h"
31 #include "game_variables.h"
32 #include "game_party.h"
33 #include "game_actors.h"
34 #include "game_system.h"
35 #include "game_message.h"
36 #include "game_screen.h"
37 #include "spriteset_map.h"
38 #include "sprite_character.h"
39 #include "scene_map.h"
40 #include "scene_battle.h"
41 #include "scene_menu.h"
42 #include "scene_save.h"
43 #include "scene_load.h"
44 #include "scene_name.h"
45 #include "scene_shop.h"
46 #include "scene_gameover.h"
47 #include "scene.h"
48 #include "graphics.h"
49 #include "input.h"
50 #include "main_data.h"
51 #include "output.h"
52 #include "player.h"
53 #include "util_macro.h"
54 #include "game_interpreter_map.h"
55 #include <lcf/reader_lcf.h>
56
57 enum EnemyEncounterSubcommand {
58 eOptionEnemyEncounterVictory = 0,
59 eOptionEnemyEncounterEscape = 1,
60 eOptionEnemyEncounterDefeat = 2,
61 };
62
63 enum ShopSubcommand {
64 eOptionShopTransaction = 0,
65 eOptionShopNoTransaction = 1,
66 };
67
68 enum InnSubcommand {
69 eOptionInnStay = 0,
70 eOptionInnNoStay = 1,
71 };
72
SetState(const lcf::rpg::SaveEventExecState & save)73 void Game_Interpreter_Map::SetState(const lcf::rpg::SaveEventExecState& save) {
74 Clear();
75 _state = save;
76 _keyinput.fromSave(save);
77 }
78
OnMapChange()79 void Game_Interpreter_Map::OnMapChange() {
80 // When we change the map, we reset all event id's to 0.
81 for (auto& frame: _state.stack) {
82 frame.event_id = 0;
83 }
84 }
85
86 /**
87 * Execute Command.
88 */
ExecuteCommand()89 bool Game_Interpreter_Map::ExecuteCommand() {
90 auto& frame = GetFrame();
91 const auto& com = frame.commands[frame.current_command];
92
93 switch (static_cast<Cmd>(com.code)) {
94 case Cmd::RecallToLocation:
95 return CommandRecallToLocation(com);
96 case Cmd::EnemyEncounter:
97 return CommandEnemyEncounter(com);
98 case Cmd::VictoryHandler:
99 return CommandVictoryHandler(com);
100 case Cmd::EscapeHandler:
101 return CommandEscapeHandler(com);
102 case Cmd::DefeatHandler:
103 return CommandDefeatHandler(com);
104 case Cmd::EndBattle:
105 return CommandEndBattle(com);
106 case Cmd::OpenShop:
107 return CommandOpenShop(com);
108 case Cmd::Transaction:
109 return CommandTransaction(com);
110 case Cmd::NoTransaction:
111 return CommandNoTransaction(com);
112 case Cmd::EndShop:
113 return CommandEndShop(com);
114 case Cmd::ShowInn:
115 return CommandShowInn(com);
116 case Cmd::Stay:
117 return CommandStay(com);
118 case Cmd::NoStay:
119 return CommandNoStay(com);
120 case Cmd::EndInn:
121 return CommandEndInn(com);
122 case Cmd::EnterHeroName:
123 return CommandEnterHeroName(com);
124 case Cmd::Teleport:
125 return CommandTeleport(com);
126 case Cmd::EnterExitVehicle:
127 return CommandEnterExitVehicle(com);
128 case Cmd::PanScreen:
129 return CommandPanScreen(com);
130 case Cmd::ShowBattleAnimation:
131 return CommandShowBattleAnimation(com);
132 case Cmd::FlashSprite:
133 return CommandFlashSprite(com);
134 case Cmd::ProceedWithMovement:
135 return CommandProceedWithMovement(com);
136 case Cmd::HaltAllMovement:
137 return CommandHaltAllMovement(com);
138 case Cmd::PlayMovie:
139 return CommandPlayMovie(com);
140 case Cmd::OpenSaveMenu:
141 return CommandOpenSaveMenu(com);
142 case Cmd::OpenMainMenu:
143 return CommandOpenMainMenu(com);
144 case Cmd::OpenLoadMenu:
145 return CommandOpenLoadMenu(com);
146 case Cmd::ToggleAtbMode:
147 return CommandToggleAtbMode(com);
148 case Cmd::OpenVideoOptions:
149 return CommandOpenVideoOptions(com);
150 default:
151 return Game_Interpreter::ExecuteCommand();
152 }
153 }
154
155 /**
156 * Commands
157 */
CommandRecallToLocation(lcf::rpg::EventCommand const & com)158 bool Game_Interpreter_Map::CommandRecallToLocation(lcf::rpg::EventCommand const& com) { // Code 10830
159 if (Game_Message::IsMessageActive()) {
160 return false;
161 }
162
163 auto& frame = GetFrame();
164 auto& index = frame.current_command;
165
166 int var_map_id = com.parameters[0];
167 int var_x = com.parameters[1];
168 int var_y = com.parameters[2];
169 int map_id = Main_Data::game_variables->Get(var_map_id);
170 int x = Main_Data::game_variables->Get(var_x);
171 int y = Main_Data::game_variables->Get(var_y);
172
173 auto tt = main_flag ? TeleportTarget::eForegroundTeleport : TeleportTarget::eParallelTeleport;
174
175 Main_Data::game_player->ReserveTeleport(map_id, x, y, -1, tt);
176
177 // Parallel events should keep on running in 2k and 2k3, unlike in later versions
178 if (!main_flag)
179 return true;
180
181 index++;
182 return false;
183 }
184
CommandEnemyEncounter(lcf::rpg::EventCommand const & com)185 bool Game_Interpreter_Map::CommandEnemyEncounter(lcf::rpg::EventCommand const& com) { // code 10710
186 auto& frame = GetFrame();
187 auto& index = frame.current_command;
188
189 if (Game_Message::IsMessageActive()) {
190 return false;
191 }
192
193 BattleArgs args;
194
195 args.troop_id = ValueOrVariable(com.parameters[0], com.parameters[1]);
196
197 switch (com.parameters[2]) {
198 case 0:
199 Game_Map::SetupBattle(args);
200 break;
201 case 1:
202 args.background = ToString(com.string);
203
204 if (Player::IsRPG2k3()) {
205 args.formation = static_cast<lcf::rpg::System::BattleFormation>(com.parameters[7]);
206 }
207 break;
208 case 2:
209 args.terrain_id = com.parameters[8];
210 break;
211 default:
212 return false;
213 }
214 auto escape_mode = com.parameters[3]; // 0 disallow, 1 end event processing, 2 victory/escape custom handler
215 auto defeat_mode = com.parameters[4]; // 0 game over, 1 victory/defeat custom handler
216
217 if (escape_mode == 1) {
218 _state.abort_on_escape = true;
219 }
220
221 args.allow_escape = (escape_mode != 0);
222 args.first_strike = com.parameters[5] != 0;
223
224 if (Player::IsRPG2k3()) {
225 args.condition = static_cast<lcf::rpg::System::BattleCondition>(com.parameters[6]);
226 }
227
228 auto indent = com.indent;
229 auto continuation = [this, indent, defeat_mode](BattleResult result) {
230 int sub_idx = subcommand_sentinel;
231
232 switch (result) {
233 case BattleResult::Victory:
234 sub_idx = eOptionEnemyEncounterVictory;
235 break;
236 case BattleResult::Escape:
237 sub_idx = eOptionEnemyEncounterEscape;
238 if (_state.abort_on_escape) {
239 return EndEventProcessing();
240 }
241 break;
242 case BattleResult::Defeat:
243 sub_idx = eOptionEnemyEncounterDefeat;
244 if (defeat_mode == 0) {
245 Scene::Push(std::make_shared<Scene_Gameover>());
246 }
247 break;
248 case BattleResult::Abort:
249 break;
250 }
251
252 SetSubcommandIndex(indent, sub_idx);
253 };
254
255 args.on_battle_end = continuation;
256
257 Scene::instance->SetRequestedScene(Scene_Battle::Create(std::move(args)));
258
259 // save game compatibility with RPG_RT
260 ReserveSubcommandIndex(com.indent);
261
262 ++index;
263 return false;
264 }
265
CommandVictoryHandler(lcf::rpg::EventCommand const & com)266 bool Game_Interpreter_Map::CommandVictoryHandler(lcf::rpg::EventCommand const& com) { // code 20710
267 return CommandOptionGeneric(com, eOptionEnemyEncounterVictory, {Cmd::EscapeHandler, Cmd::DefeatHandler, Cmd::EndBattle});
268 }
269
CommandEscapeHandler(lcf::rpg::EventCommand const & com)270 bool Game_Interpreter_Map::CommandEscapeHandler(lcf::rpg::EventCommand const& com) { // code 20711
271 return CommandOptionGeneric(com, eOptionEnemyEncounterEscape, {Cmd::DefeatHandler, Cmd::EndBattle});
272 }
273
CommandDefeatHandler(lcf::rpg::EventCommand const & com)274 bool Game_Interpreter_Map::CommandDefeatHandler(lcf::rpg::EventCommand const& com) { // code 20712
275 return CommandOptionGeneric(com, eOptionEnemyEncounterDefeat, {Cmd::EndBattle});
276 }
277
CommandEndBattle(lcf::rpg::EventCommand const &)278 bool Game_Interpreter_Map::CommandEndBattle(lcf::rpg::EventCommand const& /* com */) { // code 20713
279 return true;
280 }
281
CommandOpenShop(lcf::rpg::EventCommand const & com)282 bool Game_Interpreter_Map::CommandOpenShop(lcf::rpg::EventCommand const& com) { // code 10720
283 auto& frame = GetFrame();
284 auto& index = frame.current_command;
285
286 if (Game_Message::IsMessageActive()) {
287 return false;
288 }
289
290 bool allow_buy = false;
291 bool allow_sell = false;
292
293 switch (com.parameters[0]) {
294 case 0:
295 allow_buy = true;
296 allow_sell = true;
297 break;
298 case 1:
299 allow_buy = true;
300 break;
301 case 2:
302 allow_sell = true;
303 break;
304 default:
305 break;
306 }
307
308 auto shop_type = com.parameters[1];
309
310 // Not used, but left here for documentation purposes
311 //bool has_shop_handlers = com.parameters[2] != 0;
312
313 std::vector<int> goods;
314 for (auto it = com.parameters.begin() + 4; it < com.parameters.end(); ++it) {
315 goods.push_back(*it);
316 }
317
318 auto indent = com.indent;
319 auto continuation = [this, indent](bool did_transaction) {
320 int sub_idx = did_transaction ? eOptionShopTransaction : eOptionShopNoTransaction;
321 SetSubcommandIndex(indent, sub_idx);
322 };
323
324 auto scene = std::make_shared<Scene_Shop>(
325 std::move(goods), shop_type, allow_buy, allow_sell, std::move(continuation));
326
327 Scene::instance->SetRequestedScene(std::move(scene));
328
329 // save game compatibility with RPG_RT
330 ReserveSubcommandIndex(com.indent);
331
332 ++index;
333 return false;
334 }
335
CommandTransaction(lcf::rpg::EventCommand const & com)336 bool Game_Interpreter_Map::CommandTransaction(lcf::rpg::EventCommand const& com) { // code 20720
337 return CommandOptionGeneric(com, eOptionShopTransaction, {Cmd::NoTransaction, Cmd::EndShop});
338 }
339
CommandNoTransaction(lcf::rpg::EventCommand const & com)340 bool Game_Interpreter_Map::CommandNoTransaction(lcf::rpg::EventCommand const& com) { // code 20721
341 return CommandOptionGeneric(com, eOptionShopNoTransaction, {Cmd::EndShop});
342 }
343
CommandEndShop(lcf::rpg::EventCommand const &)344 bool Game_Interpreter_Map::CommandEndShop(lcf::rpg::EventCommand const& /* com */) { // code 20722
345 return true;
346 }
347
CommandShowInn(lcf::rpg::EventCommand const & com)348 bool Game_Interpreter_Map::CommandShowInn(lcf::rpg::EventCommand const& com) { // code 10730
349 int inn_type = com.parameters[0];
350 auto inn_price = com.parameters[1];
351 // Not used, but left here for documentation purposes
352 // bool has_inn_handlers = com.parameters[2] != 0;
353
354 if (inn_price == 0) {
355 if (Game_Message::IsMessageActive()) {
356 return false;
357 }
358
359 // Skip prompt.
360 _async_op = ContinuationShowInnStart(com.indent, 0, inn_price);
361 return true;
362 }
363
364 // Emulates RPG_RT behavior (Bug?) Inn's called by parallel events
365 // overwrite the current message.
366 if (main_flag && !Game_Message::CanShowMessage(main_flag)) {
367 return false;
368 }
369
370 auto pm = PendingMessage();
371
372 StringView greeting_1, greeting_2, greeting_3, accept, cancel;
373
374 switch (inn_type) {
375 case 0:
376 greeting_1 = lcf::Data::terms.inn_a_greeting_1;
377 greeting_2 = lcf::Data::terms.inn_a_greeting_2;
378 greeting_3 = lcf::Data::terms.inn_a_greeting_3;
379 accept = lcf::Data::terms.inn_a_accept;
380 cancel = lcf::Data::terms.inn_a_cancel;
381 break;
382 case 1:
383 greeting_1 = lcf::Data::terms.inn_b_greeting_1;
384 greeting_2 = lcf::Data::terms.inn_b_greeting_2;
385 greeting_3 = lcf::Data::terms.inn_b_greeting_3;
386 accept = lcf::Data::terms.inn_b_accept;
387 cancel = lcf::Data::terms.inn_b_cancel;
388 break;
389 }
390
391 if (Player::IsRPG2kE()) {
392 auto price_s = std::to_string(inn_price);
393 pm.PushLine(
394 Utils::ReplacePlaceholders(
395 greeting_1,
396 Utils::MakeArray('V', 'U'),
397 Utils::MakeSvArray(price_s, lcf::Data::terms.gold)
398 )
399 );
400 pm.PushLine(
401 Utils::ReplacePlaceholders(
402 greeting_3,
403 Utils::MakeArray('V', 'U'),
404 Utils::MakeSvArray(price_s, lcf::Data::terms.gold)
405 )
406 );
407 }
408 else {
409 pm.PushLine(fmt::format("{} {}{} {}", greeting_1, inn_price, lcf::Data::terms.gold, greeting_2));
410 pm.PushLine(ToString(greeting_3));
411 }
412
413 bool can_afford = (Main_Data::game_party->GetGold() >= inn_price);
414 pm.SetChoiceResetColors(true);
415
416 pm.PushChoice(ToString(accept), can_afford);
417 pm.PushChoice(ToString(cancel));
418
419 pm.SetShowGoldWindow(true);
420
421 int indent = com.indent;
422 pm.SetChoiceContinuation([this, indent, inn_price](int choice_result) {
423 return ContinuationShowInnStart(indent, choice_result, inn_price);
424 });
425
426 // save game compatibility with RPG_RT
427 ReserveSubcommandIndex(com.indent);
428
429 Game_Message::SetPendingMessage(std::move(pm));
430 _state.show_message = true;
431
432 return true;
433 }
434
ContinuationShowInnStart(int indent,int choice_result,int price)435 AsyncOp Game_Interpreter_Map::ContinuationShowInnStart(int indent, int choice_result, int price) {
436 bool inn_stay = (choice_result == 0);
437
438 SetSubcommandIndex(indent, inn_stay ? eOptionInnStay : eOptionInnNoStay);
439
440 if (inn_stay) {
441 Main_Data::game_party->GainGold(-price);
442
443 return AsyncOp::MakeCallInn();
444 }
445 return {};
446 }
447
CommandStay(lcf::rpg::EventCommand const & com)448 bool Game_Interpreter_Map::CommandStay(lcf::rpg::EventCommand const& com) { // code 20730
449 return CommandOptionGeneric(com, eOptionInnStay, {Cmd::NoStay, Cmd::EndInn});
450 }
451
CommandNoStay(lcf::rpg::EventCommand const & com)452 bool Game_Interpreter_Map::CommandNoStay(lcf::rpg::EventCommand const& com) { // code 20731
453 return CommandOptionGeneric(com, eOptionInnNoStay, {Cmd::EndInn});
454 }
455
CommandEndInn(lcf::rpg::EventCommand const &)456 bool Game_Interpreter_Map::CommandEndInn(lcf::rpg::EventCommand const& /* com */) { // code 20732
457 return true;
458 }
459
CommandEnterHeroName(lcf::rpg::EventCommand const & com)460 bool Game_Interpreter_Map::CommandEnterHeroName(lcf::rpg::EventCommand const& com) { // code 10740
461 auto& frame = GetFrame();
462 auto& index = frame.current_command;
463
464 if (Game_Message::IsMessageActive()) {
465 return false;
466 }
467
468 auto actor_id = com.parameters[0];
469 auto charset = com.parameters[1];
470 auto use_default_name = com.parameters[2];
471
472 auto scene = std::make_shared<Scene_Name>(actor_id, charset, use_default_name);
473 Scene::instance->SetRequestedScene(std::move(scene));
474
475 ++index;
476 return false;
477 }
478
CommandTeleport(lcf::rpg::EventCommand const & com)479 bool Game_Interpreter_Map::CommandTeleport(lcf::rpg::EventCommand const& com) { // Code 10810
480 // TODO: if in battle return true
481 if (Game_Message::IsMessageActive()) {
482 return false;
483 }
484
485 auto& frame = GetFrame();
486 auto& index = frame.current_command;
487
488 int map_id = com.parameters[0];
489 int x = com.parameters[1];
490 int y = com.parameters[2];
491
492 // RPG2k3 feature
493 int direction = com.parameters.size() > 3 ? com.parameters[3] - 1 : -1;
494
495 auto tt = main_flag ? TeleportTarget::eForegroundTeleport : TeleportTarget::eParallelTeleport;
496
497 Main_Data::game_player->ReserveTeleport(map_id, x, y, direction, tt);
498
499 // Parallel events should keep on running in 2k and 2k3, unlike in later versions
500 if (!main_flag)
501 return true;
502
503 index++;
504 return false;
505 }
506
CommandEnterExitVehicle(lcf::rpg::EventCommand const &)507 bool Game_Interpreter_Map::CommandEnterExitVehicle(lcf::rpg::EventCommand const& /* com */) { // code 10840
508 Main_Data::game_player->GetOnOffVehicle();
509
510 return true;
511 }
512
CommandPanScreen(lcf::rpg::EventCommand const & com)513 bool Game_Interpreter_Map::CommandPanScreen(lcf::rpg::EventCommand const& com) { // code 11060
514 int direction;
515 int distance;
516 int speed;
517 bool waiting_pan_screen = false;
518
519 auto& player = *Main_Data::game_player;
520
521 switch (com.parameters[0]) {
522 case 0: // Lock
523 player.LockPan();
524 break;
525 case 1: // Unlock
526 player.UnlockPan();
527 break;
528 case 2: // Pan
529 direction = com.parameters[1];
530 distance = com.parameters[2];
531 // FIXME: For an "instant pan" Yume2kki passes a huge value (53) here
532 // which crashes depending on the hardware
533 speed = Utils::Clamp<int>(com.parameters[3], 1, 6);
534 waiting_pan_screen = com.parameters[4] != 0;
535 player.StartPan(direction, distance, speed);
536 break;
537 case 3: // Reset
538 speed = Utils::Clamp<int>(com.parameters[3], 1, 6);
539 waiting_pan_screen = com.parameters[4] != 0;
540 player.ResetPan(speed);
541 distance = std::max(
542 std::abs(player.GetPanX() - player.GetTargetPanX())
543 , std::abs(player.GetPanY() - player.GetTargetPanY()));
544 distance /= SCREEN_TILE_SIZE;
545 break;
546 }
547
548 if (waiting_pan_screen) {
549 // RPG_RT uses the max wait for all pending pan commands, not just the current one.
550 _state.wait_time = player.GetPanWait();
551 }
552
553 return true;
554 }
555
CommandShowBattleAnimation(lcf::rpg::EventCommand const & com)556 bool Game_Interpreter_Map::CommandShowBattleAnimation(lcf::rpg::EventCommand const& com) { // code 11210
557 int animation_id = com.parameters[0];
558 int evt_id = com.parameters[1];
559 bool waiting_battle_anim = com.parameters[2] > 0;
560 bool global = com.parameters[3] > 0;
561
562 Game_Character* chara = GetCharacter(evt_id);
563 if (chara == NULL)
564 return true;
565
566 if (evt_id == Game_Character::CharThisEvent)
567 evt_id = GetThisEventId();
568
569 int frames = Main_Data::game_screen->ShowBattleAnimation(animation_id, evt_id, global);
570
571 if (waiting_battle_anim) {
572 _state.wait_time = frames;
573 }
574
575 return true;
576 }
577
CommandFlashSprite(lcf::rpg::EventCommand const & com)578 bool Game_Interpreter_Map::CommandFlashSprite(lcf::rpg::EventCommand const& com) { // code 11320
579 int event_id = com.parameters[0];
580 int r = com.parameters[1];
581 int g = com.parameters[2];
582 int b = com.parameters[3];
583 int p = com.parameters[4];
584
585 int tenths = com.parameters[5];
586 bool wait = com.parameters[6] > 0;
587 Game_Character* event = GetCharacter(event_id);
588
589 if (event != NULL) {
590 event->Flash(r, g, b, p, tenths * DEFAULT_FPS / 10);
591
592 if (wait) {
593 SetupWait(tenths);
594 }
595 }
596
597 return true;
598 }
599
CommandProceedWithMovement(lcf::rpg::EventCommand const &)600 bool Game_Interpreter_Map::CommandProceedWithMovement(lcf::rpg::EventCommand const& /* com */) { // code 11340
601 _state.wait_movement = true;
602 return true;
603 }
604
CommandHaltAllMovement(lcf::rpg::EventCommand const &)605 bool Game_Interpreter_Map::CommandHaltAllMovement(lcf::rpg::EventCommand const& /* com */) { // code 11350
606 Game_Map::RemoveAllPendingMoves();
607 return true;
608 }
609
CommandPlayMovie(lcf::rpg::EventCommand const & com)610 bool Game_Interpreter_Map::CommandPlayMovie(lcf::rpg::EventCommand const& com) { // code 11560
611 if (Game_Message::IsMessageActive()) {
612 return false;
613 }
614
615 auto filename = ToString(com.string);
616 int pos_x = ValueOrVariable(com.parameters[0], com.parameters[1]);
617 int pos_y = ValueOrVariable(com.parameters[0], com.parameters[2]);
618 int res_x = com.parameters[3];
619 int res_y = com.parameters[4];
620
621 Output::Warning("Couldn't play movie: {}. Movie playback is not implemented (yet).", filename);
622
623 Main_Data::game_screen->PlayMovie(filename, pos_x, pos_y, res_x, res_y);
624
625 return true;
626 }
627
CommandOpenSaveMenu(lcf::rpg::EventCommand const &)628 bool Game_Interpreter_Map::CommandOpenSaveMenu(lcf::rpg::EventCommand const& /* com */) { // code 11910
629 auto& frame = GetFrame();
630 auto& index = frame.current_command;
631
632 if (Game_Message::IsMessageActive()) {
633 return false;
634 }
635
636 Scene::instance->SetRequestedScene(std::make_shared<Scene_Save>());
637 ++index;
638 return false;
639 }
640
CommandOpenMainMenu(lcf::rpg::EventCommand const &)641 bool Game_Interpreter_Map::CommandOpenMainMenu(lcf::rpg::EventCommand const& /* com */) { // code 11950
642 auto& frame = GetFrame();
643 auto& index = frame.current_command;
644
645 if (Game_Message::IsMessageActive()) {
646 return false;
647 }
648
649 Scene::instance->SetRequestedScene(std::make_shared<Scene_Menu>());
650 ++index;
651 return false;
652 }
653
CommandOpenLoadMenu(lcf::rpg::EventCommand const &)654 bool Game_Interpreter_Map::CommandOpenLoadMenu(lcf::rpg::EventCommand const& /* com */) {
655 auto& frame = GetFrame();
656 auto& index = frame.current_command;
657
658 if (Game_Message::IsMessageActive()) {
659 return false;
660 }
661
662 Scene::instance->SetRequestedScene(std::make_shared<Scene_Load>());
663 ++index;
664 return false;
665 }
666
CommandToggleAtbMode(lcf::rpg::EventCommand const &)667 bool Game_Interpreter_Map::CommandToggleAtbMode(lcf::rpg::EventCommand const& /* com */) {
668 Main_Data::game_system->ToggleAtbMode();
669 return true;
670 }
671
CommandOpenVideoOptions(lcf::rpg::EventCommand const &)672 bool Game_Interpreter_Map::CommandOpenVideoOptions(lcf::rpg::EventCommand const& /* com */) {
673 if (Game_Message::IsMessageActive()) {
674 return false;
675 }
676
677 Output::Warning("OpenVideoOptions: Command not supported");
678 return true;
679 }
680
681