2013-05-09 10:44:08 -04:00
/* EQEMu: Everquest Server Emulator
Copyright ( C ) 2001 - 2003 EQEMu Development Team ( http : //eqemulator.net)
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; version 2 of the License .
2013-05-06 13:07:41 -04:00
2013-05-09 10:44:08 -04:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY except by those people which sell it , which
2013-02-16 16:14:39 -08:00
are required to give you total support for your newly bought product ;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
2013-05-09 10:44:08 -04:00
A PARTICULAR PURPOSE . See the GNU General Public License for more details .
2013-05-06 13:07:41 -04:00
2013-05-09 10:44:08 -04:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2013-02-16 16:14:39 -08:00
*/
2014-12-15 17:22:13 -06:00
2015-01-19 04:12:09 -06:00
# include "../common/global_define.h"
2013-02-20 13:54:26 -08:00
# include "../common/features.h"
2013-02-16 16:14:39 -08:00
# include "../common/rulesys.h"
2014-12-15 17:22:13 -06:00
# include "../common/string_util.h"
# include "client.h"
# include "groups.h"
# include "mob.h"
# include "raids.h"
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
# include "queryserv.h"
2014-12-15 17:22:13 -06:00
# include "quest_parser_collection.h"
2017-06-10 15:12:31 -07:00
# include "lua_parser.h"
2014-12-15 17:22:13 -06:00
# include "string_ids.h"
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
2014-12-15 20:08:46 -05:00
# ifdef BOTS
# include "bot.h"
# endif
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
extern QueryServ * QServ ;
2013-02-16 16:14:39 -08:00
2018-01-06 10:22:26 -05:00
static uint32 ScaleAAXPBasedOnCurrentAATotal ( int earnedAA , uint32 add_aaxp )
2018-01-01 14:23:24 -05:00
{
2018-01-06 10:22:26 -05:00
float baseModifier = RuleR ( AA , ModernAAScalingStartPercent ) ;
int aaMinimum = RuleI ( AA , ModernAAScalingAAMinimum ) ;
int aaLimit = RuleI ( AA , ModernAAScalingAALimit ) ;
2018-01-01 14:23:24 -05:00
// Are we within the scaling window?
if ( earnedAA > = aaLimit | | earnedAA < aaMinimum )
{
2019-09-01 23:54:24 -05:00
LogDebug ( " Not within AA scaling window " ) ;
2018-01-01 14:23:24 -05:00
// At or past the limit. We're done.
2018-01-06 10:22:26 -05:00
return add_aaxp ;
2018-01-01 14:23:24 -05:00
}
// We're not at the limit yet. How close are we?
int remainingAA = aaLimit - earnedAA ;
// We might not always be X - 0
int scaleRange = aaLimit - aaMinimum ;
// Normalize and get the effectiveness based on the range and the character's
// current spent AA.
float normalizedScale = ( float ) remainingAA / scaleRange ;
// Scale.
2018-01-06 10:22:26 -05:00
uint32 totalWithExpMod = add_aaxp * ( baseModifier / 100 ) * normalizedScale ;
2018-01-01 14:23:24 -05:00
// Are we so close to the scale limit that we're earning more XP without scaling? This
// will happen when we get very close to the limit. In this case, just grant the unscaled
// amount.
2018-01-06 10:22:26 -05:00
if ( totalWithExpMod < add_aaxp )
2018-01-01 14:23:24 -05:00
{
2018-01-06 10:22:26 -05:00
return add_aaxp ;
2018-01-01 14:23:24 -05:00
}
2018-01-02 17:27:59 -05:00
Log ( Logs : : Detail ,
Logs : : None ,
" Total before the modifier %d :: NewTotal %d :: ScaleRange: %d, SpentAA: %d, RemainingAA: %d, normalizedScale: %0.3f " ,
2018-01-06 10:22:26 -05:00
add_aaxp , totalWithExpMod , scaleRange , earnedAA , remainingAA , normalizedScale ) ;
2018-01-01 14:23:24 -05:00
return totalWithExpMod ;
}
2013-02-16 16:14:39 -08:00
static uint32 MaxBankedGroupLeadershipPoints ( int Level )
{
if ( Level < 35 )
return 4 ;
if ( Level < 51 )
return 6 ;
return 8 ;
}
static uint32 MaxBankedRaidLeadershipPoints ( int Level )
{
if ( Level < 45 )
return 6 ;
if ( Level < 55 )
return 8 ;
return 10 ;
}
2015-05-25 12:35:53 -04:00
uint32 Client : : CalcEXP ( uint8 conlevel ) {
uint32 in_add_exp = EXP_FORMULA ;
if ( ( XPRate ! = 0 ) )
in_add_exp = static_cast < uint32 > ( in_add_exp * ( static_cast < float > ( XPRate ) / 100.0f ) ) ;
float totalmod = 1.0 ;
float zemmod = 1.0 ;
//get modifiers
if ( RuleR ( Character , ExpMultiplier ) > = 0 ) {
totalmod * = RuleR ( Character , ExpMultiplier ) ;
}
if ( zone - > newzone_data . zone_exp_multiplier > = 0 ) {
zemmod * = zone - > newzone_data . zone_exp_multiplier ;
}
if ( RuleB ( Character , UseRaceClassExpBonuses ) )
{
if ( GetBaseRace ( ) = = HALFLING ) {
totalmod * = 1.05 ;
}
if ( GetClass ( ) = = ROGUE | | GetClass ( ) = = WARRIOR ) {
totalmod * = 1.05 ;
}
}
if ( zone - > IsHotzone ( ) )
{
totalmod + = RuleR ( Zone , HotZoneBonus ) ;
}
in_add_exp = uint32 ( float ( in_add_exp ) * totalmod * zemmod ) ;
if ( RuleB ( Character , UseXPConScaling ) )
{
if ( conlevel ! = 0xFF ) {
switch ( conlevel )
{
2017-03-13 15:07:56 -04:00
case CON_GRAY :
2015-05-25 12:35:53 -04:00
in_add_exp = 0 ;
return 0 ;
2017-03-13 15:07:56 -04:00
case CON_GREEN :
in_add_exp = in_add_exp * RuleI ( Character , GreenModifier ) / 100 ;
break ;
2015-05-25 12:35:53 -04:00
case CON_LIGHTBLUE :
in_add_exp = in_add_exp * RuleI ( Character , LightBlueModifier ) / 100 ;
break ;
case CON_BLUE :
in_add_exp = in_add_exp * RuleI ( Character , BlueModifier ) / 100 ;
break ;
case CON_WHITE :
in_add_exp = in_add_exp * RuleI ( Character , WhiteModifier ) / 100 ;
break ;
case CON_YELLOW :
in_add_exp = in_add_exp * RuleI ( Character , YellowModifier ) / 100 ;
break ;
case CON_RED :
in_add_exp = in_add_exp * RuleI ( Character , RedModifier ) / 100 ;
break ;
}
}
}
float aatotalmod = 1.0 ;
if ( zone - > newzone_data . zone_exp_multiplier > = 0 ) {
aatotalmod * = zone - > newzone_data . zone_exp_multiplier ;
}
if ( RuleB ( Character , UseRaceClassExpBonuses ) )
{
if ( GetBaseRace ( ) = = HALFLING ) {
aatotalmod * = 1.05 ;
}
if ( GetClass ( ) = = ROGUE | | GetClass ( ) = = WARRIOR ) {
aatotalmod * = 1.05 ;
}
}
if ( RuleB ( Zone , LevelBasedEXPMods ) ) {
if ( zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod ) {
in_add_exp * = zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod ;
}
}
return in_add_exp ;
}
2017-06-10 15:12:31 -07:00
uint32 Client : : GetExperienceForKill ( Mob * against )
{
# ifdef LUA_EQEMU
uint32 lua_ret = 0 ;
bool ignoreDefault = false ;
lua_ret = LuaParser : : Instance ( ) - > GetExperienceForKill ( this , against , ignoreDefault ) ;
if ( ignoreDefault ) {
return lua_ret ;
}
# endif
if ( against & & against - > IsNPC ( ) ) {
uint32 level = ( uint32 ) against - > GetLevel ( ) ;
return EXP_FORMULA ;
}
return 0 ;
}
2018-01-06 10:22:26 -05:00
float static GetConLevelModifierPercent ( uint8 conlevel )
{
switch ( conlevel )
{
case CON_GREEN :
return ( float ) RuleI ( Character , GreenModifier ) / 100 ;
break ;
case CON_LIGHTBLUE :
return ( float ) RuleI ( Character , LightBlueModifier ) / 100 ;
break ;
case CON_BLUE :
return ( float ) RuleI ( Character , BlueModifier ) / 100 ;
break ;
case CON_WHITE :
return ( float ) RuleI ( Character , WhiteModifier ) / 100 ;
break ;
case CON_YELLOW :
return ( float ) RuleI ( Character , YellowModifier ) / 100 ;
break ;
case CON_RED :
return ( float ) RuleI ( Character , RedModifier ) / 100 ;
break ;
default :
return 0 ;
}
}
2013-02-16 16:14:39 -08:00
2018-01-06 10:22:26 -05:00
void Client : : CalculateNormalizedAAExp ( uint32 & add_aaxp , uint8 conlevel , bool resexp )
{
// Functionally this is the same as having the case in the switch, but this is
// cleaner to read.
if ( CON_GRAY = = conlevel | | resexp )
{
add_aaxp = 0 ;
return ;
}
// For this, we ignore the provided value of add_aaxp because it doesn't
// apply. XP per AA is normalized such that there are X white con kills
// per AA.
uint32 whiteConKillsPerAA = RuleI ( AA , NormalizedAANumberOfWhiteConPerAA ) ;
uint32 xpPerAA = RuleI ( AA , ExpPerPoint ) ;
float colorModifier = GetConLevelModifierPercent ( conlevel ) ;
float percentToAAXp = ( float ) m_epp . perAA / 100 ;
// Normalize the amount of AA XP we earned for this kill.
add_aaxp = percentToAAXp * ( xpPerAA / ( whiteConKillsPerAA / colorModifier ) ) ;
}
void Client : : CalculateStandardAAExp ( uint32 & add_aaxp , uint8 conlevel , bool resexp )
{
if ( ! resexp )
{
//if XP scaling is based on the con of a monster, do that now.
if ( RuleB ( Character , UseXPConScaling ) )
{
if ( conlevel ! = 0xFF & & ! resexp )
{
add_aaxp * = GetConLevelModifierPercent ( conlevel ) ;
}
}
} //end !resexp
float aatotalmod = 1.0 ;
if ( zone - > newzone_data . zone_exp_multiplier > = 0 ) {
aatotalmod * = zone - > newzone_data . zone_exp_multiplier ;
}
// Shouldn't race not affect AA XP?
if ( RuleB ( Character , UseRaceClassExpBonuses ) )
{
if ( GetBaseRace ( ) = = HALFLING ) {
aatotalmod * = 1.05 ;
}
if ( GetClass ( ) = = ROGUE | | GetClass ( ) = = WARRIOR ) {
aatotalmod * = 1.05 ;
}
}
// why wasn't this here? Where should it be?
if ( zone - > IsHotzone ( ) )
{
aatotalmod + = RuleR ( Zone , HotZoneBonus ) ;
}
if ( RuleB ( Zone , LevelBasedEXPMods ) ) {
if ( zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod ) {
add_aaxp * = zone - > level_exp_mod [ GetLevel ( ) ] . AAExpMod ;
}
}
add_aaxp = ( uint32 ) ( RuleR ( Character , AAExpMultiplier ) * add_aaxp * aatotalmod ) ;
}
void Client : : CalculateLeadershipExp ( uint32 & add_exp , uint8 conlevel )
{
if ( IsLeadershipEXPOn ( ) & & ( conlevel = = CON_BLUE | | conlevel = = CON_WHITE | | conlevel = = CON_YELLOW | | conlevel = = CON_RED ) )
{
add_exp = static_cast < uint32 > ( static_cast < float > ( add_exp ) * 0.8f ) ;
if ( GetGroup ( ) )
{
if ( m_pp . group_leadership_points < MaxBankedGroupLeadershipPoints ( GetLevel ( ) )
& & RuleI ( Character , KillsPerGroupLeadershipAA ) > 0 )
{
uint32 exp = GROUP_EXP_PER_POINT / RuleI ( Character , KillsPerGroupLeadershipAA ) ;
Client * mentoree = GetGroup ( ) - > GetMentoree ( ) ;
if ( GetGroup ( ) - > GetMentorPercent ( ) & & mentoree & &
mentoree - > GetGroupPoints ( ) < MaxBankedGroupLeadershipPoints ( mentoree - > GetLevel ( ) ) )
{
uint32 mentor_exp = exp * ( GetGroup ( ) - > GetMentorPercent ( ) / 100.0f ) ;
exp - = mentor_exp ;
mentoree - > AddLeadershipEXP ( mentor_exp , 0 ) ; // ends up rounded down
2019-08-11 00:14:02 -05:00
mentoree - > MessageString ( Chat : : LeaderShip , GAIN_GROUP_LEADERSHIP_EXP ) ;
2018-01-06 10:22:26 -05:00
}
if ( exp > 0 )
{
// possible if you mentor 100% to the other client
AddLeadershipEXP ( exp , 0 ) ; // ends up rounded up if mentored, no idea how live actually does it
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , GAIN_GROUP_LEADERSHIP_EXP ) ;
2018-01-06 10:22:26 -05:00
}
}
else
{
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , MAX_GROUP_LEADERSHIP_POINTS ) ;
2018-01-06 10:22:26 -05:00
}
}
else
{
Raid * raid = GetRaid ( ) ;
// Raid leaders CAN NOT gain group AA XP, other group leaders can though!
if ( raid - > IsLeader ( this ) )
{
if ( m_pp . raid_leadership_points < MaxBankedRaidLeadershipPoints ( GetLevel ( ) )
& & RuleI ( Character , KillsPerRaidLeadershipAA ) > 0 )
{
AddLeadershipEXP ( 0 , RAID_EXP_PER_POINT / RuleI ( Character , KillsPerRaidLeadershipAA ) ) ;
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , GAIN_RAID_LEADERSHIP_EXP ) ;
2018-01-06 10:22:26 -05:00
}
else
{
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , MAX_RAID_LEADERSHIP_POINTS ) ;
2018-01-06 10:22:26 -05:00
}
}
else
{
if ( m_pp . group_leadership_points < MaxBankedGroupLeadershipPoints ( GetLevel ( ) )
& & RuleI ( Character , KillsPerGroupLeadershipAA ) > 0 )
{
uint32 group_id = raid - > GetGroup ( this ) ;
uint32 exp = GROUP_EXP_PER_POINT / RuleI ( Character , KillsPerGroupLeadershipAA ) ;
Client * mentoree = raid - > GetMentoree ( group_id ) ;
if ( raid - > GetMentorPercent ( group_id ) & & mentoree & &
mentoree - > GetGroupPoints ( ) < MaxBankedGroupLeadershipPoints ( mentoree - > GetLevel ( ) ) )
{
uint32 mentor_exp = exp * ( raid - > GetMentorPercent ( group_id ) / 100.0f ) ;
exp - = mentor_exp ;
mentoree - > AddLeadershipEXP ( mentor_exp , 0 ) ;
2019-08-11 00:14:02 -05:00
mentoree - > MessageString ( Chat : : LeaderShip , GAIN_GROUP_LEADERSHIP_EXP ) ;
2018-01-06 10:22:26 -05:00
}
if ( exp > 0 )
{
AddLeadershipEXP ( exp , 0 ) ;
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , GAIN_GROUP_LEADERSHIP_EXP ) ;
2018-01-06 10:22:26 -05:00
}
}
else
{
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , MAX_GROUP_LEADERSHIP_POINTS ) ;
2018-01-06 10:22:26 -05:00
}
}
}
}
}
2014-08-19 10:55:29 -05:00
2018-01-06 10:22:26 -05:00
void Client : : CalculateExp ( uint32 in_add_exp , uint32 & add_exp , uint32 & add_aaxp , uint8 conlevel , bool resexp )
{
add_exp = in_add_exp ;
2013-02-16 16:14:39 -08:00
2018-01-06 10:22:26 -05:00
if ( ! resexp & & ( XPRate ! = 0 ) )
{
2013-02-16 16:14:39 -08:00
add_exp = static_cast < uint32 > ( in_add_exp * ( static_cast < float > ( XPRate ) / 100.0f ) ) ;
2018-01-06 10:22:26 -05:00
}
2013-05-06 13:07:41 -04:00
2018-01-06 10:22:26 -05:00
// Make sure it was initialized.
add_aaxp = 0 ;
2013-05-06 13:07:41 -04:00
2018-01-06 10:22:26 -05:00
if ( ! resexp )
{
2013-02-16 16:14:39 -08:00
//figure out how much of this goes to AAs
add_aaxp = add_exp * m_epp . perAA / 100 ;
2018-01-01 14:23:24 -05:00
2015-05-25 12:35:53 -04:00
//take that amount away from regular exp
2013-02-16 16:14:39 -08:00
add_exp - = add_aaxp ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
float totalmod = 1.0 ;
float zemmod = 1.0 ;
2018-01-01 14:23:24 -05:00
2013-02-16 16:14:39 -08:00
//get modifiers
2018-01-06 10:22:26 -05:00
if ( RuleR ( Character , ExpMultiplier ) > = 0 ) {
2013-02-16 16:14:39 -08:00
totalmod * = RuleR ( Character , ExpMultiplier ) ;
}
2018-01-01 14:23:24 -05:00
//add the zone exp modifier.
2018-01-06 10:22:26 -05:00
if ( zone - > newzone_data . zone_exp_multiplier > = 0 ) {
2013-02-16 16:14:39 -08:00
zemmod * = zone - > newzone_data . zone_exp_multiplier ;
}
2018-01-06 10:22:26 -05:00
if ( RuleB ( Character , UseRaceClassExpBonuses ) )
2013-02-16 16:14:39 -08:00
{
2018-01-06 10:22:26 -05:00
if ( GetBaseRace ( ) = = HALFLING ) {
2013-02-16 16:14:39 -08:00
totalmod * = 1.05 ;
}
2018-01-06 10:22:26 -05:00
if ( GetClass ( ) = = ROGUE | | GetClass ( ) = = WARRIOR ) {
2013-02-16 16:14:39 -08:00
totalmod * = 1.05 ;
}
}
2018-01-01 14:23:24 -05:00
//add hotzone modifier if one has been set.
2018-01-06 10:22:26 -05:00
if ( zone - > IsHotzone ( ) )
2013-02-16 16:14:39 -08:00
{
totalmod + = RuleR ( Zone , HotZoneBonus ) ;
}
add_exp = uint32 ( float ( add_exp ) * totalmod * zemmod ) ;
2013-05-06 13:07:41 -04:00
2018-01-01 14:23:24 -05:00
//if XP scaling is based on the con of a monster, do that now.
2018-01-06 10:22:26 -05:00
if ( RuleB ( Character , UseXPConScaling ) )
2013-02-16 16:14:39 -08:00
{
2018-01-06 10:22:26 -05:00
if ( conlevel ! = 0xFF & & ! resexp )
{
add_exp = add_exp * GetConLevelModifierPercent ( conlevel ) ;
2013-02-16 16:14:39 -08:00
}
}
2018-01-06 10:22:26 -05:00
// Calculate any changes to leadership experience.
CalculateLeadershipExp ( add_exp , conlevel ) ;
2013-02-16 16:14:39 -08:00
} //end !resexp
2018-01-06 10:22:26 -05:00
if ( RuleB ( Zone , LevelBasedEXPMods ) ) {
if ( zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod ) {
add_exp * = zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod ;
2013-02-16 16:14:39 -08:00
}
}
2018-01-06 10:22:26 -05:00
add_exp = GetEXP ( ) + add_exp ;
}
2017-12-15 01:47:45 -05:00
2018-01-06 10:22:26 -05:00
void Client : : AddEXP ( uint32 in_add_exp , uint8 conlevel , bool resexp ) {
2013-02-16 16:14:39 -08:00
2018-01-06 10:22:26 -05:00
this - > EVENT_ITEM_ScriptStopReturn ( ) ;
uint32 exp = 0 ;
2018-01-01 14:23:24 -05:00
uint32 aaexp = 0 ;
2013-02-16 16:14:39 -08:00
2018-01-06 10:22:26 -05:00
if ( m_epp . perAA < 0 | | m_epp . perAA > 100 )
m_epp . perAA = 0 ; // stop exploit with sanity check
// Calculate regular XP
CalculateExp ( in_add_exp , exp , aaexp , conlevel , resexp ) ;
// Calculate regular AA XP
if ( ! RuleB ( AA , NormalizedAAEnabled ) )
2018-01-01 14:23:24 -05:00
{
2018-01-06 10:22:26 -05:00
CalculateStandardAAExp ( aaexp , conlevel , resexp ) ;
2018-01-01 14:23:24 -05:00
}
else
{
2018-01-06 10:22:26 -05:00
CalculateNormalizedAAExp ( aaexp , conlevel , resexp ) ;
}
// Are we also doing linear AA acceleration?
if ( RuleB ( AA , ModernAAScalingEnabled ) & & aaexp > 0 )
{
aaexp = ScaleAAXPBasedOnCurrentAATotal ( GetAAPoints ( ) , aaexp ) ;
2018-01-01 14:23:24 -05:00
}
// Get current AA XP total
2013-02-16 16:14:39 -08:00
uint32 had_aaexp = GetAAXP ( ) ;
2018-01-01 14:23:24 -05:00
// Add it to the XP we just earned.
2013-02-16 16:14:39 -08:00
aaexp + = had_aaexp ;
2018-01-01 14:23:24 -05:00
// Make sure our new total (existing + just earned) isn't lower than the
// existing total. If it is, we overflowed the bounds of uint32 and wrapped.
// Reset to the existing total.
2018-01-06 10:22:26 -05:00
if ( aaexp < had_aaexp )
{
2013-02-16 16:14:39 -08:00
aaexp = had_aaexp ; //watch for wrap
2018-01-06 10:22:26 -05:00
}
2013-05-06 13:07:41 -04:00
2018-07-21 00:01:36 -04:00
// AA Sanity Checking for players who set aa exp and deleveled below allowed aa level.
2018-07-21 16:10:55 -04:00
if ( GetLevel ( ) < = 50 & & m_epp . perAA > 0 ) {
2019-08-11 00:00:55 -05:00
Message ( Chat : : Yellow , " You are below the level allowed to gain AA Experience. AA Experience set to 0% " ) ;
2018-07-21 00:01:36 -04:00
aaexp = 0 ;
m_epp . perAA = 0 ;
}
2018-01-01 14:23:24 -05:00
// Now update our character's normal and AA xp
2013-02-16 16:14:39 -08:00
SetEXP ( exp , aaexp , resexp ) ;
}
void Client : : SetEXP ( uint32 set_exp , uint32 set_aaxp , bool isrezzexp ) {
2019-09-01 23:54:24 -05:00
LogDebug ( " Attempting to Set Exp for [{}] (XP: [{}], AAXP: [{}], Rez: [{}]) " , this - > GetCleanName ( ) , set_exp , set_aaxp , isrezzexp ? " true " : " false " ) ;
2017-06-10 15:12:31 -07:00
auto max_AAXP = GetRequiredAAExperience ( ) ;
2013-02-16 16:14:39 -08:00
if ( max_AAXP = = 0 | | GetEXPForLevel ( GetLevel ( ) ) = = 0xFFFFFFFF ) {
2019-08-11 00:00:55 -05:00
Message ( Chat : : Red , " Error in Client::SetEXP. EXP not set. " ) ;
2013-02-16 16:14:39 -08:00
return ; // Must be invalid class/race
}
2015-05-25 12:35:53 -04:00
uint32 i = 0 ;
uint32 membercount = 0 ;
if ( GetGroup ( ) )
{
for ( i = 0 ; i < MAX_GROUP_MEMBERS ; i + + ) {
if ( GetGroup ( ) - > members [ i ] ! = nullptr ) {
membercount + + ;
}
}
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( ( set_exp + set_aaxp ) > ( m_pp . exp + m_pp . expAA ) ) {
2016-09-26 02:09:39 -07:00
uint32 exp_gained = set_exp - m_pp . exp ;
uint32 aaxp_gained = set_aaxp - m_pp . expAA ;
float exp_percent = ( float ) ( ( float ) exp_gained / ( float ) ( GetEXPForLevel ( GetLevel ( ) + 1 ) - GetEXPForLevel ( GetLevel ( ) ) ) ) * ( float ) 100 ; //EXP needed for level
float aaxp_percent = ( float ) ( ( float ) aaxp_gained / ( float ) ( RuleI ( AA , ExpPerPoint ) ) ) * ( float ) 100 ; //AAEXP needed for level
std : : string exp_amount_message = " " ;
if ( RuleI ( Character , ShowExpValues ) > = 1 ) {
if ( exp_gained > 0 & & aaxp_gained > 0 ) exp_amount_message = StringFormat ( " %u, %u AA " , exp_gained , aaxp_gained ) ;
else if ( exp_gained > 0 ) exp_amount_message = StringFormat ( " %u " , exp_gained ) ;
else exp_amount_message = StringFormat ( " %u AA " , aaxp_gained ) ;
}
std : : string exp_percent_message = " " ;
if ( RuleI ( Character , ShowExpValues ) > = 2 ) {
if ( exp_gained > 0 & & aaxp_gained > 0 ) exp_percent_message = StringFormat ( " (%.3f%%, %.3f%%AA) " , exp_percent , aaxp_percent ) ;
else if ( exp_gained > 0 ) exp_percent_message = StringFormat ( " (%.3f%%) " , exp_percent ) ;
else exp_percent_message = StringFormat ( " (%.3f%%AA) " , aaxp_percent ) ;
}
if ( isrezzexp ) {
2017-06-16 23:12:54 -07:00
if ( RuleI ( Character , ShowExpValues ) > 0 )
2019-08-11 00:00:55 -05:00
Message ( Chat : : Experience , " You regain %s experience from resurrection. %s " , exp_amount_message . c_str ( ) , exp_percent_message . c_str ( ) ) ;
2019-08-11 00:14:02 -05:00
else MessageString ( Chat : : Experience , REZ_REGAIN ) ;
2016-09-26 02:09:39 -07:00
} else {
if ( membercount > 1 ) {
2017-06-16 23:12:54 -07:00
if ( RuleI ( Character , ShowExpValues ) > 0 )
2019-08-11 00:00:55 -05:00
Message ( Chat : : Experience , " You have gained %s party experience! %s " , exp_amount_message . c_str ( ) , exp_percent_message . c_str ( ) ) ;
2019-08-11 00:14:02 -05:00
else MessageString ( Chat : : Experience , GAIN_GROUPXP ) ;
2016-09-26 02:09:39 -07:00
}
else if ( IsRaidGrouped ( ) ) {
2017-06-16 23:12:54 -07:00
if ( RuleI ( Character , ShowExpValues ) > 0 )
2019-08-11 00:00:55 -05:00
Message ( Chat : : Experience , " You have gained %s raid experience! %s " , exp_amount_message . c_str ( ) , exp_percent_message . c_str ( ) ) ;
2019-08-11 00:14:02 -05:00
else MessageString ( Chat : : Experience , GAIN_RAIDEXP ) ;
2016-09-26 02:09:39 -07:00
}
else {
2017-06-16 23:12:54 -07:00
if ( RuleI ( Character , ShowExpValues ) > 0 )
2019-08-11 00:00:55 -05:00
Message ( Chat : : Experience , " You have gained %s experience! %s " , exp_amount_message . c_str ( ) , exp_percent_message . c_str ( ) ) ;
2019-08-11 00:14:02 -05:00
else MessageString ( Chat : : Experience , GAIN_XP ) ;
2016-09-26 02:09:39 -07:00
}
2013-02-16 16:14:39 -08:00
}
}
else if ( ( set_exp + set_aaxp ) < ( m_pp . exp + m_pp . expAA ) ) { //only loss message if you lose exp, no message if you gained/lost nothing.
2016-09-26 02:09:39 -07:00
uint32 exp_lost = m_pp . exp - set_exp ;
float exp_percent = ( float ) ( ( float ) exp_lost / ( float ) ( GetEXPForLevel ( GetLevel ( ) + 1 ) - GetEXPForLevel ( GetLevel ( ) ) ) ) * ( float ) 100 ;
2019-08-11 00:00:55 -05:00
if ( RuleI ( Character , ShowExpValues ) = = 1 & & exp_lost > 0 ) Message ( Chat : : Yellow , " You have lost %i experience. " , exp_lost ) ;
else if ( RuleI ( Character , ShowExpValues ) = = 2 & & exp_lost > 0 ) Message ( Chat : : Yellow , " You have lost %i experience. (%.3f%%) " , exp_lost , exp_percent ) ;
else Message ( Chat : : Yellow , " You have lost experience. " ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//check_level represents the level we should be when we have
//this ammount of exp (once these loops complete)
uint16 check_level = GetLevel ( ) + 1 ;
//see if we gained any levels
2015-05-11 16:34:46 -07:00
bool level_increase = true ;
int8 level_count = 0 ;
2013-02-16 16:14:39 -08:00
while ( set_exp > = GetEXPForLevel ( check_level ) ) {
check_level + + ;
if ( check_level > 127 ) { //hard level cap
check_level = 127 ;
break ;
}
2015-05-11 16:34:46 -07:00
level_count + + ;
2013-02-16 16:14:39 -08:00
if ( GetMercID ( ) )
UpdateMercLevel ( ) ;
}
//see if we lost any levels
while ( set_exp < GetEXPForLevel ( check_level - 1 ) ) {
check_level - - ;
if ( check_level < 2 ) { //hard level minimum
check_level = 2 ;
break ;
}
2015-05-11 16:34:46 -07:00
level_increase = false ;
2013-02-16 16:14:39 -08:00
if ( GetMercID ( ) )
UpdateMercLevel ( ) ;
}
check_level - - ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//see if we gained any AAs
if ( set_aaxp > = max_AAXP ) {
/*
Note : AA exp is stored differently than normal exp .
2013-05-06 13:07:41 -04:00
Exp points are only stored in m_pp . expAA until you
gain a full AA point , once you gain it , a point is
2013-02-16 16:14:39 -08:00
added to m_pp . aapoints and the ammount needed to gain
that point is subtracted from m_pp . expAA
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
then , once they spend an AA point , it is subtracted from
m_pp . aapoints . In theory it then goes into m_pp . aapoints_spent ,
but im not sure if we have that in the right spot .
*/
//record how many points we have
uint32 last_unspentAA = m_pp . aapoints ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//figure out how many AA points we get from the exp were setting
m_pp . aapoints = set_aaxp / max_AAXP ;
2019-09-01 23:54:24 -05:00
LogDebug ( " Calculating additional AA Points from AAXP for [{}]: [{}] / [{}] = [{}] points " , this - > GetCleanName ( ) , set_aaxp , max_AAXP , ( float ) set_aaxp / ( float ) max_AAXP ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//get remainder exp points, set in PP below
set_aaxp = set_aaxp - ( max_AAXP * m_pp . aapoints ) ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//add in how many points we had
m_pp . aapoints + = last_unspentAA ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//figure out how many points were actually gained
/*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused
2013-05-06 13:07:41 -04:00
2019-08-11 00:00:55 -05:00
//Message(Chat::Yellow, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
2013-02-16 16:14:39 -08:00
char val1 [ 20 ] = { 0 } ;
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : Experience , GAIN_ABILITY_POINT , ConvertArray ( m_pp . aapoints , val1 ) , m_pp . aapoints = = 1 ? " " : " (s) " ) ; //You have gained an ability point! You now have %1 ability point%2.
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
/* QS: PlayerLogAARate */
if ( RuleB ( QueryServ , PlayerLogAARate ) ) {
int add_points = ( m_pp . aapoints - last_unspentAA ) ;
std : : string query = StringFormat ( " INSERT INTO `qs_player_aa_rate_hourly` (char_id, aa_count, hour_time) VALUES (%i, %i, UNIX_TIMESTAMP() - MOD(UNIX_TIMESTAMP(), 3600)) ON DUPLICATE KEY UPDATE `aa_count` = `aa_count` + %i " , this - > CharacterID ( ) , add_points , add_points ) ;
QServ - > SendQuery ( query . c_str ( ) ) ;
}
2019-08-11 00:00:55 -05:00
//Message(Chat::Yellow, "You now have %d skill points available to spend.", m_pp.aapoints);
2013-02-16 16:14:39 -08:00
}
uint8 maxlevel = RuleI ( Character , MaxExpLevel ) + 1 ;
if ( maxlevel < = 1 )
maxlevel = RuleI ( Character , MaxLevel ) + 1 ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( check_level > maxlevel ) {
check_level = maxlevel ;
2013-04-24 15:58:51 -05:00
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
if ( RuleB ( Character , KeepLevelOverMax ) ) {
2013-04-24 15:58:51 -05:00
set_exp = GetEXPForLevel ( GetLevel ( ) + 1 ) ;
}
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
else {
2013-04-24 15:58:51 -05:00
set_exp = GetEXPForLevel ( maxlevel ) ;
}
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2018-12-13 21:44:52 -05:00
if ( GetClientMaxLevel ( ) > 0 ) {
int client_max_level = GetClientMaxLevel ( ) ;
if ( GetLevel ( ) > = client_max_level ) {
uint32 expneeded = GetEXPForLevel ( client_max_level ) ;
if ( set_exp > expneeded ) {
set_exp = expneeded ;
2018-12-13 19:41:19 -05:00
}
}
}
2013-02-16 16:14:39 -08:00
if ( ( GetLevel ( ) ! = check_level ) & & ! ( check_level > = maxlevel ) ) {
char val1 [ 20 ] = { 0 } ;
2015-05-11 16:34:46 -07:00
if ( level_increase )
{
if ( level_count = = 1 )
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : Experience , GAIN_LEVEL , ConvertArray ( check_level , val1 ) ) ;
2015-05-11 16:34:46 -07:00
else
2019-08-11 00:00:55 -05:00
Message ( Chat : : Yellow , " Welcome to level %i! " , check_level ) ;
2015-05-11 16:34:46 -07:00
if ( check_level = = RuleI ( Character , DeathItemLossLevel ) )
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : Yellow , CORPSE_ITEM_LOST ) ;
2015-05-11 16:34:46 -07:00
if ( check_level = = RuleI ( Character , DeathExpLossLevel ) )
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : Yellow , CORPSE_EXP_LOST ) ;
2013-02-16 16:14:39 -08:00
}
else
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : Experience , LOSE_LEVEL , ConvertArray ( check_level , val1 ) ) ;
2014-03-31 09:31:49 -04:00
# ifdef BOTS
uint8 myoldlevel = GetLevel ( ) ;
# endif
2013-02-16 16:14:39 -08:00
SetLevel ( check_level ) ;
2014-03-31 09:31:49 -04:00
# ifdef BOTS
if ( RuleB ( Bots , BotLevelsWithOwner ) )
// hack way of doing this..but, least invasive... (same criteria as gain level for sendlvlapp)
Bot : : LevelBotWithClient ( this , GetLevel ( ) , ( myoldlevel = = check_level - 1 ) ) ;
# endif
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
//If were at max level then stop gaining experience if we make it to the cap
if ( GetLevel ( ) = = maxlevel - 1 ) {
uint32 expneeded = GetEXPForLevel ( maxlevel ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
if ( set_exp > expneeded ) {
2013-05-09 10:44:08 -04:00
set_exp = expneeded ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
}
2013-02-16 16:14:39 -08:00
//set the client's EXP and AAEXP
m_pp . exp = set_exp ;
m_pp . expAA = set_aaxp ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( GetLevel ( ) < 51 ) {
m_epp . perAA = 0 ; // turn off aa exp if they drop below 51
} else
2015-06-10 22:46:57 -07:00
SendAlternateAdvancementStats ( ) ; //otherwise, send them an AA update
2013-02-16 16:14:39 -08:00
//send the expdata in any case so the xp bar isnt stuck after leveling
uint32 tmpxp1 = GetEXPForLevel ( GetLevel ( ) + 1 ) ;
uint32 tmpxp2 = GetEXPForLevel ( GetLevel ( ) ) ;
// Quag: crash bug fix... Divide by zero when tmpxp1 and 2 equalled each other, most likely the error case from GetEXPForLevel() (invalid class, etc)
if ( tmpxp1 ! = tmpxp2 & & tmpxp1 ! = 0xFFFFFFFF & & tmpxp2 ! = 0xFFFFFFFF ) {
2016-05-25 16:10:28 -04:00
auto outapp = new EQApplicationPacket ( OP_ExpUpdate , sizeof ( ExpUpdate_Struct ) ) ;
2013-02-16 16:14:39 -08:00
ExpUpdate_Struct * eu = ( ExpUpdate_Struct * ) outapp - > pBuffer ;
float tmpxp = ( float ) ( ( float ) set_exp - tmpxp2 ) / ( ( float ) tmpxp1 - tmpxp2 ) ;
eu - > exp = ( uint32 ) ( 330.0f * tmpxp ) ;
FastQueuePacket ( & outapp ) ;
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
if ( admin > = 100 & & GetGM ( ) ) {
char val1 [ 20 ] = { 0 } ;
char val2 [ 20 ] = { 0 } ;
char val3 [ 20 ] = { 0 } ;
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : Experience , GM_GAINXP , ConvertArray ( set_aaxp , val1 ) , ConvertArray ( set_exp , val2 ) , ConvertArray ( GetEXPForLevel ( GetLevel ( ) + 1 ) , val3 ) ) ; //[GM] You have gained %1 AXP and %2 EXP (%3).
2013-02-16 16:14:39 -08:00
}
}
void Client : : SetLevel ( uint8 set_level , bool command )
{
2013-05-09 10:44:08 -04:00
if ( GetEXPForLevel ( set_level ) = = 0xFFFFFFFF ) {
2019-09-01 22:05:44 -05:00
LogError ( " Client::SetLevel() GetEXPForLevel([{}]) = 0xFFFFFFFF " , set_level ) ;
2013-05-09 10:44:08 -04:00
return ;
}
2016-05-25 16:10:28 -04:00
auto outapp = new EQApplicationPacket ( OP_LevelUpdate , sizeof ( LevelUpdate_Struct ) ) ;
2013-05-09 10:44:08 -04:00
LevelUpdate_Struct * lu = ( LevelUpdate_Struct * ) outapp - > pBuffer ;
lu - > level = set_level ;
if ( m_pp . level2 ! = 0 )
lu - > level_old = m_pp . level2 ;
else
lu - > level_old = level ;
level = set_level ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
if ( IsRaidGrouped ( ) ) {
2013-05-09 10:44:08 -04:00
Raid * r = this - > GetRaid ( ) ;
if ( r ) {
r - > UpdateLevel ( GetName ( ) , set_level ) ;
}
}
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
if ( set_level > m_pp . level2 ) {
2013-05-09 10:44:08 -04:00
if ( m_pp . level2 = = 0 )
m_pp . points + = 5 ;
else
m_pp . points + = ( 5 * ( set_level - m_pp . level2 ) ) ;
m_pp . level2 = set_level ;
}
if ( set_level > m_pp . level ) {
parse - > EventPlayer ( EVENT_LEVEL_UP , this , " " , 0 ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
/* QS: PlayerLogLevels */
if ( RuleB ( QueryServ , PlayerLogLevels ) ) {
std : : string event_desc = StringFormat ( " Leveled UP :: to Level:%i from Level:%i in zoneid:%i instid:%i " , set_level , m_pp . level , this - > GetZoneID ( ) , this - > GetInstanceID ( ) ) ;
QServ - > PlayerLogEvent ( Player_Log_Levels , this - > CharacterID ( ) , event_desc ) ;
}
}
else if ( set_level < m_pp . level ) {
/* QS: PlayerLogLevels */
if ( RuleB ( QueryServ , PlayerLogLevels ) ) {
std : : string event_desc = StringFormat ( " Leveled DOWN :: to Level:%i from Level:%i in zoneid:%i instid:%i " , set_level , m_pp . level , this - > GetZoneID ( ) , this - > GetInstanceID ( ) ) ;
QServ - > PlayerLogEvent ( Player_Log_Levels , this - > CharacterID ( ) , event_desc ) ;
}
2013-05-09 10:44:08 -04:00
}
m_pp . level = set_level ;
if ( command ) {
m_pp . exp = GetEXPForLevel ( set_level ) ;
2019-08-11 00:00:55 -05:00
Message ( Chat : : Yellow , " Welcome to level %i! " , set_level ) ;
2013-05-09 10:44:08 -04:00
lu - > exp = 0 ;
}
else {
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
float tmpxp = ( float ) ( ( float ) m_pp . exp - GetEXPForLevel ( GetLevel ( ) ) ) / ( ( float ) GetEXPForLevel ( GetLevel ( ) + 1 ) - GetEXPForLevel ( GetLevel ( ) ) ) ;
2013-05-09 10:44:08 -04:00
lu - > exp = ( uint32 ) ( 330.0f * tmpxp ) ;
}
QueuePacket ( outapp ) ;
safe_delete ( outapp ) ;
this - > SendAppearancePacket ( AT_WhoLevel , set_level ) ; // who level change
2013-02-16 16:14:39 -08:00
2019-09-02 02:18:54 -05:00
LogInfo ( " Setting Level for [{}] to [{}] " , GetName ( ) , set_level ) ;
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
CalcBonuses ( ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
if ( ! RuleB ( Character , HealOnLevel ) ) {
2013-05-09 10:44:08 -04:00
int mhp = CalcMaxHP ( ) ;
if ( GetHP ( ) > mhp )
SetHP ( mhp ) ;
}
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
else {
2013-05-09 10:44:08 -04:00
SetHP ( CalcMaxHP ( ) ) ; // Why not, lets give them a free heal
}
2013-05-06 13:07:41 -04:00
2018-02-26 09:33:15 -08:00
if ( RuleI ( World , PVPMinLevel ) > 0 & & level > = RuleI ( World , PVPMinLevel ) & & m_pp . pvp = = 0 ) SetPVP ( true ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
DoTributeUpdate ( ) ;
2013-05-09 10:44:08 -04:00
SendHPUpdate ( ) ;
SetMana ( CalcMaxMana ( ) ) ;
UpdateWho ( ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
2015-01-29 23:04:41 -06:00
UpdateMercLevel ( ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
2013-05-09 10:44:08 -04:00
Save ( ) ;
2013-02-16 16:14:39 -08:00
}
// Note: The client calculates exp separately, we cant change this function
// Add: You can set the values you want now, client will be always sync :) - Merkur
uint32 Client : : GetEXPForLevel ( uint16 check_level )
{
2017-06-10 15:12:31 -07:00
# ifdef LUA_EQEMU
uint32 lua_ret = 0 ;
bool ignoreDefault = false ;
lua_ret = LuaParser : : Instance ( ) - > GetEXPForLevel ( this , check_level , ignoreDefault ) ;
if ( ignoreDefault ) {
return lua_ret ;
}
# endif
2013-02-16 16:14:39 -08:00
uint16 check_levelm1 = check_level - 1 ;
float mod ;
if ( check_level < 31 )
mod = 1.0 ;
else if ( check_level < 36 )
mod = 1.1 ;
else if ( check_level < 41 )
mod = 1.2 ;
else if ( check_level < 46 )
mod = 1.3 ;
else if ( check_level < 52 )
mod = 1.4 ;
else if ( check_level < 53 )
mod = 1.5 ;
else if ( check_level < 54 )
mod = 1.6 ;
else if ( check_level < 55 )
mod = 1.7 ;
else if ( check_level < 56 )
mod = 1.9 ;
else if ( check_level < 57 )
mod = 2.1 ;
else if ( check_level < 58 )
mod = 2.3 ;
else if ( check_level < 59 )
mod = 2.5 ;
else if ( check_level < 60 )
mod = 2.7 ;
else if ( check_level < 61 )
mod = 3.0 ;
else
mod = 3.1 ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
float base = ( check_levelm1 ) * ( check_levelm1 ) * ( check_levelm1 ) ;
mod * = 1000 ;
2013-05-06 13:07:41 -04:00
2013-06-01 10:49:58 -05:00
uint32 finalxp = uint32 ( base * mod ) ;
2015-10-14 22:57:17 -04:00
if ( RuleB ( Character , UseOldRaceExpPenalties ) )
{
float racemod = 1.0 ;
if ( GetBaseRace ( ) = = TROLL | | GetBaseRace ( ) = = IKSAR ) {
racemod = 1.2 ;
} else if ( GetBaseRace ( ) = = OGRE ) {
racemod = 1.15 ;
} else if ( GetBaseRace ( ) = = BARBARIAN ) {
racemod = 1.05 ;
} else if ( GetBaseRace ( ) = = HALFLING ) {
racemod = 0.95 ;
}
finalxp = uint32 ( finalxp * racemod ) ;
}
if ( RuleB ( Character , UseOldClassExpPenalties ) )
{
float classmod = 1.0 ;
if ( GetClass ( ) = = PALADIN | | GetClass ( ) = = SHADOWKNIGHT | | GetClass ( ) = = RANGER | | GetClass ( ) = = BARD ) {
classmod = 1.4 ;
} else if ( GetClass ( ) = = MONK ) {
classmod = 1.2 ;
} else if ( GetClass ( ) = = WIZARD | | GetClass ( ) = = ENCHANTER | | GetClass ( ) = = MAGICIAN | | GetClass ( ) = = NECROMANCER ) {
classmod = 1.1 ;
} else if ( GetClass ( ) = = ROGUE ) {
classmod = 0.91 ;
} else if ( GetClass ( ) = = WARRIOR ) {
classmod = 0.9 ;
}
finalxp = uint32 ( finalxp * classmod ) ;
}
2013-05-22 07:19:09 -05:00
finalxp = mod_client_xp_for_level ( finalxp , check_level ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
return finalxp ;
2013-02-16 16:14:39 -08:00
}
2019-10-31 23:37:05 -04:00
void Client : : AddLevelBasedExp ( uint8 exp_percentage , uint8 max_level , bool ignore_mods )
2016-09-10 14:21:19 -04:00
{
uint32 award ;
uint32 xp_for_level ;
if ( exp_percentage > 100 )
{
exp_percentage = 100 ;
}
if ( ! max_level | | GetLevel ( ) < max_level )
{
max_level = GetLevel ( ) ;
}
xp_for_level = GetEXPForLevel ( max_level + 1 ) - GetEXPForLevel ( max_level ) ;
award = xp_for_level * exp_percentage / 100 ;
2019-10-31 23:37:05 -04:00
if ( RuleB ( Zone , LevelBasedEXPMods ) & & ! ignore_mods )
2016-09-10 14:21:19 -04:00
{
if ( zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod )
{
award * = zone - > level_exp_mod [ GetLevel ( ) ] . ExpMod ;
}
}
uint32 newexp = GetEXP ( ) + award ;
2013-02-16 16:14:39 -08:00
SetEXP ( newexp , GetAAXP ( ) ) ;
}
void Group : : SplitExp ( uint32 exp , Mob * other ) {
if ( other - > CastToNPC ( ) - > MerchantType ! = 0 ) // Ensure NPC isn't a merchant
2013-05-09 10:44:08 -04:00
return ;
2013-02-16 16:14:39 -08:00
if ( other - > GetOwner ( ) & & other - > GetOwner ( ) - > IsClient ( ) ) // Ensure owner isn't pc
return ;
2013-05-06 13:07:41 -04:00
unsigned int i ;
uint32 groupexp = exp ;
uint8 membercount = 0 ;
2013-02-16 16:14:39 -08:00
uint8 maxlevel = 1 ;
2013-05-06 13:07:41 -04:00
for ( i = 0 ; i < MAX_GROUP_MEMBERS ; i + + ) {
if ( members [ i ] ! = nullptr ) {
if ( members [ i ] - > GetLevel ( ) > maxlevel )
maxlevel = members [ i ] - > GetLevel ( ) ;
2013-02-16 16:14:39 -08:00
membercount + + ;
2013-05-06 13:07:41 -04:00
}
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
float groupmod ;
2013-11-12 18:06:24 -05:00
if ( membercount > 1 & & membercount < 6 )
2013-11-12 16:08:31 -08:00
groupmod = 1 + .2 * ( membercount - 1 ) ; //2members=1.2exp, 3=1.4, 4=1.6, 5=1.8
2013-02-16 16:14:39 -08:00
else if ( membercount = = 6 )
groupmod = 2.16 ;
else
groupmod = 1.0 ;
2015-06-07 16:53:38 -07:00
if ( membercount > 1 & & membercount < = 6 )
2015-05-25 12:35:53 -04:00
groupexp + = ( uint32 ) ( ( float ) exp * groupmod * ( RuleR ( Character , GroupExpMultiplier ) ) ) ;
2013-02-16 16:14:39 -08:00
int conlevel = Mob : : GetLevelCon ( maxlevel , other - > GetLevel ( ) ) ;
2017-03-13 15:07:56 -04:00
if ( conlevel = = CON_GRAY )
2013-02-16 16:14:39 -08:00
return ; //no exp for greenies...
2013-05-06 13:07:41 -04:00
if ( membercount = = 0 )
return ;
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
for ( i = 0 ; i < MAX_GROUP_MEMBERS ; i + + ) {
2013-05-04 18:06:58 -07:00
if ( members [ i ] ! = nullptr & & members [ i ] - > IsClient ( ) ) // If Group Member is Client
2013-02-16 16:14:39 -08:00
{
Client * cmember = members [ i ] - > CastToClient ( ) ;
2013-05-06 13:07:41 -04:00
// add exp + exp cap
2013-02-16 16:14:39 -08:00
int16 diff = cmember - > GetLevel ( ) - maxlevel ;
int16 maxdiff = - ( cmember - > GetLevel ( ) * 15 / 10 - cmember - > GetLevel ( ) ) ;
if ( maxdiff > - 5 )
maxdiff = - 5 ;
2013-05-06 13:07:41 -04:00
if ( diff > = ( maxdiff ) ) { /*Instead of person who killed the mob, the person who has the highest level in the group*/
2013-02-16 16:14:39 -08:00
uint32 tmp = ( cmember - > GetLevel ( ) + 3 ) * ( cmember - > GetLevel ( ) + 3 ) * 75 * 35 / 10 ;
uint32 tmp2 = groupexp / membercount ;
2013-05-06 13:07:41 -04:00
cmember - > AddEXP ( tmp < tmp2 ? tmp : tmp2 , conlevel ) ;
}
}
2013-02-16 16:14:39 -08:00
}
}
void Raid : : SplitExp ( uint32 exp , Mob * other ) {
if ( other - > CastToNPC ( ) - > MerchantType ! = 0 ) // Ensure NPC isn't a merchant
return ;
if ( other - > GetOwner ( ) & & other - > GetOwner ( ) - > IsClient ( ) ) // Ensure owner isn't pc
return ;
2013-05-06 13:07:41 -04:00
uint32 groupexp = exp ;
uint8 membercount = 0 ;
2013-02-16 16:14:39 -08:00
uint8 maxlevel = 1 ;
2013-05-06 13:07:41 -04:00
for ( int i = 0 ; i < MAX_RAID_MEMBERS ; i + + ) {
if ( members [ i ] . member ! = nullptr ) {
if ( members [ i ] . member - > GetLevel ( ) > maxlevel )
maxlevel = members [ i ] . member - > GetLevel ( ) ;
2013-02-16 16:14:39 -08:00
2013-05-06 13:07:41 -04:00
membercount + + ;
}
2013-02-16 16:14:39 -08:00
}
groupexp = ( uint32 ) ( ( float ) groupexp * ( 1.0f - ( RuleR ( Character , RaidExpMultiplier ) ) ) ) ;
int conlevel = Mob : : GetLevelCon ( maxlevel , other - > GetLevel ( ) ) ;
2017-03-13 15:07:56 -04:00
if ( conlevel = = CON_GRAY )
2013-02-16 16:14:39 -08:00
return ; //no exp for greenies...
2013-05-06 13:07:41 -04:00
if ( membercount = = 0 )
return ;
2013-02-16 16:14:39 -08:00
2013-05-09 10:44:08 -04:00
for ( unsigned int x = 0 ; x < MAX_RAID_MEMBERS ; x + + ) {
2013-05-04 18:06:58 -07:00
if ( members [ x ] . member ! = nullptr ) // If Group Member is Client
2013-02-16 16:14:39 -08:00
{
Client * cmember = members [ x ] . member ;
2013-05-06 13:07:41 -04:00
// add exp + exp cap
2013-02-16 16:14:39 -08:00
int16 diff = cmember - > GetLevel ( ) - maxlevel ;
int16 maxdiff = - ( cmember - > GetLevel ( ) * 15 / 10 - cmember - > GetLevel ( ) ) ;
if ( maxdiff > - 5 )
maxdiff = - 5 ;
2013-05-06 13:07:41 -04:00
if ( diff > = ( maxdiff ) ) { /*Instead of person who killed the mob, the person who has the highest level in the group*/
2013-02-16 16:14:39 -08:00
uint32 tmp = ( cmember - > GetLevel ( ) + 3 ) * ( cmember - > GetLevel ( ) + 3 ) * 75 * 35 / 10 ;
uint32 tmp2 = ( groupexp / membercount ) + 1 ;
2013-05-06 13:07:41 -04:00
cmember - > AddEXP ( tmp < tmp2 ? tmp : tmp2 , conlevel ) ;
}
}
2013-02-16 16:14:39 -08:00
}
}
void Client : : SetLeadershipEXP ( uint32 group_exp , uint32 raid_exp ) {
while ( group_exp > = GROUP_EXP_PER_POINT ) {
group_exp - = GROUP_EXP_PER_POINT ;
m_pp . group_leadership_points + + ;
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , GAIN_GROUP_LEADERSHIP_POINT ) ;
2013-02-16 16:14:39 -08:00
}
while ( raid_exp > = RAID_EXP_PER_POINT ) {
raid_exp - = RAID_EXP_PER_POINT ;
m_pp . raid_leadership_points + + ;
2019-08-11 00:14:02 -05:00
MessageString ( Chat : : LeaderShip , GAIN_RAID_LEADERSHIP_POINT ) ;
2013-02-16 16:14:39 -08:00
}
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
m_pp . group_leadership_exp = group_exp ;
m_pp . raid_leadership_exp = raid_exp ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
SendLeadershipEXPUpdate ( ) ;
}
void Client : : AddLeadershipEXP ( uint32 group_exp , uint32 raid_exp ) {
SetLeadershipEXP ( GetGroupEXP ( ) + group_exp , GetRaidEXP ( ) + raid_exp ) ;
}
void Client : : SendLeadershipEXPUpdate ( ) {
2016-05-25 16:10:28 -04:00
auto outapp = new EQApplicationPacket ( OP_LeadershipExpUpdate , sizeof ( LeadershipExpUpdate_Struct ) ) ;
2013-02-16 16:14:39 -08:00
LeadershipExpUpdate_Struct * eu = ( LeadershipExpUpdate_Struct * ) outapp - > pBuffer ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
eu - > group_leadership_exp = m_pp . group_leadership_exp ;
eu - > group_leadership_points = m_pp . group_leadership_points ;
eu - > raid_leadership_exp = m_pp . raid_leadership_exp ;
eu - > raid_leadership_points = m_pp . raid_leadership_points ;
2013-05-06 13:07:41 -04:00
2013-02-16 16:14:39 -08:00
FastQueuePacket ( & outapp ) ;
}
uint32 Client : : GetCharMaxLevelFromQGlobal ( ) {
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
QGlobalCache * char_c = nullptr ;
char_c = this - > GetQGlobals ( ) ;
2013-02-16 16:14:39 -08:00
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
std : : list < QGlobal > globalMap ;
uint32 ntype = 0 ;
2013-02-16 16:14:39 -08:00
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
if ( char_c ) {
QGlobalCache : : Combine ( globalMap , char_c - > GetBucket ( ) , ntype , this - > CharacterID ( ) , zone - > GetZoneID ( ) ) ;
}
2013-02-16 16:14:39 -08:00
2016-05-25 16:10:28 -04:00
auto iter = globalMap . begin ( ) ;
Changed zone process window title format, example: 'crushbone :: clients: 6 inst_id: 1 inst_ver: 0 :: port: 7015'
Most of the following changes are QueryServ related, fully implemented its original functionality to be able to offload
intensive or metric based logging to a remote server process that could exist on another server entirely
Implemented Player Event Logging Types (Go to table `qs_player_events`):
1 = Player_Log_Quest,
2 = Player_Log_Zoning,
3 = Player_Log_Deaths,
4 = Player_Log_Connect_State,
5 = Player_Log_Levels,
6 = Player_Log_Keyring_Addition,
7 = Player_Log_QGlobal_Update,
8 = Player_Log_Task_Updates,
9 = Player_Log_AA_Purchases,
10 = Player_Log_Trade_Skill_Events,
11 = Player_Log_Issued_Commands,
12 = Player_Log_Money_Transactions,
13 = Player_Log_Alternate_Currency_Transactions,
- All QueryServ logging will be implemented with a front end in EoC 2.0 very soon
Changed all QS Error related logging to 'QUERYSERV__ERROR'
(Natedog) (Crash Fix) Legacy MySQL bug revert for loading AA's COALESCE( from COALESCE (
Implemented Perl Quest objects (LUA still needed to be exported):
- quest::qs_send_query("MySQL query") - Will send a raw query to the QueryServ process, useful for custom logging
- quest::qs_player_event(char_id, event_desc); - Will process a quest type event to table `qs_player_events`
Added MySQL Tables:
- `qs_player_aa_rate_hourly`
- `qs_player_events`
- Source table structures from:
- utils\sql\git\queryserv\required\08_23_2014_player_events_and_player_aa_rate_hourly
To get the complete QueryServ schema, source from here:
- utils\sql\git\queryserv\required\Complete_QueryServ_Table_Structures.sql
Added rules for each logging type, source rules here with them enabled by default:
- utils\sql\git\queryserv\required\Complete_QueryServ_Rules_Enabled.sql
Spawn related logging cleanup
General code cleanup
Added queryserv.cpp and queryserv.h with QueryServ class
2014-08-23 23:59:20 -05:00
uint32 gcount = 0 ;
while ( iter ! = globalMap . end ( ) ) {
if ( ( * iter ) . name . compare ( " CharMaxLevel " ) = = 0 ) {
return atoi ( ( * iter ) . value . c_str ( ) ) ;
}
+ + iter ;
+ + gcount ;
}
2013-02-16 16:14:39 -08:00
2018-12-13 21:44:52 -05:00
return 0 ;
2013-04-24 15:58:51 -05:00
}
2017-06-10 15:12:31 -07:00
2019-09-01 22:05:44 -05:00
uint32 Client : : GetCharMaxLevelFromBucket ( )
{
uint32 char_id = this - > CharacterID ( ) ;
std : : string query = StringFormat ( " SELECT value FROM data_buckets WHERE `key` = '%i-CharMaxLevel' " , char_id ) ;
auto results = database . QueryDatabase ( query ) ;
2018-12-13 19:41:19 -05:00
if ( ! results . Success ( ) ) {
2019-09-01 22:05:44 -05:00
LogError ( " Data bucket for CharMaxLevel for char ID [{}] failed " , char_id ) ;
return 0 ;
}
2018-12-13 19:41:19 -05:00
if ( results . RowCount ( ) > 0 ) {
auto row = results . begin ( ) ;
return atoi ( row [ 0 ] ) ;
}
2018-12-13 21:44:52 -05:00
return 0 ;
2018-12-13 19:41:19 -05:00
}
2017-06-10 15:12:31 -07:00
uint32 Client : : GetRequiredAAExperience ( ) {
# ifdef LUA_EQEMU
uint32 lua_ret = 0 ;
bool ignoreDefault = false ;
lua_ret = LuaParser : : Instance ( ) - > GetRequiredAAExperience ( this , ignoreDefault ) ;
if ( ignoreDefault ) {
return lua_ret ;
}
# endif
return RuleI ( AA , ExpPerPoint ) ;
}