|
From: <xer...@us...> - 2026-07-29 02:38:42
|
Revision: 1682
http://sourceforge.net/p/seq/svn/1682
Author: xerxes00
Date: 2026-07-29 02:38:41 +0000 (Wed, 29 Jul 2026)
Log Message:
-----------
EQ Legends 2026-07-28 patch: opcodes updated + fixes
Opcodes: remapped the zone opcode set for the Legends 2026-07-28 patch.
Code:
- position/heading/self-state decode via structs in everquest.h
(eqlClientSelfPosStruct, playerPosUpdateEQLStruct, spawnStruct posData)
- spell-id widened uint16 -> uint32 end to end; high-id spells no longer alias
- spell window shows only own buffs + buffs the player cast (per-record
caster filter)
- loadout-swap re-creates a deleted spawn instead of dropping it (fixes
spawns stuck as Unknown)
- statlist: guard food/water percent against zero max (SIGFPE fix)
- moved inline EQL packet layouts into everquest.h structs
(moneyUpdateEQLStruct, dzSwitchInfoEQLStruct, spawnEventEQLStruct)
- aalist: QT_VERSION guard for setSectionResizeMode (Qt4 build) - thanks kkmonte
Modified Paths:
--------------
showeq/branches/showeqlegends/conf/zoneopcodes.xml
showeq/branches/showeqlegends/src/aalist.cpp
showeq/branches/showeqlegends/src/everquest.h
showeq/branches/showeqlegends/src/group.cpp
showeq/branches/showeqlegends/src/guildshell.cpp
showeq/branches/showeqlegends/src/interface.cpp
showeq/branches/showeqlegends/src/message.h
showeq/branches/showeqlegends/src/messageshell.cpp
showeq/branches/showeqlegends/src/packetformat.cpp
showeq/branches/showeqlegends/src/player.cpp
showeq/branches/showeqlegends/src/s_everquest.h
showeq/branches/showeqlegends/src/spawnshell.cpp
showeq/branches/showeqlegends/src/spells.cpp
showeq/branches/showeqlegends/src/spells.h
showeq/branches/showeqlegends/src/spellshell.cpp
showeq/branches/showeqlegends/src/spellshell.h
showeq/branches/showeqlegends/src/statlist.cpp
showeq/branches/showeqlegends/src/util.cpp
showeq/branches/showeqlegends/src/util.h
showeq/branches/showeqlegends/src/zonemgr.cpp
Modified: showeq/branches/showeqlegends/conf/zoneopcodes.xml
===================================================================
--- showeq/branches/showeqlegends/conf/zoneopcodes.xml 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/conf/zoneopcodes.xml 2026-07-29 02:38:41 UTC (rev 1682)
@@ -16,104 +16,98 @@
-->
<!-- Critical opcodes used directly by ShowEQ -->
- <opcode id="6a88" name="OP_PlayerProfile" priority="10" updated="07/14/26">
+ <opcode id="50e5" name="OP_PlayerProfile" priority="10" updated="07/28/26">
<comment>CharProfileCode</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="144f" name="OP_ZoneEntry" priority="10" updated="07/14/26">
+ <opcode id="5c7f" name="OP_ZoneEntry" priority="10" updated="07/28/26">
<comment>ZoneEntryCode</comment>
<payload dir="client" typename="ClientZoneEntryStruct" sizechecktype="match"/>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="0b7f" name="OP_TimeOfDay" priority="3" updated="07/14/26">
- <comment>TimeOfDayCode</comment>
+ <opcode id="7377" name="OP_TimeOfDay" priority="3" updated="07/28/26">
<payload dir="server" typename="timeOfDayStruct" sizechecktype="match"/>
</opcode>
- <opcode id="65dd" name="OP_NewZone" priority="10" updated="07/14/26">
+ <opcode id="47f2" name="OP_NewZone" priority="10" updated="07/28/26">
<comment>NewZoneCode</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="75dd" name="OP_SpawnDoor" priority="9" updated="07/14/26">
- <comment>DoorSpawnsCode</comment>
+ <opcode id="3f1b" name="OP_SpawnDoor" priority="9" updated="07/28/26">
<payload dir="server" typename="doorStruct" sizechecktype="modulus"/>
</opcode>
- <opcode id="7e02" name="OP_GroundSpawn" priority="9" updated="07/14/26">
+ <opcode id="5331" name="OP_GroundSpawn" priority="9" updated="07/28/26">
<comment>MakeDropCode</comment>
<payload dir="server" typename="makeDropStruct" sizechecktype="none"/>
</opcode>
- <opcode id="5926" name="OP_SendZonePoints" priority="5" updated="07/14/26">
+ <opcode id="0834" name="OP_SendZonePoints" priority="5" updated="07/28/26">
<comment>Coords in a zone that will port you to another zone</comment>
<payload dir="server" typename="zonePointsStruct" sizechecktype="none"/>
</opcode>
- <opcode id="7830" name="OP_AAExpUpdate" priority="4" updated="07/14/26">
- <comment>Receiving AA experience. Also when percent to AA changes.</comment>
+ <opcode id="1d38" name="OP_AAExpUpdate" priority="4" updated="07/28/26">
<payload dir="server" typename="altExpUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="53b7" name="OP_ExpUpdate" priority="4" updated="07/14/26">
- <comment>ExpUpdateCode</comment>
+ <opcode id="5abf" name="OP_ExpUpdate" priority="4" updated="07/28/26">
<payload dir="server" typename="expUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5924" name="OP_GuildMOTD" priority="2" updated="07/14/26">
+ <opcode id="70c5" name="OP_GuildMOTD" priority="2" updated="07/28/26">
<comment>GuildMOTD</comment>
<payload dir="server" typename="guildMOTDStruct" sizechecktype="none"/>
</opcode>
- <opcode id="5188" name="OP_ClientUpdate" priority="10" updated="07/14/26">
+ <opcode id="5bfd" name="OP_ClientUpdate" priority="10" updated="07/28/26">
<comment>Position updates</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="3348" name="OP_MobUpdate" priority="10" updated="07/14/26">
+ <opcode id="26d8" name="OP_MobUpdate" priority="10" updated="07/28/26">
<comment>MobUpdateCode</comment>
<payload dir="both" typename="spawnPositionUpdate" sizechecktype="none"/>
</opcode>
- <opcode id="0e2c" name="OP_DeleteSpawn" priority="10" updated="07/14/26">
+ <opcode id="1856" name="OP_DeleteSpawn" priority="10" updated="07/28/26">
<comment>DeleteSpawnCode</comment>
<payload dir="both" typename="deleteSpawnStruct" sizechecktype="match"/>
</opcode>
- <opcode id="483c" name="OP_RemoveSpawn" priority="10" updated="07/14/26">
+ <opcode id="27cb" name="OP_RemoveSpawn" priority="10" updated="07/28/26">
<comment>Remove spawn from zone</comment>
<payload dir="both" typename="removeSpawnStruct" sizechecktype="none"/>
</opcode>
- <opcode id="2874" name="OP_WearChange" priority="2" updated="07/14/26">
+ <opcode id="4a78" name="OP_WearChange" priority="2" updated="07/28/26">
<priorityNote>stock handler no-op; id mapped for log id only</priorityNote>
<comment>SpawnUpdateCode</comment>
<payload dir="both" typename="SpawnUpdateStruct" sizechecktype="match"/>
</opcode>
- <opcode id="4170" name="OP_SpawnAppearance" priority="10" updated="07/14/26">
+ <opcode id="384f" name="OP_SpawnAppearance" priority="10" updated="07/28/26">
<comment>SpawnAppearanceCode</comment>
<payload dir="both" typename="spawnEventEQLStruct" sizechecktype="match"/>
</opcode>
- <opcode id="3b0c" name="OP_Stamina" priority="4" updated="07/14/26">
- <comment>Server updating on hunger/thirst</comment>
+ <opcode id="17a1" name="OP_Stamina" priority="4" updated="07/28/26">
<payload dir="server" typename="staminaStruct" sizechecktype="match"/>
</opcode>
- <opcode id="a5c0" name="OP_HPUpdate" priority="10" updated="07/14/26">
+ <opcode id="3139" name="OP_HPUpdate" priority="10" updated="07/28/26">
<comment>NpcHpUpdateCode Update HP % of a PC or NPC</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="0717" name="OP_GuildMemberUpdate" priority="3" updated="07/14/26">
- <comment>Info regarding guild members</comment>
+ <opcode id="0aa2" name="OP_GuildMemberUpdate" priority="3" updated="07/28/26">
<payload dir="server" typename="GuildMemberUpdate" sizechecktype="match"/>
</opcode>
- <opcode id="597e" name="OP_ClickObject" priority="9" updated="07/14/26">
- <comment>Items dropped on the ground</comment>
+ <opcode id="23ee" name="OP_ClickObject" priority="9" updated="07/28/26">
+ <comment>Server removing a ground drop (pickup)</comment>
<payload dir="server" typename="remDropStruct" sizechecktype="match"/>
</opcode>
- <opcode id="76e5" name="OP_Action" priority="7" updated="07/14/26">
+ <opcode id="50e8" name="OP_Action" priority="7" updated="07/28/26">
<comment>Spells cast etc</comment>
<payload dir="both" typename="actionStruct" sizechecktype="match"/>
<payload dir="both" typename="actionAltStruct" sizechecktype="match"/>
</opcode>
- <opcode id="5446" name="OP_Action2" priority="7" updated="07/14/26">
+ <opcode id="7df9" name="OP_Action2" priority="7" updated="07/28/26">
<comment>Combat actions i.e. bash, kick etc</comment>
<payload dir="both" typename="action2Struct" sizechecktype="match"/>
</opcode>
- <opcode id="1f81" name="OP_Consider" priority="9" updated="07/14/26">
- <comment>ConsiderCode</comment>
+ <opcode id="64c4" name="OP_Consider" priority="9" updated="07/28/26">
+ <comment>Consider request/response</comment>
<payload dir="both" typename="considerStruct" sizechecktype="match"/>
</opcode>
- <opcode id="3ef7" name="OP_TargetMouse" priority="9" updated="07/14/26">
- <comment>Targeting a person - old ClientTargetCode</comment>
+ <opcode id="3897" name="OP_TargetMouse" priority="9" updated="07/28/26">
+ <comment>Targeting a spawn via mouse</comment>
<payload dir="both" typename="clientTargetStruct" sizechecktype="match"/>
</opcode>
<opcode id="ffff" name="OP_SpawnRename" priority="6" updated="07/19/23">
@@ -120,101 +114,92 @@
<comment>Spawns getting renamed after initial NewSpawn</comment>
<payload dir="server" typename="spawnRenameStruct" sizechecktype="match"/>
</opcode>
- <opcode id="2e7d" name="OP_Illusion" priority="8" updated="07/14/26">
+ <opcode id="5201" name="OP_Illusion" priority="8" updated="07/28/26">
<comment>Spawn being illusioned (changing forms)</comment>
<payload dir="both" typename="spawnIllusionStruct" sizechecktype="match"/>
</opcode>
- <opcode id="4ca8" name="OP_ZoneChange" priority="10" updated="07/14/26">
+ <opcode id="3360" name="OP_ZoneChange" priority="10" updated="07/28/26">
<priorityNote>server never sends it; handler only sets m_zoning</priorityNote>
<comment>old ZoneChangeCode</comment>
<payload dir="both" typename="zoneChangeEQLStruct" sizechecktype="match"/>
</opcode>
- <opcode id="7869" name="OP_GroupInvite" priority="4" updated="07/14/26">
+ <opcode id="63c6" name="OP_GroupInvite" priority="4" updated="07/28/26">
<comment>You invite someone while ungrouped or get invited by someone ungrouped</comment>
<payload dir="both" typename="groupInviteStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0ff2" name="OP_GroupCancelInvite" priority="4" updated="07/14/26">
+ <opcode id="7a77" name="OP_GroupCancelInvite" priority="4" updated="07/28/26">
<priorityNote>single sample; reason byte unverified</priorityNote>
<comment>Declining to join a group</comment>
<payload dir="both" typename="groupDeclineStruct" sizechecktype="none"/>
</opcode>
- <opcode id="41d7" name="OP_GroupFollow" priority="4" updated="07/14/26">
- <comment>You join a group or player joins group</comment>
+ <opcode id="4e40" name="OP_GroupFollow" priority="4" updated="07/28/26">
<payload dir="server" typename="groupFollowStruct" sizechecktype="match"/>
</opcode>
- <opcode id="d305" name="OP_GroupUpdate" priority="6" updated="07/14/26">
- <comment>Group updates</comment>
- <comment>168B group roster refresh (fires at join/disband, member name@64)</comment>
+ <opcode id="68d3" name="OP_GroupUpdate" priority="6" updated="07/28/26">
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="227d" name="OP_GroupDisband" priority="4" updated="07/14/26">
- <comment>You disband from group</comment>
+ <opcode id="216d" name="OP_GroupDisband" priority="4" updated="07/28/26">
<payload dir="server" typename="groupDisbandStruct" sizechecktype="match"/>
</opcode>
- <opcode id="4546" name="OP_GroupLeader" priority="4" updated="07/14/26">
+ <opcode id="18e2" name="OP_GroupLeader" priority="4" updated="07/28/26">
<priorityNote>single sample; unconfirmed on /makeleader</priorityNote>
- <comment>Group leader change</comment>
<payload dir="server" typename="groupLeaderChangeStruct" sizechecktype="none"/>
</opcode>
- <opcode id="6c3c" name="OP_Buff" priority="6" updated="07/14/26">
+ <opcode id="122f" name="OP_Buff" priority="6" updated="07/28/26">
<priorityNote>client dir = memorize/forget, consumed silently</priorityNote>
<comment>old BuffDropCode</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="6cbd" name="OP_BeginCast" priority="5" updated="07/14/26">
- <comment>BeginCastCode</comment>
+ <opcode id="2c36" name="OP_BeginCast" priority="5" updated="07/28/26">
<payload dir="both" typename="beginCastStruct" sizechecktype="none"/>
</opcode>
- <opcode id="7a2f" name="OP_CastSpell" priority="5" updated="07/14/26">
- <comment>StartCastCode</comment>
+ <opcode id="155e" name="OP_CastSpell" priority="5" updated="07/28/26">
<payload dir="both" typename="startCastStruct" sizechecktype="match"/>
</opcode>
- <opcode id="6f46" name="OP_SwapSpell" priority="3" updated="07/14/26">
+ <opcode id="4459" name="OP_SwapSpell" priority="3" updated="07/28/26">
<comment>TradeSpellBookSlotsCode</comment>
<payload dir="both" typename="tradeSpellBookSlotsStruct" sizechecktype="match"/>
</opcode>
- <opcode id="6a04" name="OP_InspectAnswer" priority="3" updated="07/14/26">
+ <opcode id="5503" name="OP_InspectAnswer" priority="3" updated="07/28/26">
<comment>InspectDataCode</comment>
<payload dir="server" typename="inspectDataStruct" sizechecktype="match"/>
</opcode>
- <opcode id="61a5" name="OP_Emote" priority="4" updated="07/14/26">
+ <opcode id="6d34" name="OP_Emote" priority="4" updated="07/28/26">
<comment>EmoteTextCode</comment>
<payload dir="both" typename="emoteTextStruct" sizechecktype="none"/>
</opcode>
- <opcode id="7b92" name="OP_SimpleMessage" priority="4" updated="07/14/26">
+ <opcode id="72cb" name="OP_SimpleMessage" priority="4" updated="07/28/26">
<comment>SimpleMessageCode</comment>
<payload dir="server" typename="simpleMessageStruct" sizechecktype="match"/>
</opcode>
- <opcode id="15d0" name="OP_FormattedMessage" priority="4" updated="07/14/26">
+ <opcode id="06f1" name="OP_FormattedMessage" priority="4" updated="07/28/26">
<comment>FormattedMessageCode i.e. pet dismissed etc</comment>
<payload dir="server" typename="formattedMessageStruct" sizechecktype="none"/>
</opcode>
- <opcode id="7015" name="OP_CommonMessage" priority="9" updated="07/14/26">
+ <opcode id="37fa" name="OP_CommonMessage" priority="9" updated="07/28/26">
<comment>ChannelMessageCode i.e. /tell /ooc /shout etc</comment>
<payload dir="both" typename="channelMessageStruct" sizechecktype="none"/>
</opcode>
- <opcode id="2189" name="OP_SpecialMesg" priority="4" updated="07/14/26">
+ <opcode id="4e60" name="OP_SpecialMesg" priority="4" updated="07/28/26">
<comment>Communicate textual info to client including hail responses etc</comment>
<payload dir="server" typename="specialMessageStruct" sizechecktype="none"/>
</opcode>
- <opcode id="5e9e" name="OP_RandomReq" priority="2" updated="07/14/26">
- <comment>RandomReqCode</comment>
+ <opcode id="05b1" name="OP_RandomReq" priority="2" updated="07/28/26">
<payload dir="client" typename="randomReqStruct" sizechecktype="none"/>
</opcode>
- <opcode id="77bd" name="OP_RandomReply" priority="2" updated="07/14/26">
- <comment>RandomCode</comment>
+ <opcode id="79a0" name="OP_RandomReply" priority="2" updated="07/28/26">
<payload dir="server" typename="randomStruct" sizechecktype="match"/>
</opcode>
- <opcode id="2265" name="OP_ConsentResponse" priority="3" updated="07/14/26">
+ <opcode id="492d" name="OP_ConsentResponse" priority="3" updated="07/28/26">
<comment>Server replying with consent information after /consent</comment>
<payload dir="server" typename="consentResponseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="05fc" name="OP_DenyResponse" priority="3" updated="07/14/26">
+ <opcode id="3991" name="OP_DenyResponse" priority="3" updated="07/28/26">
<comment>Server replying with deny information after /deny</comment>
<payload dir="server" typename="consentResponseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="2255" name="OP_ManaChange" priority="5" updated="07/14/26">
+ <opcode id="2b95" name="OP_ManaChange" priority="5" updated="07/28/26">
<comment>Mana change. Bards send this up with no size. Casters receive this for mana updates.</comment>
<payload dir="server" typename="manaDecrementStruct" sizechecktype="match"/>
</opcode>
@@ -222,12 +207,12 @@
<comment>MoneyOnCorpseCode</comment>
<payload dir="server" typename="moneyOnCorpseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="3873" name="OP_SkillUpdate" priority="5" updated="07/14/26">
+ <opcode id="0462" name="OP_SkillUpdate" priority="5" updated="07/28/26">
<priorityNote>prior id 0dc7 was the zone-in bulk dump (OOB crash); bounds guard kept</priorityNote>
<comment>Skill up code</comment>
<payload dir="server" typename="skillIncStruct" sizechecktype="match"/>
</opcode>
- <opcode id="0d68" name="OP_LevelUpdate" priority="8" updated="07/14/26">
+ <opcode id="70c6" name="OP_LevelUpdate" priority="8" updated="07/28/26">
<priorityNote>single sample</priorityNote>
<comment>LevelUpUpdateCode</comment>
<payload dir="server" typename="levelUpUpdateStruct" sizechecktype="none"/>
@@ -238,46 +223,39 @@
</opcode>
<!-- Not necessary for SEQ to run but here to name packets in logs. -->
- <opcode id="2ac8" name="OP_Logout" priority="3" updated="07/14/26">
+ <opcode id="1160" name="OP_Logout" priority="3" updated="07/28/26">
<priorityNote>handler wired DIR_Client only</priorityNote>
<comment>Camp/logout handshake</comment>
<payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="729e" name="OP_ExpandedGuildInfo" priority="0" updated="07/14/26">
+ <opcode id="652b" name="OP_Animation" priority="0" updated="07/28/26">
<priorityNote>noHandler</priorityNote>
- <comment>Guild ranks and other misc guild data - Variable length</comment>
- <payload dir="server" typename="uint8_t" sizechecktype="none"/>
+ <comment>spawnId + action + value; fires per spawn animation</comment>
+ <payload dir="both" typename="spawnAnimationStruct" sizechecktype="none"/>
</opcode>
- <opcode id="4ecf" name="OP_Animation" priority="0" updated="07/14/26">
+ <opcode id="3fb1" name="OP_InspectRequest" priority="0" updated="07/28/26">
<priorityNote>noHandler</priorityNote>
- <comment>Combat animation, emote animations etc - 4 bytes</comment>
- <payload dir="both" typename="uint8_t" sizechecktype="none"/>
- </opcode>
- <opcode id="0cdf" name="OP_InspectRequest" priority="0" updated="07/14/26">
- <priorityNote>noHandler</priorityNote>
- <comment>InspectRequestCode - 8 bytes</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="7d46" name="OP_LootMessageEQL" priority="4" updated="07/14/26">
+ <opcode id="7199" name="OP_LootMessageEQL" priority="4" updated="07/28/26">
<comment>Loot-and-sell message</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="4d77" name="OP_MoneyUpdateEQL" priority="4" updated="07/14/26">
- <comment>Money totals</comment>
+ <opcode id="03c3" name="OP_MoneyUpdateEQL" priority="4" updated="07/28/26">
+ <comment>Running money total [plat,gold,silver,copper]</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="3959" name="OP_GuildsInZoneList" priority="8" updated="07/14/26">
+ <opcode id="157b" name="OP_GuildsInZoneList" priority="8" updated="07/28/26">
<comment>Listing of guild names present in the current zone. Generally seen on zoning</comment>
<payload dir="server" typename="guildsInZoneListStruct" sizechecktype="none"/>
</opcode>
- <opcode id="6c4c" name="OP_NewGuildInZone" priority="8" updated="07/14/26">
+ <opcode id="63a5" name="OP_NewGuildInZone" priority="8" updated="07/28/26">
<comment>An additional guild name has appeared in the current zone. Seen when a guilded player enters the current zone</comment>
<payload dir="server" typename="newGuildInZoneStruct" sizechecktype="none"/>
</opcode>
- <opcode id="1a0b" name="OP_Find" priority="0" updated="07/14/26">
+ <opcode id="767d" name="OP_Find" priority="0" updated="07/28/26">
<priorityNote>noHandler</priorityNote>
- <comment>Find window data - variable length, 24 min</comment>
- <payload dir="server" typename="uint8_t" sizechecktype="none"/>
+ <payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
<!-- Below are used to help make sense of the logs when searching for opcodes
@@ -284,58 +262,47 @@
Using these marks unknown opcodes in logs for easier reading -->
<!-- Below are unverified -->
- <opcode id="31ae" name="OP_SendAATable" priority="5" updated="07/14/26">
+ <opcode id="2a24" name="OP_SendAATable" priority="5" updated="07/28/26">
<comment>AA definition table</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
- </opcode>
+ </opcode>
- <opcode id="1ce7" name="OP_HideCorpse" priority="0" updated="07/14/26">
+ <opcode id="6ec9" name="OP_HideCorpse" priority="0" updated="07/28/26">
<priorityNote>noHandler</priorityNote>
- <comment>/hidecorpse request</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="4fb6" name="OP_SelfPosEQL" priority="10" updated="07/14/26">
+ <opcode id="6323" name="OP_SelfPosEQL" priority="10" updated="07/28/26">
<comment>Client self-position</comment>
<payload dir="client" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="021e" name="OP_NpcMoveUpdate" priority="10" updated="07/14/26">
+ <opcode id="3e7b" name="OP_NpcMoveUpdate" priority="10" updated="07/28/26">
<comment>Position updates</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="36bf" name="OP_Death" priority="7" updated="07/14/26">
+ <opcode id="2087" name="OP_Death" priority="7" updated="07/28/26">
<priorityNote>also fires on corpse decay</priorityNote>
<comment>old NewCorpseCode</comment>
<payload dir="server" typename="newCorpseStruct" sizechecktype="match"/>
</opcode>
- <opcode id="7d1c" name="OP_DeathEQL" priority="9" updated="07/14/26">
+ <opcode id="58ab" name="OP_DeathEQL" priority="3" updated="07/28/26">
<comment>Death/combat subcode channel</comment>
<payload dir="both" typename="deathRecordEQLStruct" sizechecktype="none"/>
</opcode>
- <opcode id="591d" name="OP_GuildMemberList" priority="3" updated="07/14/26">
- <comment>List of guild members - Variable length</comment>
+ <opcode id="6e10" name="OP_GuildMemberList" priority="3" updated="07/28/26">
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="73e2" name="OP_BuffList" priority="6" updated="07/14/26">
+ <opcode id="7bda" name="OP_BuffList" priority="6" updated="07/28/26">
<comment>Per-spawn buff list</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="631c" name="OP_LoadoutSwapEQL" priority="3" updated="07/14/26">
+ <opcode id="4c71" name="OP_LoadoutSwapEQL" priority="3" updated="07/28/26">
<comment>Loadout-swap self refresh</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="6768" name="OP_LootDrops" priority="4" updated="07/14/26">
- <comment>Personal loot list</comment>
+ <opcode id="2a6f" name="OP_LootDrops" priority="4" updated="07/28/26">
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="713a" name="OP_BuffList2" priority="6" updated="07/14/26">
- <comment>Per-spawn buff list (channel 2)</comment>
- <payload dir="server" typename="uint8_t" sizechecktype="none"/>
- </opcode>
- <opcode id="5c47" name="OP_BuffList3" priority="6" updated="07/14/26">
- <comment>Per-spawn buff list (channel 3)</comment>
- <payload dir="server" typename="uint8_t" sizechecktype="none"/>
- </opcode>
- <opcode id="18ba" name="OP_DzSwitchInfoEQL" priority="3" updated="07/14/26">
+ <opcode id="2216" name="OP_DzSwitchInfoEQL" priority="3" updated="07/28/26">
<priorityNote>wired but untested on Legends</priorityNote>
<comment>Dynamic-zone switch info</comment>
<payload dir="server" typename="uint8_t" sizechecktype="none"/>
@@ -1246,14 +1213,12 @@
<comment>SpellFadeCode</comment>
<payload dir="both" typename="spellFadedStruct" sizechecktype="none"/>
</opcode>
- <opcode id="0fab" name="OP_Stance" priority="0" updated="07/14/26">
+ <opcode id="0b49" name="OP_Stance" priority="0" updated="07/28/26">
<priorityNote>noHandler</priorityNote>
- <comment>EQ Legends swappable stance; server echo carries active ability id - 4 bytes</comment>
- <payload dir="server" typename="uint8_t" sizechecktype="none"/>
+ <payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
- <opcode id="3b12" name="OP_Invocation" priority="0" updated="07/14/26">
+ <opcode id="2ae5" name="OP_Invocation" priority="0" updated="07/28/26">
<priorityNote>noHandler</priorityNote>
- <comment>EQ Legends swappable invocation; server echo carries active ability id - 4 bytes</comment>
- <payload dir="server" typename="uint8_t" sizechecktype="none"/>
+ <payload dir="both" typename="uint8_t" sizechecktype="none"/>
</opcode>
</seqopcodes>
Modified: showeq/branches/showeqlegends/src/aalist.cpp
===================================================================
--- showeq/branches/showeqlegends/src/aalist.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/aalist.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -48,9 +48,15 @@
// Points are pinned to the same small width; nothing stretches to fill
// the pane (empty space to the right).
header()->setStretchLastSection(false);
+#if QT_VERSION >= 0x050000
header()->setSectionResizeMode(AACOL_NAME, QHeaderView::ResizeToContents);
header()->setSectionResizeMode(AACOL_RANK, QHeaderView::Interactive);
header()->setSectionResizeMode(AACOL_POINTS, QHeaderView::Interactive);
+#else
+ header()->setResizeMode(AACOL_NAME, QHeaderView::ResizeToContents);
+ header()->setResizeMode(AACOL_RANK, QHeaderView::Interactive);
+ header()->setResizeMode(AACOL_POINTS, QHeaderView::Interactive);
+#endif
setColumnWidth(AACOL_RANK, 56);
setColumnWidth(AACOL_POINTS, 56);
Modified: showeq/branches/showeqlegends/src/everquest.h
===================================================================
--- showeq/branches/showeqlegends/src/everquest.h 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/everquest.h 2026-07-29 02:38:41 UTC (rev 1682)
@@ -686,6 +686,22 @@
/*0032*/
};
+// EQ Legends dynamic-zone switch info container (176B, instance-create).
+// Restructured from the stock dzSwitchInfo above; decoded by
+// ZoneMgr::dzSwitchInfoEQL, which translates it into the stock struct.
+struct dzSwitchInfoEQLStruct
+{
+/*0000*/ uint16_t zoneID;
+/*0002*/ uint16_t instanceID;
+/*0004*/ uint32_t unknown0004; // -1 observed
+/*0008*/ float y;
+/*0012*/ float x;
+/*0016*/ float z;
+/*0020*/ float heading; // heading? unvalidated
+/*0024*/ uint32_t type;
+/*0028*/ // zero tail (container is 176B)
+};
+
/*
** Dynamic Zone Info Struct
** Length: 212 Octets
@@ -1153,22 +1169,25 @@
// but are unvalidated; heading/animation/pitch positions
// in words 3-4 are unmapped (0x6000/0 observed) - all are
// zeroed at consumption in spawn.cpp until wire-mapped.
- signed z:19; // z coord (loc value 1)
+ // EQ Legends 2026-07-28 posData layout (spawnshell skips the
+ // one leading junk word, then reads these 5). word0 and
+ // word3 carry the two horizontal coords; assigning y to
+ // word0 and x to word3 rotates the dots to align with the
+ // zone map (the reverse assignment came out 90 deg off).
+ signed y:19; // y coord (EQ Legends x/y transposed) - word0
+ signed deltaY:13; // presumed change in y (unvalidated)
+
+ signed z:19; // z coord (loc value 1) - word1
signed deltaZ:13; // presumed change in z (unvalidated)
- signed x:19; // x coord (EQ Legends x/y transposed)
+ signed padCoord:32; // gap word (0 observed) - word2
+
+ signed x:19; // x coord (EQ Legends x/y transposed) - word3
signed deltaX:13; // presumed change in x (unvalidated)
- signed y:19; // y coord (EQ Legends x/y transposed)
- signed deltaY:13; // presumed change in y (unvalidated)
-
- unsigned heading:12; // candidate heading word (unvalidated)
+ unsigned heading:12; // word4 (unmapped/zeroed)
unsigned padding00:20;
- signed deltaHeading:10; // unmapped
- signed animation:10; // unmapped
- unsigned pitch:12; // unmapped
-
};
int32_t posData[5];
};
@@ -1551,7 +1570,7 @@
};
/*
-** EQ Legends OP_MobUpdate (opcode 0x67e0, 14 bytes, 2026-07-07 wire).
+** EQ Legends OP_MobUpdate (14 bytes).
** Coordinate block starts at payload offset 4 and packs, low bit first:
** x : bits 0..18 z : bits 19..37 (7-bit gap) y : bits 45..63
** each signed 19-bit, world value = field >> 3 (live convention).
@@ -1574,24 +1593,25 @@
/*
** EQ Legends player waypoint position update
-** Wire: one-byte-netop 0x03 family, LE opcode 0x0b03, fixed 24 bytes.
+** Wire: one-byte-netop 0x03 family, fixed 24 bytes.
** posData words use the same bit layout as the spawnStruct union.
*/
struct playerPosUpdateEQLStruct
{
/*0000*/ uint32_t spawnId;
-/*0004*/ uint32_t flags; // 0x00010842 observed constant
-/*0008*/ uint32_t unknown0008; // zero observed
-/*0012*/ signed z:19, deltaZ:13; // coord block, same 19-bit
-/*0016*/ signed x:19; // >>3 packing as spawnStruct
- unsigned heading:13; // h2048 heading (0..2047) in x-word high bits
-/*0020*/ signed y:19, deltaY:13; // deltas unvalidated, unused
-/*0024*/ uint32_t tail; // zero observed
-/*0028*/
+/*0004*/ uint32_t unknown0004;
+/*0008*/ signed x:19; // map-X coord, >>3 to Spawn units (bit64)
+ signed deltaX:13;
+/*0012*/ signed z:19; // z coord, >>3 (bit96)
+ signed deltaZ:13;
+/*0016*/ uint32_t unknown0016; // heading/animation region
+/*0020*/ signed y:19; // map-Y coord, >>3 (bit160)
+ signed deltaY:13;
+/*0024*/
};
/*
-** EQ Legends spawn appearance event (OP_SpawnAppearance = 0x1bdc)
+** EQ Legends spawn appearance event (OP_SpawnAppearance)
** Stock 8B spawnAppearanceStruct u32-widened; fixed 24 bytes on the
** wire (3748/3748 captured packets, both directions).
** Decoded by SpawnShell::spawnEventEQL.
@@ -1607,7 +1627,7 @@
};
/*
-** EQ Legends client zone-change request (OP_ZoneChange = 0x76d3)
+** EQ Legends client zone-change request (OP_ZoneChange)
** Fixed 484 bytes on the wire (32/32 captured packets). Carries
** position but no zone id; the server never sends this opcode (a
** zone change is a session teardown + new session). Layout unmapped;
@@ -2092,7 +2112,7 @@
};
/*
-** EQ Legends death/combat record (opcode 0x295d, subcode 0x07, 36 bytes)
+** EQ Legends death/combat record (subcode 0x07, 36 bytes)
** A combat damage event; the fatal hit is not flagged - spawn removal
** at death is carried by OP_RemoveSpawn/OP_DeleteSpawn, so consumers
** must treat this as informational only.
@@ -2235,10 +2255,10 @@
/*0018*/ uint32_t targetId; // The current selected target
/*0022*/ uint8_t unknown0022[2]; // ***Placeholder
/*0024*/ uint8_t unknown0024[2]; // ***Placeholder
-/*0026*/ uint8_t unknown0026[14]; // ***Placeholder (EQL wire
- // is fixed 40B, 76/76
- // packets; stock was 39)
-/*0040*/
+/*0026*/ uint8_t unknown0026[18]; // ***Placeholder (EQL wire
+ // is fixed 44B - slot@0,
+ // spellId@4, targetId@18)
+/*0044*/
};
/*
@@ -2384,11 +2404,7 @@
/*0000*/ uint32_t exp; // EQ Legends: level progress
// on a 0-100000 scale
// (hundredths of a percent);
- // live was x/330. NOTE: on
- // Legends this rides opcode
- // 6801 (in-game-calibrated
- // against the exp bar; the
- // ids were cross-wired)
+ // live was x/330
/*0004*/ uint32_t unknown0004; // 0 observed
/*0008*/ uint32_t aaUnspent; // unassigned AA points
// (in-game-verified)
@@ -2405,12 +2421,7 @@
{
/*0000*/ uint32_t altexp; // EQ Legends: AA per-point
// progress on a 0-100000
- // scale (live was x/330).
- // NOTE: on Legends this
- // rides opcode 42d1
- // (in-game-calibrated
- // against the AA bar; the
- // ids were cross-wired)
+ // scale (live was x/330)
/*0004*/ uint32_t aapoints; // unassigned AA points
// (in-game-verified)
/*0008*/ uint32_t unknown0008; // varying tail (suffix u32
@@ -2608,6 +2619,30 @@
/*0042*/
};
+// EQ Legends 2026-07-28 real-time client self-state (the 38-byte body on
+// the c2s OP_ClientUpdate/OP_SelfPosEQL stream). Wire-verified against
+// /loc: y@6, z@10, heading@26 (facing packed in the low 21 bits), x@34.
+struct eqlClientSelfPosStruct
+{
+/*0000*/ uint16_t ctr; // update counter
+/*0002*/ uint16_t spawnId; // player's spawn id
+/*0004*/ uint16_t unknown0004;
+/*0006*/ float y; // y coord (loc value 2)
+/*0010*/ float z; // z coord (loc value 3)
+/*0014*/ uint8_t unknown0014[8];
+/*0022*/ union {
+ uint32_t headingRaw; // raw dword @22
+ struct {
+ unsigned :20; // low 20 bits unused for facing
+ unsigned heading :11; // facing 0..2047 (bits 20-30); swept a full circle on a spin
+ unsigned :1;
+ };
+ };
+/*0026*/ uint8_t unknown0026[8];
+/*0034*/ float x; // x coord (loc value 1)
+/*0038*/
+};
+
/*
** Spawn Appearance
** Length: 8 Octets
@@ -2693,6 +2728,17 @@
/*0012*/
};
+// EQ Legends money update (OP_MoneyUpdateEQL): the player's full running
+// coin totals (not a live-style per-coin delta), sent when money changes.
+struct moneyUpdateEQLStruct
+{
+/*0000*/ uint32_t platinum; // current platinum total
+/*0004*/ uint32_t gold; // current gold total
+/*0008*/ uint32_t silver; // current silver total
+/*0012*/ uint32_t copper; // current copper total
+/*0016*/
+};
+
/* Memorize slot operations, mem, forget, etc */
struct memorizeSlotStruct
Modified: showeq/branches/showeqlegends/src/group.cpp
===================================================================
--- showeq/branches/showeqlegends/src/group.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/group.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -70,8 +70,8 @@
// EQ Legends does NOT resend the group roster on zone-in (verified
// 2026-07-09: zoned mid-group, no group packets followed the
// profile), so we must NOT clear here - the group persists across
- // zones and is only changed by the per-member add/remove opcodes
- // (0x1512 / 0x09aa). Clearing here (stock behavior, which relied on
+ // zones and is only changed by the per-member add/remove opcodes.
+ // Clearing here (stock behavior, which relied on
// a post-profile groupUpdate to repopulate) would wipe the group on
// every zone with nothing to refill it.
(void)player;
@@ -243,10 +243,10 @@
void GroupMgr::groupRosterEQL(const uint8_t* data, size_t len)
{
- // EQ Legends full group roster (OP_GroupUpdate = 0x397d), resent at
- // zone-in - the group analog of the buff list (0x77ae): it loads the
- // members you already have when ShowEQ zones in or starts up mid-
- // group, which the incremental 0x1512/0x09aa updates cannot. The
+ // EQ Legends full group roster (OP_GroupUpdate), resent at zone-in -
+ // the group analog of the buff list: it loads the members you already
+ // have when ShowEQ zones in or starts up mid-group, which the
+ // incremental member add/remove updates cannot. The
// stock groupUpdate parser cannot read this format (verified), so it
// needs a dedicated decoder. Header: u32 groupId | u32 count |
// leader name @8; then count 44-byte member records from offset 18
Modified: showeq/branches/showeqlegends/src/guildshell.cpp
===================================================================
--- showeq/branches/showeqlegends/src/guildshell.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/guildshell.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -115,13 +115,13 @@
void GuildMember::update(const GuildMemberUpdate* gmu)
{
- // EQ Legends: the 0x51ed member-update reliably carries only
+ // EQ Legends: the member-update reliably carries only
// guildId, name, and rank - the zone/instance/lastOn tail is
// uninitialized server memory (0x7fff.. pointer bytes observed).
// A member logging off sends one of these with a garbage zone
// (e.g. 5376), which then drove a bogus zoneNameFromID lookup and
// a spurious "zone not found" console line for an offline member.
- // Zone/lastOn are authoritative from the roster (0x31ed) only;
+ // Zone/lastOn are authoritative from the roster only;
// leave them untouched here.
(void)gmu;
#ifdef GUILDSHELL_DIAG
Modified: showeq/branches/showeqlegends/src/interface.cpp
===================================================================
--- showeq/branches/showeqlegends/src/interface.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/interface.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -631,7 +631,7 @@
{
connect(m_zoneMgr, SIGNAL(playerProfile(const charProfileStruct*)),
m_groupMgr, SLOT(player(const charProfileStruct*)));
- // EQL: 0x397d is the full group roster, resent at zone-in (the
+ // EQL: the full group roster, resent at zone-in (the
// Legends wire uses per-member 0x1512/0x09aa for live changes and
// this full roster on zone). Authoritative - clears + repopulates.
m_packet->connect2("OP_GroupUpdate", SP_Zone, DIR_Server,
@@ -710,7 +710,7 @@
if (m_guildShell)
{
- // EQL: 0x31ed roster is stock's layout except a 1-byte-wider
+ // EQL: the roster is stock's layout except a 1-byte-wider
// header, classMask in the class slot, and zoneId in live's
// skipped tail; GuildShell handles all three.
m_packet->connect2("OP_GuildMemberList", SP_Zone, DIR_Server,
@@ -765,7 +765,7 @@
m_packet->connect2("OP_Emote", SP_Zone, DIR_Server|DIR_Client,
"emoteTextStruct", SZC_None,
m_messageShell, SLOT(emoteText(const uint8_t*)));
- // EQL: 0x17af inspect answer is the stock inspectDataStruct
+ // EQL: the inspect answer is the stock inspectDataStruct
// (head byte-perfect; the 1956B wire size equals the struct
// incl. its unknown1772 tail - 3/3 captured inspects), so the
// size check is back on.
@@ -806,7 +806,7 @@
m_packet->connect2("OP_MemorizeSpell", SP_Zone, DIR_Server|DIR_Client,
"memSpellStruct", SZC_Match,
m_messageShell, SLOT(handleSpell(const uint8_t*, size_t, uint8_t)));
- // EQL: 0x5591 = stock beginCastStruct (spellId u16@0, spawnId
+ // EQL: stock beginCastStruct (spellId u16@0, spawnId
// u16@4 wire-verified); 19B vs stock 11B so no size check.
m_packet->connect2("OP_BeginCast", SP_Zone, DIR_Server|DIR_Client,
"beginCastStruct", SZC_None,
@@ -814,9 +814,9 @@
m_packet->connect2("OP_BuffFadeMsg", SP_Zone, DIR_Server|DIR_Client,
"spellFadedStruct", SZC_None,
m_messageShell, SLOT(spellFaded(const uint8_t*)));
- // EQL: 0x10b5 = stock startCastStruct (slot@0, spellId@4,
+ // EQL: stock startCastStruct (slot@0, spellId@4,
// targetId@18). startCast prints the player's own cast WITH its
- // target; OP_BeginCast (0x5591) prints other spawns' casts and
+ // target; OP_BeginCast prints other spawns' casts and
// skips self, so together there is exactly one line per cast and
// the self line keeps its target.
m_packet->connect2("OP_CastSpell", SP_Zone, DIR_Server|DIR_Client,
@@ -926,9 +926,9 @@
m_packet->connect2("OP_Action2", SP_Zone, DIR_Client|DIR_Server,
"action2Struct", SZC_Match,
this, SLOT(action2Message(const uint8_t*)));
- // EQL: 0x66cb is stock OP_Death - newCorpseStruct fits byte-perfect
+ // EQL: stock OP_Death - newCorpseStruct fits byte-perfect
// (40B; corpseid always 0 since corpses never spawn on the Legends
- // wire; community-corroborated 2026-07-09). The 0x295d subcode
+ // wire; community-corroborated community wire). The subcode
// channel is registered separately as OP_DeathEQL.
m_packet->connect2("OP_Death", SP_Zone, DIR_Server,
"newCorpseStruct", SZC_Match,
@@ -1025,7 +1025,7 @@
m_packet->connect2("OP_Death", SP_Zone, DIR_Server,
"newCorpseStruct", SZC_Match,
m_spawnShell, SLOT(killSpawn(const uint8_t*)));
- // EQL: report-only decoder for the 0x295d subcode channel (both dirs
+ // EQL: report-only decoder for the subcode channel (both dirs
// so the c2s 2/9/25B classes are consumed without dispatcher warnings).
m_packet->connect2("OP_DeathEQL", SP_Zone, DIR_Server|DIR_Client,
"deathRecordEQLStruct", SZC_None,
@@ -1044,7 +1044,7 @@
m_packet->connect2("OP_LootDrops", SP_Zone, DIR_Server,
"uint8_t", SZC_None,
m_messageShell, SLOT(lootDrops(const uint8_t*, size_t, uint8_t)));
- // EQL: live money-total update (0x5203); print PlayerMoney on change
+ // EQL: live money-total update; print PlayerMoney on change
m_packet->connect2("OP_MoneyUpdateEQL", SP_Zone, DIR_Server,
"uint8_t", SZC_None,
m_messageShell, SLOT(moneyUpdateEQL(const uint8_t*, size_t, uint8_t)));
@@ -1064,7 +1064,7 @@
m_packet->connect2("OP_Consider", SP_Zone, DIR_Server|DIR_Client,
"considerStruct", SZC_Match,
m_spawnShell, SLOT(consMessage(const uint8_t*, size_t, uint8_t)));
- // EQ Legends 2026-07-07: opcode 0x2735 is a stat tick channel, not
+ // EQ Legends: this opcode is a stat tick channel, not
// movement (xml name OP_SpawnStatEQL); movement rides OP_MobUpdate.
// The old npcMoveUpdate binding is disabled - its 13-24 byte accept
// window decoded the 21B stat ticks as coordinates and leaked
@@ -1072,7 +1072,7 @@
// m_packet->connect2("OP_NpcMoveUpdate", SP_Zone, DIR_Server,
// "uint8_t", SZC_None,
// m_spawnShell, SLOT(npcMoveUpdate(const uint8_t*, size_t, uint8_t)));
- // EQ Legends 2026-07-08: OP_NpcMoveUpdate relocated to 0x7352 - the
+ // EQ Legends: OP_NpcMoveUpdate relocated - the
// live-rate NPC pathing channel lost in the 07/07 rotation. EQL bit
// layout differs from stock (sign+magnitude coords, pad word), so a
// dedicated decoder consumes it (SpawnShell::npcMoveUpdateEQL).
@@ -1088,7 +1088,7 @@
m_packet->connect2("OP_HPUpdate", SP_Zone, DIR_Server,
"uint8_t", SZC_None,
m_spawnShell, SLOT(statUpdateEQL(const uint8_t*, size_t, uint8_t)));
- // EQL: 0x1bdc is stock OP_SpawnAppearance with a u32-widened struct
+ // EQL: stock OP_SpawnAppearance with a u32-widened struct
// (was misnamed OP_Consider, then OP_SpawnEventEQL); dedicated
// decoder, stock 8B spawnAppearanceStruct handler disabled.
m_packet->connect2("OP_SpawnAppearance", SP_Zone, DIR_Server|DIR_Client,
@@ -1097,7 +1097,7 @@
// EQ Legends: stock live handlers playerUpdate/playerUpdate2 pass
// deltas and animation from live struct layouts into updateSpawn.
// EQL 0x0b03 records do not use those layouts; when the
- // OP_ClientUpdate name moved to 0x0b03 these connects came alive
+ // OP_ClientUpdate name moved; these connects came alive
// and garbage deltas sent player dots racing north. Disconnected
// until an EQL delta source is wire-validated.
m_packet->connect2("OP_CorpseLocResponse", SP_Zone, DIR_Server,
@@ -1133,26 +1133,19 @@
m_packet->connect2("OP_CastSpell", SP_Zone, DIR_Server|DIR_Client,
"startCastStruct", SZC_Match,
m_spellShell, SLOT(selfStartSpellCast(const uint8_t*)));
- // 0x3ada is OP_Buff as a compact record (24B here); the shared buffChange
+ // OP_Buff as a compact record (24B here); the shared buffChange
// decoder consumes it (no size check - it also takes the 16B live form).
// The stock 168B buffStruct never occurs on this wire.
m_packet->connect2("OP_Buff", SP_Zone, DIR_Server,
"uint8_t", SZC_None,
m_spellShell, SLOT(buffChange(const uint8_t*, size_t, uint8_t)));
- // EQL: 0x77ae is the per-spawn buff LIST (authoritative; loads
- // active buffs at zone-in with real remaining durations).
+ // EQL: the per-spawn buff LIST (authoritative; loads active buffs at
+ // zone-in with real remaining durations). A single feed now carries
+ // every spawn population (self/pet/other), keyed by spawn id; the
+ // earlier split across separate ids was consolidated into this one.
m_packet->connect2("OP_BuffList", SP_Zone, DIR_Server,
"uint8_t", SZC_None,
m_spellShell, SLOT(buffList(const uint8_t*, size_t, uint8_t)));
- // EQL: Legends splits the buff-list feed across three ids by spawn
- // population (self/pet/other); identical format, same decoder.
- // Duplicate-name wiring follows the stock OP_Group*2 pattern.
- m_packet->connect2("OP_BuffList2", SP_Zone, DIR_Server,
- "uint8_t", SZC_None,
- m_spellShell, SLOT(buffList(const uint8_t*, size_t, uint8_t)));
- m_packet->connect2("OP_BuffList3", SP_Zone, DIR_Server,
- "uint8_t", SZC_None,
- m_spellShell, SLOT(buffList(const uint8_t*, size_t, uint8_t)));
m_packet->connect2("OP_Action", SP_Zone, DIR_Server|DIR_Client,
"actionStruct", SZC_Match,
m_spellShell, SLOT(action(const uint8_t*, size_t, uint8_t)));
@@ -1183,7 +1176,7 @@
m_packet->connect2("OP_ClientUpdate", SP_Zone, DIR_Client,
"uint8_t", SZC_None,
m_player, SLOT(playerSelfState(const uint8_t*, size_t, uint8_t)));
- // EQ Legends 2026-07-07: the c2s self-state moved to opcode 0x0201
+ // EQ Legends: the c2s self-state moved to a new opcode
// (xml name OP_SelfPosEQL); same handler, new opcode.
m_packet->connect2("OP_SelfPosEQL", SP_Zone, DIR_Client,
"uint8_t", SZC_None,
Modified: showeq/branches/showeqlegends/src/message.h
===================================================================
--- showeq/branches/showeqlegends/src/message.h 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/message.h 2026-07-29 02:38:41 UTC (rev 1682)
@@ -69,7 +69,7 @@
MT_Hunt,
MT_Locate,
MT_ChatChannel, // EQL UCS: cross-zone/General channel chat (port 9877)
- MT_Loot, // EQL loot-and-sell notifications (OP_LootMessageEQL 0x32f7)
+ MT_Loot, // EQL loot-and-sell notifications (OP_LootMessageEQL)
MT_Max = MT_Loot,
};
Modified: showeq/branches/showeqlegends/src/messageshell.cpp
===================================================================
--- showeq/branches/showeqlegends/src/messageshell.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/messageshell.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -547,7 +547,7 @@
}
-// EQL loot-and-sell notification (OP_LootMessageEQL 0x32f7):
+// EQL loot-and-sell notification (OP_LootMessageEQL):
// [u32 formatId][NUL-terminated preformatted text]
// formatId 286 = "You looted a <item> from a <corpse> and sold it for
// <money>." The item is an inline serialized link - a long uppercase-hex
@@ -604,7 +604,7 @@
m_messages->addMessage(MT_Loot, text);
}
-// EQL personal loot list (OP_LootDrops 0x5a29): the items YOU can loot
+// EQL personal loot list (OP_LootDrops): the items YOU can loot
// off a corpse (Legends forced personal loot). Layout:
// [2 bytes][u32][u32 corpseId @6][u32 count @10][corpse name NUL]
// then per-item fields. Each item name is a clean NUL-terminated
@@ -715,7 +715,7 @@
m_messages->addMessage(MT_Money, "Update");
}
-// EQL live money update (OP_MoneyUpdateEQL 0x5203): 16 bytes,
+// EQL live money update (OP_MoneyUpdateEQL): 16 bytes,
// [u32 platinum][u32 gold][u32 silver][u32 copper] = current totals on
// the player. Fires periodically; announce only when the totals change
// so the console money line tracks coin live (stock only sets it from
@@ -724,10 +724,11 @@
{
if (dir != DIR_Server || len < 16)
return;
- uint32_t p = eqtohuint32(data);
- uint32_t g = eqtohuint32(data + 4);
- uint32_t s = eqtohuint32(data + 8);
- uint32_t c = eqtohuint32(data + 12);
+ const moneyUpdateEQLStruct* m = (const moneyUpdateEQLStruct*)data;
+ uint32_t p = m->platinum;
+ uint32_t g = m->gold;
+ uint32_t s = m->silver;
+ uint32_t c = m->copper;
static uint32_t lp = ~0u, lg = ~0u, ls = ~0u, lc = ~0u;
if (p == lp && g == lg && s == ls && c == lc)
return;
Modified: showeq/branches/showeqlegends/src/packetformat.cpp
===================================================================
--- showeq/branches/showeqlegends/src/packetformat.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/packetformat.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -29,17 +29,17 @@
#include <zlib.h>
// UPSTREAM: mechanism benefits live too; the floor bytes below are the
-// historically-observed values (the 0x88 example is a Legends id).
+// historically-observed low-byte seed values.
// Low bytes of the flag-split opcode channels (see packetformat.h). Seeded
// with the historically-observed bytes as a floor; EQPacket overwrites/adds
// to this from the loaded opcode map so it tracks OP_ClientUpdate's current
-// id automatically. 0x88 = OP_ClientUpdate 0x5188 (2026-07-14 rotation).
+// id automatically.
bool eqFlagSplitLowByte[256] = { false };
static struct EqFlagSplitInit {
EqFlagSplitInit() {
- eqFlagSplitLowByte[0x71] = true; // pre-2026-07 OP_ClientUpdate family
+ eqFlagSplitLowByte[0x71] = true; // pre-rotation OP_ClientUpdate family
eqFlagSplitLowByte[0x52] = true;
- eqFlagSplitLowByte[0x88] = true; // 2026-07-14 OP_ClientUpdate 0x5188
+ eqFlagSplitLowByte[0x88] = true; // a later OP_ClientUpdate rotation
}
} g_eqFlagSplitInit;
Modified: showeq/branches/showeqlegends/src/player.cpp
===================================================================
--- showeq/branches/showeqlegends/src/player.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/player.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -1260,7 +1260,7 @@
void Player::playerSelfState(const uint8_t* data, size_t len, uint8_t dir)
{
/*
- EQ Legends OP_ClientUpdate (0x0b03) client direction: the 42 byte
+ EQ Legends OP_ClientUpdate client direction: the 42 byte
self-state struct. On the wire it is flag-split raw or zlib; the
packet layer reconstitutes the opcode and inflates, so the payload
arrives here aligned and plaintext (a 44 byte variant exists and its
@@ -1271,7 +1271,7 @@
same space the live self-update carries. Wire x/y transpose to map
y/x, the same convention as the keepalive path above.
*/
- // EQ Legends 2026-07-07: self-state moved to c2s opcode 0x0201 with
+ // EQ Legends: self-state moved to a c2s opcode with
// floats at offsets 0/4/8 in the order (map Y, map X, Z) - the same
// transposed convention as the spawn and MobUpdate paths. Verified
// against backfill position. Minimum observed length is 16 bytes of
@@ -1281,22 +1281,21 @@
// EQ Legends 2026-07-15: the real-time CLIENT self-state - a 38-byte
// float body carrying the player's own spawnId @2, the freshest
- // position, AND the only client-side facing. Wire-verified from
- // ShowEQ's delivered bytes (id matched, heading held constant on a
- // straight run then swept on a turn):
- // u16 ctr @0, u16 spawnId @2, float Z @10, float mapX @14,
- // u32 heading @18 (facing in the low 21 bits; full circle 2^21, so
- // (&0x1FFFFF)>>10 = EQ h2048), float mapY @26.
+ // position, AND the only client-side facing.
+ // 2026-07-28 patch: the 0728 client rotated the field offsets within
+ // the same 38-byte body (wire-verified from delivered bytes - @6/@34
+ // tracked movement smoothly, @14 became a ~0 velocity delta, @18 went
+ // to a constant 0, and @26 now carries the quiet-NaN facing):
+ // float Z @10, float mapX @6, float mapY @34,
+ // u32 heading @26 (facing in the low 21 bits; full circle 2^21, so
+ // (&0x1FFFFF)>>10 = EQ h2048).
+ // Old 0714 layout was mapX@14, heading@18, mapY@26.
// This supersedes the 1.5-2s-stale %17 flush below for freshness
- // (m_selfStateAge gate). If the dot lands mirrored, swap @14/@26.
+ // (m_selfStateAge gate). If the dot lands mirrored, swap @6/@34.
if (len == 38)
{
- float zz, mx, my;
- uint32_t hraw;
- memcpy(&zz, data + 10, 4);
- memcpy(&mx, data + 14, 4);
- memcpy(&hraw, data + 18, 4);
- memcpy(&my, data + 26, 4);
+ const eqlClientSelfPosStruct *sp = (const eqlClientSelfPosStruct*)data;
+ float zz = sp->z, mx = sp->x, my = sp->y;
if ((mx != 0.0f || my != 0.0f) &&
fabsf(mx) < 100000.0f && fabsf(my) < 100000.0f && fabsf(zz) < 10000.0f)
{
@@ -1311,7 +1310,7 @@
updateLastChanged();
emit changeItem(this, tSpawnChangedPosition);
}
- int h2048 = (hraw & 0x1FFFFF) >> 10;
+ int h2048 = sp->heading;
if (h2048 <= 2047)
{
setHeading(h2048, 0);
@@ -1385,7 +1384,7 @@
return;
}
- // The 42-byte self-state (0x7171 client dir; live analog of the
+ // The 42-byte self-state (client dir; live analog of the
// pre-patch 0x0b03 42B struct). Layout, wire-validated 2026-07-08
// against a controlled facing test and a tracked run:
// u32 seq @0, u16 zero @4, float @6 (turn-rate-like, unconsumed),
Modified: showeq/branches/showeqlegends/src/s_everquest.h
===================================================================
--- showeq/branches/showeqlegends/src/s_everquest.h 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/s_everquest.h 2026-07-29 02:38:41 UTC (rev 1682)
@@ -30,6 +30,7 @@
AddStruct(ClientZoneEntryStruct);
AddStruct(newZoneStruct);
AddStruct(dzSwitchInfo);
+AddStruct(dzSwitchInfoEQLStruct);
AddStruct(dzInfo);
AddStruct(playerProfileStruct);
AddStruct(charProfileStruct);
@@ -110,6 +111,7 @@
AddStruct(randomStruct);
AddStruct(playerSpawnPosStruct);
AddStruct(playerSelfPosStruct);
+AddStruct(eqlClientSelfPosStruct);
AddStruct(spawnAppearanceStruct);
AddStruct(bindWoundStruct);
AddStruct(inspectedStruct);
@@ -118,6 +120,7 @@
AddStruct(newGuildInZoneStruct);
AddStruct(guildsInZoneListStruct);
AddStruct(moneyUpdateStruct);
+AddStruct(moneyUpdateEQLStruct);
AddStruct(memorizeSlotStruct);
AddStruct(cRunToggleStruct);
AddStruct(cChatFiltersStruct);
Modified: showeq/branches/showeqlegends/src/spawnshell.cpp
===================================================================
--- showeq/branches/showeqlegends/src/spawnshell.cpp 2026-07-24 20:43:30 UTC (rev 1681)
+++ showeq/branches/showeqlegends/src/spawnshell.cpp 2026-07-29 02:38:41 UTC (rev 1682)
@@ -826,15 +826,12 @@
// 2026-07-07 EQL patch inserted 8 bytes here, between the equipment
// block and the position words (content unidentified - possibly the
// relocated heading/animation fields; word values 0x6000/0 observed).
- netStream.skipBytes(8);
-
- // EQ Legends posData is 4 words (z/x/y coord words + the 0x6000
- // heading word); live's 5th word does not exist on this wire -
- // it was previously absorbing the first 4 bytes of the string
- // block, truncating titles (the first 4 title chars were lost).
- for (int i = 0; i < 4; ++i)
+ // One leadi...
[truncated message content] |