void WorldSession::HandleQuestgiverHelloOpcode(WorldPackets::Quest::QuestGiverHello& packet) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_HELLO %s", packet.QuestGiverGUID.ToString().c_str()); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(packet.QuestGiverGUID, UNIT_NPC_FLAG_QUESTGIVER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleQuestgiverHelloOpcode - %s not found or you can't interact with him.", packet.QuestGiverGUID.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving creature->StopMoving(); if (sScriptMgr->OnGossipHello(_player, creature)) return; _player->PrepareGossipMenu(creature, creature->GetCreatureTemplate()->GossipMenuId, true); _player->SendPreparedGossip(creature); creature->AI()->sGossipHello(_player); }
void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recv_data) { uint64 guid; recv_data >> guid; sLog.outDebug ("WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); Creature* pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!pCreature) { sLog.outDebug ("WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guid)); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving if (!pCreature->IsStopped()) pCreature->StopMoving(); if (sScriptMgr.GossipHello(_player, pCreature)) return; _player->PrepareGossipMenu(pCreature, pCreature->GetCreatureTemplate()->GossipMenuId); _player->SendPreparedGossip(pCreature); }
void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData) { uint64 guid; recvData >> guid; TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_HELLO npc = %u", GUID_LOPART(guid)); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleQuestgiverHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guid)); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // Stop the npc if moving creature->StopMoving(); if (sScriptMgr->OnGossipHello(_player, creature)) return; _player->PrepareGossipMenu(creature, creature->GetCreatureTemplate()->GossipMenuId, true); _player->SendPreparedGossip(creature); creature->AI()->sGossipHello(_player); }
void WorldSession::HandleGossipHelloOpcode(WorldPacket & recvData) { ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_GOSSIP_HELLO"); uint64 guid; recvData >> guid; Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) { ;//sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // xinef: check if we have ANY npc flags if (unit->GetUInt32Value(UNIT_NPC_FLAGS) == UNIT_NPC_FLAG_NONE) return; // xinef: do not allow to open gossip when npc is in combat if (unit->GetUInt32Value(UNIT_NPC_FLAGS) == UNIT_NPC_FLAG_GOSSIP && unit->IsInCombat()) // should work on all flags? 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); // xinef: and if he has pure gossip or is banker and moves or is tabard designer? //if (unit->IsArmorer() || unit->IsCivilian() || unit->IsQuestGiver() || unit->IsServiceProvider() || unit->IsGuard()) { //if (!unit->GetTransport()) // pussywizard: reverted with new spline (old: without this check, npc would stay in place and the transport would continue moving, so the npc falls off. NPCs on transports don't have waypoints, so stopmoving is not needed) 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::HandleGossipHelloOpcode(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_GOSSIP_HELLO"); ObjectGuid guid; recvData.ReadGuidMask(guid, 2, 4, 0, 3, 6, 7, 5, 1); recvData.ReadGuidBytes(guid, 4, 7, 1, 0, 5, 3, 6, 2); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); 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 MovementInform(uint32 /*type*/, uint32 id) { Player* player = Unit::GetPlayer(*me, PlayerGUID); if (id == 1) { GameObject* Keg = me->FindNearestGameObject(GO_KEG, 20); if (Keg) Keg->Delete(); me->HandleEmote(7); me->SetReactState(REACT_AGGRESSIVE); me->GetMotionMaster()->MoveTargetedHome(); Creature* Credit = me->FindNearestCreature(NPC_QUEST_CREDIT, 50, true); if (player && Credit) player->KilledMonster(Credit->GetCreatureTemplate(), Credit->GetGUID()); } }
void OPvPCapturePointEP::SummonFlightMaster(uint32 team) { if (EP_TOWER_EVENT_TEAM[EP_TOWER_PLAGUEWOOD] != team) { EP_TOWER_EVENT_TEAM[EP_TOWER_PLAGUEWOOD] = team; DelCreature(EP_PWT_FLIGHTMASTER); AddCreature(EP_PWT_FLIGHTMASTER, EP_PWT_FlightMaster.entry, team, EP_PWT_FlightMaster.map, EP_PWT_FlightMaster.x, EP_PWT_FlightMaster.y, EP_PWT_FlightMaster.z, EP_PWT_FlightMaster.o); // Change the flightmasters's faction to horde and display a red aura around the npc Creature * c = HashMapHolder<Creature>::Find(m_Creatures[EP_PWT_FLIGHTMASTER]); if (c && team == HORDE) { c->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, c->GetCreatureTemplate()->faction_H); c->SetUInt32Value(UNIT_FIELD_AURA, EP_PWT_FlightMasterAura); } } }
//set faction of creature static bool HandleNpcSetFactionIdCommand(ChatHandler* handler, const char* args) { if (!*args) return false; uint32 factionId = (uint32) atoi((char*)args); if (!sFactionTemplateStore.LookupEntry(factionId)) { handler->PSendSysMessage(LANG_WRONG_FACTION, factionId); handler->SetSentErrorMessage(true); return false; } Creature* creature = handler->getSelectedCreature(); if (!creature) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } creature->setFaction(factionId); // Faction is set in creature_template - not inside creature // Update in memory.. if (CreatureTemplate const* cinfo = creature->GetCreatureTemplate()) { const_cast<CreatureTemplate*>(cinfo)->faction_A = factionId; const_cast<CreatureTemplate*>(cinfo)->faction_H = factionId; } // ..and DB PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_CREATURE_FACTION); stmt->setUInt16(0, uint16(factionId)); stmt->setUInt16(1, uint16(factionId)); stmt->setUInt32(2, creature->GetEntry()); WorldDatabase.Execute(stmt); return true; }
static bool HandleNpcInfoCommand(ChatHandler* handler, const char* /*args*/) { Creature* target = handler->getSelectedCreature(); if (!target) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } uint32 faction = target->getFaction(); uint32 npcflags = target->GetUInt32Value(UNIT_NPC_FLAGS); uint32 displayid = target->GetDisplayId(); uint32 nativeid = target->GetNativeDisplayId(); uint32 Entry = target->GetEntry(); CreatureTemplate const* cInfo = target->GetCreatureTemplate(); int64 curRespawnDelay = target->GetRespawnTimeEx()-time(NULL); if (curRespawnDelay < 0) curRespawnDelay = 0; std::string curRespawnDelayStr = secsToTimeString(uint64(curRespawnDelay), true); std::string defRespawnDelayStr = secsToTimeString(target->GetRespawnDelay(), true); handler->PSendSysMessage(LANG_NPCINFO_CHAR, target->GetDBTableGUIDLow(), target->GetGUIDLow(), faction, npcflags, Entry, displayid, nativeid); handler->PSendSysMessage(LANG_NPCINFO_LEVEL, target->getLevel()); handler->PSendSysMessage(LANG_NPCINFO_HEALTH, target->GetCreateHealth(), target->GetMaxHealth(), target->GetHealth()); handler->PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str()); handler->PSendSysMessage(LANG_NPCINFO_LOOT, cInfo->lootid, cInfo->pickpocketLootId, cInfo->SkinLootId); handler->PSendSysMessage(LANG_NPCINFO_DUNGEON_ID, target->GetInstanceId()); handler->PSendSysMessage(LANG_NPCINFO_PHASEMASK, target->GetPhaseMask()); handler->PSendSysMessage(LANG_NPCINFO_ARMOR, target->GetArmor()); handler->PSendSysMessage(LANG_NPCINFO_POSITION, float(target->GetPositionX()), float(target->GetPositionY()), float(target->GetPositionZ())); handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); if (npcflags & UNIT_NPC_FLAG_VENDOR) handler->SendSysMessage(LANG_NPCINFO_VENDOR); if (npcflags & UNIT_NPC_FLAG_TRAINER) handler->SendSysMessage(LANG_NPCINFO_TRAINER); return true; }
void WorldSession::HandleGossipHelloOpcode(WorldPacket& recv_data) { sLog->outDebug("WORLD: Received CMSG_GOSSIP_HELLO"); uint64 guid; recv_data >> guid; Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!unit) { sLog->outDebug("WORLD: HandleGossipHelloOpcode - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } GetPlayer()->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); // remove fake death //if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) // GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); if (unit->isArmorer() || unit->isCivilian() || unit->isQuestGiver() || unit->isServiceProvider()) { 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->GossipHello(_player, unit)) { _player->TalkedToCreature(unit->GetEntry(), unit->GetGUID()); _player->PrepareGossipMenu(unit, unit->GetCreatureTemplate()->GossipMenuId); _player->SendPreparedGossip(unit); } }
void GuildTaskMgr::CheckKillTask(Player* player, Unit* victim) { uint32 owner = player->GetGUID().GetCounter(); Creature* creature = victim->ToCreature(); if (!creature) return; map<uint32,uint32> tasks = GetTaskValues(owner, "killTask"); for (map<uint32,uint32>::iterator i = tasks.begin(); i != tasks.end(); ++i) { uint32 guildId = i->first; uint32 value = i->second; Guild* guild = sGuildMgr->GetGuildById(guildId); if (value != creature->GetCreatureTemplate()->Entry) continue; sLog->outMessage("gtask", LOG_LEVEL_DEBUG, "%s / %s: guild task complete", guild->GetName().c_str(), player->GetName().c_str()); SetTaskValue(owner, guildId, "reward", 1, urand(sPlayerbotAIConfig.minGuildTaskRewardTime, sPlayerbotAIConfig.maxGuildTaskRewardTime)); ChatHandler(player->GetSession()).PSendSysMessage("You have completed a guild task"); } }
//npc tame handling static bool HandleNpcTameCommand(ChatHandler* handler, const char* /*args*/) { Creature* creatureTarget = handler->getSelectedCreature(); if (!creatureTarget || creatureTarget->isPet()) { handler->PSendSysMessage (LANG_SELECT_CREATURE); handler->SetSentErrorMessage (true); return false; } Player* player = handler->GetSession()->GetPlayer(); if (player->GetPetGUID()) { handler->SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); handler->SetSentErrorMessage (true); return false; } CreatureTemplate const* cInfo = creatureTarget->GetCreatureTemplate(); if (!cInfo->isTameable (player->CanTameExoticPets())) { handler->PSendSysMessage (LANG_CREATURE_NON_TAMEABLE, cInfo->Entry); handler->SetSentErrorMessage (true); return false; } // Everything looks OK, create new pet Pet* pet = player->CreateTamedPetFrom(creatureTarget); if (!pet) { handler->PSendSysMessage (LANG_CREATURE_NON_TAMEABLE, cInfo->Entry); handler->SetSentErrorMessage (true); return false; } // place pet before player float x, y, z; player->GetClosePoint (x, y, z, creatureTarget->GetObjectSize(), CONTACT_DISTANCE); pet->Relocate(x, y, z, M_PI-player->GetOrientation()); // set pet to defensive mode by default (some classes can't control controlled pets in fact). pet->SetReactState(REACT_DEFENSIVE); // calculate proper level uint8 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); // add to world pet->GetMap()->AddToMap(pet->ToCreature()); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); player->PetSpellInitialize(); return true; }
void WorldSession::SendTrainerList(uint64 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 - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); CreatureTemplate const* ci = unit->GetCreatureTemplate(); if (!ci) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid)); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { TC_LOG_DEBUG("network", "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", GUID_LOPART(guid), unit->GetEntry()); return; } ObjectGuid oGuid = guid; WorldPacket data(SMSG_TRAINER_LIST, 1 + 8 + 4 + (trainer_spells->spellList.size() * 30) + 4 + 4 + strTitle.size()); data.WriteBit(oGuid[4]); data.WriteBit(oGuid[5]); size_t count_pos = data.bitwpos(); data.WriteBits(0, 19); // placeholder data.WriteBits(strTitle.size(), 11); data.WriteBit(oGuid[6]); data.WriteBit(oGuid[2]); data.WriteBit(oGuid[7]); data.WriteBit(oGuid[1]); data.WriteBit(oGuid[3]); data.WriteBit(oGuid[0]); data.FlushBits(); data.WriteByteSeq(oGuid[4]); // 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; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (!tSpell->learnedSpell[i]) continue; if (!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell[i])) { valid = false; break; } } if (!valid) continue; data << uint8(tSpell->reqLevel); data << uint32(floor(tSpell->spellCost * fDiscountMod)); data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) // spells required (3 max) uint8 maxReq = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (!tSpell->learnedSpell[i]) continue; 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; } data << uint32(tSpell->reqSkill); data << uint32(tSpell->reqSkillValue); TrainerSpellState state = _player->GetTrainerSpellState(tSpell); data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); ++count; } data.WriteString(strTitle); data.WriteByteSeq(oGuid[6]); data.WriteByteSeq(oGuid[7]); data.WriteByteSeq(oGuid[1]); data.WriteByteSeq(oGuid[3]); data << uint32(1); // different value for each trainer, also found in CMSG_TRAINER_BUY_SPELL data.WriteByteSeq(oGuid[5]); data.WriteByteSeq(oGuid[0]); data.WriteByteSeq(oGuid[2]); data << uint32(trainer_spells->trainerType); data.PutBits(count_pos, count, 19); SendPacket(&data); }
static bool HandlePetCreateCommand(ChatHandler* handler, char const* /*args*/) { Player* player = handler->GetSession()->GetPlayer(); Creature* creatureTarget = handler->getSelectedCreature(); if (!creatureTarget || creatureTarget->IsPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) { handler->PSendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } CreatureTemplate const* creatureTemplate = creatureTarget->GetCreatureTemplate(); // Creatures with family CREATURE_FAMILY_NONE crashes the server if (creatureTemplate->family == CREATURE_FAMILY_NONE) { handler->PSendSysMessage("This creature cannot be tamed. Family id: 0 (CREATURE_FAMILY_NONE)."); handler->SetSentErrorMessage(true); return false; } if (player->GetPetGUID()) { handler->PSendSysMessage("You already have a pet"); handler->SetSentErrorMessage(true); return false; } // Everything looks OK, create new pet Pet* pet = new Pet(player, HUNTER_PET); if (!pet->CreateBaseAtCreature(creatureTarget)) { delete pet; handler->PSendSysMessage("Error 1"); return false; } creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view pet->SetGuidValue(UNIT_FIELD_CREATEDBY, player->GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); if (!pet->InitStatsForLevel(creatureTarget->getLevel())) { TC_LOG_ERROR("misc", "InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); handler->PSendSysMessage("Error 2"); delete pet; return false; } // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()-1); pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); // this enables pet details window (Shift+P) pet->InitPetCreateSpells(); pet->SetFullHealth(); pet->GetMap()->AddToMap(pet->ToCreature()); // visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()); player->SetMinion(pet, true); pet->SavePetToDB(PET_SAVE_AS_CURRENT); player->PetSpellInitialize(); return true; }
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* trainer = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!trainer) { 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 race for mount trainers if (trainer->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_MOUNTS) { if (uint32 trainerRace = trainer->GetCreatureTemplate()->trainer_race) if (_player->getRace() != trainerRace) return; } // check class for class trainers if (_player->getClass() != trainer->GetCreatureTemplate()->trainer_class && trainer->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS) return; // check present spell in trainer spell list TrainerSpellData const* trainer_spells = trainer->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(trainer))); // check money requirement if (!_player->HasEnoughMoney(nSpellCost)) return; _player->ModifyMoney(-int32(nSpellCost)); trainer->SendPlaySpellVisual(179); // 53 SpellCastDirected trainer->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::SendTrainerList(uint64 guid, const std::string& strTitle) { sLog->outDebug("WORLD: SendTrainerList"); Creature *unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog->outDebug("WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); // trainer list loaded at check; if (!unit->isCanTrainingOf(_player, true)) return; CreatureTemplate const* ci = unit->GetCreatureTemplate(); if (!ci) { sLog->outDebug("WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid)); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { sLog->outDebug("WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", GUID_LOPART(guid), unit->GetEntry()); 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); uint32 count = 0; for (TrainerSpellList::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) { TrainerSpell const* tSpell = *itr; if (!_player->IsSpellFitByClassAndRace(tSpell->spell)) continue; ++count; bool primary_prof_first_rank = sSpellMgr->IsPrimaryProfessionFirstRankSpell(tSpell->spell); SpellChainNode const* chain_node = sSpellMgr->GetSpellChainNode(tSpell->spell); uint32 req_spell = sSpellMgr->GetSpellRequired(tSpell->spell); data << uint32(tSpell->spell); data << uint8(_player->GetTrainerSpellState(tSpell)); data << uint32(floor(tSpell->spellcost * fDiscountMod)); data << uint32(primary_prof_first_rank ? 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); data << uint32(chain_node && chain_node->prev ? chain_node->prev : req_spell); data << uint32(chain_node && chain_node->prev ? req_spell : 0); data << uint32(0); } data << strTitle; data.put<uint32>(count_pos, count); SendPacket(&data); }
void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket & recv_data) { bool isCurrency = recv_data.GetOpcode() == CMSG_AUTOSTORE_LOOT_CURRENCY; sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_AUTOSTORE_LOOT_ITEM"); Player* player = GetPlayer(); uint64 lguid = player->GetLootGUID(); Loot* loot = NULL; uint8 lootSlot = 0; uint32 objEntry = 0; uint32 objType = 0; recv_data >> lootSlot; if (IS_GAMEOBJECT_GUID(lguid)) { GameObject* go = player->GetMap()->GetGameObject(lguid); // not check distance for GO in case owned GO (fishing bobber case, for example) or Fishing hole GO if (!go || ((go->GetOwnerGUID() != _player->GetGUID() && go->GetGoType() != GAMEOBJECT_TYPE_FISHINGHOLE) && !go->IsWithinDistInMap(_player, INTERACTION_DISTANCE))) { player->SendLootRelease(lguid); return; } objEntry = go->GetGOInfo()->entry; objType = 3; loot = &go->loot; } else if (IS_ITEM_GUID(lguid)) { Item* pItem = player->GetItemByGuid(lguid); if (!pItem) { player->SendLootRelease(lguid); return; } objEntry = pItem->GetTemplate()->ItemId; objType = 2; loot = &pItem->loot; } else if (IS_CORPSE_GUID(lguid)) { Corpse* bones = ObjectAccessor::GetCorpse(*player, lguid); if (!bones) { player->SendLootRelease(lguid); return; } loot = &bones->loot; } else { Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid); bool ok_loot = creature && creature->isAlive() == (player->getClass() == CLASS_ROGUE && creature->lootForPickPocketed); if (!ok_loot || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE)) { player->SendLootRelease(lguid); return; } objEntry = creature->GetCreatureTemplate()->Entry; objType = 1; loot = &creature->loot; } if (isCurrency && loot) { uint8 currencys = 0; std::list<CurrencyLoot> temp = sObjectMgr->GetCurrencyLoot(objEntry, objType); for (std::list<CurrencyLoot>::iterator i = temp.begin(); i != temp.end(); ++i) { if (currencys == lootSlot) player->SetCurrency(i->CurrencyId, i->CurrencyAmount * 100); ++currencys; } } else if (loot) player->StoreLootItem(lootSlot, loot); }
void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList"); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // trainer list loaded at check; if (!unit->isCanTrainingOf(_player, true)) return; CreatureTemplate const* ci = unit->GetCreatureTemplate(); if (!ci) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid)); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", GUID_LOPART(guid), unit->GetEntry()); return; } WorldPacket data(SMSG_TRAINER_LIST, 8+4+4+trainer_spells->spellList.size()*38 + strTitle.size()+1); data << guid; data << uint32(trainer_spells->trainerType); data << uint32(1); // different value for each trainer, also found in CMSG_TRAINER_BUY_SPELL 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 << 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 == 2) 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 == 2) break; } while (maxReq < 2) { data << uint32(0); ++maxReq; } 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 ++count; } data << strTitle; data.put<uint32>(count_pos, count); SendPacket(&data); }
void LootObject::Refresh(Player* bot, ObjectGuid guid) { skillId = SKILL_NONE; reqSkillValue = 0; reqItem = NULL; this->guid = ObjectGuid(); PlayerbotAI* ai = bot->GetPlayerbotAI(); Creature *creature = ai->GetCreature(guid); if (creature && creature->getDeathState() == CORPSE) { if (creature->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE)) this->guid = guid; if (creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE)) { skillId = creature->GetCreatureTemplate()->GetRequiredLootSkill(); uint32 targetLevel = creature->getLevel(); reqSkillValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel - 10) * 10 : targetLevel * 5; if (bot->HasSkill(skillId) && bot->GetSkillValue(skillId) >= reqSkillValue) this->guid = guid; } return; } GameObject* go = ai->GetGameObject(guid); if (go && go->isSpawned()) { uint32 lockId = go->GetGOInfo()->GetLockId(); LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); if (!lockInfo) return; // TODO: remove? /*for(uint32 i = 0; i < 6; ++i) { if (go->GetGOInfo()->questItems[i]) { this->guid = guid; return; } }*/ for (int i = 0; i < 8; ++i) { switch (lockInfo->Type[i]) { case LOCK_KEY_ITEM: if (lockInfo->Index[i] > 0) { reqItem = lockInfo->Index[i]; this->guid = guid; } break; case LOCK_KEY_SKILL: if (SkillByLockType(LockType(lockInfo->Index[i])) > 0) { skillId = SkillByLockType(LockType(lockInfo->Index[i])); reqSkillValue = lockInfo->Skill[i]; this->guid = guid; } break; default: break; } } } }
bool GossipHelloAction::Execute(Event event) { ObjectGuid guid; WorldPacket &p = event.getPacket(); if (p.empty()) { Player* master = GetMaster(); if (master && master->GetSelectedUnit()) guid = master->GetSelectedUnit()->GetGUID(); } else { p.rpos(0); p >> guid; } if (!guid) return false; Creature *pCreature = bot->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_NONE); if (!pCreature) { sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "[PlayerbotMgr]: HandleMasterIncomingPacket - Received CMSG_GOSSIP_HELLO %d not found or you can't interact with him.", guid.GetRawValue()); return false; } GossipMenuItemsMapBounds pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBounds(pCreature->GetCreatureTemplate()->GossipMenuId); if (pMenuItemBounds.first == pMenuItemBounds.second) return false; WorldPacket p1; p1 << guid; bot->GetSession()->HandleGossipHelloOpcode(p1); bot->SetFacingToObject(pCreature); ostringstream out; out << "--- " << pCreature->GetName() << " ---"; ai->TellMasterNoFacing(out.str()); GossipMenu& menu = bot->PlayerTalkClass->GetGossipMenu(); int i = 0, loops = 0; set<uint32> alreadyTalked; while (i < menu.GetMenuItemCount() && loops++ < 100) { GossipMenuItem const* item = menu.GetItem(i); ai->TellMasterNoFacing(item->Message); if (item->OptionType < 1000 && item->OptionType != GOSSIP_OPTION_GOSSIP) { i++; continue; } WorldPacket p1; std::string code; p1 << guid << menu.GetMenuId() << i << code; bot->GetSession()->HandleGossipSelectOptionOpcode(p1); i = 0; } bot->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID()); return true; }
static bool HandleNpcBotSpawnCommand(ChatHandler* handler, const char* args) { if (!*args) { handler->SendSysMessage(".npcbot spawn"); handler->SendSysMessage("Adds new npcbot spawn of given entry in world. You can shift-link the npc"); handler->SendSysMessage("Syntax: .npcbot spawn #entry"); handler->SetSentErrorMessage(true); return false; } char* charID = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); if (!charID) return false; uint32 id = atoi(charID); CreatureTemplate const* creInfo = sObjectMgr->GetCreatureTemplate(id); if (!creInfo) { handler->PSendSysMessage("creature %u does not exist!", id); handler->SetSentErrorMessage(true); return false; } if (!(creInfo->flags_extra & CREATURE_FLAG_EXTRA_NPCBOT)) { handler->PSendSysMessage("creature %u is not a npcbot!", id); handler->SetSentErrorMessage(true); return false; } PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_NPCBOT_OWNER); //"SELECT owner FROM character_npcbot WHERE entry = ?", CONNECTION_SYNCH stmt->setUInt32(0, id); PreparedQueryResult res1 = CharacterDatabase.Query(stmt); if (res1) { handler->PSendSysMessage("Npcbot %u already exists in `characters_npcbot` table!", id); handler->SendSysMessage("If you want to replace this bot to new location use '.npc move' command"); handler->SetSentErrorMessage(true); return false; } stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_BY_ID); //"SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH stmt->setUInt32(0, id); PreparedQueryResult res2 = WorldDatabase.Query(stmt); if (res2) { handler->PSendSysMessage("Npcbot %u already exists in `creature` table!", id); handler->SetSentErrorMessage(true); return false; } Player* chr = handler->GetSession()->GetPlayer(); if (chr->GetTransport()) { handler->SendSysMessage("Cannot spawn bots on transport!"); handler->SetSentErrorMessage(true); return false; } float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); Map* map = chr->GetMap(); if (map->Instanceable()) { handler->SendSysMessage("Cannot spawn bots in instances!"); handler->SetSentErrorMessage(true); return false; } Creature* creature = new Creature(); if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMgr().GetPhaseMaskForSpawn(), id, 0, 0, x, y, z, o, 0)) { delete creature; return false; } uint8 roleMask = BOT_ROLE_DPS; uint8 m_class = creature->GetCreatureTemplate()->trainer_class; if (!(m_class == CLASS_WARRIOR || m_class == CLASS_ROGUE || m_class == CLASS_PALADIN || m_class == CLASS_DEATH_KNIGHT || m_class == CLASS_SHAMAN || m_class == BOT_CLASS_BM)) roleMask |= BOT_ROLE_RANGED; if (m_class == CLASS_PRIEST || m_class == CLASS_DRUID || m_class == CLASS_SHAMAN || m_class == CLASS_PALADIN) roleMask |= BOT_ROLE_HEAL; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_NPCBOT); //"INSERT INTO characters_npcbot (entry, roles) VALUES (?, ?)", CONNECTION_SYNCH stmt->setUInt32(0, id); stmt->setUInt8(1, roleMask); CharacterDatabase.DirectExecute(stmt); creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMgr().GetPhaseMaskForSpawn()); uint32 db_guid = creature->GetDBTableGUIDLow(); if (!creature->LoadBotCreatureFromDB(db_guid, map)) { handler->SendSysMessage("Cannot load npcbot from DB!"); handler->SetSentErrorMessage(true); //return false; delete creature; return false; } sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid)); handler->SendSysMessage("Npcbot successfully spawned."); return true; }
void WorldSession::HandleGossipSelectOptionOpcode(WorldPackets::NPC::GossipSelectOption& packet) { if (!_player->PlayerTalkClass->GetGossipMenu().GetItem(packet.GossipIndex)) return; // Prevent cheating on C++ scripted menus if (_player->PlayerTalkClass->GetGossipMenu().GetSenderGUID() != packet.GossipUnit) return; Creature* unit = nullptr; GameObject* go = nullptr; if (packet.GossipUnit.IsCreatureOrVehicle()) { unit = GetPlayer()->GetNPCIfCanInteractWith(packet.GossipUnit, UNIT_NPC_FLAG_NONE); if (!unit) { TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found or you can't interact with him.", packet.GossipUnit.ToString().c_str()); return; } } else if (packet.GossipUnit.IsGameObject()) { go = _player->GetMap()->GetGameObject(packet.GossipUnit); if (!go) { TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - %s not found.", packet.GossipUnit.ToString().c_str()); return; } } else { TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - unsupported %s.", packet.GossipUnit.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); if ((unit && unit->GetCreatureTemplate()->ScriptID != unit->LastUsedScriptID) || (go && go->GetGOInfo()->ScriptId != go->LastUsedScriptID)) { TC_LOG_DEBUG("network", "WORLD: HandleGossipSelectOptionOpcode - Script reloaded while in use, ignoring and set new scipt id"); if (unit) unit->LastUsedScriptID = unit->GetCreatureTemplate()->ScriptID; if (go) go->LastUsedScriptID = go->GetGOInfo()->ScriptId; _player->PlayerTalkClass->SendCloseGossip(); return; } if (!packet.PromotionCode.empty()) { if (unit) { unit->AI()->sGossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode.c_str()); if (!sScriptMgr->OnGossipSelectCode(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode.c_str())) _player->OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); } else { go->AI()->GossipSelectCode(_player, packet.GossipID, packet.GossipIndex, packet.PromotionCode.c_str()); if (!sScriptMgr->OnGossipSelectCode(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex), packet.PromotionCode.c_str())) _player->OnGossipSelect(go, packet.GossipIndex, packet.GossipID); } } else { if (unit) { unit->AI()->sGossipSelect(_player, packet.GossipID, packet.GossipIndex); if (!sScriptMgr->OnGossipSelect(_player, unit, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex))) _player->OnGossipSelect(unit, packet.GossipIndex, packet.GossipID); } else { go->AI()->GossipSelect(_player, packet.GossipID, packet.GossipIndex); if (!sScriptMgr->OnGossipSelect(_player, go, _player->PlayerTalkClass->GetGossipOptionSender(packet.GossipIndex), _player->PlayerTalkClass->GetGossipOptionAction(packet.GossipIndex))) _player->OnGossipSelect(go, packet.GossipIndex, packet.GossipID); } } }
void WorldSession::SendTrainerList(uint64 guid, const std::string &strTitle) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList"); Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); if (!unit) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - Unit (GUID: %u) not found or you can not interact with him.", uint32(GUID_LOPART(guid))); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); // trainer list loaded at check; if (!unit->isCanTrainingOf(_player, true)) return; CreatureTemplate const *creatureInfo = unit->GetCreatureTemplate(); if (!creatureInfo) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!", GUID_LOPART(guid)); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if (!trainer_spells) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", GUID_LOPART(guid), unit->GetEntry()); return; } WorldPacket data(SMSG_TRAINER_LIST, 8 + 4 + 4 + trainer_spells->spellList.size() * 38 + strTitle.size() + 1); data << guid; data << uint32(trainer_spells->trainerType); data << uint32(1); size_t count_pos = data.wpos(); data << uint32(trainer_spells->spellList.size()); // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); uint32 count = 0; for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) { TrainerSpell const* tSpell = &itr->second; TrainerSpellState state = _player->GetTrainerSpellState(tSpell); data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) data << uint8(state); data << uint32(floor(tSpell->spellCost * fDiscountMod)); data << uint8(tSpell->reqLevel); data << uint32(tSpell->reqSkill); data << uint32(tSpell->reqSkillValue); data << uint32(0); data << uint32(0); data << uint32(0); data << uint32(0); ++count; } data << strTitle; data.put<uint32>(count_pos, count); SendPacket(&data); }