Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions src/game_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
{
}

int Game_Character::GetId() const {
// This should be overridden by subclasses that have a meaningful ID.
// Returning 0 for the base class is a safe default.
return 0;
}

void Game_Character::SanitizeData(std::string_view name) {
SanitizeMoveRoute(name, data()->move_route, data()->move_route_index, "move_route_index");
}
Expand Down Expand Up @@ -445,6 +451,49 @@
case Code::decrease_transp:
SetTransparency(GetTransparency() - 1);
break;
// START of Maniac Patch custom commands
case static_cast<Code>(100): // Custom: Set Speed

Check warning on line 455 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '100' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 455 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '100' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 455 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '100' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 455 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '100' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 455 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '100' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
SetMoveSpeed(move_command.parameter_a);
break;
case static_cast<Code>(101): // Custom: Set Freq

Check warning on line 458 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '101' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 458 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '101' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 458 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '101' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 458 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '101' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 458 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '101' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
SetMoveFrequency(move_command.parameter_a);
SetMaxStopCountForStep();
break;
case static_cast<Code>(102): // Custom: Set Transparency

Check warning on line 462 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '102' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 462 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '102' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 462 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '102' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 462 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '102' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 462 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '102' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
SetTransparency(move_command.parameter_a);
break;
// END of Maniac Patch custom commands

// START of new custom "off-script" commands
case static_cast<Code>(110): // SetAnimationType

Check warning on line 468 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '110' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 468 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '110' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 468 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '110' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 468 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '110' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 468 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '110' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
SetAnimationType(static_cast<lcf::rpg::EventPage::AnimType>(move_command.parameter_a));
break;
case static_cast<Code>(111): { // Event2Event

Check warning on line 471 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '111' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 471 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '111' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 471 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '111' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 471 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '111' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 471 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '111' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
Game_Character* target = GetCharacter(move_command.parameter_a, GetId());
if (target) {
SetFacing(target->GetFacing());
SetDirection(target->GetDirection());
SetX(target->GetX());
SetY(target->GetY());
}
break;
}
case static_cast<Code>(112): { // FaceTowards

Check warning on line 481 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '112' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 481 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '112' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 481 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '112' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 481 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '112' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 481 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '112' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
Game_Character* target = GetCharacter(move_command.parameter_a, GetId());
if (target && !IsMoving()) {
TurnTowardCharacter(*target);
UpdateFacing();
}
break;
}
case static_cast<Code>(113): { // FaceAway

Check warning on line 489 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (x86_64)

case value '113' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 489 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:24.04 (arm64)

case value '113' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 489 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (arm64)

case value '113' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 489 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / ubuntu:22.04 (x86_64)

case value '113' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]

Check warning on line 489 in src/game_character.cpp

View workflow job for this annotation

GitHub Actions / debian:12 (x86_64)

case value '113' not in enumerated type 'const lcf::rpg::MoveCommand::Code' [-Wswitch]
Game_Character* target = GetCharacter(move_command.parameter_a, GetId());
if (target && !IsMoving()) {
TurnAwayFromCharacter(*target);
UpdateFacing();
}
break;
}
default:
break;
}
Expand Down Expand Up @@ -791,6 +840,14 @@
SetMoveRouteFinished(false);
}

void Game_Character::AppendMoveRoute(const lcf::rpg::MoveRoute& new_route) {
auto& current_commands = data()->move_route.move_commands;
const auto& new_commands = new_route.move_commands;
current_commands.insert(current_commands.end(), new_commands.begin(), new_commands.end());
// Do NOT overwrite repeat/skippable flags. They belong to the whole route.
SetMoveRouteFinished(false);
}

struct SearchNode {
int x = 0;
int y = 0;
Expand Down
5 changes: 5 additions & 0 deletions src/game_character.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class Game_Character {

static std::string_view TypeToStr(Type t);

virtual int GetId() const;

virtual ~Game_Character() = default;
Game_Character(Game_Character&&) = default;
Game_Character& operator=(const Game_Character&) = default;
Expand Down Expand Up @@ -700,6 +702,9 @@ class Game_Character {
*/
void ForceMoveRoute(const lcf::rpg::MoveRoute& new_route, int frequency);

/** Appends a move route to the current one */
void AppendMoveRoute(const lcf::rpg::MoveRoute & new_route);

/**
* Cancels a previous forced move route.
*/
Expand Down
172 changes: 156 additions & 16 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <ctime>
#include <iomanip>
#include <iostream>
#include <lcf/scope_guard.h>
#include <regex>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -47,6 +48,8 @@
#include "game_interpreter_control_variables.h"
#include "game_windows.h"
#include "json_helper.h"
#include "lcf/rpg/eventcommand.h"
#include "lcf/rpg/movecommand.h"
#include "maniac_patch.h"
#include "spriteset_map.h"
#include "sprite_character.h"
Expand Down Expand Up @@ -3174,29 +3177,166 @@ bool Game_Interpreter::CommandMoveEvent(lcf::rpg::EventCommand const& com) { //
int repeat = ManiacBitmask(com.parameters[2], 0x1);

Game_Character* event = GetCharacter(event_id, "MoveEvent");
if (event != NULL) {
// If the event is a vehicle in use, push the commands to the player instead
if (event_id >= Game_Character::CharBoat && event_id <= Game_Character::CharAirship)
if (static_cast<Game_Vehicle*>(event)->IsInUse())
event = Main_Data::game_player.get();
if (!event) {
return true;
}

lcf::rpg::MoveRoute route;
int move_freq = com.parameters[1];
// If the event is a vehicle in use, push the commands to the player instead
if (event_id >= Game_Character::CharBoat && event_id <= Game_Character::CharAirship)
if (static_cast<Game_Vehicle*>(event)->IsInUse())
event = Main_Data::game_player.get();

if (move_freq <= 0 || move_freq > 8) {
// Invalid values
move_freq = 6;
}
lcf::rpg::MoveRoute route;
int move_freq = com.parameters[1];

route.repeat = repeat != 0;
route.skippable = com.parameters[3] != 0;
if (move_freq <= 0 || move_freq > 8) {
// Invalid values
move_freq = 6;
}

for (auto it = com.parameters.begin() + 4; it < com.parameters.end(); ) {
route.move_commands.push_back(DecodeMove(it));
}
route.repeat = repeat != 0;
route.skippable = com.parameters[3] != 0;

for (auto it = com.parameters.begin() + 4; it < com.parameters.end(); ) {
route.move_commands.push_back(DecodeMove(it));
}

auto force_route = lcf::makeScopeGuard([&]() {
// Set the move route when the command ends
event->ForceMoveRoute(route, move_freq);
});

if (!Player::IsPatchManiac()) {
return true;
}

// Check for Add Move Route commands
auto add_command = [&](const lcf::rpg::MoveCommand& cmd, int repeat = 1) {
for (int i = 0; i < repeat; ++i) {
route.move_commands.push_back(cmd);
}
};
using Code = lcf::rpg::MoveCommand::Code;

auto& frame = GetFrame();
const auto& list = frame.commands;
auto& index = frame.current_command;

++index;
while (index < static_cast<int>(list.size())) {
const auto& next_cmd = ResolveEventCommand(list[index]);

if (static_cast<Cmd>(next_cmd.code) == Cmd::Maniac_AddMoveRoute) {
if (next_cmd.parameters.size() < 2) {
Output::Warning("AddMoveRoute: Command is missing action_type parameter.");
break;
}

int action_type = next_cmd.parameters[1];
lcf::rpg::MoveCommand cmd = {};

switch (action_type) {
case 0: { // .move(direction, distance) and specific moves like .moveUp(n)
cmd.command_id = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
int repeat = ValueOrVariableBitfield(next_cmd, 0, 2, 3);
if (next_cmd.parameters.size() <= 3) {
repeat = 1;
}
if (cmd.command_id >= static_cast<int32_t>(Code::move_up) && cmd.command_id <= static_cast<int32_t>(Code::move_forward)) {
add_command(cmd, repeat);
}
break;
}
case 1: { // .face(direction) and specific facings like .faceUp
int direction = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
cmd.command_id = direction + static_cast<int32_t>(Code::face_up); // Apply Offset

if (cmd.command_id >= static_cast<int32_t>(Code::face_up) && cmd.command_id <= static_cast<int32_t>(Code::face_away_from_hero)) {
add_command(cmd);
}
break;
}
case 2: // .pause
cmd.command_id = static_cast<int32_t>(Code::wait); // Wait
add_command(cmd);
break;
case 3: { // .jump(x_offset, y_offset)
int x_offset = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
int y_offset = ValueOrVariableBitfield(next_cmd, 0, 2, 3);

// TODO: Check this
cmd.command_id = static_cast<int32_t>(Code::begin_jump);
add_command(cmd);
cmd.command_id = (int32_t)((x_offset >= 0) ? lcf::rpg::MoveCommand::Code::move_right : lcf::rpg::MoveCommand::Code::move_left);
add_command(cmd, std::abs(x_offset));
cmd.command_id = (int32_t)((y_offset >= 0) ? lcf::rpg::MoveCommand::Code::move_down : lcf::rpg::MoveCommand::Code::move_up);
add_command(cmd, std::abs(y_offset));
cmd.command_id = static_cast<int32_t>(Code::end_jump);
add_command(cmd);
break;
}
case 4: { // Toggles like .fixDir/[on|off], .beginThrough/[on|off]
int toggle_type = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
bool is_on = ValueOrVariableBitfield(next_cmd, 0, 2, 3) != 0;
int base_cmd_id = 0;
switch (toggle_type) {
case 0: base_cmd_id = static_cast<int32_t>(Code::begin_jump); break; // Begin/End Jump
case 1: base_cmd_id = static_cast<int32_t>(Code::lock_facing); break; // Lock/Unlock Facing
case 2: base_cmd_id = static_cast<int32_t>(Code::walk_everywhere_on); break; // Through ON/OFF
case 3: base_cmd_id = static_cast<int32_t>(Code::stop_animation); break; // Stop/Start Animation
default: return true;
}
cmd.command_id = base_cmd_id + (is_on ? 0 : 1);
add_command(cmd);
break;
}
case 5: { // Direct setters like .speed(n), .freq(n), .trans(n)
int type = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
int value = ValueOrVariableBitfield(next_cmd, 0, 2, 3);
switch (type) {
case 0: cmd.command_id = 100; value += 4; break; // Custom: Set Speed
case 1: cmd.command_id = 101; break; // Custom: Set Freq
case 2: cmd.command_id = 102; break; // Custom: Set Transparency
default: return true;
}
cmd.parameter_a = value;
add_command(cmd);
break;
}
case 6: { // .switch(id, val)
cmd.parameter_a = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
cmd.command_id = ValueOrVariableBitfield(next_cmd, 0, 2, 3) != 0 ? static_cast<int32_t>(Code::switch_on) : static_cast<int32_t>(Code::switch_off); // Switch ON / OFF
add_command(cmd);
break;
}
case 7: { // .setBody("[name]", [index])
cmd.command_id = static_cast<int32_t>(Code::change_graphic);
cmd.parameter_string = lcf::DBString(CommandStringOrVariableBitfield(next_cmd, 0, 4, 5));
cmd.parameter_a = ValueOrVariableBitfield(next_cmd, 0, 1, 2);
add_command(cmd);
break;
}
case 8: { // .se("[name]", vol, pitch, balance)
cmd.command_id = static_cast<int32_t>(Code::play_sound_effect);
cmd.parameter_string = lcf::DBString(CommandStringOrVariableBitfield(next_cmd, 0, 5, 5));
cmd.parameter_a = next_cmd.parameters.size() > 2 ? ValueOrVariableBitfield(next_cmd, 0, 1, 2) : 100;
cmd.parameter_b = next_cmd.parameters.size() > 3 ? ValueOrVariableBitfield(next_cmd, 0, 2, 3) : 100;
cmd.parameter_c = next_cmd.parameters.size() > 4 ? ValueOrVariableBitfield(next_cmd, 0, 3, 4) : 50;
add_command(cmd);
break;
}
default:
Output::Warning("AddMoveRoute: Unknown action type {}", action_type);
break;
}

++index;
}
else {
break;
}
}

return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/game_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,12 @@ class Game_Interpreter : public Game_BaseInterpreterContext
bool CommandManiacControlStrings(lcf::rpg::EventCommand const& com);
bool CommandManiacWritePicture(lcf::rpg::EventCommand const& com);
bool CommandManiacCallCommand(lcf::rpg::EventCommand const& com);
bool CommandManiacGetGameInfo(lcf::rpg::EventCommand const& com);

bool CommandEasyRpgSetInterpreterFlag(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgProcessJson(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgCloneMapEvent(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgDestroyMapEvent(lcf::rpg::EventCommand const& com);
bool CommandManiacGetGameInfo(lcf::rpg::EventCommand const& com);

void SetSubcommandIndex(int indent, int idx);
uint8_t& ReserveSubcommandIndex(int indent);
Expand Down
1 change: 1 addition & 0 deletions src/game_interpreter_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <unordered_set>
#include "audio.h"
#include "feature.h"
#include "game_strings.h"
#include "game_character.h"
#include "game_map.h"
#include "game_battle.h"
Expand Down
6 changes: 0 additions & 6 deletions src/game_interpreter_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,6 @@ class Game_Interpreter_Map : public Game_Interpreter
bool CommandEasyRpgWaitForSingleMovement(lcf::rpg::EventCommand const& com);
AsyncOp ContinuationShowInnStart(int indent, int choice_result, int price);

bool CommandSmartMoveRoute(
lcf::rpg::EventCommand const& com,
int maxRouteStepsDefault, int maxSearchStepsDefault,
int abortIfAlreadyMovingDefault
); // Internal generic path finder function.

static std::vector<Game_Character*> pending;
};

Expand Down
2 changes: 2 additions & 0 deletions src/game_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class Game_Player : public Game_PlayerBase {
public:
Game_Player();

int GetId() const override { return CharPlayer; }

/** Load from saved game */
void SetSaveData(lcf::rpg::SavePartyLocation data);

Expand Down
2 changes: 2 additions & 0 deletions src/game_vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class Game_Vehicle : public Game_VehicleBase {

explicit Game_Vehicle(Type type);

int GetId() const override { return -data()->vehicle - 1; } // Boat:-2, Ship:-3, Airship:-4

/** Load from saved game */
void SetSaveData(lcf::rpg::SaveVehicleLocation save);

Expand Down
Loading