void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { _log(CLIENT__EXP, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false"); //max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2() if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) { Message(13, "Error in Client::SetEXP. EXP not set."); return; // Must be invalid class/race } if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) { if (isrezzexp) this->Message_StringID(MT_Experience, REZ_REGAIN); else{ if(this->IsGrouped()) this->Message_StringID(MT_Experience, GAIN_GROUPXP); else if(IsRaidGrouped()) Message_StringID(MT_Experience, GAIN_RAIDEXP); else this->Message_StringID(MT_Experience, GAIN_XP); } } 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. Message(15, "You have lost experience."); } //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 while (set_exp >= GetEXPForLevel(check_level)) { check_level++; if (check_level > 127) { //hard level cap check_level = 127; break; } 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; } if(GetMercID()) UpdateMercLevel(); } check_level--; //see if we gained any AAs if (set_aaxp >= max_AAXP) { /* Note: AA exp is stored differently than normal exp. Exp points are only stored in m_pp.expAA until you gain a full AA point, once you gain it, a point is added to m_pp.aapoints and the ammount needed to gain that point is subtracted from m_pp.expAA 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; //figure out how many AA points we get from the exp were setting m_pp.aapoints = set_aaxp / max_AAXP; _log(CLIENT__EXP, "Calculating additional AA Points from AAXP for %s: %u / %u = %.1f points", this->GetCleanName(), set_aaxp, max_AAXP, (float)set_aaxp / (float)max_AAXP); //get remainder exp points, set in PP below set_aaxp = set_aaxp - (max_AAXP * m_pp.aapoints); //add in how many points we had m_pp.aapoints += last_unspentAA; //set_aaxp = m_pp.expAA % max_AAXP; //figure out how many points were actually gained /*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused //Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA); char val1[20]={0}; Message_StringID(MT_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. //Message(15, "You now have %d skill points available to spend.", m_pp.aapoints); } uint8 maxlevel = RuleI(Character, MaxExpLevel) + 1; if(maxlevel <= 1) maxlevel = RuleI(Character, MaxLevel) + 1; if(check_level > maxlevel) { check_level = maxlevel; //DCBOOKMARK if(RuleB(Character, KeepLevelOverMax)) { set_exp = GetEXPForLevel(GetLevel()+1); } else { set_exp = GetEXPForLevel(maxlevel); } } if(RuleB(Character, PerCharacterQglobalMaxLevel)){ uint32 MaxLevel = GetCharMaxLevelFromQGlobal(); if(MaxLevel){ if(GetLevel() >= MaxLevel){ uint32 expneeded = GetEXPForLevel(MaxLevel); if(set_exp > expneeded) { set_exp = expneeded; } } } } if ((GetLevel() != check_level) && !(check_level >= maxlevel)) { char val1[20]={0}; if (GetLevel() == check_level-1){ Message_StringID(MT_Experience, GAIN_LEVEL,ConvertArray(check_level,val1)); SendLevelAppearance(); //Message(15, "You have gained a level! Welcome to level %i!", check_level); } if (GetLevel() == check_level){ Message_StringID(MT_Experience, LOSE_LEVEL,ConvertArray(check_level,val1)); //Message(15, "You lost a level! You are now level %i!", check_level); } else Message(15, "Welcome to level %i!", check_level); SetLevel(check_level); } //If were at max level then stop gaining experience if we make it to the cap if(GetLevel() == maxlevel - 1){ uint32 expneeded = GetEXPForLevel(maxlevel); if(set_exp > expneeded) { set_exp = expneeded; } } //set the client's EXP and AAEXP m_pp.exp = set_exp; m_pp.expAA = set_aaxp; if (GetLevel() < 51) { m_epp.perAA = 0; // turn off aa exp if they drop below 51 } else SendAAStats(); //otherwise, send them an AA update //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) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct)); 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); } if (admin>=100 && GetGM()) { char val1[20]={0}; char val2[20]={0}; char val3[20]={0}; Message_StringID(MT_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). //Message(15, "[GM] You now have %d / %d EXP and %d / %d AA exp.", set_exp, GetEXPForLevel(GetLevel()+1), set_aaxp, max_AAXP); } }
void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { Log.Out(Logs::Detail, Logs::None, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false"); //max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2() if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) { Message(13, "Error in Client::SetEXP. EXP not set."); return; // Must be invalid class/race } if ((set_exp + set_aaxp) > (m_pp.exp+m_pp.expAA)) { if (isrezzexp) this->Message_StringID(MT_Experience, REZ_REGAIN); else{ if(this->IsGrouped()) this->Message_StringID(MT_Experience, GAIN_GROUPXP); else if(IsRaidGrouped()) Message_StringID(MT_Experience, GAIN_RAIDEXP); else this->Message_StringID(MT_Experience, GAIN_XP); } } 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. Message(15, "You have lost experience."); } //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 bool level_increase = true; int8 level_count = 0; while (set_exp >= GetEXPForLevel(check_level)) { check_level++; if (check_level > 127) { //hard level cap check_level = 127; break; } level_count++; 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; } level_increase = false; if(GetMercID()) UpdateMercLevel(); } check_level--; //see if we gained any AAs if (set_aaxp >= max_AAXP) { /* Note: AA exp is stored differently than normal exp. Exp points are only stored in m_pp.expAA until you gain a full AA point, once you gain it, a point is added to m_pp.aapoints and the ammount needed to gain that point is subtracted from m_pp.expAA 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; //figure out how many AA points we get from the exp were setting m_pp.aapoints = set_aaxp / max_AAXP; Log.Out(Logs::Detail, Logs::None, "Calculating additional AA Points from AAXP for %s: %u / %u = %.1f points", this->GetCleanName(), set_aaxp, max_AAXP, (float)set_aaxp / (float)max_AAXP); //get remainder exp points, set in PP below set_aaxp = set_aaxp - (max_AAXP * m_pp.aapoints); //add in how many points we had m_pp.aapoints += last_unspentAA; //set_aaxp = m_pp.expAA % max_AAXP; //figure out how many points were actually gained /*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused //Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA); char val1[20]={0}; Message_StringID(MT_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. /* 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()); } //Message(15, "You now have %d skill points available to spend.", m_pp.aapoints); } uint8 maxlevel = RuleI(Character, MaxExpLevel) + 1; if(maxlevel <= 1) maxlevel = RuleI(Character, MaxLevel) + 1; if(check_level > maxlevel) { check_level = maxlevel; if(RuleB(Character, KeepLevelOverMax)) { set_exp = GetEXPForLevel(GetLevel()+1); } else { set_exp = GetEXPForLevel(maxlevel); } } if(RuleB(Character, PerCharacterQglobalMaxLevel)){ uint32 MaxLevel = GetCharMaxLevelFromQGlobal(); if(MaxLevel){ if(GetLevel() >= MaxLevel){ uint32 expneeded = GetEXPForLevel(MaxLevel); if(set_exp > expneeded) { set_exp = expneeded; } } } } if ((GetLevel() != check_level) && !(check_level >= maxlevel)) { char val1[20]={0}; if (level_increase) { if (level_count == 1) Message_StringID(MT_Experience, GAIN_LEVEL, ConvertArray(check_level, val1)); else Message(15, "Welcome to level %i!", check_level); if (check_level == RuleI(Character, DeathItemLossLevel)) Message_StringID(15, CORPSE_ITEM_LOST); if (check_level == RuleI(Character, DeathExpLossLevel)) Message_StringID(15, CORPSE_EXP_LOST); } else Message_StringID(MT_Experience, LOSE_LEVEL, ConvertArray(check_level, val1)); #ifdef BOTS uint8 myoldlevel = GetLevel(); #endif SetLevel(check_level); #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 } //If were at max level then stop gaining experience if we make it to the cap if(GetLevel() == maxlevel - 1){ uint32 expneeded = GetEXPForLevel(maxlevel); if(set_exp > expneeded) { set_exp = expneeded; } } //set the client's EXP and AAEXP m_pp.exp = set_exp; m_pp.expAA = set_aaxp; if (GetLevel() < 51) { m_epp.perAA = 0; // turn off aa exp if they drop below 51 } else SendAAStats(); //otherwise, send them an AA update //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) { EQApplicationPacket* outapp = new EQApplicationPacket(OP_ExpUpdate, sizeof(ExpUpdate_Struct)); 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); } if (admin>=100 && GetGM()) { char val1[20]={0}; char val2[20]={0}; char val3[20]={0}; Message_StringID(MT_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). //Message(15, "[GM] You now have %d / %d EXP and %d / %d AA exp.", set_exp, GetEXPForLevel(GetLevel()+1), set_aaxp, max_AAXP); } }