diff --git a/common/base_packet.h b/common/base_packet.h index 93e9435e2..94d8b7df4 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -81,6 +81,7 @@ public: void ReadString(char *str) { uint32 len = static_cast(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; } void ReadString(std::string &str) { str = reinterpret_cast(pBuffer + _rpos); _rpos += str.length() + 1; } void ReadString(char *str, uint32 Offset, uint32 MaxLength) const; + void ReadLengthString(std::string& str) { uint32 len = *(uint32*)(pBuffer + _rpos); _rpos += sizeof(uint32); str.resize(len); memcpy(&str[0], pBuffer + _rpos, len); _rpos += len; } uint32 GetWritePosition() { return _wpos; } uint32 GetReadPosition() { return _rpos; } diff --git a/common/patches/tob.cpp b/common/patches/tob.cpp index e40bda653..0536034b8 100644 --- a/common/patches/tob.cpp +++ b/common/patches/tob.cpp @@ -238,6 +238,22 @@ namespace TOB FINISH_ENCODE(); } + ENCODE(OP_Begging) + { + ENCODE_LENGTH_EXACT(BeggingResponse_Struct); + SETUP_DIRECT_ENCODE(BeggingResponse_Struct, structs::BeggingResponse_Struct); + + OUT(Unknown00); + OUT(Unknown04); + OUT(Unknown08); + eq->Result = static_cast(emu->Result); + OUT(Amount); + eq->StringSize = 0; // set this to 0, but it's a string size + eq->Lucky = 0; // set to 1 to message a lucky beg + + FINISH_ENCODE(); + } + ENCODE(OP_BeginCast) { ENCODE_LENGTH_EXACT(BeginCast_Struct); @@ -597,8 +613,8 @@ namespace TOB OUT(skills[i]); } - eq->unknown408[0] = 1; - eq->unknown408[1] = 0xC9; + eq->unknown408[0] = 1; // this tells the client to update the GM window + eq->unknown408[1] = 0xC9; // these appear to be languages, but it's only testing if this is non-zero eq->unknown408[2] = 0xC9; eq->unknown408[3] = 0xC9; eq->unknown408[4] = 0xC9; @@ -698,8 +714,6 @@ namespace TOB OUT(spawnid); OUT_str(charname); OUT(race); - eq->unknown006[0] = 0; - eq->unknown006[1] = 0; OUT(gender); OUT(texture); OUT(helmtexture); @@ -893,6 +907,7 @@ namespace TOB ENCODE_LENGTH_EXACT(moneyOnCorpseStruct); SETUP_DIRECT_ENCODE(moneyOnCorpseStruct, structs::moneyOnCorpseStruct); + // TODO: The type has changed to accomodate all kinds of loot options and actions, including advloot eq->type = emu->response; OUT(platinum); OUT(gold); @@ -3693,6 +3708,23 @@ namespace TOB DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } + DECODE(OP_CorpseDrag) + { + std::string CorpseName; + __packet->ReadLengthString(CorpseName); + + std::string DraggerName; + __packet->ReadLengthString(DraggerName); + + __packet->SetReadPosition(0); + __packet->size = sizeof(CorpseDrag_Struct); + __packet->pBuffer = new unsigned char[__packet->size]{}; + auto* emu = reinterpret_cast(__packet->pBuffer); + + strncpy(emu->CorpseName, CorpseName.c_str(), 64); + strncpy(emu->DraggerName, DraggerName.c_str(), 64); + } + DECODE(OP_DeleteItem) { DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); @@ -3759,6 +3791,21 @@ namespace TOB DECODE_FORWARD(OP_GroupInvite); } + DECODE(OP_LootItem) + { + DECODE_LENGTH_EXACT(structs::LootingItem_Struct); + SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); + + Log(Logs::Detail, Logs::Netcode, "TOB::DECODE(OP_LootItem)"); + + IN(lootee); + IN(looter); + emu->slot_id = TOBToServerCorpseMainSlot(eq->slot_id); + IN(auto_loot); + + FINISH_DIRECT_DECODE(); + } + DECODE(OP_MemorizeSpell) { DECODE_LENGTH_EXACT(structs::MemorizeSpell_Struct); SETUP_DIRECT_DECODE(MemorizeSpell_Struct, structs::MemorizeSpell_Struct); diff --git a/common/patches/tob_ops.h b/common/patches/tob_ops.h index 01226f487..9384162c1 100644 --- a/common/patches/tob_ops.h +++ b/common/patches/tob_ops.h @@ -4,6 +4,7 @@ E(OP_Action) E(OP_Animation) E(OP_ApplyPoison) E(OP_AugmentInfo) +E(OP_Begging) E(OP_BeginCast) E(OP_BlockedBuffs) E(OP_CancelTrade) @@ -77,12 +78,14 @@ D(OP_ClientUpdate) D(OP_ClickDoor) D(OP_Consider) D(OP_ConsiderCorpse) +D(OP_CorpseDrag) D(OP_DeleteItem) D(OP_EnterWorld) D(OP_GMTraining) D(OP_GroupDisband) D(OP_GroupInvite) D(OP_GroupInvite2) +D(OP_LootItem) D(OP_MemorizeSpell) D(OP_MoveItem) D(OP_RemoveBlockedBuffs) diff --git a/common/patches/tob_structs.h b/common/patches/tob_structs.h index 04a066ad5..cf5c6d8f3 100644 --- a/common/patches/tob_structs.h +++ b/common/patches/tob_structs.h @@ -645,7 +645,7 @@ namespace TOB { { /*000*/ uint32 spawn_id; /*004*/ uint32 killer_id; - /*008*/ uint32 corpseid; //not read by client + /*008*/ uint32 corpseid; /*012*/ uint32 unknown1; //not read by client /*016*/ int32 spell_id; /*020*/ uint32 attack_skill; @@ -790,7 +790,7 @@ namespace TOB { //This is what we call OP_Action //To the client though this is basically a missile hit though //OP_Action is basically "instant missile hit" to the client - //@0x1401f0970 MissileHitInfo::Deserialize(CUnSerializeBuffer *buffer); + //@0x1402024C0 MissileHitInfo::Deserialize(CUnSerializeBuffer *buffer); struct MissileHitInfo { uint16 target; @@ -896,38 +896,34 @@ namespace TOB { struct Illusion_Struct { /*000*/ uint32 spawnid; /*004*/ char charname[64]; - /*068*/ uint16 race; //according to eqlib this is s32 - /*070*/ char unknown006[2]; - /*072*/ uint8 gender; - /*073*/ uint8 texture; - /*074*/ uint8 armorVariation; - /*075*/ uint8 armorMaterial; - /*076*/ uint8 helmtexture; - /*077*/ uint8 unknown077; //padding from this being a pack(4) struct actually - /*078*/ uint8 unknown078; - /*079*/ uint8 unknown079; + /*068*/ int32 race; + /*072*/ int32 class_; + /*076*/ float size; /*080*/ uint32 face; - /*084*/ uint8 hairstyle; - /*085*/ uint8 haircolor; - /*086*/ uint8 beard; - /*087*/ uint8 beardcolor; - /*088*/ float size; - /*092*/ uint32_t npc_tint; - /*096*/ bool keep_armor_properties; - /*097*/ uint8 unknown097[3]; //padding from this being a pack(4) struct actually - /*100*/ ArmorPropertyStruct armorProperties[9]; - /*280*/ uint32_t armorTints[9]; - /*316*/ int32 class_; - /*320*/ uint32 drakkin_heritage; - /*324*/ uint32 drakkin_tattoo; - /*328*/ uint32 drakkin_details; + /*084*/ uint32 npc_tint; + /*088*/ uint32 keep_armor_properties; + /*092*/ uint32 drakkin_heritage; + /*096*/ uint32 drakkin_tattoo; + /*100*/ uint32 drakkin_details; + /*104*/ uint8 gender; + /*105*/ uint8 texture; + /*106*/ uint8 helmtexture; + /*107*/ uint8 armorVariation; + /*108*/ uint8 armorMaterial; + /*109*/ uint8 hairstyle; + /*110*/ uint8 haircolor; + /*111*/ uint8 beard; + /*112*/ uint8 beardcolor; + /*113*/ uint8 padding[3]; + /*116*/ ArmorPropertyStruct armorProperties[9]; + /*296*/ uint32 armorTints[9]; /*332*/ }; struct moneyOnCorpseStruct { - /*000*/ uint8 type; + /*000*/ uint8 type; // 0 = someone is already looting, 1 = OK, 2 = cannot access at this time, 3 = OK, 4 = cannot loot while hostile nearby, 5 = too far away to loot, 6 = loot all, 7 = cancel loot, 8 = add access, 9 = using advloot (when right clicking), 10 = show advloot /*001*/ uint8 padding1[3]; - /*004*/ uint32 flags; + /*004*/ uint32 flags; // 1 = extra lucky bonus, 2 = lucky bonus, 4 = bonus /*008*/ uint32 platinum; /*012*/ uint32 gold; /*016*/ uint32 silver; @@ -935,6 +931,15 @@ namespace TOB { /*024*/ }; + struct LootingItem_Struct { + /*000*/ uint32 lootee; + /*004*/ uint32 looter; + /*008*/ uint32 slot_id; + /*012*/ int32 auto_loot; + /*016*/ uint32 unknown16; + /*020*/ + }; + struct GroupGeneric_Struct { /*0000*/ char name1[64]; /*0064*/ char name2[64]; @@ -1102,6 +1107,17 @@ namespace TOB { uint32 Zone; }; + struct BeggingResponse_Struct + { + /*00*/ uint32 Unknown00; + /*04*/ uint32 Unknown04; + /*08*/ uint32 Unknown08; + /*12*/ uint8 Result; // 0 = Fail, 1 = Plat, 2 = Gold, 3 = Silver, 4 = Copper + /*13*/ uint32 Amount; + /*17*/ uint32 StringSize; // set this to 0, but it's a string size + /*21*/ uint8 Lucky; // set to 1 to message a lucky beg + }; + #pragma pack() }; //end namespace structs diff --git a/tob/opcodes.md b/tob/opcodes.md index 0539e74af..eb34f557c 100644 --- a/tob/opcodes.md +++ b/tob/opcodes.md @@ -12,7 +12,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_AAExpUpdate` | 🟢 Verified | | | | `OP_AcceptNewTask` | 🔴 Not-Set | | | | `OP_AckPacket` | 🟢 Verified | | | -| `OP_Action` | 🟡 Unverified | | | +| `OP_Action` | 🟢 Verified | | | | `OP_Action2` | 🔴 Not-Set | | | | `OP_AddNimbusEffect` | 🟡 Unverified | | | | `OP_AdventureData` | 🔴 Not-Set | | | @@ -41,7 +41,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_AltCurrencyReclaim` | 🔴 Not-Set | | | | `OP_AltCurrencySell` | 🔴 Not-Set | | | | `OP_AltCurrencySellSelection` | 🔴 Not-Set | | | -| `OP_Animation` | 🟡 Unverified | | | +| `OP_Animation` | 🟢 Verified | | | | `OP_AnnoyingZoneUnknown` | 🔴 Not-Set | | | | `OP_ApplyPoison` | 🟡 Unverified | | | | `OP_ApproveName` | 🟡 Unverified | This takes multiple parameters from the client, and it can take multiple integer values from the server | | @@ -53,7 +53,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_AugmentItem` | 🟡 Unverified | | | | `OP_AutoAttack` | 🟡 Unverified | | | | `OP_AutoAttack2` | 🟡 Unverified | | | -| `OP_AutoFire` | 🟡 Unverified | | | +| `OP_AutoFire` | 🟢 Verified | | | | `OP_Bandolier` | 🔴 Not-Set | | | | `OP_BankerChange` | 🟡 Unverified | | | | `OP_Barter` | 🔴 Not-Set | | | @@ -62,7 +62,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_BazaarSearch` | 🔴 Not-Set | | | | `OP_BecomeCorpse` | 🔴 Not-Set | | | | `OP_BecomeTrader` | 🔴 Not-Set | | | -| `OP_Begging` | 🟡 Unverified | | | +| `OP_Begging` | 🟢 Verified | | | | `OP_BeginCast` | 🟢 Verified | | | | `OP_Bind_Wound` | 🟡 Unverified | | | | `OP_BlockedBuffs` | 🟢 Verified | | | @@ -107,30 +107,30 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_Command` | 🔴 Not-Set | | | | `OP_CompletedTasks` | 🔴 Not-Set | | | | `OP_ConfirmDelete` | 🟡 Unverified | | | -| `OP_Consent` | 🟡 Unverified | | | -| `OP_ConsentDeny` | 🟡 Unverified | | | +| `OP_Consent` | 🟢 Verified | | | +| `OP_ConsentDeny` | 🟢 Verified | | | | `OP_ConsentResponse` | 🟢 Verified | | | | `OP_Consider` | 🟢 Verified | | | -| `OP_ConsiderCorpse` | 🟡 Unverified | | | +| `OP_ConsiderCorpse` | 🟢 Verified | | | | `OP_Consume` | 🟡 Unverified | | | | `OP_ControlBoat` | 🟡 Unverified | | | -| `OP_CorpseDrag` | 🟡 Unverified | | | -| `OP_CorpseDrop` | 🟡 Unverified | | | +| `OP_CorpseDrag` | 🟢 Verified | | | +| `OP_CorpseDrop` | 🟢 Verified | | | | `OP_CrashDump` | 🔴 Not-Set | | | | `OP_CrystalCountUpdate` | 🔴 Not-Set | | | | `OP_CrystalCreate` | 🔴 Not-Set | | | | `OP_CrystalReclaim` | 🔴 Not-Set | | | | `OP_CustomTitles` | 🔴 Not-Set | | | | `OP_Damage` | 🟡 Unverified | | | -| `OP_Death` | 🟡 Unverified | | | +| `OP_Death` | 🟢 Verified | | | | `OP_DelegateAbility` | 🔴 Not-Set | | | | `OP_DeleteCharacter` | 🟢 Verified | | | | `OP_DeleteCharge` | 🟡 Unverified | | | | `OP_DeleteItem` | 🟡 Unverified | | | | `OP_DeletePetition` | 🔴 Not-Set | | | | `OP_DeleteSpawn` | 🟡 Unverified | | | -| `OP_DeleteSpell` | 🟡 Unverified | | | -| `OP_DenyResponse` | 🟡 Unverified | | | +| `OP_DeleteSpell` | 🟢 Verified | | | +| `OP_DenyResponse` | 🟢 Verified | appears unused by server or client | | | `OP_Disarm` | 🟡 Unverified | | | | `OP_DisarmTraps` | 🟡 Unverified | | | | `OP_DisciplineTimer` | 🟡 Unverified | | | @@ -162,7 +162,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_DzSetLeaderName` | 🔴 Not-Set | | | | `OP_DzSwapPlayer` | 🔴 Not-Set | | | | `OP_Emote` | 🔴 Not-Set | | | -| `OP_EndLootRequest` | 🟡 Unverified | | | +| `OP_EndLootRequest` | 🟢 Verified | can be sent to close the client's looting session (with no data) | | | `OP_EnduranceUpdate` | 🔴 Not-Set | | | | `OP_EnterChat` | 🔴 Not-Set | | | | `OP_EnterWorld` | 🟢 Verified | | | @@ -194,7 +194,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_GMBecomeNPC` | 🔴 Not-Set | | | | `OP_GMDelCorpse` | 🔴 Not-Set | | | | `OP_GMEmoteZone` | 🔴 Not-Set | | | -| `OP_GMEndTraining` | 🟡 Unverified | | | +| `OP_GMEndTraining` | 🟢 Verified | | | | `OP_GMEndTrainingResponse` | 🔴 Not-Set | | | | `OP_GMFind` | 🔴 Not-Set | | | | `OP_GMGoto` | 🔴 Not-Set | | | @@ -207,9 +207,9 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_GMServers` | 🔴 Not-Set | | | | `OP_GMSummon` | 🔴 Not-Set | | | | `OP_GMToggle` | 🔴 Not-Set | | | -| `OP_GMTraining` | 🟡 Unverified | | | -| `OP_GMTrainSkill` | 🟡 Unverified | | | -| `OP_GMTrainSkillConfirm` | 🟡 Unverified | | | +| `OP_GMTraining` | 🟢 Verified | | | +| `OP_GMTrainSkill` | 🟢 Verified | | | +| `OP_GMTrainSkillConfirm` | 🟢 Verified | | | | `OP_GMZoneRequest` | 🔴 Not-Set | | | | `OP_GMZoneRequest2` | 🔴 Not-Set | | | | `OP_GroundSpawn` | 🟢 Verified | | | @@ -277,9 +277,9 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_GuildWar` | 🔴 Not-Set | | | | `OP_Heartbeat` | 🔴 Not-Set | | | | `OP_Hide` | 🟡 Unverified | | | -| `OP_HideCorpse` | 🟡 Unverified | | | +| `OP_HideCorpse` | 🟢 Verified | | | | `OP_HPUpdate` | 🟢 Verified | | | -| `OP_Illusion` | 🟡 Unverified | | | +| `OP_Illusion` | 🟢 Verified | Actually a generic appearance change packet, including name for self | | | `OP_IncreaseStats` | 🟡 Unverified | | | | `OP_InitialHPUpdate` | 🔴 Not-Set | | | | `OP_InitialMobHealth` | 🔴 Not-Set | | | @@ -342,9 +342,9 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_Logout` | 🟡 Unverified | | | | `OP_LogoutReply` | 🔴 Not-Set | | | | `OP_LogServer` | 🟢 Verified | Mostly unused values | | -| `OP_LootComplete` | 🟡 Unverified | | | -| `OP_LootItem` | 🟡 Unverified | | | -| `OP_LootRequest` | 🟡 Unverified | | | +| `OP_LootComplete` | 🟢 Verified | | | +| `OP_LootItem` | 🟢 Verified | | | +| `OP_LootRequest` | 🟢 Verified | | | | `OP_ManaChange` | 🟢 Verified | | | | `OP_ManaUpdate` | 🔴 Not-Set | | | | `OP_MarkNPC` | 🔴 Not-Set | | | @@ -373,7 +373,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_MobManaUpdate` | 🔴 Not-Set | | | | `OP_MobRename` | 🔴 Not-Set | | | | `OP_MobUpdate` | 🔴 Not-Set | | | -| `OP_MoneyOnCorpse` | 🟡 Unverified | | | +| `OP_MoneyOnCorpse` | 🟢 Verified | This is the loot response struct, it provides all the logistics for things like advloot | | | `OP_MoneyUpdate` | 🟡 Unverified | | | | `OP_MOTD` | 🟢 Verified | | | | `OP_MoveCoin` | 🟡 Unverified | | | @@ -440,8 +440,8 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_RaidJoin` | 🔴 Not-Set | | | | `OP_RaidUpdate` | 🔴 Not-Set | | | | `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_RandomReply` | 🟢 Verified | | | +| `OP_RandomReq` | 🟢 Verified | | | | `OP_ReadBook` | 🟡 Unverified | | | | `OP_RecipeAutoCombine` | 🟡 Unverified | | | | `OP_RecipeDetails` | 🟡 Unverified | | | @@ -492,7 +492,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_SendTitleList` | 🔴 Not-Set | | | | `OP_SendTributes` | 🔴 Not-Set | | | | `OP_SendZonepoints` | 🟢 Verified | | | -| `OP_SenseHeading` | 🟡 Unverified | | | +| `OP_SenseHeading` | 🟢 Verified | | | | `OP_SenseTraps` | 🟡 Unverified | | | | `OP_ServerListRequest` | 🔴 Not-Set | | | | `OP_ServerListResponse` | 🔴 Not-Set | | | @@ -535,7 +535,7 @@ Below is a status list for the 450 opcodes we currently use on the server for th | `OP_ShopParcelIcon` | 🟡 Unverified | | | | `OP_ShopRequest` | 🟡 Unverified | | | | `OP_SimpleMessage` | 🟢 Verified | | | -| `OP_SkillUpdate` | 🟡 Unverified | | | +| `OP_SkillUpdate` | 🟢 Verified | | | | `OP_Sneak` | 🟡 Unverified | | | | `OP_Some3ByteHPUpdate` | 🔴 Not-Set | | | | `OP_Some6ByteHPUpdate` | 🔴 Not-Set | | | diff --git a/utils/patches/patch_TOB.conf b/utils/patches/patch_TOB.conf index 895b19c17..f6709f730 100644 --- a/utils/patches/patch_TOB.conf +++ b/utils/patches/patch_TOB.conf @@ -183,7 +183,6 @@ OP_RefreshBuffs=0x754c OP_RefreshTargetBuffs=0x197f OP_RefreshPetBuffs=0x4f42 OP_Illusion=0x7fb0 -OP_MoneyOnCorpse=0x6f63 OP_RandomReply=0x1234 OP_DenyResponse=0x339b OP_SkillUpdate=0x0149 @@ -225,7 +224,7 @@ OP_KeyRing=0x0000 OP_WhoAllRequest=0x3328 OP_WhoAllResponse=0x4dfd OP_FriendsWho=0x3547 -OP_ConfirmDelete=0x14a8 # This is sent fromt the client after a movement update (with just spawn ID as the content) +OP_ConfirmDelete=0x14a8 # This is sent from the client after a movement update (with just spawn ID as the content) OP_Logout=0x46f8 OP_Rewind=0x898a OP_TargetCommand=0x46bf @@ -415,6 +414,7 @@ OP_MercenarySuspendResponse=0x0000 OP_MercenaryUnsuspendResponse=0x0000 # Looting +OP_MoneyOnCorpse=0x6f63 # this is actually a loot logistics packet OP_LootRequest=0x2239 OP_EndLootRequest=0x173c OP_LootItem=0x5241