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]; int dm = dMonster[tx][ty];
dm = dm > 0 ? dm - 1 : -(dm + 1); dm = dm > 0 ? dm - 1 : -(dm + 1);
if (dm <= 3) if (dm < MAX_PLRS)
continue; continue;
auto &monster = Monsters[dm]; 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*/) 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) { switch (Monsters[id].MType->mtype) {
case MT_SUCCUBUS: case MT_SUCCUBUS:
SetMissAnim(mi, MFILE_FLAREEXP); 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]; ty = dst.y + CrawlTable[ck];
if (InDungeonBounds({ tx, ty })) { if (InDungeonBounds({ tx, ty })) {
int mid = dMonster[tx][ty]; int mid = dMonster[tx][ty];
if (mid == 0)
continue;
mid = mid > 0 ? mid - 1 : -(mid + 1); mid = mid > 0 ? mid - 1 : -(mid + 1);
auto &monster = Monsters[mid]; auto &monster = Monsters[mid];
if (mid > MAX_PLRS - 1 && monster._mAi != AI_DIABLO && monster.MType->mtype != MT_NAKRUL) { 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; i = 6;
auto md = static_cast<Direction>(Missiles[mi]._miVar1); auto md = static_cast<Direction>(Missiles[mi]._miVar1);
int monsterId = AddMonster({ tx, ty }, md, 1, true); int monsterId = AddMonster({ tx, ty }, md, 1, true);
M_StartStand(Monsters[monsterId], md); if (monsterId != -1)
M_StartStand(Monsters[monsterId], md);
break; break;
} }
} }

121
Source/monster.cpp

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

2
Source/msg.cpp

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

Loading…
Cancel
Save