TrinityCore
CharacterPackets.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "CharacterPackets.h"
19#include "ClubUtils.h"
20#include "DB2Stores.h"
21#include "Field.h"
22#include "ObjectMgr.h"
23#include "Player.h"
24#include "StringConvert.h"
25#include "World.h"
26
27namespace UF
28{
29ByteBuffer& operator<<(ByteBuffer& data, ChrCustomizationChoice const& customizationChoice)
30{
31 data << uint32(customizationChoice.ChrCustomizationOptionID);
32 data << uint32(customizationChoice.ChrCustomizationChoiceID);
33
34 return data;
35}
36
38{
39 data >> customizationChoice.ChrCustomizationOptionID;
40 data >> customizationChoice.ChrCustomizationChoiceID;
41
42 return data;
43}
44}
45
46namespace WorldPackets
47{
48namespace Character
49{
51{
52 auto first = customizations.begin();
53 auto last = customizations.end();
54 for (auto itr = first; itr != last; ++itr)
55 {
56 auto insertion = std::upper_bound(first, itr, *itr, [](ChrCustomizationChoice const& left, ChrCustomizationChoice const& right)
57 {
59 });
60 std::rotate(insertion, itr, std::next(itr));
61 }
62}
63
64ByteBuffer& operator<<(ByteBuffer& data, CustomTabardInfo const& customTabardInfo)
65{
66 data << int32(customTabardInfo.EmblemStyle);
67 data << int32(customTabardInfo.EmblemColor);
68 data << int32(customTabardInfo.BorderStyle);
69 data << int32(customTabardInfo.BorderColor);
70 data << int32(customTabardInfo.BackgroundColor);
71
72 return data;
73}
74
76{
77 data >> customTabardInfo.EmblemStyle;
78 data >> customTabardInfo.EmblemColor;
79 data >> customTabardInfo.BorderStyle;
80 data >> customTabardInfo.BorderColor;
81 data >> customTabardInfo.BackgroundColor;
82
83 return data;
84}
85
87{
89}
90
92{
93 // 0 1 2 3 4 5
94 // "SELECT characters.guid, characters.name, characters.race, characters.class, characters.gender, characters.level, "
95 // 6 7 8 9 10
96 // "characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, "
97 // 11 12 13 14 15 16 17
98 // "guild_member.guildid, characters.playerFlags, characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, "
99 // 18 19 20 21 22
100 // "character_banned.guid, characters.slot, characters.logout_time, characters.activeTalentGroup, characters.lastLoginBuild, "
101 // 23 24 25 26 27
102 // "characters.personalTabardEmblemStyle, characters.personalTabardEmblemColor, characters.personalTabardBorderStyle, characters.personalTabardBorderColor, characters.personalTabardBackgroundColor "
103 // 28
104 // "character_declinedname.genitive"
105
106 Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
108 Name = fields[1].GetString();
109 RaceID = fields[2].GetUInt8();
110 ClassID = fields[3].GetUInt8();
111 SexID = fields[4].GetUInt8();
112 ExperienceLevel = fields[5].GetUInt8();
113 ZoneID = int32(fields[6].GetUInt16());
114 MapID = int32(fields[7].GetUInt16());
115 PreloadPos = Position(fields[8].GetFloat(), fields[9].GetFloat(), fields[10].GetFloat());
116
117 if (ObjectGuid::LowType guildId = fields[11].GetUInt64())
118 GuildGUID = ObjectGuid::Create<HighGuid::Guild>(guildId);
119
120 uint32 playerFlags = fields[12].GetUInt32();
121 uint32 atLoginFlags = fields[13].GetUInt16();
122
123 if (playerFlags & PLAYER_FLAGS_RESTING)
125
126 if (atLoginFlags & AT_LOGIN_RESURRECT)
127 playerFlags &= ~PLAYER_FLAGS_GHOST;
128
129 if (playerFlags & PLAYER_FLAGS_GHOST)
131
132 if (atLoginFlags & AT_LOGIN_RENAME)
134
135 if (fields[18].GetUInt64())
137
138 if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[28].GetString().empty())
140
141 if (atLoginFlags & AT_LOGIN_CUSTOMIZE)
143 else if (atLoginFlags & AT_LOGIN_CHANGE_FACTION)
145 else if (atLoginFlags & AT_LOGIN_CHANGE_RACE)
147
148 Flags3 = 0;
149 Flags4 = 0;
150 FirstLogin = (atLoginFlags & AT_LOGIN_FIRST) != 0;
151
152 // show pet at selection character in character list only for non-ghost character
154 {
155 if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(fields[14].GetUInt32()))
156 {
157 PetCreatureDisplayID = fields[15].GetUInt32();
158 PetExperienceLevel = fields[16].GetUInt16();
159 PetCreatureFamilyID = creatureInfo->family;
160 }
161 }
162
163 BoostInProgress = false;
164 ProfessionIds[0] = 0;
165 ProfessionIds[1] = 0;
166
167 std::vector<std::string_view> equipment = Trinity::Tokenize(fields[17].GetStringView(), ' ', false);
168 ListPosition = fields[19].GetUInt8();
169 LastPlayedTime = fields[20].GetInt64();
170 if (ChrSpecializationEntry const* spec = sDB2Manager.GetChrSpecializationByIndex(ClassID, fields[21].GetUInt8()))
171 SpecID = spec->ID;
172
173 LastLoginVersion = fields[22].GetUInt32();
174
175 PersonalTabard.EmblemStyle = fields[23].GetInt32();
176 PersonalTabard.EmblemColor = fields[24].GetInt32();
177 PersonalTabard.BorderStyle = fields[25].GetInt32();
178 PersonalTabard.BorderColor = fields[26].GetInt32();
180
181 constexpr std::size_t equipmentFieldsPerSlot = 5;
182
183 for (std::size_t slot = 0; slot < VisualItems.size() && (slot + 1) * equipmentFieldsPerSlot <= equipment.size(); ++slot)
184 {
185 std::size_t visualBase = slot * equipmentFieldsPerSlot;
186 VisualItems[slot].InvType = Trinity::StringTo<uint8>(equipment[visualBase + 0]).value_or(0);
187 VisualItems[slot].DisplayID = Trinity::StringTo<uint32>(equipment[visualBase + 1]).value_or(0);
188 VisualItems[slot].DisplayEnchantID = Trinity::StringTo<uint32>(equipment[visualBase + 2]).value_or(0);
189 VisualItems[slot].Subclass = Trinity::StringTo<uint8>(equipment[visualBase + 3]).value_or(0);
190 VisualItems[slot].SecondaryItemModifiedAppearanceID = Trinity::StringTo<int32>(equipment[visualBase + 4]).value_or(0);
191 }
192}
193
195{
196 data << uint32(visualItem.DisplayID);
197 data << uint32(visualItem.DisplayEnchantID);
198 data << int32(visualItem.SecondaryItemModifiedAppearanceID);
199 data << uint8(visualItem.InvType);
200 data << uint8(visualItem.Subclass);
201
202 return data;
203}
204
206{
207 ASSERT(charInfo.MailSenders.size() == charInfo.MailSenderTypes.size());
208
209 data << charInfo.Guid;
210 data << uint64(charInfo.GuildClubMemberID);
211 data << uint8(charInfo.ListPosition);
212 data << uint8(charInfo.RaceID);
213 data << uint8(charInfo.ClassID);
214 data << uint8(charInfo.SexID);
215 data << uint32(charInfo.Customizations.size());
216 data << uint8(charInfo.ExperienceLevel);
217 data << int32(charInfo.ZoneID);
218 data << int32(charInfo.MapID);
219 data << charInfo.PreloadPos;
220 data << charInfo.GuildGUID;
221 data << uint32(charInfo.Flags);
222 data << uint32(charInfo.Flags2);
223 data << uint32(charInfo.Flags3);
224 data << uint32(charInfo.PetCreatureDisplayID);
225 data << uint32(charInfo.PetExperienceLevel);
226 data << uint32(charInfo.PetCreatureFamilyID);
227
228 data << uint32(charInfo.ProfessionIds[0]);
229 data << uint32(charInfo.ProfessionIds[1]);
230
232 data << visualItem;
233
234 data << charInfo.LastPlayedTime;
235 data << int16(charInfo.SpecID);
236 data << int32(charInfo.Unknown703);
237 data << int32(charInfo.LastLoginVersion);
238 data << uint32(charInfo.Flags4);
239 data << uint32(charInfo.MailSenders.size());
240 data << uint32(charInfo.MailSenderTypes.size());
241 data << uint32(charInfo.OverrideSelectScreenFileDataID);
242 data << charInfo.PersonalTabard;
243
244 for (ChrCustomizationChoice const& customization : charInfo.Customizations)
245 data << customization;
246
247 if (!charInfo.MailSenderTypes.empty())
248 data.append(charInfo.MailSenderTypes.data(), charInfo.MailSenderTypes.size());
249
250 data.WriteBits(charInfo.Name.length(), 6);
251 data.WriteBit(charInfo.FirstLogin);
252 data.WriteBit(charInfo.BoostInProgress);
253 data.WriteBits(charInfo.unkWod61x, 5);
254 data.WriteBit(charInfo.RpeResetAvailable);
256
257 for (std::string const& str : charInfo.MailSenders)
258 data.WriteBits(str.length() + 1, 6);
259
260 data.FlushBits();
261
262 for (std::string const& str : charInfo.MailSenders)
263 if (!str.empty())
264 data << str;
265
266 data.WriteString(charInfo.Name);
267
268 return data;
269}
270
272{
273 data << int32(raceUnlock.RaceID);
274 data.WriteBit(raceUnlock.HasExpansion);
275 data.WriteBit(raceUnlock.HasAchievement);
276 data.WriteBit(raceUnlock.HasHeritageArmor);
277 data.WriteBit(raceUnlock.IsLocked);
278 data.FlushBits();
279
280 return data;
281}
282
284{
285 data << int32(unlockedConditionalAppearance.AchievementID);
286 data << int32(unlockedConditionalAppearance.Unused);
287
288 return data;
289}
290
292{
293 data << int32(raceLimitDisableInfo.RaceID);
294 data << int32(raceLimitDisableInfo.BlockReason);
295
296 return data;
297}
298
300{
301 _worldPacket.reserve(9 + Characters.size() * sizeof(CharacterInfo) + RaceUnlockData.size() * sizeof(RaceUnlock));
302
310 _worldPacket << uint32(Characters.size());
315
318
319 for (UnlockedConditionalAppearance const& unlockedConditionalAppearance : UnlockedConditionalAppearances)
320 _worldPacket << unlockedConditionalAppearance;
321
322 for (RaceLimitDisableInfo const& raceLimitDisableInfo : RaceLimitDisables)
323 _worldPacket << raceLimitDisableInfo;
324
325 for (CharacterInfo const& charInfo : Characters)
326 _worldPacket << charInfo;
327
328 for (RaceUnlock const& raceUnlock : RaceUnlockData)
329 _worldPacket << raceUnlock;
330
331 return &_worldPacket;
332}
333
335{
336 _worldPacket >> SequenceIndex;
338}
339
341{
342 _worldPacket << uint32(SequenceIndex);
343 _worldPacket << uint32(Result);
344
345 return &_worldPacket;
346}
347
349{
350 CreateInfo = std::make_shared<CharacterCreateInfo>();
351 uint32 nameLength = _worldPacket.ReadBits(6);
352 bool const hasTemplateSet = _worldPacket.ReadBit();
353 CreateInfo->IsTrialBoost = _worldPacket.ReadBit();
354 CreateInfo->UseNPE = _worldPacket.ReadBit();
355
356 _worldPacket >> CreateInfo->Race;
357 _worldPacket >> CreateInfo->Class;
358 _worldPacket >> CreateInfo->Sex;
359 CreateInfo->Customizations.resize(_worldPacket.read<uint32>());
360 CreateInfo->Name = _worldPacket.ReadString(nameLength);
361 if (hasTemplateSet)
362 CreateInfo->TemplateSet = _worldPacket.read<int32>();
363
364 for (ChrCustomizationChoice& customization : CreateInfo->Customizations)
365 _worldPacket >> customization;
366
367 SortCustomizations(CreateInfo->Customizations);
368}
369
371{
372 _worldPacket << uint8(Code);
373 _worldPacket << Guid;
374 return &_worldPacket;
375}
376
378{
379 _worldPacket >> Guid;
380}
381
383{
384 _worldPacket << uint8(Code);
385 return &_worldPacket;
386}
387
389{
390 RenameInfo = std::make_shared<CharacterRenameInfo>();
391 _worldPacket >> RenameInfo->Guid;
392 RenameInfo->NewName = _worldPacket.ReadString(_worldPacket.ReadBits(6));
393}
394
396{
397 _worldPacket << uint8(Result);
398 _worldPacket.WriteBit(Guid.has_value());
399 _worldPacket.WriteBits(Name.length(), 6);
401
402 if (Guid)
403 _worldPacket << *Guid;
404
406
407 return &_worldPacket;
408}
409
411{
412 CustomizeInfo = std::make_shared<CharCustomizeInfo>();
413 _worldPacket >> CustomizeInfo->CharGUID;
414 _worldPacket >> CustomizeInfo->SexID;
415 CustomizeInfo->Customizations.resize(_worldPacket.read<uint32>());
416 for (ChrCustomizationChoice& customization : CustomizeInfo->Customizations)
417 _worldPacket >> customization;
418
419 SortCustomizations(CustomizeInfo->Customizations);
420
421 CustomizeInfo->CharName = _worldPacket.ReadString(_worldPacket.ReadBits(6));
422}
423
425{
426 RaceOrFactionChangeInfo = std::make_shared<CharRaceOrFactionChangeInfo>();
427
428 RaceOrFactionChangeInfo->FactionChange = _worldPacket.ReadBit();
429
430 uint32 nameLength = _worldPacket.ReadBits(6);
431
432 _worldPacket >> RaceOrFactionChangeInfo->Guid;
433 _worldPacket >> RaceOrFactionChangeInfo->SexID;
434 _worldPacket >> RaceOrFactionChangeInfo->RaceID;
435 _worldPacket >> RaceOrFactionChangeInfo->InitialRaceID;
436 RaceOrFactionChangeInfo->Customizations.resize(_worldPacket.read<uint32>());
437 RaceOrFactionChangeInfo->Name = _worldPacket.ReadString(nameLength);
438 for (ChrCustomizationChoice& customization : RaceOrFactionChangeInfo->Customizations)
439 _worldPacket >> customization;
440
441 SortCustomizations(RaceOrFactionChangeInfo->Customizations);
442}
443
445{
446 _worldPacket << uint8(Result);
447 _worldPacket << Guid;
448 _worldPacket.WriteBit(Display.has_value());
450
451 if (Display)
452 {
453 _worldPacket.WriteBits(Display->Name.length(), 6);
454 _worldPacket << uint8(Display->SexID);
455 _worldPacket << uint8(Display->RaceID);
456 _worldPacket << uint32(Display->Customizations->size());
457 _worldPacket.WriteString(Display->Name);
458 for (ChrCustomizationChoice customization : *Display->Customizations)
459 _worldPacket << customization;
460 }
461
462 return &_worldPacket;
463}
464
466{
468 _worldPacket >> Sex;
469}
470
472{
474 _worldPacket.WriteBits(Name.length(), 6);
476
478
479 return &_worldPacket;
480}
481
483{
484}
485
487{
488 Entries.resize(_worldPacket.ReadBits(9));
489 for (ReorderInfo& reorderInfo : Entries)
490 {
491 _worldPacket >> reorderInfo.PlayerGUID;
492 _worldPacket >> reorderInfo.NewPosition;
493 }
494}
495
497{
498 UndeleteInfo = std::make_shared<CharacterUndeleteInfo>();
499 _worldPacket >> UndeleteInfo->ClientToken;
500 _worldPacket >> UndeleteInfo->CharacterGuid;
501}
502
504{
509 return &_worldPacket;
510}
511
513{
517 return &_worldPacket;
518}
519
521{
524}
525
527{
529 _worldPacket << Pos;
531 return &_worldPacket;
532}
533
535{
537 return &_worldPacket;
538}
539
541{
543}
544
546{
550 return &_worldPacket;
551}
552
554{
557}
558
560{
563
564 return &_worldPacket;
565}
566
568{
570}
571
573{
575}
576
578{
583
584 return &_worldPacket;
585}
586
588{
590}
591
593{
598 for (ChrCustomizationChoice& customization : Customizations)
599 _worldPacket >> customization;
600
602}
603
605{
607 return &_worldPacket;
608}
609
611{
616 _worldPacket << float(GroupBonus);
617
618 return &_worldPacket;
619}
620
622{
624
625 return &_worldPacket;
626}
627
629{
631}
632
634{
636}
637
639{
642}
643
645{
647}
648
650{
652 return &_worldPacket;
653}
654
656 : ServerPacket(SMSG_CHAR_CUSTOMIZE_SUCCESS, 16 + 1 + 1 + 1 + 1 + 1 + 1 + 1), Customizations(info->Customizations)
657{
658 CharGUID = info->CharGUID;
659 SexID = info->SexID;
660 CharName = info->CharName;
661}
662
664{
668 for (ChrCustomizationChoice customization : Customizations)
669 _worldPacket << customization;
670
671 _worldPacket.WriteBits(CharName.length(), 6);
674
675 return &_worldPacket;
676}
677
679{
682
683 return &_worldPacket;
684}
685
687{
689
690 uint8 stringLengths[MAX_DECLINED_NAME_CASES];
691
692 for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
693 stringLengths[i] = _worldPacket.ReadBits(7);
694
695 for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i)
696 DeclinedNames.name[i] = _worldPacket.ReadString(stringLengths[i]);
697}
698
700{
703
704 return &_worldPacket;
705}
706
708{
711}
712
714{
716
717 return &_worldPacket;
718}
719}
720}
#define sDB2Manager
Definition: DB2Stores.h:538
uint8_t uint8
Definition: Define.h:144
int16_t int16
Definition: Define.h:139
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
#define sObjectMgr
Definition: ObjectMgr.h:1946
@ PLAYER_FLAGS_RESTING
Definition: Player.h:433
@ PLAYER_FLAGS_GHOST
Definition: Player.h:432
@ AT_LOGIN_FIRST
Definition: Player.h:543
@ AT_LOGIN_RESURRECT
Definition: Player.h:546
@ AT_LOGIN_CUSTOMIZE
Definition: Player.h:541
@ AT_LOGIN_RENAME
Definition: Player.h:538
@ AT_LOGIN_CHANGE_RACE
Definition: Player.h:545
@ AT_LOGIN_CHANGE_FACTION
Definition: Player.h:544
@ CLASS_HUNTER
@ CLASS_WARLOCK
@ CLASS_DEATH_KNIGHT
@ CHAR_CUSTOMIZE_FLAG_RACE
@ CHAR_CUSTOMIZE_FLAG_FACTION
@ CHAR_CUSTOMIZE_FLAG_CUSTOMIZE
@ CHARACTER_FLAG_RESTING
@ CHARACTER_FLAG_GHOST
@ CHARACTER_FLAG_DECLINED
@ CHARACTER_FLAG_LOCKED_BY_BILLING
@ CHARACTER_FLAG_RENAME
#define MAX_DECLINED_NAME_CASES
Definition: UnitDefines.h:484
uint32 ReadBits(int32 bits)
Definition: ByteBuffer.h:209
void reserve(size_t ressize)
Definition: ByteBuffer.h:546
void WriteString(std::string const &str)
Definition: ByteBuffer.h:500
void resize(size_t newsize)
Definition: ByteBuffer.h:539
void append(T value)
Definition: ByteBuffer.h:143
bool WriteBit(bool bit)
Definition: ByteBuffer.h:175
void WriteBits(std::size_t value, int32 bits)
Definition: ByteBuffer.h:203
void FlushBits()
Definition: ByteBuffer.h:155
std::string ReadString(uint32 length, bool requireValidUtf8=true)
Definition: ByteBuffer.cpp:78
bool ReadBit()
Definition: ByteBuffer.h:191
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
std::string GetString() const
Definition: Field.cpp:118
int64 GetInt64() const
Definition: Field.cpp:86
uint16 GetUInt16() const
Definition: Field.cpp:46
uint32 GetUInt32() const
Definition: Field.cpp:62
int32 GetInt32() const
Definition: Field.cpp:70
uint64 LowType
Definition: ObjectGuid.h:278
Array< ChrCustomizationChoice, 250 > Customizations
WorldPacket const * Write() override
Array< ChrCustomizationChoice, 250 > const & Customizations
CharCustomizeSuccess(CharCustomizeInfo const *customizeInfo)
WorldPacket const * Write() override
WorldPacket const * Write() override
bool IsNewPlayerRestrictionSkipped
allows client to skip new player restrictions
std::vector< CharacterInfo > Characters
all characters on the list
bool IsNewPlayer
forbids hero classes and allied races
bool IsDeletedCharacters
used for character undelete list
bool IsNewPlayerRestricted
forbids using level boost and class trials
std::vector< RaceLimitDisableInfo > RaceLimitDisables
std::vector< UnlockedConditionalAppearance > UnlockedConditionalAppearances
WorldPacket const * Write() override
WorldPacket const * Write() override
TaggedPosition< Position::XYZO > Pos
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * Write() override
float FarClip
Visibility distance (for terrain)
ObjectGuid Guid
Guid of the player that is logging in.
WorldPacket const * Write() override
std::shared_ptr< CharacterUndeleteInfo > UndeleteInfo
uint32 CurrentCooldown
Current cooldown until next free character restoration. (in sec)
uint32 MaxCooldown
Max. cooldown until next free character restoration. Displayed in undelete confirm message....
OpcodeClient GetOpcode() const
Definition: Packet.h:68
WorldPacket _worldPacket
Definition: Packet.h:43
@ CMSG_ENUM_CHARACTERS
Definition: Opcodes.h:338
@ CMSG_ENUM_CHARACTERS_DELETED_BY_CLIENT
Definition: Opcodes.h:339
@ CMSG_REORDER_CHARACTERS
Definition: Opcodes.h:695
@ SMSG_CHAR_CUSTOMIZE_SUCCESS
Definition: Opcodes.h:1104
#define sWorld
Definition: World.h:931
@ CONFIG_DECLINED_NAMES_USED
Definition: World.h:135
uint64 CreateClubMemberId(ObjectGuid guid)
Definition: ClubUtils.cpp:22
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition: Util.cpp:56
Definition: Object.h:109
ByteBuffer & operator>>(ByteBuffer &data, ChrCustomizationChoice &customizationChoice)
ByteBuffer & operator<<(ByteBuffer &data, ChrCustomizationChoice const &customizationChoice)
ByteBuffer & operator<<(ByteBuffer &data, CustomTabardInfo const &customTabardInfo)
void SortCustomizations(Array< ChrCustomizationChoice, 250 > &customizations)
ByteBuffer & operator>>(ByteBuffer &data, CustomTabardInfo &customTabardInfo)
STL namespace.
std::string name[MAX_DECLINED_NAME_CASES]
Definition: UnitDefines.h:491
ObjectGuid CharacterGuid
User specified variables.
CharacterInfo(Field *fields)
Initialize the struct with values from QueryResult.
uint64 GuildClubMemberID
same as bgs.protocol.club.v1.MemberId.unique_id, guessed basing on SMSG_QUERY_PLAYER_NAME_RESPONSE (t...
void rotate(float x0, float y0, float *x, float *y, float angle)
Definition: vec3d.h:243