diff --git a/common/ruletypes.h b/common/ruletypes.h index 37bf96711..ce00b7e51 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -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) diff --git a/zone/aa.cpp b/zone/aa.cpp index 5acce37d6..0d5416c9f 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -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); } diff --git a/zone/bot.cpp b/zone/bot.cpp index 531dba75f..1487f2045 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -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( + EQ::Clamp(max_hp, + static_cast(0LL), + static_cast(std::numeric_limits::max())) + ); + return max_hp; } diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 0490b87d3..451515675 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -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( + EQ::Clamp(max_hp, + static_cast(0LL), + static_cast(std::numeric_limits::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() diff --git a/zone/merc.cpp b/zone/merc.cpp index 513e608d9..7a65d5ff7 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -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( + EQ::Clamp(max_hp, + static_cast(0LL), + static_cast(std::numeric_limits::max())) + ); return max_hp; }