Core/Packets: Added SMSG_TRAINER_LIST and fixed build

This commit is contained in:
Intel
2014-11-25 00:40:47 +02:00
parent 0df8e9137a
commit bac37625f3
6 changed files with 83 additions and 30 deletions

View File

@@ -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; }

View File

@@ -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)

View File

@@ -54,4 +54,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const&
for (uint32 itemMod : itemInstance.Modifications)
data << itemMod;
}
return data;
}

View File

@@ -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;
}

View File

@@ -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;
};
}
}

View File

@@ -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);