mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-22 18:15:31 +01:00
Core/Packets: Added SMSG_TRAINER_LIST and fixed build
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -54,4 +54,6 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Item::ItemInstance const&
|
||||
for (uint32 itemMod : itemInstance.Modifications)
|
||||
data << itemMod;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user