From 9e9ef6809b8222cf9b92c20cb6a0c82284601863 Mon Sep 17 00:00:00 2001 From: Kinglykrab <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 28 May 2022 14:35:17 -0400 Subject: [PATCH] [Cleanup] Cleanup spell and max level bucket logic. (#2181) * [Cleanup] Cleanup spell and max level bucket logic. - Spell buckets will now allow new mob->SetBucket() buckets since most people use these now. - Max level bucket will now allow new mob->SetBucket() bucket since most people use these now. - Clean up GetScribeableSpells() and GetLearnableDisciplines() logic and magic numbers. - Make GetClientMaxLevel() uint8 instead of int since it can only be 0-255. * Fix typo from other commit. * Lua setter. * Update client.cpp --- zone/client.cpp | 136 ++++++++++++++++++++++------------------- zone/client.h | 10 +-- zone/client_packet.cpp | 2 +- zone/embparser_api.cpp | 2 +- zone/exp.cpp | 67 +++++++++++--------- zone/lua_client.cpp | 6 +- zone/lua_client.h | 4 +- zone/perl_client.cpp | 8 +-- zone/spells.cpp | 88 ++++++++++++-------------- 9 files changed, 164 insertions(+), 159 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index a7f0f0cbd..b15cc5c2d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -282,11 +282,9 @@ Client::Client(EQStreamInterface* ieqs) if (!RuleB(Character, PerCharacterQglobalMaxLevel) && !RuleB(Character, PerCharacterBucketMaxLevel)) { SetClientMaxLevel(0); } else if (RuleB(Character, PerCharacterQglobalMaxLevel)) { - int client_max_level = GetCharMaxLevelFromQGlobal(); - SetClientMaxLevel(client_max_level); + SetClientMaxLevel(GetCharMaxLevelFromQGlobal()); } else if (RuleB(Character, PerCharacterBucketMaxLevel)) { - int client_max_level = GetCharMaxLevelFromBucket(); - SetClientMaxLevel(client_max_level); + SetClientMaxLevel(GetCharMaxLevelFromBucket()); } KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS)); @@ -10295,40 +10293,45 @@ void Client::Fling(float value, float target_x, float target_y, float target_z, } std::vector Client::GetLearnableDisciplines(uint8 min_level, uint8 max_level) { - bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals); - bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets); - bool SpellGlobalCheckResult = false; - bool SpellBucketCheckResult = false; std::vector learnable_disciplines; - for (int spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { + for (uint16 spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { bool learnable = false; - if (!IsValidSpell(spell_id)) - continue; - if (!IsDiscipline(spell_id)) - continue; - if (spells[spell_id].classes[WARRIOR] == 0) - continue; - if (max_level > 0 && spells[spell_id].classes[m_pp.class_ - 1] > max_level) - continue; - if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) - continue; - if (spells[spell_id].skill == 52) - continue; - if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == 10) - continue; - if (HasDisciplineLearned(spell_id)) + if (!IsValidSpell(spell_id)) { continue; + } - if (SpellGlobalRule) { - SpellGlobalCheckResult = SpellGlobalCheck(spell_id, CharacterID()); - if (SpellGlobalCheckResult) { - learnable = true; - } - } else if (SpellBucketRule) { - SpellBucketCheckResult = SpellBucketCheck(spell_id, CharacterID()); - if (SpellBucketCheckResult) { - learnable = true; - } + if (!IsDiscipline(spell_id)) { + continue; + } + + if (spells[spell_id].classes[WARRIOR] == 0) { + continue; + } + + if (max_level && spells[spell_id].classes[m_pp.class_ - 1] > max_level) { + continue; + } + + if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) { + continue; + } + + if (spells[spell_id].skill == EQ::skills::SkillTigerClaw) { + continue; + } + + if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) { + continue; + } + + if (HasDisciplineLearned(spell_id)) { + continue; + } + + if (RuleB(Spells, EnableSpellGlobals) && SpellGlobalCheck(spell_id, CharacterID())) { + learnable = true; + } else if (RuleB(Spells, EnableSpellBuckets) && SpellBucketCheck(spell_id, CharacterID())) { + learnable = true; } else { learnable = true; } @@ -10361,40 +10364,45 @@ std::vector Client::GetMemmedSpells() { } std::vector Client::GetScribeableSpells(uint8 min_level, uint8 max_level) { - bool SpellGlobalRule = RuleB(Spells, EnableSpellGlobals); - bool SpellBucketRule = RuleB(Spells, EnableSpellBuckets); - bool SpellGlobalCheckResult = false; - bool SpellBucketCheckResult = false; std::vector scribeable_spells; - for (int spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { + for (uint16 spell_id = 0; spell_id < SPDAT_RECORDS; ++spell_id) { bool scribeable = false; - if (!IsValidSpell(spell_id)) - continue; - if (IsDiscipline(spell_id)) - continue; - if (spells[spell_id].classes[WARRIOR] == 0) - continue; - if (max_level > 0 && spells[spell_id].classes[m_pp.class_ - 1] > max_level) - continue; - if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) - continue; - if (spells[spell_id].skill == 52) - continue; - if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == 10) - continue; - if (HasSpellScribed(spell_id)) + if (!IsValidSpell(spell_id)) { continue; + } - if (SpellGlobalRule) { - SpellGlobalCheckResult = SpellGlobalCheck(spell_id, CharacterID()); - if (SpellGlobalCheckResult) { - scribeable = true; - } - } else if (SpellBucketRule) { - SpellBucketCheckResult = SpellBucketCheck(spell_id, CharacterID()); - if (SpellBucketCheckResult) { - scribeable = true; - } + if (IsDiscipline(spell_id)) { + continue; + } + + if (spells[spell_id].classes[WARRIOR] == 0) { + continue; + } + + if (max_level && spells[spell_id].classes[m_pp.class_ - 1] > max_level) { + continue; + } + + if (min_level > 1 && spells[spell_id].classes[m_pp.class_ - 1] < min_level) { + continue; + } + + if (spells[spell_id].skill == EQ::skills::SkillTigerClaw) { + continue; + } + + if (RuleB(Spells, UseCHAScribeHack) && spells[spell_id].effect_id[EFFECT_COUNT - 1] == SE_CHA) { + continue; + } + + if (HasSpellScribed(spell_id)) { + continue; + } + + if (RuleB(Spells, EnableSpellGlobals) && SpellGlobalCheck(spell_id, CharacterID())) { + scribeable = true; + } else if (RuleB(Spells, EnableSpellBuckets) && SpellBucketCheck(spell_id, CharacterID())) { + scribeable = true; } else { scribeable = true; } diff --git a/zone/client.h b/zone/client.h index f755ef432..180e30464 100644 --- a/zone/client.h +++ b/zone/client.h @@ -720,8 +720,8 @@ public: void SendGuildJoin(GuildJoin_Struct* gj); void RefreshGuildInfo(); - int GetClientMaxLevel() const { return client_max_level; } - void SetClientMaxLevel(int max_level) { client_max_level = max_level; } + uint8 GetClientMaxLevel() const { return client_max_level; } + void SetClientMaxLevel(uint8 max_level) { client_max_level = max_level; } void CheckManaEndUpdate(); void SendManaUpdate(); @@ -828,8 +828,8 @@ public: void UntrainDiscBySpellID(uint16 spell_id, bool update_client = true); bool SpellGlobalCheck(uint16 spell_id, uint32 char_id); bool SpellBucketCheck(uint16 spell_id, uint32 char_id); - uint32 GetCharMaxLevelFromQGlobal(); - uint32 GetCharMaxLevelFromBucket(); + uint8 GetCharMaxLevelFromQGlobal(); + uint8 GetCharMaxLevelFromBucket(); void Fling(float value, float target_x, float target_y, float target_z, bool ignore_los = false, bool clipping = false); @@ -2008,7 +2008,7 @@ private: void InterrogateInventory_(bool errorcheck, Client* requester, int16 head, int16 index, const EQ::ItemInstance* inst, const EQ::ItemInstance* parent, bool log, bool silent, bool &error, int depth); bool InterrogateInventory_error(int16 head, int16 index, const EQ::ItemInstance* inst, const EQ::ItemInstance* parent, int depth); - int client_max_level; + uint8 client_max_level; uint32 m_expedition_id = 0; ExpeditionInvite m_pending_expedition_invite { 0 }; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index c97c60031..3c98f8e01 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1318,7 +1318,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) drakkin_details = m_pp.drakkin_details; // Max Level for Character:PerCharacterQglobalMaxLevel and Character:PerCharacterBucketMaxLevel - int client_max_level = 0; + uint8 client_max_level = 0; if (RuleB(Character, PerCharacterQglobalMaxLevel)) { client_max_level = GetCharMaxLevelFromQGlobal(); } else if (RuleB(Character, PerCharacterBucketMaxLevel)) { diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index e1164b760..18eddc546 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -8351,7 +8351,7 @@ XS(XS__checknamefilter); XS(XS__checknamefilter) { dXSARGS; if (items != 1) { - Perl_croak(aTHX_ "Usage: quest::checknamefilter(std::string name)"); + Perl_croak(aTHX_ "Usage: quest::checknamefilter(string name)"); } dXSTARG; diff --git a/zone/exp.cpp b/zone/exp.cpp index aad0f141b..b0fa4ac3a 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -22,6 +22,7 @@ #include "../common/string_util.h" #include "client.h" +#include "data_bucket.h" #include "groups.h" #include "mob.h" #include "raids.h" @@ -722,12 +723,12 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } } - if (GetClientMaxLevel() > 0) { - int client_max_level = GetClientMaxLevel(); + auto client_max_level = GetClientMaxLevel(); + if (client_max_level) { if (GetLevel() >= client_max_level) { - uint32 expneeded = GetEXPForLevel(client_max_level); - if(set_exp > expneeded) { - set_exp = expneeded; + auto exp_needed = GetEXPForLevel(client_max_level); + if (set_exp > exp_needed) { + set_exp = exp_needed; } } } @@ -1148,44 +1149,52 @@ void Client::SendLeadershipEXPUpdate() { FastQueuePacket(&outapp); } -uint32 Client::GetCharMaxLevelFromQGlobal() { - QGlobalCache *char_c = nullptr; - char_c = GetQGlobals(); +uint8 Client::GetCharMaxLevelFromQGlobal() { + auto char_cache = GetQGlobals(); - std::list globalMap; - uint32 ntype = 0; + std::list global_map; - if(char_c) { - QGlobalCache::Combine(globalMap, char_c->GetBucket(), ntype, CharacterID(), zone->GetZoneID()); + if (char_cache) { + QGlobalCache::Combine(global_map, char_cache->GetBucket(), 0, CharacterID(), zone->GetZoneID()); } - auto iter = globalMap.begin(); - uint32 gcount = 0; - while(iter != globalMap.end()) { - if((*iter).name.compare("CharMaxLevel") == 0){ - return atoi((*iter).value.c_str()); + for (const auto& global : global_map) { + if (global.name == "CharMaxLevel") { + if (StringIsNumber(global.value)) { + return static_cast(std::stoul(global.value)); + } } - ++iter; - ++gcount; } return 0; } -uint32 Client::GetCharMaxLevelFromBucket() +uint8 Client::GetCharMaxLevelFromBucket() { - uint32 char_id = CharacterID(); - std::string query = StringFormat("SELECT value FROM data_buckets WHERE `key` = '%i-CharMaxLevel'", char_id); - auto results = database.QueryDatabase(query); - if (!results.Success()) { - LogError("Data bucket for CharMaxLevel for char ID [{}] failed", char_id); - return 0; + auto new_bucket_name = fmt::format( + "{}-CharMaxLevel", + GetBucketKey() + ); + + auto bucket_value = DataBucket::GetData(new_bucket_name); + if (!bucket_value.empty()) { + if (StringIsNumber(bucket_value)) { + return static_cast(std::stoul(bucket_value)); + } } - if (results.RowCount() > 0) { - auto row = results.begin(); - return atoi(row[0]); + auto old_bucket_name = fmt::format( + "{}-CharMaxLevel", + CharacterID() + ); + + bucket_value = DataBucket::GetData(old_bucket_name); + if (!bucket_value.empty()) { + if (StringIsNumber(bucket_value)) { + return static_cast(std::stoul(bucket_value)); + } } + return 0; } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 4fba59888..69d5c2c25 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1844,12 +1844,12 @@ void Lua_Client::SetSecondaryWeaponOrnamentation(uint32 model_id) { self->SetSecondaryWeaponOrnamentation(model_id); } -void Lua_Client::SetClientMaxLevel(int value) { +void Lua_Client::SetClientMaxLevel(uint8 max_level) { Lua_Safe_Call_Void(); - self->SetClientMaxLevel(value); + self->SetClientMaxLevel(max_level); } -int Lua_Client::GetClientMaxLevel() { +uint8 Lua_Client::GetClientMaxLevel() { Lua_Safe_Call_Int(); return self->GetClientMaxLevel(); } diff --git a/zone/lua_client.h b/zone/lua_client.h index 5bb841c57..86a1ea552 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -423,8 +423,8 @@ public: void SetSecondaryWeaponOrnamentation(uint32 model_id); void TaskSelector(luabind::adl::object table); - void SetClientMaxLevel(int value); - int GetClientMaxLevel(); + void SetClientMaxLevel(uint8 max_level); + uint8 GetClientMaxLevel(); void DialogueWindow(std::string markdown); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 732d6cf55..81d6b8a3d 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -4759,12 +4759,12 @@ XS(XS_Client_SetClientMaxLevel); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_SetClientMaxLevel) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: Client::SetClientMaxLevel(THIS, int in_level)"); + Perl_croak(aTHX_ "Usage: Client::SetClientMaxLevel(THIS, uint8 max_level)"); { Client* THIS; - int in_level = (int)SvUV(ST(1)); + uint8 max_level = (uint8) SvUV(ST(1)); VALIDATE_THIS_IS_CLIENT; - THIS->SetClientMaxLevel(in_level); + THIS->SetClientMaxLevel(max_level); } XSRETURN_EMPTY; } @@ -4776,7 +4776,7 @@ XS(XS_Client_GetClientMaxLevel) { Perl_croak(aTHX_ "Usage: Client::GetClientMaxLevel(THIS)"); { Client* THIS; - int RETVAL; + uint8 RETVAL; dXSTARG; VALIDATE_THIS_IS_CLIENT; RETVAL = THIS->GetClientMaxLevel(); diff --git a/zone/spells.cpp b/zone/spells.cpp index 6a448679d..a7b518655 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -78,6 +78,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/data_verification.h" #include "../common/misc_functions.h" +#include "data_bucket.h" #include "quest_parser_collection.h" #include "string_ids.h" #include "worldserver.h" @@ -5511,7 +5512,7 @@ uint32 Client::GetHighestScribedSpellinSpellGroup(uint32 spell_group) return highest_spell_id; } -bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { +bool Client::SpellGlobalCheck(uint16 spell_id, uint32 character_id) { std::string query = fmt::format( "SELECT qglobal, value FROM spell_globals WHERE spellid = {}", spell_id @@ -5536,7 +5537,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { query = fmt::format( "SELECT value FROM quest_globals WHERE charid = {} AND name = '{}'", - char_id, + character_id, EscapeString(spell_global_name) ); @@ -5546,7 +5547,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { "Spell global [{}] for spell ID [{}] for character ID [{}] query failed.", spell_global_name, spell_id, - char_id + character_id ); return false; // Query failed, do not allow scribing. @@ -5557,7 +5558,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { "Spell global [{}] for spell ID [{}] for character ID [{}] does not exist.", spell_global_name, spell_id, - char_id + character_id ); return false; // No rows found, do not allow scribing. @@ -5580,7 +5581,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { "Spell global [{}] for spell ID [{}] for character ID [{}] did not match value [{}] value found was [{}].", spell_global_name, spell_id, - char_id, + character_id, spell_global_value, global_value ); @@ -5588,7 +5589,7 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 char_id) { return false; } -bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) { +bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) { auto query = fmt::format( "SELECT `key`, value FROM spell_buckets WHERE spellid = {}", spell_id @@ -5611,57 +5612,44 @@ bool Client::SpellBucketCheck(uint16 spell_id, uint32 char_id) { return true; // If the entry in the spell_buckets table has nothing set for the qglobal name, allow scribing. } - query = fmt::format( - "SELECT value FROM data_buckets WHERE `key` = '{}-{}'", - char_id, - EscapeString(spell_bucket_name) + auto new_bucket_name = fmt::format( + "{}-{}", + GetBucketKey(), + spell_bucket_name ); - results = database.QueryDatabase(query); - if (!results.Success()) { - LogError( - "Spell bucket [{}] for spell ID [{}] for character ID [{}] query failed.", - spell_bucket_name, - spell_id, - char_id - ); - - return false; // Query failed, do not allow scribing. - } - - if (!results.RowCount()) { - LogError( - "Spell bucket [{}] for spell ID [{}] for character ID [{}] does not exist.", - spell_bucket_name, - spell_id, - char_id - ); - - return false; // No rows found, do not allow scribing. - } - - row = results.begin(); - std::string bucket_value = row[0]; - if (StringIsNumber(bucket_value) && StringIsNumber(spell_bucket_value)) { - if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { - return true; // If value is greater than or equal to spell bucket value, allow scribing. - } - } else { - if (bucket_value == spell_bucket_value) { - return true; // If value is equal to spell bucket value, allow scribing. + auto bucket_value = DataBucket::GetData(new_bucket_name); + if (!bucket_value.empty()) { + if (StringIsNumber(bucket_value) && StringIsNumber(spell_bucket_value)) { + if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { + return true; // If value is greater than or equal to spell bucket value, allow scribing. + } + } else { + if (bucket_value == spell_bucket_value) { + return true; // If value is equal to spell bucket value, allow scribing. + } } } - // If user's data bucket does not meet requirements, do not allow scribing. - LogError( - "Spell bucket [{}] for spell ID [{}] for character ID [{}] did not match value [{}] value found was [{}].", - spell_bucket_name, - spell_id, - char_id, - spell_bucket_value, - bucket_value + auto old_bucket_name = fmt::format( + "{}-{}", + character_id, + spell_bucket_name ); + bucket_value = DataBucket::GetData(old_bucket_name); + if (!bucket_value.empty()) { + if (StringIsNumber(bucket_value) && StringIsNumber(spell_bucket_value)) { + if (std::stoi(bucket_value) >= std::stoi(spell_bucket_value)) { + return true; // If value is greater than or equal to spell bucket value, allow scribing. + } + } else { + if (bucket_value == spell_bucket_value) { + return true; // If value is equal to spell bucket value, allow scribing. + } + } + } + return false; }