Browse Source

Refactored "StartWalk(...)" into different functions and moved tightly coupled "Direction" parameters into an array.

pull/2217/head
Matheus Gomes 5 years ago committed by Anders Jenbo
parent
commit
5ee7edbde1
  1. 352
      Source/player.cpp

352
Source/player.cpp

@ -28,6 +28,187 @@
namespace devilution {
namespace {
struct DirectionSettings {
Direction dir;
Point tileAdd;
Point offset;
Point map;
_scroll_direction scrollDir;
PLR_MODE walkMode;
void (*walkModeHandler)(int, Point, const DirectionSettings &);
};
void PM_ChangeLightOff(PlayerStruct &player)
{
if (player._plid == NO_LIGHT)
return;
const LightListStruct *l = &LightList[player._plid];
int x = 2 * player.position.offset.y + player.position.offset.x;
int y = 2 * player.position.offset.y - player.position.offset.x;
x = (x / 8) * (x < 0 ? 1 : -1);
y = (y / 8) * (y < 0 ? 1 : -1);
int lx = x + (l->position.tile.x * 8);
int ly = y + (l->position.tile.y * 8);
int offx = l->position.offset.x + (l->position.tile.x * 8);
int offy = l->position.offset.y + (l->position.tile.y * 8);
if (abs(lx - offx) < 3 && abs(ly - offy) < 3)
return;
ChangeLightOff(player._plid, { x, y });
}
void WalkUpwards(int pnum, Point vel, const DirectionSettings &walkParams)
{
auto &player = plr[pnum];
dPlayer[player.position.future.x][player.position.future.y] = -(pnum + 1);
player.position.temp = walkParams.tileAdd;
}
void WalkDownwards(int pnum, Point vel, const DirectionSettings &walkParams)
{
auto &player = plr[pnum];
dPlayer[player.position.tile.x][player.position.tile.y] = -(pnum + 1);
player.position.temp = player.position.tile;
player.position.tile = player.position.future; // Move player to the next tile to maintain correct render order
dPlayer[player.position.tile.x][player.position.tile.y] = pnum + 1;
ChangeLightXY(player._plid, player.position.tile);
PM_ChangeLightOff(player);
}
void WalkSides(int pnum, Point vel, const DirectionSettings &walkParams)
{
auto &player = plr[pnum];
Point const nextPosition = walkParams.map + player.position.tile;
dPlayer[player.position.tile.x][player.position.tile.y] = -(pnum + 1);
dPlayer[player.position.future.x][player.position.future.y] = -(pnum + 1);
player._pVar4 = nextPosition.x;
player._pVar5 = nextPosition.y;
dFlags[nextPosition.x][nextPosition.y] |= BFLAG_PLAYERLR;
if (leveltype != DTYPE_TOWN) {
ChangeLightXY(player._plid, nextPosition);
PM_ChangeLightOff(player);
}
player.position.temp = player.position.future;
}
static constexpr std::array<const DirectionSettings, 8> directionSettings { {
// clang-format off
{ DIR_S, { 1, 1 }, { 0, -32 }, { 0, 0 }, SDIR_S, PM_WALK2, WalkDownwards },
{ DIR_SW, { 0, 1 }, { 32, -16 }, { 0, 0 }, SDIR_SW, PM_WALK2, WalkDownwards },
{ DIR_W, { -1, 1 }, { 32, -16 }, { 0, 1 }, SDIR_W, PM_WALK3, WalkSides },
{ DIR_NW, { -1, 0 }, { 0, 0 }, { 0, 0 }, SDIR_NW, PM_WALK, WalkUpwards },
{ DIR_N, { -1, -1 }, { 0, 0 }, { 0, 0 }, SDIR_N, PM_WALK, WalkUpwards },
{ DIR_NE, { 0, -1 }, { 0, 0 }, { 0, 0 }, SDIR_NE, PM_WALK, WalkUpwards },
{ DIR_E, { 1, -1 }, { -32, -16 }, { 1, 0 }, SDIR_E, PM_WALK3, WalkSides },
{ DIR_SE, { 1, 0 }, { -32, -16 }, { 0, 0 }, SDIR_SE, PM_WALK2, WalkDownwards }
// clang-format on
} };
void ScrollViewPort(const PlayerStruct &player, _scroll_direction dir)
{
ScrollInfo.tile.x = player.position.tile.x - ViewX;
ScrollInfo.tile.y = player.position.tile.y - ViewY;
if (zoomflag) {
if (abs(ScrollInfo.tile.x) >= 3 || abs(ScrollInfo.tile.y) >= 3) {
ScrollInfo._sdir = SDIR_NONE;
} else {
ScrollInfo._sdir = dir;
}
} else if (abs(ScrollInfo.tile.x) >= 2 || abs(ScrollInfo.tile.y) >= 2) {
ScrollInfo._sdir = SDIR_NONE;
} else {
ScrollInfo._sdir = dir;
}
}
bool PlrDirOK(int pnum, Direction dir)
{
if ((DWORD)pnum >= MAX_PLRS) {
app_fatal("PlrDirOK: illegal player %i", pnum);
}
auto &player = plr[pnum];
Point position = player.position.tile;
Point futurePosition = position + dir;
if (futurePosition.x < 0 || !dPiece[futurePosition.x][futurePosition.y] || !PosOkPlayer(pnum, futurePosition)) {
return false;
}
if (dir == DIR_E) {
return !SolidLoc(position + DIR_SE) && !(dFlags[position.x + 1][position.y] & BFLAG_PLAYERLR);
}
if (dir == DIR_W) {
return !SolidLoc(position + DIR_SW) && !(dFlags[position.x][position.y + 1] & BFLAG_PLAYERLR);
}
return true;
}
void HandleWalkMode(int pnum, Point vel, Direction dir)
{
auto &player = plr[pnum];
const auto &dirModeParams = directionSettings[dir];
SetPlayerOld(player);
if (!PlrDirOK(pnum, dir)) {
return;
}
player.position.offset = dirModeParams.offset; // Offset player sprite to align with their previous tile position
//The player's tile position after finishing this movement action
player.position.future = dirModeParams.tileAdd + player.position.tile;
dirModeParams.walkModeHandler(pnum, vel, dirModeParams);
player.position.velocity = vel;
player.tempDirection = dirModeParams.dir;
player._pmode = dirModeParams.walkMode;
player.position.offset2 = dirModeParams.offset * 256;
player._pdir = dir;
}
void StartWalkAnimation(PlayerStruct &player, Direction dir, bool pmWillBeCalled)
{
int skippedFrames = -2;
if (currlevel == 0 && sgGameInitInfo.bRunInTown)
skippedFrames = 2;
if (pmWillBeCalled)
skippedFrames += 1;
NewPlrAnim(player, player_graphic::Walk, dir, player._pWFrames, 0, AnimationDistributionFlags::ProcessAnimationPending, skippedFrames);
}
/**
* @brief Start moving a player to a new tile
*/
void StartWalk(int pnum, Point vel, Direction dir, bool pmWillBeCalled)
{
auto &player = plr[pnum];
if (player._pInvincible && player._pHitPoints == 0 && pnum == myplr) {
SyncPlrKill(pnum, -1);
return;
}
HandleWalkMode(pnum, vel, dir);
StartWalkAnimation(player, dir, pmWillBeCalled);
if (pnum == myplr) {
ScrollViewPort(player, directionSettings[dir].scrollDir);
}
}
} // namespace
int myplr;
PlayerStruct plr[MAX_PLRS];
bool deathflag;
@ -1129,33 +1310,6 @@ bool SolidLoc(Point position)
return nSolidTable[dPiece[position.x][position.y]];
}
bool PlrDirOK(int pnum, Direction dir)
{
bool isOk;
if ((DWORD)pnum >= MAX_PLRS) {
app_fatal("PlrDirOK: illegal player %i", pnum);
}
auto &player = plr[pnum];
Point position = player.position.tile;
Point futurePosition = position + dir;
if (futurePosition.x < 0 || !dPiece[futurePosition.x][futurePosition.y] || !PosOkPlayer(pnum, futurePosition)) {
return false;
}
isOk = true;
if (dir == DIR_E) {
isOk = !SolidLoc(position + DIR_SE) && !(dFlags[position.x + 1][position.y] & BFLAG_PLAYERLR);
}
if (isOk && dir == DIR_W) {
isOk = !SolidLoc(position + DIR_SW) && !(dFlags[position.x][position.y + 1] & BFLAG_PLAYERLR);
}
return isOk;
}
void PlrClrTrans(Point position)
{
int i, j;
@ -1247,28 +1401,6 @@ void StartWalkStand(int pnum)
}
}
static void PM_ChangeLightOff(PlayerStruct &player)
{
if (player._plid == NO_LIGHT)
return;
const LightListStruct *l = &LightList[player._plid];
int x = 2 * player.position.offset.y + player.position.offset.x;
int y = 2 * player.position.offset.y - player.position.offset.x;
x = (x / 8) * (x < 0 ? 1 : -1);
y = (y / 8) * (y < 0 ? 1 : -1);
int lx = x + (l->position.tile.x * 8);
int ly = y + (l->position.tile.y * 8);
int offx = l->position.offset.x + (l->position.tile.x * 8);
int offy = l->position.offset.y + (l->position.tile.y * 8);
if (abs(lx - offx) < 3 && abs(ly - offy) < 3)
return;
ChangeLightOff(player._plid, { x, y });
}
void PM_ChangeOffset(int pnum)
{
if ((DWORD)pnum >= MAX_PLRS) {
@ -1298,112 +1430,6 @@ void PM_ChangeOffset(int pnum)
PM_ChangeLightOff(player);
}
/**
* @brief Start moving a player to a new tile
*/
void StartWalk(int pnum, int xvel, int yvel, int xoff, int yoff, int xadd, int yadd, int mapx, int mapy, Direction EndDir, _scroll_direction sdir, int variant, bool pmWillBeCalled)
{
auto &player = plr[pnum];
if (player._pInvincible && player._pHitPoints == 0 && pnum == myplr) {
SyncPlrKill(pnum, -1);
return;
}
SetPlayerOld(player);
if (!PlrDirOK(pnum, EndDir)) {
return;
}
//The player's tile position after finishing this movement action
int px = xadd + player.position.tile.x;
int py = yadd + player.position.tile.y;
player.position.future = { px, py };
//If this is the local player then update the camera offset position
if (pnum == myplr) {
ScrollInfo.tile.x = player.position.tile.x - ViewX;
ScrollInfo.tile.y = player.position.tile.y - ViewY;
}
switch (variant) {
case PM_WALK:
dPlayer[px][py] = -(pnum + 1);
player._pmode = PM_WALK;
player.position.velocity = { xvel, yvel };
player.position.offset = { 0, 0 };
player.position.temp = { xadd, yadd };
player.tempDirection = EndDir;
player.position.offset2 = { 0, 0 };
break;
case PM_WALK2:
dPlayer[player.position.tile.x][player.position.tile.y] = -(pnum + 1);
player.position.temp = player.position.tile;
player.position.tile = { px, py }; // Move player to the next tile to maintain correct render order
dPlayer[player.position.tile.x][player.position.tile.y] = pnum + 1;
player.position.offset = { xoff, yoff }; // Offset player sprite to align with their previous tile position
ChangeLightXY(player._plid, player.position.tile);
PM_ChangeLightOff(player);
player._pmode = PM_WALK2;
player.position.velocity = { xvel, yvel };
player.position.offset2 = { xoff * 256, yoff * 256 };
player.tempDirection = EndDir;
break;
case PM_WALK3:
int x = mapx + player.position.tile.x;
int y = mapy + player.position.tile.y;
dPlayer[player.position.tile.x][player.position.tile.y] = -(pnum + 1);
dPlayer[px][py] = -(pnum + 1);
player._pVar4 = x;
player._pVar5 = y;
dFlags[x][y] |= BFLAG_PLAYERLR;
player.position.offset = { xoff, yoff }; // Offset player sprite to align with their previous tile position
if (leveltype != DTYPE_TOWN) {
ChangeLightXY(player._plid, { x, y });
PM_ChangeLightOff(player);
}
player._pmode = PM_WALK3;
player.position.velocity = { xvel, yvel };
player.position.temp = { px, py };
player.position.offset2 = { xoff * 256, yoff * 256 };
player.tempDirection = EndDir;
break;
}
//Start walk animation
int skippedFrames = -2;
if (currlevel == 0 && sgGameInitInfo.bRunInTown)
skippedFrames = 2;
if (pmWillBeCalled)
skippedFrames += 1;
NewPlrAnim(player, player_graphic::Walk, EndDir, player._pWFrames, 0, AnimationDistributionFlags::ProcessAnimationPending, skippedFrames);
player._pdir = EndDir;
if (pnum != myplr) {
return;
}
if (zoomflag) {
if (abs(ScrollInfo.tile.x) >= 3 || abs(ScrollInfo.tile.y) >= 3) {
ScrollInfo._sdir = SDIR_NONE;
} else {
ScrollInfo._sdir = sdir;
}
} else if (abs(ScrollInfo.tile.x) >= 2 || abs(ScrollInfo.tile.y) >= 2) {
ScrollInfo._sdir = SDIR_NONE;
} else {
ScrollInfo._sdir = sdir;
}
}
void StartAttack(int pnum, Direction d)
{
if ((DWORD)pnum >= MAX_PLRS) {
@ -3027,28 +3053,28 @@ void CheckNewPath(int pnum, bool pmWillBeCalled)
switch (player.walkpath[0]) {
case WALK_N:
StartWalk(pnum, 0, -xvel, 0, 0, -1, -1, 0, 0, DIR_N, SDIR_N, PM_WALK, pmWillBeCalled);
StartWalk(pnum, { 0, -xvel }, DIR_N, pmWillBeCalled);
break;
case WALK_NE:
StartWalk(pnum, xvel, -yvel, 0, 0, 0, -1, 0, 0, DIR_NE, SDIR_NE, PM_WALK, pmWillBeCalled);
StartWalk(pnum, { xvel, -yvel }, DIR_NE, pmWillBeCalled);
break;
case WALK_E:
StartWalk(pnum, xvel3, 0, -32, -16, 1, -1, 1, 0, DIR_E, SDIR_E, PM_WALK3, pmWillBeCalled);
StartWalk(pnum, { xvel3, 0 }, DIR_E, pmWillBeCalled);
break;
case WALK_SE:
StartWalk(pnum, xvel, yvel, -32, -16, 1, 0, 0, 0, DIR_SE, SDIR_SE, PM_WALK2, pmWillBeCalled);
StartWalk(pnum, { xvel, yvel }, DIR_SE, pmWillBeCalled);
break;
case WALK_S:
StartWalk(pnum, 0, xvel, 0, -32, 1, 1, 0, 0, DIR_S, SDIR_S, PM_WALK2, pmWillBeCalled);
StartWalk(pnum, { 0, xvel }, DIR_S, pmWillBeCalled);
break;
case WALK_SW:
StartWalk(pnum, -xvel, yvel, 32, -16, 0, 1, 0, 0, DIR_SW, SDIR_SW, PM_WALK2, pmWillBeCalled);
StartWalk(pnum, { -xvel, yvel }, DIR_SW, pmWillBeCalled);
break;
case WALK_W:
StartWalk(pnum, -xvel3, 0, 32, -16, -1, 1, 0, 1, DIR_W, SDIR_W, PM_WALK3, pmWillBeCalled);
StartWalk(pnum, { -xvel3, 0 }, DIR_W, pmWillBeCalled);
break;
case WALK_NW:
StartWalk(pnum, -xvel, -yvel, 0, 0, -1, 0, 0, 0, DIR_NW, SDIR_NW, PM_WALK, pmWillBeCalled);
StartWalk(pnum, { -xvel, -yvel }, DIR_NW, pmWillBeCalled);
break;
}

Loading…
Cancel
Save