Browse Source

♻️ Replace manual direction displacement logic with 'Point' add operator

pull/2040/head
Juliano Leal Goncalves 5 years ago committed by Anders Jenbo
parent
commit
21fdb0dcd9
  1. 34
      Source/engine.h
  2. 22
      Source/inv.cpp
  3. 138
      Source/monster.cpp
  4. 2
      Source/monster.h
  5. 30
      Source/player.cpp

34
Source/engine.h

@ -91,6 +91,34 @@ struct Point {
return *this;
}
Point &operator+=(Direction direction)
{
constexpr auto toPoint = [](Direction direction) -> Point {
switch (direction) {
case DIR_S:
return { 1, 1 };
case DIR_SW:
return { 0, 1 };
case DIR_W:
return { -1, 1 };
case DIR_NW:
return { -1, 0 };
case DIR_N:
return { -1, -1 };
case DIR_NE:
return { 0, -1 };
case DIR_E:
return { 1, -1 };
case DIR_SE:
return { 1, 0 };
case DIR_OMNI:
return { 0, 0 };
}
};
return (*this) += toPoint(direction);
}
Point &operator-=(const Point &other)
{
x -= other.x;
@ -111,6 +139,12 @@ struct Point {
return a;
}
friend Point operator+(Point a, Direction direction)
{
a += direction;
return a;
}
friend Point operator-(Point a, const Point &b)
{
a -= b;

22
Source/inv.cpp

@ -1809,17 +1809,18 @@ bool TryInvPut()
return false;
Direction dir = GetDirection(plr[myplr].position.tile, { cursmx, cursmy });
if (CanPut(plr[myplr].position.tile.x + offset_x[dir], plr[myplr].position.tile.y + offset_y[dir])) {
Point position = plr[myplr].position.tile + dir;
if (CanPut(position.x, position.y)) {
return true;
}
Direction dirLeft = left[dir];
if (CanPut(plr[myplr].position.tile.x + offset_x[dirLeft], plr[myplr].position.tile.y + offset_y[dirLeft])) {
position = plr[myplr].position.tile + left[dir];
if (CanPut(position.x, position.y)) {
return true;
}
Direction dirRight = right[dir];
if (CanPut(plr[myplr].position.tile.x + offset_x[dirRight], plr[myplr].position.tile.y + offset_y[dirRight])) {
position = plr[myplr].position.tile + right[dir];
if (CanPut(position.x, position.y)) {
return true;
}
@ -1847,21 +1848,16 @@ static bool PutItem(int pnum, Point &position)
Direction d = GetDirection(plr[pnum].position.tile, position);
if (abs(relativePosition.x) > 1 || abs(relativePosition.y) > 1) {
position.x = plr[pnum].position.tile.x + offset_x[d];
position.y = plr[pnum].position.tile.y + offset_y[d];
position = plr[pnum].position.tile + d;
}
if (CanPut(position.x, position.y))
return true;
Direction dLeft = left[d];
position.x = plr[pnum].position.tile.x + offset_x[dLeft];
position.y = plr[pnum].position.tile.y + offset_y[dLeft];
position = plr[pnum].position.tile + left[d];
if (CanPut(position.x, position.y))
return true;
Direction dRight = right[d];
position.x = plr[pnum].position.tile.x + offset_x[dRight];
position.y = plr[pnum].position.tile.y + offset_y[dRight];
position = plr[pnum].position.tile + right[d];
if (CanPut(position.x, position.y))
return true;

138
Source/monster.cpp

@ -97,10 +97,6 @@ Direction left[8] = { DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW, DIR_N, DIR_NE, DIR_E
Direction right[8] = { DIR_SW, DIR_W, DIR_NW, DIR_N, DIR_NE, DIR_E, DIR_SE, DIR_S };
/** Maps from direction to the opposite direction. */
Direction opposite[8] = { DIR_N, DIR_NE, DIR_E, DIR_SE, DIR_S, DIR_SW, DIR_W, DIR_NW };
/** Maps from direction to delta X-offset. */
int offset_x[8] = { 1, 0, -1, -1, -1, 0, 1, 1 };
/** Maps from direction to delta Y-offset. */
int offset_y[8] = { 1, 1, 1, 0, -1, -1, -1, 0 };
/** Maps from monster AI ID to monster AI function. */
void (*AiProc[])(int i) = {
@ -1026,8 +1022,9 @@ void PlaceGroup(int mtype, int num, int leaderf, int leader)
if (leaderf & 1) {
int offset = GenerateRnd(8);
x1 = xp = monster[leader].position.tile.x + offset_x[offset];
y1 = yp = monster[leader].position.tile.y + offset_y[offset];
auto position = monster[leader].position.tile + static_cast<Direction>(offset);
x1 = xp = position.x;
y1 = yp = position.y;
} else {
do {
x1 = xp = GenerateRnd(80) + 16;
@ -1040,7 +1037,7 @@ void PlaceGroup(int mtype, int num, int leaderf, int leader)
}
j = 0;
for (try2 = 0; j < num && try2 < 100; xp += offset_x[GenerateRnd(8)], yp += offset_x[GenerateRnd(8)]) { /// BUGFIX: `yp += offset_y`
for (try2 = 0; j < num && try2 < 100; xp += (Point { 0, 0 } + static_cast<Direction>(GenerateRnd(8))).x, yp += (Point { 0, 0 } + static_cast<Direction>(GenerateRnd(8))).x) { /// BUGFIX: `yp += offset_y`
if (!MonstPlace(xp, yp)
|| (dTransVal[xp][yp] != dTransVal[x1][y1])
|| ((leaderf & 2) && ((abs(xp - x1) >= 4) || (abs(yp - y1) >= 4)))) {
@ -1241,20 +1238,17 @@ int AddMonster(int x, int y, Direction dir, int mtype, bool InMap)
void monster_43C785(int i)
{
int x, y, d, j, oi, mx, my;
int d, j, oi, mx, my;
Point position = {};
if (monster[i].MType) {
mx = monster[i].position.tile.x;
my = monster[i].position.tile.y;
Direction dir = monster[i]._mdir;
for (d = 0; d < 8; d++) {
x = mx + offset_x[d];
y = my + offset_y[d];
if (!SolidLoc(x, y)) {
if (dPlayer[x][y] == 0 && dMonster[x][y] == 0) {
if (dObject[x][y] == 0)
position = monster[i].position.tile + monster[i]._mdir;
if (!SolidLoc(position.x, position.y)) {
if (dPlayer[position.x][position.y] == 0 && dMonster[position.x][position.y] == 0) {
if (dObject[position.x][position.y] == 0)
break;
oi = dObject[x][y] > 0 ? dObject[x][y] - 1 : -(dObject[x][y] + 1);
oi = dObject[position.x][position.y] > 0 ? dObject[position.x][position.y] - 1 : -(dObject[position.x][position.y] + 1);
if (!object[oi]._oSolidFlag)
break;
}
@ -1266,7 +1260,7 @@ void monster_43C785(int i)
break;
}
if (j < MAX_LVLMTYPES)
AddMonster(x, y, dir, j, true);
AddMonster(position.x, position.y, monster[i]._mdir, j, true);
}
}
}
@ -1580,8 +1574,7 @@ void M_GetKnockback(int i)
Direction d = opposite[monster[i]._mdir];
if (DirOK(i, d)) {
M_ClearSquares(i);
monster[i].position.old.x += offset_x[d];
monster[i].position.old.y += offset_y[d];
monster[i].position.old += d;
NewMonsterAnim(i, &monster[i].MType->Anims[MA_GOTHIT], monster[i]._mdir);
monster[i]._mmode = MM_GOTHIT;
monster[i].position.offset = { 0, 0 };
@ -2057,7 +2050,6 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam)
int dx, dy;
int blk, blkper;
int dam, mdam;
int newx, newy;
int j, misnum, cur_ms_num, ac;
assurance((DWORD)i < MAXMONSTERS, i);
@ -2196,13 +2188,13 @@ void M_TryH2HHit(int i, int pnum, int Hit, int MinDam, int MaxDam)
if (monster[i]._mFlags & MFLAG_KNOCKBACK) {
if (plr[pnum]._pmode != PM_GOTHIT)
StartPlrHit(pnum, 0, true);
newx = plr[pnum].position.tile.x + offset_x[monster[i]._mdir];
newy = plr[pnum].position.tile.y + offset_y[monster[i]._mdir];
if (PosOkPlayer(pnum, newx, newy)) {
plr[pnum].position.tile = { newx, newy };
Point newPosition = plr[pnum].position.tile + monster[i]._mdir;
if (PosOkPlayer(pnum, newPosition.x, newPosition.y)) {
plr[pnum].position.tile = newPosition;
FixPlayerLocation(pnum, plr[pnum]._pdir);
FixPlrWalkTags(pnum);
dPlayer[newx][newy] = pnum + 1;
dPlayer[newPosition.x][newPosition.y] = pnum + 1;
SetPlayerOld(plr[pnum]);
}
}
@ -2255,9 +2247,14 @@ bool M_DoRAttack(int i)
else
multimissiles = 1;
for (mi = 0; mi < multimissiles; mi++) {
Point sourcePosition = monster[i].position.tile;
if (gbIsHellfire) {
sourcePosition += monster[i]._mdir;
}
AddMissile(
monster[i].position.tile.x + (gbIsHellfire ? offset_x[monster[i]._mdir] : 0),
monster[i].position.tile.y + (gbIsHellfire ? offset_y[monster[i]._mdir] : 0),
sourcePosition.x,
sourcePosition.y,
monster[i].enemyPosition.x,
monster[i].enemyPosition.y,
monster[i]._mdir,
@ -2286,9 +2283,14 @@ bool M_DoRSpAttack(int i)
commitment(monster[i].MData != nullptr, i); // BUGFIX: should check MData (fixed)
if (monster[i]._mAnimFrame == monster[i].MData->mAFNum2 && monster[i]._mAnimCnt == 0) {
Point sourcePosition = monster[i].position.tile;
if (gbIsHellfire) {
sourcePosition += monster[i]._mdir;
}
AddMissile(
monster[i].position.tile.x + (gbIsHellfire ? offset_x[monster[i]._mdir] : 0),
monster[i].position.tile.y + (gbIsHellfire ? offset_y[monster[i]._mdir] : 0),
sourcePosition.x,
sourcePosition.y,
monster[i].enemyPosition.x,
monster[i].enemyPosition.y,
monster[i]._mdir,
@ -3938,7 +3940,7 @@ void MAI_Golum(int i)
void MAI_SkelKing(int i)
{
MonsterStruct *Monst;
int mx, my, fx, fy, nx, ny;
int mx, my, fx, fy;
int dist, v;
assurance((DWORD)i < MAXMONSTERS, i);
@ -3972,10 +3974,9 @@ void MAI_SkelKing(int i)
if (!gbIsMultiplayer
&& ((dist >= 3 && v < 4 * Monst->_mint + 35) || v < 6)
&& LineClearMissile(Monst->position.tile.x, Monst->position.tile.y, fx, fy)) {
nx = Monst->position.tile.x + offset_x[md];
ny = Monst->position.tile.y + offset_y[md];
if (PosOkMonst(i, nx, ny) && nummonsters < MAXMONSTERS) {
M_SpawnSkel(nx, ny, md);
Point newPosition = Monst->position.tile + md;
if (PosOkMonst(i, newPosition.x, newPosition.y) && nummonsters < MAXMONSTERS) {
M_SpawnSkel(newPosition.x, newPosition.y, md);
M_StartSpStand(i, md);
}
} else {
@ -4111,7 +4112,8 @@ void MAI_HorkDemon(int i)
if (Monst->_mgoal == 1) {
if ((abs(mx) >= 3 || abs(my) >= 3) && v < 2 * Monst->_mint + 43) {
if (PosOkMonst(i, Monst->position.tile.x + offset_x[Monst->_mdir], Monst->position.tile.y + offset_y[Monst->_mdir]) && nummonsters < MAXMONSTERS) {
Point position = Monst->position.tile + Monst->_mdir;
if (PosOkMonst(i, position.x, position.y) && nummonsters < MAXMONSTERS) {
M_StartRSpAttack(i, MIS_HORKDMN, 0);
}
} else if (abs(mx) < 2 && abs(my) < 2) {
@ -4691,30 +4693,28 @@ void FreeMonsters()
bool DirOK(int i, Direction mdir)
{
int fx, fy;
int x, y;
int mcount, mi;
commitment((DWORD)i < MAXMONSTERS, i);
fx = monster[i].position.tile.x + offset_x[mdir];
fy = monster[i].position.tile.y + offset_y[mdir];
if (fy < 0 || fy >= MAXDUNY || fx < 0 || fx >= MAXDUNX || !PosOkMonst(i, fx, fy))
Point futurePosition = monster[i].position.tile + mdir;
if (futurePosition.y < 0 || futurePosition.y >= MAXDUNY || futurePosition.x < 0 || futurePosition.x >= MAXDUNX || !PosOkMonst(i, futurePosition.x, futurePosition.y))
return false;
if (mdir == DIR_E) {
if (SolidLoc(fx, fy + 1) || dFlags[fx][fy + 1] & BFLAG_MONSTLR)
if (SolidLoc(futurePosition.x, futurePosition.y + 1) || dFlags[futurePosition.x][futurePosition.y + 1] & BFLAG_MONSTLR)
return false;
} else if (mdir == DIR_W) {
if (SolidLoc(fx + 1, fy) || dFlags[fx + 1][fy] & BFLAG_MONSTLR)
if (SolidLoc(futurePosition.x + 1, futurePosition.y) || dFlags[futurePosition.x + 1][futurePosition.y] & BFLAG_MONSTLR)
return false;
} else if (mdir == DIR_N) {
if (SolidLoc(fx + 1, fy) || SolidLoc(fx, fy + 1))
if (SolidLoc(futurePosition.x + 1, futurePosition.y) || SolidLoc(futurePosition.x, futurePosition.y + 1))
return false;
} else if (mdir == DIR_S)
if (SolidLoc(fx - 1, fy) || SolidLoc(fx, fy - 1))
if (SolidLoc(futurePosition.x - 1, futurePosition.y) || SolidLoc(futurePosition.x, futurePosition.y - 1))
return false;
if (monster[i].leaderflag == 1) {
if (abs(fx - monster[monster[i].leader].position.future.x) >= 4
|| abs(fy - monster[monster[i].leader].position.future.y) >= 4) {
if (abs(futurePosition.x - monster[monster[i].leader].position.future.x) >= 4
|| abs(futurePosition.y - monster[monster[i].leader].position.future.y) >= 4) {
return false;
}
return true;
@ -4722,8 +4722,8 @@ bool DirOK(int i, Direction mdir)
if (monster[i]._uniqtype == 0 || !(UniqMonst[monster[i]._uniqtype - 1].mUnqAttr & 2))
return true;
mcount = 0;
for (x = fx - 3; x <= fx + 3; x++) {
for (y = fy - 3; y <= fy + 3; y++) {
for (x = futurePosition.x - 3; x <= futurePosition.x + 3; x++) {
for (y = futurePosition.y - 3; y <= futurePosition.y + 3; y++) {
if (y < 0 || y >= MAXDUNY || x < 0 || x >= MAXDUNX)
continue;
mi = dMonster[x][y];
@ -5072,8 +5072,6 @@ void PrintUniqueHistory()
void MissToMonst(int i, int x, int y)
{
int oldx, oldy;
int newx, newy;
int m, pnum;
MissileStruct *Miss;
MonsterStruct *Monst;
@ -5086,8 +5084,7 @@ void MissToMonst(int i, int x, int y)
assurance((DWORD)m < MAXMONSTERS, m);
Monst = &monster[m];
oldx = Miss->position.tile.x;
oldy = Miss->position.tile.y;
Point oldPosition = Miss->position.tile;
dMonster[x][y] = m + 1;
Monst->_mdir = static_cast<Direction>(Miss->_mimfnum);
Monst->position.tile = { x, y };
@ -5101,40 +5098,39 @@ void MissToMonst(int i, int x, int y)
M_StartFadein(m, Monst->_mdir, false);
}
Point newPosition = {};
if (!(Monst->_mFlags & MFLAG_TARGETS_MONSTER)) {
pnum = dPlayer[oldx][oldy] - 1;
if (dPlayer[oldx][oldy] > 0) {
pnum = dPlayer[oldPosition.x][oldPosition.y] - 1;
if (dPlayer[oldPosition.x][oldPosition.y] > 0) {
if (Monst->MType->mtype != MT_GLOOM && (Monst->MType->mtype < MT_INCIN || Monst->MType->mtype > MT_HELLBURN)) {
M_TryH2HHit(m, dPlayer[oldx][oldy] - 1, 500, Monst->mMinDamage2, Monst->mMaxDamage2);
if (pnum == dPlayer[oldx][oldy] - 1 && (Monst->MType->mtype < MT_NSNAKE || Monst->MType->mtype > MT_GSNAKE)) {
M_TryH2HHit(m, dPlayer[oldPosition.x][oldPosition.y] - 1, 500, Monst->mMinDamage2, Monst->mMaxDamage2);
if (pnum == dPlayer[oldPosition.x][oldPosition.y] - 1 && (Monst->MType->mtype < MT_NSNAKE || Monst->MType->mtype > MT_GSNAKE)) {
if (plr[pnum]._pmode != PM_GOTHIT && plr[pnum]._pmode != PM_DEATH)
StartPlrHit(pnum, 0, true);
newx = oldx + offset_x[Monst->_mdir];
newy = oldy + offset_y[Monst->_mdir];
if (PosOkPlayer(pnum, newx, newy)) {
plr[pnum].position.tile = { newx, newy };
newPosition = oldPosition + Monst->_mdir;
if (PosOkPlayer(pnum, newPosition.x, newPosition.y)) {
plr[pnum].position.tile = newPosition;
FixPlayerLocation(pnum, plr[pnum]._pdir);
FixPlrWalkTags(pnum);
dPlayer[newx][newy] = pnum + 1;
dPlayer[newPosition.x][newPosition.y] = pnum + 1;
SetPlayerOld(plr[pnum]);
}
}
}
}
} else {
if (dMonster[oldx][oldy] > 0) {
if (dMonster[oldPosition.x][oldPosition.y] > 0) {
if (Monst->MType->mtype != MT_GLOOM && (Monst->MType->mtype < MT_INCIN || Monst->MType->mtype > MT_HELLBURN)) {
M_TryM2MHit(m, dMonster[oldx][oldy] - 1, 500, Monst->mMinDamage2, Monst->mMaxDamage2);
M_TryM2MHit(m, dMonster[oldPosition.x][oldPosition.y] - 1, 500, Monst->mMinDamage2, Monst->mMaxDamage2);
if (Monst->MType->mtype < MT_NSNAKE || Monst->MType->mtype > MT_GSNAKE) {
newx = oldx + offset_x[Monst->_mdir];
newy = oldy + offset_y[Monst->_mdir];
if (PosOkMonst(dMonster[oldx][oldy] - 1, newx, newy)) {
m = dMonster[oldx][oldy];
dMonster[newx][newy] = m;
dMonster[oldx][oldy] = 0;
newPosition = oldPosition + Monst->_mdir;
if (PosOkMonst(dMonster[oldPosition.x][oldPosition.y] - 1, newPosition.x, newPosition.y)) {
m = dMonster[oldPosition.x][oldPosition.y];
dMonster[newPosition.x][newPosition.y] = m;
dMonster[oldPosition.x][oldPosition.y] = 0;
m--;
monster[m].position.tile = { newx, newy };
monster[m].position.future = { newx, newy };
monster[m].position.tile = newPosition;
monster[m].position.future = newPosition;
}
}
}

2
Source/monster.h

@ -305,7 +305,5 @@ void decode_enemy(int m, int enemy);
extern Direction left[8];
extern Direction right[8];
extern Direction opposite[8];
extern int offset_x[8];
extern int offset_y[8];
} // namespace devilution

30
Source/player.cpp

@ -1224,7 +1224,6 @@ bool SolidLoc(int x, int y)
bool PlrDirOK(int pnum, int dir)
{
int px, py;
bool isOk;
if ((DWORD)pnum >= MAX_PLRS) {
@ -1232,20 +1231,18 @@ bool PlrDirOK(int pnum, int dir)
}
auto &player = plr[pnum];
px = player.position.tile.x + offset_x[dir];
py = player.position.tile.y + offset_y[dir];
if (px < 0 || !dPiece[px][py] || !PosOkPlayer(pnum, px, py)) {
Point position = player.position.tile + static_cast<Direction>(dir);
if (position.x < 0 || !dPiece[position.x][position.y] || !PosOkPlayer(pnum, position.x, position.y)) {
return false;
}
isOk = true;
if (dir == DIR_E) {
isOk = !SolidLoc(px, py + 1) && !(dFlags[px][py + 1] & BFLAG_PLAYERLR);
isOk = !SolidLoc(position.x, position.y + 1) && !(dFlags[position.x][position.y + 1] & BFLAG_PLAYERLR);
}
if (isOk && dir == DIR_W) {
isOk = !SolidLoc(px + 1, py) && !(dFlags[px + 1][py] & BFLAG_PLAYERLR);
isOk = !SolidLoc(position.x + 1, position.y) && !(dFlags[position.x + 1][position.y] & BFLAG_PLAYERLR);
}
return isOk;
@ -1909,7 +1906,8 @@ StartPlayerKill(int pnum, int earflag)
i = NUM_INVLOC;
while (i--) {
pdd = (i + player._pdir) & 7;
PlrDeadItem(player, pi, offset_x[pdd], offset_y[pdd]);
Point offset = Point { 0, 0 } + static_cast<Direction>(pdd);
PlrDeadItem(player, pi, offset.x, offset.y);
pi++;
}
@ -2816,8 +2814,9 @@ bool PM_DoAttack(int pnum)
}
if (player.AnimInfo.CurrentFrame == player._pAFNum) {
dx = player.position.tile.x + offset_x[player._pdir];
dy = player.position.tile.y + offset_y[player._pdir];
Point position = player.position.tile + player._pdir;
dx = position.x;
dy = position.y;
if (dMonster[dx][dy] != 0) {
if (dMonster[dx][dy] > 0) {
@ -2869,15 +2868,18 @@ bool PM_DoAttack(int pnum)
|| (player.InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_SWORD && player.InvBody[INVLOC_HAND_LEFT]._iLoc == ILOC_TWOHAND)
|| (player.InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SWORD && player.InvBody[INVLOC_HAND_RIGHT]._iLoc == ILOC_TWOHAND))
&& !(player.InvBody[INVLOC_HAND_LEFT]._itype == ITYPE_SHIELD || player.InvBody[INVLOC_HAND_RIGHT]._itype == ITYPE_SHIELD))))) {
dx = player.position.tile.x + offset_x[(player._pdir + 1) % 8];
dy = player.position.tile.y + offset_y[(player._pdir + 1) % 8];
Point position = player.position.tile + right[player._pdir];
dx = position.x;
dy = position.y;
m = ((dMonster[dx][dy] > 0) ? dMonster[dx][dy] : -dMonster[dx][dy]) - 1;
if (dMonster[dx][dy] != 0 && !CanTalkToMonst(m) && monster[m].position.old.x == dx && monster[m].position.old.y == dy) {
if (PlrHitMonst(-pnum, m))
didhit = true;
}
dx = player.position.tile.x + offset_x[(player._pdir + 7) % 8];
dy = player.position.tile.y + offset_y[(player._pdir + 7) % 8];
position = player.position.tile + left[player._pdir];
dx = position.x;
dy = position.y;
m = ((dMonster[dx][dy] > 0) ? dMonster[dx][dy] : -dMonster[dx][dy]) - 1;
if (dMonster[dx][dy] != 0 && !CanTalkToMonst(m) && monster[m].position.old.x == dx && monster[m].position.old.y == dy) {
if (PlrHitMonst(-pnum, m))

Loading…
Cancel
Save