diff --git a/Source/engine.h b/Source/engine.h index 153d8a44c..ea7fb2eef 100644 --- a/Source/engine.h +++ b/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; diff --git a/Source/inv.cpp b/Source/inv.cpp index 2716ddf6b..aba328d9b 100644 --- a/Source/inv.cpp +++ b/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; diff --git a/Source/monster.cpp b/Source/monster.cpp index 4b1c0a505..451aae350 100644 --- a/Source/monster.cpp +++ b/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(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(GenerateRnd(8))).x, yp += (Point { 0, 0 } + static_cast(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(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; } } } diff --git a/Source/monster.h b/Source/monster.h index bb77ccbff..41712ca88 100644 --- a/Source/monster.h +++ b/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 diff --git a/Source/player.cpp b/Source/player.cpp index c8139df76..a08407113 100644 --- a/Source/player.cpp +++ b/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(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(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))