void Commands::forceRaid(Player& player, const std::string& param) { Raid* raid = Raids::getInstance()->getRaidByName(param); if (!raid || !raid->isLoaded()) { player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "No such raid exists."); return; } if (Raids::getInstance()->getRunning()) { player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Another raid is already being executed."); return; } Raids::getInstance()->setRunning(raid); RaidEvent* event = raid->getNextRaidEvent(); if (!event) { player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "The raid does not contain any data."); return; } raid->setState(RAIDSTATE_EXECUTING); uint32_t ticks = event->getDelay(); if (ticks > 0) { g_scheduler.addEvent(createSchedulerTask(ticks, std::bind(&Raid::executeRaidEvent, raid, event))); } else { g_dispatcher.addTask(createTask(std::bind(&Raid::executeRaidEvent, raid, event))); } player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Raid started."); }
bool Raids::loadFromXml() { if (isLoaded()) { return true; } pugi::xml_document doc; pugi::xml_parse_result result = doc.load_file("data/raids/raids.xml"); if (!result) { std::cout << "[Error - Raids::loadFromXml] Failed to load data/raids/raids.xml: " << result.description() << std::endl; return false; } for (pugi::xml_node raidNode = doc.child("raids").first_child(); raidNode; raidNode = raidNode.next_sibling()) { std::string name, file; uint32_t interval, margin; pugi::xml_attribute attr; if ((attr = raidNode.attribute("name"))) { name = attr.as_string(); } else { std::cout << "[Error - Raids::loadFromXml] Name tag missing for raid" << std::endl; continue; } if ((attr = raidNode.attribute("file"))) { file = attr.as_string(); } else { std::ostringstream ss; ss << "raids/" << name << ".xml"; file = ss.str(); std::cout << "[Warning - Raids::loadFromXml] File tag missing for raid " << name << ". Using default: " << file << std::endl; } interval = pugi::cast<uint32_t>(raidNode.attribute("interval2").value()) * 60; if (interval == 0) { std::cout << "[Error - Raids::loadFromXml] interval2 tag missing or zero (would divide by 0) for raid: " << name << std::endl; continue; } if ((attr = raidNode.attribute("margin"))) { margin = pugi::cast<uint32_t>(attr.value()) * 60 * 1000; } else { std::cout << "[Warning - Raids::loadFromXml] margin tag missing for raid: " << name << std::endl; margin = 0; } Raid* newRaid = new Raid(name, interval, margin); if (newRaid->loadFromXml("data/raids/" + file)) { raidList.push_back(newRaid); } else { std::cout << "[Error - Raids::loadFromXml] Failed to load raid: " << name << std::endl; delete newRaid; } } loaded = true; return true; }
Mob* HateList::GetDamageTop(Mob* hater) { _ZP(HateList_GetDamageTop); Mob* current = NULL; Group* grp = NULL; Raid* r = NULL; uint32 dmg_amt = 0; LinkedListIterator<tHateEntry*> iterator(list); iterator.Reset(); while(iterator.MoreElements()) { grp = NULL; r = NULL; if(iterator.GetData()->ent && iterator.GetData()->ent->IsClient()){ r = entity_list.GetRaidByClient(iterator.GetData()->ent->CastToClient()); } grp = entity_list.GetGroupByMob(iterator.GetData()->ent); if(iterator.GetData()->ent && r){ if(r->GetTotalRaidDamage(hater) >= dmg_amt) { current = iterator.GetData()->ent; dmg_amt = r->GetTotalRaidDamage(hater); } } else if (iterator.GetData()->ent != NULL && grp != NULL) { if (grp->GetTotalGroupDamage(hater) >= dmg_amt) { current = iterator.GetData()->ent; dmg_amt = grp->GetTotalGroupDamage(hater); } } else if (iterator.GetData()->ent != NULL && (uint32)iterator.GetData()->damage >= dmg_amt) { current = iterator.GetData()->ent; dmg_amt = iterator.GetData()->damage; } iterator.Advance(); } return current; }
Mob* HateList::GetDamageTop(Mob* hater) { Mob* current = nullptr; Group* grp = nullptr; Raid* r = nullptr; uint32 dmg_amt = 0; auto iterator = list.begin(); while(iterator != list.end()) { grp = nullptr; r = nullptr; if((*iterator)->ent && (*iterator)->ent->IsClient()){ r = entity_list.GetRaidByClient((*iterator)->ent->CastToClient()); } grp = entity_list.GetGroupByMob((*iterator)->ent); if((*iterator)->ent && r){ if(r->GetTotalRaidDamage(hater) >= dmg_amt) { current = (*iterator)->ent; dmg_amt = r->GetTotalRaidDamage(hater); } } else if ((*iterator)->ent != nullptr && grp != nullptr) { if (grp->GetTotalGroupDamage(hater) >= dmg_amt) { current = (*iterator)->ent; dmg_amt = grp->GetTotalGroupDamage(hater); } } else if ((*iterator)->ent != nullptr && (uint32)(*iterator)->damage >= dmg_amt) { current = (*iterator)->ent; dmg_amt = (*iterator)->damage; } ++iterator; } return current; }
bool Commands::forceRaid(Creature* creature, const std::string& cmd, const std::string& param) { Player* player = creature->getPlayer(); if(!player){ return false; } Raid* raid = Raids::getInstance()->getRaidByName(param); if(!raid || !raid->isLoaded()){ player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, "No such raid exists."); return false; } if(Raids::getInstance()->getRunning()){ player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, "Another raid is already being executed."); return false; } Raids::getInstance()->setRunning(raid); RaidEvent* event = raid->getNextRaidEvent(); if(!event){ player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, "The raid does not contain any data."); return false; } raid->setState(RAIDSTATE_EXECUTING); uint32_t ticks = event->getDelay(); if(ticks > 0){ Scheduler::getScheduler().addEvent(createSchedulerTask(ticks, boost::bind(&Raid::executeRaidEvent, raid, event))); } else{ Dispatcher::getDispatcher().addTask(createTask( boost::bind(&Raid::executeRaidEvent, raid, event))); } player->sendTextMessage(MSG_STATUS_CONSOLE_BLUE, "Raid started."); return true; }
void Raids::checkRaids() { if (!getRunning()) { uint64_t now = OTSYS_TIME(); for (auto it = raidList.begin(); it != raidList.end(); ++it) { Raid* raid = *it; if (now >= (getLastRaidEnd() + raid->getMargin())) { if (MAX_RAND_RANGE * CHECK_RAIDS_INTERVAL / raid->getInterval() >= static_cast<uint32_t>(uniform_random(0, MAX_RAND_RANGE))) { setRunning(raid); raid->startRaid(); if (!raid->canBeRepeated()) { raidList.erase(it); } break; } } } } checkRaidsEvent = g_scheduler.addEvent(createSchedulerTask(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this))); }
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; }
void Corpse::LootItem(Client* client, const EQApplicationPacket* app) { /* This gets sent no matter what as a sort of ACK */ client->QueuePacket(app); if (!loot_cooldown_timer.Check()) { SendEndLootErrorPacket(client); //unlock corpse for others if (this->being_looted_by = client->GetID()) { being_looted_by = 0xFFFFFFFF; } return; } /* To prevent item loss for a player using 'Loot All' who doesn't have inventory space for all their items. */ if (RuleB(Character, CheckCursorEmptyWhenLooting) && !client->GetInv().CursorEmpty()) { client->Message(13, "You may not loot an item while you have an item on your cursor."); SendEndLootErrorPacket(client); /* Unlock corpse for others */ if (this->being_looted_by = client->GetID()) { being_looted_by = 0xFFFFFFFF; } return; } LootingItem_Struct* lootitem = (LootingItem_Struct*)app->pBuffer; if (this->being_looted_by != client->GetID()) { client->Message(13, "Error: Corpse::LootItem: BeingLootedBy != client"); SendEndLootErrorPacket(client); return; } if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && (char_id != client->CharacterID() && client->Admin() < 150)) { client->Message(13, "Error: This is a player corpse and you dont own it."); SendEndLootErrorPacket(client); return; } if (is_locked && client->Admin() < 100) { SendLootReqErrorPacket(client, 0); client->Message(13, "Error: Corpse locked by GM."); return; } if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && GetPlayerKillItem() == 0){ client->Message(13, "Error: You cannot loot any more items from this corpse."); SendEndLootErrorPacket(client); being_looted_by = 0xFFFFFFFF; return; } const Item_Struct* item = 0; ItemInst *inst = 0; ServerLootItem_Struct* item_data = nullptr, *bag_item_data[10]; memset(bag_item_data, 0, sizeof(bag_item_data)); if (GetPlayerKillItem() > 1){ item = database.GetItem(GetPlayerKillItem()); } else if (GetPlayerKillItem() == -1 || GetPlayerKillItem() == 1){ item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN); //dont allow them to loot entire bags of items as pvp reward } else{ item_data = GetItem(lootitem->slot_id - EmuConstants::CORPSE_BEGIN, bag_item_data); } if (GetPlayerKillItem()<=1 && item_data != 0) { item = database.GetItem(item_data->item_id); } if (item != 0) { if (item_data){ inst = database.CreateItem(item, item_data ? item_data->charges : 0, item_data->aug_1, item_data->aug_2, item_data->aug_3, item_data->aug_4, item_data->aug_5, item_data->aug_6, item_data->attuned); } else { inst = database.CreateItem(item); } } if (client && inst) { if (client->CheckLoreConflict(item)) { client->Message_StringID(0, LOOT_LORE_ERROR); SendEndLootErrorPacket(client); being_looted_by = 0; delete inst; return; } if (inst->IsAugmented()) { for (int i = AUG_BEGIN; i < EmuConstants::ITEM_COMMON_SIZE; i++) { ItemInst *itm = inst->GetAugment(i); if (itm) { if (client->CheckLoreConflict(itm->GetItem())) { client->Message_StringID(0, LOOT_LORE_ERROR); SendEndLootErrorPacket(client); being_looted_by = 0; delete inst; return; } } } } char buf[88]; char corpse_name[64]; strcpy(corpse_name, corpse_name); snprintf(buf, 87, "%d %d %s", inst->GetItem()->ID, inst->GetCharges(), EntityList::RemoveNumbers(corpse_name)); buf[87] = '\0'; std::vector<EQEmu::Any> args; args.push_back(inst); args.push_back(this); parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args); parse->EventItem(EVENT_LOOT, client, inst, this, buf, 0); if (!IsPlayerCorpse() && RuleB(Character, EnableDiscoveredItems)) { if (client && !client->GetGM() && !client->IsDiscovered(inst->GetItem()->ID)) client->DiscoverItem(inst->GetItem()->ID); } if (zone->adv_data) { ServerZoneAdventureDataReply_Struct *ad = (ServerZoneAdventureDataReply_Struct*)zone->adv_data; if (ad->type == Adventure_Collect && !IsPlayerCorpse()) { if (ad->data_id == inst->GetItem()->ID) { zone->DoAdventureCountIncrease(); } } } /* First add it to the looter - this will do the bag contents too */ if (lootitem->auto_loot) { if (!client->AutoPutLootInInventory(*inst, true, true, bag_item_data)) client->PutLootInInventory(MainCursor, *inst, bag_item_data); } else { client->PutLootInInventory(MainCursor, *inst, bag_item_data); } /* Update any tasks that have an activity to loot this item */ if (RuleB(TaskSystem, EnableTaskSystem)) client->UpdateTasksForItem(ActivityLoot, item->ID); /* Remove it from Corpse */ if (item_data){ /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, item_data->equip_slot, item_data->item_id); /* Delete Item Instance */ RemoveItem(item_data->lootslot); } /* Remove Bag Contents */ if (item->ItemClass == ItemClassContainer && (GetPlayerKillItem() != -1 || GetPlayerKillItem() != 1)) { for (int i = SUB_BEGIN; i < EmuConstants::ITEM_CONTAINER_SIZE; i++) { if (bag_item_data[i]) { /* Delete needs to be before RemoveItem because its deletes the pointer for item_data/bag_item_data */ database.DeleteItemOffCharacterCorpse(this->corpse_db_id, bag_item_data[i]->equip_slot, bag_item_data[i]->item_id); /* Delete Item Instance */ RemoveItem(bag_item_data[i]); } } } if (GetPlayerKillItem() != -1) { SetPlayerKillItemID(0); } /* Send message with item link to groups and such */ Client::TextLink linker; linker.SetLinkType(linker.linkItemInst); linker.SetItemInst(inst); auto item_link = linker.GenerateLink(); client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, item_link.c_str()); if (!IsPlayerCorpse()) { Group *g = client->GetGroup(); if(g != nullptr) { g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); } else { Raid *r = client->GetRaid(); if(r != nullptr) { r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, client->GetName(), item_link.c_str()); } } } } else { SendEndLootErrorPacket(client); safe_delete(inst); return; } if (IsPlayerCorpse()){ client->SendItemLink(inst); } else{ client->SendItemLink(inst, true); } safe_delete(inst); }
bool Raids::loadFromXml() { if(isLoaded()) return true; xmlDocPtr doc = xmlParseFile("data/raids/raids.xml"); if(doc) { xmlNodePtr root, raidNode; root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"raids") != 0) { std::cout << "[Error] Raids: Wrong root node." << std::endl; xmlFreeDoc(doc); return false; } int intValue; std::string strValue; raidNode = root->children; while(raidNode) { if(xmlStrcmp(raidNode->name, (const xmlChar*)"raid") == 0) { std::string name, file; uint32_t interval, margin; if(readXMLString(raidNode, "name", strValue)) name = strValue; else { std::cout << "[Error] Raids: name tag missing for raid." << std::endl; raidNode = raidNode->next; continue; } if(readXMLString(raidNode, "file", strValue)) file = strValue; else { std::ostringstream ss; ss << "raids/" << name << ".xml"; file = ss.str(); std::cout << "[Warning] Raids: file tag missing for raid " << name << ". Using default: " << file << std::endl; } //interval2 is the average interval between // 2 executions of the raid in minutes if(readXMLInteger(raidNode, "interval2", intValue) && intValue > 0) interval = intValue * 60; else { std::cout << "[Error] Raids: interval2 tag missing or divided by 0 for raid " << name << std::endl; raidNode = raidNode->next; continue; } if(readXMLInteger(raidNode, "margin", intValue)) margin = intValue * 60 * 1000; else { std::cout << "[Warning] Raids: margin tag missing for raid " << name << std::endl; margin = 0; } Raid* newRaid = new Raid(name, interval, margin); if(!newRaid) { xmlFreeDoc(doc); return false; } bool ret = newRaid->loadFromXml("data/raids/" + file); if(!ret) { std::cout << "[Error] Raids: failed to load raid " << name << std::endl; delete newRaid; } else raidList.push_back(newRaid); } raidNode = raidNode->next; } xmlFreeDoc(doc); } else { std::cout << "[Error] Raids: Could not load data/raids/raids.xml" << std::endl; return false; } loaded = true; return true; }
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(); }
bool Raids::parseRaidNode(xmlNodePtr raidNode, bool checkDuplicate, FileType_t pathing) { if(xmlStrcmp(raidNode->name, (const xmlChar*)"raid")) return false; int32_t intValue; std::string strValue; if(!readXMLString(raidNode, "name", strValue)) { std::clog << "[Error - Raids::parseRaidNode] name tag missing for raid." << std::endl; return false; } std::string name = strValue; if(!readXMLInteger(raidNode, "interval2", intValue) || intValue <= 0) { std::clog << "[Error - Raids::parseRaidNode] interval2 tag missing or divided by 0 for raid " << name << std::endl; return false; } uint32_t interval = intValue * 60; std::string file; if(!readXMLString(raidNode, "file", strValue)) { file = name + ".xml"; std::clog << "[Warning - Raids::parseRaidNode] file tag missing for raid " << name << ", using default: " << file << std::endl; } else file = strValue; file = getFilePath(pathing, "raids/" + file); uint64_t margin = 0; if(!readXMLInteger(raidNode, "margin", intValue)) std::clog << "[Warning - Raids::parseRaidNode] margin tag missing for raid " << name << ", using default: " << margin << std::endl; else margin = intValue * 60 * 1000; RefType_t refType = REF_NONE; if(readXMLString(raidNode, "reftype", strValue) || readXMLString(raidNode, "refType", strValue)) { std::string tmpStrValue = asLowerCaseString(strValue); if(tmpStrValue == "single") refType = REF_SINGLE; else if(tmpStrValue == "block") refType = REF_BLOCK; else if(tmpStrValue != "none") std::clog << "[Warning - Raids::parseRaidNode] Unknown reftype \"" << strValue << "\" for raid " << name << std::endl; } bool ref = false; if(readXMLString(raidNode, "ref", strValue)) ref = booleanString(strValue); bool enabled = true; if(readXMLString(raidNode, "enabled", strValue)) enabled = booleanString(strValue); Raid* raid = new Raid(name, interval, margin, refType, ref, enabled); if(!raid || !raid->loadFromXml(file)) { delete raid; std::clog << "[Fatal - Raids::parseRaidNode] failed to load raid " << name << std::endl; return false; } if(checkDuplicate) { for(RaidList::iterator it = raidList.begin(); it != raidList.end(); ++it) { if((*it)->getName() == name) delete *it; } } raidList.push_back(raid); return true; }
bool Raids::loadFromXml(const std::string& _filename) { if(isLoaded()){ return true; } filename = _filename; xmlDocPtr doc = xmlParseFile(filename.c_str()); if(doc){ xmlNodePtr root, raidNode; root = xmlDocGetRootElement(doc); if(xmlStrcmp(root->name,(const xmlChar*)"raids") != 0){ std::cout << "[Error] Raids: Wrong root node." << std::endl; xmlFreeDoc(doc); return false; } int intValue; std::string strValue; raidNode = root->children; while(raidNode){ if(xmlStrcmp(raidNode->name, (const xmlChar*)"raid") == 0){ std::string name, file; uint32_t interval, margin; if(readXMLString(raidNode, "name", strValue)){ name = strValue; } else{ std::cout << "[Error] Raids: name tag missing for raid." << std::endl; raidNode = raidNode->next; continue; } if(readXMLString(raidNode, "file", strValue)){ file = strValue; } else{ std::stringstream ss; ss << "raids/" << name << ".xml"; file = ss.str(); std::cout << "[Warning] Raids: file tag missing for raid " << name << ". Using default: " << file << std::endl; } //interval2 is the average interval between // 2 executions of the raid in minutes if(readXMLInteger(raidNode, "interval2", intValue)){ interval = intValue * 60; //transform to seconds } else{ std::cout << "[Error] Raids: interval2 tag missing for raid " << name << std::endl; raidNode = raidNode->next; continue; } if(readXMLInteger(raidNode, "margin", intValue)){ margin = intValue * 60 * 1000; //transform to milliseconds } else{ std::cout << "[Warning] Raids: margin tag missing for raid " << name << std::endl; margin = 0; } Raid* newRaid = new Raid(name, interval, margin); if(!newRaid){ xmlFreeDoc(doc); return false; } bool ret = newRaid->loadFromXml(g_config.getString(ConfigManager::DATA_DIRECTORY) + "raids/" + file); if(!ret){ std::cout << "[Error] Raids: failed to load raid " << name << std::endl; delete newRaid; } else{ raidList.push_back(newRaid); } } raidNode = raidNode->next; } xmlFreeDoc(doc); } else{ std::cout << "[Error] Raids: Could not load " << filename << std::endl; return false; } loaded = true; return true; }
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 Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { this->EVENT_ITEM_ScriptStopReturn(); uint32 add_exp = in_add_exp; if(!resexp && (XPRate != 0)) add_exp = static_cast<uint32>(in_add_exp * (static_cast<float>(XPRate) / 100.0f)); if (m_epp.perAA<0 || m_epp.perAA>100) m_epp.perAA=0; // stop exploit with sanity check uint32 add_aaxp; if(resexp) { add_aaxp = 0; } else { //figure out how much of this goes to AAs add_aaxp = add_exp * m_epp.perAA / 100; //take that ammount away from regular exp add_exp -= add_aaxp; 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); } add_exp = uint32(float(add_exp) * totalmod * zemmod); if(RuleB(Character,UseXPConScaling)) { if (conlevel != 0xFF && !resexp) { switch (conlevel) { case CON_GREEN: add_exp = 0; add_aaxp = 0; return; case CON_LIGHTBLUE: add_exp = add_exp * RuleI(Character, LightBlueModifier)/100; add_aaxp = add_aaxp * RuleI(Character, LightBlueModifier)/100; break; case CON_BLUE: add_exp = add_exp * RuleI(Character, BlueModifier)/100; add_aaxp = add_aaxp * RuleI(Character, BlueModifier)/100; break; case CON_WHITE: add_exp = add_exp * RuleI(Character, WhiteModifier)/100; add_aaxp = add_aaxp * RuleI(Character, WhiteModifier)/100; break; case CON_YELLOW: add_exp = add_exp * RuleI(Character, YellowModifier)/100; add_aaxp = add_aaxp * RuleI(Character, YellowModifier)/100; break; case CON_RED: add_exp = add_exp * RuleI(Character, RedModifier)/100; add_aaxp = add_aaxp * RuleI(Character, RedModifier)/100; break; } } } 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 mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); } 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 Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); } } else { Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); } } 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)); Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP); } else { Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS); } } 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); mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); } if (exp > 0) { AddLeadershipEXP(exp, 0); Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); } } else { Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); } } } } } //end !resexp 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){ add_exp *= zone->level_exp_mod[GetLevel()].ExpMod; add_aaxp *= zone->level_exp_mod[GetLevel()].AAExpMod; } } uint32 exp = GetEXP() + add_exp; uint32 aaexp = (uint32)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod); uint32 had_aaexp = GetAAXP(); aaexp += had_aaexp; if(aaexp < had_aaexp) aaexp = had_aaexp; //watch for wrap SetEXP(exp, aaexp, resexp); }