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
This commit is contained in:
Alex 2021-04-23 08:47:39 -04:00 committed by GitHub
parent 13a50f7806
commit dd06033a58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 311 additions and 4 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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; }

View File

@ -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);

View File

@ -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;
}

View File

@ -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_<Lua_Client, Lua_Mob>("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() {

View File

@ -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();

View File

@ -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
*/

View File

@ -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, "$$");

View File

@ -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);
}

View File

@ -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;

View File

@ -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);
}

View File

@ -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);