diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 6 | ||||
-rw-r--r-- | src/server/game/Handlers/NPCHandler.cpp | 49 | ||||
-rw-r--r-- | src/server/game/Server/Packets/ItemPackets.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/Packets/NPCPackets.cpp | 28 | ||||
-rw-r--r-- | src/server/game/Server/Packets/NPCPackets.h | 26 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 2 |
6 files changed, 83 insertions, 30 deletions
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 4f805088548..523a2eb2f4d 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -392,11 +392,13 @@ struct VendorItemCount typedef std::list<VendorItemCount> VendorItemCounts; +#define MAX_TRAINERSPELL_ABILITY_REQS 3 + struct TrainerSpell { TrainerSpell() : SpellID(0), MoneyCost(0), ReqSkillLine(0), ReqSkillRank(0), ReqLevel(0) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + for (uint8 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i) ReqAbility[i] = 0; } @@ -405,7 +407,7 @@ struct TrainerSpell uint32 ReqSkillLine; uint32 ReqSkillRank; uint32 ReqLevel; - uint32 ReqAbility[3]; + uint32 ReqAbility[MAX_TRAINERSPELL_ABILITY_REQS]; // helpers bool IsCastable() const { return ReqAbility[0] != SpellID; } diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp index 0e7ea73700c..90af94f9754 100644 --- a/src/server/game/Handlers/NPCHandler.cpp +++ b/src/server/game/Handlers/NPCHandler.cpp @@ -142,18 +142,16 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) 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()); + WorldPackets::NPC::TrainerList packet; + packet.TrainerGUID = guid; + packet.TrainerType = trainer_spells->trainerType; + packet.Greeting = strTitle; // reputation discount float fDiscountMod = _player->GetReputationPriceDiscount(unit); bool can_learn_primary_prof = GetPlayer()->GetFreePrimaryProfessionPoints() > 0; + packet.Spells.resize(trainer_spells->spellList.size()); uint32 count = 0; for (TrainerSpellMap::const_iterator itr = trainer_spells->spellList.begin(); itr != trainer_spells->spellList.end(); ++itr) { @@ -179,22 +177,23 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) 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)); + WorldPackets::NPC::TrainerListSpell& spell = packet.Spells[count]; + spell.SpellID = tSpell->SpellID; + spell.MoneyCost = floor(tSpell->MoneyCost * fDiscountMod); + spell.ReqSkillLine = tSpell->ReqSkillLine; + spell.ReqSkillRank = tSpell->ReqSkillRank; + spell.ReqLevel = tSpell->ReqLevel; + spell.Usable = (state == TRAINER_SPELL_GREEN_DISABLED ? TRAINER_SPELL_GREEN : 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) + /// @todo Update this when new spell system is ready + /*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); + spell.ReqAbility[maxReq] = prevSpellId; ++maxReq; } if (maxReq == 2) @@ -202,29 +201,25 @@ void WorldSession::SendTrainerList(ObjectGuid guid, const std::string& strTitle) SpellsRequiringSpellMapBounds spellsRequired = sSpellMgr->GetSpellsRequiredForSpellBounds(tSpell->ReqAbility[i]); for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequired.first; itr2 != spellsRequired.second && maxReq < 3; ++itr2) { - data << uint32(itr2->second); + spell.ReqAbility[maxReq] = itr2->second; ++maxReq; } if (maxReq == 2) break; - } - while (maxReq < 2) + }*/ + while (maxReq < MAX_TRAINERSPELL_ABILITY_REQS) { - data << uint32(0); + spell.ReqAbility[maxReq] = 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; + // Shrink to actual data size + packet.Spells.resize(count); - data.put<uint32>(count_pos, count); - SendPacket(&data); + SendPacket(packet.Write()); } void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData) diff --git a/src/server/game/Server/Packets/ItemPackets.cpp b/src/server/game/Server/Packets/ItemPackets.cpp index 4ba9beb016e..924a9eec352 100644 --- a/src/server/game/Server/Packets/ItemPackets.cpp +++ b/src/server/game/Server/Packets/ItemPackets.cpp @@ -54,4 +54,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const& for (uint32 itemMod : itemInstance.Modifications) data << itemMod; } + + return data; } diff --git a/src/server/game/Server/Packets/NPCPackets.cpp b/src/server/game/Server/Packets/NPCPackets.cpp index 9a738d70010..60dbed09f1b 100644 --- a/src/server/game/Server/Packets/NPCPackets.cpp +++ b/src/server/game/Server/Packets/NPCPackets.cpp @@ -90,3 +90,31 @@ WorldPacket const* WorldPackets::NPC::VendorInventory::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::NPC::TrainerList::Write() +{ + _worldPacket << TrainerGUID; + _worldPacket << TrainerType; + _worldPacket << TrainerID; + + _worldPacket << int32(Spells.size()); + for (TrainerListSpell const& spell : Spells) + { + _worldPacket << spell.SpellID; + _worldPacket << spell.MoneyCost; + _worldPacket << spell.ReqSkillLine; + _worldPacket << spell.ReqSkillRank; + + for (uint32 i = 0; i < MAX_TRAINERSPELL_ABILITY_REQS; ++i) + _worldPacket << spell.ReqAbility[i]; + + _worldPacket << spell.Usable; + _worldPacket << spell.ReqLevel; + } + + _worldPacket.WriteBits(Greeting.length(), 11); + _worldPacket.FlushBits(); + _worldPacket.WriteString(Greeting); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/NPCPackets.h b/src/server/game/Server/Packets/NPCPackets.h index b8dbc913b49..221cb454765 100644 --- a/src/server/game/Server/Packets/NPCPackets.h +++ b/src/server/game/Server/Packets/NPCPackets.h @@ -20,6 +20,7 @@ #include "Packet.h" #include "ItemPackets.h" +#include "Creature.h" namespace WorldPackets { @@ -101,6 +102,31 @@ namespace WorldPackets std::vector<VendorItem> Items; ObjectGuid Vendor; }; + + struct TrainerListSpell + { + int32 SpellID = 0; + int32 MoneyCost = 0; + int32 ReqSkillLine = 0; + int32 ReqSkillRank = 0; + int32 ReqAbility[MAX_TRAINERSPELL_ABILITY_REQS]; + uint8 Usable = 0; + uint8 ReqLevel = 0; + }; + + class TrainerList final : public ServerPacket + { + public: + TrainerList() : ServerPacket(SMSG_TRAINER_LIST, 150) { } + + WorldPacket const* Write() override; + + std::string Greeting; + int32 TrainerType = 0; + ObjectGuid TrainerGUID; + int32 TrainerID = 1; + std::vector<TrainerListSpell> Spells; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 5d508f814c3..726a3068de6 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1382,7 +1382,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRADE_STATUS_EXTENDED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_FAILED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_BUY_SUCCEEDED, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRAINER_LIST, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_ABORTED, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRANSFER_PENDING, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TRIGGER_CINEMATIC, STATUS_UNHANDLED); |