Files

1189 lines
44 KiB
C++

#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 <climits>
#include <initializer_list>
#include <lcf/rpg/movecommand.h>
#include "test_move_route.h"
TEST_SUITE_BEGIN("MoveRoute");
lcf::rpg::MoveRoute MakeRoute(int code, bool repeat = false, bool skip = false) {
lcf::rpg::MoveRoute mr;
lcf::rpg::MoveCommand mc;
mc.command_id = code;
mr.move_commands = { mc };
mr.repeat = repeat;
mr.skippable = skip;
return mr;
}
lcf::rpg::MoveRoute MakeRoute(std::initializer_list<lcf::rpg::MoveCommand> 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.IsMoveRouteFinished(), done);
REQUIRE_EQ(ch.GetMoveRoute(), mr);
REQUIRE_EQ(ch.IsStopCountActive(), stop_count < max_stop_count);
}
template <typename... Args>
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>(args)...);
}
template <typename... Args>
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>(args)...);
}
template <typename... Args>
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>(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 <bool success, bool repeat, bool skip>
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<int>(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 <typename... Args>
static void testMoveSuccess(const Args&... args) {
testMove<true, false, false>(args...);
testMove<true, false, true>(args...);
testMove<true, true, false>(args...);
testMove<true, true, true>(args...);
}
template <typename... Args>
static void testMoveSuccessNoRepeat(const Args&... args) {
testMove<true, false, false>(args...);
testMove<true, false, true>(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<false, false, false>(code, x, y, dir, face, x, y, tdir, tface, px, py);
testMove<false, true, false>(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<false, false, true>(code, x, y, dir, face, x, y, dir, face, px, py);
testMove<false, true, true>(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<int>(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<int>(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<int>(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 <bool success, bool repeat, bool skip, bool end>
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<int>(lcf::rpg::MoveCommand::Code::begin_jump), repeat, skip);
if (code != lcf::rpg::MoveCommand::Code::end_jump) {
lcf::rpg::MoveCommand mc;
mc.command_id = static_cast<int>(code);
mr.move_commands.push_back(mc);
}
if (end) {
lcf::rpg::MoveCommand mc;
mc.command_id = static_cast<int>(lcf::rpg::MoveCommand::Code::end_jump);
mr.move_commands.push_back(mc);
}
auto num_cmds = static_cast<int>(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 <typename... Args>
static void testJumpSuccess(const Args&... args) {
testJump<true, false, false, true>(args...);
testJump<true, false, true, true>(args...);
testJump<true, true, false, true>(args...);
testJump<true, true, true, true>(args...);
}
template <typename... Args>
static void testJumpSuccessNoRepeat(const Args&... args) {
testJump<true, false, false, true>(args...);
testJump<true, false, true, true>(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<false, false, false, true>(code, x, y, dir, face, x, y, tdir, tface, px, py);
testJump<false, true, false, true>(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<false, false, true, true>(code, x, y, dir, face, x, y, dir, face, px, py);
testJump<false, true, true, true>(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<false, false, true, false>(code, x, y, dir, face, x, y, dir, face, px, py);
testJump<false, true, true, false>(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<int>(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<int>(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<int>(lcf::rpg::EventPage::AnimType_step_frame_fix); ++i) {
testLockFacing(static_cast<lcf::rpg::EventPage::AnimType>(i));
}
}
TEST_CASE("CommandSpeedChange") {
const MapGuard mg;
auto ch = MoveRouteVehicle();
auto mr = MakeRoute(static_cast<int>(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<int>(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<int>(lcf::rpg::MoveCommand::Code::increase_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, (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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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<int>(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();