Core/Packet: convert query packets into new system.

- Extra c++11-ification of existing code
- Refs #18637
This commit is contained in:
ariel-
2017-02-20 18:08:40 -03:00
parent c274ea8a98
commit dd1aa64563
15 changed files with 1019 additions and 352 deletions

View File

@@ -49,6 +49,8 @@
#include "Transport.h"
#include "ScriptedGossip.h"
#include "Packets/QueryPackets.h"
TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
{
TrainerSpellMap::const_iterator itr = spellList.find(spell_id);
@@ -158,7 +160,7 @@ void CreatureTemplate::InitializeQueryData()
WorldPacket CreatureTemplate::BuildQueryData(LocaleConstant loc) const
{
WorldPacket queryTemp(SMSG_CREATURE_QUERY_RESPONSE, 200);
WorldPackets::Query::QueryCreatureResponse queryTemp;
std::string locName = Name, locTitle = Title;
if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(Entry))
@@ -167,39 +169,35 @@ WorldPacket CreatureTemplate::BuildQueryData(LocaleConstant loc) const
ObjectMgr::GetLocaleString(cl->Title, loc, locTitle);
}
queryTemp << uint32(Entry); // creature entry
queryTemp << locName;
queryTemp << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
queryTemp << locTitle;
queryTemp << IconName; // "Directions" for guard, string for Icons 2.3.0
queryTemp << uint32(type_flags); // flags
queryTemp << uint32(type); // CreatureType.dbc
queryTemp << uint32(family); // CreatureFamily.dbc
queryTemp << uint32(rank); // Creature Rank (elite, boss, etc)
queryTemp << uint32(KillCredit[0]); // new in 3.1, kill credit
queryTemp << uint32(KillCredit[1]); // new in 3.1, kill credit
queryTemp << uint32(Modelid1); // Modelid1
queryTemp << uint32(Modelid2); // Modelid2
queryTemp << uint32(Modelid3); // Modelid3
queryTemp << uint32(Modelid4); // Modelid4
queryTemp << float(ModHealth); // dmg/hp modifier
queryTemp << float(ModMana); // dmg/mana modifier
queryTemp << uint8(RacialLeader);
queryTemp.CreatureID = Entry;
queryTemp.Allow = true;
CreatureQuestItemList const* items = sObjectMgr->GetCreatureQuestItemList(Entry);
if (items)
{
for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
queryTemp << (i < items->size() ? uint32((*items)[i]) : uint32(0));
}
else
{
for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
queryTemp << uint32(0);
}
queryTemp.Stats.Name = locName;
queryTemp.Stats.NameAlt = locTitle;
queryTemp.Stats.CursorName = IconName;
queryTemp.Stats.Flags = type_flags;
queryTemp.Stats.CreatureType = type;
queryTemp.Stats.CreatureFamily = family;
queryTemp.Stats.Classification = rank;
memcpy(queryTemp.Stats.ProxyCreatureID, KillCredit, sizeof(uint32) * MAX_KILL_CREDIT);
queryTemp.Stats.CreatureDisplayID[0] = Modelid1;
queryTemp.Stats.CreatureDisplayID[1] = Modelid2;
queryTemp.Stats.CreatureDisplayID[2] = Modelid3;
queryTemp.Stats.CreatureDisplayID[3] = Modelid4;
queryTemp.Stats.HpMulti = ModHealth;
queryTemp.Stats.EnergyMulti = ModMana;
queryTemp.Stats.Leader = RacialLeader;
queryTemp << uint32(movementId); // CreatureMovementInfo.dbc
return queryTemp;
for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
queryTemp.Stats.QuestItems[i] = 0;
if (CreatureQuestItemList const* items = sObjectMgr->GetCreatureQuestItemList(Entry))
for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i)
if (i < items->size())
queryTemp.Stats.QuestItems[i] = (*items)[i];
queryTemp.Stats.CreatureMovementInfoID = movementId;
return *queryTemp.Write();
}
bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)

View File

@@ -33,6 +33,8 @@
#include "World.h"
#include "Transport.h"
#include "Packets/QueryPackets.h"
void GameObjectTemplate::InitializeQueryData()
{
WorldPacket queryTemp;
@@ -45,7 +47,7 @@ void GameObjectTemplate::InitializeQueryData()
WorldPacket GameObjectTemplate::BuildQueryData(LocaleConstant loc) const
{
WorldPacket queryTemp(SMSG_GAMEOBJECT_QUERY_RESPONSE, 200);
WorldPackets::Query::QueryGameObjectResponse queryTemp;
std::string locName = name;
std::string locIconName = IconName;
@@ -57,30 +59,27 @@ WorldPacket GameObjectTemplate::BuildQueryData(LocaleConstant loc) const
ObjectMgr::GetLocaleString(gameObjectLocale->CastBarCaption, loc, locCastBarCaption);
}
queryTemp << uint32(entry);
queryTemp << uint32(type);
queryTemp << uint32(displayId);
queryTemp << locName;
queryTemp << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4
queryTemp << locIconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword)
queryTemp << locCastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting")
queryTemp << unk1; // 2.0.3, string
queryTemp.append(raw.data, MAX_GAMEOBJECT_DATA);
queryTemp << float(size); // go size
queryTemp.GameObjectID = entry;
queryTemp.Allow = true;
GameObjectQuestItemList const* items = sObjectMgr->GetGameObjectQuestItemList(entry);
if (items)
{
for (size_t i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
queryTemp << (i < items->size() ? uint32((*items)[i]) : uint32(0));
}
else
{
for (size_t i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
queryTemp << uint32(0);
}
queryTemp.Stats.Type = type;
queryTemp.Stats.DisplayID = displayId;
queryTemp.Stats.Name = locName;
queryTemp.Stats.IconName = locIconName;
queryTemp.Stats.CastBarCaption = locCastBarCaption;
queryTemp.Stats.UnkString = unk1;
memcpy(queryTemp.Stats.Data, raw.data, sizeof(uint32) * MAX_GAMEOBJECT_DATA);
queryTemp.Stats.Size = size;
return queryTemp;
for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
queryTemp.Stats.QuestItems[i] = 0;
if (GameObjectQuestItemList const* items = sObjectMgr->GetGameObjectQuestItemList(entry))
for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
if (i < items->size())
queryTemp.Stats.QuestItems[i] = (*items)[i];
return *queryTemp.Write();
}
GameObject::GameObject() : WorldObject(false), MapObject(),

View File

@@ -24,6 +24,8 @@
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "Packets/QueryPackets.h"
bool ItemTemplate::CanChangeEquipStateInCombat() const
{
switch (InventoryType)
@@ -160,7 +162,7 @@ void ItemTemplate::InitializeQueryData()
WorldPacket ItemTemplate::BuildQueryData(LocaleConstant loc) const
{
WorldPacket queryTemp(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 500);
WorldPackets::Query::QueryItemSingleResponse response;
std::string locName = Name1;
std::string locDescription = Description;
@@ -171,114 +173,105 @@ WorldPacket ItemTemplate::BuildQueryData(LocaleConstant loc) const
ObjectMgr::GetLocaleString(il->Description, loc, locDescription);
}
queryTemp << ItemId;
queryTemp << Class;
queryTemp << SubClass;
queryTemp << SoundOverrideSubclass;
queryTemp << locName;
queryTemp << uint8(0x00); //Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
queryTemp << uint8(0x00); //Name3; // blizz not send name there, just uint8(0x00);
queryTemp << uint8(0x00); //Name4; // blizz not send name there, just uint8(0x00);
queryTemp << DisplayInfoID;
queryTemp << Quality;
queryTemp << Flags;
queryTemp << Flags2;
queryTemp << BuyPrice;
queryTemp << SellPrice;
queryTemp << InventoryType;
queryTemp << AllowableClass;
queryTemp << AllowableRace;
queryTemp << ItemLevel;
queryTemp << RequiredLevel;
queryTemp << RequiredSkill;
queryTemp << RequiredSkillRank;
queryTemp << RequiredSpell;
queryTemp << RequiredHonorRank;
queryTemp << RequiredCityRank;
queryTemp << RequiredReputationFaction;
queryTemp << RequiredReputationRank;
queryTemp << int32(MaxCount);
queryTemp << int32(Stackable);
queryTemp << ContainerSlots;
queryTemp << StatsCount; // item stats count
response.ItemID = ItemId;
response.Allow = true;
response.Stats.Class = Class;
response.Stats.SubClass = SubClass;
response.Stats.SoundOverrideSubclass = SoundOverrideSubclass;
response.Stats.Name = locName;
response.Stats.DisplayInfoID = DisplayInfoID;
response.Stats.Quality = Quality;
response.Stats.Flags = Flags;
response.Stats.Flags2 = Flags2;
response.Stats.BuyPrice = BuyPrice;
response.Stats.SellPrice = SellPrice;
response.Stats.InventoryType = InventoryType;
response.Stats.AllowableClass = AllowableClass;
response.Stats.AllowableRace = AllowableRace;
response.Stats.ItemLevel = ItemLevel;
response.Stats.RequiredLevel = RequiredLevel;
response.Stats.RequiredSkill = RequiredSkill;
response.Stats.RequiredSkillRank = RequiredSkillRank;
response.Stats.RequiredSpell = RequiredSpell;
response.Stats.RequiredHonorRank = RequiredHonorRank;
response.Stats.RequiredCityRank = RequiredCityRank;
response.Stats.RequiredReputationFaction = RequiredReputationFaction;
response.Stats.RequiredReputationRank = RequiredReputationRank;
response.Stats.MaxCount = MaxCount;
response.Stats.Stackable = Stackable;
response.Stats.ContainerSlots = ContainerSlots;
response.Stats.StatsCount = StatsCount;
for (uint32 i = 0; i < StatsCount; ++i)
{
queryTemp << ItemStat[i].ItemStatType;
queryTemp << ItemStat[i].ItemStatValue;
response.Stats.ItemStat[i].ItemStatType = ItemStat[i].ItemStatType;
response.Stats.ItemStat[i].ItemStatValue = ItemStat[i].ItemStatValue;
}
queryTemp << ScalingStatDistribution; // scaling stats distribution
queryTemp << ScalingStatValue; // some kind of flags used to determine stat values column
for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
response.Stats.ScalingStatDistribution = ScalingStatDistribution;
response.Stats.ScalingStatValue = ScalingStatValue;
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
queryTemp << Damage[i].DamageMin;
queryTemp << Damage[i].DamageMax;
queryTemp << Damage[i].DamageType;
response.Stats.Damage[i].DamageMin = Damage[i].DamageMin;
response.Stats.Damage[i].DamageMax = Damage[i].DamageMax;
response.Stats.Damage[i].DamageType = Damage[i].DamageType;
}
// resistances (7)
queryTemp << Armor;
queryTemp << HolyRes;
queryTemp << FireRes;
queryTemp << NatureRes;
queryTemp << FrostRes;
queryTemp << ShadowRes;
queryTemp << ArcaneRes;
response.Stats.Resistance[SPELL_SCHOOL_NORMAL] = Armor;
response.Stats.Resistance[SPELL_SCHOOL_HOLY] = HolyRes;
response.Stats.Resistance[SPELL_SCHOOL_FIRE] = FireRes;
response.Stats.Resistance[SPELL_SCHOOL_NATURE] = NatureRes;
response.Stats.Resistance[SPELL_SCHOOL_FROST] = FrostRes;
response.Stats.Resistance[SPELL_SCHOOL_SHADOW] = ShadowRes;
response.Stats.Resistance[SPELL_SCHOOL_ARCANE] = ArcaneRes;
queryTemp << Delay;
queryTemp << AmmoType;
queryTemp << RangedModRange;
response.Stats.Delay = Delay;
response.Stats.AmmoType = AmmoType;
response.Stats.RangedModRange = RangedModRange;
for (uint8 s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
{
// spells are validated on template loading
if (Spells[s].SpellId > 0)
{
queryTemp << Spells[s].SpellId;
queryTemp << Spells[s].SpellTrigger;
queryTemp << uint32(-abs(Spells[s].SpellCharges));
queryTemp << uint32(Spells[s].SpellCooldown);
queryTemp << uint32(Spells[s].SpellCategory);
queryTemp << uint32(Spells[s].SpellCategoryCooldown);
}
else
{
queryTemp << uint32(0);
queryTemp << uint32(0);
queryTemp << uint32(0);
queryTemp << uint32(-1);
queryTemp << uint32(0);
queryTemp << uint32(-1);
}
response.Stats.Spells[s].SpellId = Spells[s].SpellId;
response.Stats.Spells[s].SpellTrigger = Spells[s].SpellTrigger;
response.Stats.Spells[s].SpellCharges = Spells[s].SpellCharges;
response.Stats.Spells[s].SpellCooldown = Spells[s].SpellCooldown;
response.Stats.Spells[s].SpellCategory = Spells[s].SpellCategory;
response.Stats.Spells[s].SpellCategoryCooldown = Spells[s].SpellCategoryCooldown;
}
queryTemp << Bonding;
queryTemp << locDescription;
queryTemp << PageText;
queryTemp << LanguageID;
queryTemp << PageMaterial;
queryTemp << StartQuest;
queryTemp << LockID;
queryTemp << int32(Material);
queryTemp << Sheath;
queryTemp << RandomProperty;
queryTemp << RandomSuffix;
queryTemp << Block;
queryTemp << ItemSet;
queryTemp << MaxDurability;
queryTemp << Area;
queryTemp << Map; // Added in 1.12.x & 2.0.1 client branch
queryTemp << BagFamily;
queryTemp << TotemCategory;
for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
response.Stats.Bonding = Bonding;
response.Stats.Description = locDescription;
response.Stats.PageText = PageText;
response.Stats.LanguageID = LanguageID;
response.Stats.PageMaterial = PageMaterial;
response.Stats.StartQuest = StartQuest;
response.Stats.LockID = LockID;
response.Stats.Material = Material;
response.Stats.Sheath = Sheath;
response.Stats.RandomProperty = RandomProperty;
response.Stats.RandomSuffix = RandomSuffix;
response.Stats.Block = Block;
response.Stats.ItemSet = ItemSet;
response.Stats.MaxDurability = MaxDurability;
response.Stats.Area = Area;
response.Stats.Map = Map;
response.Stats.BagFamily = BagFamily;
response.Stats.TotemCategory = TotemCategory;
for (uint8 s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
{
queryTemp << Socket[s].Color;
queryTemp << Socket[s].Content;
response.Stats.Socket[s].Color = Socket[s].Color;
response.Stats.Socket[s].Content = Socket[s].Content;
}
queryTemp << socketBonus;
queryTemp << GemProperties;
queryTemp << RequiredDisenchantSkill;
queryTemp << ArmorDamageModifier;
queryTemp << Duration; // added in 2.4.2.8209, duration (seconds)
queryTemp << ItemLimitCategory; // WotLK, ItemLimitCategory
queryTemp << HolidayId; // Holiday.dbc?
return queryTemp;
response.Stats.SocketBonus = socketBonus;
response.Stats.GemProperties = GemProperties;
response.Stats.RequiredDisenchantSkill = RequiredDisenchantSkill;
response.Stats.ArmorDamageModifier = ArmorDamageModifier;
response.Stats.Duration = Duration;
response.Stats.ItemLimitCategory = ItemLimitCategory;
response.Stats.HolidayId = HolidayId;
return *response.Write();
}

View File

@@ -46,6 +46,8 @@
#include "Vehicle.h"
#include "World.h"
#include "Packets/QueryPackets.h"
ScriptMapMap sSpellScripts;
ScriptMapMap sEventScripts;
ScriptMapMap sWaypointScripts;
@@ -7334,7 +7336,6 @@ void ObjectMgr::LoadQuestPOI()
// 0 1 2 3 4 5 6 7
QueryResult result = WorldDatabase.Query("SELECT QuestID, id, ObjectiveIndex, MapID, WorldMapAreaId, Floor, Priority, Flags FROM quest_poi order by QuestID");
if (!result)
{
TC_LOG_ERROR("server.loading", ">> Loaded 0 quest POI definitions. DB table `quest_poi` is empty.");
@@ -7344,8 +7345,7 @@ void ObjectMgr::LoadQuestPOI()
// 0 1 2 3
QueryResult points = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx2");
std::vector<std::vector<std::vector<QuestPOIPoint> > > POIs;
std::vector<std::vector<std::vector<QuestPOIBlobPoint>>> POIs;
if (points)
{
// The first result should have the highest questId
@@ -7365,7 +7365,10 @@ void ObjectMgr::LoadQuestPOI()
if (POIs[questId].size() <= id + 1)
POIs[questId].resize(id + 10);
QuestPOIPoint point(x, y);
QuestPOIBlobPoint point;
point.X = x;
point.Y = y;
POIs[questId][id].push_back(point);
} while (points->NextRow());
}
@@ -7383,15 +7386,30 @@ void ObjectMgr::LoadQuestPOI()
uint32 unk3 = fields[6].GetUInt32();
uint32 unk4 = fields[7].GetUInt32();
QuestPOI POI(id, objIndex, mapId, WorldMapAreaId, FloorId, unk3, unk4);
QuestPOIBlobData POI;
POI.BlobIndex = id;
POI.ObjectiveIndex = objIndex;
POI.MapID = mapId;
POI.WorldMapAreaID = WorldMapAreaId;
POI.Floor = FloorId;
POI.Unk3 = unk3;
POI.Unk4 = unk4;
if (questId < POIs.size() && id < POIs[questId].size())
{
POI.points = POIs[questId][id];
QuestPOIContainer::iterator itr = _questPOIStore.find(questId);
POI.QuestPOIBlobPointStats = POIs[questId][id];
auto itr = _questPOIStore.find(questId);
if (itr == _questPOIStore.end())
_questPOIStore[questId] = QuestPOIWrapper();
{
QuestPOIWrapper wrapper;
QuestPOIData data;
data.QuestID = questId;
wrapper.POIData = data;
_questPOIStore[questId].DataVector.push_back(POI);
_questPOIStore.emplace(questId, std::move(wrapper));
}
_questPOIStore.at(questId).POIData.QuestPOIBlobDataStats.push_back(POI);
}
else
TC_LOG_ERROR("server.loading", "Table quest_poi references unknown quest points for quest %u POI id %u", questId, id);
@@ -9359,35 +9377,35 @@ void ObjectMgr::InitializeQueriesData(QueryDataGroup mask)
// Initialize Quest POI data
if (mask & QUERY_DATA_POIS)
for (auto& poiPair : _questPOIStore)
poiPair.second.InitializeQueryData(poiPair.first);
poiPair.second.InitializeQueryData();
}
void QuestPOIWrapper::InitializeQueryData(uint32 questId)
void QuestPOIWrapper::InitializeQueryData()
{
QueryDataBuffer = BuildQueryData(questId);
QueryDataBuffer = BuildQueryData();
}
ByteBuffer QuestPOIWrapper::BuildQueryData(uint32 questId) const
ByteBuffer QuestPOIWrapper::BuildQueryData() const
{
ByteBuffer tempBuffer;
tempBuffer << uint32(questId); // quest ID
tempBuffer << uint32(DataVector.size()); // POI count
tempBuffer << uint32(POIData.QuestID); // quest ID
tempBuffer << uint32(POIData.QuestPOIBlobDataStats.size()); // POI count
for (QuestPOIVector::const_iterator itr = DataVector.begin(); itr != DataVector.end(); ++itr)
for (QuestPOIBlobData const& questPOIBlobData : POIData.QuestPOIBlobDataStats)
{
tempBuffer << uint32(itr->Id); // POI index
tempBuffer << int32(itr->ObjectiveIndex); // objective index
tempBuffer << uint32(itr->MapId); // mapid
tempBuffer << uint32(itr->AreaId); // areaid
tempBuffer << uint32(itr->FloorId); // floorid
tempBuffer << uint32(itr->Unk3); // unknown
tempBuffer << uint32(itr->Unk4); // unknown
tempBuffer << uint32(itr->points.size()); // POI points count
tempBuffer << uint32(questPOIBlobData.BlobIndex); // POI index
tempBuffer << int32(questPOIBlobData.ObjectiveIndex); // objective index
tempBuffer << uint32(questPOIBlobData.MapID); // mapid
tempBuffer << uint32(questPOIBlobData.WorldMapAreaID); // areaid
tempBuffer << uint32(questPOIBlobData.Floor); // floorid
tempBuffer << uint32(questPOIBlobData.Unk3); // unknown
tempBuffer << uint32(questPOIBlobData.Unk4); // unknown
tempBuffer << uint32(questPOIBlobData.QuestPOIBlobPointStats.size()); // POI points count
for (std::vector<QuestPOIPoint>::const_iterator itr2 = itr->points.begin(); itr2 != itr->points.end(); ++itr2)
for (QuestPOIBlobPoint const& questPOIBlobPoint : questPOIBlobData.QuestPOIBlobPointStats)
{
tempBuffer << int32(itr2->x); // POI point x
tempBuffer << int32(itr2->y); // POI point y
tempBuffer << int32(questPOIBlobPoint.X); // POI point x
tempBuffer << int32(questPOIBlobPoint.Y); // POI point y
}
}

View File

@@ -590,39 +590,37 @@ typedef std::multimap<uint32, GossipMenuItems> GossipMenuItemsContainer;
typedef std::pair<GossipMenuItemsContainer::const_iterator, GossipMenuItemsContainer::const_iterator> GossipMenuItemsMapBounds;
typedef std::pair<GossipMenuItemsContainer::iterator, GossipMenuItemsContainer::iterator> GossipMenuItemsMapBoundsNonConst;
struct QuestPOIPoint
struct QuestPOIBlobPoint
{
int32 x;
int32 y;
QuestPOIPoint() : x(0), y(0) { }
QuestPOIPoint(int32 _x, int32 _y) : x(_x), y(_y) { }
int32 X = 0;
int32 Y = 0;
};
struct QuestPOI
struct QuestPOIBlobData
{
uint32 Id;
int32 ObjectiveIndex;
uint32 MapId;
uint32 AreaId;
uint32 FloorId;
uint32 Unk3;
uint32 Unk4;
std::vector<QuestPOIPoint> points;
QuestPOI() : Id(0), ObjectiveIndex(0), MapId(0), AreaId(0), FloorId(0), Unk3(0), Unk4(0) { }
QuestPOI(uint32 id, int32 objIndex, uint32 mapId, uint32 areaId, uint32 floorId, uint32 unk3, uint32 unk4) : Id(id), ObjectiveIndex(objIndex), MapId(mapId), AreaId(areaId), FloorId(floorId), Unk3(unk3), Unk4(unk4) { }
uint32 BlobIndex = 0;
int32 ObjectiveIndex = 0;
uint32 MapID = 0;
uint32 WorldMapAreaID = 0;
uint32 Floor = 0;
uint32 Unk3 = 0;
uint32 Unk4 = 0;
std::vector<QuestPOIBlobPoint> QuestPOIBlobPointStats;
};
typedef std::vector<QuestPOI> QuestPOIVector;
struct QuestPOIData
{
uint32 QuestID = 0;
std::vector<QuestPOIBlobData> QuestPOIBlobDataStats;
};
struct QuestPOIWrapper
{
QuestPOIVector DataVector;
QuestPOIData POIData;
ByteBuffer QueryDataBuffer;
void InitializeQueryData(uint32 questId);
ByteBuffer BuildQueryData(uint32 questId) const;
void InitializeQueryData();
ByteBuffer BuildQueryData() const;
QuestPOIWrapper() : QueryDataBuffer(0) { }
};

View File

@@ -26,6 +26,8 @@
#include "Item.h"
#include "SpellInfo.h"
#include "Packets/QueryPackets.h"
void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData)
{
//TC_LOG_DEBUG("network", "WORLD: CMSG_SPLIT_ITEM");
@@ -305,31 +307,26 @@ void WorldSession::HandleDestroyItemOpcode(WorldPacket& recvData)
}
// Only _static_ data send in this packet !!!
void WorldSession::HandleItemQuerySingleOpcode(WorldPacket& recvData)
void WorldSession::HandleItemQuerySingleOpcode(WorldPackets::Query::QueryItemSingle& query)
{
//TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_QUERY_SINGLE");
uint32 item;
recvData >> item;
TC_LOG_INFO("network", "STORAGE: Item Query = %u", query.ItemID);
TC_LOG_INFO("network", "STORAGE: Item Query = %u", item);
ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item);
if (itemTemplate)
if (ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(query.ItemID))
{
if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
SendPacket(&itemTemplate->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
else
{
WorldPacket queryPacket = itemTemplate->BuildQueryData(GetSessionDbLocaleIndex());
SendPacket(&queryPacket);
WorldPacket response = itemTemplate->BuildQueryData(GetSessionDbLocaleIndex());
SendPacket(&response);
}
}
else
{
TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", item);
WorldPacket data(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 4);
data << uint32(item | 0x80000000);
SendPacket(&data);
TC_LOG_DEBUG("network", "WORLD: CMSG_ITEM_QUERY_SINGLE - NO item INFO! (ENTRY: %u)", query.ItemID);
WorldPackets::Query::QueryItemSingleResponse response;
response.ItemID = query.ItemID;
SendPacket(response.Write());
}
}

View File

@@ -29,6 +29,8 @@
#include "MapManager.h"
#include "CharacterCache.h"
#include "Packets/QueryPackets.h"
void WorldSession::SendNameQueryOpcode(ObjectGuid guid)
{
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
@@ -87,64 +89,54 @@ void WorldSession::SendQueryTimeResponse()
}
/// Only _static_ data is sent in this packet !!!
void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData)
void WorldSession::HandleCreatureQueryOpcode(WorldPackets::Query::QueryCreature& query)
{
uint32 entry;
recvData >> entry;
ObjectGuid guid;
recvData >> guid;
CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(entry);
if (ci)
if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(query.CreatureID))
{
TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), entry);
TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY '%s' - Entry: %u.", ci->Name.c_str(), query.CreatureID);
if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
SendPacket(&ci->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
else
{
WorldPacket queryPacket = ci->BuildQueryData(GetSessionDbLocaleIndex());
SendPacket(&queryPacket);
WorldPacket response = ci->BuildQueryData(GetSessionDbLocaleIndex());
SendPacket(&response);
}
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
}
else
{
TC_LOG_DEBUG("network", "WORLD: CMSG_CREATURE_QUERY - NO CREATURE INFO! (%s, ENTRY: %u)",
guid.ToString().c_str(), entry);
WorldPacket data(SMSG_CREATURE_QUERY_RESPONSE, 4);
data << uint32(entry | 0x80000000);
SendPacket(&data);
query.Guid.ToString().c_str(), query.CreatureID);
WorldPackets::Query::QueryCreatureResponse response;
response.CreatureID = query.CreatureID;
SendPacket(response.Write());
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
}
}
/// Only _static_ data is sent in this packet !!!
void WorldSession::HandleGameObjectQueryOpcode(WorldPacket& recvData)
void WorldSession::HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject& query)
{
uint32 entry;
recvData >> entry;
ObjectGuid guid;
recvData >> guid;
const GameObjectTemplate* info = sObjectMgr->GetGameObjectTemplate(entry);
if (info)
if (GameObjectTemplate const* info = sObjectMgr->GetGameObjectTemplate(query.GameObjectID))
{
if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
SendPacket(&info->QueryData[static_cast<uint32>(GetSessionDbLocaleIndex())]);
else
{
WorldPacket queryPacket = info->BuildQueryData(GetSessionDbLocaleIndex());
SendPacket(&queryPacket);
WorldPacket response = info->BuildQueryData(GetSessionDbLocaleIndex());
SendPacket(&response);
}
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
}
else
{
TC_LOG_DEBUG("network", "WORLD: CMSG_GAMEOBJECT_QUERY - Missing gameobject info for (%s, ENTRY: %u)",
guid.ToString().c_str(), entry);
WorldPacket data (SMSG_GAMEOBJECT_QUERY_RESPONSE, 4);
data << uint32(entry | 0x80000000);
SendPacket(&data);
query.Guid.ToString().c_str(), query.GameObjectID);
WorldPackets::Query::QueryGameObjectResponse response;
response.GameObjectID = query.GameObjectID;
SendPacket(response.Write());
TC_LOG_DEBUG("network", "WORLD: Sent SMSG_GAMEOBJECT_QUERY_RESPONSE");
}
}
@@ -337,46 +329,29 @@ void WorldSession::HandleCorpseMapPositionQuery(WorldPacket& recvData)
SendPacket(&data);
}
void WorldSession::HandleQuestPOIQuery(WorldPacket& recvData)
void WorldSession::HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery& query)
{
uint32 count;
recvData >> count; // quest count, max=25
if (count > MAX_QUEST_LOG_SIZE)
{
recvData.rfinish();
if (query.MissingQuestCount > MAX_QUEST_LOG_SIZE)
return;
}
// Read quest ids and add the in a unordered_set so we don't send POIs for the same quest multiple times
std::unordered_set<uint32> questIds;
for (uint32 i = 0; i < count; ++i)
questIds.insert(recvData.read<uint32>()); // quest id
for (uint32 i = 0; i < query.MissingQuestCount; ++i)
questIds.insert(query.MissingQuestPOIs[i]); // quest id
WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + (4 + 4 + 40)*questIds.size());
data << uint32(questIds.size()); // count
for (auto itr = questIds.begin(); itr != questIds.end(); ++itr)
WorldPacket data(SMSG_QUEST_POI_QUERY_RESPONSE, 4 + (4 + 4 + 40) * questIds.size());
for (uint32 questId : questIds)
{
uint32 questId = *itr;
bool questOk = false;
uint16 questSlot = _player->FindQuestSlot(questId);
if (questSlot != MAX_QUEST_LOG_SIZE)
questOk =_player->GetQuestSlotQuestId(questSlot) == questId;
if (questOk)
uint16 const questSlot = _player->FindQuestSlot(questId);
if (questSlot != MAX_QUEST_LOG_SIZE && _player->GetQuestSlotQuestId(questSlot) == questId)
{
if (QuestPOIWrapper const* poiWrapper = sObjectMgr->GetQuestPOIWrapper(questId))
{
if (sWorld->getBoolConfig(CONFIG_CACHE_DATA_QUERIES))
data.append(poiWrapper->QueryDataBuffer);
else
{
ByteBuffer POIByteBuffer = poiWrapper->BuildQueryData(questId);
ByteBuffer POIByteBuffer = poiWrapper->BuildQueryData();
data.append(POIByteBuffer);
}
}

View File

@@ -31,6 +31,8 @@
#include "ScriptMgr.h"
#include "GameObjectAI.h"
#include "Packets/QuestPackets.h"
void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData)
{
ObjectGuid guid;
@@ -250,16 +252,14 @@ void WorldSession::HandleQuestgiverQueryQuestOpcode(WorldPacket& recvData)
}
}
void WorldSession::HandleQuestQueryOpcode(WorldPacket& recvData)
void WorldSession::HandleQuestQueryOpcode(WorldPackets::Quest::QueryQuestInfo& query)
{
if (!_player)
return;
uint32 questId;
recvData >> questId;
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_QUERY quest = %u", questId);
TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUEST_QUERY quest = %u", query.QuestID);
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
if (Quest const* quest = sObjectMgr->GetQuestTemplate(query.QuestID))
_player->PlayerTalkClass->SendQuestQueryResponse(quest);
}

View File

@@ -22,6 +22,8 @@
#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Packets/QuestPackets.h"
Quest::Quest(Field* questRecord)
{
EmoteOnIncomplete = 0;
@@ -335,7 +337,7 @@ void Quest::InitializeQueryData()
WorldPacket Quest::BuildQueryData(LocaleConstant loc) const
{
WorldPacket queryTemp(SMSG_QUEST_QUERY_RESPONSE, 2000);
WorldPackets::Quest::QueryQuestInfoResponse response;
std::string locQuestTitle = GetTitle();
std::string locQuestDetails = GetDetails();
@@ -359,110 +361,91 @@ WorldPacket Quest::BuildQueryData(LocaleConstant loc) const
ObjectMgr::GetLocaleString(localeData->ObjectiveText[i], loc, locQuestObjectiveText[i]);
}
queryTemp << uint32(GetQuestId()); // quest id
queryTemp << uint32(GetQuestMethod()); // Accepted values: 0, 1 or 2. 0 == IsAutoComplete() (skip objectives/details)
queryTemp << uint32(GetQuestLevel()); // may be -1, static data, in other cases must be used dynamic level: Player::GetQuestLevel (0 is not known, but assuming this is no longer valid for quest intended for client)
queryTemp << uint32(GetMinLevel()); // min level
queryTemp << uint32(GetZoneOrSort()); // zone or sort to display in quest log
response.Info.QuestID = GetQuestId();
response.Info.QuestMethod = GetQuestMethod();
response.Info.QuestLevel = GetQuestLevel();
response.Info.QuestMinLevel = GetMinLevel();
response.Info.QuestSortID = GetZoneOrSort();
queryTemp << uint32(GetType()); // quest type
queryTemp << uint32(GetSuggestedPlayers()); // suggested players count
response.Info.QuestType = GetType();
response.Info.SuggestedGroupNum = GetSuggestedPlayers();
queryTemp << uint32(GetRepObjectiveFaction()); // shown in quest log as part of quest objective
queryTemp << uint32(GetRepObjectiveValue()); // shown in quest log as part of quest objective
response.Info.RequiredFactionId[0] = GetRepObjectiveFaction();
response.Info.RequiredFactionValue[0] = GetRepObjectiveValue();
queryTemp << uint32(GetRepObjectiveFaction2()); // shown in quest log as part of quest objective OPPOSITE faction
queryTemp << uint32(GetRepObjectiveValue2()); // shown in quest log as part of quest objective OPPOSITE faction
response.Info.RequiredFactionId[1] = GetRepObjectiveFaction2();
response.Info.RequiredFactionValue[1] = GetRepObjectiveValue2();
queryTemp << uint32(GetNextQuestInChain()); // client will request this quest from NPC, if not 0
queryTemp << uint32(GetXPId()); // used for calculating rewarded experience
response.Info.RewardNextQuest = GetNextQuestInChain();
response.Info.RewardXPDifficulty = GetXPId();
if (HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
queryTemp << uint32(0); // Hide money rewarded
else
queryTemp << uint32(GetRewOrReqMoney()); // reward money (below max lvl)
response.Info.RewardMoney = GetRewOrReqMoney();
response.Info.RewardBonusMoney = GetRewMoneyMaxLevel();
response.Info.RewardDisplaySpell = GetRewSpell();
response.Info.RewardSpell = GetRewSpellCast();
queryTemp << uint32(GetRewMoneyMaxLevel()); // used in XP calculation at client
queryTemp << uint32(GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0)
queryTemp << int32(GetRewSpellCast()); // cast spell
response.Info.RewardHonor = GetRewHonorAddition();
response.Info.RewardKillHonor = GetRewHonorMultiplier();
// rewarded honor points
queryTemp << uint32(GetRewHonorAddition());
queryTemp << float(GetRewHonorMultiplier());
queryTemp << uint32(GetSrcItemId()); // source item id
queryTemp << uint32(GetFlags() & 0xFFFF); // quest flags
queryTemp << uint32(GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
queryTemp << uint32(GetPlayersSlain()); // players slain
queryTemp << uint32(GetBonusTalents()); // bonus talents
queryTemp << uint32(GetRewArenaPoints()); // bonus arena points
queryTemp << uint32(0); // review rep show mask
response.Info.StartItem = GetSrcItemId();
response.Info.Flags = GetFlags();
response.Info.RewardTitleId = GetCharTitleId();
response.Info.RequiredPlayerKills = GetPlayersSlain();
response.Info.RewardTalents = GetBonusTalents();
response.Info.RewardArenaPoints = GetRewArenaPoints();
if (HasFlag(QUEST_FLAGS_HIDDEN_REWARDS))
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
{
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
queryTemp << uint32(0) << uint32(0);
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
queryTemp << uint32(0) << uint32(0);
response.Info.RewardItems[i] = RewardItemId[i];
response.Info.RewardAmount[i] = RewardItemIdCount[i];
}
else
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
{
queryTemp << uint32(RewardItemId[i]);
queryTemp << uint32(RewardItemIdCount[i]);
}
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
queryTemp << uint32(RewardChoiceItemId[i]);
queryTemp << uint32(RewardChoiceItemCount[i]);
}
response.Info.UnfilteredChoiceItems[i].ItemID = RewardChoiceItemId[i];
response.Info.UnfilteredChoiceItems[i].Quantity = RewardChoiceItemCount[i];
}
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
queryTemp << uint32(RewardFactionId[i]);
response.Info.RewardFactionID[i] = RewardFactionId[i];
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid+1 QuestFactionReward.dbc?
queryTemp << int32(RewardFactionValueId[i]);
response.Info.RewardFactionValue[i] = RewardFactionValueId[i];
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unk (0)
queryTemp << int32(RewardFactionValueIdOverride[i]);
response.Info.RewardFactionValueOverride[i] = RewardFactionValueIdOverride[i];
queryTemp << uint32(GetPOIContinent());
queryTemp << float(GetPOIx());
queryTemp << float(GetPOIy());
queryTemp << uint32(GetPointOpt());
response.Info.POIContinent = GetPOIContinent();
response.Info.POIx = GetPOIx();
response.Info.POIy = GetPOIy();
response.Info.POIPriority = GetPointOpt();
if (sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS))
Quest::AddQuestLevelToTitle(locQuestTitle, GetQuestLevel());
queryTemp << locQuestTitle;
queryTemp << locQuestObjectives;
queryTemp << locQuestDetails;
queryTemp << locQuestAreaDescription;
queryTemp << locQuestCompletedText; // display in quest objectives window once all objectives are completed
response.Info.Title = locQuestTitle;
response.Info.Objectives = locQuestObjectives;
response.Info.Details = locQuestDetails;
response.Info.AreaDescription = locQuestAreaDescription;
response.Info.CompletedText = locQuestCompletedText;
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
{
if (RequiredNpcOrGo[i] < 0)
queryTemp << uint32((RequiredNpcOrGo[i] * (-1)) | 0x80000000); // client expects gameobject template id in form (id|0x80000000)
else
queryTemp << uint32(RequiredNpcOrGo[i]);
queryTemp << uint32(RequiredNpcOrGoCount[i]);
queryTemp << uint32(ItemDrop[i]);
queryTemp << uint32(0); // req source count?
response.Info.RequiredNpcOrGo[i] = RequiredNpcOrGo[i];
response.Info.RequiredNpcOrGoCount[i] = RequiredNpcOrGoCount[i];
response.Info.ItemDrop[i] = ItemDrop[i];
}
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
queryTemp << uint32(RequiredItemId[i]);
queryTemp << uint32(RequiredItemCount[i]);
response.Info.RequiredItemId[i] = RequiredItemId[i];
response.Info.RequiredItemCount[i] = RequiredItemCount[i];
}
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
queryTemp << locQuestObjectiveText[i];
response.Info.ObjectiveText[i] = locQuestObjectiveText[i];
return queryTemp;
return *response.Write();
}
void Quest::AddQuestLevelToTitle(std::string &title, int32 level)

View File

@@ -18,4 +18,7 @@
#ifndef AllPackets_h__
#define AllPackets_h__
#include "QueryPackets.h"
#include "QuestPackets.h"
#endif // AllPackets_h__

View File

@@ -0,0 +1,209 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "QueryPackets.h"
void WorldPackets::Query::QueryCreature::Read()
{
_worldPacket >> CreatureID;
_worldPacket >> Guid;
}
WorldPacket const* WorldPackets::Query::QueryCreatureResponse::Write()
{
_worldPacket << uint32(CreatureID | (Allow ? 0x00000000 : 0x80000000)); // creature entry
if (Allow)
{
_worldPacket << Stats.Name;
_worldPacket << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
_worldPacket << Stats.NameAlt;
_worldPacket << Stats.CursorName; // "Directions" for guard, string for Icons 2.3.0
_worldPacket << uint32(Stats.Flags); // flags
_worldPacket << uint32(Stats.CreatureType); // CreatureType.dbc
_worldPacket << uint32(Stats.CreatureFamily); // CreatureFamily.dbc
_worldPacket << uint32(Stats.Classification); // Creature Rank (elite, boss, etc)
_worldPacket.append(Stats.ProxyCreatureID, MAX_KILL_CREDIT); // new in 3.1, kill credit
_worldPacket.append(Stats.CreatureDisplayID, MAX_CREATURE_MODELS); // Modelid
_worldPacket << float(Stats.HpMulti); // dmg/hp modifier
_worldPacket << float(Stats.EnergyMulti); // dmg/mana modifier
_worldPacket << uint8(Stats.Leader);
_worldPacket.append(Stats.QuestItems, MAX_CREATURE_QUEST_ITEMS);
_worldPacket << uint32(Stats.CreatureMovementInfoID); // CreatureMovementInfo.dbc
}
return &_worldPacket;
}
void WorldPackets::Query::QueryGameObject::Read()
{
_worldPacket >> GameObjectID;
_worldPacket >> Guid;
}
WorldPacket const* WorldPackets::Query::QueryGameObjectResponse::Write()
{
_worldPacket << uint32(GameObjectID | (Allow ? 0x00000000 : 0x80000000));
if (Allow)
{
_worldPacket << uint32(Stats.Type);
_worldPacket << uint32(Stats.DisplayID);
_worldPacket << Stats.Name;
_worldPacket << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4
_worldPacket << Stats.IconName; // 2.0.3, string. Icon name to use instead of default icon for go's (ex: "Attack" makes sword)
_worldPacket << Stats.CastBarCaption; // 2.0.3, string. Text will appear in Cast Bar when using GO (ex: "Collecting")
_worldPacket << Stats.UnkString; // 2.0.3, string
_worldPacket.append(Stats.Data, MAX_GAMEOBJECT_DATA);
_worldPacket << float(Stats.Size); // go size
_worldPacket.append(Stats.QuestItems, MAX_GAMEOBJECT_QUEST_ITEMS);
}
return &_worldPacket;
}
void WorldPackets::Query::QueryItemSingle::Read()
{
_worldPacket >> ItemID;
}
WorldPacket const* WorldPackets::Query::QueryItemSingleResponse::Write()
{
_worldPacket << uint32(ItemID | (Allow ? 0x00000000 : 0x80000000));
if (Allow)
{
_worldPacket << Stats.Class;
_worldPacket << Stats.SubClass;
_worldPacket << Stats.SoundOverrideSubclass;
_worldPacket << Stats.Name;
_worldPacket << uint8(0x00); //Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
_worldPacket << uint8(0x00); //Name3; // blizz not send name there, just uint8(0x00);
_worldPacket << uint8(0x00); //Name4; // blizz not send name there, just uint8(0x00);
_worldPacket << Stats.DisplayInfoID;
_worldPacket << Stats.Quality;
_worldPacket << Stats.Flags;
_worldPacket << Stats.Flags2;
_worldPacket << Stats.BuyPrice;
_worldPacket << Stats.SellPrice;
_worldPacket << Stats.InventoryType;
_worldPacket << Stats.AllowableClass;
_worldPacket << Stats.AllowableRace;
_worldPacket << Stats.ItemLevel;
_worldPacket << Stats.RequiredLevel;
_worldPacket << Stats.RequiredSkill;
_worldPacket << Stats.RequiredSkillRank;
_worldPacket << Stats.RequiredSpell;
_worldPacket << Stats.RequiredHonorRank;
_worldPacket << Stats.RequiredCityRank;
_worldPacket << Stats.RequiredReputationFaction;
_worldPacket << Stats.RequiredReputationRank;
_worldPacket << int32(Stats.MaxCount);
_worldPacket << int32(Stats.Stackable);
_worldPacket << Stats.ContainerSlots;
_worldPacket << Stats.StatsCount; // item stats count
for (uint32 i = 0; i < Stats.StatsCount; ++i)
{
_worldPacket << Stats.ItemStat[i].ItemStatType;
_worldPacket << Stats.ItemStat[i].ItemStatValue;
}
_worldPacket << Stats.ScalingStatDistribution; // scaling stats distribution
_worldPacket << Stats.ScalingStatValue; // some kind of flags used to determine stat values column
for (uint8 i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
{
_worldPacket << Stats.Damage[i].DamageMin;
_worldPacket << Stats.Damage[i].DamageMax;
_worldPacket << Stats.Damage[i].DamageType;
}
// resistances (7)
for (uint8 i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; ++i)
_worldPacket << Stats.Resistance[i];
_worldPacket << Stats.Delay;
_worldPacket << Stats.AmmoType;
_worldPacket << Stats.RangedModRange;
for (uint8 s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
{
// spells are validated on template loading
if (Stats.Spells[s].SpellId > 0)
{
_worldPacket << Stats.Spells[s].SpellId;
_worldPacket << Stats.Spells[s].SpellTrigger;
_worldPacket << uint32(-abs(Stats.Spells[s].SpellCharges));
_worldPacket << uint32(Stats.Spells[s].SpellCooldown);
_worldPacket << uint32(Stats.Spells[s].SpellCategory);
_worldPacket << uint32(Stats.Spells[s].SpellCategoryCooldown);
}
else
{
_worldPacket << uint32(0);
_worldPacket << uint32(0);
_worldPacket << uint32(0);
_worldPacket << uint32(-1);
_worldPacket << uint32(0);
_worldPacket << uint32(-1);
}
}
_worldPacket << Stats.Bonding;
_worldPacket << Stats.Description;
_worldPacket << Stats.PageText;
_worldPacket << Stats.LanguageID;
_worldPacket << Stats.PageMaterial;
_worldPacket << Stats.StartQuest;
_worldPacket << Stats.LockID;
_worldPacket << int32(Stats.Material);
_worldPacket << Stats.Sheath;
_worldPacket << Stats.RandomProperty;
_worldPacket << Stats.RandomSuffix;
_worldPacket << Stats.Block;
_worldPacket << Stats.ItemSet;
_worldPacket << Stats.MaxDurability;
_worldPacket << Stats.Area;
_worldPacket << Stats.Map; // Added in 1.12.x & 2.0.1 client branch
_worldPacket << Stats.BagFamily;
_worldPacket << Stats.TotemCategory;
for (uint8 s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
{
_worldPacket << Stats.Socket[s].Color;
_worldPacket << Stats.Socket[s].Content;
}
_worldPacket << Stats.SocketBonus;
_worldPacket << Stats.GemProperties;
_worldPacket << Stats.RequiredDisenchantSkill;
_worldPacket << Stats.ArmorDamageModifier;
_worldPacket << Stats.Duration; // added in 2.4.2.8209, duration (seconds)
_worldPacket << Stats.ItemLimitCategory; // WotLK, ItemLimitCategory
_worldPacket << Stats.HolidayId; // Holiday.dbc?
}
return &_worldPacket;
}
void WorldPackets::Query::QuestPOIQuery::Read()
{
_worldPacket >> MissingQuestCount; // quest count, max=25
if (MissingQuestCount <= MAX_QUEST_LOG_SIZE)
{
for (uint8 i = 0; i < MissingQuestCount; ++i)
_worldPacket >> MissingQuestPOIs[i];
}
_worldPacket.rfinish();
}

View File

@@ -0,0 +1,240 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QueryPackets_h__
#define QueryPackets_h__
#include "Packet.h"
#include "ObjectGuid.h"
#include "SharedDefines.h"
#include "Creature.h"
#include "GameObject.h"
#include "ItemTemplate.h"
#include "QuestDef.h"
namespace WorldPackets
{
namespace Query
{
class QueryCreature final : public ClientPacket
{
public:
QueryCreature(WorldPacket&& packet) : ClientPacket(CMSG_CREATURE_QUERY, std::move(packet)) { }
void Read() override;
uint32 CreatureID = 0;
ObjectGuid Guid;
};
struct CreatureStats
{
std::string Name;
std::string NameAlt;
std::string CursorName;
uint32 Flags = 0;
uint32 CreatureType = 0;
uint32 CreatureFamily = 0;
uint32 Classification = 0;
uint32 ProxyCreatureID[MAX_KILL_CREDIT];
uint32 CreatureDisplayID[MAX_CREATURE_MODELS];
float HpMulti = 0.0f;
float EnergyMulti = 0.0f;
bool Leader = false;
uint32 QuestItems[MAX_CREATURE_QUEST_ITEMS];
uint32 CreatureMovementInfoID = 0;
};
class QueryCreatureResponse final : public ServerPacket
{
public:
QueryCreatureResponse() : ServerPacket(SMSG_CREATURE_QUERY_RESPONSE, 100) { }
WorldPacket const* Write() override;
bool Allow = false;
CreatureStats Stats;
uint32 CreatureID = 0;
};
class QueryGameObject final : public ClientPacket
{
public:
QueryGameObject(WorldPacket&& packet) : ClientPacket(CMSG_GAMEOBJECT_QUERY, std::move(packet)) { }
void Read() override;
uint32 GameObjectID = 0;
ObjectGuid Guid;
};
struct GameObjectStats
{
std::string Name;
std::string IconName;
std::string CastBarCaption;
std::string UnkString;
uint32 Type = 0;
uint32 DisplayID = 0;
uint32 Data[MAX_GAMEOBJECT_DATA];
float Size = 0.0f;
uint32 QuestItems[MAX_GAMEOBJECT_QUEST_ITEMS];
};
class QueryGameObjectResponse final : public ServerPacket
{
public:
QueryGameObjectResponse() : ServerPacket(SMSG_GAMEOBJECT_QUERY_RESPONSE, 150) { }
WorldPacket const* Write() override;
uint32 GameObjectID = 0;
bool Allow = false;
GameObjectStats Stats;
};
class QueryItemSingle final : public ClientPacket
{
public:
QueryItemSingle(WorldPacket&& packet) : ClientPacket(CMSG_ITEM_QUERY_SINGLE, std::move(packet)) { }
void Read() override;
uint32 ItemID = 0;
};
struct ItemDamageData
{
float DamageMin = 0.0f;
float DamageMax = 0.0f;
uint32 DamageType = 0;
};
struct ItemStatData
{
uint32 ItemStatType = 0;
int32 ItemStatValue = 0;
};
struct ItemSpellData
{
int32 SpellId = -1;
uint32 SpellTrigger = 0;
int32 SpellCharges = 0;
int32 SpellCooldown = -1;
uint32 SpellCategory = 0;
int32 SpellCategoryCooldown = -1;
};
struct ItemSocketData
{
uint32 Color = 0;
uint32 Content = 0;
};
struct ItemStats
{
uint32 Class = 0;
uint32 SubClass = 0;
int32 SoundOverrideSubclass = 0;
std::string Name;
uint32 DisplayInfoID = 0;
uint32 Quality = 0;
uint32 Flags = 0;
uint32 Flags2 = 0;
int32 BuyPrice = 0;
uint32 SellPrice = 0;
uint32 InventoryType = 0;
uint32 AllowableClass = 0;
uint32 AllowableRace = 0;
uint32 ItemLevel = 0;
uint32 RequiredLevel = 0;
uint32 RequiredSkill = 0;
uint32 RequiredSkillRank = 0;
uint32 RequiredSpell = 0;
uint32 RequiredHonorRank = 0;
uint32 RequiredCityRank = 0;
uint32 RequiredReputationFaction = 0;
uint32 RequiredReputationRank = 0;
int32 MaxCount = 0;
int32 Stackable = 0;
uint32 ContainerSlots = 0;
uint32 StatsCount = 0;
ItemStatData ItemStat[MAX_ITEM_PROTO_STATS];
uint32 ScalingStatDistribution = 0;
uint32 ScalingStatValue = 0;
ItemDamageData Damage[MAX_ITEM_PROTO_DAMAGES];
uint32 Resistance[MAX_SPELL_SCHOOL];
uint32 Delay = 0;
uint32 AmmoType = 0;
float RangedModRange = 0.0f;
ItemSpellData Spells[MAX_ITEM_PROTO_SPELLS];
uint32 Bonding = 0;
std::string Description;
uint32 PageText = 0;
uint32 LanguageID = 0;
uint32 PageMaterial = 0;
uint32 StartQuest = 0;
uint32 LockID = 0;
int32 Material = 0;
uint32 Sheath = 0;
int32 RandomProperty = 0;
int32 RandomSuffix = 0;
uint32 Block = 0;
uint32 ItemSet = 0;
uint32 MaxDurability = 0;
uint32 Area = 0;
uint32 Map = 0;
uint32 BagFamily = 0;
uint32 TotemCategory = 0;
ItemSocketData Socket[MAX_ITEM_PROTO_SOCKETS];
uint32 SocketBonus = 0;
uint32 GemProperties = 0;
uint32 RequiredDisenchantSkill = 0;
float ArmorDamageModifier = 0.0f;
uint32 Duration = 0;
uint32 ItemLimitCategory = 0;
uint32 HolidayId = 0;
};
class QueryItemSingleResponse final : public ServerPacket
{
public:
QueryItemSingleResponse() : ServerPacket(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 500) { }
WorldPacket const* Write() override;
uint32 ItemID = 0;
bool Allow = false;
ItemStats Stats;
};
class QuestPOIQuery final : public ClientPacket
{
public:
QuestPOIQuery(WorldPacket&& packet) : ClientPacket(CMSG_QUEST_POI_QUERY, std::move(packet)) { }
void Read() override;
uint32 MissingQuestCount = 0;
uint32 MissingQuestPOIs[MAX_QUEST_LOG_SIZE] = { };
};
}
}
#endif // QueryPackets_h__

View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "QuestPackets.h"
void WorldPackets::Quest::QueryQuestInfo::Read()
{
_worldPacket >> QuestID;
}
WorldPacket const* WorldPackets::Quest::QueryQuestInfoResponse::Write()
{
_worldPacket << uint32(Info.QuestID);
_worldPacket << uint32(Info.QuestMethod);
_worldPacket << uint32(Info.QuestLevel);
_worldPacket << uint32(Info.QuestMinLevel);
_worldPacket << uint32(Info.QuestSortID);
_worldPacket << uint32(Info.QuestType);
_worldPacket << uint32(Info.SuggestedGroupNum);
for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i)
{
_worldPacket << uint32(Info.RequiredFactionId[i]);
_worldPacket << uint32(Info.RequiredFactionValue[i]);
}
_worldPacket << uint32(Info.RewardNextQuest);
_worldPacket << uint32(Info.RewardXPDifficulty);
if ((Info.Flags & QUEST_FLAGS_HIDDEN_REWARDS) != 0)
_worldPacket << uint32(0);
else
_worldPacket << uint32(Info.RewardMoney);
_worldPacket << uint32(Info.RewardBonusMoney);
_worldPacket << uint32(Info.RewardDisplaySpell);
_worldPacket << int32(Info.RewardSpell);
_worldPacket << uint32(Info.RewardHonor);
_worldPacket << float(Info.RewardKillHonor);
_worldPacket << uint32(Info.StartItem);
_worldPacket << uint32(Info.Flags & 0xFFFF);
_worldPacket << uint32(Info.RewardTitleId);
_worldPacket << uint32(Info.RequiredPlayerKills);
_worldPacket << uint32(Info.RewardTalents);
_worldPacket << uint32(Info.RewardArenaPoints);
_worldPacket << uint32(0); // review rep show mask
if ((Info.Flags & QUEST_FLAGS_HIDDEN_REWARDS) != 0)
{
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
_worldPacket << uint32(0) << uint32(0);
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
_worldPacket << uint32(0) << uint32(0);
}
else
{
for (uint8 i = 0; i < QUEST_REWARDS_COUNT; ++i)
{
_worldPacket << uint32(Info.RewardItems[i]);
_worldPacket << uint32(Info.RewardAmount[i]);
}
for (uint8 i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i)
{
_worldPacket << uint32(Info.UnfilteredChoiceItems[i].ItemID);
_worldPacket << uint32(Info.UnfilteredChoiceItems[i].Quantity);
}
}
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // reward factions ids
_worldPacket << uint32(Info.RewardFactionID[i]);
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // columnid+1 QuestFactionReward.dbc?
_worldPacket << int32(Info.RewardFactionValue[i]);
for (uint8 i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) // unk (0)
_worldPacket << int32(Info.RewardFactionValueOverride[i]);
_worldPacket << uint32(Info.POIContinent);
_worldPacket << float(Info.POIx);
_worldPacket << float(Info.POIy);
_worldPacket << uint32(Info.POIPriority);
_worldPacket << Info.Title;
_worldPacket << Info.Objectives;
_worldPacket << Info.Details;
_worldPacket << Info.AreaDescription;
_worldPacket << Info.CompletedText;
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
{
if (Info.RequiredNpcOrGo[i] < 0)
_worldPacket << uint32((Info.RequiredNpcOrGo[i] * (-1)) | 0x80000000); // client expects gameobject template id in form (id|0x80000000)
else
_worldPacket << uint32(Info.RequiredNpcOrGo[i]);
_worldPacket << uint32(Info.RequiredNpcOrGoCount[i]);
_worldPacket << uint32(Info.ItemDrop[i]);
_worldPacket << uint32(0); // req source count?
}
for (uint8 i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i)
{
_worldPacket << uint32(Info.RequiredItemId[i]);
_worldPacket << uint32(Info.RequiredItemCount[i]);
}
for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i)
_worldPacket << Info.ObjectiveText[i];
return &_worldPacket;
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QuestPackets_h__
#define QuestPackets_h__
#include "Packet.h"
#include "QuestDef.h"
namespace WorldPackets
{
namespace Quest
{
class QueryQuestInfo final : public ClientPacket
{
public:
QueryQuestInfo(WorldPacket&& packet) : ClientPacket(CMSG_QUEST_QUERY, std::move(packet)) { }
void Read() override;
uint32 QuestID = 0;
};
struct QuestInfoChoiceItem
{
uint32 ItemID = 0;
uint32 Quantity = 0;
};
struct QuestInfo
{
uint32 QuestID = 0;
uint32 QuestMethod = 0; // Accepted values: 0, 1 or 2. 0 == IsAutoComplete() (skip objectives/details)
int32 QuestLevel = 0; // may be -1, static data, in other cases must be used dynamic level: Player::GetQuestLevel (0 is not known, but assuming this is no longer valid for quest intended for client)
uint32 QuestMinLevel = 0;
int32 QuestSortID = 0; // zone or sort to display in quest log
uint32 QuestType = 0;
uint32 SuggestedGroupNum = 0;
int32 AllowableRaces = -1;
uint32 RequiredFactionId[BG_TEAMS_COUNT] = { }; // shown in quest log as part of quest objective (same/opposite faction)
int32 RequiredFactionValue[BG_TEAMS_COUNT] = { }; // shown in quest log as part of quest objective (same/opposite faction)
uint32 RewardNextQuest = 0; // client will request this quest from NPC, if not 0
uint32 RewardXPDifficulty = 0; // used for calculating rewarded experience
int32 RewardMoney = 0; // reward money (below max lvl)
uint32 RewardBonusMoney = 0; // used in XP calculation at client
uint32 RewardDisplaySpell = 0; // reward spell, this spell will be displayed (icon) (cast if RewSpellCast == 0)
int32 RewardSpell = 0;
uint32 RewardHonor = 0;
float RewardKillHonor = 0.0f;
uint32 StartItem = 0;
uint32 Flags = 0;
uint32 RewardTitleId = 0; // new 2.4.0, player gets this title (id from CharTitles)
uint32 RequiredPlayerKills = 0;
uint32 RewardTalents = 0;
int32 RewardArenaPoints = 0;
uint32 RewardItems[QUEST_REWARDS_COUNT] = { };
uint32 RewardAmount[QUEST_REWARDS_COUNT] = { };
QuestInfoChoiceItem UnfilteredChoiceItems[QUEST_REWARD_CHOICES_COUNT];
uint32 RewardFactionID[QUEST_REPUTATIONS_COUNT] = { };
int32 RewardFactionValue[QUEST_REPUTATIONS_COUNT] = { };
int32 RewardFactionValueOverride[QUEST_REPUTATIONS_COUNT] = { };
uint32 POIContinent = 0;
float POIx = 0.0f;
float POIy = 0.0f;
uint32 POIPriority = 0;
std::string Title;
std::string Objectives;
std::string Details;
std::string AreaDescription;
std::string CompletedText; // display in quest objectives window once all objectives are completed
int32 RequiredNpcOrGo[QUEST_OBJECTIVES_COUNT] = { }; // >0 Creature <0 Gameobject
uint32 RequiredNpcOrGoCount[QUEST_OBJECTIVES_COUNT] = { };
uint32 ItemDrop[QUEST_SOURCE_ITEM_IDS_COUNT] = { };
// uint32 ItemDropQuantity[QUEST_SOURCE_ITEM_IDS_COUNT] = { };
uint32 RequiredItemId[QUEST_ITEM_OBJECTIVES_COUNT] = { };
uint32 RequiredItemCount[QUEST_ITEM_OBJECTIVES_COUNT] = { };
std::string ObjectiveText[QUEST_OBJECTIVES_COUNT];
};
class QueryQuestInfoResponse final : public ServerPacket
{
public:
QueryQuestInfoResponse() : ServerPacket(SMSG_QUEST_QUERY_RESPONSE, 2000) { }
WorldPacket const* Write() override;
QuestInfo Info;
};
}
}
#endif // QuestPackets_h__

View File

@@ -71,7 +71,19 @@ class RBACData;
namespace WorldPackets
{
namespace Query
{
class QueryCreature;
class QueryGameObject;
class QueryItemSingle;
class QuestPOIQuery;
}
namespace Quest
{
class QueryQuestInfo;
}
}
enum AccountDataType
{
GLOBAL_CONFIG_CACHE = 0, // 0x01 g
@@ -570,9 +582,9 @@ class TC_GAME_API WorldSession
void HandleQueryTimeOpcode(WorldPacket& recvPacket);
void HandleCreatureQueryOpcode(WorldPacket& recvPacket);
void HandleCreatureQueryOpcode(WorldPackets::Query::QueryCreature& query);
void HandleGameObjectQueryOpcode(WorldPacket& recvPacket);
void HandleGameObjectQueryOpcode(WorldPackets::Query::QueryGameObject& query);
void HandleMoveWorldportAckOpcode(WorldPacket& recvPacket);
void HandleMoveWorldportAck(); // for server-side calls
@@ -710,7 +722,7 @@ class TC_GAME_API WorldSession
void HandleSwapInvItemOpcode(WorldPacket& recvPacket);
void HandleDestroyItemOpcode(WorldPacket& recvPacket);
void HandleAutoEquipItemOpcode(WorldPacket& recvPacket);
void HandleItemQuerySingleOpcode(WorldPacket& recvPacket);
void HandleItemQuerySingleOpcode(WorldPackets::Query::QueryItemSingle& query);
void HandleSellItemOpcode(WorldPacket& recvPacket);
void HandleBuyItemInSlotOpcode(WorldPacket& recvPacket);
void HandleBuyItemOpcode(WorldPacket& recvPacket);
@@ -749,7 +761,7 @@ class TC_GAME_API WorldSession
void HandleQuestgiverQueryQuestOpcode(WorldPacket& recvPacket);
void HandleQuestgiverChooseRewardOpcode(WorldPacket& recvPacket);
void HandleQuestgiverRequestRewardOpcode(WorldPacket& recvPacket);
void HandleQuestQueryOpcode(WorldPacket& recvPacket);
void HandleQuestQueryOpcode(WorldPackets::Quest::QueryQuestInfo& query);
void HandleQuestgiverCancel(WorldPacket& recvData);
void HandleQuestLogSwapQuest(WorldPacket& recvData);
void HandleQuestLogRemoveQuest(WorldPacket& recvData);
@@ -970,7 +982,7 @@ class TC_GAME_API WorldSession
void HandleWorldStateUITimerUpdate(WorldPacket& recvData);
void HandleReadyForAccountDataTimes(WorldPacket& recvData);
void HandleQueryQuestsCompleted(WorldPacket& recvData);
void HandleQuestPOIQuery(WorldPacket& recvData);
void HandleQuestPOIQuery(WorldPackets::Query::QuestPOIQuery& query);
void HandleEjectPassenger(WorldPacket& data);
void HandleEnterPlayerVehicle(WorldPacket& data);
void HandleUpdateProjectilePosition(WorldPacket& recvPacket);