From 4e82c70fcb0edd0de4af44c75e58f9a98685ef7b Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Fri, 16 Jul 2021 03:50:34 +0200 Subject: [PATCH] Make MonsterIsTileAccessible aware if monsters can open doors or not --- Source/missiles.cpp | 6 ++--- Source/monster.cpp | 64 +++++++++++++++++++++++++-------------------- Source/monster.h | 2 +- 3 files changed, 40 insertions(+), 32 deletions(-) diff --git a/Source/missiles.cpp b/Source/missiles.cpp index 0c04ace71..faad81851 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -198,7 +198,7 @@ void MoveMissilePos(int i) } int x = Missiles[i].position.tile.x + dx; int y = Missiles[i].position.tile.y + dy; - if (MonsterIsTileAvalible(Missiles[i]._misource, { x, y })) { + if (MonsterIsTileAvailable(Missiles[i]._misource, { x, y })) { Missiles[i].position.tile.x += dx; Missiles[i].position.tile.y += dy; Missiles[i].position.offset.deltaX += (dy * 32) - (dx * 32); @@ -4288,7 +4288,7 @@ void MI_Rhino(int i) } UpdateMissilePos(i); Point newPos = Missiles[i].position.tile; - if (!MonsterIsTileAvalible(monst, newPos) || (monster._mAi == AI_SNAKE && !MonsterIsTileAvalible(monst, newPosSnake))) { + if (!MonsterIsTileAvailable(monst, newPos) || (monster._mAi == AI_SNAKE && !MonsterIsTileAvailable(monst, newPosSnake))) { MissToMonst(i, prevPos); Missiles[i]._miDelFlag = true; return; @@ -4315,7 +4315,7 @@ void MI_Fireman(int i) Point c = (monster._mFlags & MFLAG_TARGETS_MONSTER) == 0 ? Players[enemy].position.tile : Monsters[enemy].position.tile; int j = 0; - if (b != a && (((Missiles[i]._miVar1 & 1) != 0 && a.WalkingDistance(c) >= 4) || Missiles[i]._miVar2 > 1) && MonsterIsTileAvalible(Missiles[i]._misource, a)) { + if (b != a && (((Missiles[i]._miVar1 & 1) != 0 && a.WalkingDistance(c) >= 4) || Missiles[i]._miVar2 > 1) && MonsterIsTileAvailable(Missiles[i]._misource, a)) { MissToMonst(i, a); Missiles[i]._miDelFlag = true; } else if ((monster._mFlags & MFLAG_TARGETS_MONSTER) == 0) { diff --git a/Source/monster.cpp b/Source/monster.cpp index 1dda0d277..c9ced0543 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -1157,7 +1157,7 @@ void Teleport(int i) x = mx + rx * j; y = my + ry * k; if (y >= 0 && y < MAXDUNY && x >= 0 && x < MAXDUNX && x != monster.position.tile.x && y != monster.position.tile.y) { - if (MonsterIsTileAvalible(i, { x, y })) + if (MonsterIsTileAvailable(i, { x, y })) done = true; } } @@ -2046,10 +2046,10 @@ bool RandomWalk2(int i, Direction md) /** * @brief Check if a tile is affected by a spell we are vunerable to */ -bool MonsterIsTileSafe(int i, Point position) +bool MonsterIsTileSafe(const MonsterStruct &monster, Point position) { int8_t mi = dMissile[position.x][position.y]; - if (mi == 0 || i < 0) { + if (mi == 0) { return true; } @@ -2076,9 +2076,9 @@ bool MonsterIsTileSafe(int i, Point position) } } } - if (fire && ((Monsters[i].mMagicRes & IMMUNE_FIRE) == 0 || Monsters[i].MType->mtype == MT_DIABLO)) + if (fire && ((monster.mMagicRes & IMMUNE_FIRE) == 0 || monster.MType->mtype == MT_DIABLO)) return false; - if (lightning && ((Monsters[i].mMagicRes & IMMUNE_LIGHTNING) == 0 || Monsters[i].MType->mtype == MT_DIABLO)) + if (lightning && ((monster.mMagicRes & IMMUNE_LIGHTNING) == 0 || monster.MType->mtype == MT_DIABLO)) return false; return true; @@ -2098,32 +2098,41 @@ bool MonsterIsTileClear(int i, Point position) return false; } - return MonsterIsTileSafe(i, position); + return MonsterIsTileSafe(Monsters[i], position); } /** - * @brief Check that the amonster that can open doors can stand on the tile + * @brief If a monster can access the given tile (possibly by opening a door) */ bool MonsterIsTileAccessible(int i, Point position) { - bool isdoor = false; + MonsterStruct *monster; + if (i >= 0) + monster = &Monsters[i]; + + bool canOpen = false; if (dObject[position.x][position.y] != 0) { int oi = dObject[position.x][position.y] > 0 ? dObject[position.x][position.y] - 1 : -(dObject[position.x][position.y] + 1); - isdoor = IsAnyOf(Objects[oi]._otype, OBJ_L1LDOOR, OBJ_L1RDOOR, OBJ_L2LDOOR, OBJ_L2RDOOR, OBJ_L3LDOOR, OBJ_L3RDOOR); - if (Objects[oi]._oSolidFlag && !isdoor) + + if (monster != nullptr && (monster->_mFlags & MFLAG_CAN_OPEN_DOOR) != 0) + canOpen = IsAnyOf(Objects[oi]._otype, OBJ_L1LDOOR, OBJ_L1RDOOR, OBJ_L2LDOOR, OBJ_L2RDOOR, OBJ_L3LDOOR, OBJ_L3RDOOR); + + if (Objects[oi]._oSolidFlag && !canOpen) return false; } - if ((SolidLoc(position) && !isdoor) || dPlayer[position.x][position.y] != 0 || dMonster[position.x][position.y] != 0) + if ((SolidLoc(position) && !canOpen) || dPlayer[position.x][position.y] != 0 || dMonster[position.x][position.y] != 0) return false; - return MonsterIsTileSafe(i, position); + if (monster == nullptr) + return true; + + return MonsterIsTileSafe(*monster, position); } bool AiPlanWalk(int i) { int8_t path[MAX_PATH_LENGTH]; - bool (*check)(int, Point); /** Maps from walking path step to facing direction. */ const Direction plr2monst[9] = { DIR_S, DIR_NE, DIR_NW, DIR_SE, DIR_SW, DIR_N, DIR_E, DIR_S, DIR_W }; @@ -2131,11 +2140,7 @@ bool AiPlanWalk(int i) assert((DWORD)i < MAXMONSTERS); auto &monster = Monsters[i]; - check = MonsterIsTileAccessible; - if ((Monsters[i]._mFlags & MFLAG_CAN_OPEN_DOOR) == 0) - check = MonsterIsTileAvalible; - - if (FindPath(check, i, monster.position.tile.x, monster.position.tile.y, monster.enemyPosition.x, monster.enemyPosition.y, path) == 0) { + if (FindPath(MonsterIsTileAccessible, i, monster.position.tile.x, monster.position.tile.y, monster.enemyPosition.x, monster.enemyPosition.y, path) == 0) { return false; } @@ -2639,7 +2644,7 @@ void RhinoAi(int i) if (monster._mgoal == MGOAL_NORMAL) { if (dist >= 5 && v < 2 * monster._mint + 43 - && LineClear(MonsterIsTileAvalible, i, monster.position.tile, { fx, fy })) { + && LineClear(MonsterIsTileAvailable, i, monster.position.tile, { fx, fy })) { if (AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, monster._menemy, i, 0, 0) != -1) { if (monster.MData->snd_special) PlayEffect(monster, 3); @@ -2785,7 +2790,7 @@ void LeoricAi(int i) && ((dist >= 3 && v < 4 * monster._mint + 35) || v < 6) && LineClearMissile(monster.position.tile, { fx, fy })) { Point newPosition = monster.position.tile + md; - if (MonsterIsTileAvalible(i, newPosition) && ActiveMonsterCount < MAXMONSTERS) { + if (MonsterIsTileAvailable(i, newPosition) && ActiveMonsterCount < MAXMONSTERS) { SpawnSkeleton(newPosition, md); StartSpecialStand(monster, md); } @@ -2842,7 +2847,7 @@ void BatAi(int i) if (monster.MType->mtype == MT_GLOOM && (abs(xd) >= 5 || abs(yd) >= 5) && v < 4 * monster._mint + 33 - && LineClear(MonsterIsTileAvalible, i, monster.position.tile, { fx, fy })) { + && LineClear(MonsterIsTileAvailable, i, monster.position.tile, { fx, fy })) { if (AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, pnum, i, 0, 0) != -1) { dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); monster._mmode = MM_CHARGE; @@ -3171,7 +3176,7 @@ void SnakeAi(int i) Direction md = GetDirection(monster.position.tile, monster.position.last); monster._mdir = md; if (abs(mx) >= 2 || abs(my) >= 2) { - if (abs(mx) < 3 && abs(my) < 3 && LineClear(MonsterIsTileAvalible, i, monster.position.tile, { fx, fy }) && monster._mVar1 != MM_CHARGE) { + if (abs(mx) < 3 && abs(my) < 3 && LineClear(MonsterIsTileAvailable, i, monster.position.tile, { fx, fy }) && monster._mVar1 != MM_CHARGE) { if (AddMissile(monster.position.tile, { fx, fy }, md, MIS_RHINO, pnum, i, 0, 0) != -1) { PlayEffect(monster, 0); dMonster[monster.position.tile.x][monster.position.tile.y] = -(i + 1); @@ -3573,7 +3578,7 @@ void HorkDemonAi(int i) if (monster._mgoal == 1) { if ((abs(mx) >= 3 || abs(my) >= 3) && v < 2 * monster._mint + 43) { Point position = monster.position.tile + monster._mdir; - if (MonsterIsTileAvalible(i, position) && ActiveMonsterCount < MAXMONSTERS) { + if (MonsterIsTileAvailable(i, position) && ActiveMonsterCount < MAXMONSTERS) { StartRangedSpecialAttack(monster, MIS_HORKDMN, 0); } } else if (abs(mx) < 2 && abs(my) < 2) { @@ -4602,7 +4607,7 @@ bool DirOK(int i, Direction mdir) auto &monster = Monsters[i]; Point position = monster.position.tile; Point futurePosition = position + mdir; - if (futurePosition.y < 0 || futurePosition.y >= MAXDUNY || futurePosition.x < 0 || futurePosition.x >= MAXDUNX || !MonsterIsTileAvalible(i, futurePosition)) + if (futurePosition.y < 0 || futurePosition.y >= MAXDUNY || futurePosition.x < 0 || futurePosition.x >= MAXDUNX || !MonsterIsTileAvailable(i, futurePosition)) return false; if (mdir == DIR_E) { if (SolidLoc(position + DIR_SE) || (dFlags[position.x + 1][position.y] & BFLAG_MONSTLR) != 0) @@ -4997,7 +5002,7 @@ void MissToMonst(int i, Point position) MonsterAttackMonster(m, dMonster[oldPosition.x][oldPosition.y] - 1, 500, monster.mMinDamage2, monster.mMaxDamage2); if (monster.MType->mtype < MT_NSNAKE || monster.MType->mtype > MT_GSNAKE) { Point newPosition = oldPosition + monster._mdir; - if (MonsterIsTileAvalible(dMonster[oldPosition.x][oldPosition.y] - 1, newPosition)) { + if (MonsterIsTileAvailable(dMonster[oldPosition.x][oldPosition.y] - 1, newPosition)) { m = dMonster[oldPosition.x][oldPosition.y]; dMonster[newPosition.x][newPosition.y] = m; dMonster[oldPosition.x][oldPosition.y] = 0; @@ -5010,7 +5015,10 @@ void MissToMonst(int i, Point position) } } -bool MonsterIsTileAvalible(int i, Point position) +/** + * @brief Check that the given tile is available to the monster + */ +bool MonsterIsTileAvailable(int i, Point position) { if (dPlayer[position.x][position.y] != 0 || dMonster[position.x][position.y] != 0) return false; @@ -5036,7 +5044,7 @@ bool SpawnSkeleton(int ii, Point position) if (ii == -1) return false; - if (MonsterIsTileAvalible(-1, position)) { + if (MonsterIsTileAvailable(-1, position)) { Direction dir = GetDirection(position, position); // TODO useless calculation ActivateSpawn(ii, position.x, position.y, dir); return true; @@ -5049,7 +5057,7 @@ bool SpawnSkeleton(int ii, Point position) for (int j = position.y - 1; j <= position.y + 1; j++) { int xx = 0; for (int k = position.x - 1; k <= position.x + 1; k++) { - monstok[xx][yy] = MonsterIsTileAvalible(-1, { k, j }); + monstok[xx][yy] = MonsterIsTileAvailable(-1, { k, j }); savail = savail || monstok[xx][yy]; xx++; } diff --git a/Source/monster.h b/Source/monster.h index 01c665c47..622b773e3 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -264,7 +264,7 @@ void PrintMonstHistory(int mt); void PrintUniqueHistory(); void PlayEffect(MonsterStruct &monster, int mode); void MissToMonst(int i, Point position); -bool MonsterIsTileAvalible(int i, Point position); +bool MonsterIsTileAvailable(int i, Point position); bool IsSkel(int mt); bool IsGoat(int mt); bool SpawnSkeleton(int ii, Point position);