From b5cc8dfab1b38f5edd3c0994cbfbe77b8e3c3c93 Mon Sep 17 00:00:00 2001 From: dannuic Date: Tue, 14 Apr 2026 13:39:28 -0500 Subject: [PATCH] Verified and corrected packets through character select --- common/patches/tob.cpp | 47 ++++++++++++++++++++++++++++++++++++ common/patches/tob_ops.h | 2 ++ common/patches/tob_structs.h | 44 +++++++++++++++++++++++++++++++++ tob/opcodes.md | 22 ++++++++--------- utils/patches/patch_TOB.conf | 6 ++--- 5 files changed, 107 insertions(+), 14 deletions(-) diff --git a/common/patches/tob.cpp b/common/patches/tob.cpp index bba8655f9..3b152aa68 100644 --- a/common/patches/tob.cpp +++ b/common/patches/tob.cpp @@ -3532,6 +3532,20 @@ namespace TOB FINISH_DIRECT_DECODE(); } + DECODE(OP_ApproveName) + { + DECODE_LENGTH_EXACT(structs::NameApproval_Struct); + SETUP_DIRECT_DECODE(NameApproval_Struct, structs::NameApproval_Struct); + + IN_str(name); + IN(race_id); + IN(class_id); + + // TODO: expand the approval logic to include the rest of the TOB struct values (and remove the direct translation here) + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_AugmentInfo) { DECODE_LENGTH_EXACT(structs::AugmentInfo_Struct); @@ -3630,6 +3644,39 @@ namespace TOB delete[] __eq_buffer; } + DECODE(OP_CharacterCreate) { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(gender); + IN(race); + IN(class_); + IN(deity); + IN(start_zone); + IN(haircolor); + IN(beard); + IN(beardcolor); + IN(hairstyle); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(tutorial); + + // TODO: can handle the heroic type here as well (new member) + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_ClickDoor) { DECODE_LENGTH_EXACT(structs::ClickDoor_Struct); diff --git a/common/patches/tob_ops.h b/common/patches/tob_ops.h index 22a32b403..afaf305c3 100644 --- a/common/patches/tob_ops.h +++ b/common/patches/tob_ops.h @@ -66,11 +66,13 @@ E(OP_ZoneSpawns) //list of packets we need to decode on the way in: D(OP_Animation) D(OP_ApplyPoison) +D(OP_ApproveName) D(OP_AugmentInfo) D(OP_AugmentItem) D(OP_BlockedBuffs) D(OP_CastSpell) D(OP_ChannelMessage) +D(OP_CharacterCreate) D(OP_ClientUpdate) D(OP_ClickDoor) D(OP_Consider) diff --git a/common/patches/tob_structs.h b/common/patches/tob_structs.h index 9e7da1b07..f859036e6 100644 --- a/common/patches/tob_structs.h +++ b/common/patches/tob_structs.h @@ -186,6 +186,50 @@ namespace TOB { /*000*/ uint32 CharCount; //number of chars in this packet }; + /* + ** Character Creation struct + ** Length: 168 Bytes + ** OpCode: 0x1859 + */ + struct CharCreate_Struct + { + /*00*/ uint8 padding[72]; + /*48*/ uint32 gender; + /*4c*/ uint32 race; + /*50*/ uint32 class_; + /*54*/ uint32 deity; + /*58*/ uint32 start_zone; // this is the zone ID of the start zone + /*5c*/ uint32 haircolor; + /*60*/ uint32 beard; + /*64*/ uint32 beardcolor; + /*68*/ uint32 hairstyle; + /*6c*/ uint32 face; + /*70*/ uint32 eyecolor1; + /*74*/ uint32 eyecolor2; + /*78*/ uint32 drakkin_heritage; + /*7c*/ uint32 drakkin_tattoo; + /*80*/ uint32 drakkin_details; + /*84*/ uint32 STR; + /*88*/ uint32 STA; + /*8c*/ uint32 AGI; + /*90*/ uint32 DEX; + /*94*/ uint32 WIS; + /*98*/ uint32 INT; + /*9c*/ uint32 CHA; + /*a0*/ uint32 tutorial; + /*a4*/ uint32 heroic_type; + /*a8*/ + }; + + struct NameApproval_Struct { + char name[64]; + uint32 race_id; + uint32 class_id; + uint32 deity_id; + uint32 heroic_type; // seen 0, client can also send 1-4 + uint32 unknown; // always 0? + }; + enum TOBAppearance : uint32 { None, diff --git a/tob/opcodes.md b/tob/opcodes.md index 1359c9692..36d89c787 100644 --- a/tob/opcodes.md +++ b/tob/opcodes.md @@ -44,7 +44,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_Animation` | 🟡 Unverified | | | | `OP_AnnoyingZoneUnknown` | 🔴 Not-Set | | | | `OP_ApplyPoison` | 🟡 Unverified | | | -| `OP_ApproveName` | 🟡 Unverified | | | +| `OP_ApproveName` | 🟡 Unverified | This takes multiple parameters from the client, and it can take multiple integer values from the server | | | `OP_ApproveWorld` | 🔴 Not-Set | | | | `OP_ApproveZone` | 🔴 Not-Set | | | | `OP_Assist` | 🟡 Unverified | | | @@ -83,8 +83,8 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_ChangeSize` | 🟡 Unverified | | | | `OP_ChannelMessage` | 🟡 Unverified | | | | `OP_ChangePetName` | 🔴 Not-Set | | | -| `OP_CharacterCreate` | 🟡 Unverified | Wasn't sure on the status of this | | -| `OP_CharacterCreateRequest` | 🟡 Unverified | Wasn't sure on status of this | | +| `OP_CharacterCreate` | 🟢 Verified | Sends heroic type, can be used for something? | | +| `OP_CharacterCreateRequest` | 🟢 Verified | | | | `OP_CharInventory` | 🟡 Unverified | | | | `OP_Charm` | 🟡 Unverified | | | | `OP_ChatMessage` | 🔴 Not-Set | | | @@ -125,7 +125,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_Damage` | 🟡 Unverified | | | | `OP_Death` | 🟡 Unverified | | | | `OP_DelegateAbility` | 🔴 Not-Set | | | -| `OP_DeleteCharacter` | 🟡 Unverified | | | +| `OP_DeleteCharacter` | 🟢 Verified | | | | `OP_DeleteCharge` | 🟡 Unverified | | | | `OP_DeleteItem` | 🟡 Unverified | | | | `OP_DeletePetition` | 🔴 Not-Set | | | @@ -182,7 +182,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_FinishWindow2` | 🟡 Unverified | | | | `OP_Fishing` | 🟡 Unverified | | | | `OP_Fling` | 🟡 Unverified | | | -| `OP_FloatListThing` | 🟡 Unverified | | | +| `OP_FloatListThing` | 🟢 Verified | Movement History. Sent from client, but emu doesn't use it so setting it as varified. Reference is 0x1402FFAD0 | | | `OP_Forage` | 🟡 Unverified | | | | `OP_ForceFindPerson` | 🔴 Not-Set | | | | `OP_FormattedMessage` | 🟡 Unverified | | | @@ -376,7 +376,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_MobUpdate` | 🔴 Not-Set | | | | `OP_MoneyOnCorpse` | 🟡 Unverified | | | | `OP_MoneyUpdate` | 🟡 Unverified | | | -| `OP_MOTD` | 🟡 Unverified | | | +| `OP_MOTD` | 🟢 Verified | | | | `OP_MoveCoin` | 🟡 Unverified | | | | `OP_MoveDoor` | 🟡 Unverified | | | | `OP_MoveItem` | 🟡 Unverified | | | @@ -441,7 +441,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_RaidInvite` | 🔴 Not-Set | | | | `OP_RaidJoin` | 🔴 Not-Set | | | | `OP_RaidUpdate` | 🔴 Not-Set | | | -| `OP_RandomNameGenerator` | 🟡 Unverified | | | +| `OP_RandomNameGenerator` | 🟢 Verified | The client no longer sends this packet (random name generation is done entirely in the client). The client will still accept this packet to set name (emu doesn't do this, but it's always been supported) | | | `OP_RandomReply` | 🟡 Unverified | | | | `OP_RandomReq` | 🟡 Unverified | | | | `OP_ReadBook` | 🟡 Unverified | | | @@ -486,7 +486,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_SendLoginInfo` | 🟢 Verified | | | | `OP_SendMaxCharacters` | 🟢 Verified | | | | `OP_SendMembership` | 🟢 Verified | | | -| `OP_SendMembershipDetails` | 🟢 Unverified | The struct is correct, will need reversing for actual option keys/values | | +| `OP_SendMembershipDetails` | 🟢 Verified | The struct is correct, will need reversing for actual option keys/values | | | `OP_SendSystemStats` | 🔴 Not-Set | | | | `OP_SendTitleList` | 🔴 Not-Set | | | | `OP_SendTributes` | 🔴 Not-Set | | | @@ -497,7 +497,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_ServerListResponse` | 🔴 Not-Set | | | | `OP_SessionReady` | 🔴 Not-Set | | | | `OP_SetChatServer` | 🔴 Not-Set | | | -| `OP_SetChatServer2` | 🟡 Unverified | | | +| `OP_SetChatServer2` | 🟢 Verified | | | | `OP_SetFace` | 🔴 Not-Set | | | | `OP_SetGroupTarget` | 🔴 Not-Set | | | | `OP_SetGuildMOTD` | 🔴 Not-Set | | | @@ -612,10 +612,10 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_World_Client_CRC2` | 🟢 Verified | | | | `OP_World_Client_CRC3` | 🟢 Verified | | | | `OP_WorldClientReady` | 🟡 Unverified | | | -| `OP_WorldComplete` | 🟡 Unverified | | | +| `OP_WorldComplete` | 🟢 Verified | | | | `OP_WorldLogout` | 🔴 Not-Set | | | | `OP_WorldObjectsSent` | 🟡 Unverified | | | -| `OP_WorldUnknown001` | 🟡 Unverified | | | +| `OP_WorldUnknown001` | 🟢 Verified | SetServerTime. emu doesn't currently use it so setting it to verified, but the reference is 0x140292550 | | | `OP_XTargetAutoAddHaters` | 🔴 Not-Set | | | | `OP_XTargetOpen` | 🔴 Not-Set | | | | `OP_XTargetOpenResponse` | 🔴 Not-Set | | | diff --git a/utils/patches/patch_TOB.conf b/utils/patches/patch_TOB.conf index d3264a945..3102e24a3 100644 --- a/utils/patches/patch_TOB.conf +++ b/utils/patches/patch_TOB.conf @@ -34,15 +34,15 @@ OP_SendMembershipDetails=0x2373 OP_CharacterCreateRequest=0x6b67 OP_CharacterCreate=0x1859 OP_DeleteCharacter=0x71ca -OP_RandomNameGenerator=0x7f4a +OP_RandomNameGenerator=0x7f4a # TOB client no longer sends this, and the S->C packet isn't used by emu OP_ApproveName=0x5306 OP_MOTD=0x1eef OP_SetChatServer=0x0000 OP_SetChatServer2=0x34c1 OP_ZoneServerInfo=0x2323 OP_WorldComplete=0x1223 -OP_WorldUnknown001=0x7723 -OP_FloatListThing=0x504f +OP_WorldUnknown001=0x7723 # SetServerTime, S->C +OP_FloatListThing=0x504f # Movement History, C->S # Reasons for Disconnect: OP_ZoneUnavail=0x29a6