Browse Source

Replace level member with a member function in monster (#5336)

pull/5354/head
Mikołaj Piróg 4 years ago committed by GitHub
parent
commit
5e340d3261
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      Source/items.cpp
  2. 4
      Source/loadsave.cpp
  3. 10
      Source/missiles.cpp
  4. 31
      Source/monster.cpp
  5. 33
      Source/monster.h

4
Source/items.cpp

@ -1323,7 +1323,7 @@ int RndUItem(Monster *monster)
if (AllItemsList[i].iRnd == IDROP_NEVER) if (AllItemsList[i].iRnd == IDROP_NEVER)
okflag = false; okflag = false;
if (monster != nullptr) { if (monster != nullptr) {
if (monster->level < AllItemsList[i].iMinMLvl) if (monster->level(sgGameInitInfo.nDifficulty) < AllItemsList[i].iMinMLvl)
okflag = false; okflag = false;
} else { } else {
if (2 * curlv < AllItemsList[i].iMinMLvl) if (2 * curlv < AllItemsList[i].iMinMLvl)
@ -3026,7 +3026,7 @@ int RndItem(const Monster &monster)
if ((monsterTreasureFlags & T_NODROP) != 0) if ((monsterTreasureFlags & T_NODROP) != 0)
return 0; return 0;
return RndItemForMonsterLevel(monster.level); return RndItemForMonsterLevel(monster.level(sgGameInitInfo.nDifficulty));
} }
void SpawnUnique(_unique_items uid, Point position) void SpawnUnique(_unique_items uid, Point position)

4
Source/loadsave.cpp

@ -631,7 +631,7 @@ void LoadMonster(LoadHelper *file, Monster &monster)
monster.corpseId = file->NextLE<int8_t>(); monster.corpseId = file->NextLE<int8_t>();
monster.whoHit = file->NextLE<int8_t>(); monster.whoHit = file->NextLE<int8_t>();
monster.level = file->NextLE<int8_t>(); file->Skip(1); // Skip level - now calculated on the fly
file->Skip(1); // Alignment file->Skip(1); // Alignment
file->Skip(2); // Skip exp - now calculated from monstdat when the monster dies 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<int8_t>(monster.corpseId); file->WriteLE<int8_t>(monster.corpseId);
file->WriteLE<int8_t>(monster.whoHit); file->WriteLE<int8_t>(monster.whoHit);
file->WriteLE<int8_t>(monster.level); file->WriteLE<int8_t>(static_cast<int8_t>(monster.level(sgGameInitInfo.nDifficulty)));
file->Skip(1); // Alignment file->Skip(1); // Alignment
file->WriteLE<uint16_t>(static_cast<uint16_t>(std::min<unsigned>(std::numeric_limits<uint16_t>::max(), monster.exp(sgGameInitInfo.nDifficulty)))); file->WriteLE<uint16_t>(static_cast<uint16_t>(std::min<unsigned>(std::numeric_limits<uint16_t>::max(), monster.exp(sgGameInitInfo.nDifficulty))));

10
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 -= player.CalculateArmorPierce(monster.armorClass, false);
hper -= (dist * dist) / 2; hper -= (dist * dist) / 2;
} else { } else {
hper = player.GetMagicToHit() - (monster.level * 2) - dist; hper = player.GetMagicToHit() - (monster.level(sgGameInitInfo.nDifficulty) * 2) - dist;
} }
hper = clamp(hper, 5, 95); 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(); int tac = player.GetArmor();
if (monster != nullptr) { if (monster != nullptr) {
hper = monster->toHit hper = monster->toHit
+ ((monster->level - player._pLevel) * 2) + ((monster->level(sgGameInitInfo.nDifficulty) - player._pLevel) * 2)
+ 30 + 30
- (dist * 2) - tac; - (dist * 2) - tac;
} else { } else {
hper = 100 - (tac / 2) - (dist * 2); hper = 100 - (tac / 2) - (dist * 2);
} }
} else if (monster != nullptr) { } 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; 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); int blkper = player.GetBlockChance(false);
if (monster != nullptr) if (monster != nullptr)
blkper -= (monster->level - player._pLevel) * 2; blkper -= (monster->level(sgGameInitInfo.nDifficulty) - player._pLevel) * 2;
blkper = clamp(blkper, 0, 100); blkper = clamp(blkper, 0, 100);
int8_t resper; int8_t resper;
@ -1955,7 +1955,7 @@ void AddFlash(Missile &missile, const AddMissileParameter & /*parameter*/)
ConsumeSpell(player, SPL_FLASH); ConsumeSpell(player, SPL_FLASH);
} break; } break;
case MissileSource::Monster: case MissileSource::Monster:
missile._midam = missile.sourceMonster()->level * 2; missile._midam = missile.sourceMonster()->level(sgGameInitInfo.nDifficulty) * 2;
break; break;
case MissileSource::Trap: case MissileSource::Trap:
missile._midam = currlevel / 2; missile._midam = currlevel / 2;

31
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.tickCounterOfCurrentFrame = GenerateRnd(monster.animInfo.ticksPerFrame - 1);
monster.animInfo.currentFrame = GenerateRnd(monster.animInfo.numberOfFrames - 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); int maxhp = monster.data().hitPointsMinimum + GenerateRnd(monster.data().hitPointsMaximum - monster.data().hitPointsMinimum + 1);
if (monster.type().type == MT_DIABLO && !gbIsHellfire) { if (monster.type().type == MT_DIABLO && !gbIsHellfire) {
maxhp /= 2; maxhp /= 2;
monster.level -= 15;
} }
monster.maxHitPoints = maxhp << 6; monster.maxHitPoints = maxhp << 6;
@ -183,7 +181,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio
else else
monster.maxHitPoints += 64; monster.maxHitPoints += 64;
monster.hitPoints = monster.maxHitPoints; monster.hitPoints = monster.maxHitPoints;
monster.level += 15;
monster.toHit += NightmareToHitBonus; monster.toHit += NightmareToHitBonus;
monster.minDamage = 2 * (monster.minDamage + 2); monster.minDamage = 2 * (monster.minDamage + 2);
monster.maxDamage = 2 * (monster.maxDamage + 2); monster.maxDamage = 2 * (monster.maxDamage + 2);
@ -198,7 +195,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio
else else
monster.maxHitPoints += 192; monster.maxHitPoints += 192;
monster.hitPoints = monster.maxHitPoints; monster.hitPoints = monster.maxHitPoints;
monster.level += 30;
monster.toHit += HellToHitBonus; monster.toHit += HellToHitBonus;
monster.minDamage = 4 * monster.minDamage + 6; monster.minDamage = 4 * monster.minDamage + 6;
monster.maxDamage = 4 * monster.maxDamage + 6; monster.maxDamage = 4 * monster.maxDamage + 6;
@ -943,7 +939,7 @@ void Teleport(Monster &monster)
void MonsterHitMonster(Monster &attacker, Monster &target, int dam) 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); target.direction = Opposite(attacker.direction);
} }
@ -1130,7 +1126,7 @@ void MonsterAttackPlayer(Monster &monster, Player &player, int hit, int minDam,
ac += 40; ac += 40;
if (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::ACAgainstUndead) && monster.data().monsterClass == MonsterClass::Undead) if (HasAnyOf(player.pDamAcFlags, ItemSpecialEffectHf::ACAgainstUndead) && monster.data().monsterClass == MonsterClass::Undead)
ac += 20; ac += 20;
hit += 2 * (monster.level - player._pLevel) hit += 2 * (monster.level(sgGameInitInfo.nDifficulty) - player._pLevel)
+ 30 + 30
- ac; - ac;
int minhit = 15; 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) { if ((player._pmode == PM_STAND || player._pmode == PM_ATTACK) && player._pBlockFlag) {
blkper = GenerateRnd(100); blkper = GenerateRnd(100);
} }
int blk = player.GetBlockChance() - (monster.level * 2); int blk = player.GetBlockChance() - (monster.level(sgGameInitInfo.nDifficulty) * 2);
blk = clamp(blk, 0, 100); blk = clamp(blk, 0, 100);
if (hper >= hit) if (hper >= hit)
return; return;
@ -3098,13 +3094,6 @@ void InitTRNForUniqueMonster(Monster &monster)
void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t minionType, int bosspacksize, const UniqueMonsterData &uniqueMonsterData) void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t minionType, int bosspacksize, const UniqueMonsterData &uniqueMonsterData)
{ {
monster.uniqueType = monsterType; monster.uniqueType = monsterType;
if (uniqueMonsterData.mlevel != 0) {
monster.level = 2 * uniqueMonsterData.mlevel;
} else {
monster.level = monster.data().level + 5;
}
monster.maxHitPoints = uniqueMonsterData.mmaxhp << 6; monster.maxHitPoints = uniqueMonsterData.mmaxhp << 6;
if (!gbIsMultiplayer) if (!gbIsMultiplayer)
@ -3142,7 +3131,6 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t
monster.maxHitPoints += (gbIsMultiplayer ? 100 : 50) << 6; monster.maxHitPoints += (gbIsMultiplayer ? 100 : 50) << 6;
else else
monster.maxHitPoints += 64; monster.maxHitPoints += 64;
monster.level += 15;
monster.hitPoints = monster.maxHitPoints; monster.hitPoints = monster.maxHitPoints;
monster.minDamage = 2 * (monster.minDamage + 2); monster.minDamage = 2 * (monster.minDamage + 2);
monster.maxDamage = 2 * (monster.maxDamage + 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; monster.maxHitPoints += (gbIsMultiplayer ? 200 : 100) << 6;
else else
monster.maxHitPoints += 192; monster.maxHitPoints += 192;
monster.level += 30;
monster.hitPoints = monster.maxHitPoints; monster.hitPoints = monster.maxHitPoints;
monster.minDamage = 4 * monster.minDamage + 6; monster.minDamage = 4 * monster.minDamage + 6;
monster.maxDamage = 4 * monster.maxDamage + 6; monster.maxDamage = 4 * monster.maxDamage + 6;
@ -3627,7 +3614,7 @@ void M_StartHit(Monster &monster, int dam)
{ {
PlayEffect(monster, MonsterSound::Hit); 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) { if (monster.type().type == MT_BLINK) {
Teleport(monster); Teleport(monster);
} else if (IsAnyOf(monster.type().type, MT_NSCAV, MT_BSCAV, MT_WSCAV, MT_YSCAV, MT_GRAVEDIG)) { } 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) void M_StartHit(Monster &monster, const Player &player, int dam)
{ {
monster.tag(player); 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.enemy = player.getId();
monster.enemyPosition = player.position.future; monster.enemyPosition = player.position.future;
monster.flags &= ~MFLAG_TARGETS_MONSTER; 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) void MonsterDeath(Monster &monster, Direction md, bool sendmsg)
{ {
if (!monster.isPlayerMinion()) 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]++; MonsterKillCounts[monster.type().type]++;
monster.hitPoints = 0; monster.hitPoints = 0;
@ -3933,10 +3920,10 @@ void ProcessMonsters()
monster.aiSeed = AdvanceRndSeed(); monster.aiSeed = AdvanceRndSeed();
} }
if ((monster.flags & MFLAG_NOHEAL) == 0 && monster.hitPoints < monster.maxHitPoints && monster.hitPoints >> 6 > 0) { if ((monster.flags & MFLAG_NOHEAL) == 0 && monster.hitPoints < monster.maxHitPoints && monster.hitPoints >> 6 > 0) {
if (monster.level > 1) { if (monster.level(sgGameInitInfo.nDifficulty) > 1) {
monster.hitPoints += monster.level / 2; monster.hitPoints += monster.level(sgGameInitInfo.nDifficulty) / 2;
} else { } 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 monster.hitPoints = std::min(monster.hitPoints, monster.maxHitPoints); // prevent going over max HP with part of a single regen tick
} }

33
Source/monster.h

@ -18,6 +18,7 @@
#include "engine/point.hpp" #include "engine/point.hpp"
#include "engine/sound.h" #include "engine/sound.h"
#include "engine/world_tile.hpp" #include "engine/world_tile.hpp"
#include "init.h"
#include "monstdat.h" #include "monstdat.h"
#include "spelldat.h" #include "spelldat.h"
#include "textdat.h" #include "textdat.h"
@ -248,7 +249,6 @@ struct Monster { // note: missing field _mAFNum
uint8_t uniqTrans; uint8_t uniqTrans;
int8_t corpseId; int8_t corpseId;
int8_t whoHit; int8_t whoHit;
int8_t level;
uint8_t minDamage; uint8_t minDamage;
uint8_t maxDamage; uint8_t maxDamage;
uint8_t minDamageSpecial; uint8_t minDamageSpecial;
@ -340,6 +340,37 @@ struct Monster { // note: missing field _mAFNum
return monsterExp; 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<int8_t>(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 * @brief Returns the network identifier for this monster
* *

Loading…
Cancel
Save