Browse Source

🐛 Fix bounds checks in monster code

pull/2379/head
Anders Jenbo 5 years ago
parent
commit
a44781bd73
  1. 9
      Source/missiles.cpp
  2. 121
      Source/monster.cpp
  3. 2
      Source/msg.cpp

9
Source/missiles.cpp

@ -1485,7 +1485,7 @@ void AddBerserk(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t /*mienem
int dm = dMonster[tx][ty];
dm = dm > 0 ? dm - 1 : -(dm + 1);
if (dm <= 3)
if (dm < MAX_PLRS)
continue;
auto &monster = Monsters[dm];
@ -2233,7 +2233,7 @@ void AddLightning(int mi, Point /*src*/, Point dst, int midir, int8_t mienemy, i
void AddMisexp(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t mienemy, int id, int /*dam*/)
{
if (mienemy != 0 && id > 0) {
if (mienemy != 0 && id >= 0) {
switch (Monsters[id].MType->mtype) {
case MT_SUCCUBUS:
SetMissAnim(mi, MFILE_FLAREEXP);
@ -2597,6 +2597,8 @@ void AddStone(int mi, Point /*src*/, Point dst, int /*midir*/, int8_t /*mienemy*
ty = dst.y + CrawlTable[ck];
if (InDungeonBounds({ tx, ty })) {
int mid = dMonster[tx][ty];
if (mid == 0)
continue;
mid = mid > 0 ? mid - 1 : -(mid + 1);
auto &monster = Monsters[mid];
if (mid > MAX_PLRS - 1 && monster._mAi != AI_DIABLO && monster.MType->mtype != MT_NAKRUL) {
@ -3481,7 +3483,8 @@ void MI_HorkSpawn(int mi)
i = 6;
auto md = static_cast<Direction>(Missiles[mi]._miVar1);
int monsterId = AddMonster({ tx, ty }, md, 1, true);
M_StartStand(Monsters[monsterId], md);
if (monsterId != -1)
M_StartStand(Monsters[monsterId], md);
break;
}
}

121
Source/monster.cpp

@ -1957,13 +1957,14 @@ void GroupUnity(int i)
assert((DWORD)i < MAXMONSTERS);
auto &monster = Monsters[i];
auto &leader = Monsters[monster.leader];
if (monster.leaderflag != MonsterRelation::Individual) {
bool clear = IsLineNotSolid(monster.position.tile, leader.position.future);
if (clear || monster.leaderflag != MonsterRelation::Minion) {
if (clear
&& monster.leaderflag == MonsterRelation::Leader
&& monster.position.tile.WalkingDistance(leader.position.future) < 4) {
if (monster.leaderflag == MonsterRelation::Individual) {
return;
}
if (monster.leader != 0) {
auto &leader = Monsters[monster.leader];
if (IsLineNotSolid(monster.position.tile, leader.position.future)) {
if (monster.leaderflag == MonsterRelation::Leader && monster.position.tile.WalkingDistance(leader.position.future) < 4) {
leader.packsize++;
monster.leaderflag = MonsterRelation::Minion;
}
@ -1971,35 +1972,34 @@ void GroupUnity(int i)
leader.packsize--;
monster.leaderflag = MonsterRelation::Leader;
}
}
if (monster.leaderflag == MonsterRelation::Minion) {
if (monster._msquelch > leader._msquelch) {
leader.position.last = monster.position.tile;
leader._msquelch = monster._msquelch - 1;
}
if (leader._mAi == AI_GARG) {
if ((leader._mFlags & MFLAG_ALLOW_SPECIAL) != 0) {
leader._mFlags &= ~MFLAG_ALLOW_SPECIAL;
leader._mmode = MM_SATTACK;
if (monster.leaderflag == MonsterRelation::Minion) {
if (monster._msquelch > leader._msquelch) {
leader.position.last = monster.position.tile;
leader._msquelch = monster._msquelch - 1;
}
}
} else if (monster._uniqtype != MonsterRelation::Individual) {
if ((UniqMonst[monster._uniqtype - 1].mUnqAttr & 2) != 0) {
for (int j = 0; j < ActiveMonsterCount; j++) {
auto &minion = Monsters[ActiveMonsters[j]];
if (minion.leaderflag == MonsterRelation::Minion && minion.leader == i) {
if (monster._msquelch > minion._msquelch) {
minion.position.last = monster.position.tile;
minion._msquelch = monster._msquelch - 1;
}
if (minion._mAi == AI_GARG) {
if ((minion._mFlags & MFLAG_ALLOW_SPECIAL) != 0) {
minion._mFlags &= ~MFLAG_ALLOW_SPECIAL;
minion._mmode = MM_SATTACK;
}
}
}
}
if (monster._mAi == AI_GARG && (monster._mFlags & MFLAG_ALLOW_SPECIAL) != 0) {
if (monster.leaderflag == MonsterRelation::Minion || monster.packsize > 0) {
monster._mFlags &= ~MFLAG_ALLOW_SPECIAL;
monster._mmode = MM_SATTACK;
}
}
if (monster.leaderflag == MonsterRelation::Leader && monster._uniqtype != 0) {
if ((UniqMonst[monster._uniqtype - 1].mUnqAttr & 2) == 0) {
return;
}
for (int j = 0; j < ActiveMonsterCount; j++) {
auto &minion = Monsters[ActiveMonsters[j]];
if (minion.leaderflag != MonsterRelation::Minion || minion.leader != i) {
continue;
}
if (monster._msquelch > minion._msquelch) {
minion.position.last = monster.position.tile;
minion._msquelch = monster._msquelch - 1;
}
}
}
@ -4386,38 +4386,35 @@ void GolumAi(int i)
if ((golem._mFlags & MFLAG_TARGETS_MONSTER) == 0)
UpdateEnemy(golem);
bool haveEnemy = (golem._mFlags & MFLAG_NO_ENEMY) == 0;
if (golem._mmode == MM_ATTACK) {
return;
}
auto &enemy = Monsters[golem._menemy];
int mex = golem.position.tile.x - enemy.position.future.x;
int mey = golem.position.tile.y - enemy.position.future.y;
Direction md = GetDirection(golem.position.tile, enemy.position.tile);
golem._mdir = md;
if (abs(mex) < 2 && abs(mey) < 2 && haveEnemy) {
golem.enemyPosition = enemy.position.tile;
if (enemy._msquelch == 0) {
enemy._msquelch = UINT8_MAX;
enemy.position.last = golem.position.tile;
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
int menemy = dMonster[golem.position.tile.x + k - 2][golem.position.tile.y + j - 2]; // BUGFIX: Check if indexes are between 0 and 112
if (menemy > 0)
Monsters[menemy - 1]._msquelch = UINT8_MAX; // BUGFIX: should be `Monsters[_menemy-1]`, not Monsters[_menemy]. (fixed)
if ((golem._mFlags & MFLAG_NO_ENEMY) == 0) {
auto &enemy = Monsters[golem._menemy];
int mex = golem.position.tile.x - enemy.position.future.x;
int mey = golem.position.tile.y - enemy.position.future.y;
golem._mdir = GetDirection(golem.position.tile, enemy.position.tile);
if (abs(mex) < 2 && abs(mey) < 2) {
golem.enemyPosition = enemy.position.tile;
if (enemy._msquelch == 0) {
enemy._msquelch = UINT8_MAX;
enemy.position.last = golem.position.tile;
for (int j = 0; j < 5; j++) {
for (int k = 0; k < 5; k++) {
int enemyId = dMonster[golem.position.tile.x + k - 2][golem.position.tile.y + j - 2]; // BUGFIX: Check if indexes are between 0 and 112
if (enemyId > 0)
Monsters[enemyId - 1]._msquelch = UINT8_MAX; // BUGFIX: should be `Monsters[_menemy-1]`, not Monsters[_menemy]. (fixed)
}
}
}
StartAttack(golem);
return;
}
StartAttack(golem);
return;
if (AiPlanPath(i))
return;
}
if (haveEnemy && AiPlanPath(i))
return;
golem._pathcount++;
if (golem._pathcount > 8)
golem._pathcount = 5;
@ -4426,7 +4423,7 @@ void GolumAi(int i)
if (ok)
return;
md = left[md];
Direction md = left[golem._mdir];
for (int j = 0; j < 8 && !ok; j++) {
md = right[md];
ok = DirOK(i, md);
@ -4628,12 +4625,10 @@ bool DirOK(int i, Direction mdir)
if (y < 0 || y >= MAXDUNY || x < 0 || x >= MAXDUNX)
continue;
int mi = dMonster[x][y];
if (mi < 0)
mi = -mi;
if (mi != 0)
mi--;
// BUGFIX: should only run pack member check if mi was non-zero prior to executing the body of the above if-statement.
auto &minion = Monsters[mi];
if (mi == 0)
continue;
auto &minion = Monsters[(mi < 0) ? -(mi + 1) : (mi - 1)];
if (minion.leaderflag == MonsterRelation::Minion
&& minion.leader == i
&& minion.position.future == Point { x, y }) {

2
Source/msg.cpp

@ -1264,7 +1264,7 @@ DWORD OnMonstDeath(TCmd *pCmd, int pnum)
if (gbBufferMsgs == 1)
SendPacket(pnum, p, sizeof(*p));
else if (pnum != MyPlayerId) {
else if (pnum != MyPlayerId && p->wParam1 < MAXMONSTERS) {
if (currlevel == Players[pnum].plrlevel)
M_SyncStartKill(p->wParam1, { p->x, p->y }, pnum);
delta_kill_monster(p->wParam1, { p->x, p->y }, Players[pnum].plrlevel);

Loading…
Cancel
Save