void WorldSession::HandleReportPvPAFK(WorldPacket& recvData) { ObjectGuid playerGuid; recvData >> playerGuid; Player* reportedPlayer = ObjectAccessor::FindPlayer(playerGuid); if (!reportedPlayer) { TC_LOG_INFO("bg.reportpvpafk", "WorldSession::HandleReportPvPAFK: %s [IP: %s] reported %s", _player->GetName().c_str(), _player->GetSession()->GetRemoteAddress().c_str(), playerGuid.ToString().c_str()); return; } TC_LOG_DEBUG("bg.battleground", "WorldSession::HandleReportPvPAFK: %s reported %s", _player->GetName().c_str(), reportedPlayer->GetName().c_str()); reportedPlayer->ReportedAfkBy(_player); }
void WorldSession::HandleBinderActivateOpcode(WorldPacket& recvData) { ObjectGuid npcGUID; recvData >> npcGUID; if (!GetPlayer()->IsInWorld() || !GetPlayer()->IsAlive()) return; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(npcGUID, UNIT_NPC_FLAG_INNKEEPER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleBinderActivateOpcode - %s not found or you can not interact with him.", npcGUID.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); SendBindPoint(unit); }
//remove player from queue and from group info, if group info is empty then remove it too void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount) { int32 bracket_id = -1; // signed for proper for-loop finish QueuedPlayersMap::iterator itr; //remove player from map, if he's there itr = m_QueuedPlayers.find(guid); if (itr == m_QueuedPlayers.end()) { std::string playerName = "Unknown"; if (Player* player = ObjectAccessor::FindPlayer(guid)) playerName = player->GetName(); TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: couldn't find player %s (%s)", playerName.c_str(), guid.ToString().c_str()); return; } GroupQueueInfo* group = itr->second.GroupInfo; GroupsQueueType::iterator group_itr; // mostly people with the highest levels are in battlegrounds, thats why // we count from MAX_BATTLEGROUND_QUEUES - 1 to 0 uint32 index = (group->Team == HORDE) ? BG_QUEUE_PREMADE_HORDE : BG_QUEUE_PREMADE_ALLIANCE; for (int32 bracket_id_tmp = MAX_BATTLEGROUND_BRACKETS - 1; bracket_id_tmp >= 0 && bracket_id == -1; --bracket_id_tmp) { //we must check premade and normal team's queue - because when players from premade are joining bg, //they leave groupinfo so we can't use its players size to find out index for (uint32 j = index; j < BG_QUEUE_GROUP_TYPES_COUNT; j += BG_TEAMS_COUNT) { GroupsQueueType::iterator k = m_QueuedGroups[bracket_id_tmp][j].begin(); for (; k != m_QueuedGroups[bracket_id_tmp][j].end(); ++k) { if ((*k) == group) { bracket_id = bracket_id_tmp; group_itr = k; //we must store index to be able to erase iterator index = j; break; } } } } //player can't be in queue without group, but just in case if (bracket_id == -1) { TC_LOG_ERROR("bg.battleground", "BattlegroundQueue: ERROR Cannot find groupinfo for %s", guid.ToString().c_str()); return; } TC_LOG_DEBUG("bg.battleground", "BattlegroundQueue: Removing %s, from bracket_id %u", guid.ToString().c_str(), (uint32)bracket_id); // ALL variables are correctly set // We can ignore leveling up in queue - it should not cause crash // remove player from group // if only one player there, remove group // remove player queue info from group queue info std::map<ObjectGuid, PlayerQueueInfo*>::iterator pitr = group->Players.find(guid); if (pitr != group->Players.end()) group->Players.erase(pitr); // if invited to bg, and should decrease invited count, then do it if (decreaseInvitedCount && group->IsInvitedToBGInstanceGUID) if (Battleground* bg = sBattlegroundMgr->GetBattleground(group->IsInvitedToBGInstanceGUID, group->BgTypeId)) bg->DecreaseInvitedCount(group->Team); // remove player queue info m_QueuedPlayers.erase(itr); // announce to world if arena team left queue for rated match, show only once if (group->ArenaType && group->IsRated && group->Players.empty() && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE)) if (ArenaTeam* Team = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId)) sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, Team->GetName().c_str(), group->ArenaType, group->ArenaType, group->ArenaTeamRating); // if player leaves queue and he is invited to rated arena match, then he have to lose if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount) { if (ArenaTeam* at = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId)) { TC_LOG_DEBUG("bg.battleground", "UPDATING memberLost's personal arena rating for %s by opponents rating: %u", guid.ToString().c_str(), group->OpponentsTeamRating); if (Player* player = ObjectAccessor::FindConnectedPlayer(guid)) at->MemberLost(player, group->OpponentsMatchmakerRating); else at->OfflineMemberLost(guid, group->OpponentsMatchmakerRating); at->SaveToDB(); } } // remove group queue info if needed if (group->Players.empty()) { m_QueuedGroups[bracket_id][index].erase(group_itr); delete group; return; } // if group wasn't empty, so it wasn't deleted, and player have left a rated // queue -> everyone from the group should leave too // don't remove recursively if already invited to bg! if (!group->IsInvitedToBGInstanceGUID && group->IsRated) { // remove next player, this is recursive // first send removal information if (Player* plr2 = ObjectAccessor::FindConnectedPlayer(group->Players.begin()->first)) { Battleground* bg = sBattlegroundMgr->GetBattlegroundTemplate(group->BgTypeId); BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(group->BgTypeId, group->ArenaType); uint32 queueSlot = plr2->GetBattlegroundQueueIndex(bgQueueTypeId); plr2->RemoveBattlegroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to // queue->removeplayer, it causes bugs WorldPacket data; sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_NONE, 0, 0, 0, 0); plr2->GetSession()->SendPacket(&data); } // then actually delete, this may delete the group as well! RemovePlayer(group->Players.begin()->first, decreaseInvitedCount); } }
void WorldSession::HandlePetCancelAuraOpcode(WorldPacket& recvPacket) { ObjectGuid guid; uint32 spellId; recvPacket >> guid; recvPacket >> spellId; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { TC_LOG_ERROR("network", "WORLD: unknown PET spell id %u", spellId); return; } Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (!pet) { TC_LOG_ERROR("network", "HandlePetCancelAura: Attempt to cancel an aura for non-existant %s by player '%s'", guid.ToString().c_str(), GetPlayer()->GetName().c_str()); return; } if (pet != GetPlayer()->GetGuardianPet() && pet != GetPlayer()->GetCharm()) { TC_LOG_ERROR("network", "HandlePetCancelAura: %s is not a pet of player '%s'", guid.ToString().c_str(), GetPlayer()->GetName().c_str()); return; } if (!pet->IsAlive()) { pet->SendPetActionFeedback(FEEDBACK_PET_DEAD); return; } pet->RemoveOwnedAura(spellId, ObjectGuid::Empty, 0, AURA_REMOVE_BY_CANCEL); }
void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) { ObjectGuid guid; uint32 spellId = 0; recvData >> guid >> spellId; TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL %s, learn spell id is: %u", guid.ToString().c_str(), spellId); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", guid.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // check present spell in trainer spell list TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) return; // not found, cheat? TrainerSpell const* trainer_spell = trainer_spells->Find(spellId); if (!trainer_spell) return; // can't be learn, cheat? Or double learn with lags... if (_player->GetTrainerSpellState(trainer_spell) != TRAINER_SPELL_GREEN) return; // apply reputation discount uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); // check money requirement if (!_player->HasEnoughMoney(nSpellCost)) return; _player->ModifyMoney(-int32(nSpellCost)); unit->SendPlaySpellVisual(179); // 53 SpellCastDirected unit->SendPlaySpellImpact(_player->GetGUID(), 362); // 113 EmoteSalute // learn explicitly or cast explicitly if (trainer_spell->IsCastable()) _player->CastSpell(_player, trainer_spell->spell, true); else _player->LearnSpell(spellId, false); WorldPacket data(SMSG_TRAINER_BUY_SUCCEEDED, 12); data << uint64(guid); data << uint32(spellId); // should be same as in packet from client SendPacket(&data); }
void WorldSession::HandlePetSetAction(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_SET_ACTION"); ObjectGuid petguid; uint8 count; recvData >> petguid; Unit* pet = ObjectAccessor::GetUnit(*_player, petguid); if (!pet || pet != _player->GetFirstControlled()) { TC_LOG_ERROR("network", "HandlePetSetAction: Unknown %s or owner (%s)", petguid.ToString().c_str(), _player->GetGUID().ToString().c_str()); return; } CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { TC_LOG_ERROR("network", "WorldSession::HandlePetSetAction: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } count = (recvData.size() == 24) ? 2 : 1; uint32 position[2]; uint32 data[2]; bool move_command = false; for (uint8 i = 0; i < count; ++i) { recvData >> position[i]; recvData >> data[i]; uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); //ignore invalid position if (position[i] >= MAX_UNIT_ACTION_BAR_INDEX) return; // in the normal case, command and reaction buttons can only be moved, not removed // at moving count == 2, at removing count == 1 // ignore attempt to remove command|reaction buttons (not possible at normal case) if (act_state == ACT_COMMAND || act_state == ACT_REACTION) { if (count == 1) return; move_command = true; } } // check swap (at command->spell swap client remove spell first in another packet, so check only command move correctness) if (move_command) { uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]); if (act_state_0 == ACT_COMMAND || act_state_0 == ACT_REACTION) { uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]); UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]); if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() || act_state_0 != actionEntry_1->GetType()) return; } uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]); if (act_state_1 == ACT_COMMAND || act_state_1 == ACT_REACTION) { uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]); UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]); if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() || act_state_1 != actionEntry_0->GetType()) return; } } for (uint8 i = 0; i < count; ++i) { uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]); uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]); TC_LOG_DEBUG("network", "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName().c_str(), position[i], spell_id, uint32(act_state)); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add if (!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) { if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id)) { //sign for autocast if (act_state == ACT_ENABLED) { if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->IsPet()) ((Pet*)pet)->ToggleAutocast(spellInfo, true); else for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) if ((*itr)->GetEntry() == pet->GetEntry()) (*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, true); } //sign for no/turn off autocast else if (act_state == ACT_DISABLED) { if (pet->GetTypeId() == TYPEID_UNIT && pet->ToCreature()->IsPet()) ((Pet*)pet)->ToggleAutocast(spellInfo, false); else for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) if ((*itr)->GetEntry() == pet->GetEntry()) (*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, false); } } charmInfo->SetActionBar(position[i], spell_id, ActiveStates(act_state)); } } }
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_CAST_SPELL"); ObjectGuid guid; uint8 castCount; uint32 spellId; uint8 castFlags; recvPacket >> guid >> castCount >> spellId >> castFlags; TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL, %s, castCount: %u, spellId %u, castFlags %u", guid.ToString().c_str(), castCount, spellId, castFlags); // This opcode is also sent from charmed and possessed units (players and creatures) if (!_player->GetGuardianPet() && !_player->GetCharm()) return; Unit* caster = ObjectAccessor::GetUnit(*_player, guid); if (!caster || (caster != _player->GetGuardianPet() && caster != _player->GetCharm())) { TC_LOG_ERROR("network", "HandlePetCastSpellOpcode: %s isn't pet of player %s (%s).", guid.ToString().c_str(), GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str()); return; } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) { TC_LOG_ERROR("network", "WORLD: unknown PET spell id %i", spellId); return; } // do not cast not learned spells if (!caster->HasSpell(spellId) || spellInfo->IsPassive()) return; SpellCastTargets targets; targets.Read(recvPacket, caster); HandleClientCastFlags(recvPacket, castFlags, targets); caster->ClearUnitState(UNIT_STATE_FOLLOW); Spell* spell = new Spell(caster, spellInfo, TRIGGERED_NONE); spell->m_cast_count = castCount; // probably pending spell cast spell->m_targets = targets; SpellCastResult result = spell->CheckPetCast(NULL); if (result == SPELL_CAST_OK) { if (Creature* creature = caster->ToCreature()) { creature->AddCreatureSpellCooldown(spellId); if (Pet* pet = creature->ToPet()) { // 10% chance to play special pet attack talk, else growl // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (pet->getPetType() == SUMMON_PET && (urand(0, 100) < 10)) pet->SendPetTalk(PET_TALK_SPECIAL_SPELL); else pet->SendPetAIReaction(guid); } } spell->prepare(&(spell->m_targets)); } else { spell->SendPetCastResult(result); if (caster->GetTypeId() == TYPEID_PLAYER) { if (!caster->ToPlayer()->HasSpellCooldown(spellId)) GetPlayer()->SendClearCooldown(spellId, caster); } else { if (!caster->ToCreature()->HasSpellCooldown(spellId)) GetPlayer()->SendClearCooldown(spellId, caster); } spell->finish(false); delete spell; } }
void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData) { ObjectGuid guid; recvData >> guid; uint32 questStatus = DIALOG_STATUS_NONE; Object* questGiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!questGiver) { TC_LOG_INFO("network", "Error in CMSG_QUESTGIVER_STATUS_QUERY, called for non-existing questgiver (%s)", guid.ToString().c_str()); return; } switch (questGiver->GetTypeId()) { case TYPEID_UNIT: { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", questGiver->GetGUID().GetCounter()); if (!questGiver->ToCreature()->IsHostileTo(_player)) // do not show quest status to enemies questStatus = _player->GetQuestDialogStatus(questGiver); break; } case TYPEID_GAMEOBJECT: { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", questGiver->GetGUID().GetCounter()); questStatus = _player->GetQuestDialogStatus(questGiver); break; } default: TC_LOG_ERROR("network", "QuestGiver called for unexpected type %u", questGiver->GetTypeId()); break; } // inform client about status of quest _player->PlayerTalkClass->SendQuestGiverStatus(uint8(questStatus), guid); }
void WorldSession::HandleQuestgiverRequestRewardOpcode(WorldPacket& recvData) { uint32 questId; ObjectGuid guid; recvData >> guid >> questId; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_REQUEST_REWARD npc = %s, quest = %u", guid.ToString().c_str(), questId); Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) return; if (_player->CanCompleteQuest(questId)) _player->CompleteQuest(questId); if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE) return; if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); }
void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket& recvData) { ObjectGuid guid; uint32 questId; uint8 unk1; recvData >> guid >> questId >> unk1; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_QUERY_QUEST npc = %s, quest = %u, unk1 = %u", guid.ToString().c_str(), questId, unk1); // Verify that the guid is valid and is a questgiver or involved in the requested quest Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); if (!object || (!object->hasQuest(questId) && !object->hasInvolvedQuest(questId))) { _player->PlayerTalkClass->SendCloseGossip(); return; } if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { // not sure here what should happen to quests with QUEST_FLAGS_AUTOCOMPLETE // if this breaks them, add && object->GetTypeId() == TYPEID_ITEM to this check // item-started quests never have that flag if (!_player->CanTakeQuest(quest, true)) return; if (quest->IsAutoAccept() && _player->CanAddQuest(quest, true)) _player->AddQuestAndCheckCompletion(quest, object); if (quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE)) _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, object->GetGUID(), _player->CanCompleteQuest(quest->GetQuestId()), true); else _player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, object->GetGUID(), true); } }
void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData) { uint32 questId, reward; ObjectGuid guid; recvData >> guid >> questId >> reward; if (reward >= QUEST_REWARD_CHOICES_COUNT) { TC_LOG_ERROR("network", "Error in CMSG_QUESTGIVER_CHOOSE_REWARD: player %s (guid %d) tried to get invalid reward (%u) (possible packet-hacking detected)", _player->GetName().c_str(), _player->GetGUID().GetCounter(), reward); return; } TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_CHOOSE_REWARD npc = %s, quest = %u, reward = %u", guid.ToString().c_str(), questId, reward); Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) return; if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { if ((!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) || (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE && !quest->IsAutoComplete())) { TC_LOG_ERROR("network", "Error in QUEST_STATUS_COMPLETE: player %s (guid %u) tried to complete quest %u, but is not allowed to do so (possible packet-hacking or high latency)", _player->GetName().c_str(), _player->GetGUID().GetCounter(), questId); return; } if (_player->CanRewardQuest(quest, reward, true)) { _player->RewardQuest(quest, reward, object); switch (object->GetTypeId()) { case TYPEID_UNIT: { Creature* questgiver = object->ToCreature(); if (!sScriptMgr->OnQuestReward(_player, questgiver, quest, reward)) { // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { // Only send the quest to the player if the conditions are met if (_player->CanTakeQuest(nextQuest, false)) { if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) _player->AddQuestAndCheckCompletion(nextQuest, object); _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); } } questgiver->AI()->sQuestReward(_player, quest, reward); } break; } case TYPEID_GAMEOBJECT: { GameObject* questGiver = object->ToGameObject(); if (!sScriptMgr->OnQuestReward(_player, questGiver, quest, reward)) { // Send next quest if (Quest const* nextQuest = _player->GetNextQuest(guid, quest)) { // Only send the quest to the player if the conditions are met if (_player->CanTakeQuest(nextQuest, false)) { if (nextQuest->IsAutoAccept() && _player->CanAddQuest(nextQuest, true)) _player->AddQuestAndCheckCompletion(nextQuest, object); _player->PlayerTalkClass->SendQuestGiverQuestDetails(nextQuest, guid, true); } } questGiver->AI()->QuestReward(_player, quest, reward); } break; } default: break; } } else _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); } }
void WorldSession::HandleQuestgiverAcceptQuestOpcode(WorldPacket& recvData) { ObjectGuid guid; uint32 questId; uint32 startCheat; recvData >> guid >> questId >> startCheat; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_ACCEPT_QUEST %s, quest = %u, startCheat = %u", guid.ToString().c_str(), questId, startCheat); Object* object; if (!guid.IsPlayer()) object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT | TYPEMASK_ITEM); else object = ObjectAccessor::FindPlayer(guid); #define CLOSE_GOSSIP_CLEAR_DIVIDER() \ do { \ _player->PlayerTalkClass->SendCloseGossip(); \ _player->SetDivider(ObjectGuid::Empty); \ } while (0) // no or incorrect quest giver if (!object) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Player* playerQuestObject = object->ToPlayer()) { if ((_player->GetDivider() && _player->GetDivider() != guid) || !playerQuestObject->CanShareQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (!_player->IsInSameRaidWith(playerQuestObject)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } else { if (!object->hasQuest(questId)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } } // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId)) { // prevent cheating if (!GetPlayer()->CanTakeQuest(quest, true)) { CLOSE_GOSSIP_CLEAR_DIVIDER(); return; } if (!_player->GetDivider().IsEmpty()) { Player* player = ObjectAccessor::FindPlayer(_player->GetDivider()); if (player) { player->SendPushToPartyResponse(_player, QUEST_PARTY_MSG_ACCEPT_QUEST); _player->SetDivider(ObjectGuid::Empty); } } if (_player->CanAddQuest(quest, true)) { _player->AddQuestAndCheckCompletion(quest, object); if (quest->HasFlag(QUEST_FLAGS_PARTY_ACCEPT)) { if (Group* group = _player->GetGroup()) { for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* player = itr->GetSource(); if (!player || player == _player) // not self continue; if (player->CanTakeQuest(quest, true)) { player->SetDivider(_player->GetGUID()); // need confirmation that any gossip window will close player->PlayerTalkClass->SendCloseGossip(); _player->SendQuestConfirmAccept(quest, player); } } } } _player->PlayerTalkClass->SendCloseGossip(); if (quest->GetSrcSpell() > 0) _player->CastSpell(_player, quest->GetSrcSpell(), true); return; } } CLOSE_GOSSIP_CLEAR_DIVIDER(); #undef CLOSE_GOSSIP_CLEAR_DIVIDER }
static bool HandleCharacterChangeRaceCommand(ChatHandler* handler, char const* args) { Player* target; ObjectGuid targetGuid; std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->setUInt16(0, uint16(AT_LOGIN_CHANGE_RACE)); if (target) { /// @todo add text into database handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER, handler->GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE); stmt->setUInt64(1, target->GetGUID().GetCounter()); } else { std::string oldNameLink = handler->playerLink(targetName); /// @todo add text into database handler->PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), targetGuid.ToString().c_str()); stmt->setUInt64(1, targetGuid.GetCounter()); } CharacterDatabase.Execute(stmt); return true; }
//rename characters static bool HandleCharacterRenameCommand(ChatHandler* handler, char const* args) { Player* target; ObjectGuid targetGuid; std::string targetName; if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; char const* newNameStr = strtok(NULL, " "); if (newNameStr) { std::string playerOldName; std::string newName = newNameStr; if (target) { // check online security if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; playerOldName = target->GetName(); } else { // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; ObjectMgr::GetPlayerNameByGUID(targetGuid, playerOldName); } if (!normalizePlayerName(newName)) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } if (ObjectMgr::CheckPlayerName(newName, target ? target->GetSession()->GetSessionDbcLocale() : sWorld->GetDefaultDbcLocale(), true) != CHAR_NAME_SUCCESS) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } if (WorldSession* session = handler->GetSession()) { if (!session->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME) && sObjectMgr->IsReservedName(newName)) { handler->SendSysMessage(LANG_RESERVED_NAME); handler->SetSentErrorMessage(true); return false; } } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, newName); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { handler->PSendSysMessage(LANG_RENAME_PLAYER_ALREADY_EXISTS, newName.c_str()); handler->SetSentErrorMessage(true); return false; } // Remove declined name from db stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_DECLINED_NAME); stmt->setUInt64(0, targetGuid.GetCounter()); CharacterDatabase.Execute(stmt); if (target) { target->SetName(newName); if (WorldSession* session = target->GetSession()) session->KickPlayer(); } else { stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_NAME_BY_GUID); stmt->setString(0, newName); stmt->setUInt64(1, targetGuid.GetCounter()); CharacterDatabase.Execute(stmt); } sWorld->UpdateCharacterInfo(targetGuid, newName); handler->PSendSysMessage(LANG_RENAME_PLAYER_WITH_NEW_NAME, playerOldName.c_str(), newName.c_str()); if (WorldSession* session = handler->GetSession()) { if (Player* player = session->GetPlayer()) sLog->outCommand(session->GetAccountId(), "GM %s (Account: %u) forced rename %s to player %s (Account: %u)", player->GetName().c_str(), session->GetAccountId(), newName.c_str(), playerOldName.c_str(), ObjectMgr::GetPlayerAccountIdByGUID(targetGuid)); } else sLog->outCommand(0, "CONSOLE forced rename '%s' to '%s' (%s)", playerOldName.c_str(), newName.c_str(), targetGuid.ToString().c_str()); } else { if (target) { // check online security if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; handler->PSendSysMessage(LANG_RENAME_PLAYER, handler->GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_RENAME); } else { // check offline security if (handler->HasLowerSecurity(NULL, targetGuid)) return false; std::string oldNameLink = handler->playerLink(targetName); handler->PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), targetGuid.ToString().c_str()); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ADD_AT_LOGIN_FLAG); stmt->setUInt16(0, uint16(AT_LOGIN_RENAME)); stmt->setUInt64(1, targetGuid.GetCounter()); CharacterDatabase.Execute(stmt); } } return true; }
void WorldSession::SendPetitionShowList(ObjectGuid guid) { Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandlePetitionShowListOpcode - %s not found or you can't interact with him.", guid.ToString().c_str()); return; } WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6); data << guid; // npc guid if (creature->IsTabardDesigner()) { data << uint8(1); // count data << uint32(1); // index data << uint32(GUILD_CHARTER); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id data << uint32(GUILD_CHARTER_COST); // charter cost data << uint32(0); // unknown data << uint32(sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)); // required signs } else { data << uint8(3); // count // 2v2 data << uint32(1); // index data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost data << uint32(2); // unknown data << uint32(2); // required signs? // 3v3 data << uint32(2); // index data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost data << uint32(3); // unknown data << uint32(3); // required signs? // 5v5 data << uint32(3); // index data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry data << uint32(CHARTER_DISPLAY_ID); // charter display id data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost data << uint32(5); // unknown data << uint32(5); // required signs? } SendPacket(&data); TC_LOG_DEBUG("network", "Sent SMSG_PETITION_SHOWLIST"); }
void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData) { uint32 questId; ObjectGuid guid; recvData >> guid >> questId; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %s, quest = %u", guid.ToString().c_str(), questId); Quest const* quest = sObjectMgr->GetQuestTemplate(questId); if (!quest) return; Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT); if (!object || !object->hasInvolvedQuest(questId)) return; // some kind of WPE protection if (!_player->CanInteractWithQuestGiver(object)) return; if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE) { TC_LOG_ERROR("network", "Possible hacking attempt: Player %s [guid: %u] tried to complete quest [entry: %u] without being in possession of the quest!", _player->GetName().c_str(), _player->GetGUID().GetCounter(), questId); return; } if (Battleground* bg = _player->GetBattleground()) bg->HandleQuestComplete(questId, _player); if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE) { if (quest->IsRepeatable()) _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanCompleteRepeatableQuest(quest), false); else _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false); } else { if (quest->GetReqItemsCount()) // some items required _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false); else // no items required _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true); } }
void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spellid, uint16 flag, ObjectGuid guid2) { CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { TC_LOG_DEBUG("network", "WorldSession::HandlePetAction(petGuid: %s, tagGuid: %s, spellId: %u, flag: %u): object (GUID: %u Entry: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", guid1.ToString().c_str(), guid2.ToString().c_str(), spellid, flag, pet->GetGUIDLow(), pet->GetEntry(), pet->GetTypeId()); return; } switch (flag) { case ACT_COMMAND: //0x07 switch (spellid) { case COMMAND_STAY: //flat=1792 //STAY pet->StopMoving(); pet->GetMotionMaster()->Clear(false); pet->GetMotionMaster()->MoveIdle(); charmInfo->SetCommandState(COMMAND_STAY); charmInfo->SetIsCommandAttack(false); charmInfo->SetIsAtStay(true); charmInfo->SetIsCommandFollow(false); charmInfo->SetIsFollowing(false); charmInfo->SetIsReturning(false); charmInfo->SaveStayPosition(); break; case COMMAND_FOLLOW: //spellid=1792 //FOLLOW pet->AttackStop(); pet->InterruptNonMeleeSpells(false); pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle()); charmInfo->SetCommandState(COMMAND_FOLLOW); charmInfo->SetIsCommandAttack(false); charmInfo->SetIsAtStay(false); charmInfo->SetIsReturning(true); charmInfo->SetIsCommandFollow(true); charmInfo->SetIsFollowing(false); break; case COMMAND_ATTACK: //spellid=1792 //ATTACK { // Can't attack if owner is pacified if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY)) { //pet->SendPetCastFail(spellid, SPELL_FAILED_PACIFIED); /// @todo Send proper error message to client return; } // only place where pet can be player Unit* TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); if (!TargetUnit) return; if (Unit* owner = pet->GetOwner()) if (!owner->IsValidAttackTarget(TargetUnit)) return; pet->ClearUnitState(UNIT_STATE_FOLLOW); // This is true if pet has no target or has target but targets differs. if (pet->GetVictim() != TargetUnit || (pet->GetVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) { if (pet->GetVictim()) pet->AttackStop(); if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled) { charmInfo->SetIsCommandAttack(true); charmInfo->SetIsAtStay(false); charmInfo->SetIsFollowing(false); charmInfo->SetIsCommandFollow(false); charmInfo->SetIsReturning(false); pet->ToCreature()->AI()->AttackStart(TargetUnit); //10% chance to play special pet attack talk, else growl if (pet->ToCreature()->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) pet->SendPetTalk((uint32)PET_TALK_ATTACK); else { // 90% chance for pet and 100% chance for charmed creature pet->SendPetAIReaction(guid1); } } else // charmed player { if (pet->GetVictim() && pet->GetVictim() != TargetUnit) pet->AttackStop(); charmInfo->SetIsCommandAttack(true); charmInfo->SetIsAtStay(false); charmInfo->SetIsFollowing(false); charmInfo->SetIsCommandFollow(false); charmInfo->SetIsReturning(false); pet->Attack(TargetUnit, true); pet->SendPetAIReaction(guid1); } } break; } case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet) if (pet->GetCharmerGUID() == GetPlayer()->GetGUID()) _player->StopCastingCharm(); else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID()) { ASSERT(pet->GetTypeId() == TYPEID_UNIT); if (pet->IsPet()) { if (((Pet*)pet)->getPetType() == HUNTER_PET) GetPlayer()->RemovePet((Pet*)pet, PET_SAVE_AS_DELETED); else //dismissing a summoned pet is like killing them (this prevents returning a soulshard...) pet->setDeathState(CORPSE); } else if (pet->HasUnitTypeMask(UNIT_MASK_MINION)) { ((Minion*)pet)->UnSummon(); } } break; default: TC_LOG_ERROR("network", "WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } break; case ACT_REACTION: // 0x6 switch (spellid) { case REACT_PASSIVE: //passive pet->AttackStop(); // no break; case REACT_DEFENSIVE: //recovery case REACT_AGGRESSIVE: //activete if (pet->GetTypeId() == TYPEID_UNIT) pet->ToCreature()->SetReactState(ReactStates(spellid)); break; } break; case ACT_DISABLED: // 0x81 spell (disabled), ignore case ACT_PASSIVE: // 0x01 case ACT_ENABLED: // 0xC1 spell { Unit* unit_target = NULL; if (guid2) unit_target = ObjectAccessor::GetUnit(*_player, guid2); // do not cast unknown spells SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) { TC_LOG_ERROR("network", "WORLD: unknown PET spell id %i", spellid); return; } for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) return; } // do not cast not learned spells if (!pet->HasSpell(spellid) || spellInfo->IsPassive()) return; // Clear the flags as if owner clicked 'attack'. AI will reset them // after AttackStart, even if spell failed if (pet->GetCharmInfo()) { pet->GetCharmInfo()->SetIsAtStay(false); pet->GetCharmInfo()->SetIsCommandAttack(true); pet->GetCharmInfo()->SetIsReturning(false); pet->GetCharmInfo()->SetIsFollowing(false); } Spell* spell = new Spell(pet, spellInfo, TRIGGERED_NONE); SpellCastResult result = spell->CheckPetCast(unit_target); //auto turn to target unless possessed if (result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed() && !pet->IsVehicle()) { if (unit_target) { pet->SetInFront(unit_target); if (Player* player = unit_target->ToPlayer()) pet->SendUpdateToPlayer(player); } else if (Unit* unit_target2 = spell->m_targets.GetUnitTarget()) { pet->SetInFront(unit_target2); if (Player* player = unit_target2->ToPlayer()) pet->SendUpdateToPlayer(player); } if (Unit* powner = pet->GetCharmerOrOwner()) if (Player* player = powner->ToPlayer()) pet->SendUpdateToPlayer(player); result = SPELL_CAST_OK; } if (result == SPELL_CAST_OK) { pet->ToCreature()->AddCreatureSpellCooldown(spellid); unit_target = spell->m_targets.GetUnitTarget(); //10% chance to play special pet attack talk, else growl //actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell if (pet->ToCreature()->IsPet() && (((Pet*)pet)->getPetType() == SUMMON_PET) && (pet != unit_target) && (urand(0, 100) < 10)) pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); else { pet->SendPetAIReaction(guid1); } if (unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed() && !pet->IsVehicle()) { // This is true if pet has no target or has target but targets differs. if (pet->GetVictim() != unit_target) { if (pet->GetVictim()) pet->AttackStop(); pet->GetMotionMaster()->Clear(); if (pet->ToCreature()->IsAIEnabled) pet->ToCreature()->AI()->AttackStart(unit_target); } } spell->prepare(&(spell->m_targets)); } else { if (pet->isPossessed() || pet->IsVehicle()) /// @todo: confirm this check Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); else spell->SendPetCastResult(result); if (!pet->ToCreature()->HasSpellCooldown(spellid)) GetPlayer()->SendClearCooldown(spellid, pet); spell->finish(false); delete spell; // reset specific flags in case of spell fail. AI will reset other flags if (pet->GetCharmInfo()) pet->GetCharmInfo()->SetIsCommandAttack(false); } break; } default: TC_LOG_ERROR("network", "WORLD: unknown PET flag Action %i and spellid %i.", uint32(flag), spellid); } }
void WorldSession::HandlePetitionShowSignOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_SHOW_SIGNATURES"); uint8 signs = 0; ObjectGuid petitionguid; recvData >> petitionguid; // petition guid uint32 petitionGuidLow = petitionguid.GetCounter(); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); stmt->setUInt32(0, petitionGuidLow); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { TC_LOG_DEBUG("entities.player.items", "Petition %s is not found for player %u %s", petitionguid.ToString().c_str(), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str()); return; } Field* fields = result->Fetch(); uint32 type = fields[0].GetUInt8(); // if guild petition and has guild => error, return; if (type == GUILD_CHARTER_TYPE && _player->GetGuildId()) return; stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); stmt->setUInt32(0, petitionGuidLow); result = CharacterDatabase.Query(stmt); // result == NULL also correct in case no sign yet if (result) signs = uint8(result->GetRowCount()); TC_LOG_DEBUG("network", "CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionGuidLow); WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12)); data << uint64(petitionguid); // petition guid data << uint64(_player->GetGUID()); // owner guid data << uint32(petitionGuidLow); // guild guid data << uint8(signs); // sign's count for (uint8 i = 1; i <= signs; ++i) { Field* fields2 = result->Fetch(); uint32 lowGuid = fields2[0].GetUInt32(); data << ObjectGuid(HIGHGUID_PLAYER, 0, lowGuid); // Player GUID data << uint32(0); // there 0 ... result->NextRow(); } SendPacket(&data); }
void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_SPELL_AUTOCAST"); ObjectGuid guid; uint32 spellid; uint8 state; //1 for on, 0 for off recvPacket >> guid >> spellid >> state; if (!_player->GetGuardianPet() && !_player->GetCharm()) return; if (ObjectAccessor::FindPlayer(guid)) return; Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if (!pet || (pet != _player->GetGuardianPet() && pet != _player->GetCharm())) { TC_LOG_ERROR("network", "HandlePetSpellAutocastOpcode. %s isn't pet of player %s (%s).", guid.ToString().c_str(), GetPlayer()->GetName().c_str(), GetPlayer()->GetGUID().ToString().c_str()); return; } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) { TC_LOG_ERROR("network", "WORLD: unknown PET spell id %u", spellid); return; } // do not add not learned spells/ passive spells if (!pet->HasSpell(spellid) || !spellInfo->IsAutocastable()) return; CharmInfo* charmInfo = pet->GetCharmInfo(); if (!charmInfo) { TC_LOG_ERROR("network", "WorldSession::HandlePetSpellAutocastOpcod: object (GUID: %u TypeId: %u) is considered pet-like but doesn't have a charminfo!", pet->GetGUIDLow(), pet->GetTypeId()); return; } if (pet->IsPet()) ((Pet*)pet)->ToggleAutocast(spellInfo, state != 0); else for (Unit::ControlList::iterator itr = GetPlayer()->m_Controlled.begin(); itr != GetPlayer()->m_Controlled.end(); ++itr) if ((*itr)->GetEntry() == pet->GetEntry()) (*itr)->GetCharmInfo()->ToggleCreatureAutocast(spellInfo, state != 0); charmInfo->SetSpellAutocast(spellInfo, state != 0); }
void WorldSession::SendPetitionQueryOpcode(ObjectGuid petitionguid) { ObjectGuid ownerguid; uint32 type; std::string name = "NO_NAME_FOR_GUID"; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); stmt->setUInt32(0, petitionguid.GetCounter()); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); ownerguid = ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); name = fields[1].GetString(); type = fields[2].GetUInt8(); } else { TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition (%s)", petitionguid.ToString().c_str()); return; } WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10)); data << uint32(petitionguid.GetCounter()); // guild/team guid (in Trinity always same as GUID_LOPART(petition guid) data << uint64(ownerguid); // charter owner guid data << name; // name (guild/arena team) data << uint8(0); // some string if (type == GUILD_CHARTER_TYPE) { uint32 needed = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); data << uint32(needed); data << uint32(needed); data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition } else { data << uint32(type-1); data << uint32(type-1); data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition } data << uint32(0); // 5 data << uint32(0); // 6 data << uint32(0); // 7 data << uint32(0); // 8 data << uint16(0); // 9 2 bytes field data << uint32(0); // 10 data << uint32(0); // 11 data << uint32(0); // 13 count of next strings? for (int i = 0; i < 10; ++i) data << uint8(0); // some string data << uint32(0); // 14 data << uint32(type != GUILD_CHARTER_TYPE); // 15 0 - guild, 1 - arena team SendPacket(&data); }
void WorldSession::SendListInventory(ObjectGuid vendorGuid) { TC_LOG_DEBUG("network", "WORLD: Sent SMSG_LIST_INVENTORY"); Creature* vendor = GetPlayer()->GetNPCIfCanInteractWith(vendorGuid, UNIT_NPC_FLAG_VENDOR); if (!vendor) { TC_LOG_DEBUG("network", "WORLD: SendListInventory - %s not found or you can not interact with him.", vendorGuid.ToString().c_str()); _player->SendSellError(SELL_ERR_CANT_FIND_VENDOR, NULL, ObjectGuid::Empty); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving if (vendor->HasUnitState(UNIT_STATE_MOVING)) vendor->StopMoving(); VendorItemData const* vendorItems = vendor->GetVendorItems(); uint32 rawItemCount = vendorItems ? vendorItems->GetItemCount() : 0; WorldPackets::NPC::VendorInventory packet; packet.Vendor = vendor->GetGUID(); packet.Items.resize(rawItemCount); const float discountMod = _player->GetReputationPriceDiscount(vendor); uint8 count = 0; for (uint32 slot = 0; slot < rawItemCount; ++slot) { VendorItem const* vendorItem = vendorItems->GetItem(slot); if (!vendorItem) continue; WorldPackets::NPC::VendorItem& item = packet.Items[count]; if (vendorItem->Type == ITEM_VENDOR_TYPE_ITEM) { ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(vendorItem->item); if (!itemTemplate) continue; int32 leftInStock = !vendorItem->maxcount ? -1 : vendor->GetVendorItemCurrentCount(vendorItem); if (!_player->IsGameMaster()) // ignore conditions if GM on { // Respect allowed class if (!(itemTemplate->GetAllowableClass() & _player->getClassMask()) && itemTemplate->GetBonding() == BIND_WHEN_PICKED_UP) continue; // Only display items in vendor lists for the team the player is on if ((itemTemplate->GetFlags2() & ITEM_FLAG2_HORDE_ONLY && _player->GetTeam() == ALLIANCE) || (itemTemplate->GetFlags2() & ITEM_FLAG2_ALLIANCE_ONLY && _player->GetTeam() == HORDE)) continue; // Items sold out are not displayed in list if (leftInStock == 0) continue; } if (!sConditionMgr->IsObjectMeetingVendorItemConditions(vendor->GetEntry(), vendorItem->item, _player, vendor)) { TC_LOG_DEBUG("condition", "SendListInventory: conditions not met for creature entry %u item %u", vendor->GetEntry(), vendorItem->item); continue; } int32 price = vendorItem->IsGoldRequired(itemTemplate) ? uint32(floor(itemTemplate->GetBuyPrice() * discountMod)) : 0; if (int32 priceMod = _player->GetTotalAuraModifier(SPELL_AURA_MOD_VENDOR_ITEMS_PRICES)) price -= CalculatePct(price, priceMod); item.MuID = slot + 1; // client expects counting to start at 1 item.Durability = itemTemplate->MaxDurability; item.ExtendedCostID = vendorItem->ExtendedCost; item.Type = vendorItem->Type; item.Quantity = leftInStock; item.StackCount = itemTemplate->GetBuyCount(); item.Price = price; item.Item.ItemID = vendorItem->item; } else if (vendorItem->Type == ITEM_VENDOR_TYPE_CURRENCY) { CurrencyTypesEntry const* currencyTemplate = sCurrencyTypesStore.LookupEntry(vendorItem->item); if (!currencyTemplate) continue; if (!vendorItem->ExtendedCost) continue; // there's no price defined for currencies, only extendedcost is used item.MuID = slot + 1; // client expects counting to start at 1 item.ExtendedCostID = vendorItem->ExtendedCost; item.Item.ItemID = vendorItem->item; item.Type = vendorItem->Type; item.StackCount = vendorItem->maxcount; } else continue; if (++count >= MAX_VENDOR_ITEMS) break; } // Resize vector to real size (some items can be skipped due to checks) packet.Items.resize(count); SendPacket(packet.Write()); }
void WorldSession::HandlePetitionRenameOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode MSG_PETITION_RENAME"); // ok ObjectGuid petitionGuid; uint32 type; std::string newName; recvData >> petitionGuid; // guid recvData >> newName; // new name Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_TYPE); stmt->setUInt32(0, petitionGuid.GetCounter()); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); type = fields[0].GetUInt8(); } else { TC_LOG_DEBUG("network", "CMSG_PETITION_QUERY failed for petition %s", petitionGuid.ToString().c_str()); return; } if (type == GUILD_CHARTER_TYPE) { if (sGuildMgr->GetGuildByName(newName)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, newName); return; } if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, newName); return; } } else { if (sArenaTeamMgr->GetArenaTeamByName(newName)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } if (sObjectMgr->IsReservedName(newName) || !ObjectMgr::IsValidCharterName(newName)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newName, "", ERR_ARENA_TEAM_NAME_INVALID); return; } } stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PETITION_NAME); stmt->setString(0, newName); stmt->setUInt32(1, petitionGuid.GetCounter()); CharacterDatabase.Execute(stmt); TC_LOG_DEBUG("network", "Petition %s renamed to '%s'", petitionGuid.ToString().c_str(), newName.c_str()); WorldPacket data(MSG_PETITION_RENAME, (8+newName.size()+1)); data << uint64(petitionGuid); data << newName; SendPacket(&data); }
void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList"); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - %s not found or you can not interact with him.", guid.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - Training spells not found for %s", guid.ToString().c_str()); return; } WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); data << guid; data << uint32(trainer_spells->trainerType); size_t count_pos = data.wpos(); data << uint32(trainer_spells->spellList.size()); // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; uint32 count = 0; for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) { TrainerSpell const* tSpell = &itr->second; bool valid = true; bool primary_prof_first_rank = false; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (!tSpell->learnedSpell[i]) continue; if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i])) { valid = false; break; } SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(tSpell->learnedSpell[i]); if (learnedSpellInfo && learnedSpellInfo->IsPrimaryProfessionFirstRank()) primary_prof_first_rank = true; } if (!valid) continue; TrainerSpellState state = _player->GetTrainerSpellState(tSpell); data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); data << uint32(floor(tSpell->spellCost * fDiscountMod)); data << uint32(primary_prof_first_rank && can_learn_primary_prof ? 1 : 0); // primary prof. learn confirmation dialog data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state data << uint8(tSpell->reqLevel); data << uint32(tSpell->reqSkill); data << uint32(tSpell->reqSkillValue); //prev + req or req + 0 uint8 maxReq = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (!tSpell->learnedSpell[i]) continue; if (uint32 prevSpellId = sSpellMgr->GetPrevSpellInChain(tSpell->learnedSpell[i])) { data << uint32(prevSpellId); ++maxReq; } if (maxReq == 3) break; SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->learnedSpell[i]); for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) { data << uint32(itr2->second); ++maxReq; } if (maxReq == 3) break; } while (maxReq < 3) { data << uint32(0); ++maxReq; } ++count; } data << strTitle; data.put<uint32>(count_pos, count); SendPacket(&data); }
void WorldSession::HandlePetitionSignOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_SIGN"); // ok Field* fields; ObjectGuid petitionGuid; uint8 unk; recvData >> petitionGuid; // petition guid recvData >> unk; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURES); stmt->setUInt32(0, petitionGuid.GetCounter()); stmt->setUInt32(1, petitionGuid.GetCounter()); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) { TC_LOG_ERROR("network", "Petition %s is not found for player %u %s", petitionGuid.ToString().c_str(), GetPlayer()->GetGUIDLow(), GetPlayer()->GetName().c_str()); return; } fields = result->Fetch(); ObjectGuid ownerGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()); uint64 signs = fields[1].GetUInt64(); uint8 type = fields[2].GetUInt8(); uint32 playerGuid = _player->GetGUIDLow(); if (ownerGuid == _player->GetGUID()) return; // not let enemies sign guild charter if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr->GetPlayerTeamByGUID(ownerGuid)) { if (type != GUILD_CHARTER_TYPE) SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); else Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NOT_ALLIED); return; } if (type != GUILD_CHARTER_TYPE) { if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName().c_str(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S); return; } uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; if (_player->GetArenaTeamId(slot)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName().c_str(), ERR_ALREADY_IN_ARENA_TEAM_S); return; } if (_player->GetArenaTeamIdInvited()) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName().c_str(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } } else { if (_player->GetGuildId()) { Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_IN_GUILD_S, _player->GetName()); return; } if (_player->GetGuildIdInvited()) { Guild::SendCommandResult(this, GUILD_COMMAND_INVITE, ERR_ALREADY_INVITED_TO_GUILD_S, _player->GetName()); return; } } if (++signs > type) // client signs maximum return; // Client doesn't allow to sign petition two times by one character, but not check sign by another character from same account // not allow sign another player from already sign player account stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIG_BY_ACCOUNT); stmt->setUInt32(0, GetAccountId()); stmt->setUInt32(1, petitionGuid.GetCounter()); result = CharacterDatabase.Query(stmt); if (result) { WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionGuid); data << uint64(_player->GetGUID()); data << (uint32)PETITION_SIGN_ALREADY_SIGNED; // close at signer side SendPacket(&data); // update for owner if online if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) owner->GetSession()->SendPacket(&data); return; } stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION_SIGNATURE); stmt->setUInt32(0, ownerGuid.GetCounter()); stmt->setUInt32(1, petitionGuid.GetCounter()); stmt->setUInt32(2, playerGuid); stmt->setUInt32(3, GetAccountId()); CharacterDatabase.Execute(stmt); TC_LOG_DEBUG("network", "PETITION SIGN: %s by player: %s (GUID: %u Account: %u)", petitionGuid.ToString().c_str(), _player->GetName().c_str(), playerGuid, GetAccountId()); WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4)); data << uint64(petitionGuid); data << uint64(_player->GetGUID()); data << uint32(PETITION_SIGN_OK); // close at signer side SendPacket(&data); // update signs count on charter, required testing... //Item* item = _player->GetItemByGuid(petitionguid)); //if (item) // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); // update for owner if online if (Player* owner = ObjectAccessor::FindConnectedPlayer(ownerGuid)) owner->GetSession()->SendPacket(&data); }
void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_GOSSIP_HELLO"); ObjectGuid guid; recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleGossipHelloOpcode - %s not found or you can not interact with him.", guid.ToString().c_str()); return; } // set faction visible if needed if (FactionTemplateEntry const* factionTemplateEntry = sFactionTemplateStore.LookupEntry(unit->getFaction())) _player->GetReputationMgr().SetVisible(factionTemplateEntry); GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); // remove fake death //if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) // GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard()) { unit->StopMoving(); } // If spiritguide, no need for gossip menu, just put player into resurrect queue if (unit->IsSpiritGuide()) { Battleground* bg = _player->GetBattleground(); if (bg) { bg->AddPlayerToResurrectQueue(unit->GetGUID(), _player->GetGUID()); sBattlegroundMgr->SendAreaSpiritHealerQueryOpcode(_player, bg, unit->GetGUID()); return; } } if (!sScriptMgr->OnGossipHello(_player, unit)) { // _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID()); _player->PrepareGossipMenu(unit, unit->GetCreatureTemplate()->GossipMenuId, true); _player->SendPreparedGossip(unit); } unit->AI()->sGossipHello(_player); }
void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_BUY"); ObjectGuid guidNPC; uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client std::string name; recvData >> guidNPC; // NPC GUID recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint64>(); // 0 recvData >> name; // name recvData.read_skip<std::string>(); // some string recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint16>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 recvData.read_skip<uint32>(); // 0 for (int i = 0; i < 10; ++i) recvData.read_skip<std::string>(); recvData >> clientIndex; // index recvData.read_skip<uint32>(); // 0 TC_LOG_DEBUG("network", "Petitioner %s tried sell petition: name %s", guidNPC.ToString().c_str(), name.c_str()); // prevent cheating Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC, UNIT_NPC_FLAG_PETITIONER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandlePetitionBuyOpcode - %s not found or you can't interact with him.", guidNPC.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); uint32 charterid = 0; uint32 cost = 0; uint32 type = 0; if (creature->IsTabardDesigner()) { // if tabard designer, then trying to buy a guild charter. // do not let if already in guild. if (_player->GetGuildId()) return; charterid = GUILD_CHARTER; cost = GUILD_CHARTER_COST; type = GUILD_CHARTER_TYPE; } else { /// @todo find correct opcode if (_player->getLevel() < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) { SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)); return; } switch (clientIndex) // arenaSlot+1 as received from client (1 from 3 case) { case 1: charterid = ARENA_TEAM_CHARTER_2v2; cost = ARENA_TEAM_CHARTER_2v2_COST; type = ARENA_TEAM_CHARTER_2v2_TYPE; break; case 2: charterid = ARENA_TEAM_CHARTER_3v3; cost = ARENA_TEAM_CHARTER_3v3_COST; type = ARENA_TEAM_CHARTER_3v3_TYPE; break; case 3: charterid = ARENA_TEAM_CHARTER_5v5; cost = ARENA_TEAM_CHARTER_5v5_COST; type = ARENA_TEAM_CHARTER_5v5_TYPE; break; default: TC_LOG_DEBUG("network", "unknown selection at buy arena petition: %u", clientIndex); return; } if (_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } } if (type == GUILD_CHARTER_TYPE) { if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, name); return; } if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_INVALID, name); return; } } else { if (sArenaTeamMgr->GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } if (sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); return; } } ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(charterid); if (!pProto) { _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0); return; } if (!_player->HasEnoughMoney(cost)) { //player hasn't got enough money _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, creature, charterid, 0); return; } ItemPosCountVec dest; InventoryResult msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount); if (msg != EQUIP_ERR_OK) { _player->SendEquipError(msg, NULL, NULL, charterid); return; } _player->ModifyMoney(-(int32)cost); Item* charter = _player->StoreNewItem(dest, charterid, true); if (!charter) return; charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) charter->SetState(ITEM_CHANGED, _player); _player->SendNewItem(charter, 1, true, false); // a petition is invalid, if both the owner and the type matches // we checked above, if this player is in an arenateam, so this must be // datacorruption PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_BY_OWNER); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt8(1, type); PreparedQueryResult result = CharacterDatabase.Query(stmt); std::ostringstream ssInvalidPetitionGUIDs; if (result) { do { Field* fields = result->Fetch(); ssInvalidPetitionGUIDs << '\'' << fields[0].GetUInt32() << "', "; } while (result->NextRow()); } // delete petitions with the same guid as this one ssInvalidPetitionGUIDs << '\'' << charter->GetGUIDLow() << '\''; TC_LOG_DEBUG("network", "Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); CharacterDatabase.EscapeString(name); SQLTransaction trans = CharacterDatabase.BeginTransaction(); trans->PAppend("DELETE FROM petition WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); trans->PAppend("DELETE FROM petition_sign WHERE petitionguid IN (%s)", ssInvalidPetitionGUIDs.str().c_str()); stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PETITION); stmt->setUInt32(0, _player->GetGUIDLow()); stmt->setUInt32(1, charter->GetGUIDLow()); stmt->setString(2, name); stmt->setUInt8(3, uint8(type)); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); }
void WorldSession::HandleBankerActivateOpcode(WorldPacket& recvData) { ObjectGuid guid; TC_LOG_DEBUG("network", "WORLD: Received CMSG_BANKER_ACTIVATE"); recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleBankerActivateOpcode - %s not found or you can not interact with him.", guid.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); SendShowBank(guid); }
void WorldSession::HandleTurnInPetitionOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "Received opcode CMSG_TURN_IN_PETITION"); // Get petition guid from packet WorldPacket data; ObjectGuid petitionGuid; recvData >> petitionGuid; // Check if player really has the required petition charter Item* item = _player->GetItemByGuid(petitionGuid); if (!item) return; TC_LOG_DEBUG("network", "Petition %s turned in by %u", petitionGuid.ToString().c_str(), _player->GetGUIDLow()); // Get petition data from db uint32 ownerguidlo; uint32 type; std::string name; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION); stmt->setUInt32(0, petitionGuid.GetCounter()); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) { Field* fields = result->Fetch(); ownerguidlo = fields[0].GetUInt32(); name = fields[1].GetString(); type = fields[2].GetUInt8(); } else { TC_LOG_ERROR("network", "Player %s (guid: %u) tried to turn in petition (%s) that is not present in the database", _player->GetName().c_str(), _player->GetGUIDLow(), petitionGuid.ToString().c_str()); return; } // Only the petition owner can turn in the petition if (_player->GetGUIDLow() != ownerguidlo) return; // Petition type (guild/arena) specific checks if (type == GUILD_CHARTER_TYPE) { // Check if player is already in a guild if (_player->GetGuildId()) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; _player->GetSession()->SendPacket(&data); return; } // Check if guild name is already taken if (sGuildMgr->GetGuildByName(name)) { Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_NAME_EXISTS_S, name); return; } } else { // Check for valid arena bracket (2v2, 3v3, 5v5) uint8 slot = ArenaTeam::GetSlotByType(type); if (slot >= MAX_ARENA_SLOT) return; // Check if player is already in an arena team if (_player->GetArenaTeamId(slot)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return; } // Check if arena team name is already taken if (sArenaTeamMgr->GetArenaTeamByName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } } // Get petition signatures from db uint8 signatures; stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PETITION_SIGNATURE); stmt->setUInt32(0, petitionGuid.GetCounter()); result = CharacterDatabase.Query(stmt); if (result) signatures = uint8(result->GetRowCount()); else signatures = 0; uint32 requiredSignatures; if (type == GUILD_CHARTER_TYPE) requiredSignatures = sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS); else requiredSignatures = type-1; // Notify player if signatures are missing if (signatures < requiredSignatures) { data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; SendPacket(&data); return; } // Proceed with guild/arena team creation // Delete charter item _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true); if (type == GUILD_CHARTER_TYPE) { // Create guild Guild* guild = new Guild; if (!guild->Create(_player, name)) { delete guild; return; } // Register guild and add guild master sGuildMgr->AddGuild(guild); Guild::SendCommandResult(this, GUILD_COMMAND_CREATE, ERR_GUILD_COMMAND_SUCCESS, name); // Add members from signatures for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); guild->AddMember(ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32())); result->NextRow(); } } else { // Receive the rest of the packet in arena team creation case uint32 background, icon, iconcolor, border, bordercolor; recvData >> background >> icon >> iconcolor >> border >> bordercolor; // Create arena team ArenaTeam* arenaTeam = new ArenaTeam(); if (!arenaTeam->Create(_player->GetGUID(), type, name, background, icon, iconcolor, border, bordercolor)) { delete arenaTeam; return; } // Register arena team sArenaTeamMgr->AddArenaTeam(arenaTeam); TC_LOG_DEBUG("network", "PetitonsHandler: Arena team (guid: %u) added to ObjectMgr", arenaTeam->GetId()); // Add members for (uint8 i = 0; i < signatures; ++i) { Field* fields = result->Fetch(); ObjectGuid memberGUID(HIGHGUID_PLAYER, fields[0].GetUInt32()); TC_LOG_DEBUG("network", "PetitionsHandler: Adding arena team (guid: %u) member %s", arenaTeam->GetId(), memberGUID.ToString().c_str()); arenaTeam->AddMember(memberGUID); result->NextRow(); } } SQLTransaction trans = CharacterDatabase.BeginTransaction(); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_BY_GUID); stmt->setUInt32(0, petitionGuid.GetCounter()); trans->Append(stmt); stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PETITION_SIGNATURE_BY_GUID); stmt->setUInt32(0, petitionGuid.GetCounter()); trans->Append(stmt); CharacterDatabase.CommitTransaction(trans); // created TC_LOG_DEBUG("network", "Player %s (%s) turning in petition %s", _player->GetName().c_str(), _player->GetGUID().ToString().c_str(), petitionGuid.ToString().c_str()); data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); data << (uint32)PETITION_TURN_OK; SendPacket(&data); }
void LFGPlayerScript::OnLogin(Player* player, bool /*loginFirst*/) { if (!sLFGMgr->isOptionEnabled(LFG_OPTION_ENABLE_DUNGEON_FINDER | LFG_OPTION_ENABLE_RAID_BROWSER)) return; // Temporal: Trying to determine when group data and LFG data gets desynched ObjectGuid guid = player->GetGUID(); ObjectGuid gguid = sLFGMgr->GetGroup(guid); if (Group const* group = player->GetGroup()) { ObjectGuid gguid2 = group->GetGUID(); if (gguid != gguid2) { TC_LOG_ERROR("lfg", "%s on group %s but LFG has group %s saved... Fixing.", player->GetSession()->GetPlayerInfo().c_str(), gguid2.ToString().c_str(), gguid.ToString().c_str()); sLFGMgr->SetupGroupMember(guid, group->GetGUID()); } } sLFGMgr->SetTeam(player->GetGUID(), player->GetTeam()); /// @todo - Restore LfgPlayerData and send proper status to player if it was in a group }
void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) { ObjectGuid guid; uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; bool isPremade = false; Group* grp = NULL; recvData >> guid; // battlemaster guid recvData >> bgTypeId_; // battleground type id (DBC id) recvData >> instanceId; // instance id, 0 if First Available selected recvData >> joinAsGroup; // join as group if (!sBattlemasterListStore.LookupEntry(bgTypeId_)) { TC_LOG_ERROR("network", "Battleground: invalid bgtype (%u) received. possible cheater? player guid %u", bgTypeId_, _player->GetGUID().GetCounter()); return; } if (DisableMgr::IsDisabledFor(DISABLE_TYPE_BATTLEGROUND, bgTypeId_, NULL)) { ChatHandler(this).PSendSysMessage(LANG_BG_DISABLED); return; } BattlegroundTypeId bgTypeId = BattlegroundTypeId(bgTypeId_); TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from %s", guid.ToString().c_str()); // can do this, since it's battleground, not arena BattlegroundQueueTypeId bgQueueTypeId = BattlegroundMgr::BGQueueTypeId(bgTypeId, 0); BattlegroundQueueTypeId bgQueueTypeIdRandom = BattlegroundMgr::BGQueueTypeId(BATTLEGROUND_RB, 0); // ignore if player is already in BG if (_player->InBattleground()) 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); if (!bg) return; // expected bracket entry PvPDifficultyEntry const* bracketEntry = GetBattlegroundBracketByLevel(bg->GetMapId(), _player->getLevel()); if (!bracketEntry) return; GroupJoinBattlegroundResult err; // check queue conditions if (!joinAsGroup) { if (GetPlayer()->isUsingLfg()) { // player is using dungeon finder or raid finder WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_LFG_CANT_USE_BATTLEGROUND); GetPlayer()->GetSession()->SendPacket(&data); return; } // check Deserter debuff if (!_player->CanJoinToBattleground(bg)) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_GROUP_JOIN_BATTLEGROUND_DESERTERS); _player->GetSession()->SendPacket(&data); return; } if (_player->GetBattlegroundQueueIndex(bgQueueTypeIdRandom) < PLAYER_MAX_BATTLEGROUND_QUEUES) { // player is already in random queue WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_RANDOM_BG); _player->GetSession()->SendPacket(&data); return; } if (_player->InBattlegroundQueue() && bgTypeId == BATTLEGROUND_RB) { // player is already in queue, can't start random queue WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_IN_NON_RANDOM_BG); _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()) { WorldPacket data; sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, ERR_BATTLEGROUND_TOO_MANY_QUEUES); _player->GetSession()->SendPacket(&data); return; } // check Freeze debuff if (_player->HasAura(9454)) return; BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); uint32 avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); // already checked if queueSlot is valid, now just get it uint32 queueSlot = _player->AddBattlegroundQueueId(bgQueueTypeId); WorldPacket data; // send status packet (in queue) sBattlegroundMgr->BuildBattlegroundStatusPacket(&data, bg, queueSlot, STATUS_WAIT_QUEUE, avgTime, 0, ginfo->ArenaType, 0); SendPacket(&data); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, _player->GetGUID().GetCounter(), _player->GetName().c_str()); } else { grp = _player->GetGroup(); // no group found, error if (!grp) return; if (grp->GetLeaderGUID() != _player->GetGUID()) return; err = grp->CanJoinBattlegroundQueue(bg, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); isPremade = (grp->GetMembersCount() >= bg->GetMinPlayersPerTeam()); BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = NULL; uint32 avgTime = 0; if (err > 0) { TC_LOG_DEBUG("bg.battleground", "Battleground: the following players are joining as group:"); ginfo = bgQueue.AddGroup(_player, grp, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); avgTime = bgQueue.GetAverageQueueWaitTime(ginfo, bracketEntry->GetBracketId()); } for (GroupReference* itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player* member = itr->GetSource(); if (!member) continue; // this should never happen 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, ginfo->ArenaType, 0); member->GetSession()->SendPacket(&data); sBattlegroundMgr->BuildGroupJoinedBattlegroundPacket(&data, err); member->GetSession()->SendPacket(&data); TC_LOG_DEBUG("bg.battleground", "Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s", bgQueueTypeId, bgTypeId, member->GetGUID().GetCounter(), member->GetName().c_str()); } TC_LOG_DEBUG("bg.battleground", "Battleground: group end"); } sBattlegroundMgr->ScheduleQueueUpdate(0, 0, bgQueueTypeId, bgTypeId, bracketEntry->GetBracketId()); }