Browse Source

Make MonsterIsTileAccessible aware if monsters can open doors or not

pull/2399/head
Anders Jenbo 5 years ago
parent
commit
4e82c70fcb
  1. 6
      Source/missiles.cpp
  2. 64
      Source/monster.cpp
  3. 2
      Source/monster.h

6
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) {

64
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++;
}

2
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);

Loading…
Cancel
Save