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