void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recv_data*/) { DEBUG_LOG("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); ObjectGuid guid = player->GetLootGuid(); if (!guid) return; Loot* pLoot = NULL; Item* pItem = NULL; switch (guid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && (pGameObject->GetOwnerGuid() == _player->GetObjectGuid() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = _player->GetMap()->GetCorpse(guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { pItem = GetPlayer()->GetItemByGuid(guid); if (!pItem || !pItem->HasGeneratedLoot()) return; pLoot = &pItem->loot; break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (!guid.IsItem() && player->GetGroup()) // item can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) playersNear.push_back(playerGroup); } if (playersNear.size() == 0) { sLog.outError("WorldSession::HandleLootMoneyOpcode %s try aquire group loot without any group member! Cheat attempt assumed.", player->GetObjectGuid().GetString().c_str()); return; } uint64 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); if (Guild* guild = sGuildMgr.GetGuildById((*i)->GetGuildId())) if (uint32 guildGold = (*i)->GetTotalAuraModifier(SPELL_AURA_MOD_MONEY_TO_GUILD_BANK) / 100.0f * money_per_player) guild->HandleCashFlow(guildGold, *i); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4+1); data << uint32(money_per_player); data << uint8(playersNear.size() > 1 ? 0 : 1);// 0 is "you share of loot..." (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(pLoot->gold); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); if (Guild* guild = sGuildMgr.GetGuildById(player->GetGuildId())) if (uint32 guildGold = player->GetTotalAuraModifier(SPELL_AURA_MOD_MONEY_TO_GUILD_BANK) / 100.0f * pLoot->gold) guild->HandleCashFlow(guildGold, player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4+1); data << uint32(pLoot->gold); data << uint8(1); // 1 is "you loot..." player->GetSession()->SendPacket(&data); } pLoot->gold = 0; if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); } }
void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* loot = NULL; bool shareMoney = true; switch(GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); // do not check distance for GO if player is the owner of it (ex. fishing bobber) if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player, INTERACTION_DISTANCE)))) loot = &go->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*player, guid); if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = player->GetItemByGuid(guid)) { loot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* creature = player->GetMap()->GetCreature(guid); bool lootAllowed = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &creature->loot; if (creature->isAlive()) shareMoney = false; } break; } default: return; // unlootable type } if (loot) { if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->getSource(); if (!member) continue; if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false)) playersNear.push_back(member); } uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(goldPerPlayer); data << uint8(0); // Controls the text displayed 0 is "Your share is...", 1 "You loot..." (*i)->GetSession()->SendPacket(&data); (*i)->ModifyMoney(goldPerPlayer); (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); } } else { WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(loot->gold); data << uint8(1); SendPacket(&data); player->ModifyMoney(loot->gold); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); } loot->gold = 0; loot->NotifyMoneyRemoved(); } }
void WorldSession::DoLootRelease(ObjectGuid lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(ObjectGuid::Empty); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (lguid.IsGameObject()) { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= go->GetGOValue()->FishingHole.MaxOpens) go->SetLootState(GO_JUST_DEACTIVATED); else go->SetLootState(GO_READY); } else go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED, player); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) loot->roundRobinPlayer.Clear(); } } else if (lguid.IsCorpse()) // ONLY remove insignia at BG { Corpse* corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (lguid.IsItem()) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else { // Only delete item if no loot or money (unlooted loot is saved to db) or if it isn't an openable item if (pItem->loot.isLooted() || !(proto->Flags & ITEM_PROTO_FLAG_OPENABLE)) player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } return; // item can be looted only single player } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING); if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &creature->loot; if (loot->isLooted()) { creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!creature->IsAlive()) creature->AllLootRemovedFromCorpse(); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { loot->roundRobinPlayer.Clear(); if (Group* group = player->GetGroup()) { group->SendLooter(creature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. creature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/) { TC_LOG_DEBUG("network", "WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* loot = NULL; bool shareMoney = true; switch (GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid); // do not check distance for GO if player is the owner of it (ex. fishing bobber) if (go && ((go->GetOwnerGUID() == player->GetGUID() || go->IsWithinDistInMap(player, INTERACTION_DISTANCE)))) loot = &go->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*player, guid); if (bones && bones->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = player->GetItemByGuid(guid)) { loot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* creature = player->GetMap()->GetCreature(guid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING); if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE)) { loot = &creature->loot; if (creature->IsAlive()) shareMoney = false; } else player->SendLootError(guid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL); break; } default: return; // unlootable type } if (loot) { loot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; if (player->IsWithinDistInMap(member, sWorld->getFloatConfig(CONFIG_GROUP_XP_DISTANCE), false)) playersNear.push_back(member); } uint32 goldPerPlayer = uint32((loot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(goldPerPlayer); (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(goldPerPlayer); data << uint8(playersNear.size() <= 1); // Controls the text displayed in chat. 0 is "Your share is..." and 1 is "You loot..." (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(loot->gold); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4 + 1); data << uint32(loot->gold); data << uint8(1); // "You loot..." SendPacket(&data); } #ifdef ELUNA sEluna->OnLootMoney(player, loot->gold); #endif loot->gold = 0; // Delete the money loot record from the DB if (loot->containerID > 0) loot->DeleteLootMoneyFromContainerItemDB(); // Delete container if empty if (loot->isLooted() && IS_ITEM_GUID(guid)) player->GetSession()->DoLootRelease(guid); } }
void WorldSession::DoLootRelease(uint64 lguid) { Player *player = GetPlayer(); Loot *loot; player->SetLootGUID(0); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld->getRate(RATE_MINING_AMOUNT); float min_amount = go_min*amount_rate; float max_amount = go_max*amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld->getRate(RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate, 4*(1/double(max_amount))*double(uses)); if (roll_chance_f((float)(100*chance+skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned in next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else { // not fully looted object go->SetLootState(GO_ACTIVATED); // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* pGroup = player->GetGroup()) { if (pGroup->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; } } else loot->roundRobinPlayer = 0; } } } else if (IS_CORPSE_GUID(lguid)) // ONLY remove insignia at BG { Corpse *corpse = ObjectAccessor::GetCorpse(*player, lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) return; ItemTemplate const* proto = pItem->GetTemplate(); // destroy only 5 items from stack in case prospecting and milling if (proto->Flags & (ITEM_PROTO_FLAG_PROSPECTABLE | ITEM_PROTO_FLAG_MILLABLE)) { pItem->m_lootGenerated = false; pItem->loot.clear(); uint32 count = pItem->GetCount(); // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. if (count > 5) count = 5; player->DestroyItemCount(pItem, count, true); } else // FIXME: item must not be deleted in case not fully looted state. But this pre-request implement loot saving in DB at item save. Or cheating possible. player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); return; // item can be looted only single player } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; if (loot->isLooted()) { // skip pickpocketing loot for speed, skinning timer reduction is no-op in fact if (!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); pCreature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); loot->clear(); } else { // if the round robin player release, reset it. if (player->GetGUID() == loot->roundRobinPlayer) { if (Group* pGroup = player->GetGroup()) { if (pGroup->GetLootMethod() != MASTER_LOOT) { loot->roundRobinPlayer = 0; pGroup->SendLooter(pCreature, NULL); // force update of dynamic flags, otherwise other group's players still not able to loot. pCreature->ForceValuesUpdateAtIndex(UNIT_DYNAMIC_FLAGS); } } else loot->roundRobinPlayer = 0; } } } //Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetGUID()); }
bool ArenaTeam::AddMember(const uint64& PlayerGuid) { std::string plName; uint8 plClass; // arena team is full (can't have more than type * 2 players!) if (GetMembersSize() >= GetType() * 2) return false; Player *pl = objmgr.GetPlayer(PlayerGuid); if (pl) { if (pl->GetArenaTeamId(GetSlot())) { sLog.outError("Arena::AddMember() : player already in this sized team"); return false; } plClass = pl->getClass(); plName = pl->GetName(); } else { // 0 1 QueryResult_AutoPtr result = CharacterDatabase.PQuery("SELECT name, class FROM characters WHERE guid='%u'", GUID_LOPART(PlayerGuid)); if (!result) return false; plName = (*result)[0].GetCppString(); plClass = (*result)[1].GetUInt8(); // check if player already in arenateam of that size if (Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0) { sLog.outError("Arena::AddMember() : player already in this sized team"); return false; } } // remove all player signs from another petitions // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(PlayerGuid, GetType()); ArenaTeamMember newmember; newmember.name = plName; newmember.guid = PlayerGuid; newmember.Class = plClass; newmember.games_season = 0; newmember.games_week = 0; newmember.wins_season = 0; newmember.wins_week = 0; newmember.personal_rating = ARENA_NEW_PERSONAL_RATING; m_members.push_back(newmember); CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", m_TeamId, GUID_LOPART(newmember.guid), newmember.personal_rating); if (pl) { pl->SetInArenaTeam(m_TeamId, GetSlot()); pl->SetArenaTeamIdInvited(0); pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating); // hide promote/remove buttons if (m_CaptainGuid != PlayerGuid) pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1); sLog.outArena("Player: %s [GUID: %u] joined arena team type: %u [Id: %u].", pl->GetName(), pl->GetGUIDLow(), GetType(), GetId()); } return true; }
bool ArenaTeam::AddMember(ObjectGuid playerGuid) { std::string plName; uint8 plClass; // arena team is full (can't have more than type * 2 players!) if (GetMembersSize() >= GetMaxMembersSize()) return false; Player* pl = sObjectMgr.GetPlayer(playerGuid); if (pl) { if (pl->GetArenaTeamId(GetSlot())) { sLog.outError("Arena::AddMember() : player already in this sized team"); return false; } plClass = pl->getClass(); plName = pl->GetName(); } else { // 0 1 QueryResult* result = CharacterDatabase.PQuery("SELECT name, class FROM characters WHERE guid='%u'", playerGuid.GetCounter()); if (!result) return false; plName = (*result)[0].GetCppString(); plClass = (*result)[1].GetUInt8(); delete result; // check if player already in arenateam of that size if (Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0) { sLog.outError("Arena::AddMember() : player %s already in this sized team", playerGuid.GetString().c_str()); return false; } } // remove all player signs from another petitions // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(playerGuid, GetType()); ArenaTeamMember newmember; newmember.name = plName; newmember.guid = playerGuid; newmember.Class = plClass; newmember.games_season = 0; newmember.games_week = 0; newmember.wins_season = 0; newmember.wins_week = 0; int32 conf_value = sWorld.getConfig(CONFIG_INT32_ARENA_STARTPERSONALRATING); if (conf_value < 0) // -1 = select by season id { if (sWorld.getConfig(CONFIG_UINT32_ARENA_SEASON_ID) >= 6) { if (m_stats.rating < 1000) newmember.personal_rating = 0; else newmember.personal_rating = 1000; } else { newmember.personal_rating = 1500; } } else newmember.personal_rating = uint32(conf_value); m_members.push_back(newmember); CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", m_TeamId, newmember.guid.GetCounter(), newmember.personal_rating); if (pl) { pl->SetInArenaTeam(m_TeamId, GetSlot(), GetType()); pl->SetArenaTeamIdInvited(0); pl->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_PERSONAL_RATING, newmember.personal_rating); // hide promote/remove buttons if (m_CaptainGuid != playerGuid) pl->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1); } return true; }
void WorldSession::HandleLootMoneyOpcode(WorldPacket & /*recv_data*/) { sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); Player *player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot *pLoot = NULL; switch(GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject *pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && ((pGameObject->GetOwnerGUID() == _player->GetGUID() || pGameObject->IsWithinDistInMap(_player,INTERACTION_DISTANCE)))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse *bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); if (bones && bones->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { if (Item *item = GetPlayer()->GetItemByGuid(guid)) pLoot = &item->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { if (!IS_ITEM_GUID(guid) && player->GetGroup()) //item can be looted only single player { Group *group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup,sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE),false)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold)/(playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); (*i)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, money_per_player); //Offset surely incorrect, but works WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else { player->ModifyMoney(pLoot->gold); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, pLoot->gold); } pLoot->gold = 0; pLoot->NotifyMoneyRemoved(); } }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) { sLog.outDebug("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player *player = GetPlayer(); uint64 lguid = player->GetLootGUID(); Loot *loot; uint8 lootSlot; recv_data >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player,INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; } else if (IS_CORPSE_GUID(lguid)) { Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player,INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; } QuestItem *qitem = NULL; QuestItem *ffaitem = NULL; QuestItem *conditem = NULL; LootItem *item = loot->LootItemInSlot(lootSlot,player,&qitem,&ffaitem,&conditem); if (!item) { player->SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL); return; } // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) { player->SendLootRelease(lguid); return; } ItemPosCountVec dest; uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count); if (msg == EQUIP_ERR_OK) { Item * newitem = player->StoreNewItem(dest, item->itemid, true, item->randomPropertyId); if (qitem) { qitem->is_looted = true; //freeforall is 1 if everyone's supposed to get the quest item. if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) player->SendNotifyLootItemRemoved(lootSlot); else loot->NotifyQuestItemRemoved(qitem->index); } else { if (ffaitem) { //freeforall case, notify only one player of the removal ffaitem->is_looted=true; player->SendNotifyLootItemRemoved(lootSlot); } else { //not freeforall, notify everyone if (conditem) conditem->is_looted=true; loot->NotifyItemRemoved(lootSlot); } } //if only one person is supposed to loot the item, then set it to looted if (!item->freeforall) item->is_looted = true; --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count); player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count); } else player->SendEquipError(msg, NULL, NULL); }
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 10); std::string name; uint8 race, class_; recv_data >> name >> race >> class_; recv_data.rpos(0); if(!sWorld.VerifyName(name.c_str(), name.length())) { OutPacket(SMSG_CHAR_CREATE, 1, "\x32"); return; } if(g_characterNameFilter->Parse(name, false)) { OutPacket(SMSG_CHAR_CREATE, 1, "\x32"); return; } //reserved for console whisper if(name == "Console" || name == "console") { OutPacket(SMSG_CHAR_CREATE, 1, "\x32"); return; } if(objmgr.GetPlayerInfoByName(name.c_str()) != 0) { OutPacket(SMSG_CHAR_CREATE, 1, "\x32"); return; } if(!sHookInterface.OnNewCharacter(race, class_, this, name.c_str())) { OutPacket(SMSG_CHAR_CREATE, 1, "\x32"); return; } if( class_ == DEATHKNIGHT && (!HasFlag(ACCOUNT_FLAG_XPACK_02) || !CanCreateDeathKnight() ) ) { OutPacket(SMSG_CHAR_CREATE, 1, "\x3B"); return; } QueryResult * result = CharacterDatabase.Query("SELECT COUNT(*) FROM banned_names WHERE name = '%s'", CharacterDatabase.EscapeString(name).c_str()); if(result) { if(result->Fetch()[0].GetUInt32() > 0) { // That name is banned! OutPacket(SMSG_CHAR_CREATE, 1, "\x51"); // You cannot use that name delete result; return; } delete result; } // loading characters //checking number of chars is useless since client will not allow to create more than 10 chars //as the 'create' button will not appear (unless we want to decrease maximum number of characters) Player* pNewChar = objmgr.CreatePlayer(); pNewChar->SetSession(this); if(!pNewChar->Create( recv_data )) { // failed. pNewChar->ok_to_remove = true; pNewChar->Destructor(); return; } //Same Faction limitation only applies to PVP and RPPVP realms, after 3.1.0 the Blizzard is disable this function, so actually we are disable this. /*uint32 realmType = sLogonCommHandler.GetRealmType(); if(!HasGMPermissions() && (realmType == REALMTYPE_PVP || realmType == REALMTYPE_RPPVP) && _side >= 0) { if( ((pNewChar->GetTeam() == 0) && (_side == 1)) || ((pNewChar->GetTeam() == 1) && (_side == 0)) ) { pNewChar->ok_to_remove = true; pNewChar->Destructor(); WorldPacket data(1); data.SetOpcode(SMSG_CHAR_CREATE); data << (uint8)ALL_CHARS_ON_PVP_REALM_MUST_AT_SAME_SIDE+1; SendPacket( &data ); return; } }*/ pNewChar->UnSetBanned(); pNewChar->addSpell(22027); // Remove Insignia if(pNewChar->getClass() == WARLOCK) { pNewChar->AddSummonSpell(416, 3110); // imp fireball pNewChar->AddSummonSpell(417, 19505); pNewChar->AddSummonSpell(1860, 3716); pNewChar->AddSummonSpell(1863, 7814); } pNewChar->SaveToDB(true); PlayerInfo *pn=new PlayerInfo; memset(pn, 0, sizeof(PlayerInfo)); pn->guid = pNewChar->GetLowGUID(); pn->name = strdup(pNewChar->GetName()); pn->cl = pNewChar->getClass(); pn->race = pNewChar->getRace(); pn->gender = pNewChar->getGender(); pn->lastLevel = pNewChar->getLevel(); pn->lastZone = pNewChar->GetZoneId(); pn->lastOnline = UNIXTIME; pn->team = pNewChar->GetTeam(); pn->acct = GetAccountId(); #ifdef VOICE_CHAT pn->groupVoiceId = -1; #endif objmgr.AddPlayerInfo(pn); pNewChar->ok_to_remove = true; pNewChar->Destructor(); // CHAR_CREATE_SUCCESS OutPacket(SMSG_CHAR_CREATE, 1, "\x2F"); sLogonCommHandler.UpdateAccountCount(GetAccountId(), 1); m_lastEnumTime = 0; }
bool Guild::AddMember(ObjectGuid plGuid, uint32 plRank) { Player* pl = sObjectMgr.GetPlayer(plGuid); if (pl) { if (pl->GetGuildId() != 0) { return false; } } else { if (Player::GetGuildIdFromDB(plGuid) != 0) // player already in guild { return false; } } // remove all player signs from another petitions // this will be prevent attempt joining player to many guilds and corrupt guild data integrity Player::RemovePetitionsAndSigns(plGuid); uint32 lowguid = plGuid.GetCounter(); // fill player data MemberSlot newmember; newmember.guid = plGuid; if (pl) { newmember.accountId = pl->GetSession()->GetAccountId(); newmember.Name = pl->GetName(); newmember.Level = pl->getLevel(); newmember.Class = pl->getClass(); newmember.ZoneId = pl->GetZoneId(); } else { // 0 1 2 3 4 QueryResult* result = CharacterDatabase.PQuery("SELECT name,level,class,zone,account FROM characters WHERE guid = '%u'", lowguid); if (!result) { return false; } // player doesn't exist Field* fields = result->Fetch(); newmember.Name = fields[0].GetCppString(); newmember.Level = fields[1].GetUInt8(); newmember.Class = fields[2].GetUInt8(); newmember.ZoneId = fields[3].GetUInt32(); newmember.accountId = fields[4].GetInt32(); delete result; if (newmember.Level < 1 || newmember.Level > STRONG_MAX_LEVEL || !((1 << (newmember.Class - 1)) & CLASSMASK_ALL_PLAYABLE)) { sLog.outError("%s has a broken data in field `characters` table, can not add him to guild.", plGuid.GetString().c_str()); return false; } } newmember.RankId = plRank; newmember.OFFnote = (std::string)""; newmember.Pnote = (std::string)""; newmember.LogoutTime = time(NULL); members[lowguid] = newmember; std::string dbPnote = newmember.Pnote; std::string dbOFFnote = newmember.OFFnote; CharacterDatabase.escape_string(dbPnote); CharacterDatabase.escape_string(dbOFFnote); CharacterDatabase.PExecute("INSERT INTO guild_member (guildid,guid,rank,pnote,offnote) VALUES ('%u', '%u', '%u','%s','%s')", m_Id, lowguid, newmember.RankId, dbPnote.c_str(), dbOFFnote.c_str()); // If player not in game data in data field will be loaded from guild tables, no need to update it!! if (pl) { pl->SetInGuild(m_Id); pl->SetRank(newmember.RankId); pl->SetGuildIdInvited(0); } UpdateAccountsNumber(); // Used by Eluna #ifdef ENABLE_ELUNA sEluna->OnAddMember(this, pl, newmember.RankId); #endif /* ENABLE_ELUNA */ return true; }
bool ChatHandler::HandleFlyMountCommand(char* /*args*/) { Player *chr = m_session->GetPlayer(); // Zakaz: if( chr->isInCombat() // - Pocas combatu || chr->GetMap()->Instanceable() // - V instancii || !chr->CanFreeMove() ) // - Ak sa nemoze volne pohybovat (sap, taxi ...) { SendSysMessage(LANG_YOU_IN_COMBAT); SetSentErrorMessage(true); return false; } // smrt if(chr->isDead()) { SendSysMessage("You are dead!"); SetSentErrorMessage(true); return false; } // zakaz pre low lvl if(chr->getLevel() != 70) { SendSysMessage("Required 70 level!"); SetSentErrorMessage(true); return false; } switch(chr->GetAreaId()) { //case 1637: // orgrimmar //case 1519: // stormwind //case 3487: // silvermoon case 168: // Tirisfal glades sea case 1256: // Azshara sea case 4080: // ioqd SendSysMessage("Not allowed here!"); SetSentErrorMessage(true); return false; } // cely ioqd a Diremaul if(chr->GetZoneId() == 4080 || chr->GetZoneId() == 2557) { SendSysMessage("Not allowed here!"); SetSentErrorMessage(true); return false; } // ine mapy ako azeroth if(chr->GetMapId() != 0 && chr->GetMapId() != 1 && chr->GetMapId() != 530) { SendSysMessage("Not allowed here!"); SetSentErrorMessage(true); return false; } // dismount chr->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); Item * firstpositem = chr->GetItemByPos(INVENTORY_SLOT_BAG_0, 23); if(firstpositem && ( firstpositem->GetProto()->RequiredSkill == 762 && firstpositem->GetProto()->RequiredSkillRank > 150 || // 762 = riding skill firstpositem->GetProto()->ItemId == 34060 || // Flying Machine Control firstpositem->GetProto()->ItemId == 34061 )) // Turbo-Charged Flying Machine Control chr->CastSpell(chr, firstpositem->GetProto()->Spells[0].SpellId, false); else if(chr->getClass() == CLASS_DRUID) { // odstranenie formy chr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); // swift flight form chr->CastSpell(chr, 40120, false); } // alici grifina else if (chr->GetTeam() == ALLIANCE) chr->CastSpell(chr, 32290, false); // horda netopiera else chr->CastSpell(chr, 32295, false); return true; }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recv_data*/) { sLog.outDebug("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); uint64 guid = player->GetLootGUID(); if (!guid) return; Loot* pLoot = NULL; bool shareMoney = true; switch (GUID_HIPART(guid)) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && ((pGameObject->GetOwnerGUID() == _player->GetGUID() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE)))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = ObjectAccessor::GetCorpse(*GetPlayer(), guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { pLoot = &bones->loot; shareMoney = false; } break; } case HIGHGUID_ITEM: { if (Item* item = GetPlayer()->GetItemByGuid(guid)) { pLoot = &item->loot; shareMoney = false; } break; } case HIGHGUID_UNIT: { Creature* creature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_SKINNING); if (ok_loot && creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { pLoot = &creature->loot; if (creature->IsAlive()) shareMoney = false; } else player->SendLootError(guid, ok_loot ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL); break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (shareMoney && player->GetGroup()) //item, pickpocket and players can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->GetDistance2d(playerGroup) < sWorld.getConfig(CONFIG_GROUP_XP_DISTANCE)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else player->ModifyMoney(pLoot->gold); pLoot->gold = 0; } }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: %s", LookupOpcodeName(recv_data.GetOpcode())); Player* player = GetPlayer(); ObjectGuid lguid = player->GetLootGuid(); Loot* loot; uint8 lootSlot; Item* pItem = NULL; recv_data >> lootSlot; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; break; } case HIGHGUID_ITEM: { pItem = player->GetItemByGuid(lguid); if (!pItem || !pItem->HasGeneratedLoot()) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; break; } case HIGHGUID_CORPSE: { Corpse* bones = player->GetMap()->GetCorpse(lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; break; } case HIGHGUID_UNIT: case HIGHGUID_VEHICLE: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } QuestItem* qitem = NULL; QuestItem* ffaitem = NULL; QuestItem* conditem = NULL; QuestItem* currency = NULL; LootItem* item = loot->LootItemInSlot(lootSlot, player, &qitem, &ffaitem, &conditem, ¤cy); if (!item) { player->SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL); return; } // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) { player->SendLootRelease(lguid); return; } if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); if (currency) { if (CurrencyTypesEntry const * currencyEntry = sCurrencyTypesStore.LookupEntry(item->itemid)) player->ModifyCurrencyCount(item->itemid, int32(item->count * currencyEntry->GetPrecision())); player->SendNotifyLootItemRemoved(lootSlot, true); currency->is_looted = true; --loot->unlootedCount; return; } ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count); if (msg == EQUIP_ERR_OK) { Item* newitem = player->StoreNewItem(dest, item->itemid, true, item->randomPropertyId, item->GetAllowedLooters()); if (qitem) { qitem->is_looted = true; // freeforall is 1 if everyone's supposed to get the quest item. if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) player->SendNotifyLootItemRemoved(lootSlot); else loot->NotifyQuestItemRemoved(qitem->index); } else { if (ffaitem) { // freeforall case, notify only one player of the removal ffaitem->is_looted = true; player->SendNotifyLootItemRemoved(lootSlot); } else { // not freeforall, notify everyone if (conditem) conditem->is_looted = true; loot->NotifyItemRemoved(lootSlot); } } // if only one person is supposed to loot the item, then set it to looted if (!item->freeforall) item->is_looted = true; --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, loot->loot_type, item->count); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count); if (ItemPrototype const* proto = sObjectMgr.GetItemPrototype(item->itemid)) if (proto->Quality > ITEM_QUALITY_EPIC || (proto->Quality == ITEM_QUALITY_EPIC && proto->ItemLevel >= MinNewsItemLevel[sWorld.getConfig(CONFIG_UINT32_EXPANSION)])) if (Guild* guild = sGuildMgr.GetGuildById(player->GetGuildId())) guild->LogNewsEvent(GUILD_NEWS_ITEM_LOOTED, time(NULL), player->GetObjectGuid(), 0, item->itemid); } else player->SendEquipError(msg, NULL, NULL, item->itemid); }
//show info of player bool ChatHandler::HandlePInfoCommand(const char* args) { Player* target; uint64 target_guid; std::string target_name; uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, target_name)) { target = sObjectMgr->GetPlayerByLowGUID(parseGUID); target_guid = parseGUID; } else if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) return false; uint32 accId = 0; uint32 money = 0; uint32 total_player_time = 0; uint8 level = 0; uint32 latency = 0; uint8 race; uint8 Class; int64 muteTime = 0; int64 banTime = -1; uint32 mapId; uint32 areaId; uint32 phase = 0; // get additional information from Player object if (target) { // check online security if (HasLowerSecurity(target, 0)) return false; accId = target->GetSession()->GetAccountId(); money = target->GetMoney(); total_player_time = target->GetTotalPlayedTime(); level = target->getLevel(); latency = target->GetSession()->GetLatency(); race = target->getRace(); Class = target->getClass(); muteTime = target->GetSession()->m_muteTime; mapId = target->GetMapId(); areaId = target->GetAreaId(); phase = target->GetPhaseMask(); } // get additional information from DB else { // check offline security if (HasLowerSecurity(NULL, target_guid)) return false; // 0 1 2 3 4 5 6 7 QueryResult result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account, race, class, map, zone FROM characters " "WHERE guid = '%u'", GUID_LOPART(target_guid)); if (!result) return false; Field *fields = result->Fetch(); total_player_time = fields[0].GetUInt32(); level = fields[1].GetUInt32(); money = fields[2].GetUInt32(); accId = fields[3].GetUInt32(); race = fields[4].GetUInt8(); Class = fields[5].GetUInt8(); mapId = fields[6].GetUInt16(); areaId = fields[7].GetUInt16(); } std::string username = GetTrinityString(LANG_ERROR); std::string email = GetTrinityString(LANG_ERROR); std::string last_ip = GetTrinityString(LANG_ERROR); uint32 security = 0; std::string last_login = GetTrinityString(LANG_ERROR); QueryResult result = LoginDatabase.PQuery("SELECT a.username, aa.gmlevel, a.email, a.last_ip, a.last_login, a.mutetime " "FROM account a " "LEFT JOIN account_access aa " "ON (a.id = aa.id) " "WHERE a.id = '%u'", accId); if (result) { Field* fields = result->Fetch(); username = fields[0].GetString(); security = fields[1].GetUInt32(); email = fields[2].GetString(); muteTime = fields[5].GetUInt64(); if (email.empty()) email = "-"; if (!m_session || m_session->GetSecurity() >= AccountTypes(security)) { last_ip = fields[3].GetString(); last_login = fields[4].GetString(); } else { last_ip = "-"; last_login = "******"; } } std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, email.c_str(), security, last_ip.c_str(), last_login.c_str(), latency); std::string bannedby = "unknown"; std::string banreason = ""; if (QueryResult result = LoginDatabase.PQuery("SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned " "WHERE id = '%u' AND active ORDER BY bandate ASC LIMIT 1", accId)) { Field * fields = result->Fetch(); banTime = fields[1].GetBool() ? 0 : fields[0].GetUInt64(); bannedby = fields[2].GetString(); banreason = fields[3].GetString(); } else if (QueryResult result = CharacterDatabase.PQuery("SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned " "WHERE guid = '%u' AND active ORDER BY bandate ASC LIMIT 1", GUID_LOPART(target_guid))) { Field * fields = result->Fetch(); banTime = fields[1].GetBool() ? 0 : fields[0].GetUInt64(); bannedby = fields[2].GetString(); banreason = fields[3].GetString(); } if (muteTime > 0) PSendSysMessage(LANG_PINFO_MUTE, secsToTimeString(muteTime - time(NULL), true).c_str()); if (banTime >= 0) PSendSysMessage(LANG_PINFO_BAN, banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "permanently", bannedby.c_str(), banreason.c_str()); std::string race_s, Class_s; switch(race) { case RACE_HUMAN: race_s = "Human"; break; case RACE_ORC: race_s = "Orc"; break; case RACE_DWARF: race_s = "Dwarf"; break; case RACE_NIGHTELF: race_s = "Night Elf"; break; case RACE_UNDEAD_PLAYER: race_s = "Undead"; break; case RACE_TAUREN: race_s = "Tauren"; break; case RACE_GNOME: race_s = "Gnome"; break; case RACE_TROLL: race_s = "Troll"; break; case RACE_BLOODELF: race_s = "Blood Elf"; break; case RACE_DRAENEI: race_s = "Draenei"; break; } switch(Class) { case CLASS_WARRIOR: Class_s = "Warrior"; break; case CLASS_PALADIN: Class_s = "Paladin"; break; case CLASS_HUNTER: Class_s = "Hunter"; break; case CLASS_ROGUE: Class_s = "Rogue"; break; case CLASS_PRIEST: Class_s = "Priest"; break; case CLASS_DEATH_KNIGHT: Class_s = "Death Knight"; break; case CLASS_SHAMAN: Class_s = "Shaman"; break; case CLASS_MAGE: Class_s = "Mage"; break; case CLASS_WARLOCK: Class_s = "Warlock"; break; case CLASS_DRUID: Class_s = "Druid"; break; } std::string timeStr = secsToTimeString(total_player_time, true, true); uint32 gold = money /GOLD; uint32 silv = (money % GOLD) / SILVER; uint32 copp = (money % GOLD) % SILVER; PSendSysMessage(LANG_PINFO_LEVEL, race_s.c_str(), Class_s.c_str(), timeStr.c_str(), level, gold, silv, copp); // Add map, zone, subzone and phase to output int locale = GetSessionDbcLocale(); MapEntry const* map = sMapStore.LookupEntry(mapId); AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); AreaTableEntry const* zone = NULL; if (target) { if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone)) PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name[locale], zone->area_name[locale], area->area_name[locale], phase); else PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name[locale], area->area_name[locale], "--", phase); } else PSendSysMessage(LANG_PINFO_MAP_OFFLINE, map->name[locale], area->area_name[locale]); return true; }
int splArmor(Creature* player, cmd* cmnd, SpellData* spellData) { Player *pPlayer = player->getAsPlayer(); int mpNeeded=0, multi=0; if(!pPlayer) return(0); mpNeeded = spellData->level; if(spellData->how == CastType::CAST && !pPlayer->checkMp(mpNeeded)) return(0); if(!pPlayer->isCt()) { if(pPlayer->getClass() != CreatureClass::MAGE && pPlayer->getSecondClass() != CreatureClass::MAGE) { if(spellData->how == CastType::CAST) { player->print("The arcane nature of that spell eludes you.\n"); return(0); } else { player->print("Nothing happens.\n"); return(0); } } } if( pPlayer->getSecondClass() == CreatureClass::MAGE || (pPlayer->getClass() == CreatureClass::MAGE && pPlayer->getSecondClass() != CreatureClass::MAGE) ) { multi=1; } if(pPlayer->spellFail( spellData->how)) { if(spellData->how == CastType::CAST) pPlayer->subMp(mpNeeded); return(0); } // Cast armor on self int strength = 0; int duration = 0; if(spellData->how == CastType::CAST) { duration = 1800 + bonus((int)pPlayer->intelligence.getCur()); if(spellData->how == CastType::CAST) pPlayer->subMp(mpNeeded); if(pPlayer->getRoomParent()->magicBonus()) { player->print("The room's magical properties increase the power of your spell.\n"); duration += 600L; } if(!multi) strength = pPlayer->hp.getMax(); else strength = pPlayer->hp.getMax()/2; } else { duration = 300L; strength = pPlayer->hp.getMax()/2; } pPlayer->addEffect("armor", duration, strength, player, true, player); pPlayer->computeAC(); if(spellData->how == CastType::CAST || spellData->how == CastType::SCROLL || spellData->how == CastType::WAND) { player->print("Armor spell cast.\n"); broadcast(pPlayer->getSock(), pPlayer->getRoomParent(),"%M casts an armor spell on %sself.", pPlayer, pPlayer->himHer()); } return(1); }
void WorldSession::HandleWhoOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: Received opcode CMSG_WHO"); // recv_data.hexlike(); uint32 level_min, level_max, racemask, classmask, zones_count, str_count; uint32 zoneids[10]; // 10 is client limit std::string player_name, guild_name; recv_data >> level_min; // maximal player level, default 0 recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) recv_data >> player_name; // player name, case sensitive... recv_data >> guild_name; // guild name, case sensitive... recv_data >> racemask; // race mask recv_data >> classmask; // class mask recv_data >> zones_count; // zones count, client limit=10 (2.0.10) if (zones_count > 10) return; // can't be received from real client or broken packet for (uint32 i = 0; i < zones_count; ++i) { uint32 temp; recv_data >> temp; // zone id, 0 if zone is unknown... zoneids[i] = temp; DEBUG_LOG("Zone %u: %u", i, zoneids[i]); } recv_data >> str_count; // user entered strings count, client limit=4 (checked on 2.0.10) if (str_count > 4) return; // can't be received from real client or broken packet DEBUG_LOG("Minlvl %u, maxlvl %u, name %s, guild %s, racemask %u, classmask %u, zones %u, strings %u", level_min, level_max, player_name.c_str(), guild_name.c_str(), racemask, classmask, zones_count, str_count); std::wstring str[4]; // 4 is client limit for (uint32 i = 0; i < str_count; ++i) { std::string temp; recv_data >> temp; // user entered string, it used as universal search pattern(guild+player name)? if (!Utf8toWStr(temp, str[i])) continue; wstrToLower(str[i]); DEBUG_LOG("String %u: %s", i, temp.c_str()); } std::wstring wplayer_name; std::wstring wguild_name; if (!(Utf8toWStr(player_name, wplayer_name) && Utf8toWStr(guild_name, wguild_name))) return; wstrToLower(wplayer_name); wstrToLower(wguild_name); // client send in case not set max level value 100 but mangos support 255 max level, // update it to show GMs with characters after 100 level if (level_max >= MAX_LEVEL) level_max = STRONG_MAX_LEVEL; Team team = _player->GetTeam(); AccountTypes security = GetSecurity(); bool allowTwoSideWhoList = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST); AccountTypes gmLevelInWhoList = (AccountTypes)sWorld.getConfig(CONFIG_UINT32_GM_LEVEL_IN_WHO_LIST); uint32 matchcount = 0; uint32 displaycount = 0; WorldPacket data(SMSG_WHO, 50); // guess size data << uint32(matchcount); // placeholder, count of players matching criteria data << uint32(displaycount); // placeholder, count of players displayed // TODO: Guard Player map HashMapHolder<Player>::MapType& m = sObjectAccessor.GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { Player* pl = itr->second; if (security == SEC_PLAYER) { // player can see member of other team only if CONFIG_BOOL_ALLOW_TWO_SIDE_WHO_LIST if (pl->GetTeam() != team && !allowTwoSideWhoList) continue; // player can see MODERATOR, GAME MASTER, ADMINISTRATOR only if CONFIG_GM_IN_WHO_LIST if (pl->GetSession()->GetSecurity() > gmLevelInWhoList) continue; } // do not process players which are not in world if (!pl->IsInWorld()) continue; // check if target is globally visible for player if (!pl->IsVisibleGloballyFor(_player)) continue; // check if target's level is in level range uint32 lvl = pl->getLevel(); if (lvl < level_min || lvl > level_max) continue; // check if class matches classmask uint32 class_ = pl->getClass(); if (!(classmask & (1 << class_))) continue; // check if race matches racemask uint32 race = pl->getRace(); if (!(racemask & (1 << race))) continue; uint32 pzoneid = pl->GetZoneId(); uint8 gender = pl->getGender(); bool z_show = true; for (uint32 i = 0; i < zones_count; ++i) { if (zoneids[i] == pzoneid) { z_show = true; break; } z_show = false; } if (!z_show) continue; std::string pname = pl->GetName(); std::wstring wpname; if (!Utf8toWStr(pname, wpname)) continue; wstrToLower(wpname); if (!(wplayer_name.empty() || wpname.find(wplayer_name) != std::wstring::npos)) continue; std::string gname = sGuildMgr.GetGuildNameById(pl->GetGuildId()); std::wstring wgname; if (!Utf8toWStr(gname, wgname)) continue; wstrToLower(wgname); if (!(wguild_name.empty() || wgname.find(wguild_name) != std::wstring::npos)) continue; std::string aname; if (AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(pzoneid)) aname = areaEntry->area_name[GetSessionDbcLocale()]; bool s_show = true; for (uint32 i = 0; i < str_count; ++i) { if (!str[i].empty()) { if (wgname.find(str[i]) != std::wstring::npos || wpname.find(str[i]) != std::wstring::npos || Utf8FitTo(aname, str[i])) { s_show = true; break; } s_show = false; } } if (!s_show) continue; // 49 is maximum player count sent to client ++matchcount; if (matchcount > 49) continue; ++displaycount; data << pname; // player name data << gname; // guild name data << uint32(lvl); // player level data << uint32(class_); // player class data << uint32(race); // player race data << uint8(gender); // player gender data << uint32(pzoneid); // player zone id } data.put(0, displaycount); // insert right count, count displayed data.put(4, matchcount); // insert right count, count of matches SendPacket(&data); DEBUG_LOG("WORLD: Send SMSG_WHO Message"); }
int splStoneskin(Creature* player, cmd* cmnd, SpellData* spellData) { Player *pPlayer = player->getAsPlayer(); int mpNeeded=0, multi=0; if(player->getClass() != CreatureClass::LICH) mpNeeded = player->mp.getMax()/2; else mpNeeded = player->hp.getMax()/2; if(spellData->how == CastType::CAST && !player->checkMp(mpNeeded)) return(0); if(!player->isCt()) { if(player->getClass() != CreatureClass::LICH && player->getClass() != CreatureClass::MAGE && (!pPlayer || pPlayer->getSecondClass() != CreatureClass::MAGE)) { if(spellData->how == CastType::CAST) { player->print("The arcane nature of that spell eludes you.\n"); return(0); } else { player->print("Nothing happens.\n"); return(0); } } if(spellData->how == CastType::CAST && spellData->level < 13) { player->print("You are not powerful enough to cast this spell.\n"); return(0); } } if( pPlayer && (pPlayer->getSecondClass() == CreatureClass::MAGE || (pPlayer->getClass() == CreatureClass::MAGE && pPlayer->hasSecondClass())) ) { multi=1; } if(player->spellFail( spellData->how) && spellData->how != CastType::POTION) { if(spellData->how == CastType::CAST) player->subMp(mpNeeded); return(0); } int duration = 0; int strength = 0; // Cast stoneskin on self if(spellData->how == CastType::CAST) { duration = 240 + 10*bonus((int)player->intelligence.getCur()); if(spellData->how == CastType::CAST) player->subMp(mpNeeded); if(player->getRoomParent()->magicBonus()) { player->print("The room's magical properties increase the power of your spell.\n"); duration += 300L; } if(!multi) strength = spellData->level; else strength = MAX<unsigned int>(1, spellData->level-3); } else { duration = 180L; strength = spellData->level/2; } player->addEffect("stoneskin", duration, strength, player, true, player); if(spellData->how == CastType::CAST || spellData->how == CastType::SCROLL || spellData->how == CastType::WAND) { player->print("Stoneskin spell cast.\nYou feel impervious.\n"); broadcast(player->getSock(), player->getParent(),"%M casts a stoneskin spell on %sself.", player, player->himHer()); } else if(spellData->how == CastType::POTION) player->print("You feel impervious.\n"); return(1); }
void WorldSession::SendLfgUpdateList(uint32 dungeonID) { if (!sWorld.getConfig(CONFIG_BOOL_LFR_ENABLE)) { DEBUG_LOG("SendLfgUpdateList %u failed - Raid finder disabled", GetPlayer()->GetObjectGuid().GetCounter()); return; } DEBUG_LOG("SMSG_LFG_SEARCH_RESULTS %u dungeonentry: %u ", GetPlayer()->GetObjectGuid().GetCounter(), dungeonID); LFGDungeonEntry const* dungeon = sLFGMgr.GetDungeon(dungeonID); if (!dungeon) return; Team team = sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP) ? TEAM_NONE : GetPlayer()->GetTeam(); GuidSet groups = sLFGMgr.GetDungeonGroupQueue(dungeon, team); GuidSet players = sLFGMgr.GetDungeonPlayerQueue(dungeon, team); uint32 groupCount = groups.size(); uint32 groupSize = 4+4; for (GuidSet::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) { Group* pGroup = sObjectMgr.GetGroup(*itr); if (!pGroup) continue; Player* pLeader = sObjectMgr.GetPlayer(pGroup->GetLeaderGuid()); if (!pLeader) continue; sLFGMgr.GetLFGPlayerState(pLeader->GetObjectGuid())->AddFlags(LFG_MEMBER_FLAG_CHARINFO | LFG_MEMBER_FLAG_COMMENT | LFG_MEMBER_FLAG_GROUPLEADER | LFG_MEMBER_FLAG_GROUPGUID | LFG_MEMBER_FLAG_ROLES | LFG_MEMBER_FLAG_AREA | LFG_MEMBER_FLAG_STATUS | LFG_MEMBER_FLAG_BIND); uint32 flags = sLFGMgr.GetLFGPlayerState(pLeader->GetObjectGuid())->GetFlags(); if (flags & LFG_MEMBER_FLAG_COMMENT) groupSize += sLFGMgr.GetLFGPlayerState(pLeader->GetObjectGuid())->GetComment().size()+1; if (flags & LFG_MEMBER_FLAG_ROLES) groupSize +=3; if (flags & LFG_MEMBER_FLAG_BIND) groupSize += (8+4); players.insert(*itr); for (GroupReference *itr2 = pGroup->GetFirstMember(); itr2 != NULL; itr2 = itr2->next()) { Player* player = itr2->getSource(); if (!player || player == pLeader) continue; sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->AddFlags(LFG_MEMBER_FLAG_GROUPLEADER | LFG_MEMBER_FLAG_GROUPGUID | LFG_MEMBER_FLAG_STATUS); sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->RemoveFlags(LFG_MEMBER_FLAG_CHARINFO | LFG_MEMBER_FLAG_COMMENT | LFG_MEMBER_FLAG_ROLES | LFG_MEMBER_FLAG_AREA | LFG_MEMBER_FLAG_BIND); players.insert(player->GetObjectGuid()); } } uint32 playerCount = players.size(); uint32 playerSize = 4+4; uint32 guidsSize = 0; GuidSet playersUpdated; playersUpdated.clear(); for(GuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (!player || !player->IsInWorld()) continue; uint32 flags = sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetFlags(); playerSize += (8+4); if (flags & LFG_MEMBER_FLAG_CHARINFO) playerSize += (1+1+1+3+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4+4); if (flags & LFG_MEMBER_FLAG_COMMENT) playerSize += sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetComment().size()+1; // comment if (flags & LFG_MEMBER_FLAG_GROUPLEADER) playerSize += 1; if (flags & LFG_MEMBER_FLAG_GROUPGUID) playerSize += 8; if (flags & LFG_MEMBER_FLAG_ROLES) playerSize += 1; if (flags & LFG_MEMBER_FLAG_AREA) playerSize += 4; if (flags & LFG_MEMBER_FLAG_STATUS) playerSize += 1; if (flags & LFG_MEMBER_FLAG_BIND) playerSize += (8+4); if (flags & LFG_MEMBER_FLAG_UPDATE) { sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->RemoveFlags(LFG_MEMBER_FLAG_UPDATE); playersUpdated.insert(player->GetObjectGuid()); guidsSize += 8; } } WorldPacket data(SMSG_LFG_SEARCH_RESULTS, 4 + 4 + 1 + groupSize + playerSize + guidsSize); data << uint32(dungeon->type); // type data << uint32(dungeon->Entry()); // entry from LFGDungeons.dbc if (!playersUpdated.empty()) { data << uint8(playersUpdated.size()); for (GuidSet::const_iterator itr = playersUpdated.begin(); itr != playersUpdated.end(); ++itr) { data << *itr; // player guid } } else data << uint8(0); if (!groups.empty()) { data << uint32(groupCount); // groups count data << uint32(groupCount); // groups count2 for (GuidSet::const_iterator itr = groups.begin(); itr != groups.end(); ++itr) { Group* group = sObjectMgr.GetGroup(*itr); if (!group) continue; Player* leader = sObjectMgr.GetPlayer(group->GetLeaderGuid()); uint32 flags = sLFGMgr.GetLFGPlayerState(leader->GetObjectGuid())->GetFlags(); data << group->GetObjectGuid(); data << flags; if (flags & LFG_MEMBER_FLAG_COMMENT) { data << sLFGMgr.GetLFGPlayerState(leader->GetObjectGuid())->GetComment().c_str(); } if (flags & LFG_MEMBER_FLAG_ROLES) { for (int i = 0; i < 3; ++i) { // need implement function for roles count calculation. or not need? data << uint8(0); } } if (flags & LFG_MEMBER_FLAG_BIND) { ObjectGuid instanceGuid; uint32 encounters = 0; if (InstancePlayerBind* bind = leader->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) { instanceGuid = state->GetInstanceGuid(); encounters = state->GetCompletedEncountersMask(); } } data << instanceGuid; data << encounters; } } } else { data << uint32(0); data << uint32(0); // groups count2 } if (!players.empty()) { data << uint32(playerCount); // players count data << uint32(playerCount); // players count 2 for(GuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr) { Player* player = sObjectMgr.GetPlayer(*itr); if (!player || !player->IsInWorld()) continue; uint32 flags = sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetFlags(); data << *itr; // guid data << flags; // flags if (flags & LFG_MEMBER_FLAG_CHARINFO) // charinfo { data << uint8(player->getLevel()); data << uint8(player->getClass()); data << uint8(player->getRace()); for(int i = 0; i < 3; ++i) data << uint8(player->GetTalentsCount(i)); // spent talents count in specific tab data << uint32(player->GetArmor()); // armor data << uint32(player->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SPELL)); // spd data << uint32(player->SpellBaseHealingBonusDone(SPELL_SCHOOL_MASK_SPELL)); // heal data << uint32(player->GetRatingBonusValue(CR_CRIT_MELEE)); // crit rating melee data << uint32(player->GetRatingBonusValue(CR_CRIT_RANGED)); // crit rating ranged data << uint32(player->GetRatingBonusValue(CR_CRIT_SPELL)); // crit rating spell data << float(player->GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER)*5); // mp5 data << float(player->GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER)*5); // unk data << uint32(player->GetTotalAttackPowerValue(BASE_ATTACK)); // attack power data << uint32(player->GetTotalStatValue(STAT_AGILITY)); // agility data << uint32(player->GetMaxHealth()); // health data << uint32(player->GetMaxPower(player->GetPowerType())); // power data << uint32(player->GetFreeTalentPoints()); // free talent points (TOM_RUS) data << float(0); // unk data << uint32(player->GetRatingBonusValue(CR_DEFENSE_SKILL)); // defence rating data << uint32(player->GetRatingBonusValue(CR_DODGE)); // dodge rating data << uint32(player->GetRatingBonusValue(CR_BLOCK)); // block rating data << uint32(player->GetRatingBonusValue(CR_PARRY)); // parry rating data << uint32(player->GetRatingBonusValue(CR_HASTE_MELEE)); // crit rating data << uint32(player->GetRatingBonusValue(CR_EXPERTISE)); // expertize } if (flags & LFG_MEMBER_FLAG_COMMENT) data << sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetComment().c_str(); // comment if (flags & LFG_MEMBER_FLAG_GROUPLEADER) // Group leader flag { bool isLeader = false; if (Group* group = player->GetGroup()) if (player->GetObjectGuid() == group->GetLeaderGuid()) isLeader = true; data << uint8(isLeader); } if (flags & LFG_MEMBER_FLAG_GROUPGUID) // Group guid { ObjectGuid groupGuid = ObjectGuid(); if (Group* group = player->GetGroup()) groupGuid = group->GetObjectGuid(); data << groupGuid; } if (flags & LFG_MEMBER_FLAG_ROLES) // rolesMask data << uint8(sLFGMgr.GetLFGPlayerState(player->GetObjectGuid())->GetRoles()); if (flags & LFG_MEMBER_FLAG_AREA) // Area data << uint32(player->GetAreaId()); if (flags & LFG_MEMBER_FLAG_STATUS) // status data << uint8(0); if (flags & LFG_MEMBER_FLAG_BIND) { ObjectGuid instanceGuid; uint32 encounters = 0; if (InstancePlayerBind* bind = player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) { if (DungeonPersistentState* state = bind->state) { instanceGuid = state->GetInstanceGuid(); encounters = state->GetCompletedEncountersMask(); } } data << instanceGuid; data << encounters; } } } else { data << uint32(0); // players count data << uint32(0); // unk } SendPacket(&data); }
void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recv_data*/) { DEBUG_LOG("WORLD: CMSG_LOOT_MONEY"); Player* player = GetPlayer(); ObjectGuid guid = player->GetLootGuid(); if (!guid) return; Loot* pLoot = NULL; Item* pItem = NULL; switch (guid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* pGameObject = GetPlayer()->GetMap()->GetGameObject(guid); // not check distance for GO in case owned GO (fishing bobber case, for example) if (pGameObject && (pGameObject->GetOwnerGuid() == _player->GetObjectGuid() || pGameObject->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) pLoot = &pGameObject->loot; break; } case HIGHGUID_CORPSE: // remove insignia ONLY in BG { Corpse* bones = _player->GetMap()->GetCorpse(guid); if (bones && bones->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &bones->loot; break; } case HIGHGUID_ITEM: { pItem = GetPlayer()->GetItemByGuid(guid); if (!pItem || !pItem->HasGeneratedLoot()) return; pLoot = &pItem->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(guid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (ok_loot && pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) pLoot = &pCreature->loot ; break; } default: return; // unlootable type } if (pLoot) { pLoot->NotifyMoneyRemoved(); if (!guid.IsItem() && player->GetGroup()) // item can be looted only single player { Group* group = player->GetGroup(); std::vector<Player*> playersNear; for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* playerGroup = itr->getSource(); if (!playerGroup) continue; if (player->IsWithinDistInMap(playerGroup, sWorld.getConfig(CONFIG_FLOAT_GROUP_XP_DISTANCE), false)) playersNear.push_back(playerGroup); } uint32 money_per_player = uint32((pLoot->gold) / (playersNear.size())); for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i) { (*i)->ModifyMoney(money_per_player); WorldPacket data(SMSG_LOOT_MONEY_NOTIFY, 4); data << uint32(money_per_player); (*i)->GetSession()->SendPacket(&data); } } else player->ModifyMoney(pLoot->gold); pLoot->gold = 0; if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); } }
//show info of player bool ChatHandler::HandlePInfoCommand(const char* args) { Player* target; uint64 target_guid; std::string target_name; if (!extractPlayerTarget((char*)args, &target, &target_guid, &target_name)) return false; uint32 accId = 0; uint32 money = 0; uint32 total_player_time = 0; uint8 level = 0; uint32 latency = 0; uint8 race; uint8 Class; int64 muteTime = 0; int64 banTime = -1; // get additional information from Player object if (target) { // check online security if (HasLowerSecurity(target, 0)) return false; accId = target->GetSession()->GetAccountId(); money = target->GetMoney(); total_player_time = target->GetTotalPlayedTime(); level = target->getLevel(); latency = target->GetSession()->GetLatency(); race = target->getRace(); Class = target->getClass(); muteTime = target->GetSession()->m_muteTime; } // get additional information from DB else { // check offline security if (HasLowerSecurity(NULL, target_guid)) return false; // 0 1 2 3 4 5 QueryResult result = CharacterDatabase.PQuery("SELECT totaltime, level, money, account, race, class FROM characters WHERE guid = '%u'", GUID_LOPART(target_guid)); if (!result) return false; Field *fields = result->Fetch(); total_player_time = fields[0].GetUInt32(); level = fields[1].GetUInt32(); money = fields[2].GetUInt32(); accId = fields[3].GetUInt32(); race = fields[4].GetUInt8(); Class = fields[5].GetUInt8(); } std::string username = GetTrinityString(LANG_ERROR); std::string email = GetTrinityString(LANG_ERROR); std::string last_ip = GetTrinityString(LANG_ERROR); uint32 security = 0; std::string last_login = GetTrinityString(LANG_ERROR); QueryResult result = LoginDatabase.PQuery("SELECT a.username, aa.gmlevel, a.email, a.last_ip, a.last_login, a.mutetime " "FROM account a " "LEFT JOIN account_access aa " "ON (a.id = aa.id) " "WHERE a.id = '%u'", accId); if (result) { Field* fields = result->Fetch(); username = fields[0].GetString(); security = fields[1].GetUInt32(); email = fields[2].GetString(); muteTime = fields[5].GetUInt64(); if (email.empty()) email = "-"; if (!m_session || m_session->GetSecurity() >= AccountTypes(security)) { last_ip = fields[3].GetString(); last_login = fields[4].GetString(); } else { last_ip = "-"; last_login = "******"; } } std::string nameLink = playerLink(target_name); PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(target_guid), username.c_str(), accId, email.c_str(), security, last_ip.c_str(), last_login.c_str(), latency); if (QueryResult result = LoginDatabase.PQuery("SELECT unbandate, bandate = unbandate FROM account_banned WHERE id = '%u' AND active ORDER BY bandate ASC LIMIT 1", accId)) { Field * fields = result->Fetch(); banTime = fields[1].GetBool() ? 0 : fields[0].GetUInt64(); } else if (QueryResult result = CharacterDatabase.PQuery("SELECT unbandate, bandate = unbandate FROM character_banned WHERE guid = '%u' AND active ORDER BY bandate ASC LIMIT 1", GUID_LOPART(target_guid))) { Field * fields = result->Fetch(); banTime = fields[1].GetBool() ? 0 : fields[0].GetUInt64(); } muteTime = muteTime - time(NULL); if (muteTime > 0 || banTime >= 0) PSendSysMessage(LANG_PINFO_MUTE_BAN, muteTime > 0 ? secsToTimeString(muteTime, true).c_str() : "---", !banTime ? "perm." : (banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "---")); std::string race_s, Class_s; switch(race) { case RACE_HUMAN: race_s = "Human"; break; case RACE_ORC: race_s = "Orc"; break; case RACE_DWARF: race_s = "Dwarf"; break; case RACE_NIGHTELF: race_s = "Night Elf"; break; case RACE_UNDEAD_PLAYER: race_s = "Undead"; break; case RACE_TAUREN: race_s = "Tauren"; break; case RACE_GNOME: race_s = "Gnome"; break; case RACE_TROLL: race_s = "Troll"; break; case RACE_BLOODELF: race_s = "Blood Elf"; break; case RACE_DRAENEI: race_s = "Draenei"; break; } switch(Class) { case CLASS_WARRIOR: Class_s = "Warrior"; break; case CLASS_PALADIN: Class_s = "Paladin"; break; case CLASS_HUNTER: Class_s = "Hunter"; break; case CLASS_ROGUE: Class_s = "Rogue"; break; case CLASS_PRIEST: Class_s = "Priest"; break; case CLASS_DEATH_KNIGHT: Class_s = "Death Knight"; break; case CLASS_SHAMAN: Class_s = "Shaman"; break; case CLASS_MAGE: Class_s = "Mage"; break; case CLASS_WARLOCK: Class_s = "Warlock"; break; case CLASS_DRUID: Class_s = "Druid"; break; } std::string timeStr = secsToTimeString(total_player_time, true, true); uint32 gold = money /GOLD; uint32 silv = (money % GOLD) / SILVER; uint32 copp = (money % GOLD) % SILVER; PSendSysMessage(LANG_PINFO_LEVEL, race_s.c_str(), Class_s.c_str(), timeStr.c_str(), level, gold, silv, copp); return true; }
void WorldSession::DoLootRelease(ObjectGuid lguid) { Player* player = GetPlayer(); Loot* loot; player->SetLootGuid(ObjectGuid()); player->SendLootRelease(lguid); player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_LOOTING); if (!player->IsInWorld()) return; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = GetPlayer()->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) return; loot = &go->loot; if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR) { // locked doors are opened with spelleffect openlock, prevent remove its as looted go->UseDoorOrButton(); } else if (loot->isLooted() || go->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE) { // GO is mineral vein? so it is not removed after its looted if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) { uint32 go_min = go->GetGOInfo()->chest.minSuccessOpens; uint32 go_max = go->GetGOInfo()->chest.maxSuccessOpens; // only vein pass this check if (go_min != 0 && go_max > go_min) { float amount_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_AMOUNT); float min_amount = go_min * amount_rate; float max_amount = go_max * amount_rate; go->AddUse(); float uses = float(go->GetUseCount()); if (uses < max_amount) { if (uses >= min_amount) { float chance_rate = sWorld.getConfig(CONFIG_FLOAT_RATE_MINING_NEXT); int32 ReqValue = 175; LockEntry const* lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if (lockInfo) ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING)) / (ReqValue + 25); double chance = pow(0.8 * chance_rate, 4 * (1 / double(max_amount)) * double(uses)); if (roll_chance_f(float(100.0f * chance + skill))) { go->SetLootState(GO_READY); } else // not have more uses go->SetLootState(GO_JUST_DEACTIVATED); } else // 100% chance until min uses go->SetLootState(GO_READY); } else // max uses already go->SetLootState(GO_JUST_DEACTIVATED); } else // not vein go->SetLootState(GO_JUST_DEACTIVATED); } else if (go->GetGoType() == GAMEOBJECT_TYPE_FISHINGHOLE) { // The fishing hole used once more go->AddUse(); // if the max usage is reached, will be despawned at next tick if (go->GetUseCount() >= urand(go->GetGOInfo()->fishinghole.minSuccessOpens, go->GetGOInfo()->fishinghole.maxSuccessOpens)) { go->SetLootState(GO_JUST_DEACTIVATED); } else go->SetLootState(GO_READY); } else // not chest (or vein/herb/etc) go->SetLootState(GO_JUST_DEACTIVATED); loot->clear(); } else // not fully looted object go->SetLootState(GO_ACTIVATED); break; } case HIGHGUID_CORPSE: // ONLY remove insignia at BG { Corpse* corpse = _player->GetMap()->GetCorpse(lguid); if (!corpse || !corpse->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &corpse->loot; if (loot->isLooted()) { loot->clear(); corpse->RemoveFlag(CORPSE_FIELD_DYNAMIC_FLAGS, CORPSE_DYNFLAG_LOOTABLE); } break; } case HIGHGUID_ITEM: { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) return; switch (pItem->loot.loot_type) { // temporary loot, auto loot move case LOOT_DISENCHANTING: { if (!pItem->loot.isLooted()) player->AutoStoreLoot(pItem->loot); // can be lost if no space pItem->loot.clear(); pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); break; } // normal persistence loot default: { // must be destroyed only if no loot if (pItem->loot.isLooted()) { pItem->SetLootState(ITEM_LOOT_REMOVED); player->DestroyItem(pItem->GetBagSlot(), pItem->GetSlot(), true); } break; } } return; // item can be looted only single player } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) return; loot = &pCreature->loot; // update next looter if (Group* group = pCreature->GetGroupLootRecipient()) if (group->GetLooterGuid() == player->GetObjectGuid()) group->UpdateLooterGuid(pCreature); if (loot->isLooted()) { // for example skinning after normal loot pCreature->PrepareBodyLootState(); if (!pCreature->isAlive()) pCreature->AllLootRemovedFromCorpse(); } break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } // Player is not looking at loot list, he doesn't need to see updates on the loot list loot->RemoveLooter(player->GetObjectGuid()); }
void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder) { uint64 playerGuid = holder->GetGuid(); Player *pCurrChar = new Player(this); pCurrChar->GetMotionMaster()->Initialize(); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(false); WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); // load player specific part before send times LoadAccountData(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK); SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ( (nextpos= str_motd.find('@',pos)) != std::string::npos ) { if (nextpos != pos) { data << str_motd.substr(pos, nextpos-pos); ++linecount; } pos = nextpos + 1; } if (pos < str_motd.length()) { data << str_motd.substr(pos); ++linecount; } data.put(0, linecount); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); } //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow()); QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if(resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete resultGuild; } else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); // Increment online members of the guild guild->IncOnlineMemberCount(); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); data << uint32(0); data << uint32(0); SendPacket(&data); if(!pCurrChar->isAlive()) pCurrChar->SendCorpseReclaimDelay(true); pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if( !pCurrChar->getCinematic() ) { pCurrChar->setCinematic(1); if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) { if (cEntry->CinematicSequence) pCurrChar->SendCinematicStart(cEntry->CinematicSequence); else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) pCurrChar->SendCinematicStart(rEntry->CinematicSequence); } } if (!pCurrChar->GetMap()->Add(pCurrChar)) { AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); if(at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); } ObjectAccessor::Instance().AddObject(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); loginDatabase.PExecute("UPDATE account SET active_realm_id = %d WHERE id = '%u'", realmID, GetAccountId()); pCurrChar->SetInGameTime( getMSTime() ); // announce group about member online (must be after add to player list to receive announce to self) if(Group *group = pCurrChar->GetGroup()) { //pCurrChar->groupInfo.group->SendInit(this); // useless group->SendUpdate(); } // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if(pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetMovement(MOVE_WATER_WALK); } pCurrChar->ContinueTaxiFlight(); // reset for all pets before pet loading if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) Pet::resetTalentsForAllPetsOf(pCurrChar); // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) ) pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state SendNotification(LANG_RESET_TALENTS); } // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); if(pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)", GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow()); if(!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); m_playerLoading = false; delete holder; }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recv_data) { DEBUG_LOG("WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); ObjectGuid lguid = player->GetLootGuid(); Loot* loot; uint8 lootSlot; Item* pItem = NULL; recv_data >> lootSlot; switch (lguid.GetHigh()) { case HIGHGUID_GAMEOBJECT: { GameObject* go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGuid() != _player->GetObjectGuid() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; break; } case HIGHGUID_ITEM: { pItem = player->GetItemByGuid(lguid); if (!pItem || !pItem->HasGeneratedLoot()) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; break; } case HIGHGUID_CORPSE: { Corpse* bones = player->GetMap()->GetCorpse(lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; break; } case HIGHGUID_UNIT: { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; break; } default: { sLog.outError("%s is unsupported for looting.", lguid.GetString().c_str()); return; } } QuestItem* qitem = NULL; QuestItem* ffaitem = NULL; QuestItem* conditem = NULL; LootItem* item = loot->LootItemInSlot(lootSlot, player, &qitem, &ffaitem, &conditem); if (!item) { player->SendEquipError(EQUIP_ERR_ALREADY_LOOTED, NULL, NULL); return; } // questitems use the blocked field for other purposes if (!qitem && item->is_blocked) { player->SendLootRelease(lguid); return; } if (pItem) pItem->SetLootState(ITEM_LOOT_CHANGED); ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item->itemid, item->count); if (msg == EQUIP_ERR_OK) { Item* newitem = player->StoreNewItem(dest, item->itemid, true, item->randomPropertyId); if (qitem) { qitem->is_looted = true; // freeforall is 1 if everyone's supposed to get the quest item. if (item->freeforall || loot->GetPlayerQuestItems().size() == 1) player->SendNotifyLootItemRemoved(lootSlot); else loot->NotifyQuestItemRemoved(qitem->index); } else { if (ffaitem) { // freeforall case, notify only one player of the removal ffaitem->is_looted = true; player->SendNotifyLootItemRemoved(lootSlot); } else { // not freeforall, notify everyone if (conditem) conditem->is_looted = true; loot->NotifyItemRemoved(lootSlot); } } // if only one person is supposed to loot the item, then set it to looted if (!item->freeforall) item->is_looted = true; --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); } else player->SendEquipError(msg, NULL, NULL, item->itemid); }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); uint64 lguid = player->GetLootGUID(); Loot* loot = NULL; uint8 lootSlot = 0; recv_data >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject *go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; } else if (IS_ITEM_GUID(lguid)) { Item *pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; } else if (IS_CORPSE_GUID(lguid)) { Corpse *bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } else { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = pCreature && pCreature->isAlive() == (player->getClass() == CLASS_ROGUE && pCreature->lootForPickPocketed); if (!ok_loot || !pCreature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } loot = &pCreature->loot; } player->StoreLootItem(lootSlot, loot); }
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 10); std::string name; uint8 race, class_; recv_data >> name >> race >> class_; recv_data.rpos(0); WorldPacket data(SMSG_CHAR_CREATE, 1); if(!sWorld.VerifyName(name.c_str(), name.length())) { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } if(g_characterNameFilter->Parse(name, false)) { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } //reserved for console whisper if(name == "Console" || name == "console") { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } if(objmgr.GetPlayerInfoByName(name.c_str()) != 0) { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } if(!sHookInterface.OnNewCharacter(race, class_, this, name.c_str())) { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } if( class_ == DEATHKNIGHT && (!HasFlag(ACCOUNT_FLAG_XPACK_02) || !CanCreateDeathKnight() ) ) { if(CanCreateDeathKnight()) data << uint8(CHAR_CREATE_EXPANSION); else data << uint8(CHAR_CREATE_LEVEL_REQUIREMENT); SendPacket(&data); return; } QueryResult * result = CharacterDatabase.Query("SELECT COUNT(*) FROM banned_names WHERE name = '%s'", CharacterDatabase.EscapeString(name).c_str()); if(result) { if(result->Fetch()[0].GetUInt32() > 0) { // That name is banned! data << uint8(CHAR_NAME_PROFANE); SendPacket(&data); delete result; return; } delete result; } // loading characters //checking number of chars is useless since client will not allow to create more than 10 chars //as the 'create' button will not appear (unless we want to decrease maximum number of characters) Player* pNewChar = objmgr.CreatePlayer(); pNewChar->SetSession(this); if(!pNewChar->Create( recv_data )) { // failed. pNewChar->ok_to_remove = true; pNewChar->Destruct(); pNewChar = NULLPLR; return; } pNewChar->UnSetBanned(); pNewChar->addSpell(22027); // Remove Insignia if(pNewChar->getClass() == WARLOCK) { pNewChar->AddSummonSpell(416, 3110); // imp fireball pNewChar->AddSummonSpell(417, 19505); pNewChar->AddSummonSpell(1860, 3716); pNewChar->AddSummonSpell(1863, 7814); } pNewChar->SaveToDB(true); PlayerInfo *pn = new PlayerInfo; memset(pn, 0, sizeof(PlayerInfo)); pn->guid = pNewChar->GetLowGUID(); pn->name = strdup(pNewChar->GetName()); pn->cl = pNewChar->getClass(); pn->race = pNewChar->getRace(); pn->gender = pNewChar->getGender(); pn->lastLevel = pNewChar->getLevel(); pn->lastZone = pNewChar->GetZoneId(); pn->lastOnline = UNIXTIME; pn->team = pNewChar->GetTeam(); pn->acct = GetAccountId(); objmgr.AddPlayerInfo(pn); pNewChar->ok_to_remove = true; pNewChar->Destruct(); pNewChar = NULLPLR; // CHAR_CREATE_SUCCESS data << uint8(CHAR_CREATE_SUCCESS); SendPacket(&data); sLogonCommHandler.UpdateAccountCount(GetAccountId(), 1); }
bool ArenaTeam::AddMember(const uint64& playerGuid) { std::string playerName; uint8 playerClass; // Check if arena team is full (Can't have more than type * 2 players) if (GetMembersSize() >= GetType() * 2) return false; // Get player name and class either from db or ObjectMgr Player* player = ObjectAccessor::FindPlayer(playerGuid); if (player) { playerClass = player->getClass(); playerName = player->GetName(); } else { // 0 1 // SELECT name, class FROM characters WHERE guid = ? PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_CLASS); stmt->setUInt32(0, GUID_LOPART(playerGuid)); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) return false; playerName = (*result)[0].GetString(); playerClass = (*result)[1].GetUInt8(); } // Check if player is already in a similar arena team if ((player && player->GetArenaTeamId(GetSlot())) || Player::GetArenaTeamIdFromDB(playerGuid, GetType()) != 0) { sLog->outError("Arena: Player %s (guid: %u) already has an arena team of type %u", playerName.c_str(), GUID_LOPART(playerGuid), GetType()); return false; } // Set player's personal rating uint32 personalRating = 0; if (sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING) >= 0) personalRating = sWorld->getIntConfig(CONFIG_ARENA_START_PERSONAL_RATING); else if (GetRating() >= 1000) personalRating = 1000; // Try to get player's match maker rating from db and fall back to config setting if not found PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_MATCH_MAKER_RATING); stmt->setUInt32(0, GUID_LOPART(playerGuid)); stmt->setUInt8(1, GetSlot()); PreparedQueryResult result = CharacterDatabase.Query(stmt); uint32 matchMakerRating; if (result) matchMakerRating = (*result)[0].GetUInt32(); else matchMakerRating = sWorld->getIntConfig(CONFIG_ARENA_START_MATCHMAKER_RATING); // Remove all player signatures from other petitions // This will prevent player from joining too many arena teams and corrupt arena team data integrity Player::RemovePetitionsAndSigns(playerGuid, GetType()); // Feed data to the struct ArenaTeamMember newmember; newmember.Name = playerName; newmember.Guid = playerGuid; newmember.Class = playerClass; newmember.SeasonGames = 0; newmember.WeekGames = 0; newmember.SeasonWins = 0; newmember.WeekWins = 0; newmember.PersonalRating = personalRating; newmember.MatchMakerRating = matchMakerRating; Members.push_back(newmember); // Save player's arena team membership to db stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_ARENA_TEAM_MEMBER); stmt->setUInt32(0, TeamId); stmt->setUInt32(1, GUID_LOPART(playerGuid)); CharacterDatabase.Execute(stmt); // Inform player if online if (player) { player->SetInArenaTeam(TeamId, GetSlot(), GetType()); player->SetArenaTeamIdInvited(0); // Hide promote/remove buttons if (CaptainGuid != playerGuid) player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1); } sLog->outArena("Player: %s [GUID: %u] joined arena team type: %u [Id: %u].", playerName.c_str(), GUID_LOPART(playerGuid), GetType(), GetId()); return true; }
void StatDumper::DumpStats() { double TotalTrafficInKb = 0.0; double TotalTrafficOutKb = 0.0; double LastTotalTrafficInKb = 0.0; double LastTotalTrafficOutKb = 0.0; double TrafficInKb = 0.0; double TrafficOutKb = 0.0; double TrafficInKbsec = 0.0; double TrafficOutKbsec = 0.0; time_t timediff = 0; if( Filename[0] == '\0' ) return; FILE* f = fopen( Filename, "w" ); if( !f ) return; Log.Debug( "StatDumper", "Writing %s", Filename ); // Dump Header fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); fprintf(f, "<?xml-stylesheet type=\"text/xsl\" href=\"server_stats.xsl\"?>\n"); fprintf(f, "<serverpage>\n"); fprintf(f, " <status>\n"); uint32 races[RACE_DRAENEI+1]; uint32 classes[DRUID+1]; memset(&races[0], 0, sizeof(uint32)*(RACE_DRAENEI+1)); memset(&classes[0], 0, sizeof(uint32)*(RACE_DRAENEI+1)); std::deque<Player*> gms; { // Dump server information. #ifdef WIN32 fprintf(f, " <platform>ArcEmu %s r%u/%s-Win-%s (www.ArcEmu.org)</platform>\n", BUILD_TAG, BUILD_REVISION, CONFIG, ARCH); #else fprintf(f, " <platform>ArcEmu %s r%u/%s-%s (www.ArcEmu.org)</platform>\n", BUILD_TAG, BUILD_REVISION, PLATFORM_TEXT, ARCH); #endif char uptime[80]; GenerateUptimeString(uptime); float AvgLat; uint32 GMCount; int gm = 0; int count = 0; int avg = 0; // lock players reader objmgr._playerslock.AcquireReadLock(); HM_NAMESPACE::hash_map<uint32, Player*>::const_iterator itr; for (itr = objmgr._players.begin(); itr != objmgr._players.end(); itr++) { if(itr->second->GetSession() && itr->second->IsInWorld()) { count++; avg += itr->second->GetSession()->GetLatency(); if(itr->second->GetSession()->GetPermissionCount()) { gm++; gms.push_back(itr->second); } classes[itr->second->getClass()]++; races[itr->second->getRace()]++; } } objmgr._playerslock.ReleaseReadLock(); AvgLat = count ? (float)((float)avg / (float)count) : 0; GMCount = gm; sWorld.QueryTotalTraffic(&TotalTrafficInKb,&TotalTrafficOutKb); if(LastTrafficUpdate != 0){ sWorld.QueryLastTotalTraffic(&LastTotalTrafficInKb, &LastTotalTrafficOutKb); TrafficInKb = TotalTrafficInKb - LastTotalTrafficInKb; TrafficOutKb = TotalTrafficOutKb - LastTotalTrafficOutKb; timediff = UNIXTIME - LastTrafficUpdate; if(TrafficInKb != 0 && TrafficOutKb != 0 && timediff != 0){ TrafficInKbsec = TrafficInKb / timediff; TrafficOutKbsec = TrafficOutKb / timediff; } } LastTrafficUpdate = UNIXTIME; fprintf(f, " <uptime>%s</uptime>\n", uptime); fprintf(f, " <oplayers>%u</oplayers>\n", (unsigned int)(sWorld.getPlayerCount())); fprintf(f, " <cpu>%2.2f</cpu>\n", GetCPUUsage()); fprintf(f, " <qplayers>%u</qplayers>\n", (unsigned int)sWorld.GetQueueCount()); fprintf(f, " <ram>%.3f</ram>\n", GetRAMUsage()); fprintf(f, " <avglat>%.3f</avglat>\n", AvgLat); fprintf(f, " <threads>%u</threads>\n", (unsigned int)ThreadPool.GetActiveThreadCount()); fprintf(f, " <fthreads>%u</fthreads>\n", (unsigned int)ThreadPool.GetFreeThreadCount()); time_t t = UNIXTIME; fprintf(f, " <gmcount>%u</gmcount>\n", (unsigned int)GMCount); fprintf(f, " <lastupdate>%s</lastupdate>\n", asctime(localtime(&t))); fprintf(f, " <alliance>%u</alliance>\n", (unsigned int)sWorld.getAlliancePlayerCount()); fprintf(f, " <horde>%u</horde>\n", (unsigned int)sWorld.getHordePlayerCount()); fprintf(f, " <acceptedconns>%u</acceptedconns>\n", (unsigned int)sWorld.mAcceptedConnections); fprintf(f, " <peakcount>%u</peakcount>\n", (unsigned int)sWorld.PeakSessionCount); fprintf(f, " <wdbquerysize>%u</wdbquerysize>\n", WorldDatabase.GetQueueSize()); fprintf(f, " <cdbquerysize>%u</cdbquerysize>\n", CharacterDatabase.GetQueueSize()); fprintf(f, " <bandwithin>%lf</bandwithin>\n", TrafficInKbsec); if( TotalTrafficInKb < 1024.0 ) fprintf(f, " <bandwithintotal>%lf KB</bandwithintotal>\n", TotalTrafficInKb); else fprintf(f, " <bandwithintotal>%lf MB</bandwithintotal>\n", ( TotalTrafficInKb / 1024.0)); fprintf(f, " <bandwithout>%lf</bandwithout>\n", TrafficOutKbsec); if( TotalTrafficOutKb < 1024.0 ) fprintf(f, " <bandwithouttotal>%lf KB</bandwithouttotal>\n", TotalTrafficOutKb); else fprintf(f, " <bandwithouttotal>%lf MB</bandwithouttotal>\n", ( TotalTrafficOutKb / 1024.0 )); } fprintf(f, " </status>\n"); static const char * race_names[RACE_DRAENEI+1] = { NULL, "human", "orc", "dwarf", "nightelf", "undead", "tauren", "gnome", "troll", NULL, "bloodelf", "draenei", }; static const char * class_names[DRUID+1] = { NULL, "warrior", "paladin", "hunter", "rogue", "priest", "deathknight", "shaman", "mage", "warlock", NULL, "druid", }; fprintf(f, " <statsummary>\n"); uint32 i; for(i = 0; i <= RACE_DRAENEI; ++i) { if( race_names[i] != NULL ) fprintf(f, " <%s>%u</%s>\n", race_names[i], races[i], race_names[i]); } for(i = 0; i <= DRUID; ++i) { if( class_names[i] != NULL ) fprintf(f, " <%s>%u</%s>\n", class_names[i], classes[i], class_names[i]); } fprintf(f, " </statsummary>\n"); Player * plr; uint32 t = (uint32)time(NULL); char otime[100]; { fprintf(f, " <instances>\n"); // need a big buffer.. static char buf[500000]; memset(buf, 0, 500000); // Dump Instance Information //sWorldCreator.BuildXMLStats(buf); sInstanceMgr.BuildXMLStats(buf); fprintf(f, buf); fprintf(f, " </instances>\n"); } { // GM Information fprintf(f, " <gms>\n"); while(!gms.empty()) { plr = gms.front(); gms.pop_front(); if(!plr->bGMTagOn) continue; FillOnlineTime(t - plr->OnlineTime, otime); fprintf(f, " <gmplr>\n"); fprintf(f, " <name>%s</name>\n", plr->GetName()); fprintf(f, " <race>%u</race>\n", plr->getRace()); fprintf(f, " <class>%u</class>\n", (unsigned int)plr->getClass()); fprintf(f, " <gender>%u</gender>\n", (unsigned int)plr->getGender()); fprintf(f, " <pvprank>%u</pvprank>\n", (unsigned int)plr->GetPVPRank()); fprintf(f, " <level>%u</level>\n", (unsigned int)plr->getLevel()); fprintf(f, " <map>%u</map>\n", (unsigned int)plr->GetMapId()); fprintf(f, " <areaid>%u</areaid>\n", (unsigned int)plr->GetAreaID()); fprintf(f, " <ontime>%s</ontime>\n", otime); fprintf(f, " <latency>%u</latency>\n", (unsigned int)plr->GetSession()->GetLatency()); fprintf(f, " <permissions>%s</permissions>\n", plr->GetSession()->GetPermissions()); fprintf(f, " </gmplr>\n"); } fprintf(f, " </gms>\n"); } { fprintf(f, " <sessions>\n"); // Dump Player Information objmgr._playerslock.AcquireReadLock(); HM_NAMESPACE::hash_map<uint32, Player*>::const_iterator itr; for (itr = objmgr._players.begin(); itr != objmgr._players.end(); itr++) { plr = itr->second; if(itr->second->GetSession() && itr->second->IsInWorld()) { FillOnlineTime(t - plr->OnlineTime, otime); fprintf(f, " <plr>\n"); fprintf(f, " <name>%s</name>\n", plr->GetName()); fprintf(f, " <race>%u</race>\n", (unsigned int)plr->getRace()); fprintf(f, " <class>%u</class>\n", (unsigned int)plr->getClass()); fprintf(f, " <gender>%u</gender>\n", (unsigned int)plr->getGender()); fprintf(f, " <pvprank>%u</pvprank>\n", (unsigned int)plr->GetPVPRank()); fprintf(f, " <level>%u</level>\n", (unsigned int)plr->getLevel()); fprintf(f, " <map>%u</map>\n", (unsigned int)plr->GetMapId()); fprintf(f, " <areaid>%u</areaid>\n", (unsigned int)plr->GetAreaID()); //requested by Zdarkside for he's online map. I hope it does not scre up any parser. If so, then make a better one :P fprintf(f, " <xpos>%f</xpos>\n", plr->GetPositionX ()); fprintf(f, " <ypos>%f</ypos>\n", plr->GetPositionY()); fprintf(f, " <ontime>%s</ontime>\n", otime); fprintf(f, " <latency>%u</latency>\n", (unsigned int)plr->GetSession()->GetLatency()); fprintf(f, " </plr>\n"); if(plr->GetSession()->GetPermissionCount() > 0) gms.push_back(plr); } } objmgr._playerslock.ReleaseReadLock(); fprintf(f, " </sessions>\n"); } fprintf(f, "</serverpage>\n"); fclose(f); }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); ObjectGuid lguid = player->GetLootGUID(); Loot* loot = NULL; uint8 lootSlot = 0; recvData >> lootSlot; if (lguid.IsGameObject()) { GameObject* go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } loot = &go->loot; } else if (lguid.IsItem()) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } loot = &pItem->loot; } else if (lguid.IsCorpse()) { Corpse* bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING); if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL); return; } loot = &creature->loot; } player->StoreLootItem(lootSlot, loot); // If player is removing the last LootItem, delete the empty container. if (loot->isLooted() && lguid.IsItem()) player->GetSession()->DoLootRelease(lguid); }
void FocusMagic(uint32 diff) { if (!FOCUSMAGIC || me->getLevel() < 20 || fmCheckTimer > diff || GC_Timer > diff || Rand() < 50 || IsCasting()) return; if (Unit* target = FindAffectedTarget(FOCUSMAGIC, me->GetGUID(), 70, 2)) { fmCheckTimer = 30000; return; } else { Group* pGroup = master->GetGroup(); if (!pGroup) { if (master->getPowerType() == POWER_MANA && !master->HasAura(FOCUSMAGIC) && me->GetExactDist(master) < 30) target = master; } else { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->GetSource(); if (!pPlayer || pPlayer->isDead()) continue; if (me->GetMapId() != pPlayer->GetMapId()) continue; if ((pPlayer->getClass() == CLASS_MAGE || pPlayer->getClass() == CLASS_PRIEST || pPlayer->getClass() == CLASS_SHAMAN || pPlayer->getClass() == CLASS_DRUID || pPlayer->getClass() == CLASS_PALADIN || pPlayer->getClass() == CLASS_WARLOCK) && !pPlayer->HasAura(FOCUSMAGIC) && me->GetExactDist(pPlayer) < 30) { target = pPlayer; break; } } if (!target) { for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* pPlayer = itr->GetSource(); if (!pPlayer || !pPlayer->HaveBot()) continue; if (me->GetMapId() != pPlayer->GetMapId()) continue; for (uint8 i = 0; i != pPlayer->GetMaxNpcBots(); ++i) { Creature* cre = pPlayer->GetBotMap(i)->_Cre(); if (!cre || cre == me || cre->isDead() || cre->getPowerType() != POWER_MANA) continue; if ((cre->GetBotClass() == CLASS_MAGE || cre->GetBotClass() == CLASS_PRIEST || cre->GetBotClass() == CLASS_SHAMAN || cre->GetBotClass() == CLASS_DRUID || cre->GetBotClass() == CLASS_WARLOCK) && !cre->HasAura(FOCUSMAGIC) && me->GetExactDist(cre) < 30) { target = cre; break; } } } } } if (target && doCast(target, FOCUSMAGIC)) { GC_Timer = 500; fmCheckTimer = 30000; return; } } fmCheckTimer = 5000; }