int Client::GroupLeadershipAAHealthRegeneration() { if (IsRaidGrouped()) { int bonus = 0; Raid *raid = GetRaid(); if (!raid) return 0; uint32 group_id = raid->GetGroup(this); if (group_id < 12 && raid->GroupCount(group_id) >= 3) { switch (raid->GetLeadershipAA(groupAAHealthRegeneration, group_id)) { case 1: bonus = 4; break; case 2: bonus = 6; break; case 3: bonus = 8; break; } } if (raid->RaidCount() >= 18) { switch (raid->GetLeadershipAA(raidAAHealthRegeneration)) { case 1: bonus += 4; break; case 2: bonus += 6; break; case 3: bonus += 8; break; } } return bonus; } Group *g = GetGroup(); if(!g || (g->GroupCount() < 3)) return 0; switch(g->GetLeadershipAA(groupAAHealthRegeneration)) { case 0: return 0; case 1: return 4; case 2: return 6; case 3: return 8; } return 0; }
int Client::GroupLeadershipAAManaEnhancement() { if (IsRaidGrouped()) { int bonus = 0; Raid *raid = GetRaid(); if (!raid) return 0; uint32 group_id = raid->GetGroup(this); if (group_id < 12 && raid->GroupCount(group_id) >= 3) { switch (raid->GetLeadershipAA(groupAAManaEnhancement, group_id)) { case 1: bonus = 30; break; case 2: bonus = 60; break; case 3: bonus = 100; break; } } if (raid->RaidCount() >= 18) { switch (raid->GetLeadershipAA(raidAAManaEnhancement)) { case 1: bonus += 30; break; case 2: bonus += 60; break; case 3: bonus += 100; break; } } return bonus; } Group *g = GetGroup(); if(!g || (g->GroupCount() < 3)) return 0; switch(g->GetLeadershipAA(groupAAManaEnhancement)) { case 0: return 0; case 1: return 30; case 2: return 60; case 3: return 100; } return 0; }
bool Aura::ShouldISpawnFor(Client *c) { if (spawn_type == AuraSpawns::Noone) return false; if (spawn_type == AuraSpawns::Everyone) return true; // hey, it's our owner! if (c->GetID() == m_owner) return true; // so this one is a bit trickier auto owner = GetOwner(); if (owner == nullptr) return false; // hmm owner = owner->GetOwnerOrSelf(); // pet auras we need the pet's owner if (owner == nullptr) // shouldn't really be needed return false; // gotta check again for pet aura case -.- if (owner == c) return true; if (owner->IsRaidGrouped() && owner->IsClient()) { auto raid = owner->GetRaid(); if (raid == nullptr) return false; // hmm auto group_id = raid->GetGroup(owner->CastToClient()); if (group_id == 0xFFFFFFFF) // owner handled above, and they're in a raid and groupless return false; auto idx = raid->GetPlayerIndex(c); if (idx == 0xFFFFFFFF) // they're not in our raid! return false; if (raid->members[idx].GroupNumber != group_id) // in our raid, but not our group return false; return true; // we got here so we know that 1 they're in our raid and 2 they're in our group! } else if (owner->IsGrouped()) { auto group = owner->GetGroup(); if (group == nullptr) return false; // hmm // easy, in our group return group->IsGroupMember(c); } // our owner is not raided or grouped, and they're handled above so we don't spawn! return false; }
void Client::SetLevel(uint8 set_level, bool command) { if (GetEXPForLevel(set_level) == 0xFFFFFFFF) { LogFile->write(EQEMuLog::Error,"Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level); return; } EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); 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; if(IsRaidGrouped()) { Raid *r = this->GetRaid(); if(r){ r->UpdateLevel(GetName(), set_level); } } if(set_level > m_pp.level2) { 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); } m_pp.level = set_level; if (command){ m_pp.exp = GetEXPForLevel(set_level); Message(15, "Welcome to level %i!", set_level); lu->exp = 0; } else { float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel())); lu->exp = (uint32)(330.0f * tmpxp); } QueuePacket(outapp); safe_delete(outapp); this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change LogFile->write(EQEMuLog::Normal,"Setting Level for %s to %i", GetName(), set_level); CalcBonuses(); if(!RuleB(Character, HealOnLevel)) { int mhp = CalcMaxHP(); if(GetHP() > mhp) SetHP(mhp); } else { SetHP(CalcMaxHP()); // Why not, lets give them a free heal } DoTributeUpdate(); SendHPUpdate(); SetMana(CalcMaxMana()); UpdateWho(); if(GetMerc()) UpdateMercLevel(); Save(); }
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::SetLevel(uint8 set_level, bool command) { if (GetEXPForLevel(set_level) == 0xFFFFFFFF) { Log.Out(Logs::General, Logs::Error, "Client::SetLevel() GetEXPForLevel(%i) = 0xFFFFFFFF", set_level); return; } EQApplicationPacket* outapp = new EQApplicationPacket(OP_LevelUpdate, sizeof(LevelUpdate_Struct)); 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; if(IsRaidGrouped()) { Raid *r = this->GetRaid(); if(r){ r->UpdateLevel(GetName(), set_level); } } if(set_level > m_pp.level2) { 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); /* 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); } } m_pp.level = set_level; if (command){ m_pp.exp = GetEXPForLevel(set_level); Message(CC_Yellow, "Welcome to level %i!", set_level); lu->exp = 0; } else { float tmpxp = (float) ( (float) m_pp.exp - GetEXPForLevel( GetLevel() )) / ( (float) GetEXPForLevel(GetLevel()+1) - GetEXPForLevel(GetLevel())); lu->exp = (uint32)(330.0f * tmpxp); } QueuePacket(outapp); safe_delete(outapp); this->SendAppearancePacket(AT_WhoLevel, set_level); // who level change Log.Out(Logs::General, Logs::Normal, "Setting Level for %s to %i", GetName(), set_level); CalcBonuses(); if(!RuleB(Character, HealOnLevel)) { int mhp = CalcMaxHP(); if(GetHP() > mhp) SetHP(mhp); } else { SetHP(CalcMaxHP()); // Why not, lets give them a free heal } if(!RuleB(Character, ManaOnLevel)) { int mp = CalcMaxMana(); if(GetMana() > mp) SetMana(mp); } else { SetMana(CalcMaxMana()); // Why not, lets give them a free heal } SendHPUpdate(); SendManaUpdate(); UpdateWho(); Save(); }
void Aura::ProcessOnGroupMembersPets(Mob *owner) { auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline std::set<int> delayed_remove; bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter // This type can either live on the pet (level 55/70 MAG aura) or on the pet owner (level 85 MAG aura) auto group_member = owner->GetOwnerOrSelf(); if (group_member->IsRaidGrouped() && group_member->IsClient()) { // currently raids are just client, but safety check auto raid = group_member->GetRaid(); if (raid == nullptr) { // well shit owner->RemoveAura(GetID(), false, true); return; } auto group_id = raid->GetGroup(group_member->CastToClient()); // some lambdas so the for loop is less horrible ... auto verify_raid_client_pet = [&raid, &group_id, &group_member, this](Mob *m) { auto idx = raid->GetPlayerIndex(m->GetOwner()->CastToClient()); if (m->GetOwner()->GetID() == group_member->GetID()) { return DistanceSquared(GetPosition(), m->GetPosition()) <= distance; } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { return false; } else if (DistanceSquared(GetPosition(), m->GetPosition()) > distance) { return false; } return true; }; auto verify_raid_client_swarm = [&raid, &group_id, &group_member, this](NPC *n) { auto owner = entity_list.GetMob(n->GetSwarmOwner()); if (owner == nullptr) return false; auto idx = raid->GetPlayerIndex(owner->CastToClient()); if (owner->GetID() == group_member->GetID()) { return DistanceSquared(GetPosition(), n->GetPosition()) <= distance; } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { return false; } else if (DistanceSquared(GetPosition(), n->GetPosition()) > distance) { return false; } return true; }; for (auto &e : mob_list) { auto mob = e.second; // step 1: check if we're already managing this NPC's buff auto it = casted_on.find(mob->GetID()); if (it != casted_on.end()) { // verify still good! if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner()) { if (!verify_raid_client_pet(mob)) delayed_remove.insert(mob->GetID()); } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { auto npc = mob->CastToNPC(); if (!verify_raid_client_swarm(npc)) delayed_remove.insert(mob->GetID()); } } else { // we're not on it! if (mob->IsClient()) { continue; // never hit client } else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner() && verify_raid_client_pet(mob)) { casted_on.insert(mob->GetID()); if (is_buff) SpellFinished(spell_id, mob); } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { auto npc = mob->CastToNPC(); if (verify_raid_client_swarm(npc)) { casted_on.insert(mob->GetID()); if (is_buff) SpellFinished(spell_id, mob); } } } } } else if (group_member->IsGrouped()) { auto group = group_member->GetGroup(); if (group == nullptr) { // uh oh owner->RemoveAura(GetID(), false, true); return; } // lambdas to make for loop less ugly auto verify_group_pet = [&group, this](Mob *m) { auto owner = m->GetOwner(); if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), m->GetPosition()) <= distance) return true; return false; }; auto verify_group_swarm = [&group, this](NPC *n) { auto owner = entity_list.GetMob(n->GetSwarmOwner()); if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), n->GetPosition()) <= distance) return true; return false; }; for (auto &e : mob_list) { auto mob = e.second; auto it = casted_on.find(mob->GetID()); if (it != casted_on.end()) { // make sure we're still valid if (mob->IsPet()) { if (!verify_group_pet(mob)) delayed_remove.insert(mob->GetID()); } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo()) { if (!verify_group_swarm(mob->CastToNPC())) delayed_remove.insert(mob->GetID()); } } else { // not on, check if we should be! if (mob->IsClient()) { continue; } else if (mob->IsPet() && verify_group_pet(mob)) { casted_on.insert(mob->GetID()); if (is_buff) SpellFinished(spell_id, mob); } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo() && verify_group_swarm(mob->CastToNPC())) { casted_on.insert(mob->GetID()); if (is_buff) SpellFinished(spell_id, mob); } } } } else { auto verify_solo = [&group_member, this](Mob *m) { if (m->IsPet() && m->GetOwnerID() == group_member->GetID()) return true; else if (m->IsNPC() && m->CastToNPC()->GetSwarmOwner() == group_member->GetID()) return true; else return false; }; for (auto &e : mob_list) { auto mob = e.second; auto it = casted_on.find(mob->GetID()); bool good = verify_solo(mob); if (it != casted_on.end()) { // make sure still valid if (!good || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) { delayed_remove.insert(mob->GetID()); } } else if (good && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { casted_on.insert(mob->GetID()); if (is_buff) SpellFinished(spell_id, mob); } } } for (auto &e : delayed_remove) { auto mob = entity_list.GetMob(e); if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove mob->BuffFadeBySpellIDAndCaster(spell_id, GetID()); casted_on.erase(e); } // so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty()) cast_timer.Start(); if (!cast_timer.Enabled() || !cast_timer.Check()) return; // some auras have to recast (DRU for example, non-buff too) for (auto &e : casted_on) { auto mob = entity_list.GetMob(e); if (mob != nullptr) SpellFinished(spell_id, mob); } }
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); } }