HP overflow is now gated by a rule for clients (bots and mercs will always get fixed hp), fix for phantom stat aa regression

This commit is contained in:
KimLS 2021-09-21 21:29:28 -07:00
parent b82dfb91ae
commit 7453326f87
5 changed files with 92 additions and 46 deletions

View File

@ -167,6 +167,7 @@ RULE_BOOL(Character, EnableCharacterEXPMods, false, "Enables character zone-base
RULE_BOOL(Character, PVPEnableGuardFactionAssist, true, "Enables faction based assisting against the aggresor in pvp.")
RULE_BOOL(Character, SkillUpFromItems, true, "Allow Skill ups from clickable items")
RULE_BOOL(Character, EnableTestBuff, false, "Allow the use of /testbuff")
RULE_BOOL(Character, FixHPCalculationOverflow, true, "Fix the HP overflow bug in HP calcs, this is a client bug, if fixed and clients overflow their hp wont match the server's hp but the difference serverside can be significant so it's left as an option.")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)

View File

@ -966,7 +966,7 @@ void Client::SendPhantomStatsAlternateAdvancementRank() {
for (int i = 0; i < 7; ++i) {
outapp->WriteSInt32(SE_RaiseStatCap);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(0);
outapp->WriteSInt32(i);
outapp->WriteSInt32(i + 1);
}

View File

@ -25,6 +25,7 @@
#include "lua_parser.h"
#include "../common/string_util.h"
#include "../common/say_link.h"
#include "../common/data_verification.h"
extern volatile bool is_zone_loaded;
@ -7919,24 +7920,31 @@ uint32 Bot::GetClassHPFactor() {
}
int32 Bot::CalcMaxHP() {
int32 bot_hp = 0;
uint32 nd = 10000;
bot_hp += (GenerateBaseHitPoints() + itembonuses.HP);
nd += aabonuses.MaxHPChange;
bot_hp = ((float)bot_hp * (float)nd / (float)10000);
bot_hp += (spellbonuses.HP + aabonuses.HP);
bot_hp += GroupLeadershipAAHealthEnhancement();
bot_hp += (bot_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f));
max_hp = bot_hp;
if (current_hp > max_hp)
int64 base_hp = (CalcBaseHP() + itembonuses.HP);
int64 nd = aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
int64 max_hp = (base_hp * nd / 10000) + base_hp;
max_hp += GroupLeadershipAAHealthEnhancement();
max_hp += 5;
max_hp += GetHeroicSTA() * 10;
max_hp += aabonuses.HP + spellbonuses.HP;
if (current_hp > max_hp) {
current_hp = max_hp;
int hp_perc_cap = spellbonuses.HPPercCap[0];
if(hp_perc_cap) {
int curHP_cap = ((max_hp * hp_perc_cap) / 100);
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[1] && current_hp > spellbonuses.HPPercCap[1]))
current_hp = curHP_cap;
}
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if (hp_perc_cap) {
int curHP_cap = (max_hp * hp_perc_cap) / 100;
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
current_hp = curHP_cap;
}
}
this->max_hp = static_cast<int32>(
EQ::Clamp(max_hp,
static_cast<int64>(0LL),
static_cast<int64>(std::numeric_limits<int32>::max()))
);
return max_hp;
}

View File

@ -315,26 +315,55 @@ int32 Client::CalcHPRegenCap()
int32 Client::CalcMaxHP()
{
int32 base_hp = (CalcBaseHP() + itembonuses.HP);
int32 nd = aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
max_hp = (base_hp * nd / 10000) + base_hp;
max_hp += GroupLeadershipAAHealthEnhancement();
max_hp += 5;
max_hp += GetHeroicSTA() * 10;
max_hp += aabonuses.HP + spellbonuses.HP;
if (current_hp > max_hp) {
current_hp = max_hp;
}
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if (hp_perc_cap) {
int curHP_cap = (max_hp * hp_perc_cap) / 100;
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
current_hp = curHP_cap;
if(RuleB(Character, FixHPCalculationOverflow)) {
int64 base_hp = (CalcBaseHP() + itembonuses.HP);
int64 nd = aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
int64 max_hp = (base_hp * nd / 10000) + base_hp;
max_hp += GroupLeadershipAAHealthEnhancement();
max_hp += 5;
max_hp += GetHeroicSTA() * 10;
max_hp += aabonuses.HP + spellbonuses.HP;
if (current_hp > max_hp) {
current_hp = max_hp;
}
}
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if (hp_perc_cap) {
int curHP_cap = (max_hp * hp_perc_cap) / 100;
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
return max_hp;
current_hp = curHP_cap;
}
}
this->max_hp = static_cast<int32>(
EQ::Clamp(max_hp,
static_cast<int64>(0LL),
static_cast<int64>(std::numeric_limits<int32>::max()))
);
return max_hp;
} else {
int32 base_hp = (CalcBaseHP() + itembonuses.HP);
int32 nd = aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
max_hp = (base_hp * nd / 10000) + base_hp;
max_hp += GroupLeadershipAAHealthEnhancement();
max_hp += 5;
max_hp += GetHeroicSTA() * 10;
max_hp += aabonuses.HP + spellbonuses.HP;
if (current_hp > max_hp) {
current_hp = max_hp;
}
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if (hp_perc_cap) {
int curHP_cap = (max_hp * hp_perc_cap) / 100;
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
current_hp = curHP_cap;
}
}
return max_hp;
}
}
uint32 Mob::GetClassLevelFactor()

View File

@ -17,6 +17,7 @@
#include "../common/string_util.h"
#include "../common/rulesys.h"
#include "../common/data_verification.h"
extern volatile bool is_zone_loaded;
@ -843,23 +844,30 @@ int32 Merc::CalcHPRegenCap()
}
int32 Merc::CalcMaxHP() {
int32 base_hp = (CalcBaseHP() + itembonuses.HP);
int32 nd = aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
max_hp = (base_hp * nd / 10000) + base_hp;
int64 base_hp = (CalcBaseHP() + itembonuses.HP);
int64 nd = aabonuses.MaxHPChange + spellbonuses.MaxHPChange + itembonuses.MaxHPChange;
int64 max_hp = (base_hp * nd / 10000) + base_hp;
max_hp += GroupLeadershipAAHealthEnhancement();
max_hp += 5;
max_hp += GetHeroicSTA() * 10;
max_hp += aabonuses.HP + spellbonuses.HP;
if (current_hp > max_hp)
if (current_hp > max_hp) {
current_hp = max_hp;
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if(hp_perc_cap) {
int curHP_cap = (max_hp * hp_perc_cap) / 100;
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP]))
current_hp = curHP_cap;
}
int hp_perc_cap = spellbonuses.HPPercCap[SBIndex::RESOURCE_PERCENT_CAP];
if (hp_perc_cap) {
int curHP_cap = (max_hp * hp_perc_cap) / 100;
if (current_hp > curHP_cap || (spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP] && current_hp > spellbonuses.HPPercCap[SBIndex::RESOURCE_AMOUNT_CAP])) {
current_hp = curHP_cap;
}
}
this->max_hp = static_cast<int32>(
EQ::Clamp(max_hp,
static_cast<int64>(0LL),
static_cast<int64>(std::numeric_limits<int32>::max()))
);
return max_hp;
}