Browse Source

Exp overflow fix (#5070)

pull/5301/merge
Mikołaj Piróg 4 years ago committed by GitHub
parent
commit
32b3333bfb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      Source/loadsave.cpp
  2. 8
      Source/monster.cpp
  3. 25
      Source/monster.h

5
Source/loadsave.cpp

@ -27,6 +27,7 @@
#include "lighting.h"
#include "menu.h"
#include "missiles.h"
#include "monster.h"
#include "mpq/mpq_writer.hpp"
#include "pfile.h"
#include "qol/stash.h"
@ -632,7 +633,7 @@ void LoadMonster(LoadHelper *file, Monster &monster)
monster.whoHit = file->NextLE<int8_t>();
monster.level = file->NextLE<int8_t>();
file->Skip(1); // Alignment
monster.exp = file->NextLE<uint16_t>();
file->Skip(2); // Skip exp - now calculated from monstdat when the monster dies
if (monster.isPlayerMinion()) // Don't skip for golems
monster.toHit = file->NextLE<uint8_t>();
@ -1398,7 +1399,7 @@ void SaveMonster(SaveHelper *file, Monster &monster)
file->WriteLE<int8_t>(monster.whoHit);
file->WriteLE<int8_t>(monster.level);
file->Skip(1); // Alignment
file->WriteLE<uint16_t>(monster.exp);
file->WriteLE<uint16_t>(static_cast<uint16_t>(std::min<unsigned>(std::numeric_limits<uint16_t>::max(), monster.exp(sgGameInitInfo.nDifficulty))));
file->WriteLE<uint8_t>(static_cast<uint8_t>(std::min<uint16_t>(monster.toHit, std::numeric_limits<uint8_t>::max()))); // For backwards compatibility
file->WriteLE<uint8_t>(monster.minDamage);

8
Source/monster.cpp

@ -156,7 +156,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio
monster.rndItemSeed = AdvanceRndSeed();
monster.aiSeed = AdvanceRndSeed();
monster.whoHit = 0;
monster.exp = monster.data().exp;
monster.toHit = monster.data().toHit;
monster.minDamage = monster.data().minDamage;
monster.maxDamage = monster.data().maxDamage;
@ -185,7 +184,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio
monster.maxHitPoints += 64;
monster.hitPoints = monster.maxHitPoints;
monster.level += 15;
monster.exp = 2 * (monster.exp + 1000);
monster.toHit += NightmareToHitBonus;
monster.minDamage = 2 * (monster.minDamage + 2);
monster.maxDamage = 2 * (monster.maxDamage + 2);
@ -201,7 +199,6 @@ void InitMonster(Monster &monster, Direction rd, size_t typeIndex, Point positio
monster.maxHitPoints += 192;
monster.hitPoints = monster.maxHitPoints;
monster.level += 30;
monster.exp = 4 * (monster.exp + 1000);
monster.toHit += HellToHitBonus;
monster.minDamage = 4 * monster.minDamage + 6;
monster.maxDamage = 4 * monster.maxDamage + 6;
@ -3108,7 +3105,6 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t
monster.level = monster.data().level + 5;
}
monster.exp *= 2;
monster.maxHitPoints = uniqueMonsterData.mmaxhp << 6;
if (!gbIsMultiplayer)
@ -3148,7 +3144,6 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t
monster.maxHitPoints += 64;
monster.level += 15;
monster.hitPoints = monster.maxHitPoints;
monster.exp = 2 * (monster.exp + 1000);
monster.minDamage = 2 * (monster.minDamage + 2);
monster.maxDamage = 2 * (monster.maxDamage + 2);
monster.minDamageSpecial = 2 * (monster.minDamageSpecial + 2);
@ -3161,7 +3156,6 @@ void PrepareUniqueMonst(Monster &monster, UniqueMonsterType monsterType, size_t
monster.maxHitPoints += 192;
monster.level += 30;
monster.hitPoints = monster.maxHitPoints;
monster.exp = 4 * (monster.exp + 1000);
monster.minDamage = 4 * monster.minDamage + 6;
monster.maxDamage = 4 * monster.maxDamage + 6;
monster.minDamageSpecial = 4 * monster.minDamageSpecial + 6;
@ -3663,7 +3657,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, monster.whoHit);
AddPlrMonstExper(monster.level, monster.exp(sgGameInitInfo.nDifficulty), monster.whoHit);
MonsterKillCounts[monster.type().type]++;
monster.hitPoints = 0;

25
Source/monster.h

@ -195,7 +195,7 @@ struct Monster { // note: missing field _mAFNum
uint32_t rndItemSeed;
/** Seed used to determine AI behaviour/sync sounds in multiplayer games? */
uint32_t aiSeed;
uint16_t exp;
uint16_t toHit;
uint16_t toHitSpecial;
uint16_t resistance;
@ -317,6 +317,29 @@ struct Monster { // note: missing field _mAFNum
return pgettext("monster", data().name);
}
/**
* @brief Calculates monster's experience points.
* Fetches base exp value from @p MonstersData array.
* @param difficulty - difficulty on which calculation is performed
* @return Monster's experience points, including bonuses from difficulty and monster being unique
*/
unsigned int exp(_difficulty difficulty) const
{
unsigned int monsterExp = data().exp;
if (difficulty == DIFF_NIGHTMARE) {
monsterExp = 2 * (monsterExp + 1000);
} else if (difficulty == DIFF_HELL) {
monsterExp = 4 * (monsterExp + 1000);
}
if (isUnique()) {
monsterExp *= 2;
}
return monsterExp;
}
/**
* @brief Returns the network identifier for this monster
*

Loading…
Cancel
Save