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 WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recv_data) { uint8 slotid; ObjectGuid lootguid; ObjectGuid target_playerguid; recv_data >> lootguid >> slotid >> target_playerguid; if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetObjectGuid()) { _player->SendLootRelease(GetPlayer()->GetLootGuid()); return; } Player* target = ObjectAccessor::FindPlayer(target_playerguid); if (!target) return; DEBUG_LOG("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = %s [%s].", target_playerguid.GetString().c_str(), target->GetName()); if (_player->GetLootGuid() != lootguid) return; Loot* pLoot = NULL; if (lootguid.IsCreatureOrVehicle()) { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lootguid); if (!pCreature) return; pLoot = &pCreature->loot; } else if (lootguid.IsGameObject()) { GameObject* pGO = GetPlayer()->GetMap()->GetGameObject(lootguid); if (!pGO) return; pLoot = &pGO->loot; } else return; if (slotid > pLoot->items.size()) { DEBUG_LOG("AutoLootItem: Player %s might be using a hack! (slot %d, size " SIZEFMTD ")", GetPlayer()->GetName(), slotid, pLoot->items.size()); return; } LootItem& item = pLoot->items[slotid]; ItemPosCountVec dest; InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count); if (msg != EQUIP_ERR_OK) { target->SendEquipError(msg, NULL, NULL, item.itemid); // send duplicate of error massage to master looter _player->SendEquipError(msg, NULL, NULL, item.itemid); return; } // now move item from loot to target inventory Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId); target->SendNewItem(newitem, uint32(item.count), false, false, true); target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, pLoot->loot_type, item.count); target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count); // mark as looted item.count = 0; item.is_looted = true; pLoot->NotifyItemRemoved(slotid); --pLoot->unlootedCount; }
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::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket*/) { DEBUG_LOG("WORLD: Received CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY"); uint32 count = 0; WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4); data << uint32(count); // placeholder for(GuidSet::const_iterator itr = _player->GetClientGuids().begin(); itr != _player->GetClientGuids().end(); ++itr) { uint8 dialogStatus = DIALOG_STATUS_NONE; ObjectGuid guid = *itr; if (guid.IsEmpty()) continue; if (guid.IsAnyTypeCreature()) { // need also pet quests case support Creature* questgiver = GetPlayer()->GetMap() ? GetPlayer()->GetMap()->GetAnyTypeCreature(guid) : NULL; if (!questgiver || questgiver->IsHostileTo(_player)) continue; if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) continue; dialogStatus = sScriptMgr.GetDialogStatus(_player, questgiver); if (dialogStatus == DIALOG_STATUS_UNDEFINED) dialogStatus = getDialogStatus(_player, questgiver, DIALOG_STATUS_NONE); data << guid; data << uint8(dialogStatus); ++count; } else if (guid.IsGameObject()) { GameObject* questgiver = GetPlayer()->GetMap() ? GetPlayer()->GetMap()->GetGameObject(guid) : NULL; if (!questgiver) continue; if (questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) continue; dialogStatus = sScriptMgr.GetDialogStatus(_player, questgiver); if (dialogStatus == DIALOG_STATUS_UNDEFINED) dialogStatus = getDialogStatus(_player, questgiver, DIALOG_STATUS_NONE); data << guid; data << uint8(dialogStatus); ++count; } } data.put<uint32>(0, count); // write real count SendPacket(&data); }
bool EffectScriptEffect(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget, ObjectGuid originalCasterGuid) override { if ((uiSpellId == SPELL_INTROSPECTION_BLUE || uiSpellId == SPELL_INTROSPECTION_GREEN || uiSpellId == SPELL_INTROSPECTION_RED || uiSpellId == SPELL_INTROSPECTION_YELLOW) && uiEffIndex == EFFECT_INDEX_1) { if (pCreatureTarget->GetEntry() == NPC_SIMON_GAME_BUNNY && pCaster->GetTypeId() == TYPEID_PLAYER && originalCasterGuid.IsGameObject()) { pCreatureTarget->AI()->SendAIEvent(AI_EVENT_CUSTOM_C, pCaster, pCreatureTarget, uiSpellId); } return true; } return false; }
void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recv_data) { uint8 slotid; ObjectGuid lootguid; ObjectGuid target_playerguid; recv_data >> lootguid >> slotid >> target_playerguid; if (!_player->GetGroup() || _player->GetGroup()->GetLooterGuid() != _player->GetObjectGuid()) { _player->SendLootRelease(GetPlayer()->GetLootGuid()); return; } Player* target = sObjectAccessor.FindPlayer(target_playerguid); if (!target) { return; } DEBUG_LOG("WorldSession::HandleLootMasterGiveOpcode (CMSG_LOOT_MASTER_GIVE, 0x02A3) Target = %s [%s].", target_playerguid.GetString().c_str(), target->GetName()); if (_player->GetLootGuid() != lootguid) { return; } Loot* pLoot = NULL; if (lootguid.IsCreature()) { Creature* pCreature = GetPlayer()->GetMap()->GetCreature(lootguid); if (!pCreature) { return; } pLoot = &pCreature->loot; } else if (lootguid.IsGameObject()) { GameObject* pGO = GetPlayer()->GetMap()->GetGameObject(lootguid); if (!pGO) { return; } pLoot = &pGO->loot; } else { return; } if (slotid > pLoot->items.size()) { DEBUG_LOG("AutoLootItem: Player %s might be using a hack! (slot %d, size " SIZEFMTD ")", GetPlayer()->GetName(), slotid, pLoot->items.size()); return; } LootItem& item = pLoot->items[slotid]; ItemPosCountVec dest; InventoryResult msg = target->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, item.itemid, item.count); if (msg != EQUIP_ERR_OK) { // Assign winner to the item, avoiding other member picks it up. item.winner = target->GetObjectGuid(); target->SendEquipError(msg, NULL, NULL, item.itemid); pLoot->NotifyItemRemoved(slotid); return; } // now move item from loot to target inventory Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId); target->SendNewItem(newitem, uint32(item.count), false, false, true); // Used by Eluna #ifdef ENABLE_ELUNA sEluna->OnLootItem(target, newitem, item.count, lootguid); #endif /* ENABLE_ELUNA */ // mark as looted item.count = 0; item.is_looted = true; pLoot->NotifyItemRemoved(slotid); --pLoot->unlootedCount; }
void PlayerbotMgr::HandleMasterIncomingPacket(const WorldPacket& packet) { switch (packet.GetOpcode()) { case CMSG_ACTIVATETAXI: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; std::vector<uint32> nodes; nodes.resize(2); uint8 delay = 9; p >> guid >> nodes[0] >> nodes[1]; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_ACTIVATETAXI from %d to %d", nodes[0], nodes[1]); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { delay = delay + 3; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) continue; Unit *target = ObjectAccessor::GetUnit(*bot, guid); bot->GetPlayerbotAI()->SetIgnoreUpdateTime(delay); bot->GetMotionMaster()->Clear(true); bot->GetMotionMaster()->MoveFollow(target, INTERACTION_DISTANCE, bot->GetOrientation()); bot->GetPlayerbotAI()->GetTaxi(guid, nodes); } return; } case CMSG_ACTIVATETAXIEXPRESS: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; uint32 node_count; uint8 delay = 9; p >> guid >> node_count; std::vector<uint32> nodes; for (uint32 i = 0; i < node_count; ++i) { uint32 node; p >> node; nodes.push_back(node); } if (nodes.empty()) return; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_ACTIVATETAXIEXPRESS from %d to %d", nodes.front(), nodes.back()); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { delay = delay + 3; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) continue; Unit *target = ObjectAccessor::GetUnit(*bot, guid); bot->GetPlayerbotAI()->SetIgnoreUpdateTime(delay); bot->GetMotionMaster()->Clear(true); bot->GetMotionMaster()->MoveFollow(target, INTERACTION_DISTANCE, bot->GetOrientation()); bot->GetPlayerbotAI()->GetTaxi(guid, nodes); } return; } case CMSG_MOVE_SPLINE_DONE: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_MOVE_SPLINE_DONE"); WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; // used only for proper packet read MovementInfo movementInfo; // used only for proper packet read p >> guid.ReadAsPacked(); p >> movementInfo; p >> Unused<uint32>(); // unk for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) return; // in taxi flight packet received in 2 case: // 1) end taxi path in far (multi-node) flight // 2) switch from one map to other in case multi-map taxi path // we need process only (1) uint32 curDest = bot->m_taxi.GetTaxiDestination(); if (!curDest) return; TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest); // far teleport case if (curDestNode && curDestNode->map_id != bot->GetMapId()) { if (bot->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE) { // short preparations to continue flight FlightPathMovementGenerator* flight = (FlightPathMovementGenerator *) (bot->GetMotionMaster()->top()); flight->Interrupt(*bot); // will reset at map landing flight->SetCurrentNodeAfterTeleport(); TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()]; flight->SkipCurrentNode(); bot->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, bot->GetOrientation()); } return; } uint32 destinationnode = bot->m_taxi.NextTaxiDestination(); if (destinationnode > 0) // if more destinations to go { // current source node for next destination uint32 sourcenode = bot->m_taxi.GetTaxiSource(); // Add to taximask middle hubs in taxicheat mode (to prevent having player with disabled taxicheat and not having back flight path) if (bot->isTaxiCheater()) if (bot->m_taxi.SetTaximaskNode(sourcenode)) { WorldPacket data(SMSG_NEW_TAXI_PATH, 0); bot->GetSession()->SendPacket(&data); } // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_MOVE_SPLINE_DONE Taxi has to go from %u to %u", sourcenode, destinationnode); uint32 mountDisplayId = sObjectMgr.GetTaxiMountDisplayId(sourcenode, bot->GetTeam()); uint32 path, cost; sObjectMgr.GetTaxiPath(sourcenode, destinationnode, path, cost); if (path && mountDisplayId) bot->GetSession()->SendDoFlight(mountDisplayId, path, 1); // skip start fly node else bot->m_taxi.ClearTaxiDestinations(); // clear problematic path and next } else /* std::ostringstream out; out << "Destination reached" << bot->GetName(); ChatHandler ch(m_master); ch.SendSysMessage(out.str().c_str()); */ bot->m_taxi.ClearTaxiDestinations(); // Destination, clear source node } return; } // if master is logging out, log out all bots case CMSG_LOGOUT_REQUEST: { LogoutAllBots(); return; } // If master inspects one of his bots, give the master useful info in chat window // such as inventory that can be equipped case CMSG_INSPECT: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; p >> guid; Player* const bot = GetPlayerBot(guid); if (bot) bot->GetPlayerbotAI()->SendNotEquipList(*bot); return; } // handle emotes from the master //case CMSG_EMOTE: case CMSG_TEXT_EMOTE: { WorldPacket p(packet); p.rpos(0); // reset reader uint32 emoteNum; p >> emoteNum; /* std::ostringstream out; out << "emote is: " << emoteNum; ChatHandler ch(m_master); ch.SendSysMessage(out.str().c_str()); */ switch (emoteNum) { case TEXTEMOTE_BOW: { // Buff anyone who bows before me. Useful for players not in bot's group // How do I get correct target??? //Player* const pPlayer = GetPlayerBot(m_master->GetSelection()); //if (pPlayer->GetPlayerbotAI()->GetClassAI()) // pPlayer->GetPlayerbotAI()->GetClassAI()->BuffPlayer(pPlayer); return; } /* case TEXTEMOTE_BONK: { Player* const pPlayer = GetPlayerBot(m_master->GetSelection()); if (!pPlayer || !pPlayer->GetPlayerbotAI()) return; PlayerbotAI* const pBot = pPlayer->GetPlayerbotAI(); ChatHandler ch(m_master); { std::ostringstream out; out << "time(0): " << time(0) << " m_ignoreAIUpdatesUntilTime: " << pBot->m_ignoreAIUpdatesUntilTime; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "m_TimeDoneEating: " << pBot->m_TimeDoneEating << " m_TimeDoneDrinking: " << pBot->m_TimeDoneDrinking; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "m_CurrentlyCastingSpellId: " << pBot->m_CurrentlyCastingSpellId; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "IsBeingTeleported() " << pBot->GetPlayer()->IsBeingTeleported(); ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; bool tradeActive = (pBot->GetPlayer()->GetTrader()) ? true : false; out << "tradeActive: " << tradeActive; ch.SendSysMessage(out.str().c_str()); } { std::ostringstream out; out << "IsCharmed() " << pBot->getPlayer()->isCharmed(); ch.SendSysMessage(out.str().c_str()); } return; } */ case TEXTEMOTE_EAT: case TEXTEMOTE_DRINK: { for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->Feast(); } return; } // emote to attack selected target case TEXTEMOTE_POINT: { ObjectGuid attackOnGuid = m_master->GetSelectionGuid(); if (!attackOnGuid) return; Unit* thingToAttack = ObjectAccessor::GetUnit(*m_master, attackOnGuid); if (!thingToAttack) return; Player *bot = 0; for (PlayerBotMap::iterator itr = m_playerBots.begin(); itr != m_playerBots.end(); ++itr) { bot = itr->second; if (!bot->IsFriendlyTo(thingToAttack) && bot->IsWithinLOSInMap(thingToAttack)) bot->GetPlayerbotAI()->GetCombatTarget(thingToAttack); } return; } // emote to stay case TEXTEMOTE_STAND: { Player* const bot = GetPlayerBot(m_master->GetSelectionGuid()); if (bot) bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_STAY); else for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_STAY); } return; } // 324 is the followme emote (not defined in enum) // if master has bot selected then only bot follows, else all bots follow case 324: case TEXTEMOTE_WAVE: { Player* const bot = GetPlayerBot(m_master->GetSelectionGuid()); if (bot) bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_FOLLOW, m_master); else for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->SetMovementOrder(PlayerbotAI::MOVEMENT_FOLLOW, m_master); } return; } } return; } /* EMOTE ends here */ case CMSG_GAMEOBJ_USE: // not sure if we still need this one case CMSG_GAMEOBJ_REPORT_USE: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid objGUID; p >> objGUID; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; GameObject *obj = m_master->GetMap()->GetGameObject(objGUID); if (!obj) return; // add other go types here, i.e.: // GAMEOBJECT_TYPE_CHEST - loot quest items of chest if (obj->GetGoType() == GAMEOBJECT_TYPE_QUESTGIVER) { bot->GetPlayerbotAI()->TurnInQuests(obj); // auto accept every available quest this NPC has bot->PrepareQuestMenu(objGUID); QuestMenu& questMenu = bot->PlayerTalkClass->GetQuestMenu(); for (uint32 iI = 0; iI < questMenu.MenuItemCount(); ++iI) { QuestMenuItem const& qItem = questMenu.GetItem(iI); uint32 questID = qItem.m_qId; if (!bot->GetPlayerbotAI()->AddQuest(questID, obj)) DEBUG_LOG("Couldn't take quest"); } } } } break; case CMSG_QUESTGIVER_HELLO: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid npcGUID; p >> npcGUID; WorldObject* pNpc = m_master->GetMap()->GetWorldObject(npcGUID); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->TurnInQuests(pNpc); } return; } // if master accepts a quest, bots should also try to accept quest case CMSG_QUESTGIVER_ACCEPT_QUEST: { WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid guid; uint32 quest; uint32 unk1; p >> guid >> quest >> unk1; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_QUESTGIVER_ACCEPT_QUEST npc = %s, quest = %u, unk1 = %u", guid.GetString().c_str(), quest, unk1); Quest const* qInfo = sObjectMgr.GetQuestTemplate(quest); if (qInfo) for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (bot->GetQuestStatus(quest) == QUEST_STATUS_COMPLETE) bot->GetPlayerbotAI()->TellMaster("I already completed that quest."); else if (!bot->CanTakeQuest(qInfo, false)) { if (!bot->SatisfyQuestStatus(qInfo, false)) bot->GetPlayerbotAI()->TellMaster("I already have that quest."); else bot->GetPlayerbotAI()->TellMaster("I can't take that quest."); } else if (!bot->SatisfyQuestLog(false)) bot->GetPlayerbotAI()->TellMaster("My quest log is full."); else if (!bot->CanAddQuest(qInfo, false)) bot->GetPlayerbotAI()->TellMaster("I can't take that quest because it requires that I take items, but my bags are full!"); else { p.rpos(0); // reset reader bot->GetSession()->HandleQuestgiverAcceptQuestOpcode(p); bot->GetPlayerbotAI()->TellMaster("Got the quest."); // build needed items if quest contains any for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; i++) if (qInfo->ReqItemCount[i] > 0) { bot->GetPlayerbotAI()->SetQuestNeedItems(); break; } // build needed creatures if quest contains any for (int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) if (qInfo->ReqCreatureOrGOCount[i] > 0) { bot->GetPlayerbotAI()->SetQuestNeedCreatures(); break; } } } return; } case CMSG_AREATRIGGER: { WorldPacket p(packet); for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) continue; if (bot->IsWithinDistInMap(GetMaster(), 50)) { p.rpos(0); // reset reader bot->GetSession()->HandleAreaTriggerOpcode(p); } } return; } case CMSG_QUESTGIVER_COMPLETE_QUEST: { WorldPacket p(packet); p.rpos(0); // reset reader uint32 quest; ObjectGuid npcGUID; p >> npcGUID >> quest; // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %s, quest = %u", npcGUID.GetString().c_str(), quest); WorldObject* pNpc = m_master->GetMap()->GetWorldObject(npcGUID); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; bot->GetPlayerbotAI()->TurnInQuests(pNpc); } return; } case CMSG_LOOT_ROLL: { WorldPacket p(packet); //WorldPacket packet for CMSG_LOOT_ROLL, (8+4+1) ObjectGuid Guid; uint32 itemSlot; uint8 rollType; Loot *loot = NULL; p.rpos(0); //reset packet pointer p >> Guid; //guid of the lootable target p >> itemSlot; //loot index p >> rollType; //need,greed or pass on roll if (Guid.IsCreature()) { if (Creature* c = m_master->GetMap()->GetCreature(Guid)) loot = &c->loot; } else if (Guid.IsGameObject()) { if (GameObject* go = m_master->GetMap()->GetGameObject(Guid)) loot = &go->loot; } if (!loot) return; LootItem& lootItem = loot->items[itemSlot]; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { uint32 choice = 0; Player* const bot = it->second; if (!bot) return; Group* group = bot->GetGroup(); if (!group) return; ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(lootItem.itemid); if (!pProto) return; if (bot->GetPlayerbotAI()->CanStore()) { if (bot->CanUseItem(pProto) == EQUIP_ERR_OK && bot->GetPlayerbotAI()->IsItemUseful(lootItem.itemid)) choice = 1; // Need else if (bot->HasSkill(SKILL_ENCHANTING)) choice = 3; // Disenchant else choice = 2; // Greed } else choice = 0; // Pass group->CountRollVote(bot, Guid, itemSlot, RollVote(choice)); switch (choice) { case ROLL_NEED: bot->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1); break; case ROLL_GREED: case ROLL_DISENCHANT: bot->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1); break; } } return; } // Handle GOSSIP activate actions, prior to GOSSIP select menu actions case CMSG_GOSSIP_HELLO: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO"); WorldPacket p(packet); //WorldPacket packet for CMSG_GOSSIP_HELLO, (8) ObjectGuid guid; p.rpos(0); //reset packet pointer p >> guid; for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot) return; Creature *pCreature = bot->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!pCreature) { DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO %s not found or you can't interact with him.", guid.GetString().c_str()); return; } GossipMenuItemsMapBounds pMenuItemBounds = sObjectMgr.GetGossipMenuItemsMapBounds(pCreature->GetCreatureInfo()->GossipMenuId); for (GossipMenuItemsMap::const_iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr) { uint32 npcflags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS); if (!(itr->second.npc_option_npcflag & npcflags)) continue; switch (itr->second.option_id) { case GOSSIP_OPTION_TAXIVENDOR: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_TAXIVENDOR"); bot->GetSession()->SendLearnNewTaxiNode(pCreature); break; } case GOSSIP_OPTION_QUESTGIVER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_QUESTGIVER"); bot->GetPlayerbotAI()->TurnInQuests(pCreature); break; } case GOSSIP_OPTION_VENDOR: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_VENDOR"); if (!botConfig.GetBoolDefault("PlayerbotAI.SellGarbage", true)) return; bot->GetPlayerbotAI()->SellGarbage(); break; } case GOSSIP_OPTION_STABLEPET: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_STABLEPET"); break; } case GOSSIP_OPTION_AUCTIONEER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_AUCTIONEER"); break; } case GOSSIP_OPTION_BANKER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_BANKER"); break; } case GOSSIP_OPTION_INNKEEPER: { // bot->GetPlayerbotAI()->TellMaster("PlayerbotMgr:GOSSIP_OPTION_INNKEEPER"); break; } } } } return; } case CMSG_SPIRIT_HEALER_ACTIVATE: { // DEBUG_LOG ("[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_SPIRIT_HEALER_ACTIVATE SpiritHealer is resurrecting the Player %s",m_master->GetName()); for (PlayerBotMap::iterator itr = m_playerBots.begin(); itr != m_playerBots.end(); ++itr) { Player* const bot = itr->second; Group *grp = bot->GetGroup(); if (grp) grp->RemoveMember(bot->GetObjectGuid(), 1); } return; } case CMSG_LIST_INVENTORY: { if (!botConfig.GetBoolDefault("PlayerbotAI.SellGarbage", true)) return; WorldPacket p(packet); p.rpos(0); // reset reader ObjectGuid npcGUID; p >> npcGUID; Object* const pNpc = (WorldObject *) m_master->GetObjectByTypeMask(npcGUID, TYPEMASK_CREATURE_OR_GAMEOBJECT); if (!pNpc) return; // for all master's bots for (PlayerBotMap::const_iterator it = GetPlayerBotsBegin(); it != GetPlayerBotsEnd(); ++it) { Player* const bot = it->second; if (!bot->IsInMap(static_cast<WorldObject *>(pNpc))) { bot->GetPlayerbotAI()->TellMaster("I'm too far away to sell items!"); continue; } else bot->GetPlayerbotAI()->SellGarbage(); } return; } /* case CMSG_NAME_QUERY: case MSG_MOVE_START_FORWARD: case MSG_MOVE_STOP: case MSG_MOVE_SET_FACING: case MSG_MOVE_START_STRAFE_LEFT: case MSG_MOVE_START_STRAFE_RIGHT: case MSG_MOVE_STOP_STRAFE: case MSG_MOVE_START_BACKWARD: case MSG_MOVE_HEARTBEAT: case CMSG_STANDSTATECHANGE: case CMSG_QUERY_TIME: case CMSG_CREATURE_QUERY: case CMSG_GAMEOBJECT_QUERY: case MSG_MOVE_JUMP: case MSG_MOVE_FALL_LAND: return; default: { const char* oc = LookupOpcodeName(packet.GetOpcode()); // ChatHandler ch(m_master); // ch.SendSysMessage(oc); std::ostringstream out; out << "masterin: " << oc; sLog.outError(out.str().c_str()); } */ } }