From dd06033a588a752a685d0c4477fa7109b0e38532 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 23 Apr 2021 08:47:39 -0400 Subject: [PATCH] Add character-specific zone-based experience modifiers. (#1326) * Add character-specific zone-based experience modifiers. This will allow server operators to give players individual experience modifiers (regular and AA). Zone ID 0 will server as a global modifier for players, if no rows are found the modifier defaults to 1.0 so experience is neither increased nor decreased. Setting a zone-specific modifier will override the zone ID 0 global modifier. Requires a SQL update: sql/git/required/2021_04_11_character_exp_modifiers.sql - Add quest::getaaexpmodifierbycharid(character_id, zone_id) to Perl. - Add eq.get_aa_exp_modifier_by_char_id(character_id, zone_id) to Lua. - Add quest::getexpmodifierbycharid(character_id, zone_id) to Perl. - Add eq.get_exp_modifier_by_char_id(character_id, zone_id) to Lua. - Add quest::setaaexpmodifierbycharid(character_id, zone_id, aa_modifier) to Perl. - Add eq.set_aa_exp_modifier_by_char_id(character_id, zone_id, aa_modifier) to Lua. - Add quest::setexpmodifierbycharid(character_id, zone_id, exp_modifier) to Perl. - Add eq.set_exp_modifier_by_char_id(character_id, zone_id, exp_modifier) to Lua. - Add $client->GetAAEXPModifier(character_id, zone_id) to Perl. - Add client:GetAAEXPModifier(character_id, zone_id) to Lua. - Add $client->GetEXPModifier(character_id, zone_id) to Perl. - Add client:GetEXPModifier(character_id, zone_id) to Lua. - Add $client->SetAAEXPModifier(zone_id, aa_modifier) to Perl. - Add client:SetAAEXPModifier(zone_id, aa_modifier) to Lua. - Add $client->SetEXPModifier(zone_id, exp_modifier) to Perl. - Add client:SetEXPModifier(zone_id, exp_modifier) to Lua. * Removed unneeded []. * Fix variable name, * Fix variable name. * Fix version.h. * Rename 2021_04_11_character_exp_modifiers.sql to 2021_04_23_character_exp_modifiers.sql * Update db_update_manifest.txt --- common/ruletypes.h | 1 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../2021_04_23_character_exp_modifiers.sql | 7 ++ zone/client.h | 5 ++ zone/embparser_api.cpp | 62 ++++++++++++++ zone/exp.cpp | 8 ++ zone/lua_client.cpp | 26 +++++- zone/lua_client.h | 4 + zone/lua_general.cpp | 22 ++++- zone/perl_client.cpp | 70 ++++++++++++++++ zone/questmgr.cpp | 14 ++++ zone/questmgr.h | 6 +- zone/zonedb.cpp | 82 +++++++++++++++++++ zone/zonedb.h | 5 ++ 15 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 utils/sql/git/required/2021_04_23_character_exp_modifiers.sql diff --git a/common/ruletypes.h b/common/ruletypes.h index b66061dbd..15cc43575 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -162,6 +162,7 @@ RULE_BOOL(Character, UseNoJunkFishing, false, "Disregards junk items when fishin RULE_BOOL(Character, SoftDeletes, true, "When characters are deleted in character select, they are only soft deleted") RULE_INT(Character, DefaultGuild, 0, "If not 0, new characters placed into the guild # indicated") RULE_BOOL(Character, ProcessFearedProximity, false, "Processes proximity checks when feared") +RULE_BOOL(Character, EnableCharacterEXPMods, false, "Enables character zone-based experience modifiers.") RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/common/version.h b/common/version.h index 0ad111e7c..7b66c1dc4 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9163 +#define CURRENT_BINARY_DATABASE_VERSION 9164 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9027 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 393dc23e8..071a20e14 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -417,6 +417,7 @@ 9161|2021_02_15_npc_spell_entries_unsigned.sql|SELECT * FROM db_version WHERE version >= 9161|empty| 9162|2021_02_17_server_scheduled_events.sql|SELECT * FROM db_version WHERE version >= 9162|empty| 9163|2021_04_17_zone_safe_heading_changes.sql|SHOW COLUMNS FROM `zone` LIKE 'safe_heading'|empty| +9164|2021_04_23_character_exp_modifiers.sql|SHOW TABLES LIKE 'character_exp_modifiers'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2021_04_23_character_exp_modifiers.sql b/utils/sql/git/required/2021_04_23_character_exp_modifiers.sql new file mode 100644 index 000000000..4a1bcb5de --- /dev/null +++ b/utils/sql/git/required/2021_04_23_character_exp_modifiers.sql @@ -0,0 +1,7 @@ +CREATE TABLE `character_exp_modifiers` ( + `character_id` int NOT NULL, + `zone_id` int NOT NULL, + `aa_modifier` float NOT NULL, + `exp_modifier` float NOT NULL, + PRIMARY KEY (`character_id`, `zone_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Compact; diff --git a/zone/client.h b/zone/client.h index 741408d3f..6e2840217 100644 --- a/zone/client.h +++ b/zone/client.h @@ -600,6 +600,11 @@ public: inline uint32 GetEXP() const { return m_pp.exp; } + inline double GetAAEXPModifier(uint32 zone_id) const { return database.GetAAEXPModifier(CharacterID(), zone_id); }; + inline double GetEXPModifier(uint32 zone_id) const { return database.GetEXPModifier(CharacterID(), zone_id); }; + inline void SetAAEXPModifier(uint32 zone_id, double aa_modifier) { database.SetAAEXPModifier(CharacterID(), zone_id, aa_modifier); }; + inline void SetEXPModifier(uint32 zone_id, double exp_modifier) { database.SetEXPModifier(CharacterID(), zone_id, exp_modifier); }; + bool UpdateLDoNPoints(int32 points, uint32 theme); void SetPVPPoints(uint32 Points) { m_pp.PVPCurrentPoints = Points; } uint32 GetPVPPoints() { return m_pp.PVPCurrentPoints; } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 4ab576cd2..b95e7946e 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -6494,6 +6494,64 @@ XS(XS__gethexcolorcode) { XSRETURN(1); } +XS(XS__getaaexpmodifierbycharid); +XS(XS__getaaexpmodifierbycharid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::getaaexpmodifierbycharid(uint32 character_id, uint32 zone_id)"); + + dXSTARG; + double aa_modifier; + uint32 character_id = (uint32) SvUV(ST(0)); + uint32 zone_id = (uint32) SvUV(ST(1)); + aa_modifier = quest_manager.GetAAEXPModifierByCharID(character_id, zone_id); + XSprePUSH; + PUSHn((double) aa_modifier); + XSRETURN(1); +} + +XS(XS__getexpmodifierbycharid); +XS(XS__getexpmodifierbycharid) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::getexpmodifierbycharid(uint32 character_id, uint32 zone_id)"); + + dXSTARG; + double exp_modifier; + uint32 character_id = (uint32) SvUV(ST(0)); + uint32 zone_id = (uint32) SvUV(ST(1)); + exp_modifier = quest_manager.GetEXPModifierByCharID(character_id, zone_id); + XSprePUSH; + PUSHn((double) exp_modifier); + XSRETURN(1); +} + +XS(XS__setaaexpmodifierbycharid); +XS(XS__setaaexpmodifierbycharid) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: quest::setaaexpmodifierbycharid(uint32 character_id, uint32 zone_id, float aa_modifier)"); + } + uint32 character_id = (uint32) SvUV(ST(0)); + uint32 zone_id = (uint32) SvUV(ST(1)); + double aa_modifier = (double) SvNV(ST(2)); + quest_manager.SetAAEXPModifierByCharID(character_id, zone_id, aa_modifier); + XSRETURN_EMPTY; +} + +XS(XS__setexpmodifierbycharid); +XS(XS__setexpmodifierbycharid) { + dXSARGS; + if (items != 3) { + Perl_croak(aTHX_ "Usage: quest::setexpmodifierbycharid(uint32 character_id, uint32 zone_id, float exp_modifier)"); + } + uint32 character_id = (uint32) SvUV(ST(0)); + uint32 zone_id = (uint32) SvUV(ST(1)); + double exp_modifier = (double) SvNV(ST(2)); + quest_manager.SetEXPModifierByCharID(character_id, zone_id, exp_modifier); + XSRETURN_EMPTY; +} + /* This is the callback perl will look for to setup the quest package's XSUBs @@ -6700,10 +6758,12 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "follow"), XS__follow, file); newXS(strcpy(buf, "forcedoorclose"), XS__forcedoorclose, file); newXS(strcpy(buf, "forcedooropen"), XS__forcedooropen, file); + newXS(strcpy(buf, "getaaexpmodifierbycharid"), XS__getaaexpmodifierbycharid, file); newXS(strcpy(buf, "getcharidbyname"), XS__getcharidbyname, file); newXS(strcpy(buf, "getclassname"), XS__getclassname, file); newXS(strcpy(buf, "gethexcolorcode"), XS__gethexcolorcode, file); newXS(strcpy(buf, "getcurrencyid"), XS__getcurrencyid, file); + newXS(strcpy(buf, "getexpmodifierbycharid"), XS__getexpmodifierbycharid, file); newXS(strcpy(buf, "get_expedition"), XS__get_expedition, file); newXS(strcpy(buf, "get_expedition_by_char_id"), XS__get_expedition_by_char_id, file); newXS(strcpy(buf, "get_expedition_by_dz_id"), XS__get_expedition_by_dz_id, file); @@ -6792,10 +6852,12 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "scribespells"), XS__scribespells, file); newXS(strcpy(buf, "secondstotime"), XS__secondstotime, file); newXS(strcpy(buf, "selfcast"), XS__selfcast, file); + newXS(strcpy(buf, "setaaexpmodifierbycharid"), XS__setaaexpmodifierbycharid, file); newXS(strcpy(buf, "set_proximity"), XS__set_proximity, file); newXS(strcpy(buf, "set_zone_flag"), XS__set_zone_flag, file); newXS(strcpy(buf, "setallskill"), XS__setallskill, file); newXS(strcpy(buf, "setanim"), XS__setanim, file); + newXS(strcpy(buf, "setexpmodifierbycharid"), XS__setexpmodifierbycharid, file); newXS(strcpy(buf, "setglobal"), XS__setglobal, file); newXS(strcpy(buf, "setguild"), XS__setguild, file); newXS(strcpy(buf, "sethp"), XS__sethp, file); diff --git a/zone/exp.cpp b/zone/exp.cpp index 608a7c4ad..9b4df5492 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -327,6 +327,10 @@ void Client::CalculateStandardAAExp(uint32 &add_aaxp, uint8 conlevel, bool resex add_aaxp *= RuleR(Character, FinalExpMultiplier); } + if (RuleB(Character, EnableCharacterEXPMods)) { + add_aaxp *= GetAAEXPModifier(this->GetZoneID()); + } + add_aaxp = (uint32)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod); } @@ -486,6 +490,10 @@ void Client::CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, add_exp *= RuleR(Character, FinalExpMultiplier); } + if (RuleB(Character, EnableCharacterEXPMods)) { + add_exp *= GetEXPModifier(this->GetZoneID()); + } + add_exp = GetEXP() + add_exp; } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 1a71026f2..6b6265ce5 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -2063,6 +2063,26 @@ void Lua_Client::Fling(float value, float target_x, float target_y, float target self->Fling(value, target_x, target_y, target_z, ignore_los, clipping); } +double Lua_Client::GetAAEXPModifier(uint32 zone_id) { + Lua_Safe_Call_Real(); + return self->GetAAEXPModifier(zone_id); +} + +double Lua_Client::GetEXPModifier(uint32 zone_id) { + Lua_Safe_Call_Real(); + return self->GetEXPModifier(zone_id); +} + +void Lua_Client::SetAAEXPModifier(uint32 zone_id, double aa_modifier) { + Lua_Safe_Call_Void(); + self->SetAAEXPModifier(zone_id, aa_modifier); +} + +void Lua_Client::SetEXPModifier(uint32 zone_id, double exp_modifier) { + Lua_Safe_Call_Void(); + self->SetEXPModifier(zone_id, exp_modifier); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -2411,7 +2431,11 @@ luabind::scope lua_register_client() { .def("MovePCDynamicZone", (void(Lua_Client::*)(std::string, int, bool))&Lua_Client::MovePCDynamicZone) .def("Fling", (void(Lua_Client::*)(float,float,float,float))&Lua_Client::Fling) .def("Fling", (void(Lua_Client::*)(float,float,float,float,bool))&Lua_Client::Fling) - .def("Fling", (void(Lua_Client::*)(float,float,float,float,bool,bool))&Lua_Client::Fling); + .def("Fling", (void(Lua_Client::*)(float,float,float,float,bool,bool))&Lua_Client::Fling) + .def("GetAAEXPModifier", (double(Lua_Client::*)(uint32))&Lua_Client::GetAAEXPModifier) + .def("GetEXPModifier", (double(Lua_Client::*)(uint32))&Lua_Client::GetEXPModifier) + .def("SetAAEXPModifier", (void(Lua_Client::*)(uint32,double))&Lua_Client::SetAAEXPModifier) + .def("SetEXPModifier", (void(Lua_Client::*)(uint32,double))&Lua_Client::SetEXPModifier); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index 6d28656c1..bfd0f6b84 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -70,6 +70,10 @@ public: int GetBaseWIS(); int GetWeight(); uint32 GetEXP(); + double GetEXPModifier(uint32 zone_id); + double GetAAEXPModifier(uint32 zone_id); + void SetAAEXPModifier(uint32 zone_id, double aa_modifier); + void SetEXPModifier(uint32 zone_id, double exp_modifier); uint32 GetAAExp(); uint32 GetAAPercent(); uint32 GetTotalSecondsPlayed(); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index a1b0a1a26..a121194be 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -2326,6 +2326,22 @@ std::string lua_get_hex_color_code(std::string color_name) { return quest_manager.gethexcolorcode(color_name); } +double lua_get_aa_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id) { + return database.GetAAEXPModifier(character_id, zone_id); +} + +double lua_get_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id) { + return database.GetEXPModifier(character_id, zone_id); +} + +void lua_set_aa_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, double aa_modifier) { + database.SetAAEXPModifier(character_id, zone_id, aa_modifier); +} + +void lua_set_exp_modifier_by_char_id(uint32 character_id, uint32 zone_id, double exp_modifier) { + database.SetEXPModifier(character_id, zone_id, exp_modifier); +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -2868,7 +2884,11 @@ luabind::scope lua_register_general() { luabind::def("log_combat", (void(*)(std::string))&lua_log_combat), luabind::def("seconds_to_time", &lua_seconds_to_time), luabind::def("get_hex_color_code", &lua_get_hex_color_code), - + luabind::def("get_aa_exp_modifier_by_char_id", &lua_get_aa_exp_modifier_by_char_id), + luabind::def("get_exp_modifier_by_char_id", &lua_get_exp_modifier_by_char_id), + luabind::def("set_aa_exp_modifier_by_char_id", &lua_set_aa_exp_modifier_by_char_id), + luabind::def("set_exp_modifier_by_char_id", &lua_set_exp_modifier_by_char_id), + /** * Expansions */ diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index e3b5f4f64..4d675d8fb 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5224,6 +5224,72 @@ XS(XS_Client_GetInventory) { XSRETURN(1); } +XS(XS_Client_GetAAEXPModifier); +XS(XS_Client_GetAAEXPModifier) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::GetAAEXPModifier(THIS, uint32 zone_id)"); + { + Client* THIS; + double aa_modifier = 1.0f; + uint32 zone_id = (uint32)SvUV(ST(1)); + dXSTARG; + VALIDATE_THIS_IS_CLIENT; + aa_modifier = THIS->GetAAEXPModifier(zone_id); + XSprePUSH; + PUSHn((double) aa_modifier); + } + XSRETURN(1); +} + +XS(XS_Client_GetEXPModifier); +XS(XS_Client_GetEXPModifier) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::GetEXPModifier(THIS, uint32 zone_id)"); + { + Client* THIS; + double exp_modifier = 1.0f; + uint32 zone_id = (uint32)SvUV(ST(1)); + dXSTARG; + VALIDATE_THIS_IS_CLIENT; + exp_modifier = THIS->GetEXPModifier(zone_id); + XSprePUSH; + PUSHn((double) exp_modifier); + } + XSRETURN(1); +} + +XS(XS_Client_SetAAEXPModifier); +XS(XS_Client_SetAAEXPModifier) { + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: Client::SetAAEXPModifier(THIS, uint32 zone_id, float aa_modifier)"); + { + Client* THIS; + uint32 zone_id = (uint32)SvUV(ST(1)); + double aa_modifier = (double) SvNV(ST(2)); + VALIDATE_THIS_IS_CLIENT; + THIS->SetAAEXPModifier(zone_id, aa_modifier); + } + XSRETURN_EMPTY; +} + +XS(XS_Client_SetEXPModifier); +XS(XS_Client_SetEXPModifier) { + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: Client::SetEXPModifier(THIS, uint32 zone_id, float exp_modifier)"); + { + Client* THIS; + uint32 zone_id = (uint32)SvUV(ST(1)); + double exp_modifier = (double) SvNV(ST(2)); + VALIDATE_THIS_IS_CLIENT; + THIS->SetEXPModifier(zone_id, exp_modifier); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" #endif @@ -5285,6 +5351,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "ForageItem"), XS_Client_ForageItem, file, "$"); newXSproto(strcpy(buf, "Freeze"), XS_Client_Freeze, file, "$"); newXSproto(strcpy(buf, "GetAAExp"), XS_Client_GetAAExp, file, "$"); + newXSproto(strcpy(buf, "GetAAEXPModifier"), XS_Client_GetAAEXPModifier, file, "$$"); newXSproto(strcpy(buf, "GetAALevel"), XS_Client_GetAALevel, file, "$$"); newXSproto(strcpy(buf, "GetAAPercent"), XS_Client_GetAAPercent, file, "$"); newXSproto(strcpy(buf, "GetAAPoints"), XS_Client_GetAAPoints, file, "$$"); @@ -5328,6 +5395,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "GetEndurance"), XS_Client_GetEndurance, file, "$"); newXSproto(strcpy(buf, "GetEnduranceRatio"), XS_Client_GetEnduranceRatio, file, "$"); newXSproto(strcpy(buf, "GetEXP"), XS_Client_GetEXP, file, "$"); + newXSproto(strcpy(buf, "GetEXPModifier"), XS_Client_GetEXPModifier, file, "$$"); newXSproto(strcpy(buf, "GetExpedition"), XS_Client_GetExpedition, file, "$"); newXSproto(strcpy(buf, "GetExpeditionLockouts"), XS_Client_GetExpeditionLockouts, file, "$;$"); newXSproto(strcpy(buf, "GetFace"), XS_Client_GetFace, file, "$"); @@ -5454,6 +5522,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "SendToGuildHall"), XS_Client_SendToGuildHall, file, "$"); newXSproto(strcpy(buf, "SendWebLink"), XS_Client_SendWebLink, file, "$:$"); newXSproto(strcpy(buf, "SendZoneFlagInfo"), XS_Client_SendZoneFlagInfo, file, "$$"); + newXSproto(strcpy(buf, "SetAAEXPModifier"), XS_Client_SetAAEXPModifier, file, "$$$"); newXSproto(strcpy(buf, "SetAAPoints"), XS_Client_SetAAPoints, file, "$$"); newXSproto(strcpy(buf, "SetAATitle"), XS_Client_SetAATitle, file, "$$;$"); newXSproto(strcpy(buf, "SetAccountFlag"), XS_Client_SetAccountFlag, file, "$$"); @@ -5475,6 +5544,7 @@ XS(boot_Client) { newXSproto(strcpy(buf, "SetEbonCrystals"), XS_Client_SetEbonCrystals, file, "$$"); newXSproto(strcpy(buf, "SetEndurance"), XS_Client_SetEndurance, file, "$$"); newXSproto(strcpy(buf, "SetEXP"), XS_Client_SetEXP, file, "$$$;$"); + newXSproto(strcpy(buf, "SetEXPModifier"), XS_Client_SetEXPModifier, file, "$$$"); newXSproto(strcpy(buf, "SetFactionLevel"), XS_Client_SetFactionLevel, file, "$$$$$$"); newXSproto(strcpy(buf, "SetFactionLevel2"), XS_Client_SetFactionLevel2, file, "$$$$$$$"); newXSproto(strcpy(buf, "SetFeigned"), XS_Client_SetFeigned, file, "$$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 3872e2a35..1a1eba4fc 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -4616,3 +4616,17 @@ std::string QuestManager::gethexcolorcode(std::string color_name) { return std::string(); } +double QuestManager::GetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id) const { + return database.GetAAEXPModifier(character_id, zone_id); +} +double QuestManager::GetEXPModifierByCharID(uint32 character_id, uint32 zone_id) const { + return database.GetEXPModifier(character_id, zone_id); +} + +void QuestManager::SetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, double aa_modifier) { + database.SetAAEXPModifier(character_id, zone_id, aa_modifier); +} + +void QuestManager::SetEXPModifierByCharID(uint32 character_id, uint32 zone_id, double exp_modifier) { + database.SetEXPModifier(character_id, zone_id, exp_modifier); +} diff --git a/zone/questmgr.h b/zone/questmgr.h index f17ffda1a..83ffe6f5b 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -373,7 +373,11 @@ public: void ClearNPCTypeCache(int npctype_id); void ReloadZoneStaticData(); std::string secondstotime(int duration); - std::string gethexcolorcode(std::string color_name); + std::string gethexcolorcode(std::string color_name); + double GetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id) const; + double GetEXPModifierByCharID(uint32 character_id, uint32 zone_id) const; + void SetAAEXPModifierByCharID(uint32 character_id, uint32 zone_id, double aa_modifier); + void SetEXPModifierByCharID(uint32 character_id, uint32 zone_id, double exp_modifier); Client *GetInitiator() const; NPC *GetNPC() const; diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d68620c38..327e43058 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -4893,3 +4893,85 @@ uint32 ZoneDatabase::SaveSaylinkID(const char* saylink_text) return results.LastInsertedID(); } + +double ZoneDatabase::GetAAEXPModifier(uint32 character_id, uint32 zone_id) const { + std::string query = fmt::format( + SQL( + SELECT + `aa_modifier` + FROM + `character_exp_modifiers` + WHERE + `character_id` = {} + AND + (`zone_id` = {} OR `zone_id` = 0) + ORDER BY `zone_id` DESC + LIMIT 1 + ), + character_id, + zone_id + ); + auto results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + return atof(row[0]); + } + return 1.0f; +} + +double ZoneDatabase::GetEXPModifier(uint32 character_id, uint32 zone_id) const { + std::string query = fmt::format( + SQL( + SELECT + `exp_modifier` + FROM + `character_exp_modifiers` + WHERE + `character_id` = {} + AND + (`zone_id` = {} OR `zone_id` = 0) + ORDER BY `zone_id` DESC + LIMIT 1 + ), + character_id, + zone_id + ); + auto results = database.QueryDatabase(query); + for (auto row = results.begin(); row != results.end(); ++row) { + return atof(row[0]); + } + return 1.0f; +} + +void ZoneDatabase::SetAAEXPModifier(uint32 character_id, uint32 zone_id, double aa_modifier) { + float exp_modifier = GetEXPModifier(character_id, zone_id); + std::string query = fmt::format( + SQL( + REPLACE INTO + `character_exp_modifiers` + VALUES + ({}, {}, {}, {}) + ), + character_id, + zone_id, + aa_modifier, + exp_modifier + ); + database.QueryDatabase(query); +} + +void ZoneDatabase::SetEXPModifier(uint32 character_id, uint32 zone_id, double exp_modifier) { + float aa_modifier = GetAAEXPModifier(character_id, zone_id); + std::string query = fmt::format( + SQL( + REPLACE INTO + `character_exp_modifiers` + VALUES + ({}, {}, {}, {}) + ), + character_id, + zone_id, + aa_modifier, + exp_modifier + ); + database.QueryDatabase(query); +} diff --git a/zone/zonedb.h b/zone/zonedb.h index b77c157d3..d7e41ecb0 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -331,6 +331,11 @@ public: bool SaveCharacterSkill(uint32 character_id, uint32 skill_id, uint32 value); bool SaveCharacterSpell(uint32 character_id, uint32 spell_id, uint32 slot_id); bool SaveCharacterTribute(uint32 character_id, PlayerProfile_Struct* pp); + + double GetAAEXPModifier(uint32 character_id, uint32 zone_id) const; + double GetEXPModifier(uint32 character_id, uint32 zone_id) const; + void SetAAEXPModifier(uint32 character_id, uint32 zone_id, double aa_modifier); + void SetEXPModifier(uint32 character_id, uint32 zone_id, double exp_modifier); /* Character Inventory */ bool NoRentExpired(const char* name);