void WorldSession::HandleBattlemasterJoinArena(WorldPacket & recv_data) { sLog->outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); //recv_data.hexlike(); uint64 guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated Group * grp = NULL; recv_data >> guid >> arenaslot >> asGroup >> isRated; // ignore if we already in BG or BG queue if (_player->InBattleground()) return; Creature* unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if (!unit->isBattleMaster()) // it's not battle master return; uint8 arenatype = 0; uint32 arenaRating = 0; uint32 matchmakerRating = 0; switch(arenaslot) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog->outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); return; } //check existance Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(BATTLEGROUND_AA); if (!bg) { sLog->outError("Battleground: template bg (all arenas) not found"); return; } if (sDisableMgr->IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, BATTLEGROUND_AA, NULL)) { ChatHandler(this).PSendSysMessage(LANG_ARENA_DISABLED); return; } BattlegroundTypeId bgTypeId = bg->GetTypeID(); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, arenatype); PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err = ERR_GROUP_JOIN_BATTLEGROUND_FAIL; if (!asGroup) { // check if already in queue if (_player->GetBattlegroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattlegroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); } uint32 ateamId = 0; if (isRated) { ateamId = _player->GetArenaTeamId(arenaslot); // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) ArenaTeam * at = sArenaTeamMgr->GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queueing arenaRating = at->GetRating(); matchmakerRating = at->GetAverageMMR(grp); // the arenateam id must match for everyone in the group if (arenaRating <= 0) arenaRating = 1; } BattlegroundQueue &bgQueue = sBattlegroundMgr->m_BattlegroundQueues[bgQueueTypeId]; if (asGroup) { uint32 avgTime = 0; if (err > 0) { sLog->outDebug("Battleground: arena join as group start"); if (isRated) { sLog->outDebug("Battleground: arena team id %u, leader %s queued with matchmaker rating %u for type %u", _player->GetArenaTeamId(arenaslot), _player->GetName(), matchmakerRating, arenatype); bg->SetRated(true); } else bg->SetRated(false); GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if (!member) continue; WorldPacket data; if (err <= 0) { sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); continue; } // add to queue uint32 queueSlot = member->AddBattlegroundQueueId(bgQueueTypeId); // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); sLog->outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUIDLow(), member->GetName()); } } else { GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, arenatype, isRated, false, arenaRating, matchmakerRating, ateamId); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); sLog->outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUIDLow(), _player->GetName()); } sBattlegroundMgr->ScheduleQueueUpdate(matchmakerRating, arenatype, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }
//this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem(WorldPacket & recv_data) { uint64 auctioneer; uint32 auctionId; recv_data >> auctioneer; recv_data >> auctionId; //sLog.outDebug("Cancel AUCTION AuctionID: %u", auctionId); Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug("WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); if (auction && auction->owner == pl->GetGUIDLow()) { Item *pItem = auctionmgr.GetAItem(auction->item_guidlow); if (pItem) { if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid { uint32 auctionCut = auction->GetAuctionCut(); if (pl->GetMoney() < auctionCut) //player doesn't have enough money, maybe message needed return; //some auctionBidderNotification would be needed, but don't know that parts.. SendAuctionCancelledToBidderMail(auction); pl->ModifyMoney(-int32(auctionCut)); } // Return the item by mail std::ostringstream msgAuctionCanceledOwner; msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str()) .AddItem(pItem) .SendMailTo(pl, auction); } else { sLog.outError("Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow); SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); return; } } else { SendAuctionCommandResult(0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR); //this code isn't possible ... maybe there should be assert sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId); return; } //inform player, that auction is removed SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, AUCTION_OK); // Now remove the auction CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); auction->DeleteFromDB(); uint32 item_template = auction->item_template; auctionmgr.RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction, item_template); }
void TowerDefenseInstanceScript::TowerDefenseMapInstanceScript::HandleEventComplete(TDEventCompleteType completeType) { Player *player = GetPlayer(); if(!player) return; if(!completeType) return; switch(completeType) { case TD_EVENT_COMPLETE_UNFINISHED: { if(IsAwardingFledPlayers()){ UpdatePlayerStats(GetPlayerGUID(), TD_PLAYER_STAT_CURRENT_RESOURCES, GetResources()); SendMailToPlayer(NULL, GetPlayerGUID(), TD_SYSTEM_MSG_MAIL_BODY_EVENT_UNFINISHED, GetResources()); RecordLog("TowerDefense: Player: [%s] has received: [%u] resources due to an unfinished Event Id: [%u].", player->GetName(), GetResources(), GetEventId()); }else{ SendMailToPlayer(NULL, GetPlayerGUID(), TD_SYSTEM_MSG_MAIL_BODY_EVENT_UNFINISHED_FLED, GetResources(), GetCurrentWaveId()); RecordLog("TowerDefense: Player: [%s] was informed that he lost all his unfinished Event Id: [%u] rewards.", player->GetName(), GetResources(), GetEventId()); } UpdatePlayerStats(player->GetGUIDLow(), TD_PLAYER_STAT_EVENTS_UNFINISHED, 1); }break; case TD_EVENT_COMPLETE_QUIT: { if(player->GetSession()->isLogingOut()){ SendMessageToPlayer(TD_SYSTEM_MSG_LOGGING_OUT); return; } if(GetCurrentWaveId() < GetQuitAfterWave()){ uint32 remaining = GetQuitAfterWave() - GetCurrentWaveId(); SendMessageToPlayer(TD_SYSTEM_MSG_MORE_WAVES, remaining); return; } SendMessageToPlayer(TD_SYSTEM_MSG_QUIT_EVENT, GetResources(), GetCurrentWaveId()); UpdatePlayerStats(GetPlayerGUID(), TD_PLAYER_STAT_CURRENT_RESOURCES, GetResources()); UpdatePlayerStats(player->GetGUIDLow(), TD_PLAYER_STAT_EVENTS_LOST, 1); RecordLog("TowerDefense: Player: [%s] has received: [%u] resources after leaving Event Id: [%u].", player->GetName(), GetResources(), GetEventId()); }break; case TD_EVENT_COMPLETE_LOST: { player->PlayDirectSound(TD_ENDEVENT_MUSIC,_player); SendMessageToPlayer(TD_SYSTEM_MSG_LOST_EVENT, GetResources(), GetCurrentWaveId()); UpdatePlayerStats(player->GetGUIDLow(), TD_PLAYER_STAT_EVENTS_LOST, 1); RecordLog("TowerDefense: Player: [%s] was informed that he lost all his Event Id: [%u] rewards.", player->GetName(), GetResources(), GetEventId()); }break; case TD_EVENT_COMPLETE_WON: { SendMessageToPlayer(TD_SYSTEM_MSG_WON_EVENT, GetResources()); UpdatePlayerStats(GetPlayerGUID(), TD_PLAYER_STAT_CURRENT_RESOURCES, GetResources()); UpdatePlayerStats(player->GetGUIDLow(), TD_PLAYER_STAT_EVENTS_WON, 1); RecordLog("TowerDefense: Player: [%s] has won [%u] resources after completing Event Id: [%u].", player->GetName(), GetResources(), GetEventId()); }break; } player->DestroyItemCount(GetItemEntry(),1,true); // destroy the item from the player player->TeleportTo(1, -3673.392090, -4384.723145, 10.026433, 3.879712); // Teleport to a Neutral Mall player->RemoveAllAuras(); // remove all auras set by event player->RemoveAllAttackers(); // remove all attackers SetFinished(true); // finish the event SaveEventData(); // save event information RecordLog("TowerDefense: Player: [%s] has completed Event Id: [%u] and his event data was saved and he was teleported.", player->GetName(), GetEventId()); DeleteEventData(); }
//this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) { uint64 auctioneer, item; uint32 etime, bid, buyout; recv_data >> auctioneer >> item; recv_data >> bid >> buyout >> etime; Player *pl = GetPlayer(); if (!item || !bid || !etime) return; //check for cheaters Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(pCreature->getFaction()); if (!auctionHouseEntry) { sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); return; } sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); // client send time in minutes, convert to common used sec time etime *= MINUTE; sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); // client understand only 3 auction time switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: case 4*MIN_AUCTION_TIME: break; default: return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item *it = pl->GetItemByGuid(item); //do not allow to sell already auctioned items if (auctionmgr.GetAItem(GUID_LOPART(item))) { sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) if (!it) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); return; } if (!it->CanBeTraded()) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); //we have to take deposit : uint32 deposit = auctionmgr.GetAuctionDeposit(auctionHouseEntry, etime, it); if (pl->GetMoney() < deposit) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); return; } if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount()); } pl->ModifyMoney(-int32(deposit)); uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME)); AuctionEntry *AH = new AuctionEntry; AH->Id = objmgr.GenerateAuctionID(); if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) AH->auctioneer = 23442; else AH->auctioneer = GUID_LOPART(auctioneer); AH->item_guidlow = GUID_LOPART(item); AH->item_template = it->GetEntry(); AH->owner = pl->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auction_time; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); auctionmgr.AddAItem(it); auctionHouse->AddAuction(AH); pl->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); CharacterDatabase.BeginTransaction(); it->DeleteFromInventoryDB(); it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone AH->SaveToDB(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); }
//this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) { uint64 auctioneer; uint32 auctionId; uint32 price; recv_data >> auctioneer; recv_data >> auctionId >> price; if (!auctionId || !price) return; //check for cheaters Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug("WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject *auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); if (!auction || auction->owner == pl->GetGUIDLow()) { //you cannot bid your own auction: SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); return; } // impossible have online own another character (use this for speedup check in case online owner) Player* auction_owner = objmgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); if (!auction_owner && objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == pl->GetSession()->GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult(0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR); return; } // cheating if (price <= auction->bid || price < auction->startbid) return; // price too low for next bid if not buyout if ((price < auction->buyout || auction->buyout == 0) && price < auction->bid + auction->GetAuctionOutBid()) { //auction has already higher bid, client tests it! return; } if (price > pl->GetMoney()) { //you don't have enought money!, client tests! //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } if (price < auction->buyout || auction->buyout == 0) { if (auction->bidder > 0) { if (auction->bidder == pl->GetGUIDLow()) pl->ModifyMoney(-int32(price - auction->bid)); else { // mail to last bidder and return money SendAuctionOutbiddedMail(auction, price); pl->ModifyMoney(-int32(price)); } } else pl->ModifyMoney(-int32(price)); auction->bidder = pl->GetGUIDLow(); auction->bid = price; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); // after this update we should save player's money ... CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0); } else { //buyout: if (pl->GetGUIDLow() == auction->bidder) pl->ModifyMoney(-int32(auction->buyout - auction->bid)); else { pl->ModifyMoney(-int32(auction->buyout)); if (auction->bidder) //buyout for bidded auction .. SendAuctionOutbiddedMail(auction, auction->buyout); } auction->bidder = pl->GetGUIDLow(); auction->bid = auction->buyout; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); auctionmgr.SendAuctionSalePendingMail(auction); auctionmgr.SendAuctionSuccessfulMail(auction); auctionmgr.SendAuctionWonMail(auction); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); auction->DeleteFromDB(); uint32 item_template = auction->item_template; auctionmgr.RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction, item_template); } CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
void WorldSession::HandleVoidSwapItem(WorldPacket& recvData) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_SWAP_ITEM"); Player* player = GetPlayer(); uint32 newSlot; ObjectGuid npcGuid; ObjectGuid itemId; recvData >> newSlot; npcGuid[2] = recvData.ReadBit(); npcGuid[4] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); itemId[2] = recvData.ReadBit(); itemId[6] = recvData.ReadBit(); itemId[5] = recvData.ReadBit(); npcGuid[1] = recvData.ReadBit(); npcGuid[7] = recvData.ReadBit(); itemId[3] = recvData.ReadBit(); itemId[7] = recvData.ReadBit(); itemId[0] = recvData.ReadBit(); npcGuid[6] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); itemId[1] = recvData.ReadBit(); itemId[4] = recvData.ReadBit(); recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(itemId[3]); recvData.ReadByteSeq(itemId[2]); recvData.ReadByteSeq(itemId[4]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[0]); recvData.ReadByteSeq(itemId[6]); recvData.ReadByteSeq(itemId[1]); recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(itemId[5]); recvData.ReadByteSeq(npcGuid[6]); recvData.ReadByteSeq(itemId[0]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(itemId[7]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (!player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str()); return; } uint8 oldSlot; if (!player->GetVoidStorageItem(itemId, oldSlot)) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidSwapItem - Player (GUID: %u, name: %s) requested swapping an invalid item (slot: %u, itemid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), newSlot, uint64(itemId)); return; } bool usedSrcSlot = player->GetVoidStorageItem(oldSlot) != NULL; // should be always true bool usedDestSlot = player->GetVoidStorageItem(newSlot) != NULL; ObjectGuid itemIdDest; if (usedDestSlot) itemIdDest = player->GetVoidStorageItem(newSlot)->ItemId; if (!player->SwapVoidStorageItem(oldSlot, newSlot)) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INTERNAL_ERROR_1); return; } WorldPacket data(SMSG_VOID_ITEM_SWAP_RESPONSE, 1 + (usedSrcSlot + usedDestSlot) * (1 + 7 + 4)); data.WriteBit(!usedDestSlot); data.WriteBit(!usedSrcSlot); if (usedSrcSlot) { data.WriteBit(itemId[5]); data.WriteBit(itemId[2]); data.WriteBit(itemId[1]); data.WriteBit(itemId[4]); data.WriteBit(itemId[0]); data.WriteBit(itemId[6]); data.WriteBit(itemId[7]); data.WriteBit(itemId[3]); } data.WriteBit(!usedDestSlot); // unk if (usedDestSlot) { data.WriteBit(itemIdDest[7]); data.WriteBit(itemIdDest[3]); data.WriteBit(itemIdDest[4]); data.WriteBit(itemIdDest[0]); data.WriteBit(itemIdDest[5]); data.WriteBit(itemIdDest[1]); data.WriteBit(itemIdDest[2]); data.WriteBit(itemIdDest[6]); } data.WriteBit(!usedSrcSlot); // unk data.FlushBits(); if (usedDestSlot) { data.WriteByteSeq(itemIdDest[4]); data.WriteByteSeq(itemIdDest[6]); data.WriteByteSeq(itemIdDest[5]); data.WriteByteSeq(itemIdDest[2]); data.WriteByteSeq(itemIdDest[3]); data.WriteByteSeq(itemIdDest[1]); data.WriteByteSeq(itemIdDest[7]); data.WriteByteSeq(itemIdDest[0]); } if (usedSrcSlot) { data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[3]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(itemId[1]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(itemId[4]); data.WriteByteSeq(itemId[7]); } if (usedDestSlot) data << uint32(oldSlot); if (usedSrcSlot) data << uint32(newSlot); SendPacket(&data); }
void WorldSession::HandleVoidStorageQuery(WorldPacket& recvData) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_QUERY"); Player* player = GetPlayer(); ObjectGuid npcGuid; npcGuid[4] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[7] = recvData.ReadBit(); npcGuid[6] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); npcGuid[1] = recvData.ReadBit(); npcGuid[2] = recvData.ReadBit(); recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[6]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(npcGuid[0]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(npcGuid[2]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageQuery - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (!player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageQuery - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str()); return; } uint8 count = 0; for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) if (player->GetVoidStorageItem(i)) ++count; WorldPacket data(SMSG_VOID_STORAGE_CONTENTS, 2 * count + (14 + 4 + 4 + 4 + 4) * count); data.WriteBits(count, 8); ByteBuffer itemData((14 + 4 + 4 + 4 + 4) * count); for (uint8 i = 0; i < VOID_STORAGE_MAX_SLOT; ++i) { VoidStorageItem* item = player->GetVoidStorageItem(i); if (!item) continue; ObjectGuid itemId = item->ItemId; ObjectGuid creatorGuid = item->CreatorGuid; data.WriteBit(creatorGuid[3]); data.WriteBit(itemId[5]); data.WriteBit(creatorGuid[6]); data.WriteBit(creatorGuid[1]); data.WriteBit(itemId[1]); data.WriteBit(itemId[3]); data.WriteBit(itemId[6]); data.WriteBit(creatorGuid[5]); data.WriteBit(creatorGuid[2]); data.WriteBit(itemId[2]); data.WriteBit(creatorGuid[4]); data.WriteBit(itemId[0]); data.WriteBit(itemId[4]); data.WriteBit(itemId[7]); data.WriteBit(creatorGuid[0]); data.WriteBit(creatorGuid[7]); itemData.WriteByteSeq(creatorGuid[3]); itemData << uint32(item->ItemSuffixFactor); itemData.WriteByteSeq(creatorGuid[4]); itemData << uint32(i); itemData.WriteByteSeq(itemId[0]); itemData.WriteByteSeq(itemId[6]); itemData.WriteByteSeq(creatorGuid[0]); itemData << uint32(item->ItemRandomPropertyId); itemData.WriteByteSeq(itemId[4]); itemData.WriteByteSeq(itemId[5]); itemData.WriteByteSeq(itemId[2]); itemData.WriteByteSeq(creatorGuid[2]); itemData.WriteByteSeq(creatorGuid[6]); itemData.WriteByteSeq(itemId[1]); itemData.WriteByteSeq(itemId[3]); itemData.WriteByteSeq(creatorGuid[5]); itemData.WriteByteSeq(creatorGuid[7]); itemData << uint32(item->ItemEntry); itemData.WriteByteSeq(itemId[7]); } data.FlushBits(); data.append(itemData); SendPacket(&data); }
void WorldSession::HandleVoidStorageTransfer(WorldPacket& recvData) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_TRANSFER"); Player* player = GetPlayer(); // Read everything ObjectGuid npcGuid; npcGuid[1] = recvData.ReadBit(); uint32 countDeposit = recvData.ReadBits(26); if (countDeposit > 9) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countDeposit); return; } std::vector<ObjectGuid> itemGuids(countDeposit); for (uint32 i = 0; i < countDeposit; ++i) { itemGuids[i][4] = recvData.ReadBit(); itemGuids[i][6] = recvData.ReadBit(); itemGuids[i][7] = recvData.ReadBit(); itemGuids[i][0] = recvData.ReadBit(); itemGuids[i][1] = recvData.ReadBit(); itemGuids[i][5] = recvData.ReadBit(); itemGuids[i][3] = recvData.ReadBit(); itemGuids[i][2] = recvData.ReadBit(); } npcGuid[2] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[6] = recvData.ReadBit(); npcGuid[4] = recvData.ReadBit(); uint32 countWithdraw = recvData.ReadBits(26); if (countWithdraw > 9) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to withdraw more than 9 items (%u).", player->GetGUIDLow(), player->GetName().c_str(), countWithdraw); return; } std::vector<ObjectGuid> itemIds(countWithdraw); for (uint32 i = 0; i < countWithdraw; ++i) { itemIds[i][4] = recvData.ReadBit(); itemIds[i][7] = recvData.ReadBit(); itemIds[i][1] = recvData.ReadBit(); itemIds[i][0] = recvData.ReadBit(); itemIds[i][2] = recvData.ReadBit(); itemIds[i][3] = recvData.ReadBit(); itemIds[i][5] = recvData.ReadBit(); itemIds[i][6] = recvData.ReadBit(); } npcGuid[7] = recvData.ReadBit(); for (uint32 i = 0; i < countDeposit; ++i) { recvData.ReadByteSeq(itemGuids[i][6]); recvData.ReadByteSeq(itemGuids[i][1]); recvData.ReadByteSeq(itemGuids[i][0]); recvData.ReadByteSeq(itemGuids[i][2]); recvData.ReadByteSeq(itemGuids[i][4]); recvData.ReadByteSeq(itemGuids[i][5]); recvData.ReadByteSeq(itemGuids[i][3]); recvData.ReadByteSeq(itemGuids[i][7]); } recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[6]); for (uint32 i = 0; i < countWithdraw; ++i) { recvData.ReadByteSeq(itemIds[i][3]); recvData.ReadByteSeq(itemIds[i][0]); recvData.ReadByteSeq(itemIds[i][1]); recvData.ReadByteSeq(itemIds[i][6]); recvData.ReadByteSeq(itemIds[i][2]); recvData.ReadByteSeq(itemIds[i][7]); recvData.ReadByteSeq(itemIds[i][5]); recvData.ReadByteSeq(itemIds[i][4]); } recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(npcGuid[4]); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[0]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (!player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) queried void storage without unlocking it.", player->GetGUIDLow(), player->GetName().c_str()); return; } if (itemGuids.size() > player->GetNumOfVoidStorageFreeSlots()) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_FULL); return; } uint32 freeBagSlots = 0; if (itemIds.size() != 0) { // make this a Player function for (uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if (Bag* bag = player->GetBagByPos(i)) freeBagSlots += bag->GetFreeSlots(); for (uint8 i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) if (!player->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) ++freeBagSlots; } if (itemIds.size() > freeBagSlots) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); return; } if (!player->HasEnoughMoney(uint64(itemGuids.size() * VOID_STORAGE_STORE_ITEM))) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NOT_ENOUGH_MONEY); return; } std::pair<VoidStorageItem, uint8> depositItems[VOID_STORAGE_MAX_DEPOSIT]; uint8 depositCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemGuids.begin(); itr != itemGuids.end(); ++itr) { Item* item = player->GetItemByGuid(*itr); if (!item) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) wants to deposit an invalid item (item guid: " UI64FMTD ").", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); continue; } VoidStorageItem itemVS(sObjectMgr->GenerateVoidStorageItemId(), item->GetEntry(), item->GetUInt64Value(ITEM_FIELD_CREATOR), item->GetItemRandomPropertyId(), item->GetItemSuffixFactor()); uint8 slot = player->AddVoidStorageItem(itemVS); depositItems[depositCount++] = std::make_pair(itemVS, slot); player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); } int64 cost = depositCount * VOID_STORAGE_STORE_ITEM; player->ModifyMoney(-cost); VoidStorageItem withdrawItems[VOID_STORAGE_MAX_WITHDRAW]; uint8 withdrawCount = 0; for (std::vector<ObjectGuid>::iterator itr = itemIds.begin(); itr != itemIds.end(); ++itr) { uint8 slot; VoidStorageItem* itemVS = player->GetVoidStorageItem(*itr, slot); if (!itemVS) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) tried to withdraw an invalid item (id: " UI64FMTD ")", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); continue; } ItemPosCountVec dest; InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, itemVS->ItemEntry, 1); if (msg != EQUIP_ERR_OK) { SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_INVENTORY_FULL); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageTransfer - Player (GUID: %u, name: %s) couldn't withdraw item id " UI64FMTD " because inventory was full.", player->GetGUIDLow(), player->GetName().c_str(), uint64(*itr)); return; } Item* item = player->StoreNewItem(dest, itemVS->ItemEntry, true, itemVS->ItemRandomPropertyId); item->SetUInt64Value(ITEM_FIELD_CREATOR, uint64(itemVS->CreatorGuid)); item->SetBinding(true); player->SendNewItem(item, 1, false, false, false); withdrawItems[withdrawCount++] = *itemVS; player->DeleteVoidStorageItem(slot); } WorldPacket data(SMSG_VOID_STORAGE_TRANSFER_CHANGES, ((5 + 5 + (7 + 7) * depositCount + 7 * withdrawCount) / 8) + 7 * withdrawCount + (7 + 7 + 4 * 4) * depositCount); data.WriteBits(depositCount, 5); data.WriteBits(withdrawCount, 5); for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data.WriteBit(creatorGuid[7]); data.WriteBit(itemId[7]); data.WriteBit(itemId[4]); data.WriteBit(creatorGuid[6]); data.WriteBit(creatorGuid[5]); data.WriteBit(itemId[3]); data.WriteBit(itemId[5]); data.WriteBit(creatorGuid[4]); data.WriteBit(creatorGuid[2]); data.WriteBit(creatorGuid[0]); data.WriteBit(creatorGuid[3]); data.WriteBit(creatorGuid[1]); data.WriteBit(itemId[2]); data.WriteBit(itemId[0]); data.WriteBit(itemId[1]); data.WriteBit(itemId[6]); } for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteBit(itemId[1]); data.WriteBit(itemId[7]); data.WriteBit(itemId[3]); data.WriteBit(itemId[5]); data.WriteBit(itemId[6]); data.WriteBit(itemId[2]); data.WriteBit(itemId[4]); data.WriteBit(itemId[0]); } data.FlushBits(); for (uint8 i = 0; i < withdrawCount; ++i) { ObjectGuid itemId = withdrawItems[i].ItemId; data.WriteByteSeq(itemId[3]); data.WriteByteSeq(itemId[1]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(itemId[7]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); } for (uint8 i = 0; i < depositCount; ++i) { ObjectGuid itemId = depositItems[i].first.ItemId; ObjectGuid creatorGuid = depositItems[i].first.CreatorGuid; data << uint32(depositItems[i].first.ItemSuffixFactor); data.WriteByteSeq(itemId[6]); data.WriteByteSeq(itemId[4]); data.WriteByteSeq(creatorGuid[4]); data.WriteByteSeq(itemId[2]); data.WriteByteSeq(creatorGuid[1]); data.WriteByteSeq(creatorGuid[3]); data.WriteByteSeq(itemId[3]); data.WriteByteSeq(creatorGuid[0]); data.WriteByteSeq(itemId[0]); data.WriteByteSeq(creatorGuid[6]); data.WriteByteSeq(itemId[5]); data.WriteByteSeq(creatorGuid[5]); data.WriteByteSeq(creatorGuid[7]); data << uint32(depositItems[i].first.ItemEntry); data.WriteByteSeq(itemId[1]); data << uint32(depositItems[i].second); // slot data.WriteByteSeq(creatorGuid[2]); data.WriteByteSeq(itemId[7]); data << uint32(depositItems[i].first.ItemRandomPropertyId); } SendPacket(&data); SendVoidStorageTransferResult(VOID_TRANSFER_ERROR_NO_ERROR); }
void WorldSession::HandleVoidStorageUnlock(WorldPacket& recvData) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_VOID_STORAGE_UNLOCK"); Player* player = GetPlayer(); ObjectGuid npcGuid; npcGuid[4] = recvData.ReadBit(); npcGuid[5] = recvData.ReadBit(); npcGuid[3] = recvData.ReadBit(); npcGuid[0] = recvData.ReadBit(); npcGuid[2] = recvData.ReadBit(); npcGuid[1] = recvData.ReadBit(); npcGuid[7] = recvData.ReadBit(); npcGuid[6] = recvData.ReadBit(); recvData.ReadByteSeq(npcGuid[7]); recvData.ReadByteSeq(npcGuid[1]); recvData.ReadByteSeq(npcGuid[2]); recvData.ReadByteSeq(npcGuid[3]); recvData.ReadByteSeq(npcGuid[5]); recvData.ReadByteSeq(npcGuid[0]); recvData.ReadByteSeq(npcGuid[6]); recvData.ReadByteSeq(npcGuid[4]); Creature* unit = player->GetNPCIfCanInteractWith(npcGuid, UNIT_NPC_FLAG_VAULTKEEPER); if (!unit) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageUnlock - Unit (GUID: %u) not found or player can't interact with it.", GUID_LOPART(npcGuid)); return; } if (player->IsVoidStorageUnlocked()) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: HandleVoidStorageUnlock - Player (GUID: %u, name: %s) tried to unlock void storage a 2nd time.", player->GetGUIDLow(), player->GetName().c_str()); return; } player->ModifyMoney(-int64(VOID_STORAGE_UNLOCK)); player->UnlockVoidStorage(); }
void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); //recv_data.hexlike(); ObjectGuid guid; // arena Battlemaster guid uint8 arenaslot; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated recv_data >> guid >> arenaslot >> asGroup >> isRated; // ignore if we already in BG or BG queue if (_player->InBattleGround()) return; Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if(!unit->isBattleMaster()) // it's not battle master return; uint8 arenatype = 0; uint32 arenaRating = 0; switch(arenaslot) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog.outError("Unknown arena slot %u at HandleBattlemasterJoinArena()", arenaslot); return; } // check existance BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA); if (!bg) { sLog.outError("Battleground: template bg (all arenas) not found"); return; } BattleGroundTypeId bgTypeId = bg->GetTypeID(); BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); BattleGroundBracketId bgBracketId = _player->GetBattleGroundBracketIdFromLevel(bgTypeId); Group * grp = NULL; // check queue conditions if (!asGroup) { // you can't join in this way by client if (isRated) return; // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, arenaslot); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } uint32 ateamId = 0; if (isRated) { ateamId = _player->GetArenaTeamId(arenaslot); // check real arena team existence only here (if it was moved to group->CanJoin .. () then we would have to get it twice) ArenaTeam * at = sObjectMgr.GetArenaTeamById(ateamId); if (!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queue arenaRating = at->GetRating(); // the arena team id must match for everyone in the group // get the personal ratings for queue uint32 avg_pers_rating = 0; for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); // calc avg personal rating avg_pers_rating += member->GetArenaPersonalRating(arenaslot); } if (arenatype) avg_pers_rating /= arenatype; // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating if (avg_pers_rating + 150 < arenaRating) arenaRating = avg_pers_rating; } BattleGroundQueue &bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (asGroup) { DEBUG_LOG("Battleground: arena join as group start"); if (isRated) DEBUG_LOG("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(arenaslot),_player->GetName(),arenaRating,arenatype); GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bgBracketId, arenatype, isRated, false, arenaRating, ateamId); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } DEBUG_LOG("Battleground: arena join as group end"); //announce to world ... removed } else { GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bgBracketId, arenatype, isRated, false, arenaRating, ateamId); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, arenatype); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(arenaRating, arenatype, bgQueueTypeId, bgTypeId, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); }
void WorldSession::HandleBattlemasterJoinOpcode( WorldPacket & recv_data ) { ObjectGuid guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); return; } BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); DEBUG_LOG( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from %s", guid.GetString().c_str()); // can do this, since it's battleground, not arena BattleGroundQueueTypeId bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); // ignore if player is already in BG if (_player->InBattleGround()) return; Creature *unit = GetPlayer()->GetMap()->GetCreature(guid); if (!unit) return; if (!unit->isBattleMaster()) // it's not battlemaster return; // get bg instance or bg template if instance not found BattleGround *bg = NULL; if (instanceId) bg = sBattleGroundMgr.GetBattleGroundThroughClientInstance(instanceId, bgTypeId); if (!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } BattleGroundBracketId bgBracketId = _player->GetBattleGroundBracketIdFromLevel(bgTypeId); // check queue conditions if (!joinAsGroup) { // check Deserter debuff if (!_player->CanJoinToBattleground()) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << uint32(0xFFFFFFFE); _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if (!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = sWorld.getConfig(CONFIG_UINT32_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH) && (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized BattleGroundQueue& bgQueue = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId]; if (joinAsGroup) { DEBUG_LOG("Battleground: the following players are joining as group:"); GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bgBracketId, 0, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } DEBUG_LOG("Battleground: group end"); } else { GroupQueueInfo * ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bgBracketId, 0, false, isPremade, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType); SendPacket(&data); DEBUG_LOG("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } sBattleGroundMgr.ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, _player->GetBattleGroundBracketIdFromLevel(bgTypeId)); }
//this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_REMOVE_ITEM"); uint64 auctioneer; uint32 auctionId; recvData >> auctioneer; recvData >> auctionId; //sLog->outDebug("Cancel AUCTION AuctionID: %u", auctionId); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (auction && auction->owner == player->GetGUIDLow()) { Item* pItem = sAuctionMgr->GetAItem(auction->itemGUIDLow); if (pItem) { if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid { uint32 auctionCut = auction->GetAuctionCut(); if (!player->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed return; //some auctionBidderNotification would be needed, but don't know that parts.. sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans); player->ModifyMoney(-int32(auctionCut)); } // item will deleted or added to received mail list MailDraft(auction->BuildAuctionMailSubject(AUCTION_CANCELED), AuctionEntry::BuildAuctionMailBody(0, 0, auction->buyout, auction->deposit, 0)) .AddItem(pItem) .SendMailTo(trans, player, auction, MAIL_CHECK_MASK_COPIED); } else { sLog->outError(LOG_FILTER_NETWORKIO, "Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->itemGUIDLow); SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR); return; } } else { SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR); //this code isn't possible ... maybe there should be assert sLog->outError(LOG_FILTER_NETWORKIO, "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUIDLow(), auctionId); return; } //inform player, that auction is removed SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, ERR_AUCTION_OK); // Now remove the auction player->SaveInventoryAndGoldToDB(trans); auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); uint32 itemEntry = auction->itemEntry; sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction, itemEntry); }
//this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID"); uint64 auctioneer; uint32 auctionId; uint32 price; recvData >> auctioneer; recvData >> auctionId >> price; if (!auctionId || !price) return; //check for cheaters Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); if (!auction || auction->owner == player->GetGUIDLow()) { //you cannot bid your own auction: SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; } // impossible have online own another character (use this for speedup check in case online owner) Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == player->GetSession()->GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; } // cheating if (price <= auction->bid || price < auction->startbid) return; // price too low for next bid if not buyout if ((price < auction->buyout || auction->buyout == 0) && price < auction->bid + auction->GetAuctionOutBid()) { //auction has already higher bid, client tests it! return; } if (!player->HasEnoughMoney(price)) { //you don't have enought money!, client tests! //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (price < auction->buyout || auction->buyout == 0) { if (auction->bidder > 0) { if (auction->bidder == player->GetGUIDLow()) player->ModifyMoney(-int32(price - auction->bid)); else { // mail to last bidder and return money sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans); player->ModifyMoney(-int32(price)); } } else player->ModifyMoney(-int32(price)); auction->bidder = player->GetGUIDLow(); auction->bid = price; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_AUCTION_BID); stmt->setUInt32(0, auction->bidder); stmt->setUInt32(1, auction->bid); stmt->setUInt32(2, auction->Id); trans->Append(stmt); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK, 0); } else { //buyout: if (player->GetGUIDLow() == auction->bidder) player->ModifyMoney(-int32(auction->buyout - auction->bid)); else { player->ModifyMoney(-int32(auction->buyout)); if (auction->bidder) //buyout for bidded auction .. sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); } auction->bidder = player->GetGUIDLow(); auction->bid = auction->buyout; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); //- Mails must be under transaction control too to prevent data loss sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK); auction->DeleteFromDB(trans); uint32 itemEntry = auction->itemEntry; sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction, itemEntry); } player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) { uint64 guid; Player* player; Player* plTarget; recvPacket >> guid; if (!GetPlayer()->duel) // ignore accept from duel-sender return; player = GetPlayer(); plTarget = player->duel->opponent; if (player == player->duel->initiator || !plTarget || player == plTarget || player->duel->startTime != 0 || plTarget->duel->startTime != 0) return; //TC_LOG_DEBUG(LOG_FILTER_PACKETIO, "WORLD: Received CMSG_DUEL_ACCEPTED"); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Player 1 is: %u (%s)", player->GetGUIDLow(), player->GetName().c_str()); TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Player 2 is: %u (%s)", plTarget->GetGUIDLow(), plTarget->GetName().c_str()); time_t now = time(NULL); player->duel->startTimer = now; plTarget->duel->startTimer = now; // Reset Duel Cooldowns, Hp, Mana, Rage and Runic Power. // Elwynn Forest Durotar Circle of Wills Astranaar if (player->GetAreaId() == 12 || player->GetAreaId() == 14 || player->GetAreaId() == 4570 || player->GetAreaId() == 415) { player->SetHealth(player->GetMaxHealth()); plTarget->SetHealth(plTarget->GetMaxHealth()); player->RemoveArenaSpellCooldowns(true); plTarget->RemoveArenaSpellCooldowns(true); // Debuffs player->RemoveAura(57723); player->RemoveAura(57724); player->RemoveAura(25771); player->RemoveAura(41425); player->RemoveAura(61987); player->RemoveAura(66233); player->RemoveAura(11196); plTarget->RemoveAura(57723); plTarget->RemoveAura(57724); plTarget->RemoveAura(25771); plTarget->RemoveAura(41425); plTarget->RemoveAura(61987); plTarget->RemoveAura(66233); plTarget->RemoveAura(11196); if (player->getPowerType() == POWER_MANA) player->SetPower(POWER_MANA, player->GetMaxPower(POWER_MANA)); if (plTarget->getPowerType() == POWER_MANA) plTarget->SetPower(POWER_MANA, plTarget->GetMaxPower(POWER_MANA)); } if (player->getPowerType() == POWER_RAGE) player->SetPower(POWER_RAGE, 0); if (plTarget->getPowerType() == POWER_RAGE) plTarget->SetPower(POWER_RAGE, 0); if (player->getPowerType() == POWER_RUNIC_POWER) player->SetPower(POWER_RUNIC_POWER, 0); if (plTarget->getPowerType() == POWER_RUNIC_POWER) plTarget->SetPower(POWER_RUNIC_POWER, 0); player->SendDuelCountdown(3000); plTarget->SendDuelCountdown(3000); }
void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+4+4+1); uint64 guid; uint32 bgTypeId; uint32 instanceId; uint8 joinAsGroup; Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group if(bgTypeId >= MAX_BATTLEGROUND_TYPES) { sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); return; } sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); // can do this, since it's battleground, not arena uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); // ignore if player is already in BG if(_player->InBattleGround()) return; Creature *unit = ObjectAccessor::GetCreature(*_player, guid); if(!unit) return; if(!unit->isBattleMaster()) // it's not battlemaster return; // get bg instance or bg template if instance not found BattleGround * bg = 0; if(instanceId) BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { sLog.outError("Battleground: no available bg / template found"); return; } // check queueing conditions if(!joinAsGroup) { // check Deserter debuff if( !_player->CanJoinToBattleground() ) { WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); data << (uint32) 0xFFFFFFFE; _player->GetSession()->SendPacket(&data); return; } // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if(!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if(!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } // if we're here, then the conditions to join a bg are met. We can proceed in joining. // _player->GetGroup() was already checked, grp is already initialized if(joinAsGroup /* && _player->GetGroup()*/) { sLog.outDebug("Battleground: the following players are joining as group:"); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; // this should never happen uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: group end"); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); if(!ginfo->IsInvitedToBGInstanceGUID) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); if(!ginfo->IsInvitedToBGInstanceGUID) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } }
void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8+1+1+1); sLog.outDebug("WORLD: CMSG_BATTLEMASTER_JOIN_ARENA"); recv_data.hexlike(); // ignore if we already in BG or BG queue if(_player->InBattleGround()) return; uint64 guid; // arena Battlemaster guid uint8 type; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated Group * grp; recv_data >> guid >> type >> asGroup >> isRated; Creature *unit = ObjectAccessor::GetCreature(*_player, guid); if(!unit) return; if(!unit->isBattleMaster()) // it's not battle master return; uint8 arenatype = 0; uint32 arenaRating = 0; switch(type) { case 0: arenatype = ARENA_TYPE_2v2; break; case 1: arenatype = ARENA_TYPE_3v3; break; case 2: arenatype = ARENA_TYPE_5v5; break; default: sLog.outError("Unknown arena type %u at HandleBattleGroundArenaJoin()", type); return; } //check existance BattleGround* bg = NULL; if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) ) { sLog.outError("Battleground: template bg (all arenas) not found"); return; } uint8 bgTypeId = bg->GetTypeID(); uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); // check queueing conditions if(!asGroup) { // check if already in queue if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) //player is already in this queue return; // check if has free queue slots if(!_player->HasFreeBattleGroundQueueId()) return; } else { grp = _player->GetGroup(); // no group found, error if(!grp) return; uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type); if (err != BG_JOIN_ERR_OK) { SendBattleGroundOrArenaJoinError(err); return; } } uint32 ateamId = 0; if(isRated) { ateamId = _player->GetArenaTeamId(type); // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); if(!at) { _player->GetSession()->SendNotInArenaTeamPacket(arenatype); return; } // get the team rating for queueing arenaRating = at->GetRating(); // the arenateam id must match for everyone in the group // get the personal ratings for queueing uint32 avg_pers_rating = 0; for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); // calc avg personal rating avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5); } if( arenatype ) avg_pers_rating /= arenatype; // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating if(avg_pers_rating + 150 < arenaRating) arenaRating = avg_pers_rating; } if(asGroup) { GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId); sLog.outDebug("Battleground: arena join as group start"); if(isRated) sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } sLog.outDebug("Battleground: arena join as group end"); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); if(isRated) sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); SendPacket(&data); GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } }