diff --git a/CMakeLists.txt b/CMakeLists.txt index 9022ea306..407b1a221 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 47f14bb4e..e680266bc 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -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; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 38b109677..9fb3c4205 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -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++) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 55fbfe2c8..91a5cc68a 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -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++) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 404190d09..b24ae271c 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -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); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 07758bba6..ae55c1a53 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -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); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index c23415737..2f3afce16 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -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; diff --git a/zone/aa.cpp b/zone/aa.cpp index fff2ae727..73b2a8478 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -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) { diff --git a/zone/client.h b/zone/client.h index cb39637a1..3422bc32a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -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); diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index b415b6938..78346fb43 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -34,11 +34,12 @@ #include -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(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(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(stats)); + base_end = base_data->base_end + static_cast(base_data->endurance_factor * stats); } } else { diff --git a/zone/exp.cpp b/zone/exp.cpp index 9b4df5492..468ef974b 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -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(); }