PDA

View Full Version : 02/13/13 changes



ShortBuss
02-13-2013, 11:08 AM
Looks like the x/y/z changed again and I'm not sure how to work that part out yet. However I am starting to get some of the updated opcodes:
OP_PlayerProfile = 6725
OP_ZoneEntry = 2cbe
OP_TimeOfDay = 2d98
OP_NewZone = 082d
OP_SpawnDoor = 0e70
OP_GroundSpawn = 11ef
OP_SendZonePoints = 0a1d
OP_GuildMOTD = 7864
OP_ClientUpdate = 6cc2
OP_NpcMoveUpdate = 7342
OP_MobUpdate = 282a
OP_Consider = 0fcd
OP_TargetMouse = 02f7

showeq42
02-13-2013, 04:09 PM
struct playerSelfPosStruct
{
/*0000*/ uint16_t unknown0000; // ***Placeholder (update time counter?)
/*0002*/ uint16_t spawnId; // Player's spawn id
/*0004*/ uint16_t unknown0004; // ***Placeholder
/*0006*/ unsigned pitch:12; // pitch (up/down heading)
signed animation:10; // velocity
unsigned padding1:10; // ***Placeholder
/*0010*/ float x; // x coord (1st loc value)
/*0014*/ float deltaX; // Change in y
/*0018*/ float y; // y coord (2nd loc value)
/*0022*/ float z; // z coord (3rd loc value)
/*0026*/ float deltaY; // Change in x
/*0030*/ unsigned heading:12; // Directional heading
unsigned padding2:10; // ***Placeholder
unsigned padding3:10; // ***Placeholder
/*0034*/ float deltaZ; // Change in z
/*0038*/ signed deltaHeading:10; // change in heading
unsigned padding4:10; // ***Placeholder
unsigned padding5:12; // ***Placeholder
/*0042*/
};




opcode id="6864" name="OP_DeleteSpawn
opcode id="0ead" name="OP_RemoveSpawn"
opcode id="62bd" name="OP_Death"
opcode id="7f78" name="OP_ClickObject"

ShortBuss
02-13-2013, 04:49 PM
Can someone take me through some rough steps as to how to correct the playerselfposstruct? I may just have a big lack in understanding of how to convert the packet data into the proper variables in the structure. I located an NPC that doesn't move, got it's /loc, then looked at a pre-patch log file for that spawn. I got the 20 bytes for the position, converted to binary then tried to get x/y/z figured out based on the known location (/loc) and using the pre-patch structure. I couldn't get anything close but also realize that the values in the struct are signed int while the /loc return is decimal. Maybe there's a conversion I'm missing.

showeq42
02-13-2013, 05:54 PM
struct playerSpawnPosStruct
{
/*0000*/ uint16_t spawnId;
/*0002*/ uint16_t spawnId2;
/*0004*/ unsigned pitch:12;
signed z:19; // z coord
unsigned padding01:1;
/*0008*/ signed deltaX:13; // change in x
signed y:19; // y coord
/*0012*/ signed deltaHeading:10;// change in heading
unsigned heading:12; // heading
signed animation:10; // velocity
/*0016*/ signed deltaZ:13; // change in z
signed x:19; // x coord
/*0020*/ signed deltaY:13; // change in y
unsigned padding02:19;
/*0024*/
};

showeq42
02-13-2013, 06:13 PM
Can someone take me through some rough steps as to how to correct the playerselfposstruct? I may just have a big lack in understanding of how to convert the packet data into the proper variables in the structure. I located an NPC that doesn't move, got it's /loc, then looked at a pre-patch log file for that spawn. I got the 20 bytes for the position, converted to binary then tried to get x/y/z figured out based on the known location (/loc) and using the pre-patch structure. I couldn't get anything close but also realize that the values in the struct are signed int while the /loc return is decimal. Maybe there's a conversion I'm missing.

I use debugging code in player.cpp and spawnshell.cpp, it starts with:



#if 0
// Debug positioning without having to recompile everything...


there are two of these in spawnshell.cpp, use the 2nd one

my debugging code after today's patch, player.cpp:



#if 0
// Debug positioning without having to recompile everything...
#pragma pack(1)
struct pos
{
/*0000*/ uint16_t unknown0000; // ***Placeholder (update time counter?)
/*0002*/ uint16_t spawnId; // Player's spawn id
/*0004*/ uint16_t unknown0004; // ***Placeholder
/*0006*/ unsigned pitch:12; // pitch (up/down heading)
signed animation:10; // velocity
unsigned padding1:10; // ***Placeholder
/*0010*/ float x; // x coord (1st loc value)
/*0014*/ float deltaX; // Change in y
/*0018*/ float y; // y coord (2nd loc value)
/*0022*/ float z; // z coord (3rd loc value)
/*0026*/ float deltaY; // Change in x
/*0030*/ unsigned heading:12; // Directional heading
unsigned padding2:10; // ***Placeholder
unsigned padding3:10; // ***Placeholder
/*0034*/ float deltaZ; // Change in z
/*0038*/ signed deltaHeading:10; // change in heading
unsigned padding4:10; // ***Placeholder
unsigned padding5:12; // ***Placeholder
/*0042*/
};
#pragma pack(0)
struct pos *p = (struct pos *)data;
printf("[%.2x](%f, %f, %f), dx %f dy %f dz %f head %d dhead %d anim %d pitch %d (%x, %x, %x, %x %x)\n",
p->spawnId, p->x, p->y, p->z,
p->deltaX, p->deltaY, p->deltaZ,
p->heading, p->deltaHeading,
p->animation, p->pitch,
p->padding1, p->padding2, p->padding3,
p->padding4, p->padding5 );
#endif


and spawnshell.cpp,
i added the line "if (p->spawnId == 0x1234)"... that's the id of the 2nd char I use.



#if 0
// Debug positioning without having to recompile everything...
#pragma pack(1)
struct pos
{
/*0000*/ uint16_t spawnId;
/*0002*/ uint16_t spawnId2;
/*0004*/ unsigned pitch:12;
signed z:19; // z coord
unsigned padding01:1;
/*0008*/ signed deltaX:13; // change in x
signed y:19; // y coord
/*0012*/ signed deltaHeading:10;// change in heading
unsigned heading:12; // heading
signed animation:10; // velocity
/*0016*/ signed deltaZ:13; // change in z
signed x:19; // x coord
/*0020*/ signed deltaY:13; // change in y
unsigned padding02:19;
/*0024*/
};
#pragma pack(0)
struct pos *p = (struct pos *)data;
if (p->spawnId == 0x1234)
printf("[%.2x](%f, %f, %f), dx %f dy %f dz %f\n head %d dhead %d anim %d pitch %d (%x, %x)\n",
p->spawnId, float(p->x)/8.0, float(p->y/8.0), float(p->z)/8.0,
float(p->deltaX)/4.0, float(p->deltaY)/4.0,
float(p->deltaZ)/4.0,
p->heading, p->deltaHeading,
p->animation, p->pitch,
p->padding01, p->padding02);
#endif

ShortBuss
02-13-2013, 10:27 PM
Thank you for the explanation the debugging. I will give that a go with the corrected structs to see how it's supposed to look when working properly. I hadn't thought about running a second char with known spawn ID to help track this down, that's another good hint. Also thank you for providing the corrected struts again; with those changes in place the major functionality looks to all be working. I'm going to be away for a couple days but if we are still missing opcodes after that I'll see what else I can help find.

0men
02-14-2013, 10:52 AM
Zone entry code at least must have changed again with the 14-02-2013 update... I wish I could remember how to analyze this stuff :)

EDIT: Hmm, odd. Didn't work the first zone I tried, but now it's worked in another zone, NPCs are still spread over ridiculous range of X-numbers but drops seem OK.

EDIT2: It looks to me like the initial zone spawn info is messed up but when NPCs move they send their location and speed updates and that is still in whatever format it was, so anything that isn't static "auto-corrects". So I guess it should be possible to compare the numbers from the 2 sources with an NPC that only moves a little -- maybe a 2nd account with a character with a pet. Is there some way other than using something like GDB to do this?

fransick
02-14-2013, 11:22 AM
Zone entry code at least must have changed again with the 14-02-2013 update... I wish I could remember how to analyze this stuff :)

EDIT: Hmm, odd. Didn't work the first zone I tried, but now it's worked in another zone, NPCs are still spread over ridiculous range of X-numbers but drops seem OK.

Looks like the playerSpawnPasStruct changed again. I really need to better understand how to interpret the debug data. I think I am losing my way on the padding and different bit lengths. If someone can help me through that on IRC or entertain my noob questions, I am sure I can figure it out eventually.

I'll have some time to work on opcodes tomorrow night I hope.

ShortBuss
02-14-2013, 12:35 PM
playerSpawnPosStruct is used for when mobs move. Spawnstruct is used on zone in. Look at spawnstruct and you will see a section with the position data. This seems to stay in sync with playerSpawnPosStruct. So take the updated playerSpawnPosStruct, remove the first 2 variables ( spawnid & spawnid2) then paste the rest over the position data in spawnstruct. Should be 20bytes total. On the road now but can provide a patch diff later tonight to help.

0men
02-14-2013, 05:23 PM
Thanks, that worked just fine!

ShortBuss
02-14-2013, 11:03 PM
Here is the everquest.h patch I have now, based on the updates by showeq42



Index: src/everquest.h
================================================== =================
--- src/everquest.h (revision 783)
+++ src/everquest.h (working copy)
@@ -1076,23 +1076,18 @@
{
struct
{
- signed padding0004:13;
- signed y:19; // y coord
-
- signed deltaX:13; // change in x
- signed deltaHeading:10;// change in heading
- signed padding0008:9;
-
- signed deltaY:13; // change in y
- signed z:19; // z coord
-
- signed x:19; // x coord
- signed animation:10; // animation
- signed padding0016:3;
-
- unsigned heading:12; // heading
- signed deltaZ:13; // change in z
- signed padding0020:7;
+ unsigned pitch:12;
+ signed z:19; // z coord
+ unsigned padding01:1;
+ signed deltaX:13; // change in x
+ signed y:19; // y coord
+ signed deltaHeading:10;// change in heading
+ unsigned heading:12; // heading
+ signed animation:10; // velocity
+ signed deltaZ:13; // change in z
+ signed x:19; // x coord
+ signed deltaY:13; // change in y
+ unsigned padding02:19;
};
int32_t posData[5];
};
@@ -2339,19 +2334,18 @@
{
/*0000*/ uint16_t spawnId;
/*0002*/ uint16_t spawnId2;
-/*0004*/ signed padding0004:13;
- signed y:19; // y coord
-/*0008*/ signed deltaX:13; // change in x
- signed deltaHeading:10;// change in heading
- signed padding0008:9;
-/*0012*/ signed deltaY:13; // change in y
+/*0004*/ unsigned pitch:12;
signed z:19; // z coord
-/*0016*/ signed x:19; // x coord
- signed animation:10; // animation
- signed padding0016:3;
-/*0020*/ unsigned heading:12; // heading
- signed deltaZ:13; // change in z
- signed padding0020:7;
+ unsigned padding01:1;
+/*0008*/ signed deltaX:13; // change in x
+ signed y:19; // y coord
+/*0012*/ signed deltaHeading:10;// change in heading
+ unsigned heading:12; // heading
+ signed animation:10; // velocity
+/*0016*/ signed deltaZ:13; // change in z
+ signed x:19; // x coord
+/*0020*/ signed deltaY:13; // change in y
+ unsigned padding02:19;
/*0024*/
};

@@ -2363,21 +2357,24 @@

struct playerSelfPosStruct
{
-/*0000*/ uint8_t unknown0000[2]; // ***Placeholder (update time counter?)
+/*0000*/ uint16_t unknown0000; // ***Placeholder (update time counter?)
/*0002*/ uint16_t spawnId; // Player's spawn id
-/*0004*/ uint8_t unknown0004[6]; // ***Placeholder -- BSH 13 Apr 2011
-/*0010*/ float deltaY; // Change in x
-/*0014*/ float x; // x coord (1st loc value)
+/*0004*/ uint16_t unknown0004; // ***Placeholder
+/*0006*/ unsigned pitch:12; // pitch (up/down heading)
+ signed animation:10; // velocity
+ unsigned padding1:10; // ***Placeholder
+/*0010*/ float x; // x coord (1st loc value)
+/*0014*/ float deltaX; // Change in y
/*0018*/ float y; // y coord (2nd loc value)
-/*0022*/ signed deltaHeading:10; // change in heading
- unsigned animation:10; // animation
- unsigned padding0024:12; // ***Placeholder
-/*0026*/ float deltaZ; // Change in z
-/*0030*/ float deltaX; // Change in y
-/*0034*/ float z; // z coord (3rd loc value)
-/*0038*/ unsigned heading:12; // Directional heading
- unsigned padding0040:10; // ***Placeholder
- unsigned padding0041:10; // ***Placeholder
+/*0022*/ float z; // z coord (3rd loc value)
+/*0026*/ float deltaY; // Change in x
+/*0030*/ unsigned heading:12; // Directional heading
+ unsigned padding2:10; // ***Placeholder
+ unsigned padding3:10; // ***Placeholder
+/*0034*/ float deltaZ; // Change in z
+/*0038*/ signed deltaHeading:10; // change in heading
+ unsigned padding4:10; // ***Placeholder
+ unsigned padding5:12; // ***Placeholder
/*0042*/
};

ShortBuss
02-15-2013, 09:44 AM
Here are some more op-codes. A couple of them I wasn't completely sure and need validation, marked those with **
opcode id="6a1a" name="OP_WearChange"
opcode id="6087" name="OP_SpawnAppearance" **Need to verify
opcode id="54fb" name="OP_Stamina" **Need to verify
opcode id="6719" name="OP_GuildMemberUpdate"
opcode id="16a5" name="OP_Action"
opcode id="1375" name="OP_Action2"
opcode id="0c17" name="OP_SpawnRename"
opcode id="7cd7" name="OP_GroupInvite"
opcode id="0076" name="OP_BuffFadeMsg"
opcode id="0b2b" name="OP_BeginCast"
opcode id="5dbc" name="OP_MemorizeSpell"
opcode id="3ecd" name="OP_SimpleMessage"
opcode id="0cf4" name="OP_CommonMessage"

ShortBuss
02-15-2013, 02:56 PM
Getting harder to figure these out since this is the first time I've gone through most of them. I think these are correct but could use validation:

opcode id="0eae" name="OP_AAExpUpdate"
opcode id="7814" name="OP_ExpUpdate"
opcode id="0396" name="OP_HPUpdate"
opcode id="499e" name="OP_ZoneChange"

ShortBuss
02-16-2013, 01:40 PM
I've done about all I can with the op codes. I'm fairly sure the group invite, group follow, and group update are not completely correct, but I couldn't get it all to work out properly in that area. The rest I'm mostly sure about. There's still some that were updated 1/16/13 that I could not figure out and I left those alone.



Index: conf/zoneopcodes.xml
================================================== =================
--- conf/zoneopcodes.xml (revision 783)
+++ conf/zoneopcodes.xml (working copy)
@@ -3,231 +3,231 @@
<seqopcodes>

<!-- Critical opcodes used directly by ShowEQ -->
- <opcode id="46bb" name="OP_PlayerProfile" updated="12/12/12">
+ <opcode id="6725" name="OP_PlayerProfile" updated="02/13/13">
<comment>CharProfileCode</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="1665" name="OP_ZoneEntry" updated="12/12/12">
+ <opcode id="2cbe" name="OP_ZoneEntry" updated="02/13/13">
<comment>ZoneEntryCode</comment>
<payload dir="client" typename="ClientZoneEntryStruct" sizechecktype="match"/>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="3be2" name="OP_TimeOfDay" updated="12/12/12">
+ <opcode id="2d98" name="OP_TimeOfDay" updated="02/13/13">
<comment>TimeOfDayCode</comment>
<payload dir="server" typename="timeOfDayStruct" sizechecktype="match"/>
</opcode>
- <opcode id="7fff" name="OP_NewZone" updated="12/12/12">
+ <opcode id="082d" name="OP_NewZone" updated="02/13/13">
<comment>NewZoneCode</comment>
<payload dir="server" typename="newZoneStruct" sizechecktype="match"/>
</opcode>
- <opcode id="7b6c" name="OP_SpawnDoor" updated="12/12/12">
+ <opcode id="0e70" name="OP_SpawnDoor" updated="02/13/13">
<comment>DoorSpawnsCode</comment>
<payload dir="server" typename="doorStruct" sizechecktype="modulus"/>
</opcode>
- <opcode id="4286" name="OP_GroundSpawn" updated="12/12/12">
+ <opcode id="11ef" name="OP_GroundSpawn" updated="02/13/13">
<comment>MakeDropCode</comment>
<payload dir="server" typename="makeDropStruct" sizechecktype="none"/>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="7922" name="OP_SendZonePoints" updated="12/12/12">
+ <opcode id="0a1d" name="OP_SendZonePoints" updated="02/13/13">
<comment>Coords in a zone that will port you to another zone</comment>
<payload dir="server" typename="zonePointsStruct" sizechecktype="none"/>
</opcode>
- <opcode id="25C5" name="OP_AAExpUpdate" updated="12/12/12">
+ <opcode id="0eae" name="OP_AAExpUpdate" updated="02/13/13">
<comment>Receiving AA experience. Also when percent to AA changes.</comment>
<payload dir="server" typename="altExpUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="47E3" name="OP_ExpUpdate" updated="12/12/12">
+ <opcode id="7814" name="OP_ExpUpdate" updated="02/13/13">
<comment>ExpUpdateCode</comment>
<payload dir="server" typename="expUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0561" name="OP_GuildMOTD" updated="12/12/12">
+ <opcode id="7864" name="OP_GuildMOTD" updated="02/13/13">
<comment>GuildMOTD</comment>
<payload dir="server" typename="guildMOTDStruct" sizechecktype="none"/>
</opcode>
- <opcode id="455d" name="OP_ClientUpdate" updated="12/12/12">
- <comment>Position updates - looks to be 455d and 42 bytes as of 12/12/12</comment>
+ <opcode id="6cc2" name="OP_ClientUpdate" updated="02/13/13">
+ <comment>Position updates</comment>
<payload dir="server" typename="playerSpawnPosStruct" sizechecktype="match"/>
<payload dir="both" typename="playerSelfPosStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5BD9" name="OP_NpcMoveUpdate" updated="12/12/12">
+ <opcode id="7342" name="OP_NpcMoveUpdate" updated="02/13/13">
<comment>Position updates</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="6b5a" name="OP_MobUpdate" updated="12/12/12">
+ <opcode id="282a" name="OP_MobUpdate" updated="02/13/13">
<comment>MobUpdateCode</comment>
<payload dir="both" typename="spawnPositionUpdate" sizechecktype="match"/>
</opcode>
- <opcode id="3c8e" name="OP_DeleteSpawn" updated="12/12/12">
+ <opcode id="6864" name="OP_DeleteSpawn" updated="02/13/13">
<comment>DeleteSpawnCode</comment>
<payload dir="both" typename="deleteSpawnStruct" sizechecktype="match"/>
</opcode>
- <opcode id="3B06" name="OP_RemoveSpawn" updated="12/12/12">
+ <opcode id="0ead" name="OP_RemoveSpawn" updated="02/13/13">
<comment>Remove spawn from zone</comment>
<payload dir="both" typename="removeSpawnStruct" sizechecktype="none"/>
</opcode>
- <opcode id="3a65" name="OP_Death" updated="12/12/12">
+ <opcode id="62bd" name="OP_Death" updated="02/13/13">
<comment>old NewCorpseCode</comment>
<payload dir="server" typename="newCorpseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="1ad3" name="OP_WearChange" updated="12/12/12">
+ <opcode id="6a1a" name="OP_WearChange" updated="02/13/13">
<comment>SpawnUpdateCode</comment>
<payload dir="both" typename="SpawnUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="7360" name="OP_SpawnAppearance" updated="12/12/12">
+ <opcode id="6087" name="OP_SpawnAppearance" updated="02/13/13">
<comment>SpawnAppearanceCode</comment>
<payload dir="both" typename="spawnAppearanceStruct" sizechecktype="match"/>
</opcode>
- <opcode id="1949" name="OP_Stamina" updated="12/12/12">
+ <opcode id="54fb" name="OP_Stamina" updated="02/13/13">
<comment>Server updating on hunger/thirst</comment>
<payload dir="server" typename="staminaStruct" sizechecktype="match"/>
</opcode>
- <opcode id="07b8" name="OP_HPUpdate" updated="12/12/12">
+ <opcode id="0396" name="OP_HPUpdate" updated="02/13/13">
<comment>NpcHpUpdateCode Update HP % of a PC or NPC</comment>
<payload dir="both" typename="hpNpcUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0048" name="OP_GuildMemberUpdate" updated="12/12/12">
+ <opcode id="6719" name="OP_GuildMemberUpdate" updated="02/13/13">
<comment>Info regarding guild members</comment>
<payload dir="server" typename="GuildMemberUpdate" sizechecktype="match"/>
</opcode>
- <opcode id="7992" name="OP_ClickObject" updated="12/12/12">
+ <opcode id="7f78" name="OP_ClickObject" updated="02/13/13">
<comment>Items dropped on the ground</comment>
<payload dir="both" typename="remDropStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0ea7" name="OP_Action" updated="12/12/12">
+ <opcode id="16a5" name="OP_Action" updated="02/13/13">
<comment>Spells cast etc</comment>
<payload dir="both" typename="actionStruct" sizechecktype="match"/>
<payload dir="both" typename="actionAltStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5428" name="OP_Action2" updated="12/12/12">
+ <opcode id="1375" name="OP_Action2" updated="02/13/13">
<comment>Combat actions i.e. bash, kick etc</comment>
<payload dir="both" typename="action2Struct" sizechecktype="match"/>
</opcode>
- <opcode id="4d8d" name="OP_Consider" updated="12/12/12">
+ <opcode id="0fcd" name="OP_Consider" updated="02/13/13">
<comment>ConsiderCode</comment>
<payload dir="both" typename="considerStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0e25" name="OP_TargetMouse" updated="12/12/12">
+ <opcode id="02f7" name="OP_TargetMouse" updated="02/13/13">
<comment>Targeting a person - old ClientTargetCode</comment>
<payload dir="both" typename="clientTargetStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5040" name="OP_SpawnRename" updated="12/12/12">
+ <opcode id="0c17" name="OP_SpawnRename" updated="02/13/13">
<comment>Spawns getting renamed after initial NewSpawn</comment>
<payload dir="server" typename="spawnRenameStruct" sizechecktype="match"/>
</opcode>
- <opcode id="6C43" name="OP_Illusion" updated="12/12/12">
+ <opcode id="359a" name="OP_Illusion" updated="02/13/13">
<comment>Spawn being illusioned (changing forms)</comment>
<payload dir="both" typename="spawnIllusionStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0747" name="OP_Shroud" updated="12/12/12">
+ <opcode id="3223" name="OP_Shroud" updated="01/16/13">
<comment>Server putting players into shroud form</comment>
<payload dir="server" typename="spawnShroudSelf" sizechecktype="none"/>
</opcode>
- <opcode id="1EB4" name="OP_ZoneChange" updated="12/12/12">
+ <opcode id="499e" name="OP_ZoneChange" updated="02/13/13">
<comment>old ZoneChangeCode</comment>
<payload dir="both" typename="zoneChangeStruct" sizechecktype="match"/>
</opcode>
- <opcode id="1602" name="OP_GroupInvite" updated="12/12/12">
+ <opcode id="7cd7" name="OP_GroupInvite" updated="02/13/13">
<payload dir="both" typename="groupInviteStruct" sizechecktype="none"/>
<comment>You invite someone while ungrouped or get invited by someone ungrouped </comment>
</opcode>
- <opcode id="6E80" name="OP_GroupInvite2" updated="12/12/12">
+ <opcode id="33e8" name="OP_GroupInvite2" updated="02/13/13">
<payload dir="client" typename="groupInviteStruct" sizechecktype="none"/>
<comment>You're inviting someone and you are grouped or get invited by a group</comment>
</opcode>
- <opcode id="2B26" name="OP_GroupCancelInvite" updated="12/12/12">
+ <opcode id="5e6d" name="OP_GroupCancelInvite" updated="02/13/13">
<payload dir="both" typename="groupDeclineStruct" sizechecktype="match"/>
<comment>Declining to join a group</comment>
</opcode>
- <opcode id="0BA4" name="OP_GroupFollow" updated="12/12/12">
+ <opcode id="2244" name="OP_GroupFollow" updated="02/13/13">
<payload dir="server" typename="groupFollowStruct" sizechecktype="match"/>
<comment>You join a group or player joins group</comment>
</opcode>
- <opcode id="5FAE" name="OP_GroupFollow2" updated="12/12/12">
+ <opcode id="5fae" name="OP_GroupFollow2" updated="12/12/12">
<payload dir="server" typename="groupFollowStruct" sizechecktype="match"/>
<comment>Player joins your group</comment>
</opcode>
- <opcode id="5A07" name="OP_GroupUpdate" updated="12/12/12">
- <comment>Group member names - Variable length</comment>
+ <opcode id="3391" name="OP_GroupUpdate" updated="02/13/13">
+ <comment>Group updates</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="623D" name="OP_GroupDisband" updated="12/12/12">
+ <opcode id="351e" name="OP_GroupDisband" updated="02/13/13">
<comment>You disband from group</comment>
<payload dir="server" typename="groupDisbandStruct" sizechecktype="match"/>
</opcode>
- <opcode id="74FA" name="OP_GroupDisband2" updated="12/12/12">
+ <opcode id="65c0" name="OP_GroupDisband2" updated="02/13/13">
<comment>Other disbands from group</comment>
<payload dir="server" typename="groupDisbandStruct" sizechecktype="match"/>
</opcode>
- <opcode id="46FC" name="OP_GroupLeader" updated="12/12/12">
+ <opcode id="626d" name="OP_GroupLeader" updated="02/13/13">
<comment>Group leader change</comment>
<payload dir="server" typename="groupLeaderChangeStruct" sizechecktype="match"/>
</opcode>
- <opcode id="08ED" name="OP_Buff" updated="12/12/12">
+ <opcode id="08ed" name="OP_Buff" updated="12/12/12">
<comment>old BuffDropCode</comment>
<payload dir="both" typename="buffStruct" sizechecktype="match"/>
</opcode>
- <opcode id="41cb" name="OP_BuffFadeMsg" updated="12/12/12">
+ <opcode id="0076" name="OP_BuffFadeMsg" updated="02/13/13">
<comment>SpellFadeCode</comment>
<payload dir="both" typename="spellFadedStruct" sizechecktype="none"/>
</opcode>
- <opcode id="17FF" name="OP_BeginCast" updated="12/12/12">
+ <opcode id="0b2b" name="OP_BeginCast" updated="02/13/13">
<comment>BeginCastCode</comment>
<payload dir="both" typename="beginCastStruct" sizechecktype="match"/>
</opcode>
- <opcode id="1cb5" name="OP_CastSpell" updated="12/12/12">
+ <opcode id="0e18" name="OP_CastSpell" updated="02/13/13">
<comment>StartCastCode</comment>
<payload dir="both" typename="startCastStruct" sizechecktype="match"/>
</opcode>
- <opcode id="4736" name="OP_SwapSpell" updated="12/12/12">
+ <opcode id="30c2" name="OP_SwapSpell" updated="01/16/13">
<comment>TradeSpellBookSlotsCode</comment>
<payload dir="both" typename="tradeSpellBookSlotsStruct" sizechecktype="match"/>
</opcode>
- <opcode id="2FAC" name="OP_MemorizeSpell" updated="12/12/12">
+ <opcode id="5dbc" name="OP_MemorizeSpell" updated="02/13/13">
<comment>MemSpellCode</comment>
<payload dir="both" typename="memSpellStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5794" name="OP_InspectAnswer" updated="12/12/12">
+ <opcode id="31e3" name="OP_InspectAnswer" updated="02/13/13">
<comment>InspectDataCode</comment>
<payload dir="both" typename="inspectDataStruct" sizechecktype="match"/>
</opcode>
- <opcode id="37FD" name="OP_Emote" updated="12/12/12">
+ <opcode id="0bff" name="OP_Emote" updated="02/13/13">
<comment>EmoteTextCode</comment>
<payload dir="both" typename="emoteTextStruct" sizechecktype="none"/>
</opcode>
- <opcode id="02A5" name="OP_SimpleMessage" updated="12/12/12">
+ <opcode id="3ecd" name="OP_SimpleMessage" updated="02/13/13">
<comment>SimpleMessageCode</comment>
<payload dir="server" typename="simpleMessageStruct" sizechecktype="match"/>
</opcode>
- <opcode id="6AFE" name="OP_FormattedMessage" updated="12/12/12">
+ <opcode id="748e" name="OP_FormattedMessage" updated="02/13/13">
<comment>FormattedMessageCode i.e. pet dismissed etc</comment>
<payload dir="server" typename="formattedMessageStruct" sizechecktype="none"/>
</opcode>
- <opcode id="33BC" name="OP_CommonMessage" updated="12/12/12">
+ <opcode id="0cf4" name="OP_CommonMessage" updated="02/13/13">
<comment>ChannelMessageCode i.e. /tell /ooc /shout etc</comment>
<payload dir="both" typename="channelMessageStruct" sizechecktype="none"/>
</opcode>
- <opcode id="362C" name="OP_SpecialMesg" updated="12/12/12">
+ <opcode id="7d12" name="OP_SpecialMesg" updated="02/13/13">
<comment>Communicate textual info to client including hail responses etc</comment>
<payload dir="server" typename="specialMessageStruct" sizechecktype="none"/>
</opcode>
- <opcode id="59DB" name="OP_RandomReq" updated="12/12/12">
+ <opcode id="4fd0" name="OP_RandomReq" updated="02/13/13">
<comment>RandomReqCode</comment>
<payload dir="client" typename="randomReqStruct" sizechecktype="match"/>
</opcode>
- <opcode id="6525" name="OP_RandomReply" updated="12/12/12">
+ <opcode id="5cc5" name="OP_RandomReply" updated="02/13/13">
<comment>RandomCode</comment>
<payload dir="server" typename="randomStruct" sizechecktype="match"/>
</opcode>
- <opcode id="183D" name="OP_ConsentResponse" updated="12/12/12">
+ <opcode id="183d" name="OP_ConsentResponse" updated="12/12/12">
<comment>Server replying with consent information after /consent</comment>
<payload dir="server" typename="consentResponseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="344A" name="OP_DenyResponse" updated="12/12/12">
+ <opcode id="344a" name="OP_DenyResponse" updated="12/12/12">
<comment>Server replying with deny information after /deny</comment>
<payload dir="server" typename="consentResponseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="1E3B" name="OP_ManaChange" updated="12/12/12">
+ <opcode id="0a79" name="OP_ManaChange" updated="02/13/13">
<comment>Mana change. Bards send this up with no size. Casters receive this for mana updates.</comment>
<payload dir="server" typename="manaDecrementStruct" sizechecktype="match"/>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
@@ -242,15 +242,15 @@
<comment>MoneyOnCorpseCode</comment>
<payload dir="server" typename="moneyOnCorpseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="52C6" name="OP_SkillUpdate" updated="12/12/12">
+ <opcode id="52c6" name="OP_SkillUpdate" updated="12/12/12">
<comment>Skill up code</comment>
<payload dir="server" typename="skillIncStruct" sizechecktype="match"/>
</opcode>
- <opcode id="7CE0" name="OP_LevelUpdate" updated="12/12/12">
+ <opcode id="7ce0" name="OP_LevelUpdate" updated="12/12/12">
<comment>LevelUpUpdateCode - causing crashes as of 12/08/12 Investigating</comment>
<payload dir="server" typename="levelUpUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5437" name="OP_CorpseLocResponse" updated="12/12/12">
+ <opcode id="0000" name="OP_CorpseLocResponse" updated="12/12/12">
<comment>old CorpseLocCode:</comment>
<payload dir="server" typename="corpseLocStruct" sizechecktype="match"/>
</opcode>
@@ -258,7 +258,7 @@
<comment></comment>
<payload dir="server" typename="none" sizechecktype="match"/>
</opcode>
- <opcode id="0e01" name="OP_DzSwitchInfo" updated="12/12/12">
+ <opcode id="331d" name="OP_DzSwitchInfo" updated="01/16/13">
<comment>Expedition compass etc</comment>
<payload dir="server" typename="dzSwitchInfo" sizechecktype="none"/>
</opcode>
@@ -268,7 +268,7 @@
</opcode>

<!-- Not necessary for SEQ to run but here to name packets in logs. -->
- <opcode id="7a19" name="OP_MovementHistory" updated="12/12/12">
+ <opcode id="15f4" name="OP_MovementHistory" updated="02/13/13">
<comment>Movement history for speed/movement hack detection</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
@@ -297,7 +297,7 @@
<payload dir="server" typename="itemInfoStruct" sizechecktype="none"/>
<payload dir="client" typename="itemInfoReqStruct" sizechecktype="none"/>
</opcode>
- <opcode id="28a9" name="OP_EnvDamage" updated="11/28/12">
+ <opcode id="0518" name="OP_EnvDamage" updated="01/16/13">
<comment>Environmental Damage</comment>
<payload dir="client" typename="environmentDamageStruct" sizechecktype="match"/>
</opcode>
@@ -305,23 +305,23 @@
<comment>old cRunToggleCode</comment>
<payload dir="client" typename="cRunToggleStruct" sizechecktype="match"/>
</opcode>
- <opcode id="71f5" name="OP_UIUpdate" updated="12/12/12">
+ <opcode id="20ee" name="OP_UIUpdate" updated="02/13/13">
<comment>Seems to be sent to handle a variety of UI updates - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="1aae" name="OP_GroupMemberList" updated="08/17/12">
+ <opcode id="20d5" name="OP_GroupMemberList" updated="02/13/13">
<comment>List of group members - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="4053" name="OP_GuildMemberList" updated="12/12/12">
+ <opcode id="210b" name="OP_GuildMemberList" updated="02/13/13">
<comment>List of guild members - Variable length</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="6675" name="OP_ManaUpdate" updated="12/12/12">
+ <opcode id="089f" name="OP_ManaUpdate" updated="01/16/13">
<comment>Mana Update opcode - 10 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="71fb" name="OP_EndUpdate" updated="12/12/12">
+ <opcode id="3a7c" name="OP_EndUpdate" updated="01/16/13">
<comment>Endurance Update opcode - 10 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -337,31 +337,31 @@
<comment>Expedition Members - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="6562" name="OP_Campfire" updated="11/28/12">
+ <opcode id="23cb" name="OP_Campfire" updated="02/13/13">
<comment>Fellowship campfire information - 1076 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="3c4b" name="OP_SelectCampfire" updated="11/28/12">
+ <opcode id="0120" name="OP_SelectCampfire" updated="02/13/13">
<comment>Fellowship campfire Choices - Guessing variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="02d7" name="OP_Claims" updated="11/28/12">
+ <opcode id="bdf1" name="OP_Claims" updated="02/13/13">
<comment>Contents of claims window. /claim then refresh to capture packet - Guessing variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="3bcc" name="OP_VoiceChat" updated="12/12/12">
+ <opcode id="50a1" name="OP_VoiceChat" updated="02/13/13">
<comment>Voice chat server info - Variable length (Data sent when joining group,raid etc)</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="6e6c" name="OP_PollQuestions" updated="12/12/12">
+ <opcode id="6e09" name="OP_PollQuestions" updated="01/16/13">
<comment>SOE in-game player poll questions - Variable length</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="17ee" name="OP_PollResponses" updated="12/12/12">
+ <opcode id="7ad7" name="OP_PollResponses" updated="01/16/13">
<comment>Poll response choices - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="7251" name="OP_ShroudProgression" updated="12/12/12">
+ <opcode id="25a2" name="OP_ShroudProgression" updated="01/16/13">
<comment>Unlocked shrouds - 244 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -369,15 +369,15 @@
<comment>Shroud templates to choose from on shroud NPC - 18983 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="40fd" name="OP_Fellowship" updated="12/12/12">
+ <opcode id="5029" name="OP_Fellowship" updated="02/13/13">
<comment>Fellowship information - 2564 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="7851" name="OP_ExpandedGuildInfo" updated="12/12/12">
+ <opcode id="6f0c" name="OP_ExpandedGuildInfo" updated="02/13/13">
<comment>Guild ranks and other misc guild data - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="1cbf" name="OP_GuildBank" updated="12/12/12">
+ <opcode id="34d3" name="OP_GuildBank" updated="01/16/13">
<comment>Guild bank contents - Guessing variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -401,23 +401,23 @@
<comment>Tradeskill combine using old tradeskill window - 24 Bytes</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="786e" name="OP_ItemPlayerPacket" updated="12/12/12">
+ <opcode id="4cd2" name="OP_ItemPlayerPacket" updated="02/13/13">
<comment>Inventory/bank items coming over during zone - Variable length</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="2294" name="OP_TaskDescription" updated="12/12/12">
+ <opcode id="0736" name="OP_TaskDescription" updated="02/13/13">
<comment>Task descriptions coming down for task window - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="7181" name="OP_TaskActivity" updated="12/12/12">
+ <opcode id="74a1" name="OP_TaskActivity" updated="02/13/13">
<comment>Task activity descriptions coming down for task window - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="9495" name="OP_CompletedTasks" updated="12/12/12">
+ <opcode id="7392" name="OP_CompletedTasks" updated="02/13/13">
<comment>Task history for task window - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="471a" name="OP_CustomTitles" updated="12/12/12">
+ <opcode id="475f" name="OP_CustomTitles" updated="02/13/13">
<comment>List of available titles - 1520 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -533,7 +533,7 @@
<comment>Client side raid invite requests 140 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="5dcf" name="OP_RaidJoin" updated="11/28/12">
+ <opcode id="3ab1" name="OP_RaidJoin" updated="01/16/13">
<comment>Server side raid information - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -553,7 +553,7 @@
<comment>LFG/LFP server response - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="5a7c" name="OP_MercenaryList" updated="12/12/12">
+ <opcode id="27a5" name="OP_MercenaryList" updated="01/16/13">
<comment>Listing of hired mercenaries - 429 bytes
<payload dir="server" typename="unknown" sizechecktype="none"/></comment>
</opcode>
@@ -573,11 +573,11 @@
<comment>Client clicks off buff - 8 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="6786" name="OP_HouseAddress" updated="12/12/12">
+ <opcode id="3bf6" name="OP_HouseAddress" updated="01/16/13">
<comment>House and guildhall address information - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="7cda" name="OP_HouseContents" updated="11/28/12">
+ <opcode id="222f" name="OP_HouseContents" updated="01/16/13">
<comment>Server sending house information and contents - variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -593,11 +593,11 @@
<comment>Server sending pending rewards - variable length</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="63ae" name="OP_FTPNags" updated="12/12/12">
+ <opcode id="168d" name="OP_FTPNags" updated="02/13/13">
<comment>Free to play nags and other data - 1852 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="34c3" name="OP_Find" updated="12/12/12">
+ <opcode id="7b8a" name="OP_Find" updated="02/13/13">
<comment>Find window data - 112 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
@@ -612,15 +612,15 @@

<!-- Below are used to help make sense of the logs when searching for opcodes
Using these marks unknown opcodes in logs for easier reading -->
- <opcode id="218d" name="OP_Unknown1" updated="12/12/12">
+ <opcode id="05c3" name="OP_Unknown1" updated="01/16/13">
<comment>3 byte opcode that spam logs seemingly only when you have someone targeted. Marked here to make reading logs easier</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="48b5" name="OP_Unknown2" updated="12/12/12">
+ <opcode id="7d71" name="OP_Unknown2" updated="01/16/13">
<comment>3 byte opcode that spam logs seemingly only when you have someone targeted. Marked here to make reading logs easier</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
- <opcode id="7cb5" name="OP_Unknown3" updated="12/12/12">
+ <opcode id="68a5" name="OP_Unknown3" updated="01/16/13">
<comment>3 byte opcode that spam logs seemingly only when you have someone targeted. Marked here to make reading logs easier</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>

ShortBuss
02-17-2013, 08:19 AM
This change will fix the Gender shown on players in the mouse over tool tip on the map. I realize it's minor; still just trying to learn the code. Most, if not all, of the rest of the miscdata flags are wrong as well. I've confirmed some but I think only gender is used so I only modified it.



Index: src/everquest.h
================================================== =================
--- src/everquest.h (revision 783)
+++ src/everquest.h (working copy)
@@ -1034,7 +1034,7 @@
{
struct
{
- unsigned padding7:1;
+ unsigned gender:1; // Gender (0=male, 1=female)
unsigned AFK:1;
unsigned sneak:1;
unsigned LFG:1;
@@ -1044,7 +1044,7 @@
unsigned gm:1;
unsigned anon:1; // 0=normal, 1=anon, 2=roleplay
unsigned padding4:1;
- unsigned gender:1; // Gender (0=male, 1=female)
+ unsigned padding7:1;
unsigned padding3:1;
unsigned linkdead:1;
unsigned betabuffed:1;

Reliant
02-18-2013, 02:18 PM
We've done a lot of one-up changes to everquest.h and zonecodes.xml. I'm thinking it might be best if we posted the full versions, so people don't try applying patches to the wrong files.

Sky_Genie
02-26-2013, 08:29 AM
Is there any chance that someone might post working everquest.h and zoneopcodes.xml for me please? I seem to have borked something and get all kinds of errors when I patch using the diff files.

Thanks

ShortBuss
02-26-2013, 11:42 AM
There are 5 files that have changed since the latest SVN. You will need to update all 5. Here are the full versions that I have:

1. zoneopcodes.xml:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE seqopcodes SYSTEM "seqopcodes.dtd">
<seqopcodes>

<!-- Critical opcodes used directly by ShowEQ -->
<opcode id="6725" name="OP_PlayerProfile" updated="02/13/13">
<comment>CharProfileCode</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="2cbe" name="OP_ZoneEntry" updated="02/13/13">
<comment>ZoneEntryCode</comment>
<payload dir="client" typename="ClientZoneEntryStruct" sizechecktype="match"/>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="2d98" name="OP_TimeOfDay" updated="02/13/13">
<comment>TimeOfDayCode</comment>
<payload dir="server" typename="timeOfDayStruct" sizechecktype="match"/>
</opcode>
<opcode id="082d" name="OP_NewZone" updated="02/13/13">
<comment>NewZoneCode</comment>
<payload dir="server" typename="newZoneStruct" sizechecktype="match"/>
</opcode>
<opcode id="0e70" name="OP_SpawnDoor" updated="02/13/13">
<comment>DoorSpawnsCode</comment>
<payload dir="server" typename="doorStruct" sizechecktype="modulus"/>
</opcode>
<opcode id="11ef" name="OP_GroundSpawn" updated="02/13/13">
<comment>MakeDropCode</comment>
<payload dir="server" typename="makeDropStruct" sizechecktype="none"/>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="0a1d" name="OP_SendZonePoints" updated="02/13/13">
<comment>Coords in a zone that will port you to another zone</comment>
<payload dir="server" typename="zonePointsStruct" sizechecktype="none"/>
</opcode>
<opcode id="0eae" name="OP_AAExpUpdate" updated="02/13/13">
<comment>Receiving AA experience. Also when percent to AA changes.</comment>
<payload dir="server" typename="altExpUpdateStruct" sizechecktype="match"/>
</opcode>
<opcode id="7814" name="OP_ExpUpdate" updated="02/13/13">
<comment>ExpUpdateCode</comment>
<payload dir="server" typename="expUpdateStruct" sizechecktype="match"/>
</opcode>
<opcode id="7864" name="OP_GuildMOTD" updated="02/13/13">
<comment>GuildMOTD</comment>
<payload dir="server" typename="guildMOTDStruct" sizechecktype="none"/>
</opcode>
<opcode id="6cc2" name="OP_ClientUpdate" updated="02/13/13">
<comment>Position updates</comment>
<payload dir="server" typename="playerSpawnPosStruct" sizechecktype="match"/>
<payload dir="both" typename="playerSelfPosStruct" sizechecktype="match"/>
</opcode>
<opcode id="7342" name="OP_NpcMoveUpdate" updated="02/13/13">
<comment>Position updates</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="282a" name="OP_MobUpdate" updated="02/13/13">
<comment>MobUpdateCode</comment>
<payload dir="both" typename="spawnPositionUpdate" sizechecktype="match"/>
</opcode>
<opcode id="6864" name="OP_DeleteSpawn" updated="02/13/13">
<comment>DeleteSpawnCode</comment>
<payload dir="both" typename="deleteSpawnStruct" sizechecktype="match"/>
</opcode>
<opcode id="0ead" name="OP_RemoveSpawn" updated="02/13/13">
<comment>Remove spawn from zone</comment>
<payload dir="both" typename="removeSpawnStruct" sizechecktype="none"/>
</opcode>
<opcode id="62bd" name="OP_Death" updated="02/13/13">
<comment>old NewCorpseCode</comment>
<payload dir="server" typename="newCorpseStruct" sizechecktype="match"/>
</opcode>
<opcode id="6a1a" name="OP_WearChange" updated="02/13/13">
<comment>SpawnUpdateCode</comment>
<payload dir="both" typename="SpawnUpdateStruct" sizechecktype="match"/>
</opcode>
<opcode id="6087" name="OP_SpawnAppearance" updated="02/13/13">
<comment>SpawnAppearanceCode</comment>
<payload dir="both" typename="spawnAppearanceStruct" sizechecktype="match"/>
</opcode>
<opcode id="54fb" name="OP_Stamina" updated="02/13/13">
<comment>Server updating on hunger/thirst</comment>
<payload dir="server" typename="staminaStruct" sizechecktype="match"/>
</opcode>
<opcode id="0396" name="OP_HPUpdate" updated="02/13/13">
<comment>NpcHpUpdateCode Update HP % of a PC or NPC</comment>
<payload dir="both" typename="hpNpcUpdateStruct" sizechecktype="match"/>
</opcode>
<opcode id="6719" name="OP_GuildMemberUpdate" updated="02/13/13">
<comment>Info regarding guild members</comment>
<payload dir="server" typename="GuildMemberUpdate" sizechecktype="match"/>
</opcode>
<opcode id="7f78" name="OP_ClickObject" updated="02/13/13">
<comment>Items dropped on the ground</comment>
<payload dir="both" typename="remDropStruct" sizechecktype="match"/>
</opcode>
<opcode id="16a5" name="OP_Action" updated="02/13/13">
<comment>Spells cast etc</comment>
<payload dir="both" typename="actionStruct" sizechecktype="match"/>
<payload dir="both" typename="actionAltStruct" sizechecktype="match"/>
</opcode>
<opcode id="1375" name="OP_Action2" updated="02/13/13">
<comment>Combat actions i.e. bash, kick etc</comment>
<payload dir="both" typename="action2Struct" sizechecktype="match"/>
</opcode>
<opcode id="0fcd" name="OP_Consider" updated="02/13/13">
<comment>ConsiderCode</comment>
<payload dir="both" typename="considerStruct" sizechecktype="match"/>
</opcode>
<opcode id="02f7" name="OP_TargetMouse" updated="02/13/13">
<comment>Targeting a person - old ClientTargetCode</comment>
<payload dir="both" typename="clientTargetStruct" sizechecktype="match"/>
</opcode>
<opcode id="0c17" name="OP_SpawnRename" updated="02/13/13">
<comment>Spawns getting renamed after initial NewSpawn</comment>
<payload dir="server" typename="spawnRenameStruct" sizechecktype="match"/>
</opcode>
<opcode id="359a" name="OP_Illusion" updated="02/13/13">
<comment>Spawn being illusioned (changing forms)</comment>
<payload dir="both" typename="spawnIllusionStruct" sizechecktype="match"/>
</opcode>
<opcode id="3223" name="OP_Shroud" updated="01/16/13">
<comment>Server putting players into shroud form</comment>
<payload dir="server" typename="spawnShroudSelf" sizechecktype="none"/>
</opcode>
<opcode id="499e" name="OP_ZoneChange" updated="02/13/13">
<comment>old ZoneChangeCode</comment>
<payload dir="both" typename="zoneChangeStruct" sizechecktype="match"/>
</opcode>
<opcode id="7cd7" name="OP_GroupInvite" updated="02/13/13">
<payload dir="both" typename="groupInviteStruct" sizechecktype="none"/>
<comment>You invite someone while ungrouped or get invited by someone ungrouped </comment>
</opcode>
<opcode id="33e8" name="OP_GroupInvite2" updated="02/13/13">
<payload dir="client" typename="groupInviteStruct" sizechecktype="none"/>
<comment>You're inviting someone and you are grouped or get invited by a group</comment>
</opcode>
<opcode id="5e6d" name="OP_GroupCancelInvite" updated="02/13/13">
<payload dir="both" typename="groupDeclineStruct" sizechecktype="match"/>
<comment>Declining to join a group</comment>
</opcode>
<opcode id="2244" name="OP_GroupFollow" updated="02/13/13">
<payload dir="server" typename="groupFollowStruct" sizechecktype="match"/>
<comment>You join a group or player joins group</comment>
</opcode>
<opcode id="5fae" name="OP_GroupFollow2" updated="12/12/12">
<payload dir="server" typename="groupFollowStruct" sizechecktype="match"/>
<comment>Player joins your group</comment>
</opcode>
<opcode id="3391" name="OP_GroupUpdate" updated="02/13/13">
<comment>Group updates</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="351e" name="OP_GroupDisband" updated="02/13/13">
<comment>You disband from group</comment>
<payload dir="server" typename="groupDisbandStruct" sizechecktype="match"/>
</opcode>
<opcode id="65c0" name="OP_GroupDisband2" updated="02/13/13">
<comment>Other disbands from group</comment>
<payload dir="server" typename="groupDisbandStruct" sizechecktype="match"/>
</opcode>
<opcode id="626d" name="OP_GroupLeader" updated="02/13/13">
<comment>Group leader change</comment>
<payload dir="server" typename="groupLeaderChangeStruct" sizechecktype="match"/>
</opcode>
<opcode id="08ed" name="OP_Buff" updated="12/12/12">
<comment>old BuffDropCode</comment>
<payload dir="both" typename="buffStruct" sizechecktype="match"/>
</opcode>
<opcode id="0076" name="OP_BuffFadeMsg" updated="02/13/13">
<comment>SpellFadeCode</comment>
<payload dir="both" typename="spellFadedStruct" sizechecktype="none"/>
</opcode>
<opcode id="0b2b" name="OP_BeginCast" updated="02/13/13">
<comment>BeginCastCode</comment>
<payload dir="both" typename="beginCastStruct" sizechecktype="match"/>
</opcode>
<opcode id="0e18" name="OP_CastSpell" updated="02/13/13">
<comment>StartCastCode</comment>
<payload dir="both" typename="startCastStruct" sizechecktype="match"/>
</opcode>
<opcode id="30c2" name="OP_SwapSpell" updated="01/16/13">
<comment>TradeSpellBookSlotsCode</comment>
<payload dir="both" typename="tradeSpellBookSlotsStruct" sizechecktype="match"/>
</opcode>
<opcode id="5dbc" name="OP_MemorizeSpell" updated="02/13/13">
<comment>MemSpellCode</comment>
<payload dir="both" typename="memSpellStruct" sizechecktype="match"/>
</opcode>
<opcode id="31e3" name="OP_InspectAnswer" updated="02/13/13">
<comment>InspectDataCode</comment>
<payload dir="both" typename="inspectDataStruct" sizechecktype="match"/>
</opcode>
<opcode id="0bff" name="OP_Emote" updated="02/13/13">
<comment>EmoteTextCode</comment>
<payload dir="both" typename="emoteTextStruct" sizechecktype="none"/>
</opcode>
<opcode id="3ecd" name="OP_SimpleMessage" updated="02/13/13">
<comment>SimpleMessageCode</comment>
<payload dir="server" typename="simpleMessageStruct" sizechecktype="match"/>
</opcode>
<opcode id="748e" name="OP_FormattedMessage" updated="02/13/13">
<comment>FormattedMessageCode i.e. pet dismissed etc</comment>
<payload dir="server" typename="formattedMessageStruct" sizechecktype="none"/>
</opcode>
<opcode id="0cf4" name="OP_CommonMessage" updated="02/13/13">
<comment>ChannelMessageCode i.e. /tell /ooc /shout etc</comment>
<payload dir="both" typename="channelMessageStruct" sizechecktype="none"/>
</opcode>
<opcode id="7d12" name="OP_SpecialMesg" updated="02/13/13">
<comment>Communicate textual info to client including hail responses etc</comment>
<payload dir="server" typename="specialMessageStruct" sizechecktype="none"/>
</opcode>
<opcode id="4fd0" name="OP_RandomReq" updated="02/13/13">
<comment>RandomReqCode</comment>
<payload dir="client" typename="randomReqStruct" sizechecktype="match"/>
</opcode>
<opcode id="5cc5" name="OP_RandomReply" updated="02/13/13">
<comment>RandomCode</comment>
<payload dir="server" typename="randomStruct" sizechecktype="match"/>
</opcode>
<opcode id="183d" name="OP_ConsentResponse" updated="12/12/12">
<comment>Server replying with consent information after /consent</comment>
<payload dir="server" typename="consentResponseStruct" sizechecktype="match"/>
</opcode>
<opcode id="344a" name="OP_DenyResponse" updated="12/12/12">
<comment>Server replying with deny information after /deny</comment>
<payload dir="server" typename="consentResponseStruct" sizechecktype="match"/>
</opcode>
<opcode id="0a79" name="OP_ManaChange" updated="02/13/13">
<comment>Mana change. Bards send this up with no size. Casters receive this for mana updates.</comment>
<payload dir="server" typename="manaDecrementStruct" sizechecktype="match"/>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="3206" name="OP_BazaarSearch" updated="12/12/12">
<payload dir="client" typename="bazaarSearchQueryStruct" sizechecktype="none"/>
<payload dir="server" typename="bazaarSearchResponseStruct" sizechecktype="modulus"/>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
<comment>Bazaar search tool - struct changed and separated query from response with RoF launch. Needs work </comment>
</opcode>
<opcode id="1837" name="OP_MoneyOnCorpse" updated="12/12/12">
<comment>MoneyOnCorpseCode</comment>
<payload dir="server" typename="moneyOnCorpseStruct" sizechecktype="match"/>
</opcode>
<opcode id="52c6" name="OP_SkillUpdate" updated="12/12/12">
<comment>Skill up code</comment>
<payload dir="server" typename="skillIncStruct" sizechecktype="match"/>
</opcode>
<opcode id="7ce0" name="OP_LevelUpdate" updated="12/12/12">
<comment>LevelUpUpdateCode - causing crashes as of 12/08/12 Investigating</comment>
<payload dir="server" typename="levelUpUpdateStruct" sizechecktype="match"/>
</opcode>
<opcode id="0000" name="OP_CorpseLocResponse" updated="12/12/12">
<comment>old CorpseLocCode:</comment>
<payload dir="server" typename="corpseLocStruct" sizechecktype="match"/>
</opcode>
<opcode id="68df" name="OP_Logout" updated="12/12/12">
<comment></comment>
<payload dir="server" typename="none" sizechecktype="match"/>
</opcode>
<opcode id="331d" name="OP_DzSwitchInfo" updated="01/16/13">
<comment>Expedition compass etc</comment>
<payload dir="server" typename="dzSwitchInfo" sizechecktype="none"/>
</opcode>
<opcode id="3861" name="OP_DzInfo" updated="12/12/12">
<comment>Expedition Information</comment>
<payload dir="server" typename="dzInfo" sizechecktype="match"/>
</opcode>

<!-- Not necessary for SEQ to run but here to name packets in logs. -->
<opcode id="15f4" name="OP_MovementHistory" updated="02/13/13">
<comment>Movement history for speed/movement hack detection</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="3798" name="OP_LeaderExpUpdate" updated="11/28/12">
<comment>Leadership AA Exp Update</comment>
<payload dir="server" typename="leadExpUpdateStruct" sizechecktype="match"/>
</opcode>
<opcode id="5c45" name="OP_Trader" updated="11/28/12">
<comment>PC's turning trader on and off</comment>
<payload dir="server" typename="bazaarTraderRequest" sizechecktype="match"/>
</opcode>
<opcode id="071e" name="OP_Consent" updated="11/28/12">
<comment>/consent someone</comment>
<payload dir="client" typename="consentRequestStruct" sizechecktype="none"/>
</opcode>
<opcode id="2860" name="OP_ConsentDeny" updated="11/28/12">
<comment>/deny someone</comment>
<payload dir="client" typename="consentRequestStruct" sizechecktype="none"/>
</opcode>
<opcode id="1d6d" name="OP_ItemPacket" updated="11/28/12">
<comment>ItemCode</comment>
<payload dir="server" typename="itemPacketStruct" sizechecktype="none"/>
</opcode>
<opcode id="361c" name="OP_ItemLinkResponse" updated="11/28/12">
<comment>ItemInfoCode</comment>
<payload dir="server" typename="itemInfoStruct" sizechecktype="none"/>
<payload dir="client" typename="itemInfoReqStruct" sizechecktype="none"/>
</opcode>
<opcode id="0518" name="OP_EnvDamage" updated="01/16/13">
<comment>Environmental Damage</comment>
<payload dir="client" typename="environmentDamageStruct" sizechecktype="match"/>
</opcode>
<opcode id="402d" name="OP_SetRunMode" updated="11/28/12">
<comment>old cRunToggleCode</comment>
<payload dir="client" typename="cRunToggleStruct" sizechecktype="match"/>
</opcode>
<opcode id="20ee" name="OP_UIUpdate" updated="02/13/13">
<comment>Seems to be sent to handle a variety of UI updates - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="20d5" name="OP_GroupMemberList" updated="02/13/13">
<comment>List of group members - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="210b" name="OP_GuildMemberList" updated="02/13/13">
<comment>List of guild members - Variable length</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="089f" name="OP_ManaUpdate" updated="01/16/13">
<comment>Mana Update opcode - 10 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3a7c" name="OP_EndUpdate" updated="01/16/13">
<comment>Endurance Update opcode - 10 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3929" name="OP_Marketplace" updated="11/28/12">
<comment>Marketplace data - Guessing variable length 11444 bytes as of 11/28/12</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="2de6" name="OP_MarketplaceSelect" updated="11/28/12">
<comment>Sent when highlighting an item in Marketplace - 80 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="4e34" name="OP_DzMembers" updated="11/28/12">
<comment>Expedition Members - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="23cb" name="OP_Campfire" updated="02/13/13">
<comment>Fellowship campfire information - 1076 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0120" name="OP_SelectCampfire" updated="02/13/13">
<comment>Fellowship campfire Choices - Guessing variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="bdf1" name="OP_Claims" updated="02/13/13">
<comment>Contents of claims window. /claim then refresh to capture packet - Guessing variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="50a1" name="OP_VoiceChat" updated="02/13/13">
<comment>Voice chat server info - Variable length (Data sent when joining group,raid etc)</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="6e09" name="OP_PollQuestions" updated="01/16/13">
<comment>SOE in-game player poll questions - Variable length</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="7ad7" name="OP_PollResponses" updated="01/16/13">
<comment>Poll response choices - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="25a2" name="OP_ShroudProgression" updated="01/16/13">
<comment>Unlocked shrouds - 244 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="ba18" name="OP_ShroudTemplates" updated="10/23/12">
<comment>Shroud templates to choose from on shroud NPC - 18983 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="5029" name="OP_Fellowship" updated="02/13/13">
<comment>Fellowship information - 2564 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="6f0c" name="OP_ExpandedGuildInfo" updated="02/13/13">
<comment>Guild ranks and other misc guild data - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="34d3" name="OP_GuildBank" updated="01/16/13">
<comment>Guild bank contents - Guessing variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="2db9" name="OP_OpenTradeskillContainer" updated="11/28/12">
<comment>Opens forge, kiln etc - 92 Bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="18c4" name="OP_TradeskillRecipes" updated="11/28/12">
<comment>Learned recipes - 84 Bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0397" name="OP_TradeSkillCombine" updated="11/28/12">
<comment>Tradeskill combine using new tradeskill window - 40 Bytes</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="360d" name="OP_TradeSkillResult" updated="11/28/12">
<comment>Packets sent when tradeskill combine successful equals # of ingredients used in combine?- 12 Bytes</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="0b69" name="OP_TradeSkillCombineOld" updated="11/28/12">
<comment>Tradeskill combine using old tradeskill window - 24 Bytes</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="4cd2" name="OP_ItemPlayerPacket" updated="02/13/13">
<comment>Inventory/bank items coming over during zone - Variable length</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="0736" name="OP_TaskDescription" updated="02/13/13">
<comment>Task descriptions coming down for task window - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="74a1" name="OP_TaskActivity" updated="02/13/13">
<comment>Task activity descriptions coming down for task window - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="7392" name="OP_CompletedTasks" updated="02/13/13">
<comment>Task history for task window - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="475f" name="OP_CustomTitles" updated="02/13/13">
<comment>List of available titles - 1520 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3df3" name="OP_Animation" updated="11/28/12">
<comment>Combat animation, emote animations etc - 4 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="2bdd" name="OP_WhoAllRequest" updated="11/28/12">
<comment>WhoAllReqCode - 156 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="51a4" name="OP_WhoAllResponse" updated="11/28/12">
<comment>WhoAllOutputCode - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3d3c" name="OP_InspectRequest" updated="11/28/12">
<comment>InspectRequestCode - 8 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="40ca" name="OP_GetGuildMOTD" updated="11/28/12">
<comment>Request guildMOTD - 648 Bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="1861" name="OP_GuildMOTDResponse" updated="11/28/12">
<comment>Response guildMOTD - 648 Bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="38e9" name="OP_TradeRequest" updated="11/28/12">
<comment>You request trade session - 8 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0ccc" name="OP_TradeDeny" updated="11/28/12">
<comment>Target not ready to trade - 12 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="1439" name="OP_TradeRequestAck" updated="11/28/12">
<comment>Trade request recipient is acknowledging they are able to trade - 8 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="66f3" name="OP_CancelTrade" updated="11/28/12">
<comment>Cancel a trade window - 8 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0dd6" name="OP_FinishTrade" updated="11/28/12">
<comment>Trade is over - 12 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="2320" name="OP_TradeCoins" updated="11/28/12">
<comment>You put coins put in a trade window - 20 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="428e" name="OP_TradeCoins2" updated="11/28/12">
<comment>Someone else puts coins put in your trade window - 12 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="4cf9" name="OP_TradeAcceptClick" updated="11/28/12">
<comment>One side clicks Accept on the trade 8 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="6f69" name="OP_ItemLinkClick" updated="11/28/12">
<comment>Click on itemlinks - 52 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="6635" name="OP_LootRequest" updated="11/28/12">
<comment>LootCorpseCode - 4 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0233" name="OP_LootItem" updated="11/28/12">
<comment>Loot item from corpse - 20 bytes</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="11bc" name="OP_EndLootRequest" updated="11/28/12">
<comment>DoneLootingCode - 4 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3c94" name="OP_Track" updated="11/28/12">
<comment>Tracking data - Variable length</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="5401" name="OP_AutoAttack" updated="11/28/12">
<comment>Attack on/off - 4 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3fad" name="OP_AutoAttack2" updated="11/28/12">
<comment>Attack on/off appears to be same as OP_AutoAttack - 4 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="7488" name="OP_ClickDoor" updated="11/28/12">
<comment>DoorOpenCode click request from client - 16 bytes</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="38ab" name="OP_MoveDoor" updated="11/28/12">
<comment>DoorClickCode response from server - 2 bytes</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="29fa" name="OP_MoveItem" updated="11/28/12">
<comment>Client moving an item from one slot to another - 28 bytes</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="5751" name="OP_Jump" updated="11/28/12">
<comment>JumpCode - 0 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="339c" name="OP_TGB" updated="11/28/12">
<comment>Client telling server to set targetgroupbuff - 4 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="1d6a" name="OP_Lockouts" updated="11/28/12">
<comment>Client requesting lockouts - 0 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="4ee5" name="OP_RaidInvite" updated="11/28/12">
<comment>Client side raid invite requests 140 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3ab1" name="OP_RaidJoin" updated="01/16/13">
<comment>Server side raid information - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="24c5" name="OP_Feedback" updated="07/18/12">
<comment>Client sending feedback to server - 1148 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="34f7" name="OP_GuildsList" updated="11/28/12">
<comment>Listing of all guilds. Can be triggered by /lfg search?</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="284e" name="OP_LFGGetMatchesRequest" updated="11/28/12">
<comment>LFG/LFP client request - 16 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="11c8" name="OP_LFGGetMatchesResponse" updated="11/28/12">
<comment>LFG/LFP server response - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="27a5" name="OP_MercenaryList" updated="01/16/13">
<comment>Listing of hired mercenaries - 429 bytes
<payload dir="server" typename="unknown" sizechecktype="none"/></comment>
</opcode>
<opcode id="6e0e" name="OP_ClickInventory" updated="11/28/12">
<comment>Click items from inventory or armor - 16 bytes 5th byte is Slot ID</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3459" name="OP_ClickInventoryAck" updated="11/28/12">
<comment>Server acknowledges click from inventory or armor - 20 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="60e2" name="OP_BuffWindow" updated="11/28/12">
<comment>Changes to buff window or song window - 100 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="40d5" name="OP_ClickBuffOff" updated="11/28/12">
<comment>Client clicks off buff - 8 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="3bf6" name="OP_HouseAddress" updated="01/16/13">
<comment>House and guildhall address information - Variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="222f" name="OP_HouseContents" updated="01/16/13">
<comment>Server sending house information and contents - variable length</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="54df" name="OP_FriendsList" updated="11/28/12">
<comment>Server sending friends list contents - variable length (Sent when choosing "Welcome" from EQ button)</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="5a4f" name="OP_FriendsOnline" updated="11/28/12">
<comment>Friends currently online - variable length (Sent when choosing "Welcome" form EQ button)</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="348e" name="OP_Rewards" updated="11/28/12">
<comment>Server sending pending rewards - variable length</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="168d" name="OP_FTPNags" updated="02/13/13">
<comment>Free to play nags and other data - 1852 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="7b8a" name="OP_Find" updated="02/13/13">
<comment>Find window data - 112 bytes</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="10cb" name="OP_ConsiderCorpse" updated="11/28/12">
<comment>ConCorpseCode - 20 bytes</comment>
<payload dir="client" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0000" name="OP_TributeUpdate" updated="11/28/12">
<comment>Tribute and trophy skills - Variable length</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>

<!-- Below are used to help make sense of the logs when searching for opcodes
Using these marks unknown opcodes in logs for easier reading -->
<opcode id="05c3" name="OP_Unknown1" updated="01/16/13">
<comment>3 byte opcode that spam logs seemingly only when you have someone targeted. Marked here to make reading logs easier</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="7d71" name="OP_Unknown2" updated="01/16/13">
<comment>3 byte opcode that spam logs seemingly only when you have someone targeted. Marked here to make reading logs easier</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="68a5" name="OP_Unknown3" updated="01/16/13">
<comment>3 byte opcode that spam logs seemingly only when you have someone targeted. Marked here to make reading logs easier</comment>
<payload dir="server" typename="unknown" sizechecktype="none"/>
</opcode>

<!-- Below are unverified -->



<opcode id="0000" name="OP_RequestZoneChange" updated="10/20/07">
<comment>Send by server when a click causes zone. Also, origin</comment>
<payload dir="server" typename="requestZoneChangeStruct" sizechecktype="match"/>
</opcode>
<opcode id="0000" name="OP_WelcomeScreenTitle" updated="05/16/11">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_VeteranRewards" update="04/18/11">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_SendAATable" updated="08/12/09">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_SendAAStats" updated="08/12/09">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_AckPacket" updated="03/14/07">
<comment>Appears to be generic ack at the presentation level</comment>
</opcode>
<opcode id="0000" name="OP_Weather" updated="03/14/07">
<comment>old WeatherCode</comment>
</opcode>
<opcode id="0000" name="OP_ReqNewZone" updated="03/14/07">
<comment>Client requesting NewZone_Struct</comment>
</opcode>
<opcode id="0000" name="OP_ReqClientSpawn" updated="03/14/07">
<comment>Client requesting spawn data</comment>
</opcode>
<opcode id="0000" name="OP_SendExpZonein" updated="03/14/07">
<comment>Both directions. Negotiating sending of exp info.</comment>
</opcode>
<opcode id="0000" name="OP_AAAction" updated="03/14/07">
<comment>Used for changing percent, buying? and activating skills</comment>
</opcode>
<opcode id="0000" name="OP_SetServerFilter" updated="03/14/07">
<comment>Client telling server /filter information</comment>
</opcode>
<opcode id="0000" name="OP_ClientReady" updated="03/14/07">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_GuildTributeStatus" updated="03/14/07">
<comment>Guild tribute stats send on zone</comment>
</opcode>
<opcode id="0000" name="OP_GuildTributeInfo" updated="06/13/06">
<comment>Guild tribute loadout, only if on</comment>
</opcode>
<opcode id="0000" name="OP_RespawnWindow" updated="03/14/07">
<comment>Server telling client enough to populate the respawn window when you die</comment>
</opcode>
<opcode id="0000" name="OP_InitialMobHealth" updated="06/27/12">
<comment>Initial health sent when a player clicks on the mob. Subsequent updated will be OP_MobHealth</comment>
</opcode>
<opcode id="0000" name="OP_MobHealth" updated="03/14/07">
<comment>health sent when a player clicks on the mob</comment>
</opcode>
<opcode id="0000" name="OP_DeltaCheck" updated="03/14/07">
<comment>Client sending server delta information.</comment>
</opcode>
<opcode id="0000" name="OP_LoadSpellSet" updated="02/13/07">
<comment>/mem spellsetname</comment>
</opcode>
<opcode id="0000" name="OP_Dye" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_Consume" updated="12/07/05">
<comment>Client force feeding food/drink</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="0000" name="OP_Begging" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_LFGCommand" updated="10/27/05">
<comment>old LFGReqCode</comment>
</opcode>
<opcode id="0000" name="OP_Bug" updated="10/27/05">
<comment>/bug</comment>
</opcode>
<opcode id="0000" name="OP_Save" updated="04/19/06">
<comment>Client asking server to save user state</comment>
</opcode>
<opcode id="0000" name="OP_Camp" updated="02/13/07">
<comment>old cStartCampingCode</comment>
</opcode>
<opcode id="0000" name="OP_ShopPlayerSell" updated="10/27/05">
<comment>old SellItemCode</comment>
</opcode>
<opcode id="0000" name="OP_PetCommands" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_SaveOnZoneReq" updated="03/14/07">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_ShopEnd" updated="10/27/05">
<comment>old CloseVendorCode</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0000" name="OP_SenseTraps" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_SenseHeading" updated="10/27/05">
<comment>old cSenseHeadingCode</comment>
</opcode>
<opcode id="0000" name="OP_LootComplete" updated="12/07/05">
<comment>old sDoneLootingCode</comment>
</opcode>
<opcode id="0000" name="OP_Split" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_Surname" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_ShopRequest" updated="10/27/05">
<comment>old OpenVendorCode</comment>
<payload dir="both" typename="unknown" sizechecktype="none"/>
</opcode>
<opcode id="0000" name="OP_FaceChange" updated="10/27/05">
<comment>/face</comment>
</opcode>
<opcode id="0000" name="OP_Sneak" updated="06/29/05">
<comment>Clicked sneak</comment>
</opcode>
<opcode id="0000" name="OP_Hide" updated="06/29/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_DisarmTraps" updated="05/11/05">
<comment>Clicked disarm traps</comment>
</opcode>
<opcode id="0000" name="OP_Forage" updated="10/27/05">
<comment>old ForageCode</comment>
</opcode>
<opcode id="0000" name="OP_BoardBoat" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_LeaveBoat" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_LFPGetMatchesRequest" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_GMKill" updated="10/27/05">
<comment>GM /kill - Insta kill mob/pc</comment>
</opcode>
<opcode id="0000" name="OP_GuildPublicNote" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_YellForHelp" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_ShopPlayerBuy" updated="05/11/05">
<comment>old BuyItemCode</comment>
</opcode>
<opcode id="0000" name="OP_LFPCommand" updated="10/27/05">
<comment>looking for players</comment>
</opcode>
<opcode id="0000" name="OP_ConfirmDelete" updated="10/27/05">
<comment>Client sends this to server to confirm op_deletespawn</comment>
</opcode>
<opcode id="0000" name="OP_Report" updated="06/29/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_TargetCommand" updated="02/13/07">
<comment>Target user</comment>
</opcode>
<opcode id="0000" name="OP_LFPGetMatchesResponse" updated="02/13/07">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_FindPersonRequest" updated="02/13/07">
<comment>Control-F Find</comment>
</opcode>
<opcode id="0000" name="OP_FindResponse" updated="02/13/07">
<comment>Response to control-F</comment>
</opcode>
<opcode id="0000" name="OP_GMLastName" updated="10/27/05">
<comment>GM /lastname - Change user lastname</comment>
</opcode>
<opcode id="0000" name="OP_Mend" updated="10/27/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_MendHPUpdate" updated="05/11/05">
<comment></comment>
</opcode>
<opcode id="0000" name="OP_TributeInfo" updated="02/13/07">
<comment>Tribute information</comment>
</opcode>

<!-- OLD OPCODES. These haven't been mapped in a post 1/26/2005 world. If you
can find any of these in the current stream, please update them and let
us know!

<opcode id="1900" name="OP_ZoneSpawns" updated="05/29/08">
<comment>old ZoneSpawnsCode</comment>
<payload dir="server" typename="spawnStruct" sizechecktype="none"/>
</opcode>
<opcode id="0020" name="OP_GMServers" updated="05/26/04">
<comment>GM /servers - ?</comment>
</opcode>
<opcode id="790e" name="OP_GMKick" updated="01/26/05">
<comment>GM /kick - Boot player</comment>
</opcode>
<opcode id="0068" name="OP_Petition" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0074" name="OP_GMBecomeNPC" updated="05/26/04">
<comment>GM /becomenpc - Become an NPC</comment>
</opcode>
<opcode id="0076" name="OP_PetitionCheckout" updated="05/26/04">
<comment>Petition Checkout</comment>
</opcode>
<opcode id="007e" name="OP_PetitionCheckIn" updated="05/26/04">
<comment>Petition Checkin</comment>
</opcode>
<opcode id="688f" name="OP_PetitionResolve" updated="05/11/05">
<comment>Client Petition Resolve Request</comment>
</opcode>
<opcode id="0165" name="OP_DeletePetition" updated="01/26/05">
<comment>Player /deletepetition</comment>
</opcode>
<opcode id="0082" name="OP_PetitionQue" updated="05/26/04">
<comment>GM looking at petitions</comment>
</opcode>
<opcode id="0090" name="OP_PetitionUnCheckout" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0097" name="OP_GMSearchCorpse" updated="05/26/04">
<comment>GM /searchcorpse - Search all zones for named corpse</comment>
</opcode>
<opcode id="009a" name="OP_GuildPeace" updated="05/26/04">
<comment>/guildpeace</comment>
</opcode>
<opcode id="00a4" name="OP_GuildWar" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="00a7" name="OP_GuildLeader" updated="05/26/04">
<comment>/guildleader</comment>
</opcode>
<opcode id="00b6" name="OP_ApplyPoison" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="00da" name="OP_GMInquire" updated="05/26/04">
<comment>GM /inquire - Search soulmark data</comment>
</opcode>
<opcode id="00dc" name="OP_GMSoulmark" updated="05/26/04">
<comment>GM /praise /warn - Add soulmark comment to user file</comment>
</opcode>
<opcode id="00de" name="OP_GMHideMe" updated="05/26/04">
<comment>GM /hideme - Remove self from spawn lists and make invis</comment>
</opcode>
<opcode id="00ef" name="OP_SafePoint" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="010b" name="OP_GMGoto" updated="05/26/04">
<comment>GM /goto - Transport to another loc</comment>
</opcode>
<opcode id="012d" name="OP_BindWound" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0132" name="OP_GuildRemove" updated="05/26/04">
<comment>/guildremove</comment>
</opcode>
<opcode id="013b" name="OP_GMTraining" updated="05/26/04">
<comment>old OpenGMCode</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="013c" name="OP_GMEndTraining" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0152" name="OP_MoveCash" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0160" name="OP_Taunt" updated="05/26/04">
<comment>old ConsumeCode</comment>
</opcode>
<opcode id="016c" name="OP_Stun" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0175" name="OP_GMTrainSkill" updated="05/26/04">
<comment>old SkillTrainCode</comment>
</opcode>
<opcode id="0178" name="OP_GMEndTrainingResponse" updated="05/26/04">
<comment>old CloseGMCode</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
<opcode id="0183" name="OP_GMZoneRequest" updated="05/26/04">
<comment>/zone</comment>
</opcode>
<opcode id="018f" name="OP_BecomePK" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0197" name="OP_SetDataRate" updated="05/26/04">
<comment>Client sending datarate.txt value</comment>
</opcode>
<opcode id="0198" name="OP_GMDelCorpse" updated="05/26/04">
<comment>/delcorpse</comment>
</opcode>
<opcode id="0199" name="OP_Sacrifice" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="01af" name="OP_GMApproval" updated="05/26/04">
<comment>GM /approval - Name approval duty?</comment>
</opcode>
<opcode id="01b2" name="OP_GMToggle" updated="05/26/04">
<comment>GM /toggle - Toggle ability to receive tells from other PC's</comment>
</opcode>
<opcode id="01bc" name="OP_MoneyUpdate" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="01ba" name="OP_ReqZoneObjects" updated="05/26/04">
<comment>Client requesting zone objects</comment>
</opcode>
<opcode id="01c4" name="OP_Translocate" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="01ea" name="OP_RespondAA" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="01ed" name="OP_IncreaseStats" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="01ef" name="OP_ViewPetition" updated="05/26/04">
<comment>Player /viewpetition</comment>
</opcode>
<opcode id="01ff" name="OP_ExpansionSetting" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0205" name="OP_GainMoney" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0225" name="OP_GMZoneRequest2" updated="05/26/04">
<comment>/zone 2</comment>
</opcode>
<opcode id="0245" name="?" implicitlen="6" updated="07/14/04">
<comment>Unknown, but has implicit length</comment>
</opcode>
<opcode id="0261" name="OP_CrashDump" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0263" name="OP_GuildDemote" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="0264" name="OP_ZoneUnavail" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="028b" name="OP_GMSummon" updated="05/26/04">
<comment>GM /summon - Summon PC to self</comment>
</opcode>
<opcode id="0296" name="OP_ItemTextFile" updated="05/26/04">
<comment>old BookTextCode</comment>
<payload dir="server" typename="bookTextStruct" sizechecktype="none"/>
</opcode>
<opcode id="029e" name="OP_OpenObject" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="028e" name="OP_GMEmoteZone" updated="05/26/04">
<comment>GM /emotezone - Send zonewide emote</comment>
</opcode>
<opcode id="0296" name="OP_ReadBook" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="02b4" name="OP_SummonCorpse" updated="05/26/04">
<comment>/summoncorpse</comment>
</opcode>
<opcode id="02cc" name="OP_ShopItem" updated="05/26/04">
<comment>Merchant Item data</comment>
</opcode>
<opcode id="02d0" name="OP_AdventureRequest" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="02d1" name="OP_AdventureMerchantResponse" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="02d2" name="OP_AdventureMerchantPurchase" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="02e2" name="OP_AdventurePointsUpdate" updated="05/26/04">
<comment></comment>
</opcode>
<opcode id="02ef" name="OP_Adventure" updated="05/26/04">
<comment>/adventure</comment>
</opcode>
<opcode id="1ee8" name="OP_CombatAbility" updated="02/15/05">
<comment></comment>
</opcode>
-->
</seqopcodes>



2. everquest.h


/*
* everquest.h
*
* ShowEQ Distributed under GPL
* http://seq.sourceforge.net/
*/


/*
** Please be kind and remember to correctly re-order
** the values in here whenever you add a new item,
** thanks. - Andon
*/

/*
** Structures used in the network layer of Everquest
*/

#ifndef EQSTRUCT_H
#define EQSTRUCT_H

#include "config.h"

#ifdef __FreeBSD__
#include <sys/types.h>
#else
#include <stdint.h>
#endif

/*
** ShowEQ specific definitions
*/
// Statistical list defines
#define LIST_HP 0
#define LIST_MANA 1
#define LIST_STAM 2
#define LIST_EXP 3
#define LIST_FOOD 4
#define LIST_WATR 5
#define LIST_STR 6
#define LIST_STA 7
#define LIST_CHA 8
#define LIST_DEX 9
#define LIST_INT 10
#define LIST_AGI 11
#define LIST_WIS 12
#define LIST_MR 13
#define LIST_FR 14
#define LIST_CR 15
#define LIST_DR 16
#define LIST_PR 17
#define LIST_AC 18
#define LIST_ALTEXP 19
#define LIST_MAXLIST 20

/*
** MOB Spawn Type
*/
#define SPAWN_PLAYER 0
#define SPAWN_NPC 1
#define SPAWN_PC_CORPSE 2
#define SPAWN_NPC_CORPSE 3
#define SPAWN_NPC_UNKNOWN 4
#define SPAWN_DROP 6
#define SPAWN_DOOR 7
#define SPAWN_SELF 10

/*
** Diety List
*/
#define DEITY_UNKNOWN 0
#define DEITY_AGNOSTIC 396
#define DEITY_BRELL 202
#define DEITY_CAZIC 203
#define DEITY_EROL 204
#define DEITY_BRISTLE 205
#define DEITY_INNY 206
#define DEITY_KARANA 207
#define DEITY_MITH 208
#define DEITY_PREXUS 209
#define DEITY_QUELLIOUS 210
#define DEITY_RALLOS 211
#define DEITY_SOLUSEK 213
#define DEITY_TRIBUNAL 214
#define DEITY_TUNARE 215
#define DEITY_BERT 201
#define DEITY_RODCET 212
#define DEITY_VEESHAN 216

//Team numbers for Deity teams
#define DTEAM_GOOD 1
#define DTEAM_NEUTRAL 2
#define DTEAM_EVIL 3
#define DTEAM_OTHER 5

//Team numbers for Race teams
#define RTEAM_HUMAN 1
#define RTEAM_ELF 2
#define RTEAM_DARK 3
#define RTEAM_SHORT 4
#define RTEAM_OTHER 5

//Maximum limits of certain types of data
#define MAX_KNOWN_SKILLS 100
#define MAX_SPELL_SLOTS 16
#define MAX_KNOWN_LANGS 32
#define MAX_SPELLBOOK_SLOTS 720
#define MAX_GROUP_MEMBERS 6
#define MAX_BUFFS 42
#define MAX_GUILDS 8192
#define MAX_AA 300
#define MAX_BANDOLIERS 20
#define MAX_POTIONS_IN_BELT 5
#define MAX_TRIBUTES 5
#define MAX_DISCIPLINES 200

//Item Flags
#define ITEM_NORMAL 0x0000
#define ITEM_NORMAL1 0x0031
#define ITEM_NORMAL2 0x0036
#define ITEM_NORMAL3 0x315f
#define ITEM_NORMAL4 0x3336
#define ITEM_NORMAL5 0x0032
#define ITEM_NORMAL6 0x0033
#define ITEM_NORMAL7 0x0034
#define ITEM_NORMAL8 0x0039
#define ITEM_CONTAINER 0x7900
#define ITEM_CONTAINER_PLAIN 0x7953
#define ITEM_BOOK 0x7379
#define ITEM_VERSION 0xFFFF

// Item spellId no spell value
#define ITEM_SPELLID_NOSPELL 0xffff

// Item Field Count
#define ITEM_FIELD_SEPERATOR_COUNT 117
#define ITEM_CMN_FIELD_SEPERATOR_COUNT 102

//Combat Flags
#define COMBAT_MISS 0
#define COMBAT_BLOCK -1
#define COMBAT_PARRY -2
#define COMBAT_RIPOSTE -3
#define COMBAT_DODGE -4

#define PLAYER_CLASSES 16
#define PLAYER_RACES 15

/*
** Item Packet Type
*/
enum ItemPacketType
{
ItemPacketViewLink = 0x00,
ItemPacketMerchant = 0x64,
ItemPacketLoot = 0x66,
ItemPacketTrade = 0x67,
ItemPacketSummonItem = 0x6a,
ItemPacketWorldContainer = 0x6b
};

/*
** Item types
*/
enum ItemType
{
ItemTypeCommon = 0,
ItemTypeContainer = 1,
ItemTypeBook = 2
};

/*
** Chat Colors
*/
enum ChatColor
{
CC_Default = 0,
CC_DarkGrey = 1,
CC_DarkGreen = 2,
CC_DarkBlue = 3,
CC_Purple = 5,
CC_LightGrey = 6,
CC_User_Say = 256,
CC_User_Tell = 257,
CC_User_Group = 258,
CC_User_Guild = 259,
CC_User_OOC = 260,
CC_User_Auction = 261,
CC_User_Shout = 262,
CC_User_Emote = 263,
CC_User_Spells = 264,
CC_User_YouHitOther = 265,
CC_User_OtherHitYou = 266,
CC_User_YouMissOther = 267,
CC_User_OtherMissYou = 268,
CC_User_Duels = 269,
CC_User_Skills = 270,
CC_User_Disciplines = 271,
CC_User_Default = 273,
CC_User_MerchantOffer = 275,
CC_User_MerchantExchange = 276,
CC_User_YourDeath = 277,
CC_User_OtherDeath = 278,
CC_User_OtherHitOther = 279,
CC_User_OtherMissOther = 280,
CC_User_Who = 281,
CC_User_Yell = 282,
CC_User_NonMelee = 283,
CC_User_SpellWornOff = 284,
CC_User_MoneySplit = 285,
CC_User_Loot = 286,
CC_User_Random = 287,
CC_User_OtherSpells = 288,
CC_User_SpellFailure = 289,
CC_User_ChatChannel = 290,
CC_User_Chat1 = 291,
CC_User_Chat2 = 292,
CC_User_Chat3 = 293,
CC_User_Chat4 = 294,
CC_User_Chat5 = 295,
CC_User_Chat6 = 296,
CC_User_Chat7 = 297,
CC_User_Chat8 = 298,
CC_User_Chat9 = 299,
CC_User_Chat10 = 300,
CC_User_MeleeCrit = 301,
CC_User_SpellCrit = 302,
CC_User_TooFarAway = 303,
CC_User_NPCRampage = 304,
CC_User_NPCFurry = 305,
CC_User_NPCEnrage = 306,
CC_User_EchoSay = 307,
CC_User_EchoTell = 308,
CC_User_EchoGroup = 309,
CC_User_EchoGuild = 310,
CC_User_EchoOOC = 311,
CC_User_EchoAuction = 312,
CC_User_EchoShout = 313,
CC_User_EchoEmote = 314,
CC_User_EchoChat1 = 315,
CC_User_EchoChat2 = 316,
CC_User_EchoChat3 = 317,
CC_User_EchoChat4 = 318,
CC_User_EchoChat5 = 319,
CC_User_EchoChat6 = 320,
CC_User_EchoChat7 = 321,
CC_User_EchoChat8 = 322,
CC_User_EchoChat9 = 323,
CC_User_EchoChat10 = 324,
CC_User_UnusedAtThisTime = 325,
CC_User_ItemTags = 326,
CC_User_RaidSay = 327,
CC_User_MyPet = 328,
CC_User_DamageShield = 329,
};

/*
** Group Update actions
*/
enum GroupUpdateAction
{
GUA_Joined = 0,
GUA_Left = 1,
GUA_LastLeft = 6,
GUA_FullGroupInfo = 7,
GUA_MakeLeader = 8,
GUA_Started = 9,
};

/**
* Leadership AAs enum, used to index into leadershipAAs in charProfileStruct
*/
enum LeadershipAAIndex
{
groupMarkNPC = 0,
groupNPCHealth,
groupDelegateMainAssist,
groupDelegateMarkNPC,
groupUnknown4,
groupUnknown5,
groupInspectBuffs,
groupUnknown7,
groupSpellAwareness,
groupOffenseEnhancement,
groupManaEnhancement,
groupHealthEnhancement,
groupHealthRegeneration,
groupFindPathToPC,
groupHealthOfTargetsTarget,
groupUnknown15,
raidMarkNPC, //0x10
raidNPCHealth,
raidDelegateMainAssist,
raidDelegateMarkNPC,
raidUnknown4,
raidUnknown5,
raidUnknown6,
raidSpellAwareness,
raidOffenseEnhancement,
raidManaEnhancement,
raidHealthEnhancement,
raidHealthRegeneration,
raidFindPathToPC,
raidHealthOfTargetsTarget,
raidUnknown14,
raidUnknown15,
MAX_LEAD_AA //=32
};

/**
* Recast timer types. Used as an off set to charProfileStruct timers.
*/
enum RecastTypes
{
RecastTimer0 = 0,
RecastTimer1,
WeaponHealClickTimer, // 2
MuramiteBaneNukeClickTimer, // 3
RecastTimer4,
DispellClickTimer, // 5 (also click heal orbs?)
EpicTimer, // 6
OoWBPClickTimer, // 7
VishQuestClassItemTimer, // 8
HealPotionTimer, // 9
RecastTimer10,
RecastTimer11,
RecastTimer12,
RecastTimer13,
RecastTimer14,
RecastTimer15,
RecastTimer16,
RecastTimer17,
RecastTimer18,
ModRodTimer, // 19
MAX_RECAST_TYPES // 20
};


/*
** Compiler override to ensure
** byte aligned structures
*/
#pragma pack(1)

/*
** Generic Structures used in specific
** structures below
*/

// OpCode stuff (all kinda silly, but until we stop including the OpCode everywhere)...
struct opCodeStruct
{
int16_t opCode;

// kinda silly -- this is required for us to be able to stuff them in a QValueList
bool operator== ( const opCodeStruct t ) const
{
return ( opCode == t.opCode);
}
bool operator== ( uint16_t opCode2 ) const
{
return ( opCode == opCode2 );
}
};

/**
* Session request on a stream. This is sent by the client to initiate
* a session with the zone or world server.
*
* Size: 12 Octets
*/
struct SessionRequestStruct
{
/*0000*/ uint32_t unknown0000;
/*0004*/ uint32_t sessionId;
/*0008*/ uint32_t maxLength;
/*0012*/ uint8_t tag[10]; // "Everquest\0"
/*0022*/
};

/**
* Session response on a stream. This is the server replying to a session
* request with session information.
*
* Size: 19 Octets
*/
struct SessionResponseStruct
{
/*0000*/ uint32_t sessionId;
/*0004*/ uint32_t key;
/*0008*/ uint16_t unknown0008;
/*0010*/ uint8_t unknown0010;
/*0011*/ uint32_t maxLength;
/*0015*/ uint32_t unknown0015;
/*0019*/
};

/**
* Session disconnect on a stream. This is the server telling the client to
* close a stream.
*
* Size: 8 Octets
*/
struct SessionDisconnectStruct
{
/*0000*/ uint8_t unknown[8];
/*0008*/
};

/*
* Used in charProfileStruct
* Size: 4 Octets
*/
struct Color_Struct
{
union
{
struct
{
/*0000*/uint8_t blue;
/*0001*/uint8_t red;
/*0002*/uint8_t green;
/*0003*/uint8_t unknown0003;
} rgb;
/*0000*/uint32_t color;
};
};

/*
* Used in charProfileStruct. Buffs
* Length: 80 Octets
*/
struct spellBuff
{
/*0000*/ uint8_t unknown0000; //
/*0001*/ uint8_t unknown0001; //
/*0002*/ uint8_t unknown0002; //
/*0003*/ uint8_t unknown0003; //
/*0004*/ uint8_t unknown0004; //
/*0005*/ uint32_t playerId; // Global id of caster (for wear off)
/*0009*/ uint8_t unknown0009[5]; //
/*0014*/ int32_t duration; // Time remaining in ticks
/*0018*/ int8_t level; // Level of person who cast buff
/*0019*/ int32_t spellid; // Spell
/*0023*/ int32_t effect; // holds the dmg absorb amount on runes
/*0027*/ uint8_t unknown0027[53];
/*0080*/
};


/*
* Used in charProfileStruct
* Size: 12 Octets
*/
struct AA_Array
{
/*000*/ uint32_t AA;
/*004*/ uint32_t value;
/*008*/ uint32_t unknown008;
/*012*/
};

/**
* Used in charProfileStruct. An item inline in the stream, used in Bandolier and Potion Belt.
* Size: 72 Octets
*/
struct InlineItem
{
/*000*/ uint32_t itemId;
/*004*/ uint32_t icon;
/*008*/ char itemName[64];
/*072*/
};

/**
* Used in charProfileStruct. Contents of a Bandolier.
* Size: 320 Octets
*/
struct BandolierStruct
{
/*000*/ char bandolierName[32];
/*032*/ InlineItem mainHand;
/*104*/ InlineItem offHand;
/*176*/ InlineItem range;
/*248*/ InlineItem ammo;
/*320*/
};

/**
* Used in charProfileStruct. A tribute a player can have loaded.
* Size: 8 Octets
*/
struct TributeStruct
{
/*000*/ uint32_t tribute;
/*004*/ uint32_t rank;
/*008*/
};

/**
* Used in charProfileStruct. A bind point.
* Size: 20 Octets
*/
struct BindStruct
{
/*000*/ uint32_t zoneId;
/*004*/ float x;
/*008*/ float y;
/*012*/ float z;
/*016*/ float heading;
/*020*/
};

/*
* Used in charProfileStruct. Visible Equipment.
* Size: 20 Octets
*/
struct EquipStruct
{
/*00*/ uint32_t equip0;
/*04*/ uint32_t equip1;
/*08*/ uint32_t equip2;
/*12*/ uint32_t itemId;
/*16*/ uint32_t equip3;
/*20*/
};

/*
** Type: Zone Change Request (before hand)
** Length: 100 Octets
** OpCode: ZoneChangeCode
*/
struct zoneChangeStruct
{
/*0000*/ char name[64]; // Character Name
/*0064*/ uint16_t zoneId; // zone Id
/*0066*/ uint16_t zoneInstance; // zone Instance
/*0068*/ uint8_t unknown0068[8]; // unknown
/*0076*/ uint8_t unknown0076[12]; // ***Placeholder (6/29/2005)
/*0088*/ uint8_t unknown0088[4]; // HoT Beta (9/7/2010)
/*0092*/ uint8_t unknown0092[8]; // RoF (12/12/2012)
/*0100*/
};

/*
** Type: Request Zone Change (server asking the client to change zones)
** Size: 24 Octets
** OpCode: OP_RequestZoneChange
*/
struct requestZoneChangeStruct
{
/*0000*/ uint16_t zoneId; // Zone to change to
/*0002*/ uint16_t zoneInstance; // Instance to change to
/*0004*/ float x; // Zone in x coord in next zone
/*0008*/ float y; // Zone in y coord in next zone
/*0012*/ float z; // Zone in z coord in next zone
/*0016*/ float heading; // Zone in heading in next zone
/*0020*/ uint32_t unknown0020; // *** Placeholder
/*0024*/
};

/*
** Client Zone Entry struct
** Length: 76 Octets
** OpCode: ZoneEntryCode (when direction == client)
*/
struct ClientZoneEntryStruct
{
/*0000*/ uint32_t unknown0000; // ***Placeholder
/*0004*/ char name[32]; // Player firstname
/*0036*/ uint8_t unknown0036[28]; // ***Placeholder
/*0064*/ uint32_t unknown0064[3]; // unknown
/*0076*/
};


/*
** New Zone Code
** Length: 948 Octets
** OpCode: NewZoneCode
*/
struct newZoneStruct
{
/*0000*/ char name[64]; // Character name
/*0064*/ char shortName[32]; // Zone Short Name (maybe longer?)
/*0096*/ char unknown0096[96];
/*0192*/ char longName[278]; // Zone Long Name
/*0470*/ uint8_t ztype; // Zone type
/*0471*/ uint8_t fog_red[4]; // Zone fog (red)
/*0475*/ uint8_t fog_green[4]; // Zone fog (green)
/*0479*/ uint8_t fog_blue[4]; // Zone fog (blue)
/*0483*/ uint8_t unknown0483[87]; // *** Placeholder
/*0570*/ uint8_t sky; // Zone sky
/*0571*/ uint8_t unknown0571[13]; // *** Placeholder
/*0584*/ float zone_exp_multiplier; // Experience Multiplier
/*0588*/ float safe_y; // Zone Safe Y
/*0592*/ float safe_x; // Zone Safe X
/*0596*/ float safe_z; // Zone Safe Z
/*0600*/ float unknown0600; // *** Placeholder
/*0604*/ float unknown0604; // *** Placeholder
/*0608*/ float underworld; // Underworld
/*0612*/ float minclip; // Minimum view distance
/*0616*/ float maxclip; // Maximum view distance
/*0620*/ uint8_t unknown0616[84]; // *** Placeholder
/*0704*/ char zonefile[64]; // Zone file name?
/*0768*/ uint8_t unknown0764[36]; // *** Placeholder (12/05/2006)
/*0804*/ uint8_t unknown0800[32]; // *** Placeholder (02/13/2007)
/*0836*/ uint8_t unknown0832[12]; // *** Placeholder
/*0848*/ uint8_t unknown0844[4]; // *** Placeholder (06/29/2005)
/*0852*/ uint8_t unknown0848[4]; // *** Placeholder (09/13/2005)
/*0856*/ uint8_t unknown0852[4]; // *** Placeholder (02/21/2006)
/*0860*/ uint8_t unknown0856[36]; // *** Placeholder (06/13/2006)
/*0896*/ uint8_t unknown0892[12]; // *** Placeholder (12/05/2006)
/*0908*/ uint8_t unknown0904[8]; // *** Placeholder (02/13/2007)
/*0916*/ uint8_t unknown0916[4]; // *** Placeholder (11/24/2007)
/*0920*/ uint8_t unknown0920[4]; // *** Placeholder (01/17/2008)
/*0924*/ uint8_t unknown0924[4]; // *** Placeholder (09/03/2008)
/*0928*/ uint8_t unknown0928[4]; // *** Placeholder (10/07/2008)
/*0932*/ uint8_t unknown0932[8]; // *** Placeholder (11/04/2009)
/*0940*/ uint8_t unknown0940[4]; // *** Placeholder (12/15/2009)
/*0944*/ uint8_t unknown0944[4]; // *** Placeholder (11/15/2011)
/*0948*/
};

/*
** Dynamic Zone Switch Info Struct
** Length: 32 Octets
** OpCode: DzSwitchInfo
*/
struct dzSwitchInfo
{
/*0000*/ uint32_t unknown0000;
/*0004*/ uint32_t show; // Show compass line
/*0008*/ uint16_t zoneID;
/*0010*/ uint16_t instanceID;
/*0012*/ uint32_t type; // if(type != 1 && type > 2 && type <= 5) { color = green; } else { color = pink; }
/*0016*/ uint32_t unknown0016;
/*0020*/ float y;
/*0024*/ float x;
/*0028*/ float z;
/*0032*/
};

/*
** Dynamic Zone Info Struct
** Length: 208 Octets
** OpCode: DzInfo
*/
struct dzInfo
{
/*0000*/ uint32_t unknown0000;
/*0004*/ uint32_t unknown0004;
/*0008*/ uint8_t newDZ;
/*0009*/ uint8_t padding0009[3];
/*0012*/ uint32_t maxPlayers;
/*0016*/ char dzName[128]; // Instance name
/*0144*/ char name[64]; // Your player's name
/*0208*/
};

/**
* Player Profile. Common part of charProfileStruct shared between
* shrouding and zoning profiles.
*
* NOTE: Offsets are kept in here relative to OP_PlayerProfile to ease in
* diagnosing changes in that struct.
*/
struct playerProfileStruct
{
/*00004*/ uint16_t gender; // Player Gender - 0 Male, 1 Female
/*00008*/ uint32_t race; // Player race
/*00012*/ uint32_t class_; // Player class
/*00016*/ uint8_t unknown00016[44]; // ***Placeholder
/*00056*/ uint8_t level; // Level of player
/*00057*/ uint8_t level1; // Level of player (again?)
/*00058*/ uint8_t unknown00058[2]; // ***Placeholder
/*00060*/ BindStruct binds[5]; // Bind points (primary is first)
/*00160*/ uint32_t deity; // deity
/*00164*/ uint32_t intoxication; // Alcohol level (in ticks till sober?)
/*00168*/ uint32_t spellSlotRefresh[13]; // Refresh time (millis)
/*00220*/ uint8_t haircolor; // Player hair color
/*00221*/ uint8_t beardcolor; // Player beard color
/*00222*/ uint8_t unknown00222[6]; // *** Placeholder
/*00228*/ uint8_t eyecolor1; // Player left eye color
/*00229*/ uint8_t eyecolor2; // Player right eye color
/*00230*/ uint8_t hairstyle; // Player hair style
/*00231*/ uint8_t beard; // Player beard type
/*00232*/ uint8_t unknown00232[4]; // *** Placeholder
/*00236*/ union
{
struct
{
/*00236*/ EquipStruct equip_helmet; // Equipment: Helmet visual
/*00256*/ EquipStruct equip_chest; // Equipment: Chest visual
/*00276*/ EquipStruct equip_arms; // Equipment: Arms visual
/*00296*/ EquipStruct equip_bracers; // Equipment: Wrist visual
/*00316*/ EquipStruct equip_hands; // Equipment: Hands visual
/*00336*/ EquipStruct equip_legs; // Equipment: Legs visual
/*00356*/ EquipStruct equip_feet; // Equipment: Boots visual
/*00376*/ EquipStruct equip_primary; // Equipment: Main visual
/*00396*/ EquipStruct equip_secondary; // Equipment: Off visual
} equip;
/*00416*/ EquipStruct equipment[22];
};
/*00416*/ uint8_t unknown00416[268]; // *** Placeholder
/*00416*/ uint8_t unknowntmp[30]; // *** Placeholder
/*00688*/ Color_Struct item_tint[9]; // RR GG BB 00
/*00724*/ AA_Array aa_array[MAX_AA]; // AAs
/*04324*/ uint32_t points; // Unspent Practice points
/*04328*/ uint32_t MANA; // Current MANA
/*04332*/ uint32_t curHp; // Current HP without +HP equipment
/*04336*/ uint32_t STR; // Strength
/*04340*/ uint32_t STA; // Stamina
/*04344*/ uint32_t CHA; // Charisma
/*04348*/ uint32_t DEX; // Dexterity
/*04352*/ uint32_t INT; // Intelligence
/*04356*/ uint32_t AGI; // Agility
/*04360*/ uint32_t WIS; // Wisdom
/*04364*/ uint8_t unknown04364[28]; // *** Placeholder
/*04392*/ uint32_t face; // Player face
/*04396*/ uint8_t unknown04396[180]; // *** Placeholder
/*04576*/ int32_t sSpellBook[729]; // List of the Spells in spellbook
/*07492*/ int32_t sMemSpells[MAX_SPELL_SLOTS]; // List of spells memorized
/*07540*/ uint8_t unknown07540[17]; // *** Placeholder
/*07585*/ uint32_t platinum; // Platinum Pieces on player
/*07564*/ uint32_t gold; // Gold Pieces on player
/*07568*/ uint32_t silver; // Silver Pieces on player
/*07572*/ uint32_t copper; // Copper Pieces on player
/*07576*/ uint32_t platinum_cursor; // Platinum Pieces on cursor
/*07580*/ uint32_t gold_cursor; // Gold Pieces on cursor
/*07584*/ uint32_t silver_cursor; // Silver Pieces on cursor
/*07588*/ uint32_t copper_cursor; // Copper Pieces on cursor
/*07592*/ uint32_t skills[MAX_KNOWN_SKILLS]; // List of skills
/*07992*/ uint32_t innateSkills[26]; // innateSkills
/*08096*/ uint8_t unknown08096[16]; // *** Placeholder
/*08112*/ uint32_t toxicity; // Potion Toxicity (15=too toxic, each potion adds 3)
/*08116*/ uint32_t thirst; // Drink (ticks till next drink)
/*08120*/ uint32_t hunger; // Food (ticks till next eat)
/*08124*/ uint8_t unknown08124[20]; // *** Placeholder
/*08140*/ spellBuff buffs[MAX_BUFFS]; // Buffs currently on the player
/*11836*/ uint32_t disciplines[MAX_DISCIPLINES]; // Known disciplines
/*12236*/ uint8_t unknown12236[400]; // *** Placeholder
/*12636*/ uint32_t recastTimers[MAX_RECAST_TYPES]; // Timers (GMT of last use)
/*12716*/ uint8_t unknown12716[480]; // *** Placeholder
/*13196*/ uint32_t endurance; // Current endurance
/*13200*/ uint32_t aa_spent; // Number of spent AA points (including glyphs)
/*13204*/ uint32_t aa_assigned; // Number of points currently assigned to AAs
/*13208*/ uint32_t unknown13208[4]; // *** Placeholder
/*13224*/ uint32_t aa_unspent; // Unspent AA points
/*13228*/ uint8_t unknown13228[4]; // *** Placeholder
/*13232*/ BandolierStruct bandoliers[MAX_BANDOLIERS]; // bandolier contents
/*19632*/ InlineItem potionBelt[MAX_POTIONS_IN_BELT]; // potion belt
/*19992*/ uint8_t unknown19992[92]; // *** Placeholder
/*20084*/
};

/*
** Player Profile
** Length: Variable
** OpCode: OP_PlayerProfile
*/
struct charProfileStruct
{
/*00000*/ uint32_t checksum; //
/*00004*/ playerProfileStruct profile; // Profile
/*20084*/ char name[64]; // Name of player
/*20148*/ char lastName[32]; // Last name of player
/*20180*/ uint8_t unknown20180[4]; // *** Placeholder
/*20184*/ uint32_t accountCreateDate; // Date account was created
/*20188*/ int32_t guildID; // guildID
/*20192*/ uint32_t birthdayTime; // character birthday
/*20196*/ uint32_t lastSaveTime; // character last save time
/*20200*/ uint32_t timePlayedMin; // time character played
/*20204*/ uint8_t unknown20204[4]; // *** Placeholder
/*20208*/ uint8_t pvp; // 1=pvp, 0=not pvp
/*20209*/ uint8_t anon; // 2=roleplay, 1=anon, 0=not anon
/*20210*/ uint8_t gm; // 0=no, 1=yes (guessing!)
/*20211*/ int8_t guildstatus; // 0=member, 1=officer, 2=guildleader
/*20212*/ uint8_t unknown20212[16]; // *** Placeholder
/*20228*/ uint32_t exp; // Current Experience
/*20232*/ uint8_t unknown20232[12]; // *** Placeholder
/*20244*/ uint8_t languages[MAX_KNOWN_LANGS]; // List of languages
/*20270*/ uint8_t unknown20272[6]; // All 0x00 (language buffer?)
/*20276*/ float y; // Players y position
/*20280*/ float x; // Players x position
/*20284*/ float z; // Players z position
/*20288*/ float heading; // Players heading
/*20292*/ uint32_t standState; // 0x64 = stand
/*20296*/ uint32_t platinum_bank; // Platinum Pieces in Bank
/*20300*/ uint32_t gold_bank; // Gold Pieces in Bank
/*20304*/ uint32_t silver_bank; // Silver Pieces in Bank
/*20308*/ uint32_t copper_bank; // Copper Pieces in Bank
/*20312*/ uint32_t platinum_shared; // Shared platinum pieces
/*20316*/ uint8_t unknown20316[6220]; // *** Placeholder
/*26536*/ uint32_t expansions; // Bitmask for expansions
/*26540*/ uint8_t unknown22540[12]; // *** Placeholder
/*26552*/ uint32_t autosplit; // 0 = off, 1 = on
/*26556*/ uint8_t unknown26556[16]; // *** Placeholder
/*26572*/ uint16_t zoneId; // see zones.h
/*26574*/ uint16_t zoneInstance; // Instance id
/*26576*/ uint8_t unknown26576[992]; // *** Placeholder
/*27568*/ uint32_t leadAAActive; // 0 = leader AA off, 1 = leader AA on
/*27572*/ uint8_t unknown27572[4]; // *** Placeholder
/*27576*/ uint32_t ldon_guk_points; // Earned GUK points
/*27580*/ uint32_t ldon_mir_points; // Earned MIR points
/*27584*/ uint32_t ldon_mmc_points; // Earned MMC points
/*27588*/ uint32_t ldon_ruj_points; // Earned RUJ points
/*27592*/ uint32_t ldon_tak_points; // Earned TAK points
/*27596*/ uint32_t ldon_avail_points; // Available LDON points
/*27600*/ uint8_t unknown27600[144]; // *** Placeholder
/*27744*/ uint32_t tributeTime; // Time remaining on tribute (millisecs)
/*27748*/ uint32_t careerTribute; // Total favor points for this char
/*27752*/ uint32_t unknown23536; // *** Placeholder
/*27756*/ uint32_t currentTribute; // Current tribute points
/*27760*/ uint32_t unknown23544; // *** Placeholder
/*27764*/ uint32_t tributeActive; // 0 = off, 1=on
/*27768*/ TributeStruct tributes[MAX_TRIBUTES]; // Current tribute loadout
/*27808*/ uint8_t unknown27808[100]; // *** Placeholder
/*27908*/ float expGroupLeadAA; // Current group lead exp points
/*27912*/ float expRaidLeadAA; // Current raid lead AA exp points
/*27916*/ uint32_t groupLeadAAUnspent; // Unspent group lead AA points
/*27920*/ uint32_t unknown27920; // ***Placeholder
/*27924*/ uint32_t raidLeadAAUnspent; // Unspent raid lead AA points
/*27928*/ uint32_t unknown27928; // ***Placeholder
/*27932*/ uint32_t leadershipAAs[MAX_LEAD_AA]; // Leader AA ranks
/*28060*/ uint8_t unknown28060[128]; // *** Placeholder
/*28188*/ uint32_t airRemaining; // Air supply (seconds)
/*28192*/ uint8_t unknown28192[4592]; // *** Placeholder
/*32784*/ uint32_t expAA; // Exp earned in current AA point
/*32788*/ uint8_t unknown32788[40]; // *** Placeholder
/*32828*/ uint32_t currentRadCrystals; // Current count of radiant crystals
/*32832*/ uint32_t careerRadCrystals; // Total count of radiant crystals ever
/*32836*/ uint32_t currentEbonCrystals; // Current count of ebon crystals
/*32840*/ uint32_t careerEbonCrystals; // Total count of ebon crystals ever
/*32844*/ uint8_t groupAutoconsent; // 0=off, 1=on
/*32845*/ uint8_t raidAutoconsent; // 0=off, 1=on
/*32846*/ uint8_t guildAutoconsent; // 0=off, 1=on
/*32847*/ uint8_t unknown32487[5]; // ***Placeholder (6/29/2005)
/*32852*/ uint32_t showhelm; // 0=no, 1=yes
/*32856*/ uint8_t unknown32856[1048]; // ***Placeholder (2/13/2007)
/*33904*/
};

#if 0
// The following seem to be totally gone from charProfileStruct (9/13/05)
/*2384*/ char title[32]; // Current character title
/*2352*/ char servername[32]; // server the char was created on
/*2416*/ char suffix[32]; // Current character suffix
#endif

#if 1
struct playerAAStruct {
/* 0 */ uint8_t unknown0;
union {
uint8_t unnamed[17];
struct _named {
/* 1 */ uint8_t innate_strength;
/* 2 */ uint8_t innate_stamina;
/* 3 */ uint8_t innate_agility;
/* 4 */ uint8_t innate_dexterity;
/* 5 */ uint8_t innate_intelligence;
/* 6 */ uint8_t innate_wisdom;
/* 7 */ uint8_t innate_charisma;
/* 8 */ uint8_t innate_fire_protection;
/* 9 */ uint8_t innate_cold_protection;
/* 10 */ uint8_t innate_magic_protection;
/* 11 */ uint8_t innate_poison_protection;
/* 12 */ uint8_t innate_disease_protection;
/* 13 */ uint8_t innate_run_speed;
/* 14 */ uint8_t innate_regeneration;
/* 15 */ uint8_t innate_metabolism;
/* 16 */ uint8_t innate_lung_capacity;
/* 17 */ uint8_t first_aid;
} named;
} general_skills;
union {
uint8_t unnamed[17];
struct _named {
/* 18 */ uint8_t healing_adept;
/* 19 */ uint8_t healing_gift;
/* 20 */ uint8_t unknown20;
/* 21 */ uint8_t spell_casting_reinforcement;
/* 22 */ uint8_t mental_clarity;
/* 23 */ uint8_t spell_casting_fury;
/* 24 */ uint8_t chanelling_focus;
/* 25 */ uint8_t unknown25;
/* 26 */ uint8_t unknown26;
/* 27 */ uint8_t unknown27;
/* 28 */ uint8_t natural_durability;
/* 29 */ uint8_t natural_healing;
/* 30 */ uint8_t combat_fury;
/* 31 */ uint8_t fear_resistance;
/* 32 */ uint8_t finishing_blow;
/* 33 */ uint8_t combat_stability;
/* 34 */ uint8_t combat_agility;
} named;
} archetype_skills;
union {
uint8_t unnamed[93];
struct _name {
/* 35 */ uint8_t mass_group_buff; // All group-buff-casting classes(?)
// ===== Cleric =====
/* 36 */ uint8_t divine_resurrection;
/* 37 */ uint8_t innate_invis_to_undead; // cleric, necromancer
/* 38 */ uint8_t celestial_regeneration;
/* 39 */ uint8_t bestow_divine_aura;
/* 40 */ uint8_t turn_undead;
/* 41 */ uint8_t purify_soul;
// ===== Druid =====
/* 42 */ uint8_t quick_evacuation; // wizard, druid
/* 43 */ uint8_t exodus; // wizard, druid
/* 44 */ uint8_t quick_damage; // wizard, druid
/* 45 */ uint8_t enhanced_root; // druid
/* 46 */ uint8_t dire_charm; // enchanter, druid, necromancer
// ===== Shaman =====
/* 47 */ uint8_t cannibalization;
/* 48 */ uint8_t quick_buff; // shaman, enchanter
/* 49 */ uint8_t alchemy_mastery;
/* 50 */ uint8_t rabid_bear;
// ===== Wizard =====
/* 51 */ uint8_t mana_burn;
/* 52 */ uint8_t improved_familiar;
/* 53 */ uint8_t nexus_gate;
// ===== Enchanter =====
/* 54 */ uint8_t unknown54;
/* 55 */ uint8_t permanent_illusion;
/* 56 */ uint8_t jewel_craft_mastery;
/* 57 */ uint8_t gather_mana;
// ===== Mage =====
/* 58 */ uint8_t mend_companion; // mage, necromancer
/* 59 */ uint8_t quick_summoning;
/* 60 */ uint8_t frenzied_burnout;
/* 61 */ uint8_t elemental_form_fire;
/* 62 */ uint8_t elemental_form_water;
/* 63 */ uint8_t elemental_form_earth;
/* 64 */ uint8_t elemental_form_air;
/* 65 */ uint8_t improved_reclaim_energy;
/* 66 */ uint8_t turn_summoned;
/* 67 */ uint8_t elemental_pact;
// ===== Necromancer =====
/* 68 */ uint8_t life_burn;
/* 69 */ uint8_t dead_mesmerization;
/* 70 */ uint8_t fearstorm;
/* 71 */ uint8_t flesh_to_bone;
/* 72 */ uint8_t call_to_corpse;
// ===== Paladin =====
/* 73 */ uint8_t divine_stun;
/* 74 */ uint8_t improved_lay_of_hands;
/* 75 */ uint8_t slay_undead;
/* 76 */ uint8_t act_of_valor;
/* 77 */ uint8_t holy_steed;
/* 78 */ uint8_t fearless; // paladin, shadowknight

/* 79 */ uint8_t two_hand_bash; // paladin, shadowknight
// ===== Ranger =====
/* 80 */ uint8_t innate_camouflage; // ranger, druid
/* 81 */ uint8_t ambidexterity; // all "dual-wield" users
/* 82 */ uint8_t archery_mastery; // ranger
/* 83 */ uint8_t unknown83;
/* 84 */ uint8_t endless_quiver; // ranger
// ===== Shadow Knight =====
/* 85 */ uint8_t unholy_steed;
/* 86 */ uint8_t improved_harm_touch;
/* 87 */ uint8_t leech_touch;
/* 88 */ uint8_t unknown88;
/* 89 */ uint8_t soul_abrasion;
// ===== Bard =====
/* 90 */ uint8_t instrument_mastery;
/* 91 */ uint8_t unknown91;
/* 92 */ uint8_t unknown92;
/* 93 */ uint8_t unknown93;
/* 94 */ uint8_t jam_fest;
/* 95 */ uint8_t unknown95;
/* 96 */ uint8_t unknown96;
// ===== Monk =====
/* 97 */ uint8_t critical_mend;
/* 98 */ uint8_t purify_body;
/* 99 */ uint8_t unknown99;
/* 100 */ uint8_t rapid_feign;
/* 101 */ uint8_t return_kick;
// ===== Rogue =====
/* 102 */ uint8_t escape;
/* 103 */ uint8_t poison_mastery;
/* 104 */ uint8_t double_riposte; // all "riposte" users
/* 105 */ uint8_t unknown105;
/* 106 */ uint8_t unknown106;
/* 107 */ uint8_t purge_poison; // rogue
// ===== Warrior =====
/* 108 */ uint8_t flurry;
/* 109 */ uint8_t rampage;
/* 110 */ uint8_t area_taunt;
/* 111 */ uint8_t warcry;
/* 112 */ uint8_t bandage_wound;
// ===== (Other) =====
/* 113 */ uint8_t spell_casting_reinforcement_mastery; // all "pure" casters
/* 114 */ uint8_t unknown114;
/* 115 */ uint8_t extended_notes; // bard
/* 116 */ uint8_t dragon_punch; // monk
/* 117 */ uint8_t strong_root; // wizard
/* 118 */ uint8_t singing_mastery; // bard
/* 119 */ uint8_t body_and_mind_rejuvenation; // paladin, ranger, bard
/* 120 */ uint8_t physical_enhancement; // paladin, ranger, bard
/* 121 */ uint8_t adv_trap_negotiation; // rogue, bard
/* 122 */ uint8_t acrobatics; // all "safe-fall" users
/* 123 */ uint8_t scribble_notes; // bard
/* 124 */ uint8_t chaotic_stab; // rogue
/* 125 */ uint8_t pet_discipline; // all pet classes except enchanter
/* 126 */ uint8_t unknown126;
/* 127 */ uint8_t unknown127;
} named;
} class_skills;
};
#endif

/*
** Generic Spawn Struct
** Length: Variable.
** Used in:
** dbSpawnStruct
** petStruct
** spawnShroudOther
** spawnShroudSelf
*/

// Fixed-length struct that we'll fill with data from the variable-length packet,
// unnecessary fields removed, arranged in order with the packet.
struct spawnStruct
{
/*0000*/ char name[64];
/*0000*/ uint32_t spawnId;
/*0000*/ uint8_t level;
/*0000*/ uint8_t NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
/*0000*/ union
{
struct
{
unsigned gender:1; // Gender (0=male, 1=female)
unsigned AFK:1;
unsigned sneak:1;
unsigned LFG:1;
unsigned padding6:1;
unsigned invis:1;
unsigned padding5:11;
unsigned gm:1;
unsigned anon:1; // 0=normal, 1=anon, 2=roleplay
unsigned padding4:1;
unsigned padding7:1;
unsigned padding3:1;
unsigned linkdead:1;
unsigned betabuffed:1;
unsigned padding2:2;
unsigned targetable:1;
unsigned targetcyclable:1;
unsigned padding1:2;
unsigned trader:1;
unsigned buyer:1;
};
int32_t miscData;
};
/*0000*/ uint8_t otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable
/*0000*/ uint32_t race;
/*0000*/ uint8_t charProperties;
/*0000*/ uint32_t bodytype;
/*0000*/ uint32_t bodytype2;
/*0000*/ uint8_t curHp;
/*0000*/ uint8_t holding;
/*0000*/ uint32_t deity;
/*0000*/ uint32_t guildID;
/*0000*/ uint32_t guildstatus; // 0=member, 1=officer, 2=leader, -1=not guilded
/*0000*/ uint8_t class_;
/*0000*/ uint8_t state; // stand state
/*0000*/ uint8_t light;
/*0000*/ char lastName[32];
/*0000*/ uint32_t petOwnerId;
union
{
struct
{
unsigned pitch:12;
signed z:19; // z coord
unsigned padding01:1;
signed deltaX:13; // change in x
signed y:19; // y coord
signed deltaHeading:10;// change in heading
unsigned heading:12; // heading
signed animation:10; // velocity
signed deltaZ:13; // change in z
signed x:19; // x coord
signed deltaY:13; // change in y
unsigned padding02:19;
};
int32_t posData[5];
};
/*0000*/ union
{
struct
{
/*0000*/ Color_Struct color_helmet; // Color of helmet item
/*0000*/ Color_Struct color_chest; // Color of chest item
/*0000*/ Color_Struct color_arms; // Color of arms item
/*0000*/ Color_Struct color_bracers; // Color of bracers item
/*0000*/ Color_Struct color_hands; // Color of hands item
/*0000*/ Color_Struct color_legs; // Color of legs item
/*0000*/ Color_Struct color_feet; // Color of feet item
/*0000*/ Color_Struct color_primary; // Color of primary item
/*0000*/ Color_Struct color_secondary; // Color of secondary item
} equipment_colors;
/*0000*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above
};
/*0000*/ union
{
struct
{
/*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual
/*0000*/ EquipStruct equip_chest; // Equipment: Chest visual
/*0000*/ EquipStruct equip_arms; // Equipment: Arms visual
/*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual
/*0000*/ EquipStruct equip_hands; // Equipment: Hands visual
/*0000*/ EquipStruct equip_legs; // Equipment: Legs visual
/*0000*/ EquipStruct equip_feet; // Equipment: Boots visual
/*0000*/ EquipStruct equip_primary; // Equipment: Main visual
/*0000*/ EquipStruct equip_secondary; // Equipment: Off visual
} equip;
/*0000*/ EquipStruct equipment[9];
};
/*0000*/ char title[32];
/*0000*/ char suffix[32];
/*0000*/ uint8_t isMercenary;
};

#if 0
// Basic structure of how the packet looks on the wire, for reference.
// March 16, 2012 eqgame.exe
struct spawnStruct
{
/*0000*/ char name[0];
/*0000*/ uint32_t spawnId;
/*0000*/ uint8_t level;
/*0000*/ float unknown1;
/*0000*/ uint8_t NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse
/*0000*/ unsigned padding7:1;
unsigned AFK:1;
unsigned sneak:1;
unsigned LFG:1;
unsigned padding6:1;
unsigned invis:1;
unsigned padding5:11;
unsigned gm:1;
unsigned anon:1; // 0=normal, 1=anon, 2=roleplay
unsigned padding4:1;
unsigned gender:1; // Gender (0=male, 1=female)
unsigned padding3:1;
unsigned linkdead:1;
unsigned betabuffed:1;
unsigned padding2:2;
unsigned targetable:1;
unsigned targetcyclable:1;
unsigned padding1:2;
unsigned trader:1;
unsigned buyer:1;
/*0000*/ uint8_t otherData; // & 8 - has title, & 16 - has suffix, & 2 - auras, & 1 - it's a chest or untargetable
/*0000*/ uint32_t unknown3;
/*0000*/ uint32_t unknown4;
/*0000*/ uint32_t unknown5;
/*0000*/ uint8_t facestyle;
/*0000*/ float walkspeed;
/*0000*/ float runspeed;
/*0000*/ uint32_t race;
/*0000*/ uint8_t charProperties; // for body types - value indicates how many properties are present
/*0000*/ uint32_t bodytype;
/*0000*/ uint32_t bodytype2; // this is only present if charProperties==2
// are there more than two possible properties?
/*0000*/ uint8_t curHp;
/*0000*/ uint8_t haircolor;
/*0000*/ uint8_t facialhaircolor;
/*0000*/ uint8_t eyecolor1;
/*0000*/ uint8_t eyecolor2;
/*0000*/ uint8_t hairstyle;
/*0000*/ uint8_t facialhair;
/*0000*/ uint32_t heritage;
/*0000*/ uint32_t tattoo;
/*0000*/ uint32_t details;
/*0000*/ uint8_t holding;
/*0000*/ uint32_t deity;
/*0000*/ uint32_t guildID;
/*0000*/ uint32_t guildstatus; // 0=member, 1=officer, 2=leader, -1=not guilded
/*0000*/ uint8_t class_;
/*0000*/ uint8_t PVP;
/*0000*/ uint8_t state; // stand state
/*0000*/ uint8_t light;
/*0000*/ uint8_t unknown7;
/*0000*/ uint8_t unknown8;
/*0000*/ uint8_t unknown9;
/*0000*/ uint8_t unknown10;
/*0000*/ uint8_t unknown11;
/*0000*/ char lastName[0];
/*0000*/ uint32_t AARank;
/*0000*/ uint8_t unknown12;
/*0000*/ uint32_t petOwnerId;
/*0000*/ uint8_t unknown13;
/*0000*/ uint32_t unknown14;
/*0000*/ uint32_t unknown15;
/*0000*/ uint32_t unknown16;
/*0000*/ uint32_t unknown17;
/*0000*/ uint32_t unknown18;
/*0000*/ uint32_t unknown19;
/*0000*/ signed padding0000:12; // ***Placeholder
signed deltaX:13; // change in x
signed padding0005:7; // ***Placeholder
/*0000*/ signed deltaHeading:10; // change in heading
signed deltaY:13; // change in y
signed padding0006:9; // ***Placeholder
/*0000*/ signed y:19; // y coord
signed animation:13; // animation
/*0000*/ unsigned heading:12; // heading
signed x:19; // x coord
signed padding0014:1; // ***Placeholder
/*0000*/ signed z:19; // z coord
signed deltaZ:13; // change in z
// If not a valid player race (skip these if a valid player race)
/*0000*/ union
{
struct
{
/*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual (maybe)
/*0000*/ EquipStruct equip_primary; // Equipment: Main visual
/*0000*/ EquipStruct equip_secondary; // Equipment: Off visual
} equip;
/*0000*/ EquipStruct equipment[3];
};
// skip these bytes if not a valid player race - colors[9] and equipment[9]
/*0000*/ union
{
struct
{
/*0000*/ Color_Struct color_helmet; // Color of helmet item
/*0000*/ Color_Struct color_chest; // Color of chest item
/*0000*/ Color_Struct color_arms; // Color of arms item
/*0000*/ Color_Struct color_bracers; // Color of bracers item
/*0000*/ Color_Struct color_hands; // Color of hands item
/*0000*/ Color_Struct color_legs; // Color of legs item
/*0000*/ Color_Struct color_feet; // Color of feet item
/*0000*/ Color_Struct color_primary; // Color of primary item
/*0000*/ Color_Struct color_secondary; // Color of secondary item
} equipment_colors;
/*0000*/ Color_Struct colors[9]; // Array elements correspond to struct equipment_colors above
}
/*0000*/ union
{
struct
{
/*0000*/ EquipStruct equip_helmet; // Equipment: Helmet visual
/*0000*/ EquipStruct equip_chest; // Equipment: Chest visual
/*0000*/ EquipStruct equip_arms; // Equipment: Arms visual
/*0000*/ EquipStruct equip_bracers; // Equipment: Wrist visual
/*0000*/ EquipStruct equip_hands; // Equipment: Hands visual
/*0000*/ EquipStruct equip_legs; // Equipment: Legs visual
/*0000*/ EquipStruct equip_feet; // Equipment: Boots visual
/*0000*/ EquipStruct equip_primary; // Equipment: Main visual
/*0000*/ EquipStruct equip_secondary; // Equipment: Off visual
} equip;
/*0000*/ EquipStruct equipment[9];
};
/*0000*/ char title[0]; // only read if(otherData & 8)
/*0000*/ char suffix[0]; // only read if(otherData & 16)
/*0000*/ char unknown20[8];
/*0000*/ uint8_t isMercenary;
/*0000*/ char unknown21[54];
};
#endif


#if 0
// Old stuff from spawnStruct seq doesn't actually use at all..
//
/*0004*/ float size; // Model size
/*0078*/ int8_t aa_title; // 0=none, 1=general, 2=archtype, 3=class
/*0074*/ uint8_t invis; // Invis (0=not, 1=invis)
/*0117*/ uint8_t lfg; // 0=off, 1=lfg on
/*0196*/ uint8_t afk; // 0=no, 1=afk
/*0207*/ int8_t guildrank; // 0=normal, 1=officer, 2=leader
/*0213*/ uint8_t face; // Face id for players
/*0247*/ uint8_t is_pet; // 0=no, 1=yes
/*0284*/ uint8_t beardcolor; // Beard color
/*0500*/ uint8_t showhelm; // 0=no, 1=yes
/*0501*/ uint8_t helm; // Helm texture
/*0660*/ uint8_t hairstyle; // Hair style
/*0090*/ uint8_t eyecolor1; // Player's left eye color
/*0542*/ uint8_t eyecolor2; // Left eye color
/*0547*/ uint8_t haircolor; // Hair color
/*0574*/ uint8_t is_npc; // 0=no, 1=yes
/*0575*/ uint8_t findable; // 0=can't be found, 1=can be found
/*0728*/ uint8_t beard; // Beard style (not totally, sure but maybe!)
/*0723*/ uint8_t max_hp; // (name prolly wrong)takes on the value 100 for PCs, 100 or 110 for NPCs and 120 for PC corpses...
/*122*/ uint8_t pvp; // 0=Not pvp,1=pvp
union
{
/*0091*/ int8_t equip_chest2; // Second place in packet for chest texture (usually 0xFF in live packets)
// Not sure why there are 2 of them, but it effects chest texture!
/*0091*/ int8_t mount_color; // drogmor: 0=white, 1=black, 2=green, 3=red
};
#endif

/*
** Server Zone Entry struct
** Length: 383 Octets
** OpCode: ZoneEntryCode (when direction == server)
*
* This is just a spawnStruct for the player
*/
struct ServerZoneEntryStruct : public spawnStruct
{
};

/*
** Generic Door Struct
** Length: 96 Octets
** Used in:
** OP_SpawnDoor
**
*/

struct doorStruct
{
/*0000*/ char name[32]; // Filename of Door?
/*0016*/ // uint8_t unknown016[16]; // ***Placeholder
/*0032*/ float y; // y loc
/*0036*/ float x; // x loc
/*0040*/ float z; // z loc
/*0044*/ float heading; // heading
/*0048*/ uint32_t incline; // incline
/*0052*/ uint32_t size; // size
/*0056*/ uint8_t unknown0056[4]; // ***Placeholder
/*0060*/ uint8_t doorId; // door's id #
/*0061*/ uint8_t opentype; // open type
/*0062*/ uint8_t spawnstate; // spawn state
/*0063*/ uint8_t invertstate; // invert state
/*0064*/ uint32_t zonePoint;
/*0068*/ uint8_t unknown068[28]; // ***Placeholder
/*0096*/
};

/*
** Drop Item On Ground
** Length: Variable
** OpCode: MakeDropCode
*/
// Note: Unknowns and other members removed that we don't use since we
// now only fill this with data we need from the serialized packet
struct makeDropStruct
{
uint32_t dropId; // DropID
float heading; // Heading
float z; // Z Position
float x; // X Position
float y; // Y Position
char idFile[30]; // ACTOR ID - The client reads 30 bytes from the packet
// - 20100210 eqgame.exe in EQItemList::UnpackNetData
};

/*
** ZonePoint
** Length: 24 Octets
** Sent as part of zonePointsStruct
*/

struct zonePointStruct
{
/*0000*/ uint32_t zoneTrigger;
/*0004*/ float y;
/*0008*/ float x;
/*0012*/ float z;
/*0016*/ float heading;
/*0020*/ uint16_t zoneId;
/*0022*/ uint16_t zoneInstance;
/*0024*/
};

/*
** ZonePointsStruct
** Length: Variable
** OPCode: OP_SendZonePoints
*/
struct zonePointsStruct
{
/*0000*/ uint32_t count;
/*0004*/ zonePointStruct zonePoints[0];
/*0xxx*/ uint8_t unknown0xxx[24];
/*0yyy*/
};

/*
** Time of Day
** Length: 8 Octets
** OpCode: TimeOfDayCode
*/
struct timeOfDayStruct
{
/*0000*/ uint8_t hour; // Hour (1-24)
/*0001*/ uint8_t minute; // Minute (0-59)
/*0002*/ uint8_t day; // Day (1-28)
/*0003*/ uint8_t month; // Month (1-12)
/*0004*/ uint16_t year; // Year
/*0006*/ uint16_t unknown0016; // Placeholder
/*0008*/
};

/*
** Item Packet Struct - Works on a variety of item operations
** Packet Types: See ItemPacketType enum
** Length: Variable
** OpCode: ItemCode
*/
struct itemPacketStruct
{
/*000*/ ItemPacketType packetType; // See ItemPacketType for more info.
/*004*/ char serializedItem[0];
/*xx*/
};

/*
** Item Info Request Struct
** Length: 72 Octets
** OpCode: ItemInfoCode
*/
struct itemInfoReqStruct
{
/*000*/ uint32_t itemNr; // ItemNr
/*005*/ uint32_t requestSeq; // Request sequence number
/*008*/ char name[64]; // Item name
/*072*/
};

/*
** Item Info Response Struct
** Length: Variable
** OpCode: ItemInfoCode
*/
struct itemInfoStruct
{
/*000*/ uint32_t requestSeq; // Corresponds to sequence # in req
/*004*/ char serializedItem[0];
/*xxx*/
};

/*
** Simple Spawn Update
** Length: 14 Octets
** OpCode: MobUpdateCode
*/


struct spawnPositionUpdate
{
/*0000*/ int16_t spawnId;
/*0002*/ uint8_t unk1[2]; // BSH 13 Apr 2011
/*0004*/ int64_t y:19, z:19, u3:7,x:19;
unsigned heading:12;
signed unused2:4;
/*0014*/
};

/*
** Rename a spawn
** Length: 232 Octets
** OpCode: SpawnRename
*/
struct spawnRenameStruct
{
/*000*/ char old_name[64];
/*064*/ char old_name_again[64]; //not sure what the difference is
/*128*/ char new_name[64];
/*192*/ uint32_t unknown192; //set to 0
/*196*/ uint32_t unknown196; //set to 1
/*200*/ uint8_t unknown0084[32]; // ***Placeholder
/*232*/
};

/*
** Illusion a spawn
** Length: 336 Octets
** OpCode: Illusion
*/
struct spawnIllusionStruct
{
/*0000*/ uint32_t spawnId; // Spawn id of the target
/*0004*/ char name[64]; // Name of the target
/*0068*/ uint32_t race; // New race
/*0072*/ uint8_t gender; // New gender (0=male, 1=female)
/*0073*/ uint8_t texture; // ???
/*0074*/ uint8_t helm; // ???
/*0075*/ uint8_t unknown0075; // ***Placeholder
/*0076*/ uint32_t unknown0076; // ***Placeholder
/*0080*/ uint32_t face; // New face
/*0084*/ uint8_t unknown0084[252]; // ***Placeholder
/*0336*/
};

/**
* Shroud spawn. For others shrouding, this has their spawnId and
* spawnStruct.
*
* Length: variable
* OpCode: OP_Shroud
*/
struct spawnShroudOther
{
/*00000*/ uint32_t spawnId; // Spawn Id of the shrouded player
/*00004*/ uint16_t spawnStructSize; // Size of spawnStruct (or start of)
/*00006*/ spawnStruct spawn; // Updated spawn struct for the player (variable length)
/*xxxxx*/
};

/**
* Shroud yourself. For yourself shrouding, this has your spawnId, spawnStruct,
* bits of your charProfileStruct (no checksum, then charProfile up till
* but not including name), and an itemPlayerPacket for only items on the player
* and not the bank.
*
* Length: Variable
* OpCode: OP_Shroud
*/
struct spawnShroudSelf
{
/*00000*/ uint32_t spawnId; // Spawn Id of you
/*00004*/ uint16_t ppStart; // Start of playerProfile data (spawnId+ppStart+spawnStruct)
/*00004*/ spawnStruct spawn; // Updated spawnStruct for you (variable length)
/*xxxxx*/ playerProfileStruct profile; // Character profile for shrouded char
/*xxxxx*/ uint8_t items; // Items on the player
/*xxxxx*/
};

/*
** Campfire spawn
** Length: 997
** OpCode: OP_ZoneEntry
*/
struct spawnCampfire
{
/*0000*/ spawnStruct spawn;
/*0532*/ uint8_t unknown0532[465];
/*0997*/
};


/*
** ShowEQ Specific Structures
*/

/*
** DB spawn struct (adds zone spawn was in)
*/

struct dbSpawnStruct
{
/*0000*/ struct spawnStruct spawn; // Spawn Information
/*0258*/ char zoneName[40]; // Zone Information
};

/*
** Pet spawn struct (pets pet and owner in one struct)
*/

struct petStruct
{
/*0000*/ struct spawnStruct owner; // Pet Owner Information
/*0258*/ struct spawnStruct pet; // Pet Infromation
};

/*
** Server System Message
** Length: Variable Length
** OpCode: SysMsgCode
*/

struct sysMsgStruct
{
/*0000*/ char message[0]; // Variable length message
};

/*
** Emote text
** Length: Variable Text
** OpCode: emoteTextCode
*/

struct emoteTextStruct
{
/*0000*/ uint8_t unknown0002[4]; // ***Placeholder
/*0002*/ char text[0]; // Emote `Text
};

/*
** Channel Message received or sent
** Length: Variable
** OpCode: ChannelMessageCode

This is how channelMessageStruct looks on the wire, for reference (8/12/09 eqgame.exe)

char sender[0]; // Variable length senders name
char target[0]; // Variable length target characters name
uint32_t unknown;
uint32_t language; // Language
uint32_t chanNum; // Channel
uint32_t unknown;
uint8_t unknown;
uint32_t skillInLanguage; // senders skill in language
char message[0]; // Variable length message
uint8_t unknown;
uint32_t unknown;
uint32_t unknown;
char unknown[0]; // Variable legth unknown text
uint8_t unknown;
uint32_t unknown;

*/

// This will get filled with data from the serialized packet
struct channelMessageStruct
{
/*0000*/ char sender[64];
/*0064*/ char target[64];
/*0128*/ uint32_t language;
/*0132*/ uint32_t chanNum;
/*0144*/ uint32_t skillInLanguage;
/*0148*/ char message[2048]; // Maximum message size according to eqgame.exe
};

/*
** Formatted text messages
** Length: Variable Text
** OpCode: emoteTextCode
*/

struct formattedMessageStruct
{
/*0000*/ uint8_t unknown0002[4]; // ***Placeholder
/*0004*/ uint32_t messageFormat; // Indicates the message format
/*0008*/ ChatColor messageColor; // Message color
/*0012*/ char messages[0]; // messages(NULL delimited)
/*0???*/ uint8_t unknownXXXX[8]; // ***Placeholder
};

/*
** Simple text messages
** Length: 12 Octets
** OpCode: SimpleMessageCode
*/

struct simpleMessageStruct
{
/*0000*/ uint32_t messageFormat; // Indicates the message format
/*0004*/ ChatColor messageColor; // Message color
/*0008*/ uint32_t unknown; // ***Placeholder
/*0012*/
};

/*
** Special Message Struct
** Length: Variable Text
** OPCode: OP_SpecialMesg
*/

struct specialMessageStruct
{
/*0000*/ uint8_t unknown0000[3]; // message style?
/*0003*/ ChatColor messageColor; // message color
/*0007*/ uint16_t target; // message target
/*0009*/ uint16_t padding; // padding
/*0011*/ char source[0]; // message text
/*0xxx*/ uint32_t unknown0xxx[3]; //***Placeholder
/*0yyy*/ char message[0]; // message text
};

/*
** Guild MOTD Struct
** Length: Variable Text
** OPCode: OP_GuildMOTD
*/
struct guildMOTDStruct
{
/*0000*/ uint32_t unknown0000; //***Placeholder
/*0004*/ char target[64]; // motd target
/*0068*/ char sender[64]; // motd "sender" (who set it)
/*0132*/ uint32_t unknown0132; //***Placeholder
/*0136*/ char message[0];
};

/*
** Corpse location
** Length: 18 Octets
** OpCode: corpseLocCode
*/

struct corpseLocStruct
{
/*0000*/ uint32_t spawnId;
/*0004*/ float x;
/*0008*/ float y;
/*0012*/ float z;
/*0018*/
};

/*
** Consent request
** Length: Variable by length of the name of the consentee
*/

struct consentRequestStruct
{
/*0000*/ char consentee[0]; // Name of player who was consented
};

/*
** Consent Response
** Length: 193 Octets
*/

struct consentResponseStruct
{
/*0000*/ char consentee[64]; // Name of player who was consented
/*0064*/ char consenter[64]; // Name of player who consented
/*0128*/ uint8_t allow; // 00 = deny, 01 = allow
/*0129*/ char corpseZoneName[64]; // Zone where the corpse is
/*0193*/
};

/*
** Grouping Information
** Length: 456 Octets
** OpCode: OP_GroupUpdate
*/

struct groupUpdateStruct
{
/*0000*/ int32_t action; // Group update action
/*0004*/ char yourname[64]; // Group Member Names
/*0068*/ char membername[64]; // Group leader name
/*0132*/ uint8_t unknown0132[324]; // ***Placeholder
/*456*/
};


/*
** DEPRECATED
** Grouping Information
** Length: 768 Octets
** OpCode: OP_GroupUpdate
*/

struct groupFullUpdateStruct
{
/*0000*/ int32_t action;
/*0004*/ char membernames[MAX_GROUP_MEMBERS][64]; // Group Member Names
/*0388*/ char leader[64]; // Group leader Name
/*0452*/ char unknown0452[316]; // ***Placeholder
/*0768*/
};

/*
** Grouping Invite
** Length 148 Octets (invite a player) or 152 (you get invited)
** Opcode OP_GroupInvite
*/

struct groupInviteStruct
{
/*0000*/ char invitee[64]; // Invitee's Name
/*0064*/ char inviter[64]; // Inviter's Name
/*0128*/ uint8_t unknown0128[24]; // ***Placeholder
/*0152*/
};

/*
** Grouping Invite Answer - Decline
** Length 152 Octets
** Opcode GroupDeclineCode
*/

struct groupDeclineStruct
{
/*0000*/ char yourname[64]; // Player Name
/*0064*/ char membername[64]; // Invited Member Name
/*0128*/ uint8_t unknown0128[20]; // ***Placeholder
/*0148*/ uint8_t reason; // Already in Group = 1, Declined Invite = 3
/*0149*/ uint8_t unknown0141[3]; // ***Placeholder
/*0152*/
};

/*
** Grouping Invite Answer - Accept
** Length 148 Octets
** Opcode OP_GroupFollow
*/

struct groupFollowStruct
{
/*0000*/ char unknown0000[64]; // ***Placeholder (zeros)
/*0064*/ char invitee[64]; // Invitee's Member Name
/*0128*/ uint8_t unknown0132[4]; // ***Placeholder
/*0132*/ uint32_t level; // Invitee's level
/*0136*/ uint8_t unknown0136[12]; // ***Placeholder (zeros)
/*0148*/
};

/*
** Group Disbanding
** Length 148 Octets
** Opcode
*/

struct groupDisbandStruct
{
/*0000*/ char yourname[64]; // Player Name
/*0064*/ char membername[64]; // Invited Member Name
/*0128*/ uint8_t unknown0128[20]; // ***Placeholder
/*0148*/
};

/*
** Group Leader Change
** Length 148 Octets
** Opcode OP_GroupLeader
*/

struct groupLeaderChangeStruct
{
/*0000*/ char unknown0000[64]; // ***Placeholder
/*0064*/ char membername[64]; // Invited Member Name
/*0128*/ uint8_t unknown0128[20]; // ***Placeholder
/*0148*/
};

/*
** Delete Self
** Length: 4 Octets
** OpCode: OP_DeleteSpawn
*/

struct deleteSpawnStruct
{
/*0000*/ uint32_t spawnId; // Spawn ID to delete
/*0004*/
};

/*
** Remove Spawn
** Length: 5 Octets
** OpCode: OP_RemoveSpawn
*/

struct removeSpawnStruct
{
/*0000*/ uint32_t spawnId; // Spawn ID to delete
/*0004*/ uint8_t removeSpawn; // 0 if spawn is not in your update radius
/*0005*/
};

/*
** Remove Drop Item On Ground
** Length: 8 Octets
** OpCode: RemDropCode
*/

struct remDropStruct
{
/*0000*/ uint16_t dropId; // ID assigned to drop
/*0002*/ uint8_t unknown0004[2]; // ***Placeholder
/*0004*/ uint16_t spawnId; // ID of player picking item up
/*0006*/ uint8_t unknown0008[2]; // ***Placeholder
/*0008*/
};

/*
** Consider Struct
** Length: 20 Octets
** OpCode: considerCode
*/

struct considerStruct
{
/*0000*/ uint32_t playerid; // PlayerID
/*0004*/ uint32_t targetid; // TargetID
/*0008*/ int32_t faction; // Faction
/*0012*/ int32_t level; // Level
/*0016*/ int32_t unknown0016; // unknown
/*0020*/
};

/*
** Spell Casted On
** Length: 36 Octets
** OpCode: castOnCode
*/

struct castOnStruct
{
/*0000*/ uint16_t targetId; // Target ID
/*0002*/ uint8_t unknown0002[2]; // ***Placeholder
/*0004*/ int16_t sourceId; // ***Source ID
/*0006*/ uint8_t unknown0006[2]; // ***Placeholder
/*0008*/ uint8_t unknown0008[24]; // might be some spell info?
/*0032*/ uint16_t spellId; // Spell Id
/*0034*/ uint8_t unknown0034[2]; // ***Placeholder
/*0036*/
};

/*
** Spawn Death Blow
** Length: 32 Octets
** OpCode: NewCorpseCode
*/

struct newCorpseStruct
{
/*0000*/ uint32_t spawnId; // Id of spawn that died
/*0004*/ uint32_t killerId; // Killer
/*0008*/ uint32_t corpseid; // corpses id
/*0012*/ int32_t type; // corpse type?
/*0016*/ uint32_t spellId; // ID of Spell
/*0020*/ uint16_t zoneId; // Bind zone id
/*0022*/ uint16_t zoneInstance; // Bind zone instance
/*0024*/ uint32_t damage; // Damage
/*0028*/ uint8_t unknown0028[4]; // ***Placeholder
/*0032*/
};

/**
** Environmental damage (lava, falls)
** Length: 39 Octets
*/

struct environmentDamageStruct
{
/*0000*/ uint32_t spawnId; // Who is taking the damage
/*0004*/ uint8_t unknown0004[2];
/*0006*/ uint32_t damage; // how much damage?
/*0010*/ uint8_t unknown0010[12];
/*0022*/ uint8_t type; // Damage type. FC = fall. FA = lava.
/*0023*/ uint8_t unknown0023[16];
/*0039*/
};

/*
** Money Loot
** Length: 20 Octets
** OpCode: MoneyOnCorpseCode
*/

struct moneyOnCorpseStruct
{
/*0000*/ uint8_t unknown0002[4]; // ***Placeholder
/*0004*/ uint32_t platinum; // Platinum Pieces
/*0008*/ uint32_t gold; // Gold Pieces
/*0012*/ uint32_t silver; // Silver Pieces
/*0016*/ uint32_t copper; // Copper Pieces
/*0020*/
};

/*
** Stamina
** Length: 8 Octets
** OpCode: staminaCode
*/

struct staminaStruct
{
/*0000*/ uint32_t food; // Hunger, in ticks till next eat
/*0004*/ uint32_t water; // Thirst, in ticks till next eat
/*0008*/
};

/*
** Battle Code
** Length: 30 Octets
** OpCode: ActionCode
*/

// This can be used to gather info on spells cast on us
struct action2Struct
{
/*0000*/ uint16_t target; // Target ID
/*0002*/ uint16_t source; // Source ID
/*0004*/ uint8_t type; // Bash, kick, cast, etc.
/*0005*/ int16_t spell; // SpellID
/*0007*/ int32_t damage;
/*0011*/ uint8_t unknown0011[13]; // ***Placeholder
/*0024*/ uint8_t unknown0024[6]; // ***Placeholder (11/24/07)
/*0030*/
};

// This can be used to gather info on spells cast on us
struct actionStruct
{
/*0000*/ uint16_t target; // Target ID
/*0002*/ uint16_t source; // SourceID
/*0004*/ uint8_t level; // Caster level
/*0005*/ uint8_t unknown0005[21]; // ***Placeholder
/*0026*/ uint8_t type; // Casts, Falls, Bashes, etc...
/*0027*/ uint8_t unknown0031[6];
/*0033*/ int16_t spell; // SpellID
/*0035*/ uint8_t unknown0035[2]; // ***Placeholder
/*0037*/ uint8_t unknown0037[2]; // ***Placeholder
/*0039*/
};

// Starting with 2/21/2006, OP_Actions seem to come in pairs, duplicating
// themselves, with the second one with slightly more information. Maybe this
// has to do with buff blocking??
struct actionAltStruct
{
/*0000*/ uint16_t target; // Target ID
/*0002*/ uint16_t source; // SourceID
/*0004*/ uint8_t level; // Caster level
/*0005*/ uint8_t unknown0005[21]; // ***Placeholder
/*0026*/ uint8_t type; // Casts, Falls, Bashes, etc...
/*0027*/ uint8_t unknown0031[6];
/*0033*/ int16_t spell; // SpellID
/*0035*/ uint8_t unknown0035[2]; // ***Placeholder
/*0037*/ uint32_t unknown0037;
/*0041*/ uint8_t unknown0041[15];
/*0056*/
};

/*
** client changes target struct
** Length: 4 Octets
** OpCode: clientTargetCode
*/

struct clientTargetStruct
{
/*0000*/ uint32_t newTarget; // Target ID
/*0004*/
};

/*
** Info sent when you start to cast a spell
** Length: 44 Octets
** OpCode: StartCastCode
*/

struct startCastStruct
{
/*0000*/ int32_t slot; // Spell slot
/*0004*/ uint32_t spellId; // Spell ID
/*0008*/ int32_t inventorySlot; // ***Placeholder
/*0012*/ uint8_t unknown0012[8]; // ***Placeholder
/*0020*/ uint32_t targetId; // The current selected target
/*0024*/ uint8_t unknown0024[4]; // ***Placeholder
/*0028*/ uint8_t unknown0028[16]; // ***Placeholder (4/7/2009)
/*0044*/
};

/*
** New Mana Amount
** Length: 20 Octets
** OpCode: manaDecrementCode
*/

struct manaDecrementStruct
{
/*0000*/ int32_t newMana; // New Mana AMount
/*0004*/ int32_t unknown; // Looks like endurance but not sure why that'd be reported here
/*0008*/ int32_t spellId; // Last Spell Cast
/*0012*/ uint8_t unknown0012[4];
/*0016*/ uint8_t unknown0016[4]; //*** Placeholder (02/13/07)
/*0020*/
};

/*
** Special Message
** Length: 4 Octets + Variable Text Length
** OpCode: SPMesgCode
*/
struct spMesgStruct
{
/*0000*/ int32_t msgType; // Type of message
/*0004*/ char message[0]; // Message, followed by four Octets?
};

/*
** Spell Fade Struct
** Length: Variable length
** OpCode: SpellFadedCode
*/
struct spellFadedStruct
{
/*0000*/ uint32_t color; // color of the spell fade message
/*0004*/ char message[0]; // fade message
/*0???*/ uint8_t paddingXXX[3]; // always 0's
};

/*
** Spell Action Struct
** Length: 10 Octets
** OpCode: BeginCastCode
*/
struct beginCastStruct
{
/*0000*/ uint16_t spellId; // Id of spell
/*0002*/ int16_t param2; // Paramater 1
/*0004*/ uint16_t spawnId; // Id of who is casting
/*0006*/ int16_t param1; // Paramater 2
/*0008*/ int16_t param3; // Paramater 3
/*0010*/
};

/*
** Spell Action Struct
** Length: 16 Octets
** OpCode: MemSpellCode
*/

struct memSpellStruct
{
/*0000*/ uint32_t slotId; // Slot spell is being memorized in
/*0004*/ uint32_t spellId; // Id of spell
/*0008*/ int16_t param1; // Paramater 1
/*0010*/ int16_t param2; // Paramater 2
/*0012*/ uint8_t unknown0012[4]; // *** Placeholder
/*0016*/
};

/*
** Train Skill
** Length: 12 Octets
** OpCode: SkillTrainCode
*/

struct skillTrainStruct
{
/*0000*/ int32_t playerid; // player doing the training
/*0004*/ int32_t type; // type of training?
/*0008*/ uint32_t skillId; // Id of skill
/*0012*/
};

/*
** Skill Increment
** Length: 12 Octets
** OpCode: SkillIncCode
*/

struct skillIncStruct
{
/*0000*/ uint32_t skillId; // Id of skill
/*0004*/ int32_t value; // New value of skill
/*0008*/ uint8_t unknown0008[4]; // *** Placeholder
/*0012*/
};

/*
** When somebody changes what they're wearing
** or give a pet a weapon (model changes)
** Length: 14 Octets
** Opcode: WearChangeCode
*/

// ZBTEMP: Find newItemID ***
struct wearChangeStruct
{
/*0000*/ uint16_t spawnId; // SpawnID
/*0002*/ Color_Struct color; // item color
/*0006*/ uint8_t wearSlotId; // Slot ID
/*0007*/ uint8_t unknown0007[7]; // unknown
/*0014*/
};

/*
** Level Update
** Length: 12 Octets
** OpCode: LevelUpUpdateCode
*/

struct levelUpUpdateStruct
{
/*0000*/ uint32_t level; // New level
/*0004*/ uint32_t levelOld; // Old level
/*0008*/ uint32_t exp; // Current Experience
/*0012*/
};

/*
** Experience Update
** Length: 8 Octets
** OpCode: ExpUpdateCode
*/

struct expUpdateStruct
{
/*0000*/ uint32_t exp; // experience value x/330
/*0004*/ uint32_t type; // 0=set, 2=update
/*0008*/
};

/*
** Alternate Experience Update
** Length: 12 Octets
** OpCode: AltExpUpdateCode
*/
struct altExpUpdateStruct
{
/*0000*/ uint32_t altexp; // alt exp x/330
/*0004*/ uint32_t aapoints; // current number of AA points
/*0008*/ uint8_t percent; // percentage in integer form
/*0009*/ uint8_t unknown0009[3]; // ***Place Holder
/*0012*/
};

/**
* Leadership AA update
* Length: 32 Octets
* OpCode: LeadExpUpdate
*/
struct leadExpUpdateStruct
{
/*0000*/ uint32_t unknown0000; // All zeroes?
/*0004*/ uint32_t groupLeadExp; // Group leadership exp value
/*0008*/ uint32_t unspentGroupPoints; // Unspent group points
/*0012*/ uint32_t unknown0012; // Type?
/*0016*/ uint32_t unknown0016; // All zeroes?
/*0020*/ uint32_t raidLeadExp; // Raid leadership exp value
/*0024*/ uint32_t unspentRaidPoints; // Unspent raid points
/*0028*/ uint32_t unknown0028;
/*0032*/
};

/*
** Player Spawn Update
** Length: 27 Octets
** OpCode: SpawnUpdateCode
*/

struct SpawnUpdateStruct
{
/*0000*/ uint16_t spawnId; // Id of spawn to update
/*0002*/ uint16_t subcommand; // some sort of subcommand type
/*0004*/ int16_t arg1; // first option
/*0006*/ int16_t arg2; // second option
/*0008*/ uint8_t arg3; // third option?
/*0009*/ uint8_t unknown0009[18];
/*0027*/
};

/*
** NPC Hp Update
** Length: 10 Octets
** Opcode NpcHpUpdateCode
*/

struct hpNpcUpdateStruct
{
/*0000*/ uint16_t spawnId;
/*0002*/ int32_t curHP;
/*0006*/ int32_t maxHP;
/*0010*/
};

/*
** Inspecting Information
** Length: 1860 Octets
** OpCode: InspectDataCode
*/

struct inspectDataStruct
{
/*0000*/ uint8_t unknown0000[8]; // ***Placeholder
/*0008*/ char itemNames[23][64]; // 23 items with names
// 64 characters long.
/*1480*/ int32_t icons[23]; // Icon Information
/*1572*/ char mytext[200]; // Player Defined Text Info
/*1772*/ uint8_t unknown1772[88]; // ***Placeholder
/*1860*/
};

/*
** Reading Book Information
** Length: Variable Length Octets
** OpCode: BookTextCode
*/

struct bookTextStruct
{
/*0000*/ uint16_t unknown0000;
/*0002*/ char text[0]; // Text of item reading
};

/*
** Interrupt Casting
** Length: 6 Octets + Variable Length Octets
** Opcode: BadCastCode
*/

struct badCastStruct
{
/*0000*/ uint32_t spawnId; // Id of who is casting
/*0004*/ char message[0]; // Text Message
};

/*
** Random Number Request
** Length: 8 Octets
** OpCode: RandomCode
*/
struct randomReqStruct
{
/*0000*/ uint32_t bottom; // Low number
/*0004*/ uint32_t top; // High number
/*0008*/
};

/*
** Random Number Result
** Length: 76 Octets
** OpCode: RandomCode
*/
struct randomStruct
{
/*0000*/ uint32_t bottom; // Low number
/*0004*/ uint32_t top; // High number
/*0008*/ uint32_t result; // result number
/*0012*/ char name[64]; // name rolled by
/*0076*/
};

/*
** Player Position Update
** Length: 24 Octets
** OpCode: PlayerPosCode
*/

struct playerSpawnPosStruct
{
/*0000*/ uint16_t spawnId;
/*0002*/ uint16_t spawnId2;
/*0004*/ unsigned pitch:12;
signed z:19; // z coord
unsigned padding01:1;
/*0008*/ signed deltaX:13; // change in x
signed y:19; // y coord
/*0012*/ signed deltaHeading:10;// change in heading
unsigned heading:12; // heading
signed animation:10; // velocity
/*0016*/ signed deltaZ:13; // change in z
signed x:19; // x coord
/*0020*/ signed deltaY:13; // change in y
unsigned padding02:19;
/*0024*/
};

/*
** Self Position Update
** Length: 42 Octets
** OpCode: PlayerPosCode
*/

struct playerSelfPosStruct
{
/*0000*/ uint16_t unknown0000; // ***Placeholder (update time counter?)
/*0002*/ uint16_t spawnId; // Player's spawn id
/*0004*/ uint16_t unknown0004; // ***Placeholder
/*0006*/ unsigned pitch:12; // pitch (up/down heading)
signed animation:10; // velocity
unsigned padding1:10; // ***Placeholder
/*0010*/ float x; // x coord (1st loc value)
/*0014*/ float deltaX; // Change in y
/*0018*/ float y; // y coord (2nd loc value)
/*0022*/ float z; // z coord (3rd loc value)
/*0026*/ float deltaY; // Change in x
/*0030*/ unsigned heading:12; // Directional heading
unsigned padding2:10; // ***Placeholder
unsigned padding3:10; // ***Placeholder
/*0034*/ float deltaZ; // Change in z
/*0038*/ signed deltaHeading:10; // change in heading
unsigned padding4:10; // ***Placeholder
unsigned padding5:12; // ***Placeholder
/*0042*/
};


/*
** Spawn Appearance
** Length: 8 Octets
** OpCode: spawnAppearanceCode
*/

struct spawnAppearanceStruct
{
/*0000*/ uint16_t spawnId; // ID of the spawn
/*0002*/ uint16_t type; // Type of data sent
/*0004*/ uint32_t parameter; // Values associated with the type
/*0008*/
};


/*
** Structures that are not being currently used
* (except for logging)
*/

struct bindWoundStruct
{
/*0000*/ uint16_t playerid; // TargetID
/*0002*/ uint8_t unknown0002[2]; // ***Placeholder
/*0004*/ uint32_t hpmaybe; // Hitpoints -- Guess
/*0008*/
};

struct inspectedStruct
{
/*0000*/ uint16_t inspectorid; // Source ID
/*0002*/ uint8_t unknown0002[2]; // ***Placeholder
/*0004*/ uint16_t inspectedid; // Target ID - Should be you
/*0006*/ uint8_t unknown0006[2]; // ***Placeholder
/*0008*/
};

struct attack1Struct
{
/*0000*/ uint16_t spawnId; // Spawn ID
/*0002*/ int16_t param1; // ***Placeholder
/*0004*/ int16_t param2; // ***Placeholder
/*0006*/ int16_t param3; // ***Placeholder
/*0008*/ int16_t param4; // ***Placeholder
/*0010*/ int16_t param5; // ***Placeholder
/*0012*/
};

struct attack2Struct
{
/*0000*/ uint16_t spawnId; // Spawn ID
/*0002*/ int16_t param1; // ***Placeholder
/*0004*/ int16_t param2; // ***Placeholder
/*0006*/ int16_t param3; // ***Placeholder
/*0008*/ int16_t param4; // ***Placeholder
/*0010*/ int16_t param5; // ***Placeholder
/*0012*/
};

struct newGuildInZoneStruct
{
/*0000*/ uint8_t unknown0000[8]; // ***Placeholder
/*0008*/ char guildname[56]; // Guildname
/*0064*/
};

struct moneyUpdateStruct
{
/*0000*/ uint32_t spawnid; // ***Placeholder
/*0004*/ uint32_t cointype; // Coin Type
/*0008*/ uint32_t amount; // Amount
/*0012*/
};

/* Memorize slot operations, mem, forget, etc */

struct memorizeSlotStruct
{
/*0000*/ uint32_t slot; // Memorization slot (0-7)
/*0004*/ uint32_t spellId; // Id of spell
// (offset of spell in spdat.eff)
/*0008*/ uint32_t action; // 1-memming,0-scribing,2-forget
/*0012*/
};

/*
** Spawn Appearance
** Length: 4 Octets
** OpCode: SetRunModeCode
*/

struct cRunToggleStruct
{
/*0000*/ uint32_t status; //01=run 00=walk
/*0004*/
};

struct cChatFiltersStruct
{
/*0000*/ uint32_t DamageShields; //00=on 01=off
/*0004*/ uint32_t NPCSpells; //00=on 01=off
/*0008*/ uint32_t PCSpells; //00=all 01=off 02=grp
/*0012*/ uint32_t BardSongs; //00=all 01=me 02=grp 03=off
/*0016*/ uint32_t Unused;
/*0020*/ uint32_t GuildChat; //00=off 01=on
/*0024*/ uint32_t Socials; //00=off 01=on
/*0028*/ uint32_t GroupChat; //00=off 01=on
/*0032*/ uint32_t Shouts; //00=off 01=on
/*0036*/ uint32_t Auctions; //00=off 01=on
/*0040*/ uint32_t OOC; //00=off 01=on
/*0044*/ uint32_t MyMisses; //00=off 01=on
/*0048*/ uint32_t OthersMisses; //00=off 01=on
/*0052*/ uint32_t OthersHits; //00=off 01=on
/*0056*/ uint32_t AttackerMisses; //00=off 01=on
/*0060*/ uint32_t CriticalSpells; //00=all 01=me 02=off
/*0064*/ uint32_t CriticalMelee; //00=all 01=me 02=off
/*0068*/
};

struct cOpenSpellBookStruct
{
/*0000*/ int32_t status; //01=open 00=close
/*0004*/
};

struct tradeSpellBookSlotsStruct
{
/*0000*/ uint32_t slot1;
/*0004*/ uint32_t slot2;
/*0008*/
};


/*
** serverLFGStruct
** Length: 10 Octets
** signifies LFG, maybe afk, role, ld, etc
*/

struct serverLFGStruct
{
/*0000*/ uint16_t spawnID;
/*0002*/ uint16_t unknown0004;
/*0004*/ uint16_t LFG; //1=LFG
/*0006*/ uint16_t unknown0008;
/*0008*/
};

/*
** clientLFGStruct
** Length: 70 Octets
** signifies LFG, maybe afk, role, ld, etc
*/

struct clientLFGStruct
{
/*0000*/ uint8_t name[64];
/*0064*/ uint16_t LFG; //1=LFG
/*0066*/ uint16_t unknown0008;
};

/*
** buffStruct
** Length: 44 Octets
**
*/

struct buffStruct
{
/*0000*/ uint32_t spawnid; //spawn id
/*0004*/ uint8_t unknown0004[4];
/*0008*/ float unknown0008;
/*0012*/ uint32_t spellid; // spellidbegin
/*0016*/ uint32_t duration; // duration
/*0024*/ uint8_t unknown0024[8];
/*0028*/ uint32_t playerId; // Player id who cast the buff
/*0032*/ uint8_t unknown0032[4];
/*0036*/ uint32_t spellslot; // spellslot
/*0040*/ uint32_t changetype; // 1=buff fading,2=buff duration
/*0044*/
};

/*
** Guild Member Update structure
** Length: 80 Octets
**
*/

struct GuildMemberUpdate
{
/*000*/ uint32_t guildId; // guild id
/*004*/ char name[64]; // member name
/*068*/ uint16_t zoneId; // zone id
/*070*/ uint16_t zoneInstance; // zone instance
/*072*/ uint32_t lastOn; // time the player was last on.
/*076*/ uint8_t uknown076[4]; // 4 bytes added 11/28/12
/*080*/
};

/*
** Bazaar trader on/off struct
** Length: 76 Octets
**
*/
struct bazaarTraderRequest
{
/*000*/ uint32_t spawnId; // Spawn id of person turning trader on/off
/*004*/ uint8_t mode; // 0=off, 1=on
/*005*/ uint8_t uknown005[3]; //
/*008*/ char name[64]; // trader name
/*072*/ uint8_t uknown072[4]; //
/*076*/
};

struct bazaarSearchQueryStruct
{
uint32_t mark;
uint32_t type;
char unknownXXX0[20]; // Value seems to always be the same
char searchstring[64];
uint32_t unknownXXX1;
uint32_t unknownXXX2;
};

/*
** Item Bazaar Search Result
** Length: 160 Octets
** OpCode: BazaarSearch
*/
struct bazaarSearchResponseStruct
{
/*0000*/ uint32_t mark; // ***unknown***
/*0004*/ uint32_t player_id; // trader ID
/*0008*/ char merchant_name[64]; // trader name
/*0072*/ uint32_t count; // Count of items for sale
/*0076*/ uint32_t item_id; // ID of item for sale
/*0080*/ uint8_t uknown0080[8]; // ***unknown***
/*0088*/ char item_name[64]; // nul-padded name with appended "(count)"
/*0152*/ uint32_t price; // price in copper
/*0156*/ uint8_t uknown0156[4]; // ***unknown***
/*0160*/
};

/*
** Item Bazaar Search Result
** Length: Variable
** OpCode: BazaarSearch
*/
union bazaarSearchStruct
{
uint32_t mark;
struct bazaarSearchQueryStruct query;
struct bazaarSearchResponseStruct response[];
};

/*******************************/
/* World Server Structs */

/*
** Guild List (from world server)
** Length: 68 Octets
** used in: worldGuildList
*/

struct guildListStruct
{
/*0000*/ uint32_t guildId;
/*0004*/ char guildName[64];
};

/*
** Guild List (from world server)
** Length: Variable (serialized)
*/
struct worldGuildListStruct
{
/*000*/ uint8_t unknown000[64];
/*064*/ uint32_t numberOfGuilds; // ?
/*068*/ guildListStruct guilds[MAX_GUILDS]; // MAX_GUILDS varies by server now
};

struct worldMOTDStruct
{
/*002*/ char message[0];
/*???*/ uint8_t unknownXXX[3];
};

// Restore structure packing to default
#pragma pack()

#endif // EQSTRUCT_H

//. .7...6....,X....D4.M.\.....P.v..>..W....
//123456789012345678901234567890123456789012
//000000000111111111122222222223333333333444



3. player.h


/*
* player.h
*
* ShowEQ Distributed under GPL
* http://seq.sourceforge.net/
*/

#ifndef EQPLAYER_H
#define EQPLAYER_H

#include <qobject.h>
#include <qcolor.h>

#include "everquest.h"
#include "spawn.h"

//----------------------------------------------------------------------
// forward declarations
class GuildMgr;
class ZoneMgr;

//----------------------------------------------------------------------
// constants
const int maxSpawnLevel = 255;

enum ColorLevel
{
tGraySpawn = 0,
tGreenSpawn = 1,
tCyanSpawn = 2,
tBlueSpawn = 3,
tEvenSpawn = 4,
tYellowSpawn = 5,
tRedSpawn = 6,
tUnknownSpawn = 7,
tMaxColorLevels = 8
};

//----------------------------------------------------------------------
// Player
class Player : public QObject, public Spawn
{
Q_OBJECT
public:
Player (QObject* parent,
ZoneMgr* zoneMgr,
GuildMgr* guildMgr,
const char* name = "player");
virtual ~Player();

public slots:
void clear();
void reset();
void setUseAutoDetectedSettings(bool enable);
void setDefaultName(const QString&);
void setDefaultLastname(const QString&);
void setDefaultLevel(uint8_t);
void setDefaultRace(uint16_t);
void setDefaultClass(uint8_t);
void setDefaultDeity(uint16_t);

void player(const charProfileStruct* player);
void loadProfile(const playerProfileStruct& player);
void increaseSkill(const uint8_t* skilli);
void manaChange(const uint8_t* mana);
void updateExp(const uint8_t* exp);
void updateAltExp(const uint8_t* altexp);
void updateLevel(const uint8_t* levelup);
void updateNpcHP(const uint8_t* hpupdate);
void updateSpawnInfo(const uint8_t* su);
void updateStamina(const uint8_t* stam);
void setLastKill(const QString& name, int level);
void zoneChanged(void);
void playerUpdateSelf(const uint8_t* pupdate, size_t, uint8_t);
void consMessage(const uint8_t* con, size_t, uint8_t dir);
void tradeSpellBookSlots(const uint8_t*, size_t, uint8_t);

void setPlayerID(uint16_t playerID);
void savePlayerState(void);
void restorePlayerState(void);
void setUseDefaults(bool bdefaults) { m_useDefaults = bdefaults; }

public:
virtual QString name() const;
virtual QString lastName() const;
virtual int level() const;
virtual uint16_t deity() const;
virtual uint16_t race() const;
virtual uint8_t classVal() const;

bool useAutoDetectedSettings() const { return m_useAutoDetectedSettings; }
QString defaultName() const { return m_defaultName; }
QString defaultLastName() const { return m_defaultLastName; }
uint8_t defaultLevel() const { return m_defaultLevel; }
uint16_t defaultDeity() const { return m_defaultDeity; }
uint16_t defaultRace() const { return m_defaultRace; }
uint8_t defaultClass() const { return m_defaultClass; }
QString realName() const { return m_realName; }
void setRealName(const QString& name) { m_realName = name; }

virtual void killSpawn();

// ZBTEMP: compatibility code
uint16_t getPlayerID() const { return id(); }
int16_t headingDegrees() const { return m_headingDegrees; }
bool validPos() const { return m_validPos; }

uint32_t getSkill(uint8_t skillId) { return m_playerSkills[skillId]; }
uint8_t getLanguage(uint8_t langId) { return m_playerLanguages[langId]; }

int getPlusHP() { return m_plusHP; }
int getPlusMana() { return m_plusMana; }

uint8_t getMaxSTR() { return m_maxSTR; }
uint8_t getMaxSTA() { return m_maxSTA; }
uint8_t getMaxCHA() { return m_maxCHA; }
uint8_t getMaxDEX() { return m_maxDEX; }
uint8_t getMaxINT() { return m_maxINT; }
uint8_t getMaxAGI() { return m_maxAGI; }
uint8_t getMaxWIS() { return m_maxWIS; }
uint16_t getMaxMana() { return m_maxMana; }
uint16_t getMana() { return m_mana; }
uint32_t getSpellBookSlot(uint32_t slotid) { return m_spellBookSlots[slotid]; }

uint32_t getCurrentExp() { return m_currentExp; }
uint32_t getMaxExp() { return m_maxExp; }

const QColor& conColorBase(ColorLevel level);
void setConColorBase(ColorLevel level, const QColor& color);
const QColor& pickConColor(int otherSpawnLevel) const;


bool getStatValue(uint8_t stat,
uint32_t& curValue,
uint32_t& maxValue);

signals:
void newPlayer(void);
void buffLoad(const spellBuff*);
void newSpeed (double speed);
void statChanged ( int statNum,
int val,
int max
);
void addSkill ( int,
int
);

void changeSkill ( int,
int
);
void deleteSkills();
void addLanguage ( int,
int
);
void changeLanguage ( int,
int
);
void deleteLanguages();

void setExp(uint32_t totalExp, uint32_t totalTick,
uint32_t minExpLevel, uint32_t maxExpLevel,
uint32_t tickExpLevel);

void newExp(uint32_t newExp, uint32_t totalExp, uint32_t totalTick,
uint32_t minExpLevel, uint32_t maxExpLevel,
uint32_t tickExpLevel);
void setAltExp(uint32_t totalExp,
uint32_t maxExp, uint32_t tickExp, uint32_t aapoints);
void newAltExp(uint32_t newExp, uint32_t totalExp, uint32_t totalTick,
uint32_t maxExp, uint32_t tickExp, uint32_t aapoints);
void expAltChangedInt (int, int, int);
void expChangedInt (int, int, int);

void expGained ( const QString &,
int,
long,
QString
);

void manaChanged ( uint32_t,
uint32_t
);

void stamChanged ( int, int, int, int);
void hpChanged(int16_t, int16_t);
void changedID(uint16_t playerID);
void posChanged(int16_t x, int16_t y, int16_t z,
int16_t deltaX, int16_t deltaY, int16_t deltaZ,
int32_t heading);
void changeItem(const Item* item, uint32_t changeType);
void headingChanged(int32_t heading);
void levelChanged(uint8_t level);
void guildChanged();

protected:
void fillConTable();

private:
ZoneMgr* m_zoneMgr;
GuildMgr* m_guildMgr;

// The default values are set either by info showeq_params.
// We keep a second copy in case the player levels while playing.
QString m_defaultName;
QString m_defaultLastName;
QString m_realName;
uint16_t m_mana;
uint16_t m_defaultRace;
uint16_t m_defaultDeity;
uint8_t m_defaultClass;
uint8_t m_defaultLevel;
uint32_t m_playerSkills[MAX_KNOWN_SKILLS];
uint8_t m_playerLanguages[MAX_KNOWN_LANGS];

uint16_t m_plusMana;
uint16_t m_plusHP;

uint16_t m_maxMana;
uint8_t m_maxSTR;
uint8_t m_maxSTA;
uint8_t m_maxCHA;
uint8_t m_maxDEX;
uint8_t m_maxINT;
uint8_t m_maxAGI;
uint8_t m_maxWIS;

uint16_t m_food;
uint16_t m_water;
uint16_t m_fatigue;

// ExperienceWindow needs this
uint32_t m_currentAltExp;
uint16_t m_currentAApts;
uint32_t m_currentExp;
uint32_t m_minExp;
uint32_t m_maxExp;
uint32_t m_tickExp;

uint32_t m_spellBookSlots[MAX_SPELLBOOK_SLOTS];

// con color bases
QColor m_conColorBases[tMaxColorLevels];

// con color table
QColor m_conTable[maxSpawnLevel];

// last spawn this player killed
QString m_lastSpawnKilledName;
int m_lastSpawnKilledLevel;

// is the kill information fresh
bool m_freshKill;

// last spell cast on this player
uint16_t m_lastSpellOnId;

int16_t m_headingDegrees;
// Wether or not we use defaults, determined by wether or not we could
// decode the zone loading data.
bool m_useDefaults;

// Whether or not to use auto-detected character settings
bool m_useAutoDetectedSettings;

// which things are valid
bool m_validStam;
bool m_validMana;
bool m_validHP;
bool m_validExp;
bool m_validAttributes;
bool m_validPos;
};

inline
const QColor& Player::pickConColor(int otherSpawnLevel) const
{
return m_conTable[otherSpawnLevel];
}

#endif // EQPLAYER_H



4. spawn.cpp:


/*
* spawn.cpp
*
* ShowEQ Distributed under GPL
* http://sourceforge.net/projects/seq/
*/

/*
* Adapted from spawnlist.h - Crazy Joe Divola ([email protected])
* Date - 7/31/2001
*/

// Major rework of SpawnShell{} classes - Zaphod ([email protected])
// Based on stuff from CJD's SpawnShell{} and stuff from SpawnList and
// from Map. Some optimization ideas adapted from SINS.

#ifdef __FreeBSD__
#include <sys/types.h>
#endif

#include <limits.h>
#include <math.h>

#include <qregexp.h>

#include "spawnshell.h"
#include "fixpt.h"
#include "util.h"

//----------------------------------------------------------------------
// constants
const char * Spawn_Corpse_Designator = "'s corpse";

// fix point q format to use for spawn optimizations
const int qFormat = 14;

// used to calculate where the mob/player should be while animating
// 1.3 was figured empiraccly.. feel free to change it.. It seems to
// be preety close though.
const float animationCoefficient = 0.0013;

// fixed point animation coefficient
const int animationCoefficientFixPt =
fixPtToFixed<int, float>(animationCoefficient, qFormat);

const EquipStruct SlotEmpty = { 0, 0, 0 };

//----------------------------------------------------------------------
// Handy utility functions
// static
QString print_item (uint16_t item)
{
// sparse array of item names, some are NULL
static const char* itemnames[] =
{
#include "weapons.h"
};

// sparse array of item names (in 0x01 range), some are NULL
static const char* itemnames1[] =
{
#include "weapons1.h"
};

// sparse array of item names (in 0x27 range), some are NULL
static const char* itemnames27[] =
{
#include "weapons27.h"
};

// sparse array of item names (in 0x28 range), some are NULL
static const char* itemnames28[] =
{
#include "weapons28.h"
};

// sparse array of item names (in 0x29 range), some are NULL
static const char* itemnames29[] =
{
#include "weapons29.h"
};

// sparse array of item names (in 0x2a range), some are NULL
static const char* itemnames2a[] =
{
#include "weapons2a.h"
};

// sparse array of item names (in 0x2b range), some are NULL
static const char* itemnames2b[] =
{
#include "weapons2b.h"
};

// sparse array of item names (in 0x2c range), some are NULL
static const char* itemnames2c[] =
{
#include "weapons2c.h"
};

// sparse array of item names (in 0x2d range), some are NULL
static const char* itemnames2d[] =
{
#include "weapons2d.h"
};

// assume no material name found
const char *itemStr = NULL;

uint32_t itemLo = item & 0x00ff;
uint32_t itemHi = (item & 0xff00) >> 8;

if (itemHi == 0x00)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames) / sizeof (char*)))
itemStr = itemnames[itemLo];
}
else if (itemHi == 0x01)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames1) / sizeof (char*)))
itemStr = itemnames1[itemLo];
}
else if (itemHi == 0x27)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames27) / sizeof (char*)))
itemStr = itemnames27[itemLo];
}
else if (itemHi == 0x28)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames28) / sizeof (char*)))
itemStr = itemnames28[itemLo];
}
else if (itemHi == 0x29)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames29) / sizeof (char*)))
itemStr = itemnames29[itemLo];
}
else if (itemHi == 0x2a)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames2a) / sizeof (char*)))
itemStr = itemnames2a[itemLo];
}
else if (itemHi == 0x2b)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames2b) / sizeof (char*)))
itemStr = itemnames2b[itemLo];
}
else if (itemHi == 0x2c)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames2c) / sizeof (char*)))
itemStr = itemnames2c[itemLo];
}
else if (itemHi == 0x2d)
{
// retrieve pointer to item name
if (itemLo < (sizeof(itemnames2d) / sizeof (char*)))
itemStr = itemnames2d[itemLo];
}

// if race name exists, then return it, otherwise return a number string
if (itemStr != NULL)
return itemStr;
else
{
QString item_str;
item_str.sprintf("U%04x", item);
return item_str;
}
}

//----------------------------------------------------------------------
// Item
Item::Item(spawnItemType t, uint16_t id)
: m_filterFlags(0),
m_runtimeFilterFlags(0),
m_ID(id),
m_NPC(99), // random bogus value
m_type(t)
{
m_spawnTime.start();
m_lastUpdate.start();
updateLastChanged();
}

Item::~Item()
{
}

QString Item::name() const
{
return m_name;
}

QString Item::transformedName() const
{
return name();
}

uint16_t Item::race() const
{
return 0;
}

QString Item::raceString() const
{
return "Unknown";
}

uint8_t Item::classVal() const
{
return 0;
}

QString Item::classString() const
{
return "Unknown";
}

QString Item::info() const
{
return "";
}

QString Item::filterString() const
{
QString buff;
buff.sprintf("Name:%s:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d",
(const char*)transformedName().utf8(),
(const char*)raceString(),
(const char*)classString(),
NPC(), x(), y(), z());
return buff;
}

QString Item::dumpString() const
{
return QString("ID:") + QString::number(id()) + ":" + filterString();
}

void Item::setPos(int16_t x, int16_t y, int16_t z)
{
// set the item position
setPoint(x, y, z);
}

void Item::setDistanceToPlayer(double dist)
{
m_fdist = dist;
m_idist = (uint32_t)m_fdist;
}

void Item::setDistanceToPlayer(uint32_t dist)
{
m_idist = dist;
}

//----------------------------------------------------------------------
// Spawn
Spawn::Spawn()
: Item(tSpawn, 0)
{
m_name = "fake";
m_lastName = "";
setNPC(SPAWN_NPC_UNKNOWN);

Item::setPos(0, 0, 0);
setDeltas(0, 0, 0);
setHeading(0, 0);
setAnimation(0);
setPetOwnerID(0);
setLight(0);
setGender(0);
setDeity(0);
setRace(0);
setClassVal(0);
setHP(0);
setMaxHP(0);
setGuildID(0xffff);
setGuildTag(NULL);
setLevel(0);
setTypeflag(0);
setGM(0);
for (int i = 0; i < tNumWearSlots; i++)
setEquipment(i, SlotEmpty);

// just clear the considred flag since data would be outdated
setConsidered(false);

// finally, note when this update occurred.
updateLast();
}

Spawn::Spawn(const spawnStruct* s)
: Item(tSpawn, s->spawnId)
{
// turn on auto delete for the track list
m_spawnTrackList.setAutoDelete(true);

// have update initialize everything
update(s);
}

Spawn::Spawn(uint16_t id,
int16_t x, int16_t y, int16_t z,
int16_t deltaX, int16_t deltaY, int16_t deltaZ,
int8_t heading, int8_t deltaHeading,
uint8_t animation)
: Item(tSpawn, id)
{
// apply the unknown mob values
m_name = "unknown";
m_lastName = "";
setNPC(SPAWN_NPC_UNKNOWN);

// set what is known
setPos(x, y, z);
setDeltas(deltaX, deltaY, deltaZ);
setHeading(heading, deltaHeading);
setAnimation(animation);

// initialize what isn't to 0
setPetOwnerID(0);
setLight(0);
setGender(0);
setDeity(0);
setRace(0);
setClassVal(0);
setHP(0);
setMaxHP(0);
setLevel(0);
setGuildID(0xffff);
setGuildTag(NULL);
for (int i = 0; i < tNumWearSlots; i++)
setEquipment(i, SlotEmpty);
setTypeflag(0);
setGM(0);
setConsidered(false);

// turn on auto delete for the track list
m_spawnTrackList.setAutoDelete(true);

// Finally, note when this update ocurred
updateLast();
}

Spawn::Spawn(QDataStream& d, uint16_t id)
: Item(tSpawn, id)
{
// restore Spawn info
d.readRawBytes((char*)this, sizeof(EQPoint));
d.readRawBytes((char*)&m_lastUpdate,
((char*)this + sizeof(Item)) - (char*)&m_lastUpdate);
d.readRawBytes((char*)&m_petOwnerID,
((char*)this + sizeof(Spawn)) - (char*)&m_petOwnerID);
d >> m_name;
d >> m_lastName;

// calculate race/deity team info
calcRaceTeam();
calcDeityTeam();

// don't trust old movement data (minimize walkoffs causing scaling)
setDeltas(0, 0, 0);
setHeading(0, 0);

// even if it had been considered, mark it as not
setConsidered(false);
}

Spawn::Spawn(Spawn* s, uint16_t id) : Item(tSpawn, id)
{
setName(s->name());
setLastName(s->lastName());
Item::setPoint(s->x(), s->y(), s->z());
setPetOwnerID(s->petOwnerID());
setLight(s->light());
setGender(s->gender());
setDeity(s->deity());
setRace(s->race());
setClassVal(s->classVal());
setHP(s->HP());
setMaxHP(s->maxHP());
setGuildID(s->guildID());
setLevel(s->level());
for (int i = 0; i <= tLastCoreWearSlot; i++)
setEquipment(i, s->equipment(i));
setEquipment(tUnknown1, SlotEmpty);
setTypeflag(s->typeflag());
setGM(s->gm());
setNPC(s->NPC());
setAnimation(s->animation());
setDeltas(s->deltaX(), s->deltaY(), s->deltaZ());
setHeading(s->heading(), s->deltaHeading());
setConsidered(s->considered());

// the new copy will own the spawn track list
m_spawnTrackList.setAutoDelete(false);
m_spawnTrackList = s->m_spawnTrackList;
s->m_spawnTrackList.setAutoDelete(false);
m_spawnTrackList.setAutoDelete(true);
}

Spawn::~Spawn()
{
// clear out the spawn track list
m_spawnTrackList.clear();
}

void Spawn::update(const spawnStruct* s)
{
setName(s->name);
setLastName(s->lastName);
setPos(s->x >> 3, s->y >> 3, s->z >> 3);
setPetOwnerID(s->petOwnerId);
setLight(s->light);
setGender(s->gender);
setDeity(s->deity);
setRace(s->race);
setClassVal(s->class_);
setHP(s->curHp);
setMaxHP(100); //the client sets this to 100
setGuildID(s->guildID);
setLevel(s->level);
for (int i = 0; i <= tLastCoreWearSlot; i++)
setEquipment(i, s->equipment[i]);
setEquipment(tUnknown1, SlotEmpty);

setTypeflag(s->bodytype);
setGM(s->gm);

// If it is a corpse with Unknown (NPC) religion.
if ((s->NPC == SPAWN_PC_CORPSE) && (s->deity == DEITY_UNKNOWN))
setNPC(SPAWN_NPC_CORPSE); // it's a dead monster
else
setNPC(s->NPC); // otherwise it is what it is

setAnimation(s->animation);

// only non corpses move
if (!isCorpse())
{
setDeltas(s->deltaX >> 2, s->deltaY >> 2, s->deltaZ >> 2);
setHeading(s->heading, s->deltaHeading);
}
else
{
setDeltas(0, 0, 0);
setHeading(0, 0);
}


// just clear the considred flag since data would be outdated
setConsidered(false);

setNotUpdated(false);

// finally, note when this update occurred.
updateLast();
}

void Spawn::backfill(const spawnStruct* s)
{
int i;

// set the characteristics that probably haven't changed.
setGender(s->gender);
setDeity(s->deity);
setRace(s->race);
setClassVal(s->class_);

// don't know how we'd find out if this changed, but it may, currently
setTypeflag(s->bodytype);
// no-check
setPetOwnerID(s->petOwnerId);

// preserve the NPC setting, have they died since the spawn info
if ((m_NPC == SPAWN_PC_CORPSE) ||
(m_NPC == SPAWN_NPC_CORPSE))
{
// No hit points for the dead, sorry. You're not undead yet.
setHP(0);

// Set whether this is a player or monster corpse
if ((s->NPC == SPAWN_PLAYER) || (s->NPC == SPAWN_SELF))
setNPC(SPAWN_PC_CORPSE); // Player corpse
else
setNPC(SPAWN_NPC_CORPSE); // Monster corpse

//If it is a corpse with Unknown (NPC) religion.
if (s->NPC == SPAWN_PC_CORPSE && s->deity == DEITY_UNKNOWN)
setNPC(SPAWN_NPC_CORPSE); //It is a dead monster.
} // only change NPC value if it's unknown
else if (m_NPC == SPAWN_NPC_UNKNOWN)
{
// If it is a corpse with Unknown (NPC) religion.
if ((s->NPC == SPAWN_PC_CORPSE) && (s->deity == DEITY_UNKNOWN))
setNPC(SPAWN_NPC_CORPSE); // it's a dead monster
else
setNPC(s->NPC); // otherwise it is what it is
}

setName(s->name);
setLastName(s->lastName);

// if it's dead, append the corpse designator and make sure it's not moving
if (isCorpse())
{
m_name += Spawn_Corpse_Designator;
setDeltas(0, 0, 0);
setHeading(0, 0);
}

// only change unknown equipment
for (i = 0; i <= tLastCoreWearSlot; i++)
if (equipment(i).itemId == SlotEmpty.itemId)
setEquipment(i, s->equipment[i]);

// only change unknown or no light
if (light() == 0)
setLight(s->light);

// only set the level if it's higher (not perfect I know)
if (m_level < s->level)
setLevel(s->level);

// set guildID
if (s->NPC == SPAWN_PLAYER || s->NPC == SPAWN_SELF)
setGuildID(s->guildID);
else
setGuildID(0xffff);
}

void Spawn::killSpawn()
{
setDeltas(0, 0, 0);
setHeading(0, 0);
setHP(0);
setMaxHP(0);
if ((NPC() == SPAWN_PLAYER) || (NPC() == SPAWN_SELF) || (NPC() == SPAWN_PC_CORPSE))
setNPC(SPAWN_PC_CORPSE);
else
setNPC(SPAWN_NPC_CORPSE);

//setName(realName() + Spawn_Corpse_Designator);
}

void Spawn::setPos(int16_t x, int16_t y, int16_t z,
bool walkpathrecord, size_t walkpathlength)
{
Item::setPos(x, y, z);

if (walkpathrecord)
{
uint32_t count = m_spawnTrackList.count();

// if this is the self spawn and this is the first spawn point,
// don't add it to the track list
if ((m_NPC == SPAWN_SELF) && (count == 0) &&
(x == 0) && (y == 0) && (z == 0))
return;

// only insert if the change includes either an x or y change, not just z
if ((count == 0) ||
((m_spawnTrackList.getLast()->x() != x) ||
(m_spawnTrackList.getLast()->y() != y)))
{
// if the walk path length is limited, make sure not to exceed the limit
if ((walkpathlength > 0) &&
(count > 2) && (count > walkpathlength))
m_spawnTrackList.removeFirst();

// append the new entry to the end of the list
m_spawnTrackList.append(new SpawnTrackPoint(x, y, z));
}
}
}

void Spawn::setDeltas(int16_t deltaX, int16_t deltaY, int16_t deltaZ)
{
m_deltaX = deltaX;
m_deltaY = deltaY;
m_deltaZ = deltaZ;
m_cookedDeltaXFixPt = fixPtMulI(animationCoefficientFixPt, qFormat,
m_deltaX);
m_cookedDeltaYFixPt = fixPtMulI(animationCoefficientFixPt, qFormat,
m_deltaY);
m_cookedDeltaZFixPt = fixPtMulI(animationCoefficientFixPt, qFormat,
m_deltaZ);
}

QString Spawn::lightName() const
{
// a non-sparse array of lightnames
static const char* lightnames[] =
{
"", // 0 - No light
"CDL", // 1 - Candle
"TR", // 2 - Torch
"TGS", // 3 - Tiny Glowing Skull
"SL", // 4 - Small Lantern
"SoM", // 5 - Stein of Moggok
"LL", // 6 - Large Lantern
"FL", // 7 - Flameless lantern, Halo of Light
"GOS", // 8 - Globe of stars
"LG", // 9 - Light Globe
"LS", // 10 - Lightstone, Burnt-out lightstone, wispstone
"GLS", // 11 - Greater lightstone
"FBE", // 12 - Fire Beatle Eye, Firefly Globe
"CL", // 13 - Coldlight
};

// return light name from list if it's within range
if (light() < (sizeof(lightnames) / sizeof (char*)))
return lightnames[light()];
else
return QString::number(light());
}

QString Spawn::equipmentStr(uint8_t wearingSlot) const
{
if (wearingSlot <= tLastMaterial)
return print_material(equipment(wearingSlot).itemId);
else if (wearingSlot <= tLastWeapon)
return print_item(equipment(wearingSlot).itemId);
else if (wearingSlot < tNumWearSlots)
return print_material(equipment(wearingSlot).itemId);
else
return "";
}

QString Spawn::genderName() const
{
if (m_gender == 0)
return "Male";
if (m_gender == 1)
return "Female";
return "Neuter";
}

QString Spawn::deityName() const
{
// make sure people don't add to list without modifying code to support
static const char* deitynames[(DEITY_VEESHAN - DEITY_BERT) + 1] =
{
#include "deity.h"
};

// if it's an NPC, return quickly
if (deity() == 0)
return "NPC";

// if agnostic return it
if (deity() == DEITY_AGNOSTIC)
return "Agnostic";

// if it is a deity in the table, retrieve and return it
if ((deity() >= DEITY_BERT) && (deity() <= DEITY_VEESHAN))
{
// subtract out lowest #'d deity in list to give 0 offset
int deityIndex = deity() - DEITY_BERT;

// return deity name
return deitynames[deityIndex];
}

// all else failed, so return a number
return QString::number(deity());
}

void Spawn::calcDeityTeam()
{
m_deityTeam = DTEAM_OTHER;

switch(deity())
{
//Good
case DEITY_EROL:
case DEITY_MITH:
case DEITY_RODCET:
case DEITY_QUELLIOUS:
case DEITY_TUNARE:
m_deityTeam = DTEAM_GOOD;
break;
//Neutral
case DEITY_BRELL:
case DEITY_BRISTLE:
case DEITY_KARANA:
case DEITY_PREXUS:
case DEITY_SOLUSEK:
case DEITY_TRIBUNAL:
case DEITY_VEESHAN:
m_deityTeam = DTEAM_NEUTRAL;
break;
//Evil
case DEITY_BERT:
case DEITY_CAZIC:
case DEITY_INNY:
case DEITY_RALLOS:
m_deityTeam = DTEAM_EVIL;
break;
}
}

void Spawn::calcRaceTeam()
{
m_raceTeam = RTEAM_OTHER;

switch(race())
{
case 1: // Human
case 2: // Barb
case 3: // Erudite
case 130: // Vah Shir
m_raceTeam = RTEAM_HUMAN;
break;

case 4: // Wood Elf
case 5: // High Elf
case 7: // Half Elf
m_raceTeam = RTEAM_ELF;
break;

case 6: // Dark Elf
case 9: // Troll
case 10: // Ogre
case 128: // Iksar
m_raceTeam = RTEAM_DARK;
break;

case 8: // Dwarf
case 11: // Halfling
case 12: // Gnome
m_raceTeam = RTEAM_SHORT;
break;
}
}

QString Spawn::lastName() const
{
return m_lastName;
}

int Spawn::level() const
{
return m_level;
}

uint16_t Spawn::deity() const
{
return m_deity;
}

QString Spawn::cleanedName() const
{
QString newName = name();
newName.replace(QRegExp("[0-9]"), "");
newName.replace(QRegExp("_"), " ");
return newName;
}

QString Spawn::transformedName() const
{
QString temp = cleanedName();
QString article;

if (temp.startsWith( "a " ))
{
temp = temp.mid( 2 );
article = "a";
}
else if (temp.startsWith( "an " ))
{
temp = temp.mid( 3 );
article = "an";
}
else if (temp.startsWith( "the " ))
{
temp = temp.mid( 4 );
article = "the";
}

if (!article.isEmpty())
{
temp += ", ";
temp += article;
}

return temp;
}

uint16_t Spawn::race() const
{
return m_race;
}

QString Spawn::raceString() const
{
// sparse array of racenames, some are NULL
static const char* racenames[] =
{
#include "races.h"
};

// assume no racename found
const char *raceString = NULL;

// retrieve pointer to race name
if (race() < (sizeof(racenames) / sizeof (char*)))
raceString = racenames[race()];

// if race name exists, then return it, otherwise return a number string
if (raceString != NULL)
return raceString;
else
return QString::number(race());
}

uint8_t Spawn::classVal() const
{
return m_class;
}

QString Spawn::classString() const
{
return ::classString(classVal());
}

QString Spawn::info() const
{
// Head, Chest, Arms, Waist, Gloves, Legs, Feet, Primary, Secondary
static const char* locs[]={"H","C","A","W","G","L","F","1","2", "B"};
int i;
QString temp = "";

// Add the light source to the list if it has one
if (light())
temp += QString("Light:") + lightName() + " ";

// Worn stuff
for (i = tFirstMaterial; i <= tLastMaterial ; i++)
if (equipment(i).itemId != SlotEmpty.itemId)
temp += QString(locs[i]) + ":" + print_material(equipment(i).itemId) + " ";

// Worn weapons
for (i = tFirstWeapon; i <= tLastWeapon; i++)
if (equipment(i).itemId != SlotEmpty.itemId)
temp += QString(locs[i]) + ":" + + print_item(equipment(i).itemId) + " ";

// Worn stuff -- Current best quess is that this may be material?
i = tUnknown1;
if (equipment(i).itemId != SlotEmpty.itemId)
temp += QString(locs[i]) + ":" + print_material(equipment(i).itemId) + " ";

#if 1 // print also as slot U1 (Unknown1) until we're positive
if (equipment(i).itemId != SlotEmpty.itemId)
temp += QString("U1:U") + QString::number(equipment(i).itemId, 16) + " ";
#endif

return temp;
}

QString Spawn::typeString() const
{
static const char* typenames[] =
{
#include "typenames.h"
};

if ( (typeflag() < (sizeof(typenames) / sizeof (char*))) && (typenames[typeflag()] != NULL) )
return typenames[typeflag()];
else
return QString::number(typeflag());
}

QString Spawn::filterString() const
{
QString name = transformedName();

QString buff;
buff.sprintf("Name:%s:Level:%d:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d :Z:%d:"
"Light:%s:Deity:%s:RTeam:%d:DTeam:%d:Type:%s:LastNa me:%s:Guild:%s:",
(const char*)name.utf8(),
level(),
(const char*)raceString(),
(const char*)classString(),
((NPC() == 10) ? 0 : NPC()),
x(), y(), z(),
(const char*)lightName(),
(const char*)deityName(),
raceTeam(),
deityTeam(),
(const char*)typeString(),
(const char*)lastName().utf8(),
(const char*)guildTag().utf8());

if (gm())
buff += QString("GM:") + QString::number(gm()) + ":";

return buff;
}

QString Spawn::dumpString() const
{
return QString("ID:") + QString::number(id())
+ ":Name:" + transformedName()
+ ":LastName:" + lastName()
+ ":Level:" + QString::number(level())
+ ":HP:" + QString::number(HP())
+ ":MaxHP:" + QString::number(maxHP())
+ ":Race:" + raceString()
+ ":Class:" + classString()
+ ":NPC:" + QString::number(NPC())
+ ":X:" + QString::number(x())
+ ":Y:" + QString::number(y())
+ ":Z:" + QString::number(z())
+ ":Deity:" + deityName()
+ ":RTeam:" + QString::number(raceTeam())
+ ":DTeam:" + QString::number(deityTeam())
+ ":Type:" + typeString()
+ ":Guild:" + guildTag()
+ ":FilterFlags:" + QString::number(filterFlags())
+ ":";
}


bool Spawn::approximatePosition(bool animating,
const QTime& curTime,
EQPoint& newPos) const
{
// default is the current location of the spawn
newPos.setPoint(*this);

// if animating calculate the current predicted position
if (animating)
{
// get the amount of time since last update
int msec = m_lastUpdate.msecsTo(curTime);

if (msec < 0) // if passed midnight, adjust time accordingly
msec += 86400 * 1000;

// if it's been over 90 seconds, then don't adjust position
if (msec < (90 * 1000))
{
newPos.addPoint(fixPtMulII(m_cookedDeltaXFixPt, qFormat, msec),
fixPtMulII(m_cookedDeltaYFixPt, qFormat, msec),
fixPtMulII(m_cookedDeltaZFixPt, qFormat, msec));

return true;
}
else
return false;
}

return true;
}

void Spawn::saveSpawn(QDataStream& d)
{
// dump spawn info
// write out the raw spawn structure, skipping over the QStrings,
// and SpawnTrackList (which can't be persisted in this fashion),
// and the data we don't wan't copied over (heading/delta info).
d.writeRawBytes((const char*)this, sizeof(EQPoint));
d.writeRawBytes((const char*)&m_lastUpdate,
((char*)this + sizeof(Item))
- (char*)&m_lastUpdate);
d.writeRawBytes((const char*)&m_petOwnerID,
((char*)this + sizeof(Spawn)) - (char*)&m_petOwnerID);
d << m_name;
d << m_lastName;
}

//----------------------------------------------------------------------
// Door
Door::Door(const doorStruct* d)
: Item(tDoors, d->doorId)
{
m_NPC = SPAWN_DOOR;

update(d);
}

Door::~Door()
{
}

void Door::update(const doorStruct* d)
{
QString temp;
setPos((int16_t)(d->x),
(int16_t)(d->y),
(int16_t)(d->z * 10.0));
setHeading((int8_t)lrintf(d->heading));
m_name.sprintf("Door: %s (%d) ", d->name, d->doorId);
setZonePoint(d->zonePoint);
updateLast();
}

QString Door::raceString() const
{
return "Door";
}

QString Door::classString() const
{
return "Thing";
}

//----------------------------------------------------------------------
// Drop
Drop::Drop(const makeDropStruct* d, const QString& name)
: Item(tDrop, d->dropId)
{
m_NPC = SPAWN_DROP;

update(d, name);
}

Drop::~Drop()
{
}

void Drop::update(const makeDropStruct* d, const QString& name)
{
int itemId;
QString buff;

// set the position
setPos((int16_t)d->x,
(int16_t)d->y,
(int16_t)d->z);
setHeading((int8_t)lrintf(d->heading));

// set the drop specific info
//setItemNr(d->itemNr);
setIdFile(d->idFile);

// calculate the drop name
if (name.isEmpty())
{
if (d->idFile[0] == 'I' && d->idFile[1] == 'T')
{
buff = (d->idFile + 2);
buff = buff.section('_', 0, 0, QString::SectionCaseInsensitiveSeps);
}
else
buff = d->idFile;


itemId = buff.toInt();

buff = "Drop: ";
if (itemId > 0)
buff.append(print_item(itemId));
else
buff.append(d->idFile);
}
else
buff = QString("Drop: '") + name + "'";

// set the name
setName(buff);

updateLast();
}

QString Drop::raceString() const
{
return "Drop";
}

QString Drop::classString() const
{
return "Thing";
}



5. spawnshell.cpp:


/*
* spawnshell.cpp
*
* ShowEQ Distributed under GPL
* http://seq.sourceforge.net/
*
* Portions Copyright 2001-2003,2007 Zaphod ([email protected]).
*
*/

/*
* Adapted from spawnlist.cpp - Crazy Joe Divola ([email protected])
* Date - 7/31/2001
*/

#include "spawnshell.h"
#include "filtermgr.h"
#include "zonemgr.h"
#include "player.h"
#include "util.h"
#include "guild.h"
#include "packetcommon.h"
#include "diagnosticmessages.h"
#include "netstream.h"

#include <qfile.h>
#include <qdatastream.h>

#ifdef __FreeBSD__
#include <sys/types.h>
#endif
#include <limits.h>
#include <math.h>

//----------------------------------------------------------------------
// useful macro definitions

// define this to have the spawnshell print diagnostics
//#define SPAWNSHELL_DIAG

// define this to diagnose structures passed in to SpawnShell
//#define SPAWNSHELL_DIAG_STRUCTS

// define this to have the spawnshell validate names to help spot errors
//#define SPAWNSHELL_NAME_VALIDATE

//----------------------------------------------------------------------
// constants
static const char magicStr[5] = "spn4"; // magic is the size of uint32_t + a null
static const uint32_t* magic = (uint32_t*)magicStr;
static const char * Spawn_Corpse_Designator = "'s corpse";

//----------------------------------------------------------------------
// Handy utility function
#ifdef SPAWNSHELL_NAME_VALIDATE
static bool isValidName(const char* name, size_t len)
{
int i = 0;

// loop over the string until the maximum length is reached
while (i < len)
{
// if the terminating NULL has been found, we're done
if ( name[i] == 0 )
break;

// if the current character is outside the normal range, fail the name
if ( (name[i] < ' ') || (name[i] > '~') )
return false;

// keep going until done
i++;
}

// if we finished with i being the buffer length, fail the name
// because it's not NULL terminated
if (i == len)
return false;

// it's a real name, return success
return true;
}
#endif

//----------------------------------------------------------------------
// SpawnShell
SpawnShell::SpawnShell(FilterMgr& filterMgr,
ZoneMgr* zoneMgr,
Player* player,
GuildMgr* guildMgr)
: QObject(NULL, "spawnshell"),
m_zoneMgr(zoneMgr),
m_player(player),
m_filterMgr(filterMgr),
m_guildMgr(guildMgr),
m_spawns(701),
m_drops(211),
m_doors(307),
m_players(2)
{
m_cntDeadSpawnIDs = 0;
m_posDeadSpawnIDs = 0;
for (int i = 0; i < MAX_DEAD_SPAWNIDS; i++)
m_deadSpawnID[i] = 0;

// these should auto delete
m_spawns.setAutoDelete(true);
m_drops.setAutoDelete(true);
m_doors.setAutoDelete(true);

// we don't want this one to auto-delete
m_players.setAutoDelete(false);

// bogus list
m_players.insert(0, m_player);

// connect the FilterMgr's signals to SpawnShells slots
connect(&m_filterMgr, SIGNAL(filtersChanged()),
this, SLOT(refilterSpawns()));
connect(&m_filterMgr, SIGNAL(runtimeFiltersChanged(uint8_t)),
this, SLOT(refilterSpawnsRuntime()));

// connect SpawnShell slots to ZoneMgr signals
connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)),
this, SLOT(clear(void)));
connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)),
this, SLOT(clear(void)));

// connect Player signals to SpawnShell signals
connect(m_player, SIGNAL(changeItem(const Item*, uint32_t)),
this, SIGNAL(changeItem(const Item*, uint32_t)));

// connect Player signals to SpawnShell slots
connect(m_player, SIGNAL(changedID(uint16_t)),
this, SLOT(playerChangedID(uint16_t)));

// restore the spawn list if necessary
if (showeq_params->restoreSpawns)
restoreSpawns();

// create the timer
m_timer = new QTimer(this);

// connect the timer
connect(m_timer, SIGNAL(timeout()),
this, SLOT(saveSpawns(void)));

// start the timer (changed to oneshot to help prevent a backlog on slower
// machines)
if (showeq_params->saveSpawns)
m_timer->start(showeq_params->saveSpawnsFrequency, true);
}

void SpawnShell::clear(void)
{
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::clear()");
#endif

emit clearItems();

m_spawns.clear();
m_doors.clear();
m_drops.clear();

// clear the players list, reinsert the player
m_players.clear();
m_players.insert(0, m_player);

// emit an changeItem for the player
emit changeItem(m_player, tSpawnChangedALL);

m_cntDeadSpawnIDs = 0;
m_posDeadSpawnIDs = 0;
for (int i = 0; i < MAX_DEAD_SPAWNIDS; i++)
m_deadSpawnID[i] = 0;
} // end clear

const Item* SpawnShell::findID(spawnItemType type, int id)
{
const Item* item = NULL;

if ((type == tSpawn) && (id == m_player->id()))
return (const Item*)m_player;

if (type != tPlayer)
item = getMap(type).find(id);

return item;
}

const Item* SpawnShell::findClosestItem(spawnItemType type,
int16_t x, int16_t y,
double& minDistance)
{
ItemMap& theMap = getMap(type);
ItemIterator it(theMap);
double distance;
Item* item;
Item* closest = NULL;

// find closest spawn

// iterate over all the items in the map
for (; it.current(); ++it)
{
// get the item
item = it.current();

// calculate the distance from the specified point
distance = item->calcDist(x, y);

// is this distance closer?
if (distance < minDistance)
{
// yes, note it
minDistance = distance;
closest = item;
}
}

// return the closest item.
return closest;
}

Spawn* SpawnShell::findSpawnByName(const QString& name)
{
ItemIterator it(m_spawns);
Spawn* spawn;

for (; it.current(); ++it)
{
// the item and coerce it to the Spawn type
spawn = (Spawn*)it.current();

if (name == spawn->name())
return spawn;
}

if (name == m_player->name())
return m_player;

return NULL;
}

void SpawnShell::deleteItem(spawnItemType type, int id)
{
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::deleteItem()");
#endif
ItemMap& theMap = getMap(type);

Item* item = theMap.find(id);

if (item != NULL)
{
emit delItem(item);
theMap.remove(id);

// send notifcation of new spawn count
emit numSpawns(m_spawns.count());
}
}

bool SpawnShell::updateFilterFlags(Item* item)
{
uint8_t level = 0;

if (item->type() == tSpawn)
level = ((Spawn*)item)->level();

// get the filter flags
uint32_t flags = m_filterMgr.filterMask(item->filterString(), level);

// see if the new filter flags are different from the old ones
if (flags != item->filterFlags())
{
// yes, set the new filter flags
item->setFilterFlags(flags);

// return true to indicate that the flags have changed
return true;
}

// flags haven't changed
return false;
}

bool SpawnShell::updateRuntimeFilterFlags(Item* item)
{
uint8_t level = 0;

if (item->type() == tSpawn)
level = ((Spawn*)item)->level();

// get the filter flags
uint32_t flags = m_filterMgr.runtimeFilterMask(item->filterString(), level);

// see if the new filter flags are different from the old ones
if (flags != item->runtimeFilterFlags())
{
// yes, set the new filter flags
item->setRuntimeFilterFlags(flags);

// return true to indicate that the flags have changed
return true;
}

// flags haven't changed
return false;
}

void SpawnShell::dumpSpawns(spawnItemType type, QTextStream& out)
{
ItemIterator it(getMap(type));

for (; it.current(); ++it)
out << it.current()->dumpString() << endl;
}

// same-name slots, connecting to Packet signals
// this packet is variable in length. everything is dwords except the "idFile" field
// which can be variable
void SpawnShell::newGroundItem(const uint8_t* data, size_t len, uint8_t dir)
{
if (m_zoneMgr->isZoning())
return;

if (dir != DIR_Server)
return;

if (!data)
return;

NetStream netStream(data, len);
makeDropStruct ds;
QString name;
union { uint32_t n; float f; } x;
memset(&ds, 0, sizeof(makeDropStruct));

// read drop id
ds.dropId = netStream.readUInt32NC();

// read name
name = netStream.readText();
if(name.length())
{
strcpy(ds.idFile, name.latin1());
name.setLength(0);
}

// read past zone id
netStream.readUInt32NC();

// read past zone instance
netStream.readUInt32NC();

// read past unknown dword field
netStream.readUInt32NC();

// read heading
x.n = netStream.readUInt32NC();
ds.heading = x.f;

// read past unknown dword field
netStream.readUInt32NC();

// read past unknown dword field
netStream.readUInt32NC();

// read past unknown dword field
netStream.readUInt32NC();

// read y pos
x.n = netStream.readUInt32NC();
ds.y = x.f;

// read x pos
x.n = netStream.readUInt32NC();
ds.x = x.f;

// read z pos
x.n = netStream.readUInt32NC();
ds.z = x.f;

#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::newGroundItem(makeDropStruct *)");
#endif

Drop* item = (Drop*)m_drops.find(ds.dropId);
if (item != NULL)
{
item->update(&ds, name);
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));
updateFilterFlags(item);
item->updateLastChanged();
emit changeItem(item, tSpawnChangedALL);
}
else
{
item = new Drop(&ds, name);
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));
updateFilterFlags(item);
m_drops.insert(ds.dropId, item);
emit addItem(item);
}
}

void SpawnShell::removeGroundItem(const uint8_t* data, size_t, uint8_t dir)
{
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::removeGroundItem(remDropStruct *)");
#endif

// if zoning, then don't do anything
if (m_zoneMgr->isZoning())
return;

if (dir != DIR_Server)
return;

const remDropStruct *d = (const remDropStruct *)data;

if (d)
deleteItem(tDrop, d->dropId);
}

void SpawnShell::newDoorSpawns(const uint8_t* data, size_t len, uint8_t dir)
{
int nDoors = len / sizeof(doorStruct);
const doorStruct* doors = (const doorStruct*)data;
for (int i = 0; i < nDoors; i++)
newDoorSpawn(doors[i], sizeof(doorStruct), dir);
}

void SpawnShell::newDoorSpawn(const doorStruct& d, size_t len, uint8_t dir)
{
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::newDoorSpawn(doorStruct*)");
#endif
Item* item = m_doors.find(d.doorId);
if (item != NULL)
{
Door* door = (Door*)item;
door->update(&d);
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));
updateFilterFlags(door);
item->updateLastChanged();
emit changeItem(door, tSpawnChangedALL);
}
else
{
item = (Item*)new Door(&d);
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));
updateFilterFlags(item);
m_doors.insert(d.doorId, item);
emit addItem(item);
}
}

void SpawnShell::zoneSpawns(const uint8_t* data, size_t len)
{
int spawndatasize = len / sizeof(spawnStruct);

const spawnStruct* zspawns = (const spawnStruct*)data;

for (int i = 0; i < spawndatasize; i++)
{
#if 0
// Dump position updates for debugging spawn struct position changes
for (int j=54; j<70; i++)
{
printf("%.2x", zspawns[i][j]);

if ((j+1) % 8 == 0)
{
printf(" ");
}
else
{
printf(" ");
}
}
printf("\n");
#endif

#if 0
// Debug positioning without having to recompile everything...
#pragma pack(1)
struct pos
{
/*0002*/ signed padding0000:12; // ***Placeholder
signed deltaX:13; // change in x
signed padding0005:7; // ***Placeholder
/*0006*/ signed deltaHeading:10;// change in heading
signed deltaY:13; // change in y
signed padding0006:9; // ***Placeholder
/*0010*/ signed y:19; // y coord
signed animation:13; // animation
/*0014*/ unsigned heading:12; // heading
signed x:19; // x coord
signed padding0014:1; // ***Placeholder
/*0018*/ signed z:19; // z coord
signed deltaZ:13; // change in z
/*0022*/
};
#pragma pack(0)
struct pos *p = (struct pos *)(data + i*sizeof(spawnStruct) + 151);
printf("[%.2x](%f, %f, %f), dx %f dy %f dz %f head %f dhead %f anim %d (%x, %x, %x, %x)\n",
zspawns[i].spawnId,
float(p->x)/8.0, float(p->y/8.0), float(p->z)/8.0,
float(p->deltaX)/4.0, float(p->deltaY)/4.0,
float(p->deltaZ)/4.0,
float(p->heading), float(p->deltaHeading),
p->animation, p->padding0000,
p->padding0005, p->padding0006, p->padding0014);
#endif
newSpawn(zspawns[i]);
}
}

int32_t SpawnShell::fillSpawnStruct(spawnStruct *spawn, const uint8_t *data, size_t len, bool checkLen)
{
/*
This reads data from the variable-length spawn struct
*/

// uncomment for debug info
//#define FILLSPAWNSTRUCT_DIAG

NetStream netStream(data, len);
int32_t retVal;
uint32_t race, nTmp;
uint8_t i;

QString name = netStream.readText();

if(name.length())
strcpy(spawn->name, name.latin1());

#ifdef FILLSPAWNSTRUCT_DIAG
seqDebug("SpawnShell::fillSpawnStruct ---- %s", name.latin1());
#endif

spawn->spawnId = netStream.readUInt32NC();

spawn->level = netStream.readUInt8();
// skip the next 4 bytes
netStream.skipBytes(4);

spawn->NPC = netStream.readUInt8();
spawn->miscData = netStream.readUInt32NC();

spawn->otherData = netStream.readUInt8();

// skip unknown3, unknown4
netStream.skipBytes(8);

/* & 1 is no longer chest/untargetable. It is now /buyer flag as of 01/16/13.
if(spawn->otherData & 1)
{
// it's a chest or untargetable

do
i = netStream.readUInt8();
while(i);

do
i = netStream.readUInt8();
while(i);

do
i = netStream.readUInt8();
while(i);

// skip next 3 longs
netStream.skipBytes(12);

// next it loops through 9 longs, but we can just skip them
netStream.skipBytes(36);

// skip 1 byte
netStream.skipBytes(1);

// skip the last long
netStream.skipBytes(4);
}
*/

if(spawn->otherData & 4) // aura stuff
{
netStream.readText(); // skip 2 variable len strings
netStream.readText();
netStream.skipBytes(54); // and 54 static bytes
}

spawn->charProperties = netStream.readUInt8();
#ifdef FILLSPAWNSTRUCT_DIAG
seqDebug("charProperties = %X", spawn->charProperties);
#endif

i = spawn->charProperties;
if(i == 0)
{
spawn->bodytype = 0;
}
else
{
do
{
nTmp = netStream.readUInt32NC();

if(i == spawn->charProperties)
{
spawn->bodytype = nTmp;
#ifdef FILLSPAWNSTRUCT_DIAG
seqDebug("bodytype = %d", spawn->bodytype);
#endif
}
}
while(--i);
}

spawn->curHp = netStream.readUInt8();
#ifdef FILLSPAWNSTRUCT_DIAG
seqDebug("curHP=%d", spawn->curHp);
#endif

// skip facestyle, walk/run speeds, unknown5
netStream.skipBytes(35);

spawn->race = netStream.readUInt32NC();
spawn->holding = netStream.readUInt8();
spawn->deity = netStream.readUInt32NC();
spawn->guildID = netStream.readUInt32NC();
spawn->guildstatus = netStream.readUInt32NC();
spawn->class_ = netStream.readUInt8();

#ifdef FILLSPAWNSTRUCT_DIAG
seqDebug("race=%08X holding=%02X deity=%08X guildID=%08X guildstatus=%08X class_=%02X ",
spawn->race, spawn->holding, spawn->deity, spawn->guildID, spawn->guildstatus, spawn->class_);
#endif

netStream.skipBytes(1);

spawn->state = netStream.readUInt8();
spawn->light = netStream.readUInt8();

netStream.skipBytes(1);

name = netStream.readText();

if(name.length() > 0 && name.length() < sizeof(spawn->lastName))
{
strcpy(spawn->lastName, name.latin1());
}

netStream.skipBytes(6);

spawn->petOwnerId = netStream.readUInt32NC();

netStream.skipBytes(25);
race = spawn->race;

// this is how the client checks if equipment should be read.
if(spawn->NPC == 0 || race <= 12 || race == 128 || race == 130 || race == 330 || race == 522)
{
// skip color
netStream.skipBytes(36);
for(i = 0; i < 9; i++)
{
spawn->equipment[i].equip3 = netStream.readUInt32NC();
spawn->equipment[i].itemId = netStream.readUInt32NC();
spawn->equipment[i].equip2 = netStream.readUInt32NC();
spawn->equipment[i].equip1 = netStream.readUInt32NC();
spawn->equipment[i].equip0 = netStream.readUInt32NC();
}
} else {
netStream.skipBytes(28);
spawn->equipment[7].itemId = netStream.readUInt32NC();
spawn->equipment[7].equip2 = netStream.readUInt32NC();
spawn->equipment[7].equip1 = netStream.readUInt32NC();
spawn->equipment[7].equip0 = netStream.readUInt32NC();
// secondary
spawn->equipment[8].itemId = netStream.readUInt32NC();
spawn->equipment[8].equip2 = netStream.readUInt32NC();
spawn->equipment[8].equip1 = netStream.readUInt32NC();
spawn->equipment[8].equip0 = netStream.readUInt32NC();
}

spawn->posData[0] = netStream.readUInt32NC();
spawn->posData[1] = netStream.readUInt32NC();
spawn->posData[2] = netStream.readUInt32NC();
spawn->posData[3] = netStream.readUInt32NC();
spawn->posData[4] = netStream.readUInt32NC();

if(spawn->otherData & 16)
{
name = netStream.readText();
strcpy(spawn->title, name.latin1());
}

if(spawn->otherData & 32)
{
name = netStream.readText();
strcpy(spawn->suffix, name.latin1());
}

// unknowns
netStream.skipBytes(8);

spawn->isMercenary = netStream.readUInt8();

// unknowns
netStream.skipBytes(54);

// now we're at the end

retVal = netStream.pos() - netStream.data();

if(checkLen && (int32_t)len != retVal)
{
seqDebug("SpawnShell::fillSpawnStruct - expected length: %d, read: %d for spawn '%s'", len, retVal, spawn->name);
}

return retVal;
}

void SpawnShell::zoneEntry(const uint8_t* data, size_t len)
{
// Zone Entry. Sent when players are added to the zone.

spawnStruct *spawn = new spawnStruct;

memset(spawn,0,sizeof(spawnStruct));

fillSpawnStruct(spawn,data,len,true);

#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::zoneEntry(spawnStruct *(name='%s'))", spawn->name);
#endif

Item *item;

if(!strcmp(spawn->name,m_player->realName()))
{
// Multiple zoneEntry packets are received for your spawn after you zone
m_player->update(spawn);
emit changeItem(m_player, tSpawnChangedALL);
}
else
{
if((item=m_spawns.find(spawn->spawnId)))
{
// Update existing spawn
Spawn *s=(Spawn*)item;
s->update(spawn);
}
else
{
// Create a new spawn
newSpawn(*spawn);
}
}
}

void SpawnShell::newSpawn(const uint8_t* data)
{
// if zoning, then don't do anything
if (m_zoneMgr->isZoning())
return;

const spawnStruct* spawn = (const spawnStruct*)data;

newSpawn(*spawn);
}

void SpawnShell::newSpawn(const spawnStruct& s)
{
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::newSpawn(spawnStruct *(name='%s'))", s.name);
#endif
// if this is the SPAWN_SELF it's the player
if (s.NPC == SPAWN_SELF)
return;

// not the player, so check if it's a recently deleted spawn
for (int i =0; i < m_cntDeadSpawnIDs; i++)
{
if ((m_deadSpawnID[i] != 0) && (m_deadSpawnID[i] == s.spawnId))
{
// found a match, remove it from the deleted spawn list
m_deadSpawnID[i] = 0;

/* Commented this out because it wasn't adding shrouded spawns.
Shrouded spawns get deleted from the zone first then added
as a new spawn. leaving this here in case another work-around
needs to be found. (ieatacid - 6-8-2008)

// let the user know what's going on
seqInfo("%s(%d) has already been removed from the zone before we processed it.",
s.name, s.spawnId);

// and stop the attempt to add the spawn.
return;
*/
}
}

Item* item = m_spawns.find(s.spawnId);
if (item != NULL)
{
Spawn* spawn = (Spawn*)item;
spawn->update(&s);
updateFilterFlags(spawn);
updateRuntimeFilterFlags(spawn);
item->updateLastChanged();

if (spawn->guildID() < MAX_GUILDS)
spawn->setGuildTag(m_guildMgr->guildIdToName(spawn->guildID()));
else
spawn->setGuildTag("");
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));

emit changeItem(item, tSpawnChangedALL);
}
else
{
item = new Spawn(&s);
Spawn* spawn = (Spawn*)item;
updateFilterFlags(spawn);
updateRuntimeFilterFlags(spawn);
m_spawns.insert(s.spawnId, item);

if (spawn->guildID() < MAX_GUILDS)
spawn->setGuildTag(m_guildMgr->guildIdToName(spawn->guildID()));
else
spawn->setGuildTag("");
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));

emit addItem(item);

// send notification of new spawn count
emit numSpawns(m_spawns.count());
}
}

void SpawnShell::playerUpdate(const uint8_t* data, size_t len, uint8_t dir)
{
// if zoning, then don't do anything
if (m_zoneMgr->isZoning())
return;

#if 0
// Dump position updates for debugging client update changes
for (int i=0; i<len; i++)
{
printf("%.2x", data[i]);

if ((i+1) % 8 == 0)
{
printf(" ");
}
else
{
printf(" ");
}
}
printf("\n");
#endif

const playerSpawnPosStruct *pupdate = (const playerSpawnPosStruct *)data;

if (dir != DIR_Client)
{
int16_t y = pupdate->y >> 3;
int16_t x = pupdate->x >> 3;
int16_t z = pupdate->z >> 3;

int16_t dy = pupdate->deltaY >> 2;
int16_t dx = pupdate->deltaX >> 2;
int16_t dz = pupdate->deltaZ >> 2;

#if 0
// Debug positioning without having to recompile everything...
#pragma pack(1)
struct pos
{
/*0000*/ uint16_t spawnId;
/*0002*/ uint16_t spawnId2;
/*0004*/ signed padding0004:13;
signed y:19; // y coord
/*0008*/ signed deltaX:13; // change in x
signed deltaHeading:10;// change in heading
signed padding0008:9;
/*0012*/ signed deltaY:13; // change in y
signed z:19; // z coord
/*0016*/ signed x:19; // x coord
signed animation:10; // animation
signed padding0016:3;
/*0020*/ unsigned heading:12; // heading
signed deltaZ:13; // change in z
signed padding0020:7;
/*0024*/
};
#pragma pack(0)
struct pos *p = (struct pos *)data;
printf("[%.2x](%f, %f, %f), dx %f dy %f dz %f head %f dhead %f anim %d (%x, %x, %x, %x)\n",
p->spawnId, float(p->x)/8.0, float(p->y/8.0), float(p->z)/8.0,
float(p->deltaX)/4.0, float(p->deltaY)/4.0,
float(p->deltaZ)/4.0,
float(p->heading), float(p->deltaHeading),
p->animation, p->padding0004, p->padding0008,
p->padding0016, p->padding0020);
#endif

updateSpawn(pupdate->spawnId, x, y, z, dx, dy, dz,
pupdate->heading, pupdate->deltaHeading,pupdate->animation);
}
}

void SpawnShell::npcMoveUpdate(const uint8_t* data, size_t len, uint8_t dir)
{
/*
* Wire format:
* 2 bytes - spawnId
* 6 bit - fieldSpecifier bitmask
* 19 bit - y
* 19 bit - x
* 19 bit - z
* 12 bit - heading
* [Variable fields]
*
* Depending on bits set in fields:
* 1 = 12 bit pitch
* 2 = 10 bit delta heading
* 4 = 10 bit velocity
* 8 = 13 bit delta y
* 16= 13 bit delta x
* 32 = 13 bit delta z
*
* Fields are in that order. For example, if the fieldSpecifier is
* 1, then there is just 12 bits of pitch. If the fieldSpecifier is
* 7, then there will be 10 bits of delta heading, 10 bits of animation,
* and 13 bits of delta y. Other non-specified values are 0.
*
* Oh and the byte order needs to be converted too. How nice.
*/
#define MASK_PITCH 0x01
#define MASK_DELTA_HEADING 0x02
#define MASK_ANIMATION 0x04
#define MASK_DELTA_Y 0x08
#define MASK_DELTA_X 0x10
#define MASK_DELTA_Z 0x20

// Variable length movement packet. Sanity check.
if ((len < 13) || (len > 21))
{
// Ignore it.
seqWarn("Ignoring invalid length %d for movement packet", len);
return;
}

// if zoning, then don't do anything
if (m_zoneMgr->isZoning())
{
return;
}

// Pull data from the header.
BitStream stream(data, len);

// spawnId.
uint16_t spawnId = stream.readUInt(16);

// BSH 13 Apr 2011 -- garbage added in packet
uint16_t unk1 = stream.readUInt(16);

// 6 bit field specifier.
uint8_t fieldSpecifier = stream.readUInt(6);

// 19 bit coords. 12 bit heading. All signed.
int16_t y = stream.readInt(19) >> 3;
int16_t x = stream.readInt(19) >> 3;
int16_t z = stream.readInt(19) >> 3;
int16_t heading = stream.readInt(12);

// Variable fields are 0 unless specified.
int16_t deltaX = 0;
int16_t deltaY = 0;
int16_t deltaZ = 0;
int8_t deltaHeading = 0;
int16_t velocity = 0;
int16_t pitch = 0;

if (fieldSpecifier & MASK_PITCH)
{
// Pull off pitch. Seq doesn't pay attention to this.
pitch = stream.readInt(12);
}
if (fieldSpecifier & MASK_DELTA_HEADING)
{
// Pull off deltaHeading. It is 10 bits in length. Signed.
deltaHeading = stream.readInt(10) >> 2;
}
if (fieldSpecifier & MASK_ANIMATION)
{
// Pull off velocity. It is 10 bits in length.
velocity = stream.readInt(10) >> 2;
}
if (fieldSpecifier & MASK_DELTA_Y)
{
// Pull off deltaY. It is 13 bits in length. Signed.
deltaY = stream.readInt(13) >> 2;
}
if (fieldSpecifier & MASK_DELTA_X)
{
// Pull off deltaX. It is 13 bits in length. Signed,
deltaX = stream.readInt(13) >> 2;
}
if (fieldSpecifier & MASK_DELTA_Z)
{
// Pull off deltaZ. It is 13 bits in length. Signed.
deltaZ = stream.readInt(13) >> 2;
}

// And send the update.
updateSpawn(spawnId, x, y, z,
deltaX, deltaY, deltaZ, heading, deltaHeading, velocity);
}

void SpawnShell::updateSpawn(uint16_t id,
int16_t x, int16_t y, int16_t z,
int16_t xVel, int16_t yVel, int16_t zVel,
int8_t heading, int8_t deltaHeading,
uint8_t animation)
{
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::updateSpawn(id=%d, x=%d, y=%d, z=%d, xVel=%d, yVel=%d, zVel=%d)",
id, x, y, z, xVel, yVel, zVel);
#endif

Item* item;

if (id == m_player->id())
{
item = m_player;
}
else
{
item = m_spawns.find(id);
}

if (item != NULL)
{
Spawn* spawn = (Spawn*)item;

spawn->setPos(x, y, z,
showeq_params->walkpathrecord,
showeq_params->walkpathlength);
spawn->setAnimation(animation);

spawn->setDeltas(xVel, yVel, zVel);
spawn->setHeading(heading, deltaHeading);

// Distance
if (!showeq_params->fast_machine)
item->setDistanceToPlayer(m_player->calcDist2DInt(*item));
else
item->setDistanceToPlayer(m_player->calcDist(*item));

spawn->updateLast();
item->updateLastChanged();
emit changeItem(item, tSpawnChangedPosition);
}
else if (showeq_params->createUnknownSpawns)
{
// not the player, so check if it's a recently deleted spawn
for (int i =0; i < m_cntDeadSpawnIDs; i++)
{
// check dead spawn list for spawnID, if it was deleted, shouldn't
// see new position updates, so therefore this is probably
// for a new spawn (spawn ID being reused)
if ((m_deadSpawnID[i] != 0) && (m_deadSpawnID[i] == id))
{
// found a match, ignore it
m_deadSpawnID[i] = 0;

seqInfo("(%d) had been removed from the zone, but saw a position update on it, so assuming bogus update.",
id);

return;
}
}

item = new Spawn(id, x, y, z, xVel, yVel, zVel,
heading, deltaHeading, animation);
updateFilterFlags(item);
updateRuntimeFilterFlags(item);
m_spawns.insert(id, item);
emit addItem(item);

#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::updateSpawn created unknown spawn (id=%u)", id);
#endif

// send notification of new spawn count
emit numSpawns(m_spawns.count());
}
}

void SpawnShell::updateSpawns(const uint8_t* data)
{
// if zoning, then don't do anything
if (m_zoneMgr->isZoning())
return;

const spawnPositionUpdate* updates = (const spawnPositionUpdate*)data;
updateSpawn(updates->spawnId,
updates->x >> 3, updates->y >> 3, updates->z >> 3,
0,0,0,updates->heading,0,0);
}

void SpawnShell::updateSpawnInfo(const uint8_t* data)
{
const SpawnUpdateStruct* su = (const SpawnUpdateStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::updateSpawnInfo(id=%d, sub=%d, hp=%d, maxHp=%d)",
su->spawnId, su->subcommand, su->arg1, su->arg2);
#endif

Item* item = m_spawns.find(su->spawnId);
if (item != NULL)
{
Spawn* spawn = (Spawn*)item;
switch(su->subcommand) {
case 17: // current hp update
spawn->setHP(su->arg1);
item->updateLastChanged();
emit changeItem(item, tSpawnChangedHP);
break;
}
}
}

void SpawnShell::renameSpawn(const uint8_t* data)
{
const spawnRenameStruct* rename = (const spawnRenameStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::renameSpawn(oldname=%s, newname=%s)",
rename->old_name, rename->new_name);
#endif

Spawn* renameMe = findSpawnByName(rename->old_name);

if (renameMe != NULL)
{
renameMe->setName(rename->new_name);

uint32_t changeType = tSpawnChangedName;

if (updateFilterFlags(renameMe))
changeType |= tSpawnChangedFilter;
if (updateRuntimeFilterFlags(renameMe))
changeType |= tSpawnChangedRuntimeFilter;

renameMe->updateLastChanged();
emit changeItem(renameMe, tSpawnChangedName);
}
else
{
seqWarn("SpawnShell: tried to rename %s to %s, but the original mob didn't exist in the spawn list", rename->old_name, rename->new_name);
}
}

void SpawnShell::illusionSpawn(const uint8_t* data)
{
const spawnIllusionStruct* illusion = (const spawnIllusionStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::illusionSpawn(id=%d, name=%s, new race=%d)",
illusion->spawnId, illusion->name, illusion->race);
#endif

Item* item = m_spawns.find(illusion->spawnId);

if (item != NULL)
{
Spawn* spawn = (Spawn*) item;

// Update what we can
spawn->setGender(illusion->gender);
spawn->setRace(illusion->race);

spawn->updateLastChanged();
emit changeItem(spawn, tSpawnChangedALL);
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell: Illusioned %s (id=%d) into race %d",
illusion->name, illusion->spawnId, illusion->race);
#endif
}
else
{
// Someone with an illusion up zoning in will generate an
// OP_Illusion BEFORE the OP_NewSpawn, so they won't be
// in the spawn list. Their spawnStruct will have their
// illusioned race anyways.
}
}

void SpawnShell::shroudSpawn(const uint8_t* data, size_t len, uint8_t dir)
{
// Self or other person shrouding. newSpawn handled updates too.

NetStream netStream(data,len);

uint32_t spawnID=netStream.readUInt32NC();
uint16_t spawnStructSize=netStream.readUInt16NC();
spawnStructSize-=6;

if(spawnID!=m_player->id())
{
// Shrouding other player
spawnShroudOther *shroud = new spawnShroudOther;
fillSpawnStruct(&shroud->spawn,netStream.pos(),spawnStructSize,true);
seqInfo("Shrouding %s (id=%d)", shroud->spawn.name, shroud->spawn.spawnId);
newSpawn(shroud->spawn);
}
else
{
// Shrouding yourself.
spawnShroudSelf *shroud = new spawnShroudSelf;

fillSpawnStruct(&shroud->spawn,netStream.pos(),spawnStructSize,true);
netStream.skipBytes(spawnStructSize);
memcpy(&shroud->profile,netStream.pos(),sizeof(playerProfileStruct ));
seqInfo("Shrouding %s (id=%d)", shroud->spawn.name, shroud->spawn.spawnId);

m_player->loadProfile(shroud->profile);

// We just updated a lot of stuff.
updateFilterFlags(m_player);
updateRuntimeFilterFlags(m_player);
m_player->updateLastChanged();
emit changeItem(m_player, tSpawnChangedALL);
}
}

void SpawnShell::updateSpawnAppearance(const uint8_t* data)
{
const spawnAppearanceStruct* app = (const spawnAppearanceStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::updateSpawnAppearance(id=%d, sub=%d, parm=%08x)",
app->spawnId, app->type, app->parameter);
#endif

Item* item = m_spawns.find(app->spawnId);

if (item != NULL)
{
Spawn* spawn = (Spawn*)item;

switch(app->type)
{
case 1: // level update
spawn->setLevel(app->parameter);
spawn->updateLastChanged();
emit changeItem(spawn, tSpawnChangedLevel);
break;
}

/* Other types for OP_SpawnAppearance (from eqemu guys)
0 - this causes the client to keel over and zone to bind point
1 - level, parm = spawn level
3 - 0 = visible, 1 = invisible
4 - 0 = blue, 1 = pvp (red)
5 - light type emitted by player (lightstone, shiny shield)
14 - anim, 100=standing, 110=sitting, 111=ducking, 115=feigned, 105=looting
15 - sneak, 0 = normal, 1 = sneaking
16 - server to client, sets player spawn id
17 - Client->Server, my HP has changed (like regen tic)
18 - linkdead, 0 = normal, 1 = linkdead
19 - lev, 0=off, 1=flymode, 2=levitate
20 - GM, 0 = normal, 1 = GM - all odd numbers seem to make it GM
21 - anon, 0 = normal, 1 = anon, 2 = roleplay
22 - guild id
23 - guild rank, 0=member, 1=officer, 2=leader
24 - afk, 0 = normal, 1 = afk
28 - autosplit, 0 = normal, 1 = autosplit on
29 - spawn's size
31 -change PC's name's color to NPC color 0 = normal, 1 = npc name
*/
}
}

void SpawnShell::updateNpcHP(const uint8_t* data)
{
const hpNpcUpdateStruct* hpupdate = (const hpNpcUpdateStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::updateNpcHP(id=%d, maxhp=%d hp=%d)",
hpupdate->spawnId, hpupdate->maxHP, hpupdate->curHP);
#endif
Item* item = m_spawns.find(hpupdate->spawnId);
if (item != NULL)
{
Spawn* spawn = (Spawn*)item;
spawn->setHP(hpupdate->curHP);
spawn->setMaxHP(hpupdate->maxHP);
item->updateLastChanged();
emit changeItem(item, tSpawnChangedHP);
}
}

void SpawnShell::spawnWearingUpdate(const uint8_t* data)
{
const wearChangeStruct *wearing = (const wearChangeStruct *)data;
Item* item = m_spawns.find(wearing->spawnId);
if (item != NULL)
{
// ZBTEMP: Find newItemID
//Spawn* spawn = (Spawn*)item;
// spawn->setEquipment(wearing->wearSlotId, wearing->newItemId);
uint32_t changeType = tSpawnChangedWearing;
if (updateFilterFlags(item))
changeType |= tSpawnChangedFilter;
if (updateRuntimeFilterFlags(item))
changeType |= tSpawnChangedRuntimeFilter;
item->updateLastChanged();
emit changeItem(item, changeType);
}
}

void SpawnShell::consMessage(const uint8_t* data, size_t, uint8_t dir)
{
const considerStruct * con = (const considerStruct*)data;
Item* item;
Spawn* spawn;

if (dir == DIR_Client)
{
if (con->playerid != con->targetid)
{
item = m_spawns.find(con->targetid);
if (item != NULL)
{
spawn = (Spawn*)item;

// note that this spawn has been considered
spawn->setConsidered(true);

emit spawnConsidered(item);
}
}
return;
}

// is it you that you've conned?
if (con->playerid != con->targetid)
{
// find the spawn if it exists
item = m_spawns.find(con->targetid);

// has the spawn been seen before?
if (item != NULL)
{
// yes
Spawn* spawn = (Spawn*)item;

// note that this spawn has been considered
spawn->setConsidered(true);

emit spawnConsidered(item);
} // end if spawn found
} // else not yourself
} // end consMessage()

void SpawnShell::removeSpawn(const uint8_t* data, size_t len, uint8_t dir)
{
if(dir==DIR_Client)
return;
const removeSpawnStruct* rmSpawn = (const removeSpawnStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::removeSpawn(id=%d)", rmSpawn->spawnId);
#endif

Item *item;

if(len==sizeof(removeSpawnStruct))
{
// BSH
deleteItem(tSpawn, rmSpawn->spawnId);
// BSH

if(!rmSpawn->removeSpawn)
{
// Remove a spawn from outside the update radius
if(showeq_params->useUpdateRadius)
{
// Remove it
deleteItem(tSpawn, rmSpawn->spawnId);
}
else
{
// Set flag to change its icon
if((item=m_spawns.find(rmSpawn->spawnId)))
{
Spawn *s=(Spawn*)item;
s->setNotUpdated(true);
}
}
}
}
else if((len+1)!=sizeof(removeSpawnStruct))
{
seqWarn("OP_RemoveSpawn (dataLen: %d) doesn't match: sizeof(removeSpawnStruct): %d",
len,sizeof(removeSpawnStruct));
}
}

void SpawnShell::deleteSpawn(const uint8_t* data)
{
const deleteSpawnStruct* delspawn = (const deleteSpawnStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::deleteSpawn(id=%d)", delspawn->spawnId);
#endif
if (m_posDeadSpawnIDs < (MAX_DEAD_SPAWNIDS - 1))
m_posDeadSpawnIDs++;
else
m_posDeadSpawnIDs = 0;

if (m_cntDeadSpawnIDs < MAX_DEAD_SPAWNIDS)
m_cntDeadSpawnIDs++;

m_deadSpawnID[m_posDeadSpawnIDs] = delspawn->spawnId;

deleteItem(tSpawn, delspawn->spawnId);
}

void SpawnShell::killSpawn(const uint8_t* data)
{
const newCorpseStruct* deadspawn = (const newCorpseStruct*)data;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::killSpawn(id=%d, kid=%d)",
deadspawn->spawnId, deadspawn->killerId);
#endif
Item* item;

if (deadspawn->spawnId != m_player->id())
{
item = m_spawns.find(deadspawn->spawnId);
}
else
{
item = m_player;
}

if (item != NULL)
{
Spawn* spawn = (Spawn*)item;

// ZBTEMP: This is temporary until we can find a better way
// set the last kill info on the player (do this before changing name)

// only call setLastKill if *you* killed the spawn
if(deadspawn->killerId == m_player->id())
{
m_player->setLastKill(spawn->name(), spawn->level());
}

spawn->killSpawn();
updateFilterFlags(item);
updateRuntimeFilterFlags(item);

spawn->setName(spawn->realName() + Spawn_Corpse_Designator);

Item* killer;
killer = m_spawns.find(deadspawn->killerId);
emit killSpawn(item, killer, deadspawn->killerId);
}
}

void SpawnShell::respawnFromHover(const uint8_t* data, size_t len, uint8_t dir)
{
if(dir != DIR_Client)
return;
#ifdef SPAWNSHELL_DIAG
seqDebug("SpawnShell::respawnFromHover()");
#endif

// Our old player is a corpse, but we're rising from the dead. So
// we need to pop a corpse to represent our deadselves, invalidate
// the player, and then let the OP_ZoneEntry that is coming for the repop
// fix the player.
uint16_t corpseId = m_player->id();

// invalidate the player by severing it from its Id.
m_player->setID(0);

// Pop a corpse
Spawn* corpse = new Spawn((Spawn*) m_player, corpseId);

updateFilterFlags(corpse);
updateRuntimeFilterFlags(corpse);
m_spawns.insert(corpse->id(), corpse);

if (corpse->guildID() < MAX_GUILDS)
{
corpse->setGuildTag(m_guildMgr->guildIdToName(corpse->guildID()));
}
else
{
corpse->setGuildTag("");
}

emit addItem(corpse);

// send notification of new spawn count
emit numSpawns(m_spawns.count());
}

void SpawnShell::corpseLoc(const uint8_t* data)
{
const corpseLocStruct* corpseLoc = (const corpseLocStruct*)data;
Item* item = m_spawns.find(corpseLoc->spawnId);
if (item != NULL)
{
Spawn* spawn = (Spawn*)item;

// set the corpses location, and make sure it's not moving...
if ((spawn->NPC() == SPAWN_PLAYER) || (spawn->NPC() == SPAWN_PC_CORPSE))
{
spawn->setPos(int16_t(corpseLoc->y), int16_t(corpseLoc->x),
int16_t(corpseLoc->z),
showeq_params->walkpathrecord,
showeq_params->walkpathlength);
}
else
{
spawn->setPos(int16_t(corpseLoc->x), int16_t(corpseLoc->y),
int16_t(corpseLoc->z),
showeq_params->walkpathrecord,
showeq_params->walkpathlength);
}
spawn->killSpawn();
spawn->updateLast();
spawn->updateLastChanged();

// signal that the spawn has changed
emit killSpawn(item, NULL, 0);
}
}

void SpawnShell::playerChangedID(uint16_t playerID)
{
// remove the player from the list (if it had a 0 id)
m_players.take(0);

// re-insert the player into the list
m_players.replace(playerID, m_player);

emit changeItem(m_player, tSpawnChangedALL);
}

void SpawnShell::refilterSpawns()
{
refilterSpawns(tSpawn);
refilterSpawns(tDrop);
refilterSpawns(tDoors);
}

void SpawnShell::refilterSpawns(spawnItemType type)
{
ItemMap& theMap = getMap(type);
ItemIterator it(theMap);

if (type == tSpawn)
{
Spawn* spawn;
// iterate over all the items in the map
for (; it.current(); ++it)
{
// get the item
spawn = (Spawn*)it.current();

// update the flags, if they changed, send a notification
if (updateFilterFlags(spawn))
{
spawn->updateLastChanged();
emit changeItem(spawn, tSpawnChangedFilter);
}
}
}
else
{
Item* item;
// iterate over all the items in the map
for (; it.current(); ++it)
{
// get the item
item = it.current();

// update the flags, if they changed, send a notification
if (updateFilterFlags(item))
{
item->updateLastChanged();
emit changeItem(item, tSpawnChangedFilter);
}
}
}
}

void SpawnShell::refilterSpawnsRuntime()
{
refilterSpawnsRuntime(tSpawn);
refilterSpawnsRuntime(tDrop);
refilterSpawnsRuntime(tDoors);
}

void SpawnShell::refilterSpawnsRuntime(spawnItemType type)
{
ItemIterator it(getMap(type));

if (type == tSpawn)
{
Spawn* spawn;
// iterate over all the items in the map
for (; it.current(); ++it)
{
// get the item
spawn = (Spawn*)it.current();

// update the flags, if they changed, send a notification
if (updateRuntimeFilterFlags(spawn))
{
spawn->updateLastChanged();
emit changeItem(spawn, tSpawnChangedRuntimeFilter);
}
}
}
else
{
Item* item;
// iterate over all the items in the map
for (; it.current(); ++it)
{
// get the item
item = it.current();

// update the flags, if they changed, send a notification
if (updateRuntimeFilterFlags(item))
{
item->updateLastChanged();
emit changeItem(item, tSpawnChangedRuntimeFilter);
}
}
}
}

void SpawnShell::saveSpawns(void)
{
QFile keyFile(showeq_params->saveRestoreBaseFilename + "Spawns.dat");
if (keyFile.open(IO_WriteOnly))
{
QDataStream d(&keyFile);

// write the magic string
d << *magic;

// write a test value at the top of the file for a validity check
size_t testVal = sizeof(spawnStruct);
d << testVal;

// save the name of the current zone
d << m_zoneMgr->shortZoneName().lower();

// save the spawns
ItemMap& theMap = getMap(tSpawn);

// save the number of spawns
testVal = theMap.count();
d << testVal;

ItemIterator it(theMap);
Spawn* spawn;

// iterate over all the items in the map
for (; it.current(); ++it)
{
// get the spawn
spawn = (Spawn*)it.current();

// save the spawn id
d << spawn->id();

// save the spawn
spawn->saveSpawn(d);
}
}

// re-start the timer
if (showeq_params->saveSpawns)
m_timer->start(showeq_params->saveSpawnsFrequency, true);
}

void SpawnShell::restoreSpawns(void)
{
QString fileName = showeq_params->saveRestoreBaseFilename + "Spawns.dat";
QFile keyFile(fileName);
if (keyFile.open(IO_ReadOnly))
{
size_t i;
size_t testVal;
uint16_t id;
Spawn* item;

QDataStream d(&keyFile);

// check the magic string
uint32_t magicTest;
d >> magicTest;

if (magicTest != *magic)
{
seqWarn("Failure loading %s: Bad magic string!",
(const char*)fileName);
return;
}

// check the test value at the top of the file
d >> testVal;
if (testVal != sizeof(spawnStruct))
{
seqWarn("Failure loading %s: Bad spawnStruct size!",
(const char*)fileName);
return;
}

// attempt to validate that the info is from the current zone
QString zoneShortName;
d >> zoneShortName;
if (zoneShortName != m_zoneMgr->shortZoneName().lower())
{
seqWarn("\aWARNING: Restoring spawns for potentially incorrect zone (%s != %s)!",
(const char*)zoneShortName,
(const char*)m_zoneMgr->shortZoneName().lower());
}

// read the expected number of elements
d >> testVal;

// read in the spawns
for (i = 0; i < testVal; i++)
{
// get the spawn id
d >> id;

// re-create the spawn
item = new Spawn(d, id);

// filter and add it to the list
updateFilterFlags(item);
updateRuntimeFilterFlags(item);
m_spawns.insert(id, item);
emit addItem(item);
}

emit numSpawns(m_spawns.count());

seqInfo("Restored SPAWNS: count=%d!",
m_spawns.count());
}
else
{
seqWarn("Failure loading %s: Unable to open!",
(const char*)fileName);
}
}

#ifndef QMAKEBUILD
#include "spawnshell.moc"
#endif

Sky_Genie
02-28-2013, 06:10 AM
Thank you very much!! It is alive.

Spanners
03-05-2013, 05:14 AM
Thanks for all your hard work guys, its alive for me too!