Various changes:

- Heroic Sta HP calc will now apply after natural durability.
- The base 5 hp that everyone gets will now apply after natural
durability.
- Fixed a rounding issue in the mana calc that would sometimes give
the player +1 mana
- Fixed the endurance calc to match the client better.
- When a server has a custom stat cap active the new stat caps
will be reflected on the client.
    This is done by reserving an AA slot for a "Phantom" AA that will
    act like Planar Power with the difference between what the client
    sees and what the server has.
- AA slots cap now will be 300 (the later clients max)
instead of 240 (titanium's max)
This commit is contained in:
KimLS 2021-09-10 19:52:28 -07:00
parent c078257f70
commit 66cf4b546c
11 changed files with 143 additions and 54 deletions

View File

@ -224,6 +224,9 @@ IF(OpenSSL_FOUND AND MBEDTLS_FOUND)
SET(TLS_LIBRARY_LIBS ${OPENSSL_LIBRARIES})
SET(TLS_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR})
ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL)
IF(${OPENSSL_VERSION} VERSION_GREATER_EQUAL "1.1.1")
ADD_DEFINITIONS(-DCPPHTTPLIB_OPENSSL_SUPPORT)
ENDIF()
ELSEIF(TLS_LIBRARY_SELECTION STREQUAL "mbedTLS")
SET(TLS_LIBRARY_TYPE " mbedTLS")
SET(TLS_LIBRARY_ENABLED ON)

View File

@ -860,7 +860,7 @@ static const uint32 MAX_PP_LANGUAGE = 28;
static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size
static const uint32 MAX_PP_INNATE_SKILL = 25;
static const uint32 MAX_PP_AA_ARRAY = 240;
static const uint32 MAX_PP_AA_ARRAY = 300;
static const uint32 MAX_GROUP_MEMBERS = 6;
static const uint32 MAX_RECAST_TYPES = 20;

View File

@ -2098,15 +2098,6 @@ namespace RoF
outapp->WriteUInt32(emu->aa_array[r].charges);
}
// Fill the other 60 AAs with zeroes
for (uint32 r = 0; r < structs::MAX_PP_AA_ARRAY - MAX_PP_AA_ARRAY; r++)
{
outapp->WriteUInt32(0);
outapp->WriteUInt32(0);
outapp->WriteUInt32(0);
}
outapp->WriteUInt32(structs::MAX_PP_SKILL);
for (uint32 r = 0; r < structs::MAX_PP_SKILL; r++)

View File

@ -2155,15 +2155,6 @@ namespace RoF2
outapp->WriteUInt32(emu->aa_array[r].charges);
}
// Fill the other 60 AAs with zeroes
for (uint32 r = 0; r < structs::MAX_PP_AA_ARRAY - MAX_PP_AA_ARRAY; r++)
{
outapp->WriteUInt32(0);
outapp->WriteUInt32(0);
outapp->WriteUInt32(0);
}
outapp->WriteUInt32(structs::MAX_PP_SKILL);
for (uint32 r = 0; r < structs::MAX_PP_SKILL; r++)

View File

@ -1504,8 +1504,7 @@ namespace SoD
OUT(item_tint.Slot[r].Color);
}
// OUT(unknown00224[48]);
//NOTE: new client supports 300 AAs, our internal rep/PP
//only supports 240..
//NOTE: new client supports 300 AAs
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
OUT(aa_array[r].AA);
OUT(aa_array[r].value);

View File

@ -1172,8 +1172,7 @@ namespace SoF
OUT(item_tint.Slot[r].Color);
}
// OUT(unknown00224[48]);
//NOTE: new client supports 300 AAs, our internal rep/PP
//only supports 240..
//NOTE: new client supports 300 AAs
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
OUT(aa_array[r].AA);
OUT(aa_array[r].value);

View File

@ -1734,8 +1734,7 @@ namespace UF
OUT(item_tint.Slot[r].Color);
}
// OUT(unknown00224[48]);
//NOTE: new client supports 300 AAs, our internal rep/PP
//only supports 240..
//NOTE: new client supports 300 AAs
for (r = 0; r < MAX_PP_AA_ARRAY; r++) {
eq->aa_array[r].AA = emu->aa_array[r].AA;
eq->aa_array[r].value = emu->aa_array[r].value;

View File

@ -37,6 +37,12 @@ Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net)
extern QueryServ* QServ;
namespace detail
{
static const uint32 PhantomStatId = 999999;
}
void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, uint32 duration_override, bool followme, bool sticktarg, uint16 *eye_id) {
//It might not be a bad idea to put these into the database, eventually..
@ -845,6 +851,8 @@ void Client::SendAlternateAdvancementTable() {
SendAlternateAdvancementRank(aa.first, 1);
}
}
SendPhantomStatsAlternateAdvancementRank();
}
void Client::SendAlternateAdvancementRank(int aa_id, int level) {
@ -918,6 +926,82 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) {
safe_delete(outapp);
}
void Client::SendPhantomStatsAlternateAdvancementRank() {
//We only need to send phantom stats if stats are set to a custom value
if (RuleI(Character, StatCap) <= 0) {
return;
}
auto diff = RuleI(Character, StatCap) - GetMaxStat(false);
int size = sizeof(AARankInfo_Struct) + (sizeof(AARankEffect_Struct) * 7);
auto outapp = new EQApplicationPacket(OP_SendAATable, size);
AARankInfo_Struct *aai = (AARankInfo_Struct*)outapp->pBuffer;
aai->id = detail::PhantomStatId;
aai->upper_hotkey_sid = -1;
aai->lower_hotkey_sid = -1;
aai->title_sid = detail::PhantomStatId;
aai->desc_sid = detail::PhantomStatId;
aai->cost = 1;
aai->seq = detail::PhantomStatId;
aai->type = 3;
aai->spell = -1;
aai->spell_type = 0;
aai->spell_refresh = 0;
aai->classes = 16777215;
aai->level_req = 1;
aai->current_level = 2;
aai->max_level = 1;
aai->prev_id = -1;
aai->next_id = -1;
aai->total_cost = 1;
aai->expansion = 0;
aai->category = -1;
aai->charges = 0;
aai->grant_only = 1;
aai->total_effects = 7;
aai->total_prereqs = 0;
outapp->SetWritePosition(sizeof(AARankInfo_Struct));
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(0);
outapp->WriteSInt32(1);
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(1);
outapp->WriteSInt32(2);
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(2);
outapp->WriteSInt32(3);
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(3);
outapp->WriteSInt32(4);
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(4);
outapp->WriteSInt32(5);
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(5);
outapp->WriteSInt32(6);
outapp->WriteSInt32(262);
outapp->WriteSInt32(diff);
outapp->WriteSInt32(6);
outapp->WriteSInt32(7);
QueuePacket(outapp);
safe_delete(outapp);
}
void Client::SendAlternateAdvancementStats() {
auto outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct));
AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer;
@ -933,7 +1017,19 @@ void Client::SendAlternateAdvancementPoints() {
AATable_Struct* aa2 = (AATable_Struct *)outapp->pBuffer;
int i = 0;
if (RuleI(Character, StatCap) > 0)
{
aa2->aa_list[i].AA = detail::PhantomStatId;
aa2->aa_list[i].value = 1;
aa2->aa_list[i].charges = 0;
i++;
}
for(auto &aa : zone->aa_abilities) {
if (i >= 300) {
continue;
}
uint32 charges = 0;
auto ranks = GetAA(aa.second->first_rank_id, &charges);
if(ranks) {

View File

@ -480,7 +480,7 @@ public:
inline virtual int32 GetCorrup() const { return Corrup; }
inline virtual int32 GetPhR() const { return PhR; }
int32 GetMaxStat() const;
int32 GetMaxStat(bool check_stat_cap) const;
int32 GetMaxResist() const;
int32 GetMaxSTR() const;
int32 GetMaxSTA() const;
@ -858,6 +858,7 @@ public:
//New AA Methods
void SendAlternateAdvancementRank(int aa_id, int level);
void SendPhantomStatsAlternateAdvancementRank();
void SendAlternateAdvancementTable();
void SendAlternateAdvancementStats();
void PurchaseAlternateAdvancementRank(int rank_id);

View File

@ -34,11 +34,12 @@
#include <algorithm>
int32 Client::GetMaxStat() const
int32 Client::GetMaxStat(bool check_stat_cap) const
{
if ((RuleI(Character, StatCap)) > 0) {
return (RuleI(Character, StatCap));
if (check_stat_cap && RuleI(Character, StatCap) > 0) {
return RuleI(Character, StatCap);
}
int level = GetLevel();
int32 base = 0;
if (level < 61) {
@ -68,49 +69,49 @@ int32 Client::GetMaxResist() const
int32 Client::GetMaxSTR() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.STRCapMod
+ spellbonuses.STRCapMod
+ aabonuses.STRCapMod;
}
int32 Client::GetMaxSTA() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.STACapMod
+ spellbonuses.STACapMod
+ aabonuses.STACapMod;
}
int32 Client::GetMaxDEX() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.DEXCapMod
+ spellbonuses.DEXCapMod
+ aabonuses.DEXCapMod;
}
int32 Client::GetMaxAGI() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.AGICapMod
+ spellbonuses.AGICapMod
+ aabonuses.AGICapMod;
}
int32 Client::GetMaxINT() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.INTCapMod
+ spellbonuses.INTCapMod
+ aabonuses.INTCapMod;
}
int32 Client::GetMaxWIS() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.WISCapMod
+ spellbonuses.WISCapMod
+ aabonuses.WISCapMod;
}
int32 Client::GetMaxCHA() const
{
return GetMaxStat()
return GetMaxStat(true)
+ itembonuses.CHACapMod
+ spellbonuses.CHACapMod
+ aabonuses.CHACapMod;
@ -314,14 +315,16 @@ int32 Client::CalcHPRegenCap()
int32 Client::CalcMaxHP()
{
float nd = 10000;
max_hp = (CalcBaseHP() + itembonuses.HP);
int64 nd = 10000;
int64 max_hp = (CalcBaseHP() + itembonuses.HP);
//The AA desc clearly says it only applies to base hp..
//but the actual effect sent on live causes the client
//to apply it to (basehp + itemhp).. I will oblige to the client's whims over
//the aa description
nd += aabonuses.MaxHP; //Natural Durability, Physical Enhancement, Planar Durability
max_hp = (float)max_hp * (float)nd / (float)10000; //this is to fix the HP-above-495k issue
max_hp = max_hp * nd / 10000; //this is to fix the HP-above-495k issue
max_hp += 5;
max_hp += GetHeroicSTA() * 10;
max_hp += spellbonuses.HP + aabonuses.HP;
max_hp += GroupLeadershipAAHealthEnhancement();
max_hp += max_hp * ((spellbonuses.MaxHPChange + itembonuses.MaxHPChange) / 10000.0f);
@ -337,7 +340,8 @@ int32 Client::CalcMaxHP()
}
}
return max_hp;
this->max_hp = std::min(max_hp, 2147483647LL);
return this->max_hp;
}
uint32 Mob::GetClassLevelFactor()
@ -485,11 +489,10 @@ int32 Client::CalcBaseHP()
stats = (stats - 255) / 2;
stats += 255;
}
base_hp = 5;
base_hp = 0;
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
base_hp += base_data->base_hp + (base_data->hp_factor * stats);
base_hp += (GetHeroicSTA() * 10);
}
}
else {
@ -621,7 +624,7 @@ int32 Client::CalcBaseMana()
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
max_m = base_data->base_mana + (ConvertedWisInt * base_data->mana_factor) + (GetHeroicINT() * 10);
max_m = base_data->base_mana + static_cast<int32>(ConvertedWisInt * base_data->mana_factor) + (GetHeroicINT() * 10);
}
}
else {
@ -653,7 +656,7 @@ int32 Client::CalcBaseMana()
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
max_m = base_data->base_mana + (ConvertedWisInt * base_data->mana_factor) + (GetHeroicWIS() * 10);
max_m = base_data->base_mana + static_cast<int32>(ConvertedWisInt * base_data->mana_factor) + (GetHeroicWIS() * 10);
}
}
else {
@ -1610,6 +1613,12 @@ uint32 Mob::GetInstrumentMod(uint16 spell_id) const
void Client::CalcMaxEndurance()
{
max_end = CalcBaseEndurance() + spellbonuses.Endurance + itembonuses.Endurance + aabonuses.Endurance;
int32 heroic_stats = (GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4;
if (heroic_stats > 0) {
max_end += heroic_stats * 10;
}
if (max_end < 0) {
max_end = 0;
}
@ -1629,17 +1638,18 @@ int32 Client::CalcBaseEndurance()
{
int32 base_end = 0;
if (ClientVersion() >= EQ::versions::ClientVersion::SoF && RuleB(Character, SoDClientUseSoDHPManaEnd)) {
double heroic_stats = (GetHeroicSTR() + GetHeroicSTA() + GetHeroicDEX() + GetHeroicAGI()) / 4.0f;
double stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4.0f;
if (stats > 201.0f) {
stats = 1.25f * (stats - 201.0f) + 352.5f;
}
else if (stats > 100.0f) {
stats = 2.5f * (stats - 100.0f) + 100.0f;
int32 stats = (GetSTR() + GetSTA() + GetDEX() + GetAGI()) / 4;
if (stats > 100) {
if (stats > 200) {
stats -= (stats - 200) / 2;
}
stats += (3 * stats - 300) / 2;
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
base_end = base_data->base_end + (heroic_stats * 10.0f) + (base_data->endurance_factor * static_cast<int>(stats));
base_end = base_data->base_end + static_cast<int32>(base_data->endurance_factor * stats);
}
}
else {

View File

@ -860,7 +860,7 @@ void Client::SetLevel(uint8 set_level, bool command)
}
QueuePacket(outapp);
safe_delete(outapp);
this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change
SendAppearancePacket(AT_WhoLevel, set_level); // who level change
LogInfo("Setting Level for [{}] to [{}]", GetName(), set_level);
@ -881,8 +881,8 @@ void Client::SetLevel(uint8 set_level, bool command)
SendHPUpdate();
SetMana(CalcMaxMana());
UpdateWho();
UpdateMercLevel();
SendPhantomStatsAlternateAdvancementRank();
Save();
}