From 5e340d3261d006ea1f063dda26be3d52007beaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Pir=C3=B3g?= <69601940+aetn23@users.noreply.github.com> Date: Sat, 17 Sep 2022 11:39:44 +0200 Subject: [PATCH] Replace level member with a member function in monster (#5336) --- Source/items.cpp | 4 ++-- Source/loadsave.cpp | 4 ++-- Source/missiles.cpp | 10 +++++----- Source/monster.cpp | 31 +++++++++---------------------- Source/monster.h | 33 ++++++++++++++++++++++++++++++++- 5 files changed, 50 insertions(+), 32 deletions(-) diff --git a/Source/items.cpp b/Source/items.cpp index f248de172..c411f6827 100644 --- a/Source/items.cpp +++ b/Source/items.cpp @@ -1323,7 +1323,7 @@ int RndUItem(Monster *monster) if (AllItemsList[i].iRnd == IDROP_NEVER) okflag = false; if (monster != nullptr) { - if (monster->level < AllItemsList[i].iMinMLvl) + if (monster->level(sgGameInitInfo.nDifficulty) < AllItemsList[i].iMinMLvl) okflag = false; } else { if (2 * curlv < AllItemsList[i].iMinMLvl) @@ -3026,7 +3026,7 @@ int RndItem(const Monster &monster) if ((monsterTreasureFlags & T_NODROP) != 0) return 0; - return RndItemForMonsterLevel(monster.level); + return RndItemForMonsterLevel(monster.level(sgGameInitInfo.nDifficulty)); } void SpawnUnique(_unique_items uid, Point position) diff --git a/Source/loadsave.cpp b/Source/loadsave.cpp index 6ca3babf4..3cefa89c5 100644 --- a/Source/loadsave.cpp +++ b/Source/loadsave.cpp @@ -631,7 +631,7 @@ void LoadMonster(LoadHelper *file, Monster &monster) monster.corpseId = file->NextLE(); monster.whoHit = file->NextLE(); - monster.level = file->NextLE(); + file->Skip(1); // Skip level - now calculated on the fly file->Skip(1); // Alignment file->Skip(2); // Skip exp - now calculated from monstdat when the monster dies @@ -1397,7 +1397,7 @@ void SaveMonster(SaveHelper *file, Monster &monster) file->WriteLE(monster.corpseId); file->WriteLE(monster.whoHit); - file->WriteLE(monster.level); + file->WriteLE(static_cast(monster.level(sgGameInitInfo.nDifficulty))); file->Skip(1); // Alignment file->WriteLE(static_cast(std::min(std::numeric_limits::max(), monster.exp(sgGameInitInfo.nDifficulty)))); diff --git a/Source/missiles.cpp b/Source/missiles.cpp index a0bd4452f..34db781fa 100644 --- a/Source/missiles.cpp +++ b/Source/missiles.cpp @@ -198,7 +198,7 @@ bool MonsterMHit(int pnum, int monsterId, int mindam, int maxdam, int dist, miss hper -= player.CalculateArmorPierce(monster.armorClass, false); hper -= (dist * dist) / 2; } else { - hper = player.GetMagicToHit() - (monster.level * 2) - dist; + hper = player.GetMagicToHit() - (monster.level(sgGameInitInfo.nDifficulty) * 2) - dist; } hper = clamp(hper, 5, 95); @@ -956,14 +956,14 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missil int tac = player.GetArmor(); if (monster != nullptr) { hper = monster->toHit - + ((monster->level - player._pLevel) * 2) + + ((monster->level(sgGameInitInfo.nDifficulty) - player._pLevel) * 2) + 30 - (dist * 2) - tac; } else { hper = 100 - (tac / 2) - (dist * 2); } } else if (monster != nullptr) { - hper += (monster->level * 2) - (player._pLevel * 2) - (dist * 2); + hper += (monster->level(sgGameInitInfo.nDifficulty) * 2) - (player._pLevel * 2) - (dist * 2); } int minhit = 10; @@ -987,7 +987,7 @@ bool PlayerMHit(int pnum, Monster *monster, int dist, int mind, int maxd, missil int blkper = player.GetBlockChance(false); if (monster != nullptr) - blkper -= (monster->level - player._pLevel) * 2; + blkper -= (monster->level(sgGameInitInfo.nDifficulty) - player._pLevel) * 2; blkper = clamp(blkper, 0, 100); int8_t resper; @@ -1955,7 +1955,7 @@ void AddFlash(Missile &missile, const AddMissileParameter & /*parameter*/) ConsumeSpell(player, SPL_FLASH); } break; case MissileSource::Monster: - missile._midam = missile.sourceMonster()->level * 2; + missile._midam = missile.sourceMonster()->level(sgGameInitInfo.nDifficulty) * 2; break; case MissileSource::Trap: missile._midam = currlevel / 2; diff --git a/Source/monster.cpp b/Source/monster.cpp index 94792be8b..3f4414c56 100644 --- a/Source/monster.cpp +++ b/Source/monster.cpp @@ -130,11 +130,9 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio monster.animInfo.tickCounterOfCurrentFrame = GenerateRnd(monster.animInfo.ticksPerFrame - 1); monster.animInfo.currentFrame = GenerateRnd(monster.animInfo.numberOfFrames - 1); - monster.level = monster.data().level; int maxhp = monster.data().hitPointsMinimum + GenerateRnd(monster.data().hitPointsMaximum - monster.data().hitPointsMinimum + 1); if (monster.type().type == MT_DIABLO && !gbIsHellfire) { maxhp /= 2; - monster.level -= 15; } monster.maxHitPoints = maxhp << 6; @@ -183,7 +181,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio else monster.maxHitPoints += 64; monster.hitPoints = monster.maxHitPoints; - monster.level += 15; monster.toHit += NightmareToHitBonus; monster.minDamage = 2 * (monster.minDamage + 2); monster.maxDamage = 2 * (monster.maxDamage + 2); @@ -198,7 +195,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio else monster.maxHitPoints += 192; monster.hitPoints = monster.maxHitPoints; - monster.level += 30; monster.toHit += HellToHitBonus; monster.minDamage = 4 * monster.minDamage + 6; monster.maxDamage = 4 * monster.maxDamage + 6; @@ -943,7 +939,7 @@ void Teleport(Monster &monster) void MonsterHitMonster(Monster &attacker, Monster &target, int dam) { - if (IsAnyOf(target.type().type, MT_SNEAK, MT_STALKER, MT_UNSEEN, MT_ILLWEAV) || dam >> 6 >= target.level + 3) { + if (IsAnyOf(target.type().type, MT_SNEAK, MT_STALKER, MT_UNSEEN, MT_ILLWEAV) || dam >> 6 >= target.level(sgGameInitInfo.nDifficulty) + 3) { target.direction = Opposite(attacker.direction); } @@ -1130,7 +1126,7 @@ void MonsterAttackPlayer(Monster &monster, Player &player, int hit, int minDam, ac += 40; if (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::ACAgainstUndead) && monster.data().monsterClass == MonsterClass::Undead) ac += 20; - hit += 2 * (monster.level - player._pLevel) + hit += 2 * (monster.level(sgGameInitInfo.nDifficulty) - player._pLevel) + 30 - ac; int minhit = 15; @@ -1145,7 +1141,7 @@ void MonsterAttackPlayer(Monster &monster, Player &player, int hit, int minDam, if ((player._pmode == PM_STAND || player._pmode == PM_ATTACK) && player._pBlockFlag) { blkper = GenerateRnd(100); } - int blk = player.GetBlockChance() - (monster.level * 2); + int blk = player.GetBlockChance() - (monster.level(sgGameInitInfo.nDifficulty) * 2); blk = clamp(blk, 0, 100); if (hper >= hit) return; @@ -3098,13 +3094,6 @@ void InitTRNForUniqueMonster(Monster &monster) void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t minionType, int bosspacksize, const UniqueMonsterData &uniqueMonsterData) { monster.uniqueType = monsterType; - - if (uniqueMonsterData.mlevel != 0) { - monster.level = 2 * uniqueMonsterData.mlevel; - } else { - monster.level = monster.data().level + 5; - } - monster.maxHitPoints = uniqueMonsterData.mmaxhp << 6; if (!gbIsMultiplayer) @@ -3142,7 +3131,6 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t monster.maxHitPoints += (gbIsMultiplayer ? 100 : 50) << 6; else monster.maxHitPoints += 64; - monster.level += 15; monster.hitPoints = monster.maxHitPoints; monster.minDamage = 2 * (monster.minDamage + 2); monster.maxDamage = 2 * (monster.maxDamage + 2); @@ -3154,7 +3142,6 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t monster.maxHitPoints += (gbIsMultiplayer ? 200 : 100) << 6; else monster.maxHitPoints += 192; - monster.level += 30; monster.hitPoints = monster.maxHitPoints; monster.minDamage = 4 * monster.minDamage + 6; monster.maxDamage = 4 * monster.maxDamage + 6; @@ -3627,7 +3614,7 @@ void M_StartHit(Monster &monster, int dam) { PlayEffect(monster, MonsterSound::Hit); - if (IsAnyOf(monster.type().type, MT_SNEAK, MT_STALKER, MT_UNSEEN, MT_ILLWEAV) || dam >> 6 >= monster.level + 3) { + if (IsAnyOf(monster.type().type, MT_SNEAK, MT_STALKER, MT_UNSEEN, MT_ILLWEAV) || dam >> 6 >= monster.level(sgGameInitInfo.nDifficulty) + 3) { if (monster.type().type == MT_BLINK) { Teleport(monster); } else if (IsAnyOf(monster.type().type, MT_NSCAV, MT_BSCAV, MT_WSCAV, MT_YSCAV, MT_GRAVEDIG)) { @@ -3644,7 +3631,7 @@ void M_StartHit(Monster &monster, int dam) void M_StartHit(Monster &monster, const Player &player, int dam) { monster.tag(player); - if (IsAnyOf(monster.type().type, MT_SNEAK, MT_STALKER, MT_UNSEEN, MT_ILLWEAV) || dam >> 6 >= monster.level + 3) { + if (IsAnyOf(monster.type().type, MT_SNEAK, MT_STALKER, MT_UNSEEN, MT_ILLWEAV) || dam >> 6 >= monster.level(sgGameInitInfo.nDifficulty) + 3) { monster.enemy = player.getId(); monster.enemyPosition = player.position.future; monster.flags &= ~MFLAG_TARGETS_MONSTER; @@ -3657,7 +3644,7 @@ void M_StartHit(Monster &monster, const Player &player, int dam) void MonsterDeath(Monster &monster, Direction md, bool sendmsg) { if (!monster.isPlayerMinion()) - AddPlrMonstExper(monster.level, monster.exp(sgGameInitInfo.nDifficulty), monster.whoHit); + AddPlrMonstExper(monster.level(sgGameInitInfo.nDifficulty), monster.exp(sgGameInitInfo.nDifficulty), monster.whoHit); MonsterKillCounts[monster.type().type]++; monster.hitPoints = 0; @@ -3933,10 +3920,10 @@ void ProcessMonsters() monster.aiSeed = AdvanceRndSeed(); } if ((monster.flags & MFLAG_NOHEAL) == 0 && monster.hitPoints < monster.maxHitPoints && monster.hitPoints >> 6 > 0) { - if (monster.level > 1) { - monster.hitPoints += monster.level / 2; + if (monster.level(sgGameInitInfo.nDifficulty) > 1) { + monster.hitPoints += monster.level(sgGameInitInfo.nDifficulty) / 2; } else { - monster.hitPoints += monster.level; + monster.hitPoints += monster.level(sgGameInitInfo.nDifficulty); } monster.hitPoints = std::min(monster.hitPoints, monster.maxHitPoints); // prevent going over max HP with part of a single regen tick } diff --git a/Source/monster.h b/Source/monster.h index 4d0115467..6248f60e7 100644 --- a/Source/monster.h +++ b/Source/monster.h @@ -18,6 +18,7 @@ #include "engine/point.hpp" #include "engine/sound.h" #include "engine/world_tile.hpp" +#include "init.h" #include "monstdat.h" #include "spelldat.h" #include "textdat.h" @@ -248,7 +249,6 @@ struct Monster { // note: missing field _mAFNum uint8_t uniqTrans; int8_t corpseId; int8_t whoHit; - int8_t level; uint8_t minDamage; uint8_t maxDamage; uint8_t minDamageSpecial; @@ -340,6 +340,37 @@ struct Monster { // note: missing field _mAFNum return monsterExp; } + /** + * @brief Calculates monster's level. + * Fetches base level value from @p MonstersData array or @p UniqueMonstersData. + * @param difficulty - difficulty on which calculation is performed + * @return Monster's level, including bonuses from difficulty and monster being unique + */ + unsigned int level(_difficulty difficulty) const + { + unsigned int baseLevel = data().level; + if (isUnique()) { + baseLevel = UniqueMonstersData[static_cast(uniqueType)].mlevel; + if (baseLevel != 0) { + baseLevel *= 2; + } else { + baseLevel = data().level + 5; + } + } + + if (type().type == MT_DIABLO && !gbIsHellfire) { + baseLevel -= 15; + } + + if (difficulty == DIFF_NIGHTMARE) { + baseLevel += 15; + } else if (difficulty == DIFF_HELL) { + baseLevel += 30; + } + + return baseLevel; + } + /** * @brief Returns the network identifier for this monster *