diff options
Diffstat (limited to 'src/server/game/Handlers/NPCHandler.cpp')
-rw-r--r-- | src/server/game/Handlers/NPCHandler.cpp | 183 |
1 files changed, 26 insertions, 157 deletions
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 5b50075d2fd..dbbf3b6fe03 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -29,6 +29,7 @@ #include "Language.h" #include "Log.h" #include "Map.h" +#include "NPCPackets.h" #include "Opcodes.h" #include "ObjectMgr.h" #include "Pet.h" @@ -38,6 +39,7 @@ #include "ScriptMgr.h" #include "SpellInfo.h" #include "SpellMgr.h" +#include "Trainer.h" #include "World.h" #include "WorldPacket.h" @@ -114,135 +116,45 @@ void WorldSession::SendShowMailBox(ObjectGuid guid) SendPacket(&data); } -void WorldSession::HandleTrainerListOpcode(WorldPacket& recvData) +void WorldSession::HandleTrainerListOpcode(WorldPackets::NPC::Hello& packet) { - ObjectGuid guid; - - recvData >> guid; - SendTrainerList(guid); -} - -void WorldSession::SendTrainerList(ObjectGuid guid) -{ - std::string str = GetTrinityString(LANG_NPC_TAINER_HELLO); - SendTrainerList(guid, str); -} - -void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) -{ - Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_TRAINER); - if (!unit) + Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(packet.Unit, UNIT_NPC_FLAG_TRAINER); + if (!npc) { - TC_LOG_DEBUG("network", "WORLD: SendTrainerList - %s not found or you can not interact with him.", guid.ToString().c_str()); + TC_LOG_DEBUG("network", "WorldSession: SendTrainerList - %s not found or you can not interact with him.", packet.Unit.ToString().c_str()); return; } + if (sObjectMgr->GetTrainer(npc->GetEntry())) + SendTrainerList(npc); + else + TC_LOG_DEBUG("network", "WorldSession::SendTrainerList - Creature id %u has no trainer data.", npc->GetEntry()); +} + +void WorldSession::SendTrainerList(Creature* npc) +{ // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); - TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); - if (!trainer_spells) + Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(npc->GetEntry()); + if (!trainer) { - TC_LOG_DEBUG("network", "WORLD: SendTrainerList - Training spells not found for %s", guid.ToString().c_str()); + TC_LOG_DEBUG("network", "WorldSession: SendTrainerList - trainer spells not found for %s", npc->GetGUID().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->ReqAbility[i]) - continue; - if (!_player->IsSpellFitByClassAndRace(tSpell->ReqAbility[i])) - { - valid = false; - break; - } - SpellInfo const* learnedSpellInfo = sSpellMgr->GetSpellInfo(tSpell->ReqAbility[i]); - if (learnedSpellInfo && learnedSpellInfo->IsPrimaryProfessionFirstRank()) - primary_prof_first_rank = true; - } - if (!valid) - continue; - - TrainerSpellState state = _player->GetTrainerSpellState(tSpell); - - data << uint32(tSpell->SpellID); // learned spell (or cast-spell in profession case) - data << uint8(state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : state); - data << uint32(floor(tSpell->MoneyCost * 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->ReqSkillLine); - data << uint32(tSpell->ReqSkillRank); - //prev + req or req + 0 - uint8 maxReq = 0; - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (!tSpell->ReqAbility[i]) - continue; - if (uint32 prevSpellId = sSpellMgr->GetPrevSpellInChain(tSpell->ReqAbility[i])) - { - data << uint32(prevSpellId); - ++maxReq; - } - if (maxReq == 3) - break; - SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->ReqAbility[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); + trainer->SendSpells(npc, _player, GetSessionDbLocaleIndex()); } -void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) +void WorldSession::HandleTrainerBuySpellOpcode(WorldPackets::NPC::TrainerBuySpell& packet) { - ObjectGuid guid; - uint32 spellId = 0; + TC_LOG_DEBUG("network", "WORLD: Received CMSG_TRAINER_BUY_SPELL %s, learn spell id is: %u", packet.TrainerGUID.ToString().c_str(), packet.SpellID); - 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) + Creature* npc = GetPlayer()->GetNPCIfCanInteractWith(packet.TrainerGUID, UNIT_NPC_FLAG_TRAINER); + if (!npc) { - TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", guid.ToString().c_str()); + TC_LOG_DEBUG("network", "WORLD: HandleTrainerBuySpellOpcode - %s not found or you can not interact with him.", packet.TrainerGUID.ToString().c_str()); return; } @@ -250,54 +162,11 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) 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->MoneyCost * _player->GetReputationPriceDiscount(trainer))); - - // check money requirement - if (!_player->HasEnoughMoney(nSpellCost)) + Trainer::Trainer const* trainer = sObjectMgr->GetTrainer(npc->GetEntry()); + if (!trainer) 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->SpellID, 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); + trainer->TeachSpell(npc, _player, packet.SpellID); } void WorldSession::HandleGossipHelloOpcode(WorldPacket& recvData) |