#include "game_player.h" #include "doctest.h" #include "options.h" #include "game_map.h" #include "game_vehicle.h" #include "main_data.h" #include "game_switches.h" #include #include #include "test_move_route.h" TEST_SUITE_BEGIN("MoveRoute"); lcf::rpg::MoveRoute MakeRoute(std::initializer_list cmds, bool repeat = false, bool skip = false) { lcf::rpg::MoveRoute mr; mr.move_commands = cmds; mr.repeat = repeat; mr.skippable = skip; return mr; } static void testMoveRoute( const Game_Character& ch, bool paused, int move_frequency, int stop_count, int max_stop_count, int move_route_idx, bool overwritten, bool done, const lcf::rpg::MoveRoute& mr) { CAPTURE(paused); CAPTURE(move_frequency); CAPTURE(stop_count); CAPTURE(max_stop_count); CAPTURE(move_route_idx); CAPTURE(overwritten); CAPTURE(done); CAPTURE(mr); REQUIRE_EQ(ch.IsPaused(), paused); REQUIRE_EQ(ch.GetMoveFrequency(), move_frequency); REQUIRE_EQ(ch.GetStopCount(), stop_count); REQUIRE_EQ(ch.GetMaxStopCount(), max_stop_count); REQUIRE_EQ(ch.GetMoveRouteIndex(), move_route_idx); REQUIRE_EQ(ch.IsMoveRouteOverwritten(), overwritten); REQUIRE_EQ(ch.IsMoveRouteRepeated(), done); REQUIRE_EQ(ch.GetMoveRoute(), mr); REQUIRE_EQ(ch.IsStopCountActive(), stop_count < max_stop_count); } template static void testMoveRouteDir(const Game_Character& ch, int dir, int face, Args&&... args) { CAPTURE(dir); CAPTURE(face); REQUIRE_EQ(ch.GetDirection(), dir); REQUIRE_EQ(ch.GetFacing(), face); testMoveRoute(ch, std::forward(args)...); } template static void testMoveRouteMove(const Game_Character& ch, int x, int y, int remaining_step, Args&&... args) { CAPTURE(x); CAPTURE(y); CAPTURE(remaining_step); REQUIRE_EQ(ch.GetX(), x); REQUIRE_EQ(ch.GetY(), y); REQUIRE_GE(ch.GetRemainingStep(), 0); REQUIRE_EQ(ch.GetRemainingStep(), remaining_step); REQUIRE(!ch.IsJumping()); if (remaining_step > 0) { REQUIRE(ch.IsMoving()); } else { REQUIRE(ch.IsStopping()); REQUIRE(!ch.IsMoving()); } testMoveRouteDir(ch, std::forward(args)...); } template static void testMoveRouteJump(const Game_Character& ch, int x, int y, int remaining_step, bool is_jumping, int begin_jump_x, int begin_jump_y, Args&&... args) { CAPTURE(x); CAPTURE(y); CAPTURE(remaining_step); CAPTURE(is_jumping); CAPTURE(begin_jump_x); CAPTURE(begin_jump_y); REQUIRE_EQ(ch.GetX(), x); REQUIRE_EQ(ch.GetY(), y); REQUIRE_GE(ch.GetRemainingStep(), 0); REQUIRE_EQ(ch.GetRemainingStep(), remaining_step); REQUIRE_EQ(ch.GetBeginJumpX(), begin_jump_x); REQUIRE_EQ(ch.GetBeginJumpY(), begin_jump_y); if (remaining_step > 0) { REQUIRE_EQ(ch.IsJumping(), is_jumping); REQUIRE_EQ(ch.IsMoving(), !is_jumping); } else { REQUIRE(ch.IsStopping()); REQUIRE(!ch.IsJumping()); REQUIRE(!ch.IsMoving()); } testMoveRouteDir(ch, std::forward(args)...); } TEST_CASE("DefaultMoveRoute") { auto ch = MoveRouteVehicle(); testMoveRoute(ch, false, 2, 0, 0, 0, false, false, lcf::rpg::MoveRoute()); } TEST_CASE("ForceMoveRouteEmpty") { auto ch = MoveRouteVehicle(); ch.ForceMoveRoute(lcf::rpg::MoveRoute(), 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, false, false, lcf::rpg::MoveRoute()); } TEST_CASE("ForceMoveRouteSameFreq") { auto ch = MoveRouteVehicle(); lcf::rpg::MoveRoute mr; mr.move_commands.push_back({}); ch.ForceMoveRoute(mr, 2); // Note: Same freq means don't reset max stop count testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); ch.CancelMoveRoute(); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, false, false, mr); } TEST_CASE("ForceMoveRouteDiffFreq") { auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{}}); mr.move_commands.push_back({}); ch.ForceMoveRoute(mr, 3); testMoveRoute(ch, false, 3, 0xFFFF, 64, 0, true, false, mr); // FIXME: Test original move frequency is robust to save games ch.CancelMoveRoute(); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, false, false, mr); } static void testInvalidCmd(bool repeat, bool skip) { auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ -1 }}, repeat, skip); ch.ForceMoveRoute(mr, 3); testMoveRoute(ch, false, 3, 0xFFFF, 64, 0, true, false, mr); ForceUpdate(ch); if (repeat) { testMoveRoute(ch, false, 3, 0xFFFF + 1, 64, 0, true, true, mr); } else { testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); } } TEST_CASE("TestMoveRouteInvalidCmd") { const MapGuard mg; testInvalidCmd(false, false); testInvalidCmd(false, true); testInvalidCmd(true, false); testInvalidCmd(true, true); } template static void testMove(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tx, int ty, int tdir, int tface, int px = 0, int py = 0) { Main_Data::game_player->SetX(px); Main_Data::game_player->SetY(py); auto ch = MoveRouteVehicle(); ch.SetX(x); ch.SetY(y); ch.SetDirection(dir); ch.SetFacing(face); ch.SetAllowMovement(success); auto mr = MakeRoute({{ static_cast(code) }}, repeat, skip); CAPTURE(code); CAPTURE(x); CAPTURE(y); CAPTURE(dir); CAPTURE(face); CAPTURE(tx); CAPTURE(ty); CAPTURE(tdir); CAPTURE(tface); CAPTURE(px); CAPTURE(py); CAPTURE(success); CAPTURE(repeat); CAPTURE(skip); auto dx = tx - x; auto dy = ty - y; ch.ForceMoveRoute(mr, 3); testMoveRouteMove(ch, x, y, 0, dir, face, false, 3, 0xFFFF, 64, 0, true, false, mr); if (success) { bool repeated = false; for(int n = (repeat ? 3 : 1); n > 0; --n) { CAPTURE(n); for(int i = 224; i > 0; i -= 32) { ForceUpdate(ch); testMoveRouteMove(ch, tx, ty, i, tdir, tface, false, 3, 0, 64, 1, true, repeated, mr); } if (!repeat) { ForceUpdate(ch); testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 2, 0, 128, 0, false, false, mr); break; } repeated = true; for (int i = 0; i <= 64; ++i) { ForceUpdate(ch); testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, i, 64, 0, true, repeated, mr); } tx += dx; ty += dy; } } else { ForceUpdate(ch); if (skip) { if (repeat) { for (int i = 1; i <= 3; ++i) { testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, 0xFFFF + i, 64, 0, true, true, mr); ForceUpdate(ch); } } else { testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); } } else { testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, 0xFFFF + 1, 64, 0, true, false, mr); } } } template static void testMoveSuccess(const Args&... args) { testMove(args...); testMove(args...); testMove(args...); testMove(args...); } template static void testMoveSuccessNoRepeat(const Args&... args) { testMove(args...); testMove(args...); } static void testMoveFail(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tdir, int tface, int px = 0, int py = 0) { testMove(code, x, y, dir, face, x, y, tdir, tface, px, py); testMove(code, x, y, dir, face, x, y, tdir, tface, px, py); } static void testMoveSkip(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int px = 0, int py = 0) { testMove(code, x, y, dir, face, x, y, dir, face, px, py); testMove(code, x, y, dir, face, x, y, dir, face, px, py); } TEST_CASE("CommandMove") { const MapGuard mg; testMoveSuccess(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, 8, 7, Up, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, 9, 8, Right, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, 8, 9, Down, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, 7, 8, Left, Left); } TEST_CASE("CommandMoveFail") { const MapGuard mg; testMoveFail(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, Up, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, Right, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, Down, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, Left, Left); } TEST_CASE("CommandMoveSkip") { const MapGuard mg; testMoveSkip(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down); } TEST_CASE("CommandMoveDiagonal") { const MapGuard mg; testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, 9, 7, UpRight, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, 9, 7, UpRight, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, 9, 7, UpRight, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, 9, 7, UpRight, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, 9, 9, DownRight, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, 9, 9, DownRight, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, 9, 9, DownRight, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, 9, 9, DownRight, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, 7, 9, DownLeft, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, 7, 9, DownLeft, Left); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, 7, 9, DownLeft, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, 7, 9, DownLeft, Left); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, 7, 7, UpLeft, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, 7, 7, UpLeft, Left); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, 7, 7, UpLeft, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, 7, 7, UpLeft, Left); } TEST_CASE("CommandMoveDiagonalFail") { const MapGuard mg; testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, UpRight, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, UpRight, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, UpRight, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, UpRight, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, DownRight, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, DownRight, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, DownRight, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, DownRight, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, DownLeft, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, DownLeft, Left); testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, DownLeft, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, DownLeft, Left); testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, UpLeft, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, UpLeft, Left); testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, UpLeft, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, UpLeft, Left); } TEST_CASE("CommandMoveDiagonalSkip") { const MapGuard mg; testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left); } TEST_CASE("CommandMoveForward") { const MapGuard mg; testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, 8, 7, Up, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, 9, 8, Right, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, 8, 9, Down, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, 7, 8, Left, Left); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, 9, 7, UpRight, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, 9, 7, UpRight, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, 9, 9, DownRight, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, 9, 9, DownRight, Right); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, 7, 7, UpLeft, Up); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, 7, 7, UpLeft, Left); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, 7, 9, DownLeft, Down); testMoveSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, 7, 9, DownLeft, Left); } TEST_CASE("CommandMoveForwardFail") { const MapGuard mg; testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, Up, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, Right, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, Down, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, Left, Left); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, UpRight, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, UpRight, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, DownRight, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, DownRight, Right); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, UpLeft, Up); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, UpLeft, Left); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, DownLeft, Down); testMoveFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, DownLeft, Left); } TEST_CASE("CommandMoveForwardSkip") { const MapGuard mg; testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down); testMoveSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left); } TEST_CASE("CommandMoveRandom") { // FIXME: TBD } static void testTurn(lcf::rpg::MoveCommand::Code code, int orig_dir, int dir, int face, int x = 0, int y = 0, int px = 0, int py = 0) { Main_Data::game_player->SetX(px); Main_Data::game_player->SetY(py); auto ch = MoveRouteVehicle(); ch.SetX(x); ch.SetY(y); ch.SetDirection(orig_dir); ch.SetFacing(orig_dir); auto mr = MakeRoute({{ static_cast(code) }}); CAPTURE(code); CAPTURE(orig_dir); CAPTURE(dir); CAPTURE(face); CAPTURE(x); CAPTURE(y); CAPTURE(px); CAPTURE(py); ch.ForceMoveRoute(mr, 2); testMoveRouteDir(ch, orig_dir, orig_dir, false, 2, 0xFFFF, 0, 0, true, false, mr); for(int i = 1; i <= 64; ++i) { ForceUpdate(ch); testMoveRouteDir(ch, dir, face, false, 2, i, 64, 1, true, false, mr); } ForceUpdate(ch); testMoveRouteDir(ch, dir, face, false, 2, 65, 128, 1, false, false, mr); } TEST_CASE("CommandTurn") { const MapGuard mg; testTurn(lcf::rpg::MoveCommand::Code::face_up, Down, Up, Up); testTurn(lcf::rpg::MoveCommand::Code::face_left, Down, Left, Left); testTurn(lcf::rpg::MoveCommand::Code::face_right, Down, Right, Right); testTurn(lcf::rpg::MoveCommand::Code::face_down, Down, Down, Down); testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Down, Up, Up); testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Up, Down, Down); testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Left, Right, Right); testTurn(lcf::rpg::MoveCommand::Code::turn_180_degree, Right, Left, Left); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Down, Left, Left); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Left, Up, Up); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Up, Right, Right); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_right, Right, Down, Down); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Down, Right, Right); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Right, Up, Up); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Up, Left, Left); testTurn(lcf::rpg::MoveCommand::Code::turn_90_degree_left, Left, Down, Down); } TEST_CASE("CommandTurnRandom") { const MapGuard mg; for (int i = 0; i < 10; ++i) { auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::face_random_direction) }}); ch.ForceMoveRoute(mr, 3); testMoveRouteDir(ch, Down, Down, false, 3, 0xFFFF, 64, 0, true, false, mr); ForceUpdate(ch); testMoveRoute(ch, false, 3, 1, 32, 1, true, false, mr); REQUIRE_GE(ch.GetDirection(), Up); REQUIRE_LE(ch.GetDirection(), Left); } } TEST_CASE("CommandWait") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::wait) }}); ch.ForceMoveRoute(mr, 2); testMoveRouteDir(ch, Down, Down, false, 2, 0xFFFF, 0, 0, true, false, mr); for(int i = 1; i <= 84; ++i) { ForceUpdate(ch); testMoveRouteDir(ch, Down, Down, false, 2, i, 84, 1, true, false, mr); } ForceUpdate(ch); testMoveRouteDir(ch, Down, Down, false, 2, 85, 128, 1, false, false, mr); } template static void testJump(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tx, int ty, int tdir, int tface, int px = 0, int py = 0) { Main_Data::game_player->SetX(px); Main_Data::game_player->SetY(py); auto ch = MoveRouteVehicle(); ch.SetX(x); ch.SetY(y); ch.SetDirection(dir); ch.SetFacing(face); ch.SetAllowMovement(success); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::begin_jump) }}, repeat, skip); if (code != lcf::rpg::MoveCommand::Code::end_jump) { mr.move_commands.push_back({ static_cast(code) }); } if (end) { mr.move_commands.push_back({ static_cast(lcf::rpg::MoveCommand::Code::end_jump) }); } auto num_cmds = static_cast(mr.move_commands.size()); CAPTURE(code); CAPTURE(x); CAPTURE(y); CAPTURE(dir); CAPTURE(face); CAPTURE(tx); CAPTURE(ty); CAPTURE(tdir); CAPTURE(tface); CAPTURE(px); CAPTURE(py); CAPTURE(success); CAPTURE(repeat); CAPTURE(skip); auto dx = tx - x; auto dy = ty - y; ch.ForceMoveRoute(mr, 3); testMoveRouteJump(ch, x, y, 0, false, 0, 0, dir, face, false, 3, 0xFFFF, 64, 0, true, false, mr); if (!end) { ForceUpdate(ch); if (repeat) { testMoveRouteJump(ch, x, y, 0, false, 0, 0, dir, face, false, 3, 0xFFFF + 1, 64, 0, true, true, mr); } else { testMoveRouteJump(ch, x, y, 0, false, 0, 0, dir, face, false, 2, 0xFFFF + 1, 128, num_cmds, false, false, mr); } return; } if (success) { bool repeated = false; for(int n = (repeat ? 3 : 1); n > 0; --n) { CAPTURE(n); for(int i = 232; i > 0; i -= 24) { ForceUpdate(ch); testMoveRouteJump(ch, tx, ty, i, true, x, y, tdir, tface, false, 3, 0, 64, num_cmds, true, repeated, mr); } if (!repeat) { ForceUpdate(ch); testMoveRouteJump(ch, tx, ty, 0, false, x, y, tdir, tface, false, 2, 0, 128, 0, false, false, mr); break; } repeated = true; for (int i = 0; i <= 64; ++i) { ForceUpdate(ch); testMoveRouteMove(ch, tx, ty, 0, tdir, tface, false, 3, i, 64, 0, true, repeated, mr); } x = tx; y = ty; tx += dx; ty += dy; } } else { ForceUpdate(ch); if (skip) { if (repeat) { for (int i = 1; i <= 3; ++i) { testMoveRouteJump(ch, tx, ty, 0, false, 0, 0, tdir, tface, false, 3, 0xFFFF + i, 64, 0, true, true, mr); ForceUpdate(ch); } } else { testMoveRouteJump(ch, tx, ty, 0, false, 0, 0, tdir, tface, false, 2, 0xFFFF + 1, 128, num_cmds, false, false, mr); } } else { testMoveRouteJump(ch, tx, ty, 0, false, 0, 0, tdir, tface, false, 3, 0xFFFF + 1, 64, 0, true, false, mr); } } } template static void testJumpSuccess(const Args&... args) { testJump(args...); testJump(args...); testJump(args...); testJump(args...); } template static void testJumpSuccessNoRepeat(const Args&... args) { testJump(args...); testJump(args...); } static void testJumpFail(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int tdir, int tface, int px = 0, int py = 0) { testJump(code, x, y, dir, face, x, y, tdir, tface, px, py); testJump(code, x, y, dir, face, x, y, tdir, tface, px, py); } static void testJumpSkip(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int px = 0, int py = 0) { testJump(code, x, y, dir, face, x, y, dir, face, px, py); testJump(code, x, y, dir, face, x, y, dir, face, px, py); } static void testJumpNoEnd(lcf::rpg::MoveCommand::Code code, int x, int y, int dir, int face, int px = 0, int py = 0) { testJump(code, x, y, dir, face, x, y, dir, face, px, py); testJump(code, x, y, dir, face, x, y, dir, face, px, py); } TEST_CASE("CommandJumpInPlace") { const MapGuard mg; // FIXME: Verify this behavior testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Up, Up, 8, 8, Down, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Right, Right, 8, 8, Down, Right); testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Down, Down, 8, 8, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Left, Left, 8, 8, Down, Left); // FIXME: Test no collision } TEST_CASE("CommandJump") { const MapGuard mg; testJumpSuccess(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, 8, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, 9, 8, Right, Right); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, 8, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, 7, 8, Left, Left); } TEST_CASE("CommandJumpFail") { const MapGuard mg; testJumpFail(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down, Right, Right); testJumpFail(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down, Left, Left); } TEST_CASE("CommandJumpSkip") { const MapGuard mg; testJumpSkip(lcf::rpg::MoveCommand::Code::move_up, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_right, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_down, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_left, 8, 8, Down, Down); } TEST_CASE("CommandJumpDiagonal") { const MapGuard mg; testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, 9, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, 9, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, 9, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, 9, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, 9, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, 9, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, 9, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, 9, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, 7, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, 7, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, 7, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, 7, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, 7, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, 7, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, 7, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, 7, 7, Up, Up); } TEST_CASE("CommandJumpDiagonalFail") { const MapGuard mg; testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left, Up, Up); } TEST_CASE("CommandJumpDiagonalSkip") { const MapGuard mg; testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Up, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Right, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upright, 8, 8, Left, Left); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Up, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Right, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downright, 8, 8, Left, Left); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Up, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Right, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_downleft, 8, 8, Left, Left); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Up, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Right, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_upleft, 8, 8, Left, Left); } TEST_CASE("CommandJumpForward") { const MapGuard mg; testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, 8, 7, Up, Up); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, 9, 8, Right, Right); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, 8, 9, Down, Down); testJumpSuccess(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, 7, 8, Left, Left); // FIXME: For repeat, these will move diag and then up or down afterwards. testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, 9, 7, Up, Up); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, 9, 7, Up, Up); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, 9, 9, Down, Down); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, 9, 9, Down, Down); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, 7, 7, Up, Up); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, 7, 7, Up, Up); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, 7, 9, Down, Down); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, 7, 9, Down, Down); } TEST_CASE("CommandJumpForwardFail") { const MapGuard mg; testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right, Right, Right); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left, Left, Left); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left, Up, Up); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down, Down, Down); testJumpFail(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left, Down, Down); } TEST_CASE("CommandJumpForwardSkip") { const MapGuard mg; testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Up, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Right, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Down, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, Left, Left); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpRight, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownRight, Right); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Up); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, UpLeft, Left); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Down); testJumpSkip(lcf::rpg::MoveCommand::Code::move_forward, 8, 8, DownLeft, Left); } TEST_CASE("CommandJumpRandom") { // FIXME: TBD } TEST_CASE("CommandJumpNoEnd") { const MapGuard mg; // This makes a move route with just "Jump" testJumpNoEnd(lcf::rpg::MoveCommand::Code::end_jump, 8, 8, Down, Down); } TEST_CASE("CommandMoveTurnJumpHero") { const MapGuard mg; int x = 8; int y = 8; for (int dx = -2; dx <= 2; ++dx) { for (int dy = -2; dy <= 2; ++dy) { auto step_x = 0; auto step_y = 0; auto dir = Down; if (std::abs(dx) > std::abs(dy)) { dir = (dx > 0 ? Right : Left); step_x = (dx > 0 ? 1 : -1); } else { dir = (dy >= 0 ? Down : Up); step_y = (dy >= 0 ? 1 : -1); } auto rdir = Game_Character::GetDirection180Degree(dir); auto px = x + dx; auto py = y + dy; testTurn(lcf::rpg::MoveCommand::Code::face_hero, Left, dir, dir, x, y, px, py); testTurn(lcf::rpg::MoveCommand::Code::face_away_from_hero, Left, rdir, rdir, x, y, px, py); testMoveSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, x + step_x, y + step_y, dir, dir, px, py); testMoveSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, x - step_x, y - step_y, rdir, rdir, px, py); testMoveFail(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, dir, dir, px, py); testMoveFail(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, rdir, rdir, px, py); testMoveSkip(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, px, py); testMoveSkip(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, px, py); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, x + step_x, y + step_y, dir, dir, px, py); testJumpSuccessNoRepeat(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, x - step_x, y - step_y, rdir, rdir, px, py); testJumpFail(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, dir, dir, px, py); testJumpFail(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, rdir, rdir, px, py); testJumpSkip(lcf::rpg::MoveCommand::Code::move_towards_hero, x, y, Left, Left, px, py); testJumpSkip(lcf::rpg::MoveCommand::Code::move_away_from_hero, x, y, Left, Left, px, py); } } } void testLockFacing(lcf::rpg::EventPage::AnimType at) { const MapGuard mg; auto ch = MoveRouteVehicle(); ch.SetAnimationType(at); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::lock_facing) }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); REQUIRE_EQ(ch.IsFacingLocked(), Game_Character::IsDirectionFixedAnimationType(at)); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE(ch.IsFacingLocked()); mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::unlock_facing) }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); REQUIRE(ch.IsFacingLocked()); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE_EQ(ch.IsFacingLocked(), Game_Character::IsDirectionFixedAnimationType(at)); } TEST_CASE("CommandLockFacing") { for (int i = 0; i <= static_cast(lcf::rpg::EventPage::AnimType_step_frame_fix); ++i) { testLockFacing(static_cast(i)); } } TEST_CASE("CommandSpeedChange") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::increase_movement_speed) }}); const int n = 10; ch.SetMoveSpeed(1); int prev = ch.GetMoveSpeed(); for (int i = 0; i < 10; ++i) { ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, (i == 0 ? 0 : 128), 0, true, false, mr); REQUIRE_EQ(ch.GetMoveSpeed(), prev); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE_EQ(ch.GetMoveSpeed(), std::min(prev + 1, 6)); prev= ch.GetMoveSpeed(); } mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::decrease_movement_speed) }}); for (int i = 0; i < 10; ++i) { ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); REQUIRE_EQ(ch.GetMoveSpeed(), prev); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE_EQ(ch.GetMoveSpeed(), std::max(prev - 1, 1)); prev= ch.GetMoveSpeed(); } } TEST_CASE("CommandFreqChange") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::increase_movement_frequence) }}); const int n = 10; for (int i = 1; i < 10; ++i) { const int freq = Utils::Clamp(i, 1, 8); ch.ForceMoveRoute(mr, freq); testMoveRoute(ch, false, freq, 0xFFFF, (i == 0 && freq == 2 ? 0 : Game_Character::GetMaxStopCountForStep(freq)), 0, true, false, mr); const int next_freq = Utils::Clamp(freq + 1, 1, 8); ForceUpdate(ch); // FIXME: Need another command for the frequency to not get reset when move route is done. //testMoveRoute(ch, false, next_freq, 0xFFFF + 1, Game_Character::GetMaxStopCountForStep(next_freq), 1, false, false, mr); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); } mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::decrease_movement_frequence) }}); for (int i = 1; i < 10; ++i) { const int freq = Utils::Clamp(i, 1, 8); ch.ForceMoveRoute(mr, freq); testMoveRoute(ch, false, freq, 0xFFFF, Game_Character::GetMaxStopCountForStep(freq), 0, true, false, mr); const int next_freq = Utils::Clamp(freq - 1, 1, 8); ForceUpdate(ch); // FIXME: Need another command for the frequency to not get reset when move route is done. //testMoveRoute(ch, false, next_freq, 0xFFFF + 1, Game_Character::GetMaxStopCountForStep(next_freq), 1, false, false, mr); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); } } TEST_CASE("CommandTranspChange") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::increase_transp) }}); const int n = 10; ch.SetTransparency(0); int prev = ch.GetTransparency(); for (int i = 0; i < 10; ++i) { ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, (i == 0 ? 0 : 128), 0, true, false, mr); REQUIRE_EQ(ch.GetTransparency(), prev); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE_EQ(ch.GetTransparency(), std::min(prev + 1, 7)); prev = ch.GetTransparency(); } mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::decrease_transp) }}); for (int i = 0; i < 10; ++i) { ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); REQUIRE_EQ(ch.GetTransparency(), prev); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE_EQ(ch.GetTransparency(), std::max(prev - 1, 0)); prev = ch.GetTransparency(); } } TEST_CASE("CommandThrough") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::walk_everywhere_on) }}); auto testoff = [&]() { REQUIRE(!ch.GetThrough()); ch.SetThrough(true); REQUIRE(ch.GetThrough()); ch.ResetThrough(); REQUIRE(!ch.GetThrough()); }; auto teston = [&]() { REQUIRE(ch.GetThrough()); ch.SetThrough(false); REQUIRE(!ch.GetThrough()); ch.ResetThrough(); REQUIRE(ch.GetThrough()); }; ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); testoff(); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); teston(); mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::walk_everywhere_off) }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); teston(); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); testoff(); ch.SetThrough(true); mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::walk_everywhere_off) }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); REQUIRE(ch.GetThrough()); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); testoff(); ch.SetThrough(true); mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::walk_everywhere_on) }}); ch.ForceMoveRoute(mr, 2); REQUIRE(ch.GetThrough()); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); teston(); } TEST_CASE("CommandStopAnimation") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::stop_animation) }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); REQUIRE(!ch.IsAnimPaused()); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE(ch.IsAnimPaused()); mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::start_animation) }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); REQUIRE(ch.IsAnimPaused()); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE(!ch.IsAnimPaused()); } TEST_CASE("CommandSwitchToggle") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::switch_on), "", 3 }}); REQUIRE_NE(Main_Data::game_switches, nullptr); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); REQUIRE(!Main_Data::game_switches->Get(3)); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE(Main_Data::game_switches->Get(3)); mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::switch_off), "", 3 }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 128, 0, true, false, mr); REQUIRE(Main_Data::game_switches->Get(3)); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE(!Main_Data::game_switches->Get(3)); } TEST_CASE("CommandChangeGraphic") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::change_graphic), "x", 3 }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); REQUIRE_EQ(ch.GetSpriteName(), ""); REQUIRE_EQ(ch.GetSpriteIndex(), 0); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); REQUIRE_EQ(ch.GetSpriteName(), "x"); REQUIRE_EQ(ch.GetSpriteIndex(), 3); } TEST_CASE("CommandPlaySound") { const MapGuard mg; auto ch = MoveRouteVehicle(); auto mr = MakeRoute({{ static_cast(lcf::rpg::MoveCommand::Code::play_sound_effect), "", 100, 100, 100 }}); ch.ForceMoveRoute(mr, 2); testMoveRoute(ch, false, 2, 0xFFFF, 0, 0, true, false, mr); ForceUpdate(ch); testMoveRoute(ch, false, 2, 0xFFFF + 1, 128, 1, false, false, mr); // FIXME: Check mocked audio subsystem? } TEST_CASE("ClearPause") { auto ch = MoveRouteVehicle(); ch.SetPaused(true); REQUIRE(ch.IsPaused()); auto mr = MakeRoute({{}}); ch.ForceMoveRoute(mr, 3); REQUIRE(!ch.IsPaused()); } TEST_SUITE_END();