aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Creature/Creature.h6
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp49
-rw-r--r--src/server/game/Server/Packets/ItemPackets.cpp2
-rw-r--r--src/server/game/Server/Packets/NPCPackets.cpp28
-rw-r--r--src/server/game/Server/Packets/NPCPackets.h26
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
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);