Browse Source

Members' name changes and comments in Monster struct (#4861)

pull/4900/head
Mikołaj Piróg 4 years ago committed by GitHub
parent
commit
15989609a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      Source/control.cpp
  2. 4
      Source/controls/plrctrls.cpp
  3. 2
      Source/controls/touch/renderers.cpp
  4. 38
      Source/cursor.cpp
  5. 10
      Source/dead.cpp
  6. 14
      Source/debug.cpp
  7. 18
      Source/diablo.cpp
  8. 36
      Source/engine/render/scrollrt.cpp
  9. 2
      Source/inv.cpp
  10. 18
      Source/items.cpp
  11. 194
      Source/loadsave.cpp
  12. 2
      Source/misdat.cpp
  13. 142
      Source/missiles.cpp
  14. 4
      Source/monstdat.cpp
  15. 1920
      Source/monster.cpp
  16. 142
      Source/monster.h
  17. 60
      Source/msg.cpp
  18. 2
      Source/multi.cpp
  19. 16
      Source/objects.cpp
  20. 37
      Source/player.cpp
  21. 26
      Source/qol/monhealthbar.cpp
  22. 8
      Source/quests.cpp
  23. 24
      Source/sync.cpp
  24. 4
      Source/track.cpp

4
Source/control.cpp

@ -905,9 +905,9 @@ void DrawInfoBox(const Surface &out)
if (leveltype != DTYPE_TOWN) {
const auto &monster = Monsters[pcursmonst];
InfoColor = UiFlags::ColorWhite;
InfoString = string_view(monster.mName);
InfoString = string_view(monster.name);
ClearPanel();
if (monster._uniqtype != 0) {
if (monster.uniqType != 0) {
InfoColor = UiFlags::ColorWhitegold;
PrintUniqueHistory();
} else {

4
Source/controls/plrctrls.cpp

@ -226,9 +226,9 @@ bool HasRangedSpell()
bool CanTargetMonster(const Monster &monster)
{
if ((monster._mFlags & (MFLAG_HIDDEN | MFLAG_GOLEM)) != 0)
if ((monster.flags & (MFLAG_HIDDEN | MFLAG_GOLEM)) != 0)
return false;
if (monster._mhitpoints >> 6 <= 0) // dead
if (monster.hitPoints >> 6 <= 0) // dead
return false;
if (!IsTileLit(monster.position.tile)) // not visible

2
Source/controls/touch/renderers.cpp

@ -421,7 +421,7 @@ VirtualGamepadButtonType PrimaryActionButtonRenderer::GetDungeonButtonType()
{
if (pcursmonst != -1) {
const auto &monster = Monsters[pcursmonst];
if (M_Talker(monster) || monster.mtalkmsg != TEXT_NONE)
if (M_Talker(monster) || monster.talkMsg != TEXT_NONE)
return GetTalkButtonType(virtualPadButton->isHeld);
}
return GetAttackButtonType(virtualPadButton->isHeld);

38
Source/cursor.cpp

@ -404,58 +404,58 @@ void CheckCursMove()
if (pcurstemp != -1) {
if (!flipflag && mx + 2 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 2][my + 1] != 0 && IsTileLit({ mx + 2, my + 1 })) {
int mi = abs(dMonster[mx + 2][my + 1]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 1 };
pcursmonst = mi;
}
}
if (flipflag && mx + 1 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 1][my + 2] != 0 && IsTileLit({ mx + 1, my + 2 })) {
int mi = abs(dMonster[mx + 1][my + 2]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 2 };
pcursmonst = mi;
}
}
if (mx + 2 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 2][my + 2] != 0 && IsTileLit({ mx + 2, my + 2 })) {
int mi = abs(dMonster[mx + 2][my + 2]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 2 };
pcursmonst = mi;
}
}
if (mx + 1 < MAXDUNX && !flipflag && dMonster[mx + 1][my] != 0 && IsTileLit({ mx + 1, my })) {
int mi = abs(dMonster[mx + 1][my]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursmonst = mi;
}
}
if (my + 1 < MAXDUNY && flipflag && dMonster[mx][my + 1] != 0 && IsTileLit({ mx, my + 1 })) {
int mi = abs(dMonster[mx][my + 1]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursmonst = mi;
}
}
if (dMonster[mx][my] != 0 && IsTileLit({ mx, my })) {
int mi = abs(dMonster[mx][my]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 1) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 1) != 0) {
cursPosition = { mx, my };
pcursmonst = mi;
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 1][my + 1] != 0 && IsTileLit({ mx + 1, my + 1 })) {
int mi = abs(dMonster[mx + 1][my + 1]) - 1;
if (mi == pcurstemp && Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursmonst = mi;
}
}
if (pcursmonst != -1 && (Monsters[pcursmonst]._mFlags & MFLAG_HIDDEN) != 0) {
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_HIDDEN) != 0) {
pcursmonst = -1;
cursPosition = { mx, my };
}
if (pcursmonst != -1 && (Monsters[pcursmonst]._mFlags & MFLAG_GOLEM) != 0 && (Monsters[pcursmonst]._mFlags & MFLAG_BERSERK) == 0) {
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_GOLEM) != 0 && (Monsters[pcursmonst].flags & MFLAG_BERSERK) == 0) {
pcursmonst = -1;
}
if (pcursmonst != -1) {
@ -464,58 +464,58 @@ void CheckCursMove()
}
if (!flipflag && mx + 2 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 2][my + 1] != 0 && IsTileLit({ mx + 2, my + 1 })) {
int mi = abs(dMonster[mx + 2][my + 1]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 1 };
pcursmonst = mi;
}
}
if (flipflag && mx + 1 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 1][my + 2] != 0 && IsTileLit({ mx + 1, my + 2 })) {
int mi = abs(dMonster[mx + 1][my + 2]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 2 };
pcursmonst = mi;
}
}
if (mx + 2 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 2][my + 2] != 0 && IsTileLit({ mx + 2, my + 2 })) {
int mi = abs(dMonster[mx + 2][my + 2]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 2 };
pcursmonst = mi;
}
}
if (!flipflag && mx + 1 < MAXDUNX && dMonster[mx + 1][my] != 0 && IsTileLit({ mx + 1, my })) {
int mi = abs(dMonster[mx + 1][my]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursmonst = mi;
}
}
if (flipflag && my + 1 < MAXDUNY && dMonster[mx][my + 1] != 0 && IsTileLit({ mx, my + 1 })) {
int mi = abs(dMonster[mx][my + 1]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursmonst = mi;
}
}
if (dMonster[mx][my] != 0 && IsTileLit({ mx, my })) {
int mi = abs(dMonster[mx][my]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 1) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 1) != 0) {
cursPosition = { mx, my };
pcursmonst = mi;
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 1][my + 1] != 0 && IsTileLit({ mx + 1, my + 1 })) {
int mi = abs(dMonster[mx + 1][my + 1]) - 1;
if (Monsters[mi]._mhitpoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().mSelFlag & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursmonst = mi;
}
}
if (pcursmonst != -1 && (Monsters[pcursmonst]._mFlags & MFLAG_HIDDEN) != 0) {
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_HIDDEN) != 0) {
pcursmonst = -1;
cursPosition = { mx, my };
}
if (pcursmonst != -1 && (Monsters[pcursmonst]._mFlags & MFLAG_GOLEM) != 0 && (Monsters[pcursmonst]._mFlags & MFLAG_BERSERK) == 0) {
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_GOLEM) != 0 && (Monsters[pcursmonst].flags & MFLAG_BERSERK) == 0) {
pcursmonst = -1;
}
} else {
@ -661,7 +661,7 @@ void CheckCursMove()
pcursitem = -1;
cursPosition = { mx, my };
}
if (pcursmonst != -1 && (Monsters[pcursmonst]._mFlags & MFLAG_GOLEM) != 0 && (Monsters[pcursmonst]._mFlags & MFLAG_BERSERK) == 0) {
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_GOLEM) != 0 && (Monsters[pcursmonst].flags & MFLAG_BERSERK) == 0) {
pcursmonst = -1;
}
}

10
Source/dead.cpp

@ -57,12 +57,12 @@ void InitCorpses()
for (int i = 0; i < ActiveMonsterCount; i++) {
auto &monster = Monsters[ActiveMonsters[i]];
if (monster._uniqtype != 0) {
if (monster.uniqType != 0) {
InitDeadAnimationFromMonster(Corpses[nd], monster.type());
Corpses[nd].translationPaletteIndex = ActiveMonsters[i] + 1;
nd++;
monster._udeadval = nd;
monster.corpseId = nd;
}
}
@ -78,12 +78,12 @@ void SyncUniqDead()
{
for (int i = 0; i < ActiveMonsterCount; i++) {
auto &monster = Monsters[ActiveMonsters[i]];
if (monster._uniqtype == 0)
if (monster.uniqType == 0)
continue;
for (int dx = 0; dx < MAXDUNX; dx++) {
for (int dy = 0; dy < MAXDUNY; dy++) {
if ((dCorpse[dx][dy] & 0x1F) == monster._udeadval)
ChangeLightXY(monster.mlid, { dx, dy });
if ((dCorpse[dx][dy] & 0x1F) == monster.corpseId)
ChangeLightXY(monster.lightId, { dx, dy });
}
}
}

14
Source/debug.cpp

@ -100,13 +100,13 @@ void PrintDebugMonster(int m)
EventPlrMsg(fmt::format(
"Monster {:d} = {:s}\nX = {:d}, Y = {:d}\nEnemy = {:d}, HP = {:d}\nMode = {:d}, Var1 = {:d}",
m,
monster.mName,
monster.name,
monster.position.tile.x,
monster.position.tile.y,
monster._menemy,
monster._mhitpoints,
static_cast<int>(monster._mmode),
monster._mVar1),
monster.enemy,
monster.hitPoints,
static_cast<int>(monster.mode),
monster.var1),
UiFlags::ColorWhite);
bool bActive = false;
@ -116,7 +116,7 @@ void PrintDebugMonster(int m)
bActive = true;
}
EventPlrMsg(fmt::format("Active List = {:d}, Squelch = {:d}", bActive ? 1 : 0, monster._msquelch), UiFlags::ColorWhite);
EventPlrMsg(fmt::format("Active List = {:d}, Squelch = {:d}", bActive ? 1 : 0, monster.activeForTicks), UiFlags::ColorWhite);
}
void ProcessMessages()
@ -736,7 +736,7 @@ std::string DebugCmdSpawnUniqueMonster(const string_view parameter)
return fmt::format("I could only summon {} Monsters. The rest strike for shorter working hours.", spawnedMonster);
PrepareUniqueMonst(*monster, uniqueIndex, 0, 0, UniqueMonstersData[uniqueIndex]);
ActiveMonsterCount--;
monster->_udeadval = 1;
monster->corpseId = 1;
spawnedMonster += 1;
if (spawnedMonster >= count)

18
Source/diablo.cpp

@ -1219,8 +1219,8 @@ void UnstuckChargers()
}
for (int i = 0; i < ActiveMonsterCount; i++) {
auto &monster = Monsters[ActiveMonsters[i]];
if (monster._mmode == MonsterMode::Charge)
monster._mmode = MonsterMode::Stand;
if (monster.mode == MonsterMode::Charge)
monster.mode = MonsterMode::Stand;
}
}
@ -1229,20 +1229,20 @@ void UpdateMonsterLights()
for (int i = 0; i < ActiveMonsterCount; i++) {
auto &monster = Monsters[ActiveMonsters[i]];
if ((monster._mFlags & MFLAG_BERSERK) != 0) {
if ((monster.flags & MFLAG_BERSERK) != 0) {
int lightRadius = leveltype == DTYPE_NEST ? 9 : 3;
monster.mlid = AddLight(monster.position.tile, lightRadius);
monster.lightId = AddLight(monster.position.tile, lightRadius);
}
if (monster.mlid != NO_LIGHT) {
if (monster.mlid == MyPlayer->_plid) { // Fix old saves where some monsters had 0 instead of NO_LIGHT
monster.mlid = NO_LIGHT;
if (monster.lightId != NO_LIGHT) {
if (monster.lightId == MyPlayer->_plid) { // Fix old saves where some monsters had 0 instead of NO_LIGHT
monster.lightId = NO_LIGHT;
continue;
}
Light &light = Lights[monster.mlid];
Light &light = Lights[monster.lightId];
if (monster.position.tile != light.position.tile) {
ChangeLightXY(monster.mlid, monster.position.tile);
ChangeLightXY(monster.lightId, monster.position.tile);
}
}
}

36
Source/engine/render/scrollrt.cpp

@ -332,7 +332,7 @@ void DrawMissilePrivate(const Surface &out, const Missile &missile, Point target
const Point missileRenderPosition { targetBufferPosition + missile.position.offsetForRendering - Displacement { missile._miAnimWidth2, 0 } };
CelSprite cel { missile._miAnimData, missile._miAnimWidth };
if (missile._miUniqTrans != 0)
Cl2DrawTRN(out, missileRenderPosition.x, missileRenderPosition.y, cel, nCel, Monsters[missile._misource].uniqueTRN.get());
Cl2DrawTRN(out, missileRenderPosition.x, missileRenderPosition.y, cel, nCel, Monsters[missile._misource].uniqueMonsterTRN.get());
else if (missile._miLightFlag)
Cl2DrawLight(out, missileRenderPosition.x, missileRenderPosition.y, cel, nCel);
else
@ -363,8 +363,8 @@ void DrawMissile(const Surface &out, Point tilePosition, Point targetBufferPosit
*/
void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosition, const Monster &monster)
{
if (!monster.AnimInfo.celSprite) {
Log("Draw Monster \"{}\": NULL Cel Buffer", monster.mName);
if (!monster.animInfo.celSprite) {
Log("Draw Monster \"{}\": NULL Cel Buffer", monster.name);
return;
}
@ -429,29 +429,29 @@ void DrawMonster(const Surface &out, Point tilePosition, Point targetBufferPosit
}
};
int nCel = monster.AnimInfo.getFrameToUseForRendering();
const uint32_t frames = LoadLE32(monster.AnimInfo.celSprite->Data());
int nCel = monster.animInfo.getFrameToUseForRendering();
const uint32_t frames = LoadLE32(monster.animInfo.celSprite->Data());
if (nCel < 0 || frames > 50 || nCel >= static_cast<int>(frames)) {
Log(
"Draw Monster \"{}\" {}: facing {}, frame {} of {}",
monster.mName,
getMonsterModeDisplayName(monster._mmode),
DirectionToString(monster._mdir),
monster.name,
getMonsterModeDisplayName(monster.mode),
DirectionToString(monster.direction),
nCel,
frames);
return;
}
const auto &cel = *monster.AnimInfo.celSprite;
const auto &cel = *monster.animInfo.celSprite;
if (!IsTileLit(tilePosition)) {
Cl2DrawTRN(out, targetBufferPosition.x, targetBufferPosition.y, cel, nCel, GetInfravisionTRN());
return;
}
uint8_t *trn = nullptr;
if (monster._uniqtype != 0)
trn = monster.uniqueTRN.get();
if (monster._mmode == MonsterMode::Petrified)
if (monster.uniqType != 0)
trn = monster.uniqueMonsterTRN.get();
if (monster.mode == MonsterMode::Petrified)
trn = GetStoneTRN();
if (MyPlayer->_pInfraFlag && LightTableIndex > 8)
trn = GetInfravisionTRN();
@ -768,20 +768,20 @@ void DrawMonsterHelper(const Surface &out, Point tilePosition, Point targetBuffe
}
const auto &monster = Monsters[mi];
if ((monster._mFlags & MFLAG_HIDDEN) != 0) {
if ((monster.flags & MFLAG_HIDDEN) != 0) {
return;
}
CelSprite cel = *monster.AnimInfo.celSprite;
CelSprite cel = *monster.animInfo.celSprite;
Displacement offset = monster.position.offset;
if (monster.IsWalking()) {
offset = GetOffsetForWalking(monster.AnimInfo, monster._mdir);
if (monster.isWalking()) {
offset = GetOffsetForWalking(monster.animInfo, monster.direction);
}
const Point monsterRenderPosition { targetBufferPosition + offset - Displacement { CalculateWidth2(cel.Width()), 0 } };
if (mi == pcursmonst) {
Cl2DrawOutline(out, 233, monsterRenderPosition.x, monsterRenderPosition.y, cel, monster.AnimInfo.getFrameToUseForRendering());
Cl2DrawOutline(out, 233, monsterRenderPosition.x, monsterRenderPosition.y, cel, monster.animInfo.getFrameToUseForRendering());
}
DrawMonster(out, tilePosition, monsterRenderPosition, monster);
}
@ -848,7 +848,7 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit
break;
}
if (pDeadGuy->translationPaletteIndex != 0) {
uint8_t *trn = Monsters[pDeadGuy->translationPaletteIndex - 1].uniqueTRN.get();
uint8_t *trn = Monsters[pDeadGuy->translationPaletteIndex - 1].uniqueMonsterTRN.get();
Cl2DrawTRN(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel, trn);
} else {
Cl2DrawLight(out, px, targetBufferPosition.y, CelSprite(pCelBuff, pDeadGuy->width), nCel);

2
Source/inv.cpp

@ -2090,7 +2090,7 @@ void DoTelekinesis()
NetSendCmdGItem(true, CMD_REQUESTAGITEM, MyPlayerId, MyPlayerId, pcursitem);
if (pcursmonst != -1) {
auto &monter = Monsters[pcursmonst];
if (!M_Talker(monter) && monter.mtalkmsg == TEXT_NONE)
if (!M_Talker(monter) && monter.talkMsg == TEXT_NONE)
NetSendCmdParam1(true, CMD_KNOCKBACK, pcursmonst);
}
NewCursor(CURSOR_HAND);

18
Source/items.cpp

@ -1349,7 +1349,7 @@ int RndUItem(Monster *monster)
if (AllItemsList[i].iRnd == IDROP_NEVER)
okflag = false;
if (monster != nullptr) {
if (monster->mLevel < AllItemsList[i].iMinMLvl)
if (monster->level < AllItemsList[i].iMinMLvl)
okflag = false;
} else {
if (2 * curlv < AllItemsList[i].iMinMLvl)
@ -3026,12 +3026,12 @@ int RndItem(const Monster &monster)
if (!IsItemAvailable(i))
continue;
if (AllItemsList[i].iRnd == IDROP_DOUBLE && monster.mLevel >= AllItemsList[i].iMinMLvl
if (AllItemsList[i].iRnd == IDROP_DOUBLE && monster.level >= AllItemsList[i].iMinMLvl
&& ri < 512) {
ril[ri] = i;
ri++;
}
if (AllItemsList[i].iRnd != IDROP_NEVER && monster.mLevel >= AllItemsList[i].iMinMLvl
if (AllItemsList[i].iRnd != IDROP_NEVER && monster.level >= AllItemsList[i].iMinMLvl
&& ri < 512) {
ril[ri] = i;
ri++;
@ -3070,7 +3070,7 @@ void SpawnItem(Monster &monster, Point position, bool sendmsg)
int idx;
bool onlygood = true;
if (monster._uniqtype != 0 || ((monster.data().mTreasure & T_UNIQ) != 0 && gbIsMultiplayer)) {
if (monster.uniqType != 0 || ((monster.data().mTreasure & T_UNIQ) != 0 && gbIsMultiplayer)) {
idx = RndUItem(&monster);
if (idx < 0) {
SpawnUnique((_unique_items) - (idx + 1), position);
@ -3099,7 +3099,7 @@ void SpawnItem(Monster &monster, Point position, bool sendmsg)
int ii = AllocateItem();
auto &item = Items[ii];
GetSuperItemSpace(position, ii);
int uper = monster._uniqtype != 0 ? 15 : 1;
int uper = monster.uniqType != 0 ? 15 : 1;
int8_t mLevel = monster.data().mLevel;
if (!gbIsHellfire && monster.type().type == MT_DIABLO)
@ -4462,8 +4462,8 @@ std::string DebugSpawnItem(std::string itemName)
uint32_t begin = SDL_GetTicks();
Monster fake_m;
fake_m._mMTidx = 0;
fake_m._uniqtype = 0;
fake_m.levelType = 0;
fake_m.uniqType = 0;
int i = 0;
for (;; i++) {
@ -4476,7 +4476,7 @@ std::string DebugSpawnItem(std::string itemName)
if (i > max_iter)
return fmt::format("Item not found in {:d} tries!", max_iter);
fake_m.mLevel = dist(BetterRng) % CF_LEVEL + 1;
fake_m.level = dist(BetterRng) % CF_LEVEL + 1;
int idx = RndItem(fake_m);
if (idx > 1) {
@ -4487,7 +4487,7 @@ std::string DebugSpawnItem(std::string itemName)
Point bkp = item.position;
item = {};
item.position = bkp;
SetupAllItems(item, idx, AdvanceRndSeed(), fake_m.mLevel, 1, false, false, false);
SetupAllItems(item, idx, AdvanceRndSeed(), fake_m.level, 1, false, false, false);
std::string tmp(item._iIName);
std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c) { return std::tolower(c); });

194
Source/loadsave.cpp

@ -564,15 +564,15 @@ bool gbSkipSync = false;
void LoadMonster(LoadHelper *file, Monster &monster)
{
monster._mMTidx = file->NextLE<int32_t>();
monster._mmode = static_cast<MonsterMode>(file->NextLE<int32_t>());
monster._mgoal = static_cast<monster_goal>(file->NextLE<uint8_t>());
monster.levelType = file->NextLE<int32_t>();
monster.mode = static_cast<MonsterMode>(file->NextLE<int32_t>());
monster.goal = static_cast<monster_goal>(file->NextLE<uint8_t>());
file->Skip(3); // Alignment
monster._mgoalvar1 = file->NextLE<int32_t>();
monster._mgoalvar2 = file->NextLE<int32_t>();
monster._mgoalvar3 = file->NextLE<int32_t>();
monster.goalVar1 = file->NextLE<int32_t>();
monster.goalVar2 = file->NextLE<int32_t>();
monster.goalVar3 = file->NextLE<int32_t>();
file->Skip(4); // Unused
monster._pathcount = file->NextLE<uint8_t>();
monster.pathCount = file->NextLE<uint8_t>();
file->Skip(3); // Alignment
monster.position.tile.x = file->NextLE<int32_t>();
monster.position.tile.y = file->NextLE<int32_t>();
@ -584,77 +584,77 @@ void LoadMonster(LoadHelper *file, Monster &monster)
monster.position.offset.deltaY = file->NextLE<int32_t>();
monster.position.velocity.deltaX = file->NextLE<int32_t>();
monster.position.velocity.deltaY = file->NextLE<int32_t>();
monster._mdir = static_cast<Direction>(file->NextLE<int32_t>());
monster._menemy = file->NextLE<int32_t>();
monster.direction = static_cast<Direction>(file->NextLE<int32_t>());
monster.enemy = file->NextLE<int32_t>();
monster.enemyPosition.x = file->NextLE<uint8_t>();
monster.enemyPosition.y = file->NextLE<uint8_t>();
file->Skip(2); // Unused
file->Skip(4); // Skip pointer _mAnimData
monster.AnimInfo = {};
monster.AnimInfo.ticksPerFrame = file->NextLENarrow<int32_t, int8_t>();
monster.animInfo = {};
monster.animInfo.ticksPerFrame = file->NextLENarrow<int32_t, int8_t>();
// Ensure that we can increase the tickCounterOfCurrentFrame at least once without overflow (needed for backwards compatibility for sitting gargoyles)
monster.AnimInfo.tickCounterOfCurrentFrame = file->NextLENarrow<int32_t, int8_t>(1) - 1;
monster.AnimInfo.numberOfFrames = file->NextLENarrow<int32_t, int8_t>();
monster.AnimInfo.currentFrame = file->NextLENarrow<int32_t, int8_t>(-1);
monster.animInfo.tickCounterOfCurrentFrame = file->NextLENarrow<int32_t, int8_t>(1) - 1;
monster.animInfo.numberOfFrames = file->NextLENarrow<int32_t, int8_t>();
monster.animInfo.currentFrame = file->NextLENarrow<int32_t, int8_t>(-1);
file->Skip(4); // Skip _meflag
monster._mDelFlag = file->NextBool32();
monster._mVar1 = file->NextLE<int32_t>();
monster._mVar2 = file->NextLE<int32_t>();
monster._mVar3 = file->NextLE<int32_t>();
monster.isInvalid = file->NextBool32();
monster.var1 = file->NextLE<int32_t>();
monster.var2 = file->NextLE<int32_t>();
monster.var3 = file->NextLE<int32_t>();
monster.position.temp.x = file->NextLE<int32_t>();
monster.position.temp.y = file->NextLE<int32_t>();
monster.position.offset2.deltaX = file->NextLE<int32_t>();
monster.position.offset2.deltaY = file->NextLE<int32_t>();
file->Skip(4); // Skip actionFrame
monster._mmaxhp = file->NextLE<int32_t>();
monster._mhitpoints = file->NextLE<int32_t>();
monster.maxHitPoints = file->NextLE<int32_t>();
monster.hitPoints = file->NextLE<int32_t>();
monster._mAi = static_cast<_mai_id>(file->NextLE<uint8_t>());
monster._mint = file->NextLE<uint8_t>();
monster.ai = static_cast<_mai_id>(file->NextLE<uint8_t>());
monster.intelligence = file->NextLE<uint8_t>();
file->Skip(2); // Alignment
monster._mFlags = file->NextLE<uint32_t>();
monster._msquelch = file->NextLE<uint8_t>();
monster.flags = file->NextLE<uint32_t>();
monster.activeForTicks = file->NextLE<uint8_t>();
file->Skip(3); // Alignment
file->Skip(4); // Unused
monster.position.last.x = file->NextLE<int32_t>();
monster.position.last.y = file->NextLE<int32_t>();
monster._mRndSeed = file->NextLE<uint32_t>();
monster._mAISeed = file->NextLE<uint32_t>();
monster.rndItemSeed = file->NextLE<uint32_t>();
monster.aiSeed = file->NextLE<uint32_t>();
file->Skip(4); // Unused
monster._uniqtype = file->NextLE<uint8_t>();
monster._uniqtrans = file->NextLE<uint8_t>();
monster._udeadval = file->NextLE<int8_t>();
monster.uniqType = file->NextLE<uint8_t>();
monster.uniqTrans = file->NextLE<uint8_t>();
monster.corpseId = file->NextLE<int8_t>();
monster.mWhoHit = file->NextLE<int8_t>();
monster.mLevel = file->NextLE<int8_t>();
monster.whoHit = file->NextLE<int8_t>();
monster.level = file->NextLE<int8_t>();
file->Skip(1); // Alignment
monster.mExp = file->NextLE<uint16_t>();
monster.exp = file->NextLE<uint16_t>();
if ((monster._mFlags & MFLAG_GOLEM) != 0) // Don't skip for golems
monster.mHit = file->NextLE<uint8_t>();
if ((monster.flags & MFLAG_GOLEM) != 0) // Don't skip for golems
monster.hit = file->NextLE<uint8_t>();
else
file->Skip(1); // Skip mHit as it's already initialized
monster.mMinDamage = file->NextLE<uint8_t>();
monster.mMaxDamage = file->NextLE<uint8_t>();
file->Skip(1); // Skip mHit2 as it's already initialized
monster.mMinDamage2 = file->NextLE<uint8_t>();
monster.mMaxDamage2 = file->NextLE<uint8_t>();
monster.mArmorClass = file->NextLE<uint8_t>();
file->Skip(1); // Skip hit as it's already initialized
monster.minDamage = file->NextLE<uint8_t>();
monster.maxDamage = file->NextLE<uint8_t>();
file->Skip(1); // Skip hit2 as it's already initialized
monster.minDamage2 = file->NextLE<uint8_t>();
monster.maxDamage2 = file->NextLE<uint8_t>();
monster.armorClass = file->NextLE<uint8_t>();
file->Skip(1); // Alignment
monster.mMagicRes = file->NextLE<uint16_t>();
monster.magicResistance = file->NextLE<uint16_t>();
file->Skip(2); // Alignment
monster.mtalkmsg = static_cast<_speech_id>(file->NextLE<int32_t>());
if (monster.mtalkmsg == TEXT_KING1) // Fix original bad mapping of NONE for monsters
monster.mtalkmsg = TEXT_NONE;
monster.talkMsg = static_cast<_speech_id>(file->NextLE<int32_t>());
if (monster.talkMsg == TEXT_KING1) // Fix original bad mapping of NONE for monsters
monster.talkMsg = TEXT_NONE;
monster.leader = file->NextLE<uint8_t>();
monster.leaderRelation = static_cast<LeaderRelation>(file->NextLE<uint8_t>());
monster.packsize = file->NextLE<uint8_t>();
monster.mlid = file->NextLE<int8_t>();
if (monster.mlid == 0)
monster.mlid = NO_LIGHT; // Correct incorect values in old saves
monster.packSize = file->NextLE<uint8_t>();
monster.lightId = file->NextLE<int8_t>();
if (monster.lightId == 0)
monster.lightId = NO_LIGHT; // Correct incorect values in old saves
// Omit pointer mName;
@ -669,17 +669,17 @@ void LoadMonster(LoadHelper *file, Monster &monster)
*/
void SyncPackSize(Monster &leader)
{
if (leader._uniqtype == 0)
if (leader.uniqType == 0)
return;
if (leader._mAi != AI_SCAV)
if (leader.ai != AI_SCAV)
return;
leader.packsize = 0;
leader.packSize = 0;
for (int i = 0; i < ActiveMonsterCount; i++) {
auto &minion = Monsters[ActiveMonsters[i]];
if (minion.leaderRelation == LeaderRelation::Leashed && &Monsters[minion.leader] == &leader)
leader.packsize++;
leader.packSize++;
}
}
@ -1306,15 +1306,15 @@ void SavePlayer(SaveHelper &file, const Player &player)
void SaveMonster(SaveHelper *file, Monster &monster)
{
file->WriteLE<int32_t>(monster._mMTidx);
file->WriteLE<int32_t>(static_cast<int>(monster._mmode));
file->WriteLE<uint8_t>(monster._mgoal);
file->WriteLE<int32_t>(monster.levelType);
file->WriteLE<int32_t>(static_cast<int>(monster.mode));
file->WriteLE<uint8_t>(monster.goal);
file->Skip(3); // Alignment
file->WriteLE<int32_t>(monster._mgoalvar1);
file->WriteLE<int32_t>(monster._mgoalvar2);
file->WriteLE<int32_t>(monster._mgoalvar3);
file->WriteLE<int32_t>(monster.goalVar1);
file->WriteLE<int32_t>(monster.goalVar2);
file->WriteLE<int32_t>(monster.goalVar3);
file->Skip(4); // Unused
file->WriteLE<uint8_t>(monster._pathcount);
file->WriteLE<uint8_t>(monster.pathCount);
file->Skip(3); // Alignment
file->WriteLE<int32_t>(monster.position.tile.x);
file->WriteLE<int32_t>(monster.position.tile.y);
@ -1326,72 +1326,72 @@ void SaveMonster(SaveHelper *file, Monster &monster)
file->WriteLE<int32_t>(monster.position.offset.deltaY);
file->WriteLE<int32_t>(monster.position.velocity.deltaX);
file->WriteLE<int32_t>(monster.position.velocity.deltaY);
file->WriteLE<int32_t>(static_cast<int32_t>(monster._mdir));
file->WriteLE<int32_t>(monster._menemy);
file->WriteLE<int32_t>(static_cast<int32_t>(monster.direction));
file->WriteLE<int32_t>(monster.enemy);
file->WriteLE<uint8_t>(monster.enemyPosition.x);
file->WriteLE<uint8_t>(monster.enemyPosition.y);
file->Skip(2); // Unused
file->Skip(4); // Skip pointer _mAnimData
file->WriteLE<int32_t>(monster.AnimInfo.ticksPerFrame);
file->WriteLE<int32_t>(monster.AnimInfo.tickCounterOfCurrentFrame);
file->WriteLE<int32_t>(monster.AnimInfo.numberOfFrames);
file->WriteLE<int32_t>(monster.AnimInfo.currentFrame + 1);
file->WriteLE<int32_t>(monster.animInfo.ticksPerFrame);
file->WriteLE<int32_t>(monster.animInfo.tickCounterOfCurrentFrame);
file->WriteLE<int32_t>(monster.animInfo.numberOfFrames);
file->WriteLE<int32_t>(monster.animInfo.currentFrame + 1);
file->Skip<uint32_t>(); // Skip _meflag
file->WriteLE<uint32_t>(monster._mDelFlag ? 1 : 0);
file->WriteLE<int32_t>(monster._mVar1);
file->WriteLE<int32_t>(monster._mVar2);
file->WriteLE<int32_t>(monster._mVar3);
file->WriteLE<uint32_t>(monster.isInvalid ? 1 : 0);
file->WriteLE<int32_t>(monster.var1);
file->WriteLE<int32_t>(monster.var2);
file->WriteLE<int32_t>(monster.var3);
file->WriteLE<int32_t>(monster.position.temp.x);
file->WriteLE<int32_t>(monster.position.temp.y);
file->WriteLE<int32_t>(monster.position.offset2.deltaX);
file->WriteLE<int32_t>(monster.position.offset2.deltaY);
file->Skip<int32_t>(); // Skip _mVar8
file->WriteLE<int32_t>(monster._mmaxhp);
file->WriteLE<int32_t>(monster._mhitpoints);
file->WriteLE<int32_t>(monster.maxHitPoints);
file->WriteLE<int32_t>(monster.hitPoints);
file->WriteLE<uint8_t>(monster._mAi);
file->WriteLE<uint8_t>(monster._mint);
file->WriteLE<uint8_t>(monster.ai);
file->WriteLE<uint8_t>(monster.intelligence);
file->Skip(2); // Alignment
file->WriteLE<uint32_t>(monster._mFlags);
file->WriteLE<uint8_t>(monster._msquelch);
file->WriteLE<uint32_t>(monster.flags);
file->WriteLE<uint8_t>(monster.activeForTicks);
file->Skip(3); // Alignment
file->Skip(4); // Unused
file->WriteLE<int32_t>(monster.position.last.x);
file->WriteLE<int32_t>(monster.position.last.y);
file->WriteLE<uint32_t>(monster._mRndSeed);
file->WriteLE<uint32_t>(monster._mAISeed);
file->WriteLE<uint32_t>(monster.rndItemSeed);
file->WriteLE<uint32_t>(monster.aiSeed);
file->Skip(4); // Unused
file->WriteLE<uint8_t>(monster._uniqtype);
file->WriteLE<uint8_t>(monster._uniqtrans);
file->WriteLE<int8_t>(monster._udeadval);
file->WriteLE<uint8_t>(monster.uniqType);
file->WriteLE<uint8_t>(monster.uniqTrans);
file->WriteLE<int8_t>(monster.corpseId);
file->WriteLE<int8_t>(monster.mWhoHit);
file->WriteLE<int8_t>(monster.mLevel);
file->WriteLE<int8_t>(monster.whoHit);
file->WriteLE<int8_t>(monster.level);
file->Skip(1); // Alignment
file->WriteLE<uint16_t>(monster.mExp);
file->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.mHit, std::numeric_limits<uint8_t>::max()))); // For backwards compatibility
file->WriteLE<uint8_t>(monster.mMinDamage);
file->WriteLE<uint8_t>(monster.mMaxDamage);
file->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.mHit2, std::numeric_limits<uint8_t>::max()))); // For backwards compatibility
file->WriteLE<uint8_t>(monster.mMinDamage2);
file->WriteLE<uint8_t>(monster.mMaxDamage2);
file->WriteLE<uint8_t>(monster.mArmorClass);
file->WriteLE<uint16_t>(monster.exp);
file->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.hit, std::numeric_limits<uint8_t>::max()))); // For backwards compatibility
file->WriteLE<uint8_t>(monster.minDamage);
file->WriteLE<uint8_t>(monster.maxDamage);
file->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.hit2, std::numeric_limits<uint8_t>::max()))); // For backwards compatibility
file->WriteLE<uint8_t>(monster.minDamage2);
file->WriteLE<uint8_t>(monster.maxDamage2);
file->WriteLE<uint8_t>(monster.armorClass);
file->Skip(1); // Alignment
file->WriteLE<uint16_t>(monster.mMagicRes);
file->WriteLE<uint16_t>(monster.magicResistance);
file->Skip(2); // Alignment
file->WriteLE<int32_t>(monster.mtalkmsg == TEXT_NONE ? 0 : monster.mtalkmsg); // Replicate original bad mapping of none for monsters
file->WriteLE<int32_t>(monster.talkMsg == TEXT_NONE ? 0 : monster.talkMsg); // Replicate original bad mapping of none for monsters
file->WriteLE<uint8_t>(monster.leader);
file->WriteLE<uint8_t>(static_cast<std::uint8_t>(monster.leaderRelation));
file->WriteLE<uint8_t>(monster.packsize);
file->WriteLE<uint8_t>(monster.packSize);
// vanilla compatibility
if (monster.mlid == NO_LIGHT)
if (monster.lightId == NO_LIGHT)
file->WriteLE<int8_t>(0);
else
file->WriteLE<int8_t>(monster.mlid);
file->WriteLE<int8_t>(monster.lightId);
// Omit pointer mName;
}

2
Source/misdat.cpp

@ -15,7 +15,7 @@ namespace devilution {
/** Data related to each missile ID. */
MissileData MissilesData[] = {
// clang-format off
// mAddProc, mProc, mName, mDraw, mType, mResist, mFileNum, mlSFX, miSFX, MovementDistribution;
// mAddProc, mProc, name, mDraw, mType, mResist, mFileNum, mlSFX, miSFX, MovementDistribution;
{ &AddArrow, &MI_Arrow, MIS_ARROW, true, 0, MISR_NONE, MFILE_ARROWS, SFX_NONE, SFX_NONE, MissileMovementDistrubution::Blockable },
{ &AddFirebolt, &MI_Firebolt, MIS_FIREBOLT, true, 1, MISR_FIRE, MFILE_FIREBA, LS_FBOLT1, LS_FIRIMP2, MissileMovementDistrubution::Blockable },
{ &AddGuardian, &MI_Guardian, MIS_GUARDIAN, true, 1, MISR_NONE, MFILE_GUARD, LS_GUARD, LS_GUARDLAN, MissileMovementDistrubution::Disabled },

142
Source/missiles.cpp

@ -186,7 +186,7 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, miss
{
auto &monster = Monsters[monsterId];
if (!monster.IsPossibleToHit() || monster.IsImmune(t))
if (!monster.isPossibleToHit() || monster.isImmune(t))
return false;
int hit = GenerateRnd(100);
@ -194,18 +194,18 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, miss
const Player &player = Players[pnum];
if (MissilesData[t].mType == 0) {
hper = player.GetRangedPiercingToHit();
hper -= player.CalculateArmorPierce(monster.mArmorClass, false);
hper -= player.CalculateArmorPierce(monster.armorClass, false);
hper -= (dist * dist) / 2;
} else {
hper = player.GetMagicToHit() - (monster.mLevel * 2) - dist;
hper = player.GetMagicToHit() - (monster.level * 2) - dist;
}
hper = clamp(hper, 5, 95);
if (monster._mmode == MonsterMode::Petrified)
if (monster.mode == MonsterMode::Petrified)
hit = 0;
if (monster.TryLiftGargoyle())
if (monster.tryLiftGargoyle())
return true;
if (hit >= hper) {
@ -217,7 +217,7 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, miss
int dam;
if (t == MIS_BONESPIRIT) {
dam = monster._mhitpoints / 3 >> 6;
dam = monster.hitPoints / 3 >> 6;
} else {
dam = mindam + GenerateRnd(maxdam - mindam + 1);
}
@ -231,31 +231,31 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, miss
if (monster.data().mMonstClass == MonsterClass::Demon && HasAnyOf(player._pIFlags, ItemSpecialEffect::TripleDemonDamage))
dam *= 3;
}
bool resist = monster.IsResistant(t);
bool resist = monster.isResistant(t);
if (!shift)
dam <<= 6;
if (resist)
dam >>= 2;
if (pnum == MyPlayerId)
monster._mhitpoints -= dam;
monster.hitPoints -= dam;
if ((gbIsHellfire && HasAnyOf(player._pIFlags, ItemSpecialEffect::NoHealOnMonsters)) || (!gbIsHellfire && HasAnyOf(player._pIFlags, ItemSpecialEffect::FireArrows)))
monster._mFlags |= MFLAG_NOHEAL;
monster.flags |= MFLAG_NOHEAL;
if (monster._mhitpoints >> 6 <= 0) {
if (monster.hitPoints >> 6 <= 0) {
M_StartKill(monsterId, pnum);
} else if (resist) {
PlayEffect(monster, 1);
} else {
if (monster._mmode != MonsterMode::Petrified && MissilesData[t].mType == 0 && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))
if (monster.mode != MonsterMode::Petrified && MissilesData[t].mType == 0 && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))
M_GetKnockback(monster);
if (monster.type().type != MT_GOLEM)
M_StartHit(monster, pnum, dam);
}
if (monster._msquelch == 0) {
monster._msquelch = UINT8_MAX;
if (monster.activeForTicks == 0) {
monster.activeForTicks = UINT8_MAX;
monster.position.last = player.position.tile;
}
@ -389,12 +389,12 @@ void CheckMissileCol(Missile &missile, int minDamage, int maxDamage, bool isDama
bool isMonsterHit = false;
int mid = dMonster[mx][my];
if (mid > 0 || (mid != 0 && Monsters[abs(mid) - 1]._mmode == MonsterMode::Petrified)) {
if (mid > 0 || (mid != 0 && Monsters[abs(mid) - 1].mode == MonsterMode::Petrified)) {
mid = abs(mid) - 1;
if (missile.IsTrap()
|| (missile._micaster == TARGET_PLAYERS
&& (Monsters[missile._misource]._mFlags & MFLAG_TARGETS_MONSTER) != 0
&& ((Monsters[mid]._mFlags & MFLAG_GOLEM) != 0 || (Monsters[missile._misource]._mFlags & MFLAG_BERSERK) != 0))) {
&& (Monsters[missile._misource].flags & MFLAG_TARGETS_MONSTER) != 0
&& ((Monsters[mid].flags & MFLAG_GOLEM) != 0 || (Monsters[missile._misource].flags & MFLAG_BERSERK) != 0))) {
isMonsterHit = MonsterTrapHit(mid, minDamage, maxDamage, missile._midist, missile._mitype, isDamageShifted);
} else if (IsAnyOf(missile._micaster, TARGET_BOTH, TARGET_MONSTERS)) {
isMonsterHit = MonsterMHit(missile._misource, mid, minDamage, maxDamage, missile._midist, missile._mitype, isDamageShifted);
@ -596,7 +596,7 @@ bool GuardianTryFireAt(Missile &missile, Point target)
const Monster &monster = Monsters[mid];
if (monster.type().type == MT_GOLEM)
return false;
if (monster._mhitpoints >> 6 <= 0)
if (monster.hitPoints >> 6 <= 0)
return false;
Direction dir = GetDirection(position, target);
@ -844,34 +844,34 @@ bool MonsterTrapHit(int monsterId, int mindam, int maxdam, int dist, missile_id
{
auto &monster = Monsters[monsterId];
if (!monster.IsPossibleToHit() || monster.IsImmune(t))
if (!monster.isPossibleToHit() || monster.isImmune(t))
return false;
int hit = GenerateRnd(100);
int hper = 90 - (BYTE)monster.mArmorClass - dist;
int hper = 90 - (BYTE)monster.armorClass - dist;
hper = clamp(hper, 5, 95);
if (monster.TryLiftGargoyle())
if (monster.tryLiftGargoyle())
return true;
if (hit >= hper && monster._mmode != MonsterMode::Petrified) {
if (hit >= hper && monster.mode != MonsterMode::Petrified) {
#ifdef _DEBUG
if (!DebugGodMode)
#endif
return false;
}
bool resist = monster.IsResistant(t);
bool resist = monster.isResistant(t);
int dam = mindam + GenerateRnd(maxdam - mindam + 1);
if (!shift)
dam <<= 6;
if (resist)
monster._mhitpoints -= dam / 4;
monster.hitPoints -= dam / 4;
else
monster._mhitpoints -= dam;
monster.hitPoints -= dam;
#ifdef _DEBUG
if (DebugGodMode)
monster._mhitpoints = 0;
monster.hitPoints = 0;
#endif
if (monster._mhitpoints >> 6 <= 0) {
if (monster.hitPoints >> 6 <= 0) {
StartMonsterDeath(monster, -1, true);
} else if (resist) {
PlayEffect(monster, 1);
@ -909,15 +909,15 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missil
if (MissilesData[mtype].mType == 0) {
int tac = player.GetArmor();
if (monster != nullptr) {
hper = monster->mHit
+ ((monster->mLevel - player._pLevel) * 2)
hper = monster->hit
+ ((monster->level - player._pLevel) * 2)
+ 30
- (dist * 2) - tac;
} else {
hper = 100 - (tac / 2) - (dist * 2);
}
} else if (monster != nullptr) {
hper += (monster->mLevel * 2) - (player._pLevel * 2) - (dist * 2);
hper += (monster->level * 2) - (player._pLevel * 2) - (dist * 2);
}
int minhit = 10;
@ -941,7 +941,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missil
int blkper = player.GetBlockChance(false);
if (monster != nullptr)
blkper -= (monster->mLevel - player._pLevel) * 2;
blkper -= (monster->level - player._pLevel) * 2;
blkper = clamp(blkper, 0, 100);
int8_t resper;
@ -1140,15 +1140,15 @@ void AddBerserk(Missile &missile, const AddMissileParameter &parameter)
const Monster &monster = Monsters[monsterId];
if (monster.type().type == MT_GOLEM)
return false;
if ((monster._mFlags & MFLAG_BERSERK) != 0)
if ((monster.flags & MFLAG_BERSERK) != 0)
return false;
if (monster._uniqtype != 0 || monster._mAi == AI_DIABLO)
if (monster.uniqType != 0 || monster.ai == AI_DIABLO)
return false;
if (IsAnyOf(monster._mmode, MonsterMode::FadeIn, MonsterMode::FadeOut, MonsterMode::Charge))
if (IsAnyOf(monster.mode, MonsterMode::FadeIn, MonsterMode::FadeOut, MonsterMode::Charge))
return false;
if ((monster.mMagicRes & IMMUNE_MAGIC) != 0)
if ((monster.magicResistance & IMMUNE_MAGIC) != 0)
return false;
if ((monster.mMagicRes & RESIST_MAGIC) != 0 && ((monster.mMagicRes & RESIST_MAGIC) != 1 || GenerateRnd(2) != 0))
if ((monster.magicResistance & RESIST_MAGIC) != 0 && ((monster.magicResistance & RESIST_MAGIC) != 1 || GenerateRnd(2) != 0))
return false;
return true;
@ -1159,13 +1159,13 @@ void AddBerserk(Missile &missile, const AddMissileParameter &parameter)
auto &monster = Monsters[abs(dMonster[targetMonsterPosition->x][targetMonsterPosition->y]) - 1];
Player &player = Players[missile._misource];
const int slvl = player.GetSpellLevel(SPL_BERSERK);
monster._mFlags |= MFLAG_BERSERK | MFLAG_GOLEM;
monster.mMinDamage = (GenerateRnd(10) + 120) * monster.mMinDamage / 100 + slvl;
monster.mMaxDamage = (GenerateRnd(10) + 120) * monster.mMaxDamage / 100 + slvl;
monster.mMinDamage2 = (GenerateRnd(10) + 120) * monster.mMinDamage2 / 100 + slvl;
monster.mMaxDamage2 = (GenerateRnd(10) + 120) * monster.mMaxDamage2 / 100 + slvl;
monster.flags |= MFLAG_BERSERK | MFLAG_GOLEM;
monster.minDamage = (GenerateRnd(10) + 120) * monster.minDamage / 100 + slvl;
monster.maxDamage = (GenerateRnd(10) + 120) * monster.maxDamage / 100 + slvl;
monster.minDamage2 = (GenerateRnd(10) + 120) * monster.minDamage2 / 100 + slvl;
monster.maxDamage2 = (GenerateRnd(10) + 120) * monster.maxDamage2 / 100 + slvl;
int lightRadius = leveltype == DTYPE_NEST ? 9 : 3;
monster.mlid = AddLight(monster.position.tile, lightRadius);
monster.lightId = AddLight(monster.position.tile, lightRadius);
UseMana(player, SPL_BERSERK);
}
}
@ -1894,7 +1894,7 @@ void AddFlash(Missile &missile, const AddMissileParameter & /*parameter*/)
missile._midam += missile._midam / 2;
UseMana(player, SPL_FLASH);
} else {
missile._midam = Monsters[missile._misource].mLevel * 2;
missile._midam = Monsters[missile._misource].level * 2;
}
} else {
missile._midam = currlevel / 2;
@ -2041,8 +2041,8 @@ void AddRhino(Missile &missile, const AddMissileParameter &parameter)
InitMissileAnimationFromMonster(missile, parameter.midir, monster, graphic);
if (IsAnyOf(monster.type().type, MT_NSNAKE, MT_RSNAKE, MT_BSNAKE, MT_GSNAKE))
missile._miAnimFrame = 7;
if (monster._uniqtype != 0) {
missile._mlid = monster.mlid;
if (monster.uniqType != 0) {
missile._mlid = monster.lightId;
}
PutMissile(missile);
}
@ -2083,7 +2083,7 @@ void AddAcid(Missile &missile, const AddMissileParameter &parameter)
UpdateMissileVelocity(missile, parameter.dst, 16);
SetMissDir(missile, GetDirection16(missile.position.start, parameter.dst));
if (!gbIsHellfire || (missile.position.velocity.deltaX & 0xFFFF0000) != 0 || (missile.position.velocity.deltaY & 0xFFFF0000) != 0)
missile._mirange = 5 * (Monsters[missile._misource]._mint + 4);
missile._mirange = 5 * (Monsters[missile._misource].intelligence + 4);
else
missile._mirange = 1;
missile._mlid = NO_LIGHT;
@ -2096,7 +2096,7 @@ void AddAcidpud(Missile &missile, const AddMissileParameter & /*parameter*/)
{
missile._miLightFlag = true;
int monst = missile._misource;
missile._mirange = GenerateRnd(15) + 40 * (Monsters[monst]._mint + 1);
missile._mirange = GenerateRnd(15) + 40 * (Monsters[monst].intelligence + 1);
missile._miPreFlag = true;
}
@ -2118,7 +2118,7 @@ void AddStone(Missile &missile, const AddMissileParameter &parameter)
if (IsAnyOf(monster.type().type, MT_GOLEM, MT_DIABLO, MT_NAKRUL)) {
return false;
}
if (IsAnyOf(monster._mmode, MonsterMode::FadeIn, MonsterMode::FadeOut, MonsterMode::Charge)) {
if (IsAnyOf(monster.mode, MonsterMode::FadeIn, MonsterMode::FadeOut, MonsterMode::Charge)) {
return false;
}
@ -2134,9 +2134,9 @@ void AddStone(Missile &missile, const AddMissileParameter &parameter)
// Petrify the targeted monster
int monsterId = abs(dMonster[targetMonsterPosition->x][targetMonsterPosition->y]) - 1;
auto &monster = Monsters[monsterId];
missile.var1 = static_cast<int>(monster._mmode);
missile.var1 = static_cast<int>(monster.mode);
missile.var2 = monsterId;
monster.Petrify();
monster.petrify();
Player &player = Players[missile._misource];
@ -2429,7 +2429,7 @@ void AddFlame(Missile &missile, const AddMissileParameter &parameter)
missile._midam = 8 * i + 16 + ((8 * i + 16) / 2);
} else {
auto &monster = Monsters[missile._misource];
missile._midam = monster.mMinDamage + GenerateRnd(monster.mMaxDamage - monster.mMinDamage + 1);
missile._midam = monster.minDamage + GenerateRnd(monster.maxDamage - monster.minDamage + 1);
}
}
@ -2587,8 +2587,8 @@ Missile *AddMissile(Point src, Point dst, Direction midir, missile_id mitype, mi
if (!missile.IsTrap() && micaster == TARGET_PLAYERS) {
Monster &monster = Monsters[id];
if (monster._uniqtype != 0) {
missile._miUniqTrans = monster._uniqtrans + 1;
if (monster.uniqType != 0) {
missile._miUniqTrans = monster.uniqTrans + 1;
}
}
@ -2624,8 +2624,8 @@ void MI_LArrow(Missile &missile)
maxd = player._pIMaxDam;
} else {
Monster &monster = Monsters[p];
mind = monster.mMinDamage;
maxd = monster.mMaxDamage;
mind = monster.minDamage;
maxd = monster.maxDamage;
}
} else {
mind = GenerateRnd(10) + 1 + currlevel;
@ -2709,8 +2709,8 @@ void MI_Arrow(Missile &missile)
maxd = player._pIMaxDam;
} else {
auto &monster = Monsters[p];
mind = monster.mMinDamage;
maxd = monster.mMaxDamage;
mind = monster.minDamage;
maxd = monster.maxDamage;
}
} else {
mind = currlevel;
@ -2747,7 +2747,7 @@ void MI_Firebolt(Missile &missile)
}
} else {
auto &monster = Monsters[p];
d = monster.mMinDamage + GenerateRnd(monster.mMaxDamage - monster.mMinDamage + 1);
d = monster.minDamage + GenerateRnd(monster.maxDamage - monster.minDamage + 1);
}
} else {
d = currlevel + GenerateRnd(2 * currlevel);
@ -2894,8 +2894,8 @@ void MI_Fireball(Missile &missile)
if (missile._micaster != TARGET_MONSTERS) {
auto &monster = Monsters[missile._misource];
minDam = monster.mMinDamage;
maxDam = monster.mMaxDamage;
minDam = monster.minDamage;
maxDam = monster.maxDamage;
}
MoveMissileAndCheckMissileCol(missile, minDam, maxDam, true, false);
if (missile._mirange == 0) {
@ -3176,7 +3176,7 @@ void MI_Lightctrl(Missile &missile)
dam = (GenerateRnd(2) + GenerateRnd(Players[missile._misource]._pLevel) + 2) << 6;
} else {
auto &monster = Monsters[missile._misource];
dam = 2 * (monster.mMinDamage + GenerateRnd(monster.mMaxDamage - monster.mMinDamage + 1));
dam = 2 * (monster.minDamage + GenerateRnd(monster.maxDamage - monster.minDamage + 1));
}
SpawnLightning(missile, dam);
@ -3489,24 +3489,24 @@ void MI_Stone(Missile &missile)
{
missile._mirange--;
auto &monster = Monsters[missile.var2];
if (monster._mhitpoints == 0 && missile._miAnimType != MFILE_SHATTER1) {
if (monster.hitPoints == 0 && missile._miAnimType != MFILE_SHATTER1) {
missile._mimfnum = 0;
missile._miDrawFlag = true;
SetMissAnim(missile, MFILE_SHATTER1);
missile._mirange = 11;
}
if (monster._mmode != MonsterMode::Petrified) {
if (monster.mode != MonsterMode::Petrified) {
missile._miDelFlag = true;
return;
}
if (missile._mirange == 0) {
missile._miDelFlag = true;
if (monster._mhitpoints > 0) {
monster._mmode = static_cast<MonsterMode>(missile.var1);
monster.AnimInfo.isPetrified = false;
if (monster.hitPoints > 0) {
monster.mode = static_cast<MonsterMode>(missile.var1);
monster.animInfo.isPetrified = false;
} else {
AddCorpse(monster.position.tile, stonendx, monster._mdir);
AddCorpse(monster.position.tile, stonendx, monster.direction);
}
}
if (missile._miAnimType == MFILE_SHATTER1)
@ -3529,7 +3529,7 @@ void MI_Rhino(Missile &missile)
{
int monst = missile._misource;
auto &monster = Monsters[monst];
if (monster._mmode != MonsterMode::Charge) {
if (monster.mode != MonsterMode::Charge) {
missile._miDelFlag = true;
return;
}
@ -3537,7 +3537,7 @@ void MI_Rhino(Missile &missile)
Point prevPos = missile.position.tile;
Point newPosSnake;
dMonster[prevPos.x][prevPos.y] = 0;
if (monster._mAi == AI_SNAKE) {
if (monster.ai == AI_SNAKE) {
missile.position.traveled += missile.position.velocity * 2;
UpdateMissilePos(missile);
newPosSnake = missile.position.tile;
@ -3547,7 +3547,7 @@ void MI_Rhino(Missile &missile)
}
UpdateMissilePos(missile);
Point newPos = missile.position.tile;
if (!IsTileAvailable(monster, newPos) || (monster._mAi == AI_SNAKE && !IsTileAvailable(monster, newPosSnake))) {
if (!IsTileAvailable(monster, newPos) || (monster.ai == AI_SNAKE && !IsTileAvailable(monster, newPosSnake))) {
MissToMonst(missile, prevPos);
missile._miDelFlag = true;
return;
@ -3556,7 +3556,7 @@ void MI_Rhino(Missile &missile)
monster.position.old = newPos;
monster.position.tile = newPos;
dMonster[newPos.x][newPos.y] = -(monst + 1);
if (monster._uniqtype != 0)
if (monster.uniqType != 0)
ChangeLightXY(missile._mlid, newPos);
MoveMissilePos(missile);
PutMissile(missile);
@ -3900,7 +3900,7 @@ void MI_Bonespirit(Missile &missile)
missile._mirange = 255;
auto *monster = FindClosest(c, 19);
if (monster != nullptr) {
missile._midam = monster->_mhitpoints >> 7;
missile._midam = monster->hitPoints >> 7;
SetMissDir(missile, GetDirection(c, monster->position.tile));
UpdateMissileVelocity(missile, monster->position.tile, 16);
} else {

4
Source/monstdat.cpp

@ -25,7 +25,7 @@ constexpr uint16_t Uniq(_unique_items item)
/** Contains the data related to each monster ID. */
const MonsterData MonstersData[] = {
// clang-format off
//_monster_id mName, GraphicType, sndfile, TransFile, availability, width, mImage, has_special, snd_special, has_trans, Frames[6], rate[6], mMinDLvl, mMaxDLvl, mLevel, mMinHP, mMaxHP, mAi, mFlags , mInt, mHit, mAFNum, mMinDamage, mMaxDamage, mHit2, mAFNum2, mMinDamage2, mMaxDamage2, mArmorClass, mMonstClass , mMagicRes , mMagicRes2 , mSelFlag, mTreasure, mExp
//_monster_id name, GraphicType, sndfile, TransFile, availability, width, mImage, has_special, snd_special, has_trans, Frames[6], rate[6], mMinDLvl, mMaxDLvl, level, mMinHP, mMaxHP, mAi, mFlags , mInt, hit, mAFNum, minDamage, maxDamage, hit2, mAFNum2, minDamage2, maxDamage2, armorClass, mMonstClass , magicResistance , mMagicRes2 , mSelFlag, mTreasure, exp
// TRANSLATORS: Monster Block start
/* MT_NZOMBIE */ { P_("monster", "Zombie"), "Zombie\\Zombie", "Monsters\\Zombie\\Zombie", nullptr, MonsterAvailability::Always, 128, 799, false, false, false, { 11, 24, 12, 6, 16, 0 }, { 4, 1, 1, 1, 1, 1 }, 1, 2, 1, 4, 7, AI_ZOMBIE, 0 , 0, 10, 8, 2, 5, 0, 0, 0, 0, 5, MonsterClass::Undead, IMMUNE_MAGIC | IMMUNE_NULL_40 , IMMUNE_MAGIC | IMMUNE_NULL_40 , 3, 0, 54 },
@ -336,7 +336,7 @@ const _monster_id MonstConvTbl[] = {
/** Contains the data related to each unique monster ID. */
const UniqueMonsterData UniqueMonstersData[] = {
// clang-format off
// type, mName, mTrnName, mlevel, mmaxhp, mAi, mint, mMinDamage, mMaxDamage, mMagicRes, monsterPack, customToHit, customArmorClass, mtalkmsg
// type, name, mTrnName, mlevel, mmaxhp, mAi, mint, minDamage, maxDamage, magicResistance, monsterPack, customToHit, customArmorClass, talkMsg
// TRANSLATORS: Unique Monster Block start
{ MT_NGOATMC, P_("monster", "Gharbad the Weak"), "BSDB", 4, 120, AI_GARBUD, 3, 8, 16, IMMUNE_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::None, 0, 0, TEXT_GARBUD1 },
{ MT_SKING, P_("monster", "Skeleton King"), "GENRL", 0, 240, AI_SKELKING, 3, 6, 16, IMMUNE_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_NULL_40, UniqueMonsterPack::Independent, 0, 0, TEXT_NONE },

1920
Source/monster.cpp

File diff suppressed because it is too large Load Diff

142
Source/monster.h

@ -46,7 +46,7 @@ enum monster_flag : uint16_t {
// clang-format on
};
/** This enum contains indexes from UniqueMonstersData array for special unique monsters (usually quest related) */
/** Indexes from UniqueMonstersData array for special unique monsters (usually quest related) */
enum : uint8_t {
UMT_GARBUD,
UMT_SKELKING,
@ -149,7 +149,6 @@ struct AnimStruct {
struct CMonster {
_monster_id type;
/** placeflag enum as a flags*/
uint8_t placeFlags;
std::unique_ptr<byte[]> animData;
AnimStruct anims[6];
@ -168,100 +167,113 @@ struct CMonster {
extern CMonster LevelMonsterTypes[MaxLvlMTypes];
struct Monster { // note: missing field _mAFNum
const char *mName;
std::unique_ptr<uint8_t[]> uniqueTRN;
AnimationInfo AnimInfo;
int _mgoalvar1;
int _mgoalvar2;
int _mgoalvar3;
int _mVar1;
int _mVar2;
int _mVar3;
int _mmaxhp;
int _mhitpoints;
uint32_t _mFlags;
const char *name;
std::unique_ptr<uint8_t[]> uniqueMonsterTRN;
/**
* @brief Contains information for current animation
*/
AnimationInfo animInfo;
/** Specifies current goal of the monster */
monster_goal goal;
/** Specifies monster's behaviour regarding moving and changing goals. */
int goalVar1;
/**
* @brief Specifies turning direction for @p RoundWalk in most cases.
* Used in custom way by @p FallenAi, @p SnakeAi, @p M_FallenFear and @p FallenAi.
*/
int goalVar2;
/**
* @brief Controls monster's behaviour regarding special actions.
* Used only by @p ScavengerAi and @p MegaAi.
*/
int goalVar3;
int var1;
int var2;
int var3;
int maxHitPoints;
int hitPoints;
uint32_t flags;
/** Seed used to determine item drops on death */
uint32_t _mRndSeed;
uint32_t rndItemSeed;
/** Seed used to determine AI behaviour/sync sounds in multiplayer games? */
uint32_t _mAISeed;
uint16_t mExp;
uint16_t mHit;
uint16_t mHit2;
uint16_t mMagicRes;
_speech_id mtalkmsg;
uint32_t aiSeed;
uint16_t exp;
uint16_t hit;
uint16_t hit2;
uint16_t magicResistance;
_speech_id talkMsg;
ActorPosition position;
/** Usually corresponds to the enemy's future position */
WorldTilePosition enemyPosition;
uint8_t _mMTidx;
MonsterMode _mmode;
monster_goal _mgoal;
uint8_t _pathcount;
uint8_t levelType;
MonsterMode mode;
uint8_t pathCount;
/** Direction faced by monster (direction enum) */
Direction _mdir;
/** The current target of the monster. An index in to either the plr or monster array based on the _meflag value. */
uint8_t _menemy;
Direction direction;
/** The current target of the monster. An index in to either the player or monster array based on the _meflag value. */
uint8_t enemy;
bool isInvalid;
_mai_id ai;
/**
* @brief Contains information for current animation
* @brief Specifies monster's behaviour across various actions.
* Generally, when monster thinks it decides what to do based on this value, among other things.
* Higher values should result in more aggressive behaviour (e.g. some monsters use this to calculate the @p AiDelay).
*/
bool _mDelFlag;
_mai_id _mAi;
uint8_t _mint;
uint8_t _msquelch;
uint8_t _uniqtype;
uint8_t _uniqtrans;
int8_t _udeadval;
int8_t mWhoHit;
int8_t mLevel;
uint8_t mMinDamage;
uint8_t mMaxDamage;
uint8_t mMinDamage2;
uint8_t mMaxDamage2;
uint8_t mArmorClass;
uint8_t intelligence;
/** Stores information for how many ticks the monster will remain active */
uint8_t activeForTicks;
uint8_t uniqType;
uint8_t uniqTrans;
int8_t corpseId;
int8_t whoHit;
int8_t level;
uint8_t minDamage;
uint8_t maxDamage;
uint8_t minDamage2;
uint8_t maxDamage2;
uint8_t armorClass;
uint8_t leader;
LeaderRelation leaderRelation;
uint8_t packsize;
int8_t mlid; // BUGFIX -1 is used when not emitting light this should be signed (fixed)
uint8_t packSize;
int8_t lightId;
/**
* @brief Sets the current cell sprite to match the desired direction and animation sequence
* @brief Sets the current cell sprite to match the desired desiredDirection and animation sequence
* @param graphic Animation sequence of interest
* @param direction Desired direction the monster should be visually facing
* @param desiredDirection Desired desiredDirection the monster should be visually facing
*/
void ChangeAnimationData(MonsterGraphic graphic, Direction direction)
void changeAnimationData(MonsterGraphic graphic, Direction desiredDirection)
{
auto &animationData = type().getAnimData(graphic);
// Passing the Frames and rate properties here is only relevant when initialising a monster, but doesn't cause any harm when switching animations.
this->AnimInfo.changeAnimationData(animationData.getCelSpritesForDirection(direction), animationData.frames, animationData.rate);
this->animInfo.changeAnimationData(animationData.getCelSpritesForDirection(desiredDirection), animationData.frames, animationData.rate);
}
/**
* @brief Sets the current cell sprite to match the desired animation sequence using the direction the monster is currently facing
* @param graphic Animation sequence of interest
*/
void ChangeAnimationData(MonsterGraphic graphic)
void changeAnimationData(MonsterGraphic graphic)
{
this->ChangeAnimationData(graphic, this->_mdir);
this->changeAnimationData(graphic, this->direction);
}
/**
* @brief Check thats the correct stand Animation is loaded. This is needed if direction is changed (monster stands and looks to player).
* @param mdir direction of the monster
* @brief Check if the correct stand Animation is loaded. This is needed if direction is changed (monster stands and looks at the player).
* @param dir direction of the monster
*/
void CheckStandAnimationIsLoaded(Direction mdir);
void checkStandAnimationIsLoaded(Direction dir);
/**
* @brief Sets _mmode to MonsterMode::Petrified
* @brief Sets mode to MonsterMode::Petrified
*/
void Petrify();
void petrify();
const CMonster &type() const
{
return LevelMonsterTypes[_mMTidx];
return LevelMonsterTypes[levelType];
}
const MonsterData &data() const
@ -279,11 +291,11 @@ struct Monster { // note: missing field _mAFNum
/**
* @brief Is the monster currently walking?
*/
bool IsWalking() const;
bool IsImmune(missile_id mitype) const;
bool IsResistant(missile_id mitype) const;
bool IsPossibleToHit() const;
bool TryLiftGargoyle();
bool isWalking() const;
bool isImmune(missile_id mitype) const;
bool isResistant(missile_id mitype) const;
bool isPossibleToHit() const;
bool tryLiftGargoyle();
};
extern int LevelMonsterTypeCount;

60
Source/msg.cpp

@ -62,7 +62,7 @@ struct DMonsterStr {
Direction _mdir;
uint8_t _menemy;
uint8_t _mactive;
int32_t _mhitpoints;
int32_t hitPoints;
int8_t mWhoHit;
};
@ -506,7 +506,7 @@ void DeltaSyncGolem(const TCmdGolem &message, int pnum, uint8_t level)
monster._mactive = UINT8_MAX;
monster._menemy = message._menemy;
monster._mdir = message._mdir;
monster._mhitpoints = message._mhitpoints;
monster.hitPoints = message._mhitpoints;
}
void DeltaLeaveSync(uint8_t bLevel)
@ -523,16 +523,16 @@ void DeltaLeaveSync(uint8_t bLevel)
for (int i = 0; i < ActiveMonsterCount; i++) {
int ma = ActiveMonsters[i];
auto &monster = Monsters[ma];
if (monster._mhitpoints == 0)
if (monster.hitPoints == 0)
continue;
sgbDeltaChanged = true;
DMonsterStr &delta = deltaLevel.monster[ma];
delta.position = monster.position.tile;
delta._mdir = monster._mdir;
delta._mdir = monster.direction;
delta._menemy = encode_enemy(monster);
delta._mhitpoints = monster._mhitpoints;
delta._mactive = monster._msquelch;
delta.mWhoHit = monster.mWhoHit;
delta.hitPoints = monster.hitPoints;
delta._mactive = monster.activeForTicks;
delta.mWhoHit = monster.whoHit;
}
LocalLevels.insert_or_assign(bLevel, AutomapView);
}
@ -1588,11 +1588,11 @@ DWORD OnMonstDamage(const TCmd *pCmd, int pnum)
Player &player = Players[pnum];
if (player.isOnActiveLevel() && message.wMon < MaxMonsters) {
auto &monster = Monsters[message.wMon];
monster.mWhoHit |= 1 << pnum;
if (monster._mhitpoints > 0) {
monster._mhitpoints -= message.dwDam;
if ((monster._mhitpoints >> 6) < 1)
monster._mhitpoints = 1 << 6;
monster.whoHit |= 1 << pnum;
if (monster.hitPoints > 0) {
monster.hitPoints -= message.dwDam;
if ((monster.hitPoints >> 6) < 1)
monster.hitPoints = 1 << 6;
delta_monster_hp(monster, player);
}
}
@ -2217,8 +2217,8 @@ void delta_kill_monster(int mi, Point position, const Player &player)
sgbDeltaChanged = true;
DMonsterStr *pD = &GetDeltaLevel(player).monster[mi];
pD->position = position;
pD->_mdir = Monsters[mi]._mdir;
pD->_mhitpoints = 0;
pD->_mdir = Monsters[mi].direction;
pD->hitPoints = 0;
}
void delta_monster_hp(const Monster &monster, const Player &player)
@ -2228,8 +2228,8 @@ void delta_monster_hp(const Monster &monster, const Player &player)
sgbDeltaChanged = true;
DMonsterStr *pD = &GetDeltaLevel(player).monster[monster.getId()];
if (pD->_mhitpoints > monster._mhitpoints)
pD->_mhitpoints = monster._mhitpoints;
if (pD->hitPoints > monster.hitPoints)
pD->hitPoints = monster.hitPoints;
}
void delta_sync_monster(const TSyncMonster &monsterSync, uint8_t level)
@ -2241,14 +2241,14 @@ void delta_sync_monster(const TSyncMonster &monsterSync, uint8_t level)
sgbDeltaChanged = true;
DMonsterStr &monster = GetDeltaLevel(level).monster[monsterSync._mndx];
if (monster._mhitpoints == 0)
if (monster.hitPoints == 0)
return;
monster.position.x = monsterSync._mx;
monster.position.y = monsterSync._my;
monster._mactive = UINT8_MAX;
monster._menemy = monsterSync._menemy;
monster._mhitpoints = monsterSync._mhitpoints;
monster.hitPoints = monsterSync._mhitpoints;
monster.mWhoHit = monsterSync.mWhoHit;
}
@ -2410,20 +2410,20 @@ void DeltaLoadLevel()
monster.position.old = position;
monster.position.future = position;
}
if (deltaLevel.monster[i]._mhitpoints != -1) {
monster._mhitpoints = deltaLevel.monster[i]._mhitpoints;
monster.mWhoHit = deltaLevel.monster[i].mWhoHit;
if (deltaLevel.monster[i].hitPoints != -1) {
monster.hitPoints = deltaLevel.monster[i].hitPoints;
monster.whoHit = deltaLevel.monster[i].mWhoHit;
}
if (deltaLevel.monster[i]._mhitpoints == 0) {
if (deltaLevel.monster[i].hitPoints == 0) {
M_ClearSquares(monster);
if (monster._mAi != AI_DIABLO) {
if (monster._uniqtype == 0) {
AddCorpse(monster.position.tile, monster.type().corpseId, monster._mdir);
if (monster.ai != AI_DIABLO) {
if (monster.uniqType == 0) {
AddCorpse(monster.position.tile, monster.type().corpseId, monster.direction);
} else {
AddCorpse(monster.position.tile, monster._udeadval, monster._mdir);
AddCorpse(monster.position.tile, monster.corpseId, monster.direction);
}
}
monster._mDelFlag = true;
monster.isInvalid = true;
M_UpdateLeader(i);
} else {
decode_enemy(monster, deltaLevel.monster[i]._menemy);
@ -2431,11 +2431,11 @@ void DeltaLoadLevel()
dMonster[monster.position.tile.x][monster.position.tile.y] = i + 1;
if (monster.type().type == MT_GOLEM) {
GolumAi(i);
monster._mFlags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM);
monster.flags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM);
} else {
M_StartStand(monster, monster._mdir);
M_StartStand(monster, monster.direction);
}
monster._msquelch = deltaLevel.monster[i]._mactive;
monster.activeForTicks = deltaLevel.monster[i]._mactive;
}
}
auto localLevelIt = LocalLevels.find(localLevel);

2
Source/multi.cpp

@ -193,7 +193,7 @@ void MonsterSeeds()
sgdwGameLoops++;
const uint32_t seed = (sgdwGameLoops >> 8) | (sgdwGameLoops << 24); // _rotr(sgdwGameLoops, 8)
for (int i = 0; i < MaxMonsters; i++)
Monsters[i]._mAISeed = seed + i;
Monsters[i].aiSeed = seed + i;
}
void HandleTurnUpperBit(int pnum)

16
Source/objects.cpp

@ -3438,14 +3438,14 @@ void OperateBookCase(int i, bool sendmsg, bool sendLootMsg)
if (Quests[Q_ZHAR].IsAvailable()) {
auto &zhar = Monsters[MAX_PLRS];
if (zhar._mmode == MonsterMode::Stand // prevents playing the "angry" message for the second time if zhar got aggroed by losing vision and talking again
&& zhar._uniqtype - 1 == UMT_ZHAR
&& zhar._msquelch == UINT8_MAX
&& zhar._mhitpoints > 0) {
zhar.mtalkmsg = TEXT_ZHAR2;
M_StartStand(zhar, zhar._mdir); // BUGFIX: first parameter in call to M_StartStand should be MAX_PLRS, not 0. (fixed)
zhar._mgoal = MGOAL_ATTACK2;
zhar._mmode = MonsterMode::Talk;
if (zhar.mode == MonsterMode::Stand // prevents playing the "angry" message for the second time if zhar got aggroed by losing vision and talking again
&& zhar.uniqType - 1 == UMT_ZHAR
&& zhar.activeForTicks == UINT8_MAX
&& zhar.hitPoints > 0) {
zhar.talkMsg = TEXT_ZHAR2;
M_StartStand(zhar, zhar.direction); // BUGFIX: first parameter in call to M_StartStand should be MAX_PLRS, not 0. (fixed)
zhar.goal = MGOAL_ATTACK2;
zhar.mode = MonsterMode::Talk;
}
}
if (sendmsg)

37
Source/player.cpp

@ -810,7 +810,7 @@ bool PlrHitMonst(int pnum, int monsterId, bool adjacentDamage = false)
}
Player &player = Players[pnum];
if (!monster.IsPossibleToHit())
if (!monster.isPossibleToHit())
return false;
if (adjacentDamage) {
@ -821,14 +821,14 @@ bool PlrHitMonst(int pnum, int monsterId, bool adjacentDamage = false)
}
int hit = GenerateRnd(100);
if (monster._mmode == MonsterMode::Petrified) {
if (monster.mode == MonsterMode::Petrified) {
hit = 0;
}
hper += player.GetMeleePiercingToHit() - player.CalculateArmorPierce(monster.mArmorClass, true);
hper += player.GetMeleePiercingToHit() - player.CalculateArmorPierce(monster.armorClass, true);
hper = clamp(hper, 5, 95);
if (monster.TryLiftGargoyle())
if (monster.tryLiftGargoyle())
return true;
if (hit >= hper) {
@ -889,7 +889,7 @@ bool PlrHitMonst(int pnum, int monsterId, bool adjacentDamage = false)
dam *= 3;
}
if (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::Doppelganger) && monster.type().type != MT_DIABLO && monster._uniqtype == 0 && GenerateRnd(100) < 10) {
if (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::Doppelganger) && monster.type().type != MT_DIABLO && monster.uniqType == 0 && GenerateRnd(100) < 10) {
AddDoppelganger(monster);
}
@ -912,7 +912,7 @@ bool PlrHitMonst(int pnum, int monsterId, bool adjacentDamage = false)
}
dam *= 2;
}
monster._mhitpoints -= dam;
monster.hitPoints -= dam;
}
int skdam = 0;
@ -963,21 +963,20 @@ bool PlrHitMonst(int pnum, int monsterId, bool adjacentDamage = false)
drawhpflag = true;
}
if (HasAnyOf(player._pIFlags, ItemSpecialEffect::NoHealOnPlayer)) { // Why is there a different ItemSpecialEffect here? (see missile.cpp) is this a BUG?
monster._mFlags |= MFLAG_NOHEAL;
monster.flags |= MFLAG_NOHEAL;
}
#ifdef _DEBUG
if (DebugGodMode) {
monster._mhitpoints = 0; /* double check */
monster.hitPoints = 0; /* double check */
}
#endif
if ((monster._mhitpoints >> 6) <= 0) {
if ((monster.hitPoints >> 6) <= 0) {
M_StartKill(monsterId, pnum);
} else {
if (monster._mmode != MonsterMode::Petrified && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))
if (monster.mode != MonsterMode::Petrified && HasAnyOf(player._pIFlags, ItemSpecialEffect::Knockback))
M_GetKnockback(monster);
M_StartHit(monster, pnum, dam);
}
return true;
}
@ -1455,7 +1454,7 @@ void CheckNewPath(int pnum, bool pmWillBeCalled)
case ACTION_RATTACKMON:
case ACTION_SPELLMON:
monster = &Monsters[targetId];
if ((monster->_mhitpoints >> 6) <= 0) {
if ((monster->hitPoints >> 6) <= 0) {
player.Stop();
return;
}
@ -1503,7 +1502,7 @@ void CheckNewPath(int pnum, bool pmWillBeCalled)
if (x < 2 && y < 2) {
ClrPlrPath(player);
if (player.destAction == ACTION_ATTACKMON && monster->mtalkmsg != TEXT_NONE && monster->mtalkmsg != TEXT_VILE14) {
if (player.destAction == ACTION_ATTACKMON && monster->talkMsg != TEXT_NONE && monster->talkMsg != TEXT_VILE14) {
TalktoMonster(*monster);
} else {
StartAttack(pnum, d);
@ -1578,7 +1577,7 @@ void CheckNewPath(int pnum, bool pmWillBeCalled)
y = abs(player.position.tile.y - monster->position.future.y);
if (x <= 1 && y <= 1) {
d = GetDirection(player.position.future, monster->position.future);
if (monster->mtalkmsg != TEXT_NONE && monster->mtalkmsg != TEXT_VILE14) {
if (monster->talkMsg != TEXT_NONE && monster->talkMsg != TEXT_VILE14) {
TalktoMonster(*monster);
} else {
StartAttack(pnum, d);
@ -1599,7 +1598,7 @@ void CheckNewPath(int pnum, bool pmWillBeCalled)
break;
case ACTION_RATTACKMON:
d = GetDirection(player.position.future, monster->position.future);
if (monster->mtalkmsg != TEXT_NONE && monster->mtalkmsg != TEXT_VILE14) {
if (monster->talkMsg != TEXT_NONE && monster->talkMsg != TEXT_VILE14) {
TalktoMonster(*monster);
} else {
StartRangeAttack(pnum, d, monster->position.future.x, monster->position.future.y);
@ -3188,18 +3187,18 @@ void RemovePlrMissiles(const Player &player)
auto &golem = Monsters[MyPlayerId];
if (golem.position.tile.x != 1 || golem.position.tile.y != 0) {
M_StartKill(MyPlayerId, MyPlayerId);
AddCorpse(golem.position.tile, golem.type().corpseId, golem._mdir);
AddCorpse(golem.position.tile, golem.type().corpseId, golem.direction);
int mx = golem.position.tile.x;
int my = golem.position.tile.y;
dMonster[mx][my] = 0;
golem._mDelFlag = true;
golem.isInvalid = true;
DeleteMonsterList();
}
}
for (auto &missile : Missiles) {
if (missile._mitype == MIS_STONE && &Players[missile._misource] == &player) {
Monsters[missile.var2]._mmode = static_cast<MonsterMode>(missile.var1);
Monsters[missile.var2].mode = static_cast<MonsterMode>(missile.var1);
}
}
}
@ -3429,7 +3428,7 @@ bool PosOkPlayer(const Player &player, Point position)
if (dMonster[position.x][position.y] <= 0) {
return false;
}
if ((Monsters[dMonster[position.x][position.y] - 1]._mhitpoints >> 6) > 0) {
if ((Monsters[dMonster[position.x][position.y] - 1].hitPoints >> 6) > 0) {
return false;
}
}

26
Source/qol/monhealthbar.cpp

@ -87,20 +87,20 @@ void DrawMonsterHealthBar(const Surface &out)
const int border = 3;
int multiplier = 0;
int currLife = monster._mhitpoints;
int currLife = monster.hitPoints;
// lifestealing monsters can reach HP exceeding their max
if (monster._mhitpoints > monster._mmaxhp) {
multiplier = monster._mhitpoints / monster._mmaxhp;
currLife = monster._mhitpoints - monster._mmaxhp * multiplier;
if (monster.hitPoints > monster.maxHitPoints) {
multiplier = monster.hitPoints / monster.maxHitPoints;
currLife = monster.hitPoints - monster.maxHitPoints * multiplier;
if (currLife == 0 && multiplier > 0) {
multiplier--;
currLife = monster._mmaxhp;
currLife = monster.maxHitPoints;
}
}
DrawArt(out, position, &healthBox);
DrawHalfTransparentRectTo(out, position.x + border, position.y + border, width - (border * 2), height - (border * 2));
int barProgress = (barWidth * currLife) / monster._mmaxhp;
int barProgress = (barWidth * currLife) / monster.maxHitPoints;
if (barProgress != 0) {
DrawArt(out, position + Displacement { border + 1, border + 1 }, multiplier > 0 ? &healthBlue : &health, 0, barProgress, height - (border * 2) - 2);
}
@ -132,27 +132,27 @@ void DrawMonsterHealthBar(const Surface &out)
}
UiFlags style = UiFlags::AlignCenter | UiFlags::VerticalCenter;
DrawString(out, monster.mName, { position + Displacement { -1, 1 }, { width, height } }, style | UiFlags::ColorBlack);
if (monster._uniqtype != 0)
DrawString(out, monster.name, { position + Displacement { -1, 1 }, { width, height } }, style | UiFlags::ColorBlack);
if (monster.uniqType != 0)
style |= UiFlags::ColorWhitegold;
else if (monster.leader != 0)
style |= UiFlags::ColorBlue;
else
style |= UiFlags::ColorWhite;
DrawString(out, monster.mName, { position, { width, height } }, style);
DrawString(out, monster.name, { position, { width, height } }, style);
if (multiplier > 0)
DrawString(out, fmt::format("x{:d}", multiplier), { position, { width - 2, height } }, UiFlags::ColorWhite | UiFlags::AlignRight | UiFlags::VerticalCenter);
if (monster._uniqtype != 0 || MonsterKillCounts[monster.type().type] >= 15) {
if (monster.uniqType != 0 || MonsterKillCounts[monster.type().type] >= 15) {
monster_resistance immunes[] = { IMMUNE_MAGIC, IMMUNE_FIRE, IMMUNE_LIGHTNING };
monster_resistance resists[] = { RESIST_MAGIC, RESIST_FIRE, RESIST_LIGHTNING };
int resOffset = 5;
for (int i = 0; i < 3; i++) {
if ((monster.mMagicRes & immunes[i]) != 0) {
if ((monster.magicResistance & immunes[i]) != 0) {
DrawArt(out, position + Displacement { resOffset, height - 6 }, &resistance, i * 2 + 1);
resOffset += resistance.w() + 2;
} else if ((monster.mMagicRes & resists[i]) != 0) {
} else if ((monster.magicResistance & resists[i]) != 0) {
DrawArt(out, position + Displacement { resOffset, height - 6 }, &resistance, i * 2);
resOffset += resistance.w() + 2;
}
@ -161,7 +161,7 @@ void DrawMonsterHealthBar(const Surface &out)
int tagOffset = 5;
for (int i = 0; i < MAX_PLRS; i++) {
if (1 << i & monster.mWhoHit) {
if (1 << i & monster.whoHit) {
DrawArt(out, position + Displacement { tagOffset, height - 31 }, &playerExpTags, i + 1);
} else if (Players[i].plractive) {
DrawArt(out, position + Displacement { tagOffset, height - 31 }, &playerExpTags, 0);

8
Source/quests.cpp

@ -418,13 +418,13 @@ void CheckQuestKill(const Monster &monster, bool sendmsg)
myPlayer.Say(HeroSpeech::TheSpiritsOfTheDeadAreNowAvenged, 30);
if (sendmsg)
NetSendCmdQuest(true, quest);
} else if (monster._uniqtype - 1 == UMT_GARBUD) { //"Gharbad the Weak"
} else if (monster.uniqType - 1 == UMT_GARBUD) { //"Gharbad the Weak"
Quests[Q_GARBUD]._qactive = QUEST_DONE;
myPlayer.Say(HeroSpeech::ImNotImpressed, 30);
} else if (monster._uniqtype - 1 == UMT_ZHAR) { //"Zhar the Mad"
} else if (monster.uniqType - 1 == UMT_ZHAR) { //"Zhar the Mad"
Quests[Q_ZHAR]._qactive = QUEST_DONE;
myPlayer.Say(HeroSpeech::ImSorryDidIBreakYourConcentration, 30);
} else if (monster._uniqtype - 1 == UMT_LAZARUS) { //"Arch-Bishop Lazarus"
} else if (monster.uniqType - 1 == UMT_LAZARUS) { //"Arch-Bishop Lazarus"
auto &betrayerQuest = Quests[Q_BETRAYER];
betrayerQuest._qactive = QUEST_DONE;
myPlayer.Say(HeroSpeech::YourMadnessEndsHereBetrayer, 30);
@ -451,7 +451,7 @@ void CheckQuestKill(const Monster &monster, bool sendmsg)
betrayerQuest._qvar2 = 4;
AddMissile({ 35, 32 }, { 35, 32 }, Direction::South, MIS_RPORTAL, TARGET_MONSTERS, MyPlayerId, 0, 0);
}
} else if (monster._uniqtype - 1 == UMT_WARLORD) { //"Warlord of Blood"
} else if (monster.uniqType - 1 == UMT_WARLORD) { //"Warlord of Blood"
Quests[Q_WARLORD]._qactive = QUEST_DONE;
myPlayer.Say(HeroSpeech::YourReignOfPainHasEnded, 30);
}

24
Source/sync.cpp

@ -25,7 +25,7 @@ void SyncOneMonster()
int m = ActiveMonsters[i];
auto &monster = Monsters[m];
sgnMonsterPriority[m] = MyPlayer->position.tile.ManhattanDistance(monster.position.tile);
if (monster._msquelch == 0) {
if (monster.activeForTicks == 0) {
sgnMonsterPriority[m] += 0x1000;
} else if (sgwLRU[m] != 0) {
sgwLRU[m]--;
@ -41,11 +41,11 @@ void SyncMonsterPos(TSyncMonster &monsterSync, int ndx)
monsterSync._my = monster.position.tile.y;
monsterSync._menemy = encode_enemy(monster);
monsterSync._mdelta = sgnMonsterPriority[ndx] > 255 ? 255 : sgnMonsterPriority[ndx];
monsterSync.mWhoHit = monster.mWhoHit;
monsterSync._mhitpoints = monster._mhitpoints;
monsterSync.mWhoHit = monster.whoHit;
monsterSync._mhitpoints = monster.hitPoints;
sgnMonsterPriority[ndx] = 0xFFFF;
sgwLRU[ndx] = monster._msquelch == 0 ? 0xFFFF : 0xFFFE;
sgwLRU[ndx] = monster.activeForTicks == 0 ? 0xFFFF : 0xFFFE;
}
bool SyncMonsterActive(TSyncMonster &monsterSync)
@ -152,14 +152,14 @@ void SyncMonster(bool isOwner, const TSyncMonster &monsterSync)
{
const int monsterId = monsterSync._mndx;
Monster &monster = Monsters[monsterId];
if (monster._mhitpoints <= 0 || monster._mmode == MonsterMode::Death) {
if (monster.hitPoints <= 0 || monster.mode == MonsterMode::Death) {
return;
}
const Point position { monsterSync._mx, monsterSync._my };
const int enemyId = monsterSync._menemy;
if (monster._msquelch != 0) {
if (monster.activeForTicks != 0) {
uint32_t delta = MyPlayer->position.tile.ManhattanDistance(monster.position.tile);
if (delta > 255) {
delta = 255;
@ -172,18 +172,18 @@ void SyncMonster(bool isOwner, const TSyncMonster &monsterSync)
return;
}
}
if (IsAnyOf(monster._mmode, MonsterMode::Charge, MonsterMode::Petrified)) {
if (IsAnyOf(monster.mode, MonsterMode::Charge, MonsterMode::Petrified)) {
return;
}
if (monster.position.tile.WalkingDistance(position) <= 2) {
if (!monster.IsWalking()) {
if (!monster.isWalking()) {
Direction md = GetDirection(monster.position.tile, position);
if (DirOK(monsterId, md)) {
M_ClearSquares(monster);
dMonster[monster.position.tile.x][monster.position.tile.y] = monsterId + 1;
M_WalkDir(monster, md);
monster._msquelch = UINT8_MAX;
monster.activeForTicks = UINT8_MAX;
}
}
} else if (dMonster[position.x][position.y] == 0) {
@ -193,11 +193,11 @@ void SyncMonster(bool isOwner, const TSyncMonster &monsterSync)
decode_enemy(monster, enemyId);
Direction md = GetDirection(position, monster.enemyPosition);
M_StartStand(monster, md);
monster._msquelch = UINT8_MAX;
monster.activeForTicks = UINT8_MAX;
}
decode_enemy(monster, enemyId);
monster.mWhoHit |= monsterSync.mWhoHit;
monster.whoHit |= monsterSync.mWhoHit;
}
bool IsEnemyIdValid(const Monster &monster, int enemyId)
@ -221,7 +221,7 @@ bool IsEnemyIdValid(const Monster &monster, int enemyId)
return false;
}
if (enemy._mhitpoints <= 0) {
if (enemy.hitPoints <= 0) {
return false;
}

4
Source/track.cpp

@ -39,8 +39,8 @@ void InvalidateTargets()
{
if (pcursmonst != -1) {
const Monster &monster = Monsters[pcursmonst];
if (monster._mDelFlag || monster._mhitpoints >> 6 <= 0
|| (monster._mFlags & MFLAG_HIDDEN) != 0
if (monster.isInvalid || monster.hitPoints >> 6 <= 0
|| (monster.flags & MFLAG_HIDDEN) != 0
|| !IsTileLit(monster.position.tile)) {
pcursmonst = -1;
}

Loading…
Cancel
Save