From 052b41fbb2e3063616b5862eb05118e0694a7be7 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Thu, 4 Dec 2014 02:40:51 -0500 Subject: [PATCH 1/2] Ranged attacks will now much more accurately calculate max distance server side via accounting for differences in attacker/target size. This fixes a very common issue of player hitting range attack and nothing happening due to server improperly calculating max range. --- changelog.txt | 4 +++ zone/mob.h | 1 + zone/special_attacks.cpp | 58 +++++++++++++++++++++++++++++++++------- zone/string_ids.h | 3 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/changelog.txt b/changelog.txt index d8ed052ab..e72fc04a3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 12/04/2014 == +Kayen: Ranged attacks will now more accurately check MAX firing range, fixing the issue where you would +hit ranged attack and nothing would happpen due to incorrect server side range checks. + == 12/01/2014 == Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from. Trevius: Mercenaries now spawn with randomized facial features when purchased. diff --git a/zone/mob.h b/zone/mob.h index 18f61281f..6135c6571 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -737,6 +737,7 @@ public: void ProjectileAttack(); inline bool HasProjectileAttack() const { return ActiveProjectileATK; } inline void SetProjectileAttack(bool value) { ActiveProjectileATK = value; } + float GetRangeDistTargetSizeMod(Mob* other); bool CanDoSpecialAttack(Mob *other); bool Flurry(ExtraAttackOptions *opts); bool Rampage(ExtraAttackOptions *opts); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 1ecf10934..632a2dad1 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -765,15 +765,16 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) { } } - float range = RangeItem->Range + AmmoItem->Range + 5.0f; //Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0 + float range = RangeItem->Range + AmmoItem->Range + GetRangeDistTargetSizeMod(GetTarget()); mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range); range *= range; - if(DistNoRootNoZ(*GetTarget()) > range) { + if(DistNoRoot(*GetTarget()) > range) { mlog(COMBAT__RANGED, "Ranged attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*GetTarget()), range); - //target is out of range, client does a message + Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase. return; } - else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + else if(DistNoRoot(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. return; } @@ -1128,6 +1129,45 @@ void Mob::ProjectileAttack() SetProjectileAttack(false); } +float Mob::GetRangeDistTargetSizeMod(Mob* other) +{ + /* + Range is enforced client side, therefore these numbers do not need to be 100% accurate just close enough to + prevent any exploitation. The range mod changes in some situations depending on if size is from spawn or from SendIllusionPacket changes. + At present time only calculate from spawn (it is no consistent what happens to the calc when changing it after spawn). + */ + if (!other) + return 0.0f; + + float tsize = other->GetSize(); + + if (GetSize() > tsize) + tsize = GetSize(); + + float mod = 0.0f; + /*These are correct numbers if mob size is changed via #size (Don't know why it matters but it does) + if (tsize < 7) + mod = 16.0f; + else if (tsize >=7 && tsize <= 20) + mod = 16.0f + (0.6f * (tsize - 6.0f)); + else if (tsize >=20 && tsize <= 60) + mod = 25.0f + (1.25f * (tsize - 20.0f)); + else + mod = 75.0f; + */ + + if (tsize < 10) + mod = 18.0f; + else if (tsize >=10 && tsize < 15) + mod = 20.0f + (4.0f * (tsize - 10.0f)); + else if (tsize >=15 && tsize <= 20) + mod = 42.0f + (5.8f * (tsize - 15.0f)); + else + mod = 75.0f; + + return (mod + 2.0f); //Add 2.0f as buffer to prevent any chance of failures, client enforce range check regardless. +} + void NPC::RangedAttack(Mob* other) { @@ -1333,16 +1373,16 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 } } - int range = item->Range +50/*Fudge it a little, client will let you hit something at 0 0 0 when you are at 205 0 0*/; + float range = item->Range + GetRangeDistTargetSizeMod(GetTarget()); mlog(COMBAT__RANGED, "Calculated bow range to be %.1f", range); range *= range; - if(DistNoRootNoZ(*GetTarget()) > range) { + if(DistNoRoot(*GetTarget()) > range) { mlog(COMBAT__RANGED, "Throwing attack out of range... client should catch this. (%f > %f).\n", DistNoRootNoZ(*GetTarget()), range); - //target is out of range, client does a message + Message_StringID(13,TARGET_OUT_OF_RANGE);//Client enforces range and sends the message, this is a backup just incase. return; } - else if(DistNoRootNoZ(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ - return; + else if(DistNoRoot(*GetTarget()) < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ + Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. } if(!IsAttackAllowed(GetTarget()) || diff --git a/zone/string_ids.h b/zone/string_ids.h index e1e1bc7b3..ef758dba6 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -396,7 +396,8 @@ #define SONG_ENDS_OTHER 12688 //%1's song ends. #define SONG_ENDS_ABRUPTLY_OTHER 12689 //%1's song ends abruptly. #define DIVINE_AURA_NO_ATK 12695 //You can't attack while invulnerable! -#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive. +#define TRY_ATTACKING_SOMEONE 12696 //Try attacking someone other than yourself, it's more productive +#define RANGED_TOO_CLOSE 12698 //Your target is too close to use a ranged weapon! #define BACKSTAB_WEAPON 12874 //You need a piercing weapon as your primary weapon in order to backstab #define MORE_SKILLED_THAN_I 12931 //%1 tells you, 'You are more skilled than I! What could I possibly teach you?' #define SURNAME_EXISTS 12939 //You already have a surname. Operation failed. From af42af786935195f8b75278d85c80559630357d1 Mon Sep 17 00:00:00 2001 From: Trevius Date: Thu, 4 Dec 2014 02:13:01 -0600 Subject: [PATCH 2/2] Initial addition of the RoF2 client from May 10th 2013 (currently available on Steam as the F2P client). RoF2 is disabled by default, but you can enable by editing /common/patches/patches.cpp (see comments) --- changelog.txt | 2 + common/CMakeLists.txt | 14 +- common/eq_dictionary.h | 2 +- common/patches/patches.cpp | 4 +- common/patches/rof2.cpp | 5673 +++++++++++++++++ common/patches/rof2.h | 37 + common/patches/rof2_constants.h | 216 + common/patches/rof2_itemfields.h | 439 ++ common/patches/rof2_ops.h | 173 + common/patches/rof2_structs.h | 4922 ++++++++++++++ utils/patches/patch_RoF2.conf | 660 ++ .../scripts/opcode_scripts/conf_to_oplist.pl | 66 + utils/scripts/opcode_scripts/opcodelist.txt | 1671 +++++ .../scripts/opcode_scripts/oplist_to_conf.pl | 88 + utils/scripts/opcode_scripts/patch_NEW.conf | 661 ++ utils/scripts/opcode_scripts/patch_OLD.conf | 661 ++ 16 files changed, 15286 insertions(+), 3 deletions(-) create mode 100644 common/patches/rof2.cpp create mode 100644 common/patches/rof2.h create mode 100644 common/patches/rof2_constants.h create mode 100644 common/patches/rof2_itemfields.h create mode 100644 common/patches/rof2_ops.h create mode 100644 common/patches/rof2_structs.h create mode 100644 utils/patches/patch_RoF2.conf create mode 100644 utils/scripts/opcode_scripts/conf_to_oplist.pl create mode 100644 utils/scripts/opcode_scripts/opcodelist.txt create mode 100644 utils/scripts/opcode_scripts/oplist_to_conf.pl create mode 100644 utils/scripts/opcode_scripts/patch_NEW.conf create mode 100644 utils/scripts/opcode_scripts/patch_OLD.conf diff --git a/changelog.txt b/changelog.txt index e72fc04a3..e24dcd59d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 12/04/2014 == Kayen: Ranged attacks will now more accurately check MAX firing range, fixing the issue where you would hit ranged attack and nothing would happpen due to incorrect server side range checks. +Trevius: Initial addition of the RoF2 client from May 10th 2013 (currently available on Steam as the F2P client). +Trevius: RoF2 is disabled by default, but you can enable by editing /common/patches/patches.cpp (see comments) == 12/01/2014 == Trevius: Mercenaries now spawn as the same Gender and Size of the Merchant they are purchased from. diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 01fcd6df8..be495e9b7 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -72,6 +72,7 @@ SET(common_sources patches/sod.cpp patches/sof.cpp patches/rof.cpp + patches/rof2.cpp patches/titanium.cpp patches/underfoot.cpp SocketLib/Base64.cpp @@ -216,6 +217,11 @@ SET(common_headers patches/rof_itemfields.h patches/rof_ops.h patches/rof_structs.h + patches/rof2.h + patches/rof2_constants.h + patches/rof2_itemfields.h + patches/rof2_ops.h + patches/rof2_structs.h patches/titanium.h patches/titanium_constants.h patches/titanium_itemfields.h @@ -269,6 +275,11 @@ SOURCE_GROUP(Patches FILES patches/rof_ops.h patches/rof_constants.h patches/rof_structs.h + patches/rof2.h + patches/rof2_itemfields.h + patches/rof2_ops.h + patches/rof2_constants.h + patches/rof2_structs.h patches/titanium.h patches/titanium_itemfields.h patches/titanium_ops.h @@ -284,6 +295,7 @@ SOURCE_GROUP(Patches FILES patches/sod.cpp patches/sof.cpp patches/rof.cpp + patches/rof2.cpp patches/titanium.cpp patches/underfoot.cpp ) @@ -335,7 +347,7 @@ ADD_LIBRARY(common ${common_sources} ${common_headers}) IF(UNIX) ADD_DEFINITIONS(-fPIC) SET_SOURCE_FILES_PROPERTIES("SocketLib/Mime.cpp" PROPERTY COMPILE_FLAGS -Wno-unused-result) - SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0) + SET_SOURCE_FILES_PROPERTIES("patches/sod.cpp" "patches/sof.cpp" "patches/rof.cpp" "patches/rof2.cpp" "patches/underfoot.cpp" PROPERTIES COMPILE_FLAGS -O0) ENDIF(UNIX) diff --git a/common/eq_dictionary.h b/common/eq_dictionary.h index c08809a12..8ef38c77c 100644 --- a/common/eq_dictionary.h +++ b/common/eq_dictionary.h @@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/patches/sod_constants.h" #include "../common/patches/underfoot_constants.h" #include "../common/patches/rof_constants.h" -//#include "../common/patches/rof2_constants.h" +#include "../common/patches/rof2_constants.h" // *** DO NOT CHANGE without a full understanding of the consequences..the server is set up to use these settings explicitly!! *** // *** You will cause compilation failures and corrupt your database if partial or incorrect attempts to change them are made!! *** diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 212042210..d35ded9ba 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -8,7 +8,7 @@ #include "sof.h" #include "sod.h" #include "rof.h" -//#include "rof2.h" +#include "rof2.h" void RegisterAllPatches(EQStreamIdentifier &into) { Client62::Register(into); @@ -17,6 +17,7 @@ void RegisterAllPatches(EQStreamIdentifier &into) { SoD::Register(into); Underfoot::Register(into); RoF::Register(into); + // Uncomment the line below to enable RoF2 Client //RoF2::Register(into); } @@ -27,5 +28,6 @@ void ReloadAllPatches() { SoD::Reload(); Underfoot::Reload(); RoF::Reload(); + // Uncomment the line below to enable RoF2 Client //RoF2::Reload(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp new file mode 100644 index 000000000..372da9b07 --- /dev/null +++ b/common/patches/rof2.cpp @@ -0,0 +1,5673 @@ +#include "../debug.h" +#include "rof2.h" +#include "../opcodemgr.h" +#include "../logsys.h" +#include "../eq_stream_ident.h" +#include "../crc32.h" + +#include "../eq_packet_structs.h" +#include "../misc_functions.h" +#include "../string_util.h" +#include "../item.h" +#include "rof2_structs.h" +#include "../rulesys.h" + +#include +#include + +namespace RoF2 +{ + static const char *name = "RoF2"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; + + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + + // server to client inventory location converters + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot); + static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 ServerSlot); + static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse); + + // client to server inventory location converters + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot); + static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot); + static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse); + + void Register(EQStreamIdentifier &into) + { + //create our opcode manager if we havent already + if (opcodes == nullptr) { + //TODO: get this file name from the config file + std::string opfile = "patch_"; + opfile += name; + opfile += ".conf"; + //load up the opcode manager. + //TODO: figure out how to support shared memory with multiple patches... + opcodes = new RegularOpcodeManager(); + if (!opcodes->LoadOpcodes(opfile.c_str())) { + _log(NET__OPCODES, "Error loading opcodes file %s. Not registering patch %s.", opfile.c_str(), name); + return; + } + } + + //ok, now we have what we need to register. + + EQStream::Signature signature; + std::string pname; + + //register our world signature. + pname = std::string(name) + "_world"; + signature.ignore_eq_opcode = 0; + signature.first_length = sizeof(structs::LoginInfo_Struct); + signature.first_eq_opcode = opcodes->EmuToEQ(OP_SendLoginInfo); + into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy); + + //register our zone signature. + pname = std::string(name) + "_zone"; + signature.ignore_eq_opcode = opcodes->EmuToEQ(OP_AckPacket); + signature.first_length = sizeof(structs::ClientZoneEntry_Struct); + signature.first_eq_opcode = opcodes->EmuToEQ(OP_ZoneEntry); + into.RegisterPatch(signature, pname.c_str(), &opcodes, &struct_strategy); + + + + _log(NET__IDENTIFY, "Registered patch %s", name); + } + + void Reload() + { + //we have a big problem to solve here when we switch back to shared memory + //opcode managers because we need to change the manager pointer, which means + //we need to go to every stream and replace it's manager. + + if (opcodes != nullptr) { + //TODO: get this file name from the config file + std::string opfile = "patch_"; + opfile += name; + opfile += ".conf"; + if (!opcodes->ReloadOpcodes(opfile.c_str())) { + _log(NET__OPCODES, "Error reloading opcodes file %s for patch %s.", opfile.c_str(), name); + return; + } + _log(NET__OPCODES, "Reloaded opcodes for patch %s", name); + } + } + + Strategy::Strategy() : StructStrategy() + { + //all opcodes default to passthrough. +#include "ss_register.h" +#include "rof_ops.h" + } + + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } + + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientRoF2; + } + +#include "ss_define.h" + +// ENCODE methods + ENCODE(OP_Action) + { + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::ActionAlt_Struct); + + OUT(target); + OUT(source); + OUT(level); + eq->unknown06 = 0; + eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f; + eq->bard_focus_id = emu->bard_focus_id; + eq->knockback_angle = emu->sequence; + eq->unknown22 = 0; + OUT(type); + eq->damage = 0; + eq->unknown31 = 0; + OUT(spell); + eq->level2 = eq->level; + eq->effect_flag = emu->buff_unknown; + eq->unknown39 = 14; + eq->unknown43 = 0; + eq->unknown44 = 17; + eq->unknown45 = 0; + eq->unknown46 = -1; + eq->unknown50 = 0; + eq->unknown54 = 0; + + FINISH_ENCODE(); + } + + ENCODE(OP_AdventureMerchantSell) + { + ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); + SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); + + eq->unknown000 = 1; + OUT(npcid); + eq->slot = ServerToRoF2MainInvSlot(emu->slot); + OUT(charges); + OUT(sell_price); + + FINISH_ENCODE(); + } + + ENCODE(OP_AltCurrency) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *emu_buffer = in->pBuffer; + uint32 opcode = *((uint32*)emu_buffer); + + if (opcode == 8) { + AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(structs::AltCurrencyPopulate_Struct) + + sizeof(structs::AltCurrencyPopulateEntry_Struct) * populate->count); + structs::AltCurrencyPopulate_Struct *out_populate = (structs::AltCurrencyPopulate_Struct*)outapp->pBuffer; + + out_populate->opcode = populate->opcode; + out_populate->count = populate->count; + for (uint32 i = 0; i < populate->count; ++i) { + out_populate->entries[i].currency_number = populate->entries[i].currency_number; + out_populate->entries[i].unknown00 = populate->entries[i].unknown00; + out_populate->entries[i].currency_number2 = populate->entries[i].currency_number2; + out_populate->entries[i].item_id = populate->entries[i].item_id; + out_populate->entries[i].item_icon = populate->entries[i].item_icon; + out_populate->entries[i].stack_size = populate->entries[i].stack_size; + out_populate->entries[i].display = ((populate->entries[i].stack_size > 0) ? 1 : 0); + } + + dest->FastQueuePacket(&outapp, ack_req); + } + else { + EQApplicationPacket *outapp = new EQApplicationPacket(OP_AltCurrency, sizeof(AltCurrencyUpdate_Struct)); + memcpy(outapp->pBuffer, emu_buffer, sizeof(AltCurrencyUpdate_Struct)); + dest->FastQueuePacket(&outapp, ack_req); + } + + //dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_AltCurrencySell) + { + ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); + SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + OUT(merchant_entity_id); + eq->slot_id = ServerToRoF2Slot(emu->slot_id); + OUT(charges); + OUT(cost); + + FINISH_ENCODE(); + } + + ENCODE(OP_Animation) + { + ENCODE_LENGTH_EXACT(Animation_Struct); + SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); + + OUT(spawnid); + OUT(value); + OUT(action); + + FINISH_ENCODE(); + } + + ENCODE(OP_ApplyPoison) + { + ENCODE_LENGTH_EXACT(ApplyPoison_Struct); + SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + eq->inventorySlot = ServerToRoF2MainInvSlot(emu->inventorySlot); + OUT(success); + + FINISH_ENCODE(); + } + + ENCODE(OP_AugmentInfo) + { + ENCODE_LENGTH_EXACT(AugmentInfo_Struct); + SETUP_DIRECT_ENCODE(AugmentInfo_Struct, structs::AugmentInfo_Struct); + + OUT(itemid); + OUT(window); + strn0cpy(eq->augment_info, emu->augment_info, 64); + + FINISH_ENCODE(); + } + + ENCODE(OP_Barter) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + char *Buffer = (char *)in->pBuffer; + + uint32 SubAction = VARSTRUCT_DECODE_TYPE(uint32, Buffer); + + if (SubAction != Barter_BuyerAppearance) + { + dest->FastQueuePacket(&in, ack_req); + + return; + } + + unsigned char *__emu_buffer = in->pBuffer; + + in->size = 80; + + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + char Name[64]; + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, SubAction); + uint32 EntityID = VARSTRUCT_DECODE_TYPE(uint32, Buffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, EntityID); + uint8 Toggle = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + VARSTRUCT_DECODE_STRING(Name, Buffer); + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + OutBuffer = (char *)in->pBuffer + 72; + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, Toggle); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_BazaarSearch) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + char *Buffer = (char *)in->pBuffer; + + uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + + if (SubAction != BazaarSearchResults) + { + dest->FastQueuePacket(&in, ack_req); + return; + } + + unsigned char *__emu_buffer = in->pBuffer; + + BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer; + + int EntryCount = in->size / sizeof(BazaarSearchResults_Struct); + + if (EntryCount == 0 || (in->size % sizeof(BazaarSearchResults_Struct)) != 0) + { + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(BazaarSearchResults_Struct)); + delete in; + return; + } + + in->size = EntryCount * sizeof(structs::BazaarSearchResults_Struct); + in->pBuffer = new unsigned char[in->size]; + + memset(in->pBuffer, 0, in->size); + + structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *)in->pBuffer; + + for (int i = 0; i < EntryCount; ++i, ++emu, ++eq) + { + OUT(Beginning.Action); + OUT(SellerID); + memcpy(eq->SellerName, emu->SellerName, sizeof(eq->SellerName)); + OUT(NumItems); + OUT(ItemID); + OUT(SerialNumber); + memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); + OUT(Cost); + OUT(ItemStat); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_BeginCast) + { + SETUP_DIRECT_ENCODE(BeginCast_Struct, structs::BeginCast_Struct); + + OUT(spell_id); + OUT(caster_id); + OUT(cast_time); + + FINISH_ENCODE(); + } + + ENCODE(OP_BlockedBuffs) + { + ENCODE_LENGTH_EXACT(BlockedBuffs_Struct); + SETUP_DIRECT_ENCODE(BlockedBuffs_Struct, structs::BlockedBuffs_Struct); + + for (uint32 i = 0; i < BLOCKED_BUFF_COUNT; ++i) + eq->SpellID[i] = emu->SpellID[i]; + + // -1 for the extra 10 added in RoF2. We should really be encoding for the older clients, not RoF2, but + // we can sort that out later. + + for (uint32 i = BLOCKED_BUFF_COUNT; i < structs::BLOCKED_BUFF_COUNT; ++i) + eq->SpellID[i] = -1; + + OUT(Count); + OUT(Pet); + OUT(Initialise); + OUT(Flags); + + FINISH_ENCODE(); + } + + ENCODE(OP_Buff) + { + ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); + SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + + OUT(entityid); + eq->unknown004 = 2; + //eq->level = 80; + //eq->effect = 0; + OUT(level); + OUT(effect); + eq->unknown007 = 0; + eq->unknown008 = 1.0f; + OUT(spellid); + OUT(duration); + eq->playerId = 0x7cde; + OUT(slotid); + OUT(num_hits); + if (emu->bufffade == 1) + eq->bufffade = 1; + else + eq->bufffade = 2; + + // Bit of a hack. OP_Buff appears to add/remove the buff while OP_BuffCreate adds/removes the actual buff icon + EQApplicationPacket *outapp = nullptr; + if (eq->bufffade == 1) + { + outapp = new EQApplicationPacket(OP_BuffCreate, 29); + outapp->WriteUInt32(emu->entityid); + outapp->WriteUInt32(0x0271); // Unk + outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? + outapp->WriteUInt16(1); // 1 buff in this packet + outapp->WriteUInt32(emu->slotid); + outapp->WriteUInt32(0xffffffff); // SpellID (0xffff to remove) + outapp->WriteUInt32(0); // Duration + outapp->WriteUInt32(0); // ? + outapp->WriteUInt8(0); // Caster name + outapp->WriteUInt8(0); // Terminating byte + } + FINISH_ENCODE(); + + if (outapp) + dest->FastQueuePacket(&outapp); // Send the OP_BuffCreate to remove the buff + } + + ENCODE(OP_BuffCreate) + { + SETUP_VAR_ENCODE(BuffIcon_Struct); + + uint32 sz = 12 + (17 * emu->count); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); + + __packet->WriteUInt32(emu->entity_id); + __packet->WriteUInt32(0); // PlayerID ? + __packet->WriteUInt8(emu->all_buffs); // 1 indicates all buffs on the player (0 to add or remove a single buff) + __packet->WriteUInt16(emu->count); + + for (uint16 i = 0; i < emu->count; ++i) + { + uint16 buffslot = emu->entries[i].buff_slot; + // Not sure if this is needs amending for RoF2 yet. + if (emu->entries[i].buff_slot >= 25) + { + buffslot += 17; + } + + __packet->WriteUInt32(buffslot); + __packet->WriteUInt32(emu->entries[i].spell_id); + __packet->WriteUInt32(emu->entries[i].tics_remaining); + __packet->WriteUInt32(emu->entries[i].num_hits); // Unknown + __packet->WriteString(""); + } + __packet->WriteUInt8(!emu->all_buffs); // Unknown + + FINISH_ENCODE(); + } + + ENCODE(OP_CancelTrade) + { + ENCODE_LENGTH_EXACT(CancelTrade_Struct); + SETUP_DIRECT_ENCODE(CancelTrade_Struct, structs::CancelTrade_Struct); + + OUT(fromid); + OUT(action); + + FINISH_ENCODE(); + } + + ENCODE(OP_CastSpell) + { + ENCODE_LENGTH_EXACT(CastSpell_Struct); + SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct); + + if (emu->slot == 10) + eq->slot = 13; + else + OUT(slot); + + OUT(spell_id); + eq->inventoryslot = ServerToRoF2Slot(emu->inventoryslot); + //OUT(inventoryslot); + OUT(target_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_ChannelMessage) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + in->size = strlen(emu->sender) + 1 + strlen(emu->targetname) + 1 + strlen(emu->message) + 1 + 36; + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sender); + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->targetname); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->language); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->chan_num); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->skill_in_language); + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->message); + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint16, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_CharInventory) + { + //consume the packet + EQApplicationPacket *in = *p; + + *p = nullptr; + + if (in->size == 0) { + + in->size = 4; + in->pBuffer = new uchar[in->size]; + + *((uint32 *)in->pBuffer) = 0; + + dest->FastQueuePacket(&in, ack_req); + return; + } + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + + int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); + + if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", + opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct)); + + delete in; + + return; + } + + InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + + in->pBuffer = new uchar[4]; + *(uint32 *)in->pBuffer = ItemCount; + in->size = 4; + + for (int r = 0; r < ItemCount; r++, eq++) { + + uint32 Length = 0; + + char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0); + + if (Serialized) { + + uchar *OldBuffer = in->pBuffer; + in->pBuffer = new uchar[in->size + Length]; + memcpy(in->pBuffer, OldBuffer, in->size); + + safe_delete_array(OldBuffer); + + memcpy(in->pBuffer + in->size, Serialized, Length); + in->size += Length; + + safe_delete_array(Serialized); + } + else { + _log(NET__ERROR, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + } + } + + delete[] __emu_buffer; + + //_log(NET__ERROR, "Sending inventory to client"); + //_hex(NET__ERROR, in->pBuffer, in->size); + + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_ClickObjectAction) + { + ENCODE_LENGTH_EXACT(ClickObjectAction_Struct); + SETUP_DIRECT_ENCODE(ClickObjectAction_Struct, structs::ClickObjectAction_Struct); + + OUT(drop_id); + eq->unknown04 = -1; + eq->unknown08 = -1; + OUT(type); + OUT(icon); + eq->unknown16 = 0; + OUT_str(object_name); + + FINISH_ENCODE(); + } + + ENCODE(OP_ClientUpdate) + { + ENCODE_LENGTH_EXACT(PlayerPositionUpdateServer_Struct); + SETUP_DIRECT_ENCODE(PlayerPositionUpdateServer_Struct, structs::PlayerPositionUpdateServer_Struct); + + OUT(spawn_id); + OUT(x_pos); + OUT(delta_x); + OUT(delta_y); + OUT(z_pos); + OUT(delta_heading); + OUT(y_pos); + OUT(delta_z); + OUT(animation); + OUT(heading); + + FINISH_ENCODE(); + } + + ENCODE(OP_Consider) + { + ENCODE_LENGTH_EXACT(Consider_Struct); + SETUP_DIRECT_ENCODE(Consider_Struct, structs::Consider_Struct); + + OUT(playerid); + OUT(targetid); + OUT(faction); + OUT(level); + OUT(pvpcon); + + FINISH_ENCODE(); + } + + ENCODE(OP_Damage) + { + ENCODE_LENGTH_EXACT(CombatDamage_Struct); + SETUP_DIRECT_ENCODE(CombatDamage_Struct, structs::CombatDamage_Struct); + + OUT(target); + OUT(source); + OUT(type); + OUT(spellid); + OUT(damage); + eq->sequence = emu->sequence; + + FINISH_ENCODE(); + } + + ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } + + ENCODE(OP_DeleteItem) + { + ENCODE_LENGTH_EXACT(DeleteItem_Struct); + SETUP_DIRECT_ENCODE(DeleteItem_Struct, structs::DeleteItem_Struct); + + eq->from_slot = ServerToRoF2Slot(emu->from_slot); + eq->to_slot = ServerToRoF2Slot(emu->to_slot); + OUT(number_in_stack); + + FINISH_ENCODE(); + } + + ENCODE(OP_DeleteSpawn) + { + ENCODE_LENGTH_EXACT(DeleteSpawn_Struct); + SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); + + OUT(spawn_id); + eq->unknown04 = 1; // Observed + + FINISH_ENCODE(); + } + + ENCODE(OP_DisciplineUpdate) + { + ENCODE_LENGTH_EXACT(Disciplines_Struct); + SETUP_DIRECT_ENCODE(Disciplines_Struct, structs::Disciplines_Struct); + + memcpy(&eq->values, &emu->values, sizeof(Disciplines_Struct)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzCompass) + { + SETUP_VAR_ENCODE(ExpeditionCompass_Struct); + ALLOC_VAR_ENCODE(structs::ExpeditionCompass_Struct, sizeof(structs::ExpeditionInfo_Struct) + sizeof(structs::ExpeditionCompassEntry_Struct) * emu->count); + + OUT(count); + + for (uint32 i = 0; i < emu->count; ++i) + { + OUT(entries[i].x); + OUT(entries[i].y); + OUT(entries[i].z); + } + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionEndsWarning) + { + ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); + SETUP_DIRECT_ENCODE(ExpeditionExpireWarning, structs::ExpeditionExpireWarning); + + OUT(minutes_remaining); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionInfo) + { + ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); + + OUT(max_players); + eq->unknown004 = 785316192; + eq->unknown008 = 435601; + strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strncpy(eq->leader_name, emu->leader_name, sizeof(eq->leader_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzExpeditionList) + { + SETUP_VAR_ENCODE(ExpeditionLockoutList_Struct); + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + uint32 client_id = 0; + uint8 null_term = 0; + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&emu->count, sizeof(uint32)); + for (uint32 i = 0; i < emu->count; ++i) + { + ss.write(emu->entries[i].expedition, strlen(emu->entries[i].expedition)); + ss.write((const char*)&null_term, sizeof(char)); + ss.write((const char*)&emu->entries[i].time_left, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write(emu->entries[i].expedition_event, strlen(emu->entries[i].expedition_event)); + ss.write((const char*)&null_term, sizeof(char)); + } + + __packet->size = ss.str().length(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzJoinExpeditionConfirm) + { + ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); + SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); + + strncpy(eq->expedition_name, emu->expedition_name, sizeof(eq->expedition_name)); + strncpy(eq->player_name, emu->player_name, sizeof(eq->player_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzLeaderStatus) + { + SETUP_VAR_ENCODE(ExpeditionLeaderSet_Struct); + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + uint32 client_id = 0; + uint8 null_term = 0; + + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write(emu->leader_name, strlen(emu->leader_name)); + ss.write((const char*)&null_term, sizeof(char)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32));//0xffffffff + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&client_id, sizeof(uint32));//1 + ss.write((const char*)&client_id, sizeof(uint32)); + + __packet->size = ss.str().length(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + + FINISH_ENCODE(); + } + + ENCODE(OP_DzMemberList) + { + SETUP_VAR_ENCODE(ExpeditionMemberList_Struct); + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + + uint32 client_id = 0; + uint8 null_term = 0; + ss.write((const char*)&client_id, sizeof(uint32)); + ss.write((const char*)&emu->count, sizeof(uint32)); + for (uint32 i = 0; i < emu->count; ++i) + { + ss.write(emu->entries[i].name, strlen(emu->entries[i].name)); + ss.write((const char*)&null_term, sizeof(char)); + ss.write((const char*)&emu->entries[i].status, sizeof(char)); + } + + __packet->size = ss.str().length(); + __packet->pBuffer = new unsigned char[__packet->size]; + memcpy(__packet->pBuffer, ss.str().c_str(), __packet->size); + + FINISH_ENCODE(); + } + + ENCODE(OP_ExpansionInfo) + { + ENCODE_LENGTH_EXACT(ExpansionInfo_Struct); + SETUP_DIRECT_ENCODE(ExpansionInfo_Struct, structs::ExpansionInfo_Struct); + + OUT(Expansions); + + FINISH_ENCODE(); + } + + ENCODE(OP_GMLastName) + { + ENCODE_LENGTH_EXACT(GMLastName_Struct); + SETUP_DIRECT_ENCODE(GMLastName_Struct, structs::GMLastName_Struct); + + OUT_str(name); + OUT_str(gmname); + OUT_str(lastname); + for (int i = 0; i<4; i++) + { + eq->unknown[i] = emu->unknown[i]; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_GMTrainSkillConfirm) + { + ENCODE_LENGTH_EXACT(GMTrainSkillConfirm_Struct); + SETUP_DIRECT_ENCODE(GMTrainSkillConfirm_Struct, structs::GMTrainSkillConfirm_Struct); + + OUT(SkillID); + OUT(Cost); + OUT(NewSkill); + OUT_str(TrainerName); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroundSpawn) + { + // We are not encoding the spawn_id field here, but it doesn't appear to matter. + // + EQApplicationPacket *in = *p; + *p = nullptr; + + Object_Struct *emu = (Object_Struct *)in->pBuffer; + + unsigned char *__emu_buffer = in->pBuffer; + + in->size = strlen(emu->object_name) + sizeof(Object_Struct)-1; + in->pBuffer = new unsigned char[in->size]; + + char *OutBuffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); + VARSTRUCT_ENCODE_STRING(OutBuffer, emu->object_name); + VARSTRUCT_ENCODE_TYPE(uint16, OutBuffer, emu->zone_id); + VARSTRUCT_ENCODE_TYPE(uint16, OutBuffer, emu->zone_instance); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->drop_id); // Some unique id + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Unknown + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); + VARSTRUCT_ENCODE_TYPE(int32, OutBuffer, emu->object_type); // Unknown, observed 0x00000014 + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_GroupCancelInvite) + { + ENCODE_LENGTH_EXACT(GroupCancel_Struct); + SETUP_DIRECT_ENCODE(GroupCancel_Struct, structs::GroupCancel_Struct); + + memcpy(eq->name1, emu->name1, sizeof(eq->name1)); + memcpy(eq->name2, emu->name2, sizeof(eq->name2)); + OUT(toggle); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupFollow) + { + ENCODE_LENGTH_EXACT(GroupGeneric_Struct); + SETUP_DIRECT_ENCODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(eq->name1, emu->name1, sizeof(eq->name1)); + memcpy(eq->name2, emu->name2, sizeof(eq->name2)); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupFollow2) + { + ENCODE_LENGTH_EXACT(GroupGeneric_Struct); + SETUP_DIRECT_ENCODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(eq->name1, emu->name1, sizeof(eq->name1)); + memcpy(eq->name2, emu->name2, sizeof(eq->name2)); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupInvite) + { + ENCODE_LENGTH_EXACT(GroupGeneric_Struct); + SETUP_DIRECT_ENCODE(GroupGeneric_Struct, structs::GroupInvite_Struct); + + memcpy(eq->invitee_name, emu->name1, sizeof(eq->invitee_name)); + memcpy(eq->inviter_name, emu->name2, sizeof(eq->inviter_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_GroupUpdate) + { + //_log(NET__ERROR, "OP_GroupUpdate"); + EQApplicationPacket *in = *p; + GroupJoin_Struct *gjs = (GroupJoin_Struct*)in->pBuffer; + + //_log(NET__ERROR, "Received outgoing OP_GroupUpdate with action code %i", gjs->action); + if ((gjs->action == groupActLeave) || (gjs->action == groupActDisband)) + { + if ((gjs->action == groupActDisband) || !strcmp(gjs->yourname, gjs->membername)) + { + //_log(NET__ERROR, "Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandYou, sizeof(structs::GroupGeneric_Struct)); + + structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; + memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); + memcpy(ggs->name2, gjs->membername, sizeof(ggs->name1)); + dest->FastQueuePacket(&outapp); + + // Make an empty GLAA packet to clear out their useable GLAAs + // + outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + + dest->FastQueuePacket(&outapp); + delete in; + return; + } + //if(gjs->action == groupActLeave) + // _log(NET__ERROR, "Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupDisbandOther, sizeof(structs::GroupGeneric_Struct)); + + structs::GroupGeneric_Struct *ggs = (structs::GroupGeneric_Struct*)outapp->pBuffer; + memcpy(ggs->name1, gjs->yourname, sizeof(ggs->name1)); + memcpy(ggs->name2, gjs->membername, sizeof(ggs->name2)); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp); + + delete in; + return; + } + + if (in->size == sizeof(GroupUpdate2_Struct)) + { + // Group Update2 + //_log(NET__ERROR, "Struct is GroupUpdate2"); + + unsigned char *__emu_buffer = in->pBuffer; + GroupUpdate2_Struct *gu2 = (GroupUpdate2_Struct*)__emu_buffer; + + //_log(NET__ERROR, "Yourname is %s", gu2->yourname); + + int MemberCount = 1; + int PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; + + for (int i = 0; i < 5; ++i) + { + //_log(NET__ERROR, "Membername[%i] is %s", i, gu2->membername[i]); + if (gu2->membername[i][0] != '\0') + { + PacketLength += (22 + strlen(gu2->membername[i]) + 1); + ++MemberCount; + } + } + + //_log(NET__ERROR, "Leadername is %s", gu2->leadersname); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + + char *Buffer = (char *)outapp->pBuffer; + + // Header + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Think this should be SpawnID, but it doesn't seem to matter + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, MemberCount); + VARSTRUCT_ENCODE_STRING(Buffer, gu2->leadersname); + + // Leader + // + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_STRING(Buffer, gu2->yourname); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + //VARSTRUCT_ENCODE_STRING(Buffer, ""); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x46); // Observed 0x41 and 0x46 here + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + + int MemberNumber = 1; + + for (int i = 0; i < 5; ++i) + { + if (gu2->membername[i][0] == '\0') + continue; + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, MemberNumber++); + VARSTRUCT_ENCODE_STRING(Buffer, gu2->membername[i]); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + //VARSTRUCT_ENCODE_STRING(Buffer, ""); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x41); // Observed 0x41 and 0x46 here + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // Low byte is Main Assist Flag + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, 0); + } + + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp); + + outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + + GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; + + GLAAus->NPCMarkerID = gu2->NPCMarkerID; + memcpy(&GLAAus->LeaderAAs, &gu2->leader_aas, sizeof(GLAAus->LeaderAAs)); + + dest->FastQueuePacket(&outapp); + delete in; + + return; + + } + //_log(NET__ERROR, "Generic GroupUpdate, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + ENCODE_LENGTH_EXACT(GroupJoin_Struct); + SETUP_DIRECT_ENCODE(GroupJoin_Struct, structs::GroupJoin_Struct); + + memcpy(eq->membername, emu->membername, sizeof(eq->membername)); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupLeadershipAAUpdate, sizeof(GroupLeadershipAAUpdate_Struct)); + GroupLeadershipAAUpdate_Struct *GLAAus = (GroupLeadershipAAUpdate_Struct*)outapp->pBuffer; + + GLAAus->NPCMarkerID = emu->NPCMarkerID; + + memcpy(&GLAAus->LeaderAAs, &emu->leader_aas, sizeof(GLAAus->LeaderAAs)); + //_hex(NET__ERROR, __packet->pBuffer, __packet->size); + + FINISH_ENCODE(); + + dest->FastQueuePacket(&outapp); + } + + ENCODE(OP_GuildMemberList) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + Internal_GuildMembers_Struct *emu = (Internal_GuildMembers_Struct *)in->pBuffer; + + //make a new EQ buffer. + uint32 pnl = strlen(emu->player_name); + uint32 length = sizeof(structs::GuildMembers_Struct) + pnl + + emu->count*sizeof(structs::GuildMemberEntry_Struct) + + emu->name_length + emu->note_length; + in->pBuffer = new uint8[length]; + in->size = length; + //no memset since we fill every byte. + + uint8 *buffer; + buffer = in->pBuffer; + + //easier way to setup GuildMembers_Struct + //set prefix name + strcpy((char *)buffer, emu->player_name); + buffer += pnl; + *buffer = '\0'; + buffer++; + + // Guild ID + buffer += sizeof(uint32); + + //add member count. + *((uint32 *)buffer) = htonl(emu->count); + buffer += sizeof(uint32); + + if (emu->count > 0) { + Internal_GuildMemberEntry_Struct *emu_e = emu->member; + const char *emu_name = (const char *)(__emu_buffer + + sizeof(Internal_GuildMembers_Struct)+ //skip header + emu->count * sizeof(Internal_GuildMemberEntry_Struct) //skip static length member data + ); + const char *emu_note = (emu_name + + emu->name_length + //skip name contents + emu->count //skip string terminators + ); + + structs::GuildMemberEntry_Struct *e = (structs::GuildMemberEntry_Struct *) buffer; + + uint32 r; + for (r = 0; r < emu->count; r++, emu_e++) { + + //the order we set things here must match the struct + + //nice helper macro +#define SlideStructString(field, str) \ + { \ + int sl = strlen(str); \ + memcpy(e->field, str, sl+1); \ + e = (structs::GuildMemberEntry_Struct *) ( ((uint8 *)e) + sl ); \ + str += sl + 1; \ + } +#define PutFieldN(field) e->field = htonl(emu_e->field) + + SlideStructString(name, emu_name); + PutFieldN(level); + PutFieldN(banker); + PutFieldN(class_); + + /* Translate older ranks to new values */ + switch (emu_e->rank) { + case 0: { e->rank = htonl(5); break; } // GUILD_MEMBER 0 + case 1: { e->rank = htonl(3); break; } // GUILD_OFFICER 1 + case 2: { e->rank = htonl(1); break; } // GUILD_LEADER 2 + default: { e->rank = htonl(emu_e->rank); break; } // GUILD_NONE + } + + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + e->unknown01 = 0; + PutFieldN(total_tribute); + PutFieldN(last_tribute); + e->unknown_one = htonl(1); + SlideStructString(public_note, emu_note); + e->zoneinstance = 0; + e->zone_id = htons(emu_e->zone_id); + e->unknown_one2 = htonl(1); + e->unknown04 = 0; + +#undef SlideStructString +#undef PutFieldN + + e++; + } + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_GuildMemberUpdate) + { + SETUP_DIRECT_ENCODE(GuildMemberUpdate_Struct, structs::GuildMemberUpdate_Struct); + + OUT(GuildID); + memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName)); + OUT(ZoneID); + OUT(InstanceID); + OUT(LastSeen); + eq->Unknown76 = 0; + + FINISH_ENCODE(); + } + + ENCODE(OP_GuildsList) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + uint32 NumberOfGuilds = in->size / 64; + uint32 PacketSize = 68; // 64 x 0x00 + a uint32 that I am guessing is the highest guild ID in use. + + unsigned char *__emu_buffer = in->pBuffer; + + char *InBuffer = (char *)__emu_buffer; + + uint32 HighestGuildID = 0; + + for (unsigned int i = 0; i < NumberOfGuilds; ++i) + { + if (InBuffer[0]) + { + PacketSize += (5 + strlen(InBuffer)); + HighestGuildID = i - 1; + } + InBuffer += 64; + } + + PacketSize++; // Appears to be an extra 0x00 at the very end. + + in->size = PacketSize; + in->pBuffer = new unsigned char[in->size]; + + InBuffer = (char *)__emu_buffer; + + char *OutBuffer = (char *)in->pBuffer; + + // Init the first 64 bytes to zero, as per live. + // + memset(OutBuffer, 0, 64); + + OutBuffer += 64; + + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, HighestGuildID); + + for (unsigned int i = 0; i < NumberOfGuilds; ++i) + { + if (InBuffer[0]) + { + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, i - 1); + VARSTRUCT_ENCODE_STRING(OutBuffer, InBuffer); + } + InBuffer += 64; + } + + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0x00); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_HPUpdate) + { + SETUP_DIRECT_ENCODE(SpawnHPUpdate_Struct, structs::SpawnHPUpdate_Struct); + + OUT(spawn_id); + OUT(cur_hp); + OUT(max_hp); + + FINISH_ENCODE(); + } + + ENCODE(OP_Illusion) + { + ENCODE_LENGTH_EXACT(Illusion_Struct); + SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct); + + OUT(spawnid); + OUT_str(charname); + OUT(race); + OUT(unknown006[0]); + OUT(unknown006[1]); + OUT(gender); + OUT(texture); + OUT(helmtexture); + OUT(face); + OUT(hairstyle); + OUT(haircolor); + OUT(beard); + OUT(beardcolor); + OUT(size); + OUT(drakkin_heritage); + OUT(drakkin_tattoo); + OUT(drakkin_details); + eq->unknown316 = -1; // Observed + + FINISH_ENCODE(); + } + + /*ENCODE(OP_InspectAnswer) + { + ENCODE_LENGTH_EXACT(InspectResponse_Struct); + SETUP_DIRECT_ENCODE(InspectResponse_Struct, structs::InspectResponse_Struct); + + OUT(TargetID); + OUT(playerid); + + int r; + for (r = 0; r < 21; r++) { + strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r])); + } + // Swap last 2 slots for Arrow and Power Source + strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21])); + strn0cpy(eq->unknown_zero, emu->itemnames[21], sizeof(eq->unknown_zero)); + + int k; + for (k = 0; k < 21; k++) { + OUT(itemicons[k]); + } + // Swap last 2 slots for Arrow and Power Source + eq->itemicons[21] = emu->itemicons[22]; + eq->unknown_zero2 = emu->itemicons[21]; + strn0cpy(eq->text, emu->text, sizeof(eq->text)); + + FINISH_ENCODE(); + }*/ + + ENCODE(OP_InspectBuffs) + { + ENCODE_LENGTH_EXACT(InspectBuffs_Struct); + SETUP_DIRECT_ENCODE(InspectBuffs_Struct, structs::InspectBuffs_Struct); + + // we go over the internal 25 instead of the packet's since no entry is 0, which it will be already + for (int i = 0; i < BUFF_COUNT; i++) { + OUT(spell_id[i]); + OUT(tics_remaining[i]); + } + + FINISH_ENCODE(); + } + + ENCODE(OP_InspectRequest) + { + ENCODE_LENGTH_EXACT(Inspect_Struct); + SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); + + OUT(TargetID); + OUT(PlayerID); + + FINISH_ENCODE(); + } + + ENCODE(OP_InterruptCast) + { + ENCODE_LENGTH_EXACT(InterruptCast_Struct); + SETUP_DIRECT_ENCODE(InterruptCast_Struct, structs::InterruptCast_Struct); + + OUT(spawnid); + OUT(messageid); + + FINISH_ENCODE(); + } + + ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } + + ENCODE(OP_ItemPacket) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer; + InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem); + + uint32 length; + char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); + + if (!serialized) { + _log(NET__STRUCTS, "Serialization failed on item slot %d.", int_struct->slot_id); + delete in; + return; + } + in->size = length + 4; + in->pBuffer = new unsigned char[in->size]; + ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer; + new_item_pkt->PacketType = old_item_pkt->PacketType; + memcpy(new_item_pkt->SerializedItem, serialized, length); + + delete[] __emu_buffer; + safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_ItemVerifyReply) + { + ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); + SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); + + eq->slot = ServerToRoF2Slot(emu->slot); + OUT(spell); + OUT(target); + + FINISH_ENCODE(); + } + + ENCODE(OP_LeadershipExpUpdate) + { + SETUP_DIRECT_ENCODE(LeadershipExpUpdate_Struct, structs::LeadershipExpUpdate_Struct); + + OUT(group_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_exp); + OUT(raid_leadership_points); + + FINISH_ENCODE(); + } + + ENCODE(OP_LogServer) + { + ENCODE_LENGTH_EXACT(LogServer_Struct); + SETUP_DIRECT_ENCODE(LogServer_Struct, structs::LogServer_Struct); + + strncpy(eq->worldshortname, emu->worldshortname, sizeof(eq->worldshortname)); + + //OUT(enablevoicemacros); // These two are lost, but must be one of the 1s in unknown[249] + //OUT(enablemail); + OUT(enable_pvp); + OUT(enable_FV); + + eq->unknown016 = 1; + eq->unknown020[0] = 1; + + eq->unknown249[0] = 1; + eq->unknown249[1] = 1; + eq->unknown249[8] = 1; + eq->unknown249[9] = 1; + eq->unknown249[12] = 1; + eq->unknown249[14] = 1; + eq->unknown249[15] = 1; + eq->unknown249[16] = 1; + + eq->unknown276[0] = 1.0f; + eq->unknown276[1] = 1.0f; + eq->unknown276[6] = 1.0f; + + FINISH_ENCODE(); + } + + ENCODE(OP_LootItem) + { + ENCODE_LENGTH_EXACT(LootingItem_Struct); + SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); + + OUT(lootee); + OUT(looter); + eq->slot_id = ServerToRoF2CorpseSlot(emu->slot_id); + OUT(auto_loot); + + FINISH_ENCODE(); + } + + ENCODE(OP_ManaChange) + { + ENCODE_LENGTH_EXACT(ManaChange_Struct); + SETUP_DIRECT_ENCODE(ManaChange_Struct, structs::ManaChange_Struct); + + OUT(new_mana); + OUT(stamina); + OUT(spell_id); + eq->unknown16 = -1; // Self Interrupt/Success = -1, Fizzle = 1, Other Interrupt = 2? + + FINISH_ENCODE(); + } + + ENCODE(OP_MercenaryDataResponse) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + MercenaryMerchantList_Struct *emu = (MercenaryMerchantList_Struct *)__emu_buffer; + + char *Buffer = (char *)in->pBuffer; + + int PacketSize = sizeof(structs::MercenaryMerchantList_Struct) - 4 + emu->MercTypeCount * 4; + PacketSize += (sizeof(structs::MercenaryListEntry_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; + + uint32 r; + uint32 k; + for (r = 0; r < emu->MercCount; r++) + { + PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->Mercs[r].StanceCount; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_MercenaryDataResponse, PacketSize); + Buffer = (char *)outapp->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercTypeCount); + + for (r = 0; r < emu->MercTypeCount; r++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercGrades[r]); + } + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + + for (r = 0; r < emu->MercCount; r++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercID); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercSubType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].PurchaseCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].UpkeepCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].Status); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyUpkeep); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyType); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->Mercs[r].MercUnk01); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->Mercs[r].TimeLeft); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MerchantSlot); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercUnk02); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].StanceCount); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].MercUnk03); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->Mercs[r].MercUnk04); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // MercName + for (k = 0; k < emu->Mercs[r].StanceCount; k++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].Stances[k].StanceIndex); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].Stances[k].Stance); + } + } + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_MercenaryDataUpdate) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + MercenaryDataUpdate_Struct *emu = (MercenaryDataUpdate_Struct *)__emu_buffer; + + char *Buffer = (char *)in->pBuffer; + + EQApplicationPacket *outapp; + + uint32 PacketSize = 0; + + // There are 2 different sized versions of this packet depending if a merc is hired or not + if (emu->MercStatus >= 0) + { + PacketSize += sizeof(structs::MercenaryDataUpdate_Struct) + (sizeof(structs::MercenaryData_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; + + uint32 r; + uint32 k; + for (r = 0; r < emu->MercCount; r++) + { + PacketSize += sizeof(structs::MercenaryStance_Struct) * emu->MercData[r].StanceCount; + PacketSize += strlen(emu->MercData[r].MercName); // Null Terminator size already accounted for in the struct + } + + outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, PacketSize); + Buffer = (char *)outapp->pBuffer; + + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercStatus); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + + for (r = 0; r < emu->MercCount; r++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercID); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercSubType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].PurchaseCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].UpkeepCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Status); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyUpkeep); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyType); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->MercData[r].MercUnk01); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].TimeLeft); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MerchantSlot); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].MercUnk02); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].StanceCount); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].MercUnk03); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->MercData[r].MercUnk04); + //VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // MercName + VARSTRUCT_ENCODE_STRING(Buffer, emu->MercData[r].MercName); + for (k = 0; k < emu->MercData[r].StanceCount; k++) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Stances[k].StanceIndex); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].Stances[k].Stance); + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); // MercUnk05 + } + } + else + { + PacketSize += sizeof(structs::NoMercenaryHired_Struct); + + outapp = new EQApplicationPacket(OP_MercenaryDataUpdate, PacketSize); + Buffer = (char *)outapp->pBuffer; + + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercStatus); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); + } + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_MoveItem) + { + ENCODE_LENGTH_EXACT(MoveItem_Struct); + SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + + eq->from_slot = ServerToRoF2Slot(emu->from_slot); + eq->to_slot = ServerToRoF2Slot(emu->to_slot); + OUT(number_in_stack); + + FINISH_ENCODE(); + } + + ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } + + ENCODE(OP_NewZone) + { + SETUP_DIRECT_ENCODE(NewZone_Struct, structs::NewZone_Struct); + + OUT_str(char_name); + OUT_str(zone_short_name); + OUT_str(zone_long_name); + OUT(ztype); + int r; + for (r = 0; r < 4; r++) { + OUT(fog_red[r]); + OUT(fog_green[r]); + OUT(fog_blue[r]); + OUT(fog_minclip[r]); + OUT(fog_maxclip[r]); + } + OUT(gravity); + OUT(time_type); + for (r = 0; r < 4; r++) { + OUT(rain_chance[r]); + } + for (r = 0; r < 4; r++) { + OUT(rain_duration[r]); + } + for (r = 0; r < 4; r++) { + OUT(snow_chance[r]); + } + for (r = 0; r < 4; r++) { + OUT(snow_duration[r]); + } + for (r = 0; r < 32; r++) { + eq->unknown537[r] = 0xFF; //observed + } + OUT(sky); + OUT(zone_exp_multiplier); + OUT(safe_y); + OUT(safe_x); + OUT(safe_z); + OUT(max_z); + OUT(underworld); + OUT(minclip); + OUT(maxclip); + OUT_str(zone_short_name2); + OUT(zone_id); + OUT(zone_instance); + OUT(SuspendBuffs); + + eq->FogDensity = emu->fog_density; + + /*fill in some unknowns with observed values, hopefully it will help */ + eq->unknown800 = -1; + eq->unknown844 = 600; + eq->unknown880 = 50; + eq->unknown884 = 10; + eq->unknown888 = 1; + eq->unknown889 = 0; + eq->unknown890 = 1; + eq->unknown891 = 0; + eq->unknown892 = 0; + eq->unknown893 = 0; + eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off + eq->unknown895 = 0; + eq->unknown896 = 180; + eq->unknown900 = 180; + eq->unknown904 = 180; + eq->unknown908 = 2; + eq->unknown912 = 2; + eq->unknown932 = -1; // Set from PoK Example + eq->unknown936 = -1; // Set from PoK Example + eq->unknown944 = 1.0; // Set from PoK Example + + FINISH_ENCODE(); + } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + // This packet is variable sized now, but forcing it to the old packet size for now. + eq->Title_Count = 128; + memcpy(eq->Title, emu->Title, sizeof(eq->Title)); + eq->Text_Count = 4096; + memcpy(eq->Text, emu->Text, sizeof(eq->Text)); + OUT(Buttons); + OUT(Duration); + OUT(PopupID); + OUT(NegativeID); + // These two field names are used if Buttons == 1. We should add an interface to them via Perl. + eq->ButtonName0_Count = 25; + OUT_str(ButtonName0); + eq->ButtonName1_Count = 25; + OUT_str(ButtonName1); + + FINISH_ENCODE(); + } + + /* + ENCODE(OP_OpenNewTasksWindow) + { + AvailableTaskHeader_Struct* __emu_AvailableTaskHeader; + AvailableTaskData1_Struct* __emu_AvailableTaskData1; + AvailableTaskData2_Struct* __emu_AvailableTaskData2; + AvailableTaskTrailer_Struct* __emu_AvailableTaskTrailer; + + structs::AvailableTaskHeader_Struct* __eq_AvailableTaskHeader; + structs::AvailableTaskData1_Struct* __eq_AvailableTaskData1; + structs::AvailableTaskData2_Struct* __eq_AvailableTaskData2; + structs::AvailableTaskTrailer_Struct* __eq_AvailableTaskTrailer; + + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + + __emu_AvailableTaskHeader = (AvailableTaskHeader_Struct*)__emu_buffer; + + // For each task, SoF has an extra uint32 and what appears to be space for a null terminated string. + // + in->size = in->size + (__emu_AvailableTaskHeader->TaskCount * 5); + + in->pBuffer = new unsigned char[in->size]; + + unsigned char *__eq_buffer = in->pBuffer; + + __eq_AvailableTaskHeader = (structs::AvailableTaskHeader_Struct*)__eq_buffer; + + char *__eq_ptr, *__emu_Ptr; + + // Copy Header + // + // + + __eq_AvailableTaskHeader->TaskCount = __emu_AvailableTaskHeader->TaskCount; + __eq_AvailableTaskHeader->unknown1 = __emu_AvailableTaskHeader->unknown1; + __eq_AvailableTaskHeader->TaskGiver = __emu_AvailableTaskHeader->TaskGiver; + + __emu_Ptr = (char *) __emu_AvailableTaskHeader + sizeof(AvailableTaskHeader_Struct); + __eq_ptr = (char *) __eq_AvailableTaskHeader + sizeof(structs::AvailableTaskHeader_Struct); + + for(uint32 i=0; i<__emu_AvailableTaskHeader->TaskCount; i++) { + + __emu_AvailableTaskData1 = (AvailableTaskData1_Struct*)__emu_Ptr; + __eq_AvailableTaskData1 = (structs::AvailableTaskData1_Struct*)__eq_ptr; + + __eq_AvailableTaskData1->TaskID = __emu_AvailableTaskData1->TaskID; + // This next unknown seems to affect the colour of the task title. 0x3f80000 is what I have seen + // in RoF2 packets. Changing it to 0x3f000000 makes the title red. + __eq_AvailableTaskData1->unknown1 = 0x3f800000; + __eq_AvailableTaskData1->TimeLimit = __emu_AvailableTaskData1->TimeLimit; + __eq_AvailableTaskData1->unknown2 = __emu_AvailableTaskData1->unknown2; + + __emu_Ptr += sizeof(AvailableTaskData1_Struct); + __eq_ptr += sizeof(structs::AvailableTaskData1_Struct); + + strcpy(__eq_ptr, __emu_Ptr); // Title + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + strcpy(__eq_ptr, __emu_Ptr); // Description + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + __eq_ptr[0] = 0; + __eq_ptr += strlen(__eq_ptr) + 1; + + __emu_AvailableTaskData2 = (AvailableTaskData2_Struct*)__emu_Ptr; + __eq_AvailableTaskData2 = (structs::AvailableTaskData2_Struct*)__eq_ptr; + + __eq_AvailableTaskData2->unknown1 = __emu_AvailableTaskData2->unknown1; + __eq_AvailableTaskData2->unknown2 = __emu_AvailableTaskData2->unknown2; + __eq_AvailableTaskData2->unknown3 = __emu_AvailableTaskData2->unknown3; + __eq_AvailableTaskData2->unknown4 = __emu_AvailableTaskData2->unknown4; + + __emu_Ptr += sizeof(AvailableTaskData2_Struct); + __eq_ptr += sizeof(structs::AvailableTaskData2_Struct); + + strcpy(__eq_ptr, __emu_Ptr); // Unknown string + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + strcpy(__eq_ptr, __emu_Ptr); // Unknown string + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + + __emu_AvailableTaskTrailer = (AvailableTaskTrailer_Struct*)__emu_Ptr; + __eq_AvailableTaskTrailer = (structs::AvailableTaskTrailer_Struct*)__eq_ptr; + + __eq_AvailableTaskTrailer->ItemCount = __emu_AvailableTaskTrailer->ItemCount; + __eq_AvailableTaskTrailer->unknown1 = __emu_AvailableTaskTrailer->unknown1; + __eq_AvailableTaskTrailer->unknown2 = __emu_AvailableTaskTrailer->unknown2; + __eq_AvailableTaskTrailer->StartZone = __emu_AvailableTaskTrailer->StartZone; + + __emu_Ptr += sizeof(AvailableTaskTrailer_Struct); + __eq_ptr += sizeof(structs::AvailableTaskTrailer_Struct); + + strcpy(__eq_ptr, __emu_Ptr); // Unknown string + + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + */ + + ENCODE(OP_PetBuffWindow) + { + // The format of the RoF2 packet is identical to the OP_BuffCreate packet. + + SETUP_VAR_ENCODE(PetBuff_Struct); + + uint32 sz = 12 + (17 * emu->buffcount); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); + + __packet->WriteUInt32(emu->petid); + __packet->WriteUInt32(0); // PlayerID ? + __packet->WriteUInt8(1); // 1 indicates all buffs on the pet (0 to add or remove a single buff) + __packet->WriteUInt16(emu->buffcount); + + for (uint16 i = 0; i < BUFF_COUNT; ++i) + { + if (emu->spellid[i]) + { + __packet->WriteUInt32(i); + __packet->WriteUInt32(emu->spellid[i]); + __packet->WriteUInt32(emu->ticsremaining[i]); + __packet->WriteUInt32(0); // Unknown + __packet->WriteString(""); + } + } + __packet->WriteUInt8(0); // Unknown + + FINISH_ENCODE(); + } + + ENCODE(OP_PlayerProfile) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + PlayerProfile_Struct *emu = (PlayerProfile_Struct *)__emu_buffer; + + uint32 PacketSize = 40000; // Calculate this later + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_PlayerProfile, PacketSize); + + outapp->WriteUInt32(0); // Checksum, we will update this later + outapp->WriteUInt32(0); // Checksum size, we will update this later + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + + outapp->WriteUInt8(emu->gender); // Gender + outapp->WriteUInt32(emu->race); // Race + outapp->WriteUInt8(emu->class_); // Class + outapp->WriteUInt8(emu->level); // Level + outapp->WriteUInt8(emu->level); // Level1 + + + outapp->WriteUInt32(5); // Bind count + + for (int r = 0; r < 5; r++) + { + outapp->WriteUInt32(emu->binds[r].zoneId); + outapp->WriteFloat(emu->binds[r].x); + outapp->WriteFloat(emu->binds[r].y); + outapp->WriteFloat(emu->binds[r].z); + outapp->WriteFloat(emu->binds[r].heading); + } + + outapp->WriteUInt32(emu->deity); + outapp->WriteUInt32(emu->intoxication); + + outapp->WriteUInt32(10); // Unknown count + + for (int r = 0; r < 10; r++) + { + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt32(22); // Equipment count + + for (int r = 0; r < 9; r++) + { + outapp->WriteUInt32(emu->item_material[r]); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + // Write zeroes for the next 13 equipment slots + + for (int r = 0; r < 13; r++) + { + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(9); // Equipment2 count + + for (int r = 0; r < 9; r++) + { + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(9); // Tint Count + + for (int r = 0; r < 7; r++) + { + outapp->WriteUInt32(emu->item_tint[r].color); + } + // Write zeroes for extra two tint values + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + + outapp->WriteUInt32(9); // Tint2 Count + + for (int r = 0; r < 7; r++) + { + outapp->WriteUInt32(emu->item_tint[r].color); + } + // Write zeroes for extra two tint values + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + + outapp->WriteUInt8(emu->haircolor); + outapp->WriteUInt8(emu->beardcolor); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt8(emu->eyecolor1); + outapp->WriteUInt8(emu->eyecolor2); + outapp->WriteUInt8(emu->hairstyle); + outapp->WriteUInt8(emu->beard); + outapp->WriteUInt8(emu->face); + + // Think there should be an extra byte before the drakkin stuff (referred to as oldface in client) + // Then one of the five bytes following the drakkin stuff needs removing. + + outapp->WriteUInt32(emu->drakkin_heritage); + outapp->WriteUInt32(emu->drakkin_tattoo); + outapp->WriteUInt32(emu->drakkin_details); + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteFloat(5.0f); // Height ? + + outapp->WriteFloat(3.0f); // Unknown + outapp->WriteFloat(2.5f); // Unknown + outapp->WriteFloat(5.5f); // Unknown + + outapp->WriteUInt32(0); // Primary ? + outapp->WriteUInt32(0); // Secondary ? + + outapp->WriteUInt32(emu->points); // Unspent skill points + outapp->WriteUInt32(emu->mana); + outapp->WriteUInt32(emu->cur_hp); + + outapp->WriteUInt32(emu->STR); + outapp->WriteUInt32(emu->STA); + outapp->WriteUInt32(emu->CHA); + outapp->WriteUInt32(emu->DEX); + outapp->WriteUInt32(emu->INT); + outapp->WriteUInt32(emu->AGI); + outapp->WriteUInt32(emu->WIS); + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(300); // AA Count + + for (uint32 r = 0; r < MAX_PP_AA_ARRAY; r++) + { + outapp->WriteUInt32(emu->aa_array[r].AA); + outapp->WriteUInt32(emu->aa_array[r].value); + outapp->WriteUInt32(0); + } + + // Fill the other 60 AAs with zeroes + + for (uint32 r = 0; r < structs::MAX_PP_AA_ARRAY - MAX_PP_AA_ARRAY; r++) + { + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(structs::MAX_PP_SKILL); + + for (uint32 r = 0; r < structs::MAX_PP_SKILL; r++) + { + outapp->WriteUInt32(emu->skills[r]); + } + + // deprecated + // Write zeroes for the rest of the skills + /* + for(uint32 r = 0; r < structs::MAX_PP_SKILL - MAX_PP_SKILL; r++) + { + outapp->WriteUInt32(emu->skills[r]); + } + */ + + outapp->WriteUInt32(25); // Unknown count + + for (uint32 r = 0; r < 25; r++) + { + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt32(structs::MAX_PP_DISCIPLINES); // Discipline count + + for (uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) + { + outapp->WriteUInt32(emu->disciplines.values[r]); + } + + // Write zeroes for the rest of the disciplines + for (uint32 r = 0; r < structs::MAX_PP_DISCIPLINES - MAX_PP_DISCIPLINES; r++) + { + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(20); // Timestamp count + + for (uint32 r = 0; r < 20; r++) + { + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(MAX_RECAST_TYPES); // Timestamp count + + for (uint32 r = 0; r < MAX_RECAST_TYPES; r++) + { + outapp->WriteUInt32(emu->recastTimers[r]); + } + + outapp->WriteUInt32(100); // Timestamp2 count + + for (uint32 r = 0; r < 100; r++) + { + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(structs::MAX_PP_SPELLBOOK); // Spellbook slots + + for (uint32 r = 0; r < MAX_PP_SPELLBOOK; r++) + { + outapp->WriteUInt32(emu->spell_book[r]); + } + // zeroes for the rest of the spellbook slots + for (uint32 r = 0; r < structs::MAX_PP_SPELLBOOK - MAX_PP_SPELLBOOK; r++) + { + outapp->WriteUInt32(0xFFFFFFFFU); + } + + outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots + + for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) + { + outapp->WriteUInt32(emu->mem_spells[r]); + } + // zeroes for the rest of the slots + for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++) + { + outapp->WriteUInt32(0xFFFFFFFFU); + } + + outapp->WriteUInt32(13); // Unknown count + + for (uint32 r = 0; r < 13; r++) + { + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(structs::BUFF_COUNT); + + //*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise + //*001*/ float unknown004; // Seen 1 for no buff + //*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages + //*009*/ uint32 unknown016; + //*013*/ uint8 bard_modifier; + //*014*/ uint32 duration; + //*018*/ uint8 level; + //*019*/ uint32 spellid; + //*023*/ uint32 counters; + //*027*/ uint8 unknown0028[53]; + //*080*/ + + for (uint32 r = 0; r < BUFF_COUNT; r++) + { + float instrument_mod = 0.0f; + uint8 slotid = emu->buffs[r].slotid; + uint32 player_id = emu->buffs[r].player_id;; + + if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) + { + instrument_mod = 1.0f + (emu->buffs[r].bard_modifier - 10) / 10.0f; + slotid = 2; + player_id = 0x000717fd; + } + else + { + slotid = 0; + } + outapp->WriteUInt8(0); // Had this as slot, but always appears to be 0 on live. + outapp->WriteFloat(instrument_mod); + outapp->WriteUInt32(player_id); + outapp->WriteUInt8(0); + outapp->WriteUInt32(emu->buffs[r].counters); + //outapp->WriteUInt8(emu->buffs[r].bard_modifier); + outapp->WriteUInt32(emu->buffs[r].duration); + outapp->WriteUInt8(emu->buffs[r].level); + outapp->WriteUInt32(emu->buffs[r].spellid); + outapp->WriteUInt32(slotid); // Only ever seen 2 + outapp->WriteUInt32(0); + outapp->WriteUInt8(0); + outapp->WriteUInt32(emu->buffs[r].counters); // Appears twice ? + + for (uint32 j = 0; j < 44; ++j) + outapp->WriteUInt8(0); // Unknown + } + + for (uint32 r = 0; r < structs::BUFF_COUNT - BUFF_COUNT; r++) + { + // 80 bytes of zeroes + for (uint32 j = 0; j < 20; ++j) + outapp->WriteUInt32(0); + + } + + outapp->WriteUInt32(emu->platinum); + outapp->WriteUInt32(emu->gold); + outapp->WriteUInt32(emu->silver); + outapp->WriteUInt32(emu->copper); + + outapp->WriteUInt32(emu->platinum_cursor); + outapp->WriteUInt32(emu->gold_cursor); + outapp->WriteUInt32(emu->silver_cursor); + outapp->WriteUInt32(emu->copper_cursor); + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(0); // This is the cooldown timer for the monk 'Mend' skill. Client will add 6 minutes to this value the first time the + // player logs in. After that it will honour whatever value we send here. + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(emu->thirst_level); + outapp->WriteUInt32(emu->hunger_level); + + outapp->WriteUInt32(emu->aapoints_spent); + + outapp->WriteUInt32(5); // AA Points count ?? + outapp->WriteUInt32(1234); // AA Points assigned + outapp->WriteUInt32(0); // AA Points in General ? + outapp->WriteUInt32(0); // AA Points in Class ? + outapp->WriteUInt32(0); // AA Points in Archetype ? + outapp->WriteUInt32(0); // AA Points in Special ? + outapp->WriteUInt32(emu->aapoints); // AA Points unspent + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(structs::MAX_PLAYER_BANDOLIER); + + for (uint32 r = 0; r < EmuConstants::BANDOLIERS_COUNT; r++) + { + outapp->WriteString(emu->bandoliers[r].name); + + for (uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j) + { + outapp->WriteString(emu->bandoliers[r].items[j].item_name); + outapp->WriteUInt32(emu->bandoliers[r].items[j].item_id); + outapp->WriteUInt32(emu->bandoliers[r].items[j].icon); + } + } + + for (uint32 r = 0; r < structs::MAX_PLAYER_BANDOLIER - EmuConstants::BANDOLIERS_COUNT; r++) + { + outapp->WriteString(""); + + for (uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j) + { + outapp->WriteString(""); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + } + + outapp->WriteUInt32(structs::MAX_POTIONS_IN_BELT); + + for (uint32 r = 0; r < EmuConstants::POTION_BELT_SIZE; r++) + { + outapp->WriteString(emu->potionbelt.items[r].item_name); + outapp->WriteUInt32(emu->potionbelt.items[r].item_id); + outapp->WriteUInt32(emu->potionbelt.items[r].icon); + } + + for (uint32 r = 0; r < structs::MAX_POTIONS_IN_BELT - EmuConstants::POTION_BELT_SIZE; r++) + { + outapp->WriteString(""); + outapp->WriteUInt32(0); + outapp->WriteUInt32(0); + } + + outapp->WriteSInt32(-1); // Unknown; + outapp->WriteSInt32(123); // HP Total ? + outapp->WriteSInt32(234); // Endurance Total ? + outapp->WriteSInt32(345); // Mana Total ? + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(20); // Unknown - Expansion count ? + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->endurance); + outapp->WriteUInt32(0); // Unknown - Observed 0x7cde - This is also seen in guild packets sent to this character. + outapp->WriteUInt32(0); // Unknown - Observed 0x64 + + outapp->WriteUInt32(64); // Name Length + + uint32 CurrentPosition = outapp->GetWritePosition(); + + outapp->WriteString(emu->name); + + outapp->SetWritePosition(CurrentPosition + 64); + + outapp->WriteUInt32(32); // Last Name Length + + CurrentPosition = outapp->GetWritePosition(); + + outapp->WriteString(emu->last_name); + + outapp->SetWritePosition(CurrentPosition + 32); + + outapp->WriteUInt32(emu->birthday); + outapp->WriteUInt32(emu->birthday); // Account start date ? + outapp->WriteUInt32(emu->lastlogin); + outapp->WriteUInt32(emu->timePlayedMin); + outapp->WriteUInt32(emu->timeentitledonaccount); + outapp->WriteUInt32(0x0007ffff); // Expansion bitmask + + outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); + + for (uint32 r = 0; r < MAX_PP_LANGUAGE; r++) + { + outapp->WriteUInt8(emu->languages[r]); + } + + for (uint32 r = 0; r < structs::MAX_PP_LANGUAGE - MAX_PP_LANGUAGE; r++) + { + outapp->WriteUInt8(0); + } + + outapp->WriteUInt16(emu->zone_id); + outapp->WriteUInt16(emu->zoneInstance); + + outapp->WriteFloat(emu->y); + outapp->WriteFloat(emu->x); + outapp->WriteFloat(emu->z); + outapp->WriteFloat(emu->heading); + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->pvp); + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->gm); + + outapp->WriteUInt32(emu->guild_id); + outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt32(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt8(0); // Unknown - observed 1 in a live packet. + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt64(emu->exp); + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(emu->platinum_bank); + outapp->WriteUInt32(emu->gold_bank); + outapp->WriteUInt32(emu->silver_bank); + outapp->WriteUInt32(emu->copper_bank); + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(42); // The meaning of life ? + + for (uint32 r = 0; r < 42; r++) + { + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + } + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt32(emu->career_tribute_points); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->tribute_points); + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(EmuConstants::TRIBUTE_SIZE); + + for (uint32 r = 0; r < EmuConstants::TRIBUTE_SIZE; r++) + { + outapp->WriteUInt32(emu->tributes[r].tribute); + outapp->WriteUInt32(emu->tributes[r].tier); + } + + outapp->WriteUInt32(10); // Guild Tribute Count ? + + for (uint32 r = 0; r < 10; r++) + { + outapp->WriteUInt32(0xffffffff); + outapp->WriteUInt32(0); + } + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + // Block of 121 unknown bytes + for (uint32 r = 0; r < 121; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->currentRadCrystals); + outapp->WriteUInt32(emu->careerRadCrystals); + outapp->WriteUInt32(emu->currentEbonCrystals); + outapp->WriteUInt32(emu->careerEbonCrystals); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + // Unknown String ? + outapp->WriteUInt32(64); // Unknown + for (uint32 r = 0; r < 64; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + // Unknown String ? + outapp->WriteUInt32(64); // Unknown + for (uint32 r = 0; r < 64; r++) + outapp->WriteUInt8(0); // Unknown + + // Unknown String ? + outapp->WriteUInt32(64); // Unknown + for (uint32 r = 0; r < 64; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + // Block of 320 unknown bytes + for (uint32 r = 0; r < 320; r++) + outapp->WriteUInt8(0); // Unknown + + // Block of 343 unknown bytes + for (uint32 r = 0; r < 343; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(emu->leadAAActive); + + outapp->WriteUInt32(6); // Count ... of LDoN stats ? + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->ldon_points_guk); + outapp->WriteUInt32(emu->ldon_points_mir); + outapp->WriteUInt32(emu->ldon_points_mmc); + outapp->WriteUInt32(emu->ldon_points_ruj); + outapp->WriteUInt32(emu->ldon_points_tak); + + outapp->WriteUInt32(emu->ldon_points_available); + + outapp->WriteDouble(emu->group_leadership_exp); + outapp->WriteDouble(emu->raid_leadership_exp); + + outapp->WriteUInt32(emu->group_leadership_points); + outapp->WriteUInt32(emu->raid_leadership_points); + + outapp->WriteUInt32(64); // Group of 64 int32s follow Group/Raid Leadership abilities ? + + for (uint32 r = 0; r < MAX_LEADERSHIP_AA_ARRAY; r++) + outapp->WriteUInt32(emu->leader_abilities.ranks[r]); + + for (uint32 r = 0; r < 64 - MAX_LEADERSHIP_AA_ARRAY; r++) + outapp->WriteUInt32(0); // Unused/unsupported Leadership abilities + + outapp->WriteUInt32(emu->air_remaining); // ? + + // PVP Stats + + outapp->WriteUInt32(emu->PVPKills); + outapp->WriteUInt32(emu->PVPDeaths); + outapp->WriteUInt32(emu->PVPCurrentPoints); + outapp->WriteUInt32(emu->PVPCareerPoints); + outapp->WriteUInt32(emu->PVPBestKillStreak); + outapp->WriteUInt32(emu->PVPWorstDeathStreak); + outapp->WriteUInt32(emu->PVPCurrentKillStreak); + + // Last PVP Kill + + outapp->WriteString(emu->PVPLastKill.Name); + outapp->WriteUInt32(emu->PVPLastKill.Level); + outapp->WriteUInt32(emu->PVPLastKill.Race); + outapp->WriteUInt32(emu->PVPLastKill.Class); + outapp->WriteUInt32(emu->PVPLastKill.Zone); + outapp->WriteUInt32(emu->PVPLastKill.Time); + outapp->WriteUInt32(emu->PVPLastKill.Points); + + // Last PVP Death + + outapp->WriteString(emu->PVPLastDeath.Name); + outapp->WriteUInt32(emu->PVPLastDeath.Level); + outapp->WriteUInt32(emu->PVPLastDeath.Race); + outapp->WriteUInt32(emu->PVPLastDeath.Class); + outapp->WriteUInt32(emu->PVPLastDeath.Zone); + outapp->WriteUInt32(emu->PVPLastDeath.Time); + outapp->WriteUInt32(emu->PVPLastDeath.Points); + + outapp->WriteUInt32(emu->PVPNumberOfKillsInLast24Hours); + + // Last 50 Kills + outapp->WriteUInt32(50); + for (uint32 r = 0; r < 50; ++r) + { + outapp->WriteString(emu->PVPRecentKills[r].Name); + outapp->WriteUInt32(emu->PVPRecentKills[r].Level); + outapp->WriteUInt32(emu->PVPRecentKills[r].Race); + outapp->WriteUInt32(emu->PVPRecentKills[r].Class); + outapp->WriteUInt32(emu->PVPRecentKills[r].Zone); + outapp->WriteUInt32(emu->PVPRecentKills[r].Time); + outapp->WriteUInt32(emu->PVPRecentKills[r].Points); + } + + outapp->WriteUInt32(emu->expAA); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(emu->groupAutoconsent); + outapp->WriteUInt8(emu->raidAutoconsent); + outapp->WriteUInt8(emu->guildAutoconsent); + + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(emu->level); // Level3 ? + + outapp->WriteUInt8(emu->showhelm); + + outapp->WriteUInt32(emu->RestTimer); + + outapp->WriteUInt32(1024); // Unknown Count + + // Block of 1024 unknown bytes + outapp->WriteUInt8(31); // Unknown + + for (uint32 r = 0; r < 1023; r++) + outapp->WriteUInt8(0); // Unknown + + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + + // Think we need 1 byte of padding at the end + + outapp->WriteUInt8(0); // Unknown + + _log(NET__STRUCTS, "Player Profile Packet is %i bytes", outapp->GetWritePosition()); + + unsigned char *NewBuffer = new unsigned char[outapp->GetWritePosition()]; + memcpy(NewBuffer, outapp->pBuffer, outapp->GetWritePosition()); + safe_delete_array(outapp->pBuffer); + outapp->pBuffer = NewBuffer; + outapp->size = outapp->GetWritePosition(); + outapp->SetWritePosition(4); + outapp->WriteUInt32(outapp->size - 9); + + CRC32::SetEQChecksum(outapp->pBuffer, outapp->size - 1, 8); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + return; + } + + ENCODE(OP_RaidJoin) + { + EQApplicationPacket *inapp = *p; + unsigned char * __emu_buffer = inapp->pBuffer; + RaidCreate_Struct *raid_create = (RaidCreate_Struct*)__emu_buffer; + + EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + structs::RaidGeneral_Struct *general = (structs::RaidGeneral_Struct*)outapp_create->pBuffer; + + general->action = 8; + general->parameter = 1; + strn0cpy(general->leader_name, raid_create->leader_name, 64); + strn0cpy(general->player_name, raid_create->leader_name, 64); + + dest->FastQueuePacket(&outapp_create); + delete[] __emu_buffer; + } + + ENCODE(OP_RaidUpdate) + { + EQApplicationPacket *inapp = *p; + *p = nullptr; + unsigned char * __emu_buffer = inapp->pBuffer; + RaidGeneral_Struct *raid_gen = (RaidGeneral_Struct*)__emu_buffer; + + if (raid_gen->action == 0) // raid add has longer length than other raid updates + { + RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); + structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; + + add_member->raidGen.action = in_add_member->raidGen.action; + add_member->raidGen.parameter = in_add_member->raidGen.parameter; + strn0cpy(add_member->raidGen.leader_name, in_add_member->raidGen.leader_name, 64); + strn0cpy(add_member->raidGen.player_name, in_add_member->raidGen.player_name, 64); + add_member->_class = in_add_member->_class; + add_member->level = in_add_member->level; + add_member->isGroupLeader = in_add_member->isGroupLeader; + add_member->flags[0] = in_add_member->flags[0]; + add_member->flags[1] = in_add_member->flags[1]; + add_member->flags[2] = in_add_member->flags[2]; + add_member->flags[3] = in_add_member->flags[3]; + add_member->flags[4] = in_add_member->flags[4]; + dest->FastQueuePacket(&outapp); + } + else if (raid_gen->action == 35) + { + RaidMOTD_Struct *inmotd = (RaidMOTD_Struct *)__emu_buffer; + EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidMOTD_Struct) + strlen(inmotd->motd) + 1); + structs::RaidMOTD_Struct *outmotd = (structs::RaidMOTD_Struct *)outapp->pBuffer; + + outmotd->general.action = inmotd->general.action; + strn0cpy(outmotd->general.player_name, inmotd->general.player_name, 64); + strn0cpy(outmotd->motd, inmotd->motd, strlen(inmotd->motd) + 1); + dest->FastQueuePacket(&outapp); + } + else if (raid_gen->action == 14 || raid_gen->action == 30) + { + RaidLeadershipUpdate_Struct *inlaa = (RaidLeadershipUpdate_Struct *)__emu_buffer; + EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidLeadershipUpdate_Struct)); + structs::RaidLeadershipUpdate_Struct *outlaa = (structs::RaidLeadershipUpdate_Struct *)outapp->pBuffer; + + outlaa->action = inlaa->action; + strn0cpy(outlaa->player_name, inlaa->player_name, 64); + strn0cpy(outlaa->leader_name, inlaa->leader_name, 64); + memcpy(&outlaa->raid, &inlaa->raid, sizeof(RaidLeadershipAA_Struct)); + dest->FastQueuePacket(&outapp); + } + else + { + RaidGeneral_Struct* in_raid_general = (RaidGeneral_Struct*)__emu_buffer; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidGeneral_Struct)); + structs::RaidGeneral_Struct *raid_general = (structs::RaidGeneral_Struct*)outapp->pBuffer; + strn0cpy(raid_general->leader_name, in_raid_general->leader_name, 64); + strn0cpy(raid_general->player_name, in_raid_general->player_name, 64); + raid_general->action = in_raid_general->action; + raid_general->parameter = in_raid_general->parameter; + dest->FastQueuePacket(&outapp); + } + + delete[] __emu_buffer; + } + + ENCODE(OP_ReadBook) + { + ENCODE_LENGTH_ATLEAST(BookText_Struct); + SETUP_DIRECT_ENCODE(BookText_Struct, structs::BookRequest_Struct); + + if (emu->window == 0xFF) + eq->window = 0xFFFFFFFF; + else + eq->window = emu->window; + OUT(type); + OUT(invslot); + strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); + + FINISH_ENCODE(); + } + + ENCODE(OP_RecipeAutoCombine) + { + ENCODE_LENGTH_EXACT(RecipeAutoCombine_Struct); + SETUP_DIRECT_ENCODE(RecipeAutoCombine_Struct, structs::RecipeAutoCombine_Struct); + + OUT(object_type); + OUT(some_id); + eq->container_slot = ServerToRoF2Slot(emu->unknown1); + structs::ItemSlotStruct RoF2Slot; + RoF2Slot.SlotType = 8; // Observed + RoF2Slot.Unknown02 = 0; + RoF2Slot.MainSlot = 0xffff; + RoF2Slot.SubSlot = 0xffff; + RoF2Slot.AugSlot = 0xffff; + RoF2Slot.Unknown01 = 0; + eq->unknown_slot = RoF2Slot; + OUT(recipe_id); + OUT(reply_code); + + FINISH_ENCODE(); + } + + ENCODE(OP_RemoveBlockedBuffs) { ENCODE_FORWARD(OP_BlockedBuffs); } + + ENCODE(OP_RequestClientZoneChange) + { + ENCODE_LENGTH_EXACT(RequestClientZoneChange_Struct); + SETUP_DIRECT_ENCODE(RequestClientZoneChange_Struct, structs::RequestClientZoneChange_Struct); + + OUT(zone_id); + OUT(instance_id); + OUT(y); + OUT(x); + OUT(z); + OUT(heading); + eq->type = 0x0b; + eq->unknown004 = 0xffffffff; + eq->unknown172 = 0x0168b500; + + FINISH_ENCODE(); + } + + ENCODE(OP_RespondAA) + { + SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); + + eq->aa_spent = emu->aa_spent; + // These fields may need to be correctly populated at some point + eq->aapoints_assigned = emu->aa_spent + 1; + eq->aa_spent_general = 0; + eq->aa_spent_archetype = 0; + eq->aa_spent_class = 0; + eq->aa_spent_special = 0; + + for (uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i) + { + eq->aa_list[i].aa_skill = emu->aa_list[i].aa_skill; + eq->aa_list[i].aa_value = emu->aa_list[i].aa_value; + eq->aa_list[i].unknown08 = emu->aa_list[i].unknown08; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_RezzRequest) + { + SETUP_DIRECT_ENCODE(Resurrect_Struct, structs::Resurrect_Struct); + + OUT(zone_id); + OUT(instance_id); + OUT(y); + OUT(x); + OUT(z); + OUT_str(your_name); + OUT_str(rezzer_name); + OUT(spellid); + OUT_str(corpse_name); + OUT(action); + + FINISH_ENCODE(); + } + + ENCODE(OP_SendAATable) + { + ENCODE_LENGTH_ATLEAST(SendAA_Struct); + SETUP_VAR_ENCODE(SendAA_Struct); + ALLOC_VAR_ENCODE(structs::SendAA_Struct, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + + // Check clientver field to verify this AA should be sent for SoF + // clientver 1 is for all clients and 5 is for Live + if (emu->clientver <= 5) + { + OUT(id); + eq->unknown004 = 1; + //eq->hotkey_sid = (emu->hotkey_sid==4294967295UL)?0:(emu->id - emu->current_level + 1); + //eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->id - emu->current_level + 1); + //eq->title_sid = emu->id - emu->current_level + 1; + //eq->desc_sid = emu->id - emu->current_level + 1; + eq->hotkey_sid = (emu->hotkey_sid == 4294967295UL) ? -1 : (emu->sof_next_skill); + eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? -1 : (emu->sof_next_skill); + eq->title_sid = emu->sof_next_skill; + eq->desc_sid = emu->sof_next_skill; + OUT(class_type); + OUT(cost); + OUT(seq); + OUT(current_level); + eq->unknown037 = 1; // Introduced during HoT + OUT(prereq_skill); + eq->unknown045 = 1; // New Mar 21 2012 - Seen 1 + OUT(prereq_minpoints); + eq->type = emu->sof_type; + OUT(spellid); + eq->unknown057 = 1; // Introduced during HoT + OUT(spell_type); + OUT(spell_refresh); + OUT(classes); + OUT(berserker); + //eq->max_level = emu->sof_max_level; + OUT(max_level); + OUT(last_id); + OUT(next_id); + OUT(cost2); + eq->aa_expansion = emu->aa_expansion; + eq->special_category = emu->special_category; + OUT(total_abilities); + unsigned int r; + for (r = 0; r < emu->total_abilities; r++) { + OUT(abilities[r].skill_id); + OUT(abilities[r].base1); + OUT(abilities[r].base2); + OUT(abilities[r].slot); + } + } + + _hex(NET__ERROR, eq, sizeof(structs::SendAA_Struct) + emu->total_abilities*sizeof(structs::AA_Ability)); + + FINISH_ENCODE(); + } + + ENCODE(OP_SendCharInfo) + { + ENCODE_LENGTH_EXACT(CharacterSelect_Struct); + SETUP_VAR_ENCODE(CharacterSelect_Struct); + + //EQApplicationPacket *packet = *p; + //const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer; + + int char_count; + int namelen = 0; + for (char_count = 0; char_count < 10; char_count++) { + if (emu->name[char_count][0] == '\0') + break; + if (strcmp(emu->name[char_count], "") == 0) + break; + namelen += strlen(emu->name[char_count]); + } + + int total_length = sizeof(structs::CharacterSelect_Struct) + + char_count * sizeof(structs::CharacterSelectEntry_Struct) + + namelen; + + ALLOC_VAR_ENCODE(structs::CharacterSelect_Struct, total_length); + + //unsigned char *eq_buffer = new unsigned char[total_length]; + //structs::CharacterSelect_Struct *eq_head = (structs::CharacterSelect_Struct *) eq_buffer; + + eq->char_count = char_count; + //eq->total_chars = 10; + + unsigned char *bufptr = (unsigned char *)eq->entries; + int r; + for (r = 0; r < char_count; r++) { + { //pre-name section... + structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr; + memcpy(eq2->name, emu->name[r], strlen(emu->name[r]) + 1); + } + //adjust for name. + bufptr += strlen(emu->name[r]); + { //post-name section... + structs::CharacterSelectEntry_Struct *eq2 = (structs::CharacterSelectEntry_Struct *) bufptr; + eq2->class_ = emu->class_[r]; + eq2->race = emu->race[r]; + eq2->level = emu->level[r]; + eq2->class_2 = emu->class_[r]; + eq2->race2 = emu->race[r]; + eq2->zone = emu->zone[r]; + eq2->instance = 0; + eq2->gender = emu->gender[r]; + eq2->face = emu->face[r]; + int k; + for (k = 0; k < _MaterialCount; k++) { + eq2->equip[k].equip0 = emu->equip[r][k]; + eq2->equip[k].equip1 = 0; + eq2->equip[k].equip2 = 0; + eq2->equip[k].itemid = 0; + eq2->equip[k].equip3 = emu->equip[r][k]; + eq2->equip[k].color.color = emu->cs_colors[r][k].color; + } + eq2->u15 = 0xff; + eq2->u19 = 0xFF; + eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; + eq2->drakkin_details = emu->drakkin_details[r]; + eq2->deity = emu->deity[r]; + eq2->primary = emu->primary[r]; + eq2->secondary = emu->secondary[r]; + eq2->haircolor = emu->haircolor[r]; + eq2->beardcolor = emu->beardcolor[r]; + eq2->eyecolor1 = emu->eyecolor1[r]; + eq2->eyecolor2 = emu->eyecolor2[r]; + eq2->hairstyle = emu->hairstyle[r]; + eq2->beard = emu->beard[r]; + eq2->char_enabled = 1; + eq2->tutorial = emu->tutorial[r]; + eq2->drakkin_heritage = emu->drakkin_heritage[r]; + eq2->unknown1 = 0; + eq2->gohome = emu->gohome[r]; + eq2->LastLogin = 1212696584; + eq2->unknown2 = 0; + } + bufptr += sizeof(structs::CharacterSelectEntry_Struct); + } + + FINISH_ENCODE(); + } + + ENCODE(OP_SendMembership) + { + ENCODE_LENGTH_EXACT(Membership_Struct); + SETUP_DIRECT_ENCODE(Membership_Struct, structs::Membership_Struct); + + eq->membership = emu->membership; + eq->races = emu->races; + eq->classes = emu->classes; + eq->entrysize = 22; + for (int i = 0; i<21; i++) + { + eq->entries[i] = emu->entries[i]; + } + eq->entries[21] = 0; + + FINISH_ENCODE(); + } + + ENCODE(OP_SendZonepoints) + { + SETUP_VAR_ENCODE(ZonePoints); + ALLOC_VAR_ENCODE(structs::ZonePoints, sizeof(structs::ZonePoints) + sizeof(structs::ZonePoint_Entry) * (emu->count + 1)); + + eq->count = emu->count; + for (uint32 i = 0; i < emu->count; ++i) + { + eq->zpe[i].iterator = emu->zpe[i].iterator; + eq->zpe[i].x = emu->zpe[i].x; + eq->zpe[i].y = emu->zpe[i].y; + eq->zpe[i].z = emu->zpe[i].z; + eq->zpe[i].heading = emu->zpe[i].heading; + eq->zpe[i].zoneid = emu->zpe[i].zoneid; + eq->zpe[i].zoneinstance = emu->zpe[i].zoneinstance; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_SetGuildRank) + { + ENCODE_LENGTH_EXACT(GuildSetRank_Struct); + SETUP_DIRECT_ENCODE(GuildSetRank_Struct, structs::GuildSetRank_Struct); + + eq->GuildID = emu->Unknown00; + + /* Translate older ranks to new values */ + switch (emu->Rank) { + case 0: { eq->Rank = 5; break; } // GUILD_MEMBER 0 + case 1: { eq->Rank = 3; break; } // GUILD_OFFICER 1 + case 2: { eq->Rank = 1; break; } // GUILD_LEADER 2 + default: { eq->Rank = emu->Rank; break; } + } + + memcpy(eq->MemberName, emu->MemberName, sizeof(eq->MemberName)); + OUT(Banker); + eq->Unknown76 = 1; + + FINISH_ENCODE(); + } + + ENCODE(OP_ShopPlayerBuy) + { + ENCODE_LENGTH_EXACT(Merchant_Sell_Struct); + SETUP_DIRECT_ENCODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct); + + OUT(npcid); + OUT(playerid); + OUT(itemslot); + OUT(quantity); + OUT(price); + + FINISH_ENCODE(); + } + + ENCODE(OP_ShopPlayerSell) + { + ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); + SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); + + OUT(npcid); + eq->itemslot = ServerToRoF2MainInvSlot(emu->itemslot); + //OUT(itemslot); + OUT(quantity); + OUT(price); + + FINISH_ENCODE(); + } + + ENCODE(OP_ShopRequest) + { + ENCODE_LENGTH_EXACT(Merchant_Click_Struct); + SETUP_DIRECT_ENCODE(Merchant_Click_Struct, structs::Merchant_Click_Struct); + + OUT(npcid); + OUT(playerid); + OUT(command); + OUT(rate); + eq->unknown01 = 3; // Not sure what these values do yet, but list won't display without them + eq->unknown02 = 2592000; + + FINISH_ENCODE(); + } + + ENCODE(OP_SkillUpdate) + { + ENCODE_LENGTH_EXACT(SkillUpdate_Struct); + SETUP_DIRECT_ENCODE(SkillUpdate_Struct, structs::SkillUpdate_Struct); + + OUT(skillId); + OUT(value); + eq->unknown08 = 1; // Observed + eq->unknown09 = 80; // Observed + eq->unknown10 = 136; // Observed + eq->unknown11 = 54; // Observed + + FINISH_ENCODE(); + } + + ENCODE(OP_SomeItemPacketMaybe) + { + // This Opcode is not named very well. It is used for the animation of arrows leaving the player's bow + // and flying to the target. + // + + ENCODE_LENGTH_EXACT(Arrow_Struct); + SETUP_DIRECT_ENCODE(Arrow_Struct, structs::Arrow_Struct); + + OUT(src_y); + OUT(src_x); + OUT(src_z); + OUT(velocity); + OUT(launch_angle); + OUT(tilt); + OUT(arc); + OUT(source_id); + OUT(target_id); + OUT(item_id); + + eq->unknown070 = 175; // This needs to be set to something, else we get a 1HS animation instead of ranged. + + OUT(item_type); + OUT(skill); + + strncpy(eq->model_name, emu->model_name, sizeof(eq->model_name)); + + FINISH_ENCODE(); + } + + ENCODE(OP_SpawnAppearance) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *emu_buffer = in->pBuffer; + + SpawnAppearance_Struct *sas = (SpawnAppearance_Struct *)emu_buffer; + + if (sas->type != AT_Size) + { + dest->FastQueuePacket(&in, ack_req); + return; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_ChangeSize, sizeof(ChangeSize_Struct)); + + ChangeSize_Struct *css = (ChangeSize_Struct *)outapp->pBuffer; + + css->EntityID = sas->spawn_id; + css->Size = (float)sas->parameter; + css->Unknown08 = 0; + css->Unknown12 = 1.0f; + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_SpawnDoor) + { + SETUP_VAR_ENCODE(Door_Struct); + int door_count = __packet->size / sizeof(Door_Struct); + int total_length = door_count * sizeof(structs::Door_Struct); + ALLOC_VAR_ENCODE(structs::Door_Struct, total_length); + + int r; + for (r = 0; r < door_count; r++) { + strncpy(eq[r].name, emu[r].name, sizeof(eq[r].name)); + eq[r].xPos = emu[r].xPos; + eq[r].yPos = emu[r].yPos; + eq[r].zPos = emu[r].zPos; + eq[r].heading = emu[r].heading; + eq[r].incline = emu[r].incline; + eq[r].size = emu[r].size; + eq[r].doorId = emu[r].doorId; + eq[r].opentype = emu[r].opentype; + eq[r].state_at_spawn = emu[r].state_at_spawn; + eq[r].invert_state = emu[r].invert_state; + eq[r].door_param = emu[r].door_param; + eq[r].unknown0080 = 0; + eq[r].unknown0081 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0082 = 0; + eq[r].unknown0083 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0084 = 0; + eq[r].unknown0085 = 0; + eq[r].unknown0086 = 0; + } + + FINISH_ENCODE(); + } + + ENCODE(OP_Stun) + { + ENCODE_LENGTH_EXACT(Stun_Struct); + SETUP_DIRECT_ENCODE(Stun_Struct, structs::Stun_Struct); + + OUT(duration); + eq->unknown005 = 163; + eq->unknown006 = 67; + + FINISH_ENCODE(); + } + + ENCODE(OP_TargetBuffs) { ENCODE_FORWARD(OP_BuffCreate); } + + ENCODE(OP_TaskDescription) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskDescription, in->size + 1); + // Set the Write pointer as we don't know what has been done with the packet before we get it. + in->SetReadPosition(0); + // Copy the header + for (int i = 0; i < 5; ++i) + outapp->WriteUInt32(in->ReadUInt32()); + + // Copy Title + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + outapp->WriteUInt8(0); + + outapp->WriteUInt32(in->ReadUInt32()); // Duration + outapp->WriteUInt32(in->ReadUInt32()); // Unknown + uint32 StartTime = in->ReadUInt32(); + outapp->WriteUInt32(time(nullptr) - StartTime); // RoF2 has elapsed time here rather than starttime + + // Copy the rest of the packet verbatim + uint32 BytesLeftToCopy = in->size - in->GetReadPosition(); + memcpy(outapp->pBuffer + outapp->GetWritePosition(), in->pBuffer + in->GetReadPosition(), BytesLeftToCopy); + + delete in; + dest->FastQueuePacket(&outapp, ack_req); + } + + ENCODE(OP_TaskHistoryReply) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + // First we need to calculate the length of the new packet + in->SetReadPosition(4); + uint32 ActivityCount = in->ReadUInt32(); + + uint32 Text1Length = 0; + uint32 Text2Length = 0; + uint32 Text3Length = 0; + + uint32 OutboundPacketSize = 8; + + for (uint32 i = 0; i < ActivityCount; ++i) + { + Text1Length = 0; + Text2Length = 0; + Text3Length = 0; + + in->ReadUInt32(); // Activity type + + // Skip past Text1 + while (in->ReadUInt8()) + ++Text1Length; + + // Skip past Text2 + while (in->ReadUInt8()) + ++Text2Length; + + in->ReadUInt32(); + in->ReadUInt32(); + in->ReadUInt32(); + uint32 ZoneID = in->ReadUInt32(); + in->ReadUInt32(); + + // Skip past Text3 + while (in->ReadUInt8()) + ++Text3Length; + + char ZoneNumber[10]; + + sprintf(ZoneNumber, "%i", ZoneID); + + OutboundPacketSize += (24 + Text1Length + 1 + Text2Length + Text3Length + 1 + 7 + (strlen(ZoneNumber) * 2)); + } + + in->SetReadPosition(0); + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_TaskHistoryReply, OutboundPacketSize); + + outapp->WriteUInt32(in->ReadUInt32()); // Task index + outapp->WriteUInt32(in->ReadUInt32()); // Activity count + + for (uint32 i = 0; i < ActivityCount; ++i) + { + Text1Length = 0; + Text2Length = 0; + Text3Length = 0; + + outapp->WriteUInt32(in->ReadUInt32()); // ActivityType + + // Copy Text1 + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + + outapp->WriteUInt8(0); // Text1 has a null terminator + + uint32 CurrentPosition = in->GetReadPosition(); + + // Determine Length of Text2 + while (in->ReadUInt8()) + ++Text2Length; + + outapp->WriteUInt32(Text2Length); + + in->SetReadPosition(CurrentPosition); + + // Copy Text2 + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + + outapp->WriteUInt32(in->ReadUInt32()); // Goalcount + in->ReadUInt32(); + in->ReadUInt32(); + uint32 ZoneID = in->ReadUInt32(); + in->ReadUInt32(); + + char ZoneNumber[10]; + + sprintf(ZoneNumber, "%i", ZoneID); + + outapp->WriteUInt32(2); + outapp->WriteUInt8(0x2d); // "-" + outapp->WriteUInt8(0x31); // "1" + + outapp->WriteUInt32(2); + outapp->WriteUInt8(0x2d); // "-" + outapp->WriteUInt8(0x31); // "1" + outapp->WriteString(ZoneNumber); + + outapp->WriteUInt32(0); + + // Copy Tex3t + while (uint8 c = in->ReadUInt8()) + outapp->WriteUInt8(c); + + outapp->WriteUInt8(0); // Text3 has a null terminator + + outapp->WriteUInt8(0x31); // "1" + outapp->WriteString(ZoneNumber); + } + + delete in; + dest->FastQueuePacket(&outapp, ack_req); + } + + ENCODE(OP_Track) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + Track_Struct *emu = (Track_Struct *)__emu_buffer; + + int EntryCount = in->size / sizeof(Track_Struct); + + if (EntryCount == 0 || ((in->size % sizeof(Track_Struct))) != 0) + { + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Track_Struct)); + delete in; + return; + } + + int PacketSize = 2; + + for (int i = 0; i < EntryCount; ++i, ++emu) + PacketSize += (12 + strlen(emu->name)); + + emu = (Track_Struct *)__emu_buffer; + + in->size = PacketSize; + in->pBuffer = new unsigned char[in->size]; + + char *Buffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, EntryCount); + + for (int i = 0; i < EntryCount; ++i, ++emu) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->entityid); + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->distance); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_STRING(Buffer, emu->name); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->GroupMember); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_Trader) + { + if ((*p)->size == sizeof(ClickTrader_Struct)) + { + ENCODE_LENGTH_EXACT(ClickTrader_Struct); + SETUP_DIRECT_ENCODE(ClickTrader_Struct, structs::ClickTrader_Struct); + + eq->Code = emu->Code; + // Live actually has 200 items now, but 80 is the most our internal struct supports + for (uint32 i = 0; i < 200; i++) + { + strncpy(eq->items[i].SerialNumber, "0000000000000000", sizeof(eq->items[i].SerialNumber)); + eq->items[i].Unknown18 = 0; + if (i < 80) { + eq->ItemCost[i] = emu->ItemCost[i]; + } + else { + eq->ItemCost[i] = 0; + } + } + + FINISH_ENCODE(); + } + else if ((*p)->size == sizeof(Trader_ShowItems_Struct)) + { + ENCODE_LENGTH_EXACT(Trader_ShowItems_Struct); + SETUP_DIRECT_ENCODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct); + + eq->Code = emu->Code; + strncpy(eq->SerialNumber, "0000000000000000", sizeof(eq->SerialNumber)); + eq->TraderID = emu->TraderID; + eq->Stacksize = 0; + eq->Price = 0; + + FINISH_ENCODE(); + } + else if ((*p)->size == sizeof(TraderStatus_Struct)) + { + ENCODE_LENGTH_EXACT(TraderStatus_Struct); + SETUP_DIRECT_ENCODE(TraderStatus_Struct, structs::TraderStatus_Struct); + + eq->Code = emu->Code; + + FINISH_ENCODE(); + } + else if ((*p)->size == sizeof(TraderBuy_Struct)) + { + ENCODE_FORWARD(OP_TraderBuy); + } + } + + ENCODE(OP_TraderBuy) + { + ENCODE_LENGTH_EXACT(TraderBuy_Struct); + SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct); + + OUT(Action); + OUT(Price); + OUT(TraderID); + memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); + OUT(ItemID); + OUT(Quantity); + OUT(AlreadySold); + + FINISH_ENCODE(); + } + + ENCODE(OP_TributeInfo) + { + ENCODE_LENGTH_ATLEAST(TributeAbility_Struct); + SETUP_VAR_ENCODE(TributeAbility_Struct); + ALLOC_VAR_ENCODE(structs::TributeAbility_Struct, sizeof(structs::TributeAbility_Struct) + strlen(emu->name) + 1); + + OUT(tribute_id); + OUT(tier_count); + + for (uint32 i = 0; i < MAX_TRIBUTE_TIERS; ++i) + { + eq->tiers[i].level = emu->tiers[i].level; + eq->tiers[i].tribute_item_id = emu->tiers[i].tribute_item_id; + eq->tiers[i].cost = emu->tiers[i].cost; + } + + eq->unknown128 = 0; + + strcpy(eq->name, emu->name); + + FINISH_ENCODE(); + } + + ENCODE(OP_TributeItem) + { + ENCODE_LENGTH_EXACT(TributeItem_Struct); + SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); + + eq->slot = ServerToRoF2Slot(emu->slot); + OUT(quantity); + OUT(tribute_master_id); + OUT(tribute_points); + + FINISH_ENCODE(); + } + + ENCODE(OP_VetRewardsAvaliable) + { + EQApplicationPacket *inapp = *p; + unsigned char * __emu_buffer = inapp->pBuffer; + + uint32 count = ((*p)->Size() / sizeof(InternalVeteranReward)); + *p = nullptr; + + EQApplicationPacket *outapp_create = new EQApplicationPacket(OP_VetRewardsAvaliable, (sizeof(structs::VeteranReward)*count)); + uchar *old_data = __emu_buffer; + uchar *data = outapp_create->pBuffer; + for (unsigned int i = 0; i < count; ++i) + { + structs::VeteranReward *vr = (structs::VeteranReward*)data; + InternalVeteranReward *ivr = (InternalVeteranReward*)old_data; + + vr->claim_count = ivr->claim_count; + vr->claim_id = ivr->claim_id; + vr->number_available = ivr->number_available; + for (int x = 0; x < 8; ++x) + { + vr->items[x].item_id = ivr->items[x].item_id; + strncpy(vr->items[x].item_name, ivr->items[x].item_name, sizeof(vr->items[x].item_name)); + vr->items[x].charges = ivr->items[x].charges; + } + + old_data += sizeof(InternalVeteranReward); + data += sizeof(structs::VeteranReward); + } + + dest->FastQueuePacket(&outapp_create); + delete inapp; + } + + ENCODE(OP_WearChange) + { + ENCODE_LENGTH_EXACT(WearChange_Struct); + SETUP_DIRECT_ENCODE(WearChange_Struct, structs::WearChange_Struct); + + OUT(spawn_id); + OUT(material); + OUT(unknown06); + OUT(elite_material); + OUT(hero_forge_model); + OUT(unknown18); + OUT(color.color); + OUT(wear_slot_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_WhoAllResponse) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + char *InBuffer = (char *)in->pBuffer; + + WhoAllReturnStruct *wars = (WhoAllReturnStruct*)InBuffer; + + int Count = wars->playercount; + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_WhoAllResponse, in->size + (Count * 4)); + + char *OutBuffer = (char *)outapp->pBuffer; + + // The struct fields were moved around a bit, so adjust values before copying + wars->unknown44[0] = Count; + wars->unknown52 = 0; + + memcpy(OutBuffer, InBuffer, sizeof(WhoAllReturnStruct)); + + OutBuffer += sizeof(WhoAllReturnStruct); + InBuffer += sizeof(WhoAllReturnStruct); + + for (int i = 0; i < Count; ++i) + { + uint32 x; + + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + + InBuffer += 4; + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0xffffffff); + + char Name[64]; + + VARSTRUCT_DECODE_STRING(Name, InBuffer); // Char Name + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + + VARSTRUCT_DECODE_STRING(Name, InBuffer); // Guild Name + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + + for (int j = 0; j < 7; ++j) + { + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + } + + VARSTRUCT_DECODE_STRING(Name, InBuffer); // Account + VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + + x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + } + + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp); + delete in; + } + + ENCODE(OP_ZoneChange) + { + ENCODE_LENGTH_EXACT(ZoneChange_Struct); + SETUP_DIRECT_ENCODE(ZoneChange_Struct, structs::ZoneChange_Struct); + + memcpy(eq->char_name, emu->char_name, sizeof(emu->char_name)); + OUT(zoneID); + OUT(instanceID); + OUT(y); + OUT(x); + OUT(z) + OUT(zone_reason); + OUT(success); + + FINISH_ENCODE(); + } + + ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } + + ENCODE(OP_ZonePlayerToBind) + { + ENCODE_LENGTH_ATLEAST(ZonePlayerToBind_Struct); + + ZonePlayerToBind_Struct *zps = (ZonePlayerToBind_Struct*)(*p)->pBuffer; + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + + unsigned char *buffer1 = new unsigned char[sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name)]; + structs::ZonePlayerToBindHeader_Struct *zph = (structs::ZonePlayerToBindHeader_Struct*)buffer1; + unsigned char *buffer2 = new unsigned char[sizeof(structs::ZonePlayerToBindFooter_Struct)]; + structs::ZonePlayerToBindFooter_Struct *zpf = (structs::ZonePlayerToBindFooter_Struct*)buffer2; + + zph->x = zps->x; + zph->y = zps->y; + zph->z = zps->z; + zph->heading = zps->heading; + zph->bind_zone_id = 0; + zph->bind_instance_id = zps->bind_instance_id; + strncpy(zph->zone_name, zps->zone_name, sizeof(zph->zone_name)); + + zpf->unknown021 = 1; + zpf->unknown022 = 0; + zpf->unknown023 = 0; + zpf->unknown024 = 0; + + ss.write((const char*)buffer1, (sizeof(structs::ZonePlayerToBindHeader_Struct) + strlen(zps->zone_name))); + ss.write((const char*)buffer2, sizeof(structs::ZonePlayerToBindFooter_Struct)); + + delete[] buffer1; + delete[] buffer2; + delete[](*p)->pBuffer; + + (*p)->pBuffer = new unsigned char[ss.str().size()]; + (*p)->size = ss.str().size(); + + memcpy((*p)->pBuffer, ss.str().c_str(), ss.str().size()); + dest->FastQueuePacket(&(*p)); + } + + ENCODE(OP_ZoneServerInfo) + { + SETUP_DIRECT_ENCODE(ZoneServerInfo_Struct, ZoneServerInfo_Struct); + + OUT_str(ip); + OUT(port); + + FINISH_ENCODE(); + } + + ENCODE(OP_ZoneSpawns) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + Spawn_Struct *emu = (Spawn_Struct *)__emu_buffer; + + //determine and verify length + int entrycount = in->size / sizeof(Spawn_Struct); + if (entrycount == 0 || (in->size % sizeof(Spawn_Struct)) != 0) { + _log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(Spawn_Struct)); + delete in; + return; + } + + //_log(NET__STRUCTS, "Spawn name is [%s]", emu->name); + + emu = (Spawn_Struct *)__emu_buffer; + + //_log(NET__STRUCTS, "Spawn packet size is %i, entries = %i", in->size, entrycount); + + char *Buffer = (char *)in->pBuffer, *BufferStart; + + int r; + int k; + for (r = 0; r < entrycount; r++, emu++) { + + int PacketSize = 206; + + PacketSize += strlen(emu->name); + PacketSize += strlen(emu->lastName); + + emu->title[0] = 0; + emu->suffix[0] = 0; + + if (strlen(emu->title)) + PacketSize += strlen(emu->title) + 1; + + if (strlen(emu->suffix)) + PacketSize += strlen(emu->suffix) + 1; + + bool ShowName = 1; + if (emu->bodytype >= 66) + { + emu->race = 127; + emu->bodytype = 11; + emu->gender = 0; + ShowName = 0; + } + + float SpawnSize = emu->size; + if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + { + PacketSize += 60; + + if (emu->size == 0) + { + emu->size = 6; + SpawnSize = 6; + } + } + else + PacketSize += 216; + + if (SpawnSize == 0) + { + SpawnSize = 3; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); + Buffer = (char *)outapp->pBuffer; + BufferStart = Buffer; + VARSTRUCT_ENCODE_STRING(Buffer, emu->name); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); + VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height? + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + + structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer; + + Bitfields->gender = emu->gender; + Bitfields->ispet = emu->is_pet; + Bitfields->afk = emu->afk; + Bitfields->anon = emu->anon; + Bitfields->gm = emu->gm; + Bitfields->sneak = 0; + Bitfields->lfg = emu->lfg; + Bitfields->invis = emu->invis; + Bitfields->linkdead = 0; + Bitfields->showhelm = emu->showhelm; + Bitfields->trader = 0; + Bitfields->targetable = 1; + Bitfields->targetable_with_hotkey = (emu->IsMercenary ? 0 : 1); + Bitfields->showname = ShowName; + + // Not currently found + // Bitfields->statue = 0; + // Bitfields->buyer = 0; + + Buffer += sizeof(structs::Spawn_Struct_Bitfields); + + uint8 OtherData = 0; + + if (strlen(emu->title)) + OtherData = OtherData | 16; + + if (strlen(emu->suffix)) + OtherData = OtherData | 32; + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); + + VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3 + VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 + + // Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not + // present. Will sort that out later. + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->curHp); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->haircolor); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->beardcolor); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->eyecolor1); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->eyecolor2); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->hairstyle); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->beard); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_heritage); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // unknown8 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11 + + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face); + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->walkspeed); + VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->runspeed); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->race); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding' + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity); + if (emu->NPC) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xFFFFFFFF); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); + } + else + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildID); + + /* Translate older ranks to new values */ + switch (emu->guildrank) { + case 0: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 5); break; } // GUILD_MEMBER 0 + case 1: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 3); break; } // GUILD_OFFICER 1 + case 2: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 1); break; } // GUILD_LEADER 2 + default: { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->guildrank); break; } // + } + } + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->class_); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // pvp + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->StandState); // standstate + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->light); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->flymode); + + VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle ?? + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head. + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId); + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown14 - Stance 64 = normal 4 = aggressive 40 = stun/mezzed + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 + + if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + { + for (k = 0; k < 9; ++k) + { + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color); + } + } + + structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; + + for (k = 0; k < 9; k++) { + Equipment[k].equip0 = emu->equipment[k]; + Equipment[k].equip1 = 0; + Equipment[k].equip2 = 0; + Equipment[k].equip3 = 0; + Equipment[k].itemId = 0; + } + + Buffer += (sizeof(structs::EquipStruct) * 9); + } + else + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialPrimary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->equipment[MaterialSecondary]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + } + + structs::Spawn_Struct_Position *Position = (structs::Spawn_Struct_Position*)Buffer; + + Position->y = emu->y; + Position->deltaZ = emu->deltaZ; + Position->deltaX = emu->deltaX; + Position->x = emu->x; + Position->heading = emu->heading; + Position->deltaHeading = emu->deltaHeading; + Position->z = emu->z; + Position->animation = emu->animation; + Position->deltaY = emu->deltaY; + + Buffer += sizeof(structs::Spawn_Struct_Position); + + if (strlen(emu->title)) + { + VARSTRUCT_ENCODE_STRING(Buffer, emu->title); + } + + if (strlen(emu->suffix)) + { + VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix); + } + + Buffer += 8; + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary); + VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); + // 29 zero bytes follow + Buffer += 29; + if (Buffer != (BufferStart + PacketSize)) + { + _log(NET__ERROR, "SPAWN ENCODE LOGIC PROBLEM: Buffer pointer is now %i from end", Buffer - (BufferStart + PacketSize)); + } + //_log(NET__ERROR, "Sending zone spawn for %s packet is %i bytes", emu->name, outapp->size); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); + dest->FastQueuePacket(&outapp, ack_req); + } + + delete in; + } + +// DECODE methods + DECODE(OP_AdventureMerchantSell) + { + DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); + SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); + + IN(npcid); + emu->slot = RoF2ToServerMainInvSlot(eq->slot); + IN(charges); + IN(sell_price); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AltCurrencySell) + { + DECODE_LENGTH_EXACT(structs::AltCurrencySellItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + IN(merchant_entity_id); + emu->slot_id = RoF2ToServerSlot(eq->slot_id); + IN(charges); + IN(cost); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AltCurrencySellSelection) + { + DECODE_LENGTH_EXACT(structs::AltCurrencySelectItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); + + IN(merchant_entity_id); + emu->slot_id = RoF2ToServerSlot(eq->slot_id); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ApplyPoison) + { + DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); + SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + emu->inventorySlot = RoF2ToServerMainInvSlot(eq->inventorySlot); + IN(success); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AugmentInfo) + { + DECODE_LENGTH_EXACT(structs::AugmentInfo_Struct); + SETUP_DIRECT_DECODE(AugmentInfo_Struct, structs::AugmentInfo_Struct); + + IN(itemid); + IN(window); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_AugmentItem) + { + DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); + SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); + + emu->container_slot = RoF2ToServerSlot(eq->container_slot); + emu->augment_slot = RoF2ToServerSlot(eq->augment_slot); + emu->container_index = eq->container_index; + emu->augment_index = eq->augment_index; + emu->dest_inst_id = eq->dest_inst_id; + emu->augment_action = eq->augment_action; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_BazaarSearch) + { + char *Buffer = (char *)__packet->pBuffer; + + uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + + if ((SubAction != BazaarInspectItem) || (__packet->size != sizeof(structs::NewBazaarInspect_Struct))) + return; + + SETUP_DIRECT_DECODE(NewBazaarInspect_Struct, structs::NewBazaarInspect_Struct); + MEMSET_IN(structs::NewBazaarInspect_Struct); + + IN(Beginning.Action); + memcpy(emu->Name, eq->Name, sizeof(emu->Name)); + IN(SerialNumber); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_BlockedBuffs) + { + DECODE_LENGTH_EXACT(structs::BlockedBuffs_Struct); + SETUP_DIRECT_DECODE(BlockedBuffs_Struct, structs::BlockedBuffs_Struct); + + for (uint32 i = 0; i < BLOCKED_BUFF_COUNT; ++i) + emu->SpellID[i] = eq->SpellID[i]; + + IN(Count); + IN(Pet); + IN(Initialise); + IN(Flags); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Buff) + { + DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Live); + SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Live); + + IN(entityid); + //IN(slot); + IN(level); + IN(effect); + IN(spellid); + IN(duration); + IN(slotid); + IN(bufffade); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_BuffRemoveRequest) + { + // This is to cater for the fact that short buff box buffs start at 30 as opposed to 25 in prior clients. + // + DECODE_LENGTH_EXACT(structs::BuffRemoveRequest_Struct); + SETUP_DIRECT_DECODE(BuffRemoveRequest_Struct, structs::BuffRemoveRequest_Struct); + + emu->SlotID = (eq->SlotID < 42) ? eq->SlotID : (eq->SlotID - 17); + + IN(EntityID); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_CastSpell) + { + DECODE_LENGTH_EXACT(structs::CastSpell_Struct); + SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); + + if (eq->slot == 13) + emu->slot = 10; + else + IN(slot); + + IN(spell_id); + emu->inventoryslot = RoF2ToServerSlot(eq->inventoryslot); + //IN(inventoryslot); + IN(target_id); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ChannelMessage) + { + unsigned char *__eq_buffer = __packet->pBuffer; + + char *InBuffer = (char *)__eq_buffer; + + char Sender[64]; + char Target[64]; + + VARSTRUCT_DECODE_STRING(Sender, InBuffer); + VARSTRUCT_DECODE_STRING(Target, InBuffer); + + InBuffer += 4; + + uint32 Language = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + uint32 Channel = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + + InBuffer += 5; + + uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + + __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; + + strn0cpy(emu->targetname, Target, sizeof(emu->targetname)); + strn0cpy(emu->sender, Target, sizeof(emu->sender)); + emu->language = Language; + emu->chan_num = Channel; + emu->skill_in_language = Skill; + strcpy(emu->message, InBuffer); + + 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); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ClientUpdate) + { + // for some odd reason, there is an extra byte on the end of this on occasion.. + DECODE_LENGTH_ATLEAST(structs::PlayerPositionUpdateClient_Struct); + SETUP_DIRECT_DECODE(PlayerPositionUpdateClient_Struct, structs::PlayerPositionUpdateClient_Struct); + + IN(spawn_id); + IN(sequence); + IN(x_pos); + IN(y_pos); + IN(z_pos); + IN(heading); + IN(delta_x); + IN(delta_y); + IN(delta_z); + IN(delta_heading); + IN(animation); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Consider) + { + DECODE_LENGTH_EXACT(structs::Consider_Struct); + SETUP_DIRECT_DECODE(Consider_Struct, structs::Consider_Struct); + + IN(playerid); + IN(targetid); + IN(faction); + IN(level); + //emu->cur_hp = 1; + //emu->max_hp = 2; + //emu->pvpcon = 0; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } + + DECODE(OP_Consume) + { + DECODE_LENGTH_EXACT(structs::Consume_Struct); + SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); + + emu->slot = RoF2ToServerSlot(eq->slot); + IN(auto_consumed); + IN(type); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Damage) + { + DECODE_LENGTH_EXACT(structs::CombatDamage_Struct); + SETUP_DIRECT_DECODE(CombatDamage_Struct, structs::CombatDamage_Struct); + + IN(target); + IN(source); + IN(type); + IN(spellid); + IN(damage); + emu->sequence = eq->sequence; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DeleteItem) + { + DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); + SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); + + emu->from_slot = RoF2ToServerSlot(eq->from_slot); + emu->to_slot = RoF2ToServerSlot(eq->to_slot); + IN(number_in_stack); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_EnvDamage) + { + DECODE_LENGTH_EXACT(structs::EnvDamage2_Struct); + SETUP_DIRECT_DECODE(EnvDamage2_Struct, structs::EnvDamage2_Struct); + + IN(id); + IN(damage); + IN(dmgtype); + emu->constant = 0xFFFF; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_FaceChange) + { + DECODE_LENGTH_EXACT(structs::FaceChange_Struct); + SETUP_DIRECT_DECODE(FaceChange_Struct, structs::FaceChange_Struct); + + IN(haircolor); + IN(beardcolor); + IN(eyecolor1); + IN(eyecolor2); + IN(hairstyle); + IN(beard); + IN(face); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_FindPersonRequest) + { + DECODE_LENGTH_EXACT(structs::FindPersonRequest_Struct); + SETUP_DIRECT_DECODE(FindPersonRequest_Struct, structs::FindPersonRequest_Struct); + + IN(npc_id); + IN(client_pos.x); + IN(client_pos.y); + IN(client_pos.z); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GMLastName) + { + DECODE_LENGTH_EXACT(structs::GMLastName_Struct); + SETUP_DIRECT_DECODE(GMLastName_Struct, structs::GMLastName_Struct); + + memcpy(emu->name, eq->name, sizeof(emu->name)); + memcpy(emu->gmname, eq->gmname, sizeof(emu->gmname)); + memcpy(emu->lastname, eq->lastname, sizeof(emu->lastname)); + for (int i = 0; i<4; i++) + { + emu->unknown[i] = eq->unknown[i]; + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupCancelInvite) + { + DECODE_LENGTH_EXACT(structs::GroupCancel_Struct); + SETUP_DIRECT_DECODE(GroupCancel_Struct, structs::GroupCancel_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + IN(toggle); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupDisband) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_Disband"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupGeneric_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupGeneric_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupFollow) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_GroupFollow"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupFollow_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupFollow2) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_GroupFollow2"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupFollow_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupFollow_Struct); + + memcpy(emu->name1, eq->name1, sizeof(emu->name1)); + memcpy(emu->name2, eq->name2, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupInvite) + { + //EQApplicationPacket *in = __packet; + //_log(NET__ERROR, "Received incoming OP_GroupInvite"); + //_hex(NET__ERROR, in->pBuffer, in->size); + DECODE_LENGTH_EXACT(structs::GroupInvite_Struct); + SETUP_DIRECT_DECODE(GroupGeneric_Struct, structs::GroupInvite_Struct); + + memcpy(emu->name1, eq->invitee_name, sizeof(emu->name1)); + memcpy(emu->name2, eq->inviter_name, sizeof(emu->name2)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GroupInvite2) + { + //_log(NET__ERROR, "Received incoming OP_GroupInvite2. Forwarding"); + DECODE_FORWARD(OP_GroupInvite); + } + + DECODE(OP_GuildDemote) + { + DECODE_LENGTH_EXACT(structs::GuildDemoteStruct); + SETUP_DIRECT_DECODE(GuildDemoteStruct, structs::GuildDemoteStruct); + + strn0cpy(emu->target, eq->target, sizeof(emu->target)); + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + // IN(rank); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GuildRemove) + { + DECODE_LENGTH_EXACT(structs::GuildCommand_Struct); + SETUP_DIRECT_DECODE(GuildCommand_Struct, structs::GuildCommand_Struct); + + strn0cpy(emu->othername, eq->othername, sizeof(emu->othername)); + strn0cpy(emu->myname, eq->myname, sizeof(emu->myname)); + IN(guildeqid); + IN(officer); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_GuildStatus) + { + DECODE_LENGTH_EXACT(structs::GuildStatus_Struct); + SETUP_DIRECT_DECODE(GuildStatus_Struct, structs::GuildStatus_Struct); + + memcpy(emu->Name, eq->Name, sizeof(emu->Name)); + + FINISH_DIRECT_DECODE(); + } + + /*DECODE(OP_InspectAnswer) + { + DECODE_LENGTH_EXACT(structs::InspectResponse_Struct); + SETUP_DIRECT_DECODE(InspectResponse_Struct, structs::InspectResponse_Struct); + + IN(TargetID); + IN(playerid); + + int r; + for (r = 0; r < 21; r++) { + strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r])); + } + // Swap last 2 slots for Arrow and Power Source + strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22])); + strn0cpy(emu->itemnames[21], eq->unknown_zero, sizeof(emu->itemnames[21])); + strn0cpy(emu->unknown_zero, eq->unknown_zero, sizeof(emu->unknown_zero)); + + int k; + for (k = 0; k < 21; k++) { + IN(itemicons[k]); + } + // Swap last 2 slots for Arrow and Power Source + emu->itemicons[22] = eq->itemicons[21]; + emu->itemicons[21] = eq->unknown_zero2; + emu->unknown_zero2 = eq->unknown_zero2; + strn0cpy(emu->text, eq->text, sizeof(emu->text)); + //emu->unknown1772 = 0; + + FINISH_DIRECT_DECODE(); + }*/ + + DECODE(OP_InspectRequest) + { + DECODE_LENGTH_EXACT(structs::Inspect_Struct); + SETUP_DIRECT_DECODE(Inspect_Struct, structs::Inspect_Struct); + + IN(TargetID); + IN(PlayerID); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ItemLinkClick) + { + DECODE_LENGTH_EXACT(structs::ItemViewRequest_Struct); + SETUP_DIRECT_DECODE(ItemViewRequest_Struct, structs::ItemViewRequest_Struct); + MEMSET_IN(ItemViewRequest_Struct); + + IN(item_id); + int r; + for (r = 0; r < 5; r++) { + IN(augments[r]); + } + // Max Augs is now 6, but no code to support that many yet + IN(link_hash); + IN(icon); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ItemVerifyRequest) + { + DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); + SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); + + emu->slot = RoF2ToServerSlot(eq->slot); + IN(target); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_LoadSpellSet) + { + DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); + SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); + + for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + { + if (eq->spell[i] == 0) + emu->spell[i] = 0xFFFFFFFF; + else + emu->spell[i] = eq->spell[i]; + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_LootItem) + { + DECODE_LENGTH_EXACT(structs::LootingItem_Struct); + SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); + + IN(lootee); + IN(looter); + emu->slot_id = RoF2ToServerCorpseSlot(eq->slot_id); + IN(auto_loot); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_MoveItem) + { + DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + + //_log(NET__ERROR, "Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); + _log(NET__ERROR, "MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); + emu->from_slot = RoF2ToServerSlot(eq->from_slot); + emu->to_slot = RoF2ToServerSlot(eq->to_slot); + IN(number_in_stack); + + _hex(NET__ERROR, eq, sizeof(structs::MoveItem_Struct)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_PetCommands) + { + DECODE_LENGTH_EXACT(structs::PetCommand_Struct); + SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); + + switch (eq->command) + { + case 0x00: + emu->command = 0x04; // Health + break; + case 0x01: + emu->command = 0x10; // Leader + break; + case 0x02: + emu->command = 0x07; // Attack + break; + case 0x04: + emu->command = 0x08; // Follow + break; + case 0x05: + emu->command = 0x05; // Guard + break; + case 0x06: + emu->command = 0x09; // Sit. Needs work. This appears to be a toggle between Sit/Stand now. + break; + case 0x0c: + emu->command = 0x0b; // Taunt + break; + case 0x0f: + emu->command = 0x0c; // Hold + break; + case 0x10: + emu->command = 0x1b; // Hold on + break; + case 0x11: + emu->command = 0x1c; // Hold off + break; + case 0x1c: + emu->command = 0x01; // Back + break; + case 0x1d: + emu->command = 0x02; // Leave/Go Away + break; + default: + emu->command = eq->command; + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RaidInvite) + { + DECODE_LENGTH_ATLEAST(structs::RaidGeneral_Struct); + + // This is a switch on the RaidGeneral action + switch (*(uint32 *)__packet->pBuffer) { + case 35: { // raidMOTD + // we don't have a nice macro for this + structs::RaidMOTD_Struct *__eq_buffer = (structs::RaidMOTD_Struct *)__packet->pBuffer; + __eq_buffer->motd[1023] = '\0'; + size_t motd_size = strlen(__eq_buffer->motd) + 1; + __packet->size = sizeof(RaidMOTD_Struct) + motd_size; + __packet->pBuffer = new unsigned char[__packet->size]; + RaidMOTD_Struct *emu = (RaidMOTD_Struct *)__packet->pBuffer; + structs::RaidMOTD_Struct *eq = (structs::RaidMOTD_Struct *)__eq_buffer; + strn0cpy(emu->general.player_name, eq->general.player_name, 64); + strn0cpy(emu->motd, eq->motd, motd_size); + IN(general.action); + IN(general.parameter); + FINISH_DIRECT_DECODE(); + break; + } + case 36: { // raidPlayerNote unhandled + break; + } + default: { + DECODE_LENGTH_EXACT(structs::RaidGeneral_Struct); + SETUP_DIRECT_DECODE(RaidGeneral_Struct, structs::RaidGeneral_Struct); + strn0cpy(emu->leader_name, eq->leader_name, 64); + strn0cpy(emu->player_name, eq->player_name, 64); + IN(action); + IN(parameter); + FINISH_DIRECT_DECODE(); + break; + } + } + } + + DECODE(OP_ReadBook) + { + DECODE_LENGTH_EXACT(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(type); + IN(invslot); + emu->window = (uint8)eq->window; + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RecipeAutoCombine) + { + DECODE_LENGTH_EXACT(structs::RecipeAutoCombine_Struct); + SETUP_DIRECT_DECODE(RecipeAutoCombine_Struct, structs::RecipeAutoCombine_Struct); + + IN(object_type); + IN(some_id); + emu->unknown1 = RoF2ToServerSlot(eq->container_slot); + IN(recipe_id); + IN(reply_code); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RemoveBlockedBuffs) { DECODE_FORWARD(OP_BlockedBuffs); } + + DECODE(OP_RezzAnswer) + { + DECODE_LENGTH_EXACT(structs::Resurrect_Struct); + SETUP_DIRECT_DECODE(Resurrect_Struct, structs::Resurrect_Struct); + + IN(zone_id); + IN(instance_id); + IN(y); + IN(x); + IN(z); + memcpy(emu->your_name, eq->your_name, sizeof(emu->your_name)); + memcpy(emu->rezzer_name, eq->rezzer_name, sizeof(emu->rezzer_name)); + IN(spellid); + memcpy(emu->corpse_name, eq->corpse_name, sizeof(emu->corpse_name)); + IN(action); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Save) + { + DECODE_LENGTH_EXACT(structs::Save_Struct); + SETUP_DIRECT_DECODE(Save_Struct, structs::Save_Struct); + + memcpy(emu->unknown00, eq->unknown00, sizeof(emu->unknown00)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_SetServerFilter) + { + DECODE_LENGTH_EXACT(structs::SetServerFilter_Struct); + SETUP_DIRECT_DECODE(SetServerFilter_Struct, structs::SetServerFilter_Struct); + + int r; + for (r = 0; r < 29; r++) { + // Size 40 in RoF2 + IN(filters[r]); + } + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ShopPlayerBuy) + { + DECODE_LENGTH_EXACT(structs::Merchant_Sell_Struct); + SETUP_DIRECT_DECODE(Merchant_Sell_Struct, structs::Merchant_Sell_Struct); + + IN(npcid); + IN(playerid); + IN(itemslot); + IN(quantity); + IN(price); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ShopPlayerSell) + { + DECODE_LENGTH_EXACT(structs::Merchant_Purchase_Struct); + SETUP_DIRECT_DECODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); + + IN(npcid); + emu->itemslot = RoF2ToServerMainInvSlot(eq->itemslot); + //IN(itemslot); + IN(quantity); + IN(price); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ShopRequest) + { + DECODE_LENGTH_EXACT(structs::Merchant_Click_Struct); + SETUP_DIRECT_DECODE(Merchant_Click_Struct, structs::Merchant_Click_Struct); + + IN(npcid); + IN(playerid); + IN(command); + IN(rate); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Trader) + { + uint32 psize = __packet->size; + if (psize == sizeof(structs::ClickTrader_Struct)) + { + DECODE_LENGTH_EXACT(structs::ClickTrader_Struct); + SETUP_DIRECT_DECODE(ClickTrader_Struct, structs::ClickTrader_Struct); + MEMSET_IN(ClickTrader_Struct); + + emu->Code = eq->Code; + // Live actually has 200 items now, but 80 is the most our internal struct supports + for (uint32 i = 0; i < 80; i++) + { + emu->SerialNumber[i] = 0; // eq->SerialNumber[i]; + emu->ItemCost[i] = eq->ItemCost[i]; + } + + FINISH_DIRECT_DECODE(); + } + else if (psize == sizeof(structs::Trader_ShowItems_Struct)) + { + DECODE_LENGTH_EXACT(structs::Trader_ShowItems_Struct); + SETUP_DIRECT_DECODE(Trader_ShowItems_Struct, structs::Trader_ShowItems_Struct); + MEMSET_IN(Trader_ShowItems_Struct); + + emu->Code = eq->Code; + emu->TraderID = eq->TraderID; + + FINISH_DIRECT_DECODE(); + } + else if (psize == sizeof(structs::TraderStatus_Struct)) + { + DECODE_LENGTH_EXACT(structs::TraderStatus_Struct); + SETUP_DIRECT_DECODE(TraderStatus_Struct, structs::TraderStatus_Struct); + MEMSET_IN(TraderStatus_Struct); + + emu->Code = eq->Code; + + FINISH_DIRECT_DECODE(); + } + } + + DECODE(OP_TraderBuy) + { + DECODE_LENGTH_EXACT(structs::TraderBuy_Struct); + SETUP_DIRECT_DECODE(TraderBuy_Struct, structs::TraderBuy_Struct); + MEMSET_IN(TraderBuy_Struct); + + IN(Action); + IN(Price); + IN(TraderID); + memcpy(emu->ItemName, eq->ItemName, sizeof(emu->ItemName)); + IN(ItemID); + IN(Quantity); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TradeSkillCombine) + { + DECODE_LENGTH_EXACT(structs::NewCombine_Struct); + SETUP_DIRECT_DECODE(NewCombine_Struct, structs::NewCombine_Struct); + + int16 slot_id = RoF2ToServerSlot(eq->container_slot); + if (slot_id == 4000) { + slot_id = legacy::SLOT_TRADESKILL; // 1000 + } + emu->container_slot = slot_id; + emu->guildtribute_slot = RoF2ToServerSlot(eq->guildtribute_slot); // this should only return INVALID_INDEX until implemented -U + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TributeItem) + { + DECODE_LENGTH_EXACT(structs::TributeItem_Struct); + SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); + + emu->slot = RoF2ToServerSlot(eq->slot); + IN(quantity); + IN(tribute_master_id); + IN(tribute_points); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_WhoAllRequest) + { + DECODE_LENGTH_EXACT(structs::Who_All_Struct); + SETUP_DIRECT_DECODE(Who_All_Struct, structs::Who_All_Struct); + + memcpy(emu->whom, eq->whom, sizeof(emu->whom)); + IN(wrace); + IN(wclass); + IN(lvllow); + IN(lvlhigh); + IN(gmlookup); + IN(guildid); + IN(type); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ZoneChange) + { + DECODE_LENGTH_EXACT(structs::ZoneChange_Struct); + SETUP_DIRECT_DECODE(ZoneChange_Struct, structs::ZoneChange_Struct); + + memcpy(emu->char_name, eq->char_name, sizeof(emu->char_name)); + IN(zoneID); + IN(instanceID); + IN(y); + IN(x); + IN(z) + IN(zone_reason); + IN(success); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ZoneEntry) + { + DECODE_LENGTH_EXACT(structs::ClientZoneEntry_Struct); + SETUP_DIRECT_DECODE(ClientZoneEntry_Struct, structs::ClientZoneEntry_Struct); + + memcpy(emu->char_name, eq->char_name, sizeof(emu->char_name)); + + FINISH_DIRECT_DECODE(); + } + +// file scope helper methods + uint32 NextItemInstSerialNumber = 1; + uint32 MaxInstances = 2000000000; + + static inline int32 GetNextItemInstSerialNumber() + { + if (NextItemInstSerialNumber >= MaxInstances) + NextItemInstSerialNumber = 1; + else + NextItemInstSerialNumber++; + + return NextItemInstSerialNumber; + } + + char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) + { + int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); + uint8 null_term = 0; + bool stackable = inst->IsStackable(); + uint32 merchant_slot = inst->GetMerchantSlot(); + uint32 charges = inst->GetCharges(); + if (!stackable && charges > 254) + charges = 0xFFFFFFFF; + + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + + const Item_Struct *item = inst->GetUnscaledItem(); + //_log(NET__ERROR, "Serialize called for: %s", item->Name); + + RoF2::structs::ItemSerializationHeader hdr; + + //sprintf(hdr.unknown000, "06e0002Y1W00"); + + snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%012d", item->ID); + + hdr.stacksize = stackable ? charges : 1; + hdr.unknown004 = 0; + + structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in); + + hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? + hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; + hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; + hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; + //hdr.unknown013 = 0xffff; + hdr.price = inst->GetPrice(); + hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); + //hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff; + hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; + hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + hdr.unknown028 = 0; + hdr.last_cast_time = ((item->RecastDelay > 1) ? 1212693140 : 0); + hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); + hdr.inst_nodrop = inst->IsInstNoDrop() ? 1 : 0; + hdr.unknown044 = 0; + hdr.unknown048 = 0; + hdr.unknown052 = 0; + hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; + ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); + + if (item->EvolvingLevel > 0) { + RoF2::structs::EvolvingItem evotop; + evotop.unknown001 = 0; + evotop.unknown002 = 0; + evotop.unknown003 = 0; + evotop.unknown004 = 0; + evotop.evoLevel = item->EvolvingLevel; + evotop.progress = 95.512; + evotop.Activated = 1; + evotop.evomaxlevel = 7; + ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); + } + //ORNAMENT IDFILE / ICON + uint16 ornaIcon = 0; + if (inst->GetOrnamentationAug(ornamentationAugtype)) { + const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); + //Mainhand + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Offhand + ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Icon + ornaIcon = aug_weap->Icon; + } + else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { + char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); + //Mainhand + ss.write(tmp, strlen(tmp)); + ss.write((const char*)&null_term, sizeof(uint8)); + //Offhand + ss.write(tmp, strlen(tmp)); + ss.write((const char*)&null_term, sizeof(uint8)); + ornaIcon = inst->GetOrnamentationIcon(); + } + else { + ss.write((const char*)&null_term, sizeof(uint8)); //no mh + ss.write((const char*)&null_term, sizeof(uint8));//no of + } + + RoF2::structs::ItemSerializationHeaderFinish hdrf; + hdrf.ornamentIcon = ornaIcon; + hdrf.unknown061 = 0; + hdrf.unknown062 = 0; + hdrf.unknowna1 = 0xffffffff; + hdrf.unknowna2 = 0; + hdrf.unknown063 = 0; + hdrf.unknowna3 = 0; + hdrf.unknowna4 = 0xffffffff; + hdrf.unknowna5 = 0; + hdrf.ItemClass = item->ItemClass; + ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); + + if (strlen(item->Name) > 0) + { + ss.write(item->Name, strlen(item->Name)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + if (strlen(item->Lore) > 0) + { + ss.write(item->Lore, strlen(item->Lore)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + if (strlen(item->IDFile) > 0) + { + ss.write(item->IDFile, strlen(item->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + ss.write((const char*)&null_term, sizeof(uint8)); + //_log(NET__ERROR, "ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct)); + RoF2::structs::ItemBodyStruct ibs; + memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); + + ibs.id = item->ID; + ibs.weight = item->Weight; + ibs.norent = item->NoRent; + ibs.nodrop = item->NoDrop; + ibs.attune = item->Attuneable; + ibs.size = item->Size; + ibs.slots = SwapBits21and22(item->Slots); + ibs.price = item->Price; + ibs.icon = item->Icon; + ibs.unknown1 = 1; + ibs.unknown2 = 1; + ibs.BenefitFlag = item->BenefitFlag; + ibs.tradeskills = item->Tradeskills; + ibs.CR = item->CR; + ibs.DR = item->DR; + ibs.PR = item->PR; + ibs.MR = item->MR; + ibs.FR = item->FR; + ibs.SVCorruption = item->SVCorruption; + ibs.AStr = item->AStr; + ibs.ASta = item->ASta; + ibs.AAgi = item->AAgi; + ibs.ADex = item->ADex; + ibs.ACha = item->ACha; + ibs.AInt = item->AInt; + ibs.AWis = item->AWis; + + ibs.HP = item->HP; + ibs.Mana = item->Mana; + ibs.Endur = item->Endur; + ibs.AC = item->AC; + ibs.regen = item->Regen; + ibs.mana_regen = item->ManaRegen; + ibs.end_regen = item->EnduranceRegen; + ibs.Classes = item->Classes; + ibs.Races = item->Races; + ibs.Deity = item->Deity; + ibs.SkillModValue = item->SkillModValue; + ibs.SkillModMax = 0xffffffff; + ibs.SkillModType = (int8)(item->SkillModType); + ibs.SkillModExtra = 0; + ibs.BaneDmgRace = item->BaneDmgRace; + ibs.BaneDmgBody = item->BaneDmgBody; + ibs.BaneDmgRaceAmt = item->BaneDmgRaceAmt; + ibs.BaneDmgAmt = item->BaneDmgAmt; + ibs.Magic = item->Magic; + ibs.CastTime_ = item->CastTime_; + ibs.ReqLevel = item->ReqLevel; + if (item->ReqLevel > 100) + ibs.ReqLevel = 100; + ibs.RecLevel = item->RecLevel; + if (item->RecLevel > 100) + ibs.RecLevel = 100; + ibs.RecSkill = item->RecSkill; + ibs.BardType = item->BardType; + ibs.BardValue = item->BardValue; + ibs.Light = item->Light; + ibs.Delay = item->Delay; + ibs.ElemDmgType = item->ElemDmgType; + ibs.ElemDmgAmt = item->ElemDmgAmt; + ibs.Range = item->Range; + ibs.Damage = item->Damage; + ibs.Color = item->Color; + ibs.Prestige = 0; + ibs.ItemType = item->ItemType; + ibs.Material = item->Material; + ibs.unknown7 = 0; + ibs.EliteMaterial = item->EliteMaterial; + ibs.unknown_RoF23 = 0; + ibs.unknown_RoF24 = 0; + ibs.SellRate = item->SellRate; + ibs.CombatEffects = item->CombatEffects; + ibs.Shielding = item->Shielding; + ibs.StunResist = item->StunResist; + ibs.StrikeThrough = item->StrikeThrough; + ibs.ExtraDmgSkill = item->ExtraDmgSkill; + ibs.ExtraDmgAmt = item->ExtraDmgAmt; + ibs.SpellShield = item->SpellShield; + ibs.Avoidance = item->Avoidance; + ibs.Accuracy = item->Accuracy; + ibs.CharmFileID = item->CharmFileID; + ibs.FactionAmt1 = item->FactionAmt1; + ibs.FactionMod1 = item->FactionMod1; + ibs.FactionAmt2 = item->FactionAmt2; + ibs.FactionMod2 = item->FactionMod2; + ibs.FactionAmt3 = item->FactionAmt3; + ibs.FactionMod3 = item->FactionMod3; + ibs.FactionAmt4 = item->FactionAmt4; + ibs.FactionMod4 = item->FactionMod4; + + ss.write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); + + //charm text + if (strlen(item->CharmFile) > 0) + { + ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + //_log(NET__ERROR, "ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + RoF2::structs::ItemSecondaryBodyStruct isbs; + memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + + isbs.augtype = item->AugType; + isbs.augdistiller = 65535; + isbs.augrestrict = item->AugRestrict; + + for (int x = AUG_BEGIN; x < EmuConstants::ITEM_COMMON_SIZE; ++x) + { + isbs.augslots[x].type = item->AugSlotType[x]; + isbs.augslots[x].visible = item->AugSlotVisible[x]; + isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + } + + // Increased to 6 max aug slots + isbs.augslots[5].type = 0; + isbs.augslots[5].visible = 1; + isbs.augslots[5].unknown = 0; + + isbs.ldonpoint_type = item->PointType; + isbs.ldontheme = item->LDoNTheme; + isbs.ldonprice = item->LDoNPrice; + isbs.ldonsellbackrate = item->LDoNSellBackRate; + isbs.ldonsold = item->LDoNSold; + + isbs.bagtype = item->BagType; + isbs.bagslots = item->BagSlots; + isbs.bagsize = item->BagSize; + isbs.wreduction = item->BagWR; + + isbs.book = item->Book; + isbs.booktype = item->BookType; + + ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + + if (strlen(item->Filename) > 0) + { + ss.write((const char*)item->Filename, strlen(item->Filename)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + //_log(NET__ERROR, "ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + RoF2::structs::ItemTertiaryBodyStruct itbs; + memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + + itbs.loregroup = item->LoreGroup; + itbs.artifact = item->ArtifactFlag; + itbs.summonedflag = item->SummonedFlag; + itbs.favor = item->Favor; + itbs.fvnodrop = item->FVNoDrop; + itbs.dotshield = item->DotShielding; + itbs.atk = item->Attack; + itbs.haste = item->Haste; + itbs.damage_shield = item->DamageShield; + itbs.guildfavor = item->GuildFavor; + itbs.augdistil = item->AugDistiller; + itbs.unknown3 = 0xffffffff; + itbs.unknown4 = 0; + itbs.no_pet = item->NoPet; + itbs.unknown5 = 0; + + itbs.potion_belt_enabled = item->PotionBelt; + itbs.potion_belt_slots = item->PotionBeltSlots; + itbs.stacksize = stackable ? item->StackSize : 0; + itbs.no_transfer = item->NoTransfer; + itbs.expendablearrow = item->ExpendableArrow; + + itbs.unknown8 = 0; + itbs.unknown9 = 0; + itbs.unknown10 = 0; + itbs.unknown11 = 0; + itbs.unknown12 = 0; + itbs.unknown13 = 0; + itbs.unknown14 = 0; + + ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + + // Effect Structures Broken down to allow variable length strings for effect names + int32 effect_unknown = 0; + + //_log(NET__ERROR, "ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); + RoF2::structs::ClickEffectStruct ices; + memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); + + ices.effect = item->Click.Effect; + ices.level2 = item->Click.Level2; + ices.type = item->Click.Type; + ices.level = item->Click.Level; + ices.max_charges = item->MaxCharges; + ices.cast_time = item->CastTime; + ices.recast = item->RecastDelay; + ices.recast_type = item->RecastType; + + ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); + + if (strlen(item->ClickName) > 0) + { + ss.write((const char*)item->ClickName, strlen(item->ClickName)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + + //_log(NET__ERROR, "ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); + RoF2::structs::ProcEffectStruct ipes; + memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); + + ipes.effect = item->Proc.Effect; + ipes.level2 = item->Proc.Level2; + ipes.type = item->Proc.Type; + ipes.level = item->Proc.Level; + ipes.procrate = item->ProcRate; + + ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); + + if (strlen(item->ProcName) > 0) + { + ss.write((const char*)item->ProcName, strlen(item->ProcName)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + + //_log(NET__ERROR, "ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); + RoF2::structs::WornEffectStruct iwes; + memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); + + iwes.effect = item->Worn.Effect; + iwes.level2 = item->Worn.Level2; + iwes.type = item->Worn.Type; + iwes.level = item->Worn.Level; + + ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); + + if (strlen(item->WornName) > 0) + { + ss.write((const char*)item->WornName, strlen(item->WornName)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + RoF2::structs::WornEffectStruct ifes; + memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); + + ifes.effect = item->Focus.Effect; + ifes.level2 = item->Focus.Level2; + ifes.type = item->Focus.Type; + ifes.level = item->Focus.Level; + + ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); + + if (strlen(item->FocusName) > 0) + { + ss.write((const char*)item->FocusName, strlen(item->FocusName)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + RoF2::structs::WornEffectStruct ises; + memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); + + ises.effect = item->Scroll.Effect; + ises.level2 = item->Scroll.Level2; + ises.type = item->Scroll.Type; + ises.level = item->Scroll.Level; + + ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); + + if (strlen(item->ScrollName) > 0) + { + ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); + } + + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + // Bard Effect? + RoF2::structs::WornEffectStruct ibes; + memset(&ibes, 0, sizeof(RoF2::structs::WornEffectStruct)); + + ibes.effect = 0xffffffff; + ibes.level2 = 0; + ibes.type = 0; + ibes.level = 0; + //ibes.unknown6 = 0xffffffff; + + ss.write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); + + /* + if(strlen(item->BardName) > 0) + { + ss.write((const char*)item->BardName, strlen(item->BardName)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else */ + ss.write((const char*)&null_term, sizeof(uint8)); + + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // End of Effects + + //_log(NET__ERROR, "ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + RoF2::structs::ItemQuaternaryBodyStruct iqbs; + memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + + iqbs.scriptfileid = item->ScriptFileID; + iqbs.quest_item = item->QuestItemFlag; + iqbs.Power = 0; + iqbs.Purity = item->Purity; + iqbs.unknown16 = 0; + iqbs.BackstabDmg = item->BackstabDmg; + iqbs.DSMitigation = item->DSMitigation; + iqbs.HeroicStr = item->HeroicStr; + iqbs.HeroicInt = item->HeroicInt; + iqbs.HeroicWis = item->HeroicWis; + iqbs.HeroicAgi = item->HeroicAgi; + iqbs.HeroicDex = item->HeroicDex; + iqbs.HeroicSta = item->HeroicSta; + iqbs.HeroicCha = item->HeroicCha; + iqbs.HeroicMR = item->HeroicMR; + iqbs.HeroicFR = item->HeroicFR; + iqbs.HeroicCR = item->HeroicCR; + iqbs.HeroicDR = item->HeroicDR; + iqbs.HeroicPR = item->HeroicPR; + iqbs.HeroicSVCorrup = item->HeroicSVCorrup; + iqbs.HealAmt = item->HealAmt; + iqbs.SpellDmg = item->SpellDmg; + iqbs.clairvoyance = item->Clairvoyance; + iqbs.unknown28 = 0; + + + // Begin RoF2 Test + iqbs.unknown_TEST1 = 0; + // End RoF2 Test + + iqbs.unknown30 = 0; + iqbs.unknown39 = 1; + + iqbs.subitem_count = 0; + + char *SubSerializations[10]; // + + uint32 SubLengths[10]; + + for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + + SubSerializations[x] = nullptr; + + const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); + + if (subitem) { + + int SubSlotNumber; + + iqbs.subitem_count++; + + if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); + SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); + else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); + SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); + else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); + SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + else + SubSlotNumber = slot_id_in; // ??????? + + /* + // TEST CODE: + SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + */ + + SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); + } + } + + ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + + for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + + if (SubSerializations[x]) { + + ss.write((const char*)&x, sizeof(uint32)); + + ss.write(SubSerializations[x], SubLengths[x]); + + safe_delete_array(SubSerializations[x]); + } + } + + char* item_serial = new char[ss.tellp()]; + memset(item_serial, 0, ss.tellp()); + memcpy(item_serial, ss.str().c_str(), ss.tellp()); + + *length = ss.tellp(); + return item_serial; + } + + static inline structs::ItemSlotStruct ServerToRoF2Slot(uint32 ServerSlot) + { + structs::ItemSlotStruct RoF2Slot; + RoF2Slot.SlotType = INVALID_INDEX; + RoF2Slot.Unknown02 = NOT_USED; + RoF2Slot.MainSlot = INVALID_INDEX; + RoF2Slot.SubSlot = INVALID_INDEX; + RoF2Slot.AugSlot = INVALID_INDEX; + RoF2Slot.Unknown01 = NOT_USED; + + uint32 TempSlot = 0; + + if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // Main Inventory and Cursor + RoF2Slot.SlotType = maps::MapPossessions; + RoF2Slot.MainSlot = ServerSlot; + + if (ServerSlot == MainPowerSource) + RoF2Slot.MainSlot = slots::MainPowerSource; + + else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + RoF2Slot.MainSlot += 3; + + else if (ServerSlot >= MainAmmo) // (> 20) + RoF2Slot.MainSlot += 1; + } + + /*else if (ServerSlot < 51) { // Cursor Buffer + RoF2Slot.SlotType = maps::MapLimbo; + RoF2Slot.MainSlot = ServerSlot - 31; + }*/ + + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { // (> 250 && < 341) + RoF2Slot.SlotType = maps::MapPossessions; + TempSlot = ServerSlot - 1; + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + + if (RoF2Slot.MainSlot >= slots::MainGeneral9) // (> 30) + RoF2Slot.MainSlot = slots::MainCursor; + } + + else if (ServerSlot >= EmuConstants::TRIBUTE_BEGIN && ServerSlot <= EmuConstants::TRIBUTE_END) { // Tribute + RoF2Slot.SlotType = maps::MapTribute; + RoF2Slot.MainSlot = ServerSlot - EmuConstants::TRIBUTE_BEGIN; + } + + else if (ServerSlot >= EmuConstants::BANK_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) { + RoF2Slot.SlotType = maps::MapBank; + TempSlot = ServerSlot - EmuConstants::BANK_BEGIN; + RoF2Slot.MainSlot = TempSlot; + + if (TempSlot > 30) { // (> 30) + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } + } + + else if (ServerSlot >= EmuConstants::SHARED_BANK_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) { + RoF2Slot.SlotType = maps::MapSharedBank; + TempSlot = ServerSlot - EmuConstants::SHARED_BANK_BEGIN; + RoF2Slot.MainSlot = TempSlot; + + if (TempSlot > 30) { // (> 30) + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } + } + + else if (ServerSlot >= EmuConstants::TRADE_BEGIN && ServerSlot <= EmuConstants::TRADE_BAGS_END) { + RoF2Slot.SlotType = maps::MapTrade; + TempSlot = ServerSlot - EmuConstants::TRADE_BEGIN; + RoF2Slot.MainSlot = TempSlot; + + if (TempSlot > 30) { + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } + + /* + // OLD CODE: + if (TempSlot > 99) { + if (TempSlot > 100) + RoF2Slot.MainSlot = int((TempSlot - 100) / 10); + + else + RoF2Slot.MainSlot = 0; + + RoF2Slot.SubSlot = TempSlot - (100 + RoF2Slot.MainSlot); + } + */ + } + + else if (ServerSlot >= EmuConstants::WORLD_BEGIN && ServerSlot <= EmuConstants::WORLD_END) { + RoF2Slot.SlotType = maps::MapWorld; + TempSlot = ServerSlot - EmuConstants::WORLD_BEGIN; + RoF2Slot.MainSlot = TempSlot; + } + + _log(NET__ERROR, "Convert Server Slot %i to RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", ServerSlot, RoF2Slot.SlotType, RoF2Slot.Unknown02, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01); + + return RoF2Slot; + } + + static inline structs::MainInvItemSlotStruct ServerToRoF2MainInvSlot(uint32 ServerSlot) + { + structs::MainInvItemSlotStruct RoF2Slot; + RoF2Slot.MainSlot = INVALID_INDEX; + RoF2Slot.SubSlot = INVALID_INDEX; + RoF2Slot.AugSlot = INVALID_INDEX; + RoF2Slot.Unknown01 = NOT_USED; + + uint32 TempSlot = 0; + + if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // (< 52) + RoF2Slot.MainSlot = ServerSlot; + + if (ServerSlot == MainPowerSource) + RoF2Slot.MainSlot = slots::MainPowerSource; + + else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + RoF2Slot.MainSlot += 3; + + else if (ServerSlot >= MainAmmo) // Ammo and Personl Inventory + RoF2Slot.MainSlot += 1; + + /*else if (ServerSlot >= MainCursor) { // Cursor + RoF2Slot.MainSlot = slots::MainCursor; + + if (ServerSlot > 30) + RoF2Slot.SubSlot = (ServerSlot + 3) - 33; + }*/ + } + + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { + TempSlot = ServerSlot - 1; + RoF2Slot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; + RoF2Slot.SubSlot = TempSlot - ((RoF2Slot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + } + + _log(NET__ERROR, "Convert Server Slot %i to RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i", ServerSlot, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01); + + return RoF2Slot; + } + + static inline uint32 ServerToRoF2CorpseSlot(uint32 ServerCorpse) + { + //uint32 RoF2Corpse; + return (ServerCorpse + 1); + } + + static inline uint32 RoF2ToServerSlot(structs::ItemSlotStruct RoF2Slot) + { + uint32 ServerSlot = INVALID_INDEX; + uint32 TempSlot = 0; + + if (RoF2Slot.SlotType == maps::MapPossessions && RoF2Slot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 51) + if (RoF2Slot.MainSlot == slots::MainPowerSource) + TempSlot = MainPowerSource; + + else if (RoF2Slot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory + TempSlot = RoF2Slot.MainSlot - 3; + + /*else if (RoF2Slot.MainSlot == slots::MainGeneral9 || RoF2Slot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF2 inventory/corpse slots + // Need to figure out what to do when we get these + + // The slot range of 0 - client_max is cross-utilized between player inventory and corpse inventory. + // In the case of RoF2, player inventory is addressed as 0 - 33 and corpse inventory is addressed as 23 - 56. + // We 'could' assign the two new inventory slots as 9997 and 9998, and then work around their bag + // slot assignments, but doing so may disrupt our ability to utilize the corpse looting range properly. + + // For now, it's probably best to leave as-is and let this work itself out in the inventory rework. + }*/ + + else if (RoF2Slot.MainSlot >= slots::MainAmmo) // Ammo and Main Inventory + TempSlot = RoF2Slot.MainSlot - 1; + + else // Worn Slots + TempSlot = RoF2Slot.MainSlot; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapBank) { + TempSlot = EmuConstants::BANK_BEGIN; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + else + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapSharedBank) { + TempSlot = EmuConstants::SHARED_BANK_BEGIN; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + else + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapTrade) { + TempSlot = EmuConstants::TRADE_BEGIN; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoF2Slot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + // OLD CODE: + //TempSlot += 100 + (RoF2Slot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot; + + else + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoF2Slot.SlotType == maps::MapWorld) { + TempSlot = EmuConstants::WORLD_BEGIN; + + if (RoF2Slot.MainSlot >= SUB_BEGIN) + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + } + + /*else if (RoF2Slot.SlotType == maps::MapLimbo) { // Cursor Buffer + TempSlot = 31; + + if (RoF2Slot.MainSlot >= 0) + TempSlot += RoF2Slot.MainSlot; + + ServerSlot = TempSlot; + }*/ + + else if (RoF2Slot.SlotType == maps::MapGuildTribute) { + ServerSlot = INVALID_INDEX; + } + + _log(NET__ERROR, "Convert RoF2 Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoF2Slot.SlotType, RoF2Slot.Unknown02, RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01, ServerSlot); + + return ServerSlot; + } + + static inline uint32 RoF2ToServerMainInvSlot(structs::MainInvItemSlotStruct RoF2Slot) + { + uint32 ServerSlot = INVALID_INDEX; + uint32 TempSlot = 0; + + if (RoF2Slot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 33) + if (RoF2Slot.MainSlot == slots::MainPowerSource) + TempSlot = MainPowerSource; + + else if (RoF2Slot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory + TempSlot = RoF2Slot.MainSlot - 3; + + /*else if (RoF2Slot.MainSlot == slots::MainGeneral9 || RoF2Slot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF2 inventory slots + // Need to figure out what to do when we get these + + // Same as above + }*/ + + else if (RoF2Slot.MainSlot >= slots::MainAmmo) // Main Inventory and Ammo Slots + TempSlot = RoF2Slot.MainSlot - 1; + + else + TempSlot = RoF2Slot.MainSlot; + + if (RoF2Slot.SubSlot >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoF2Slot.SubSlot + 1; + + ServerSlot = TempSlot; + } + + _log(NET__ERROR, "Convert RoF2 Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoF2Slot.MainSlot, RoF2Slot.SubSlot, RoF2Slot.AugSlot, RoF2Slot.Unknown01, ServerSlot); + + return ServerSlot; + } + + static inline uint32 RoF2ToServerCorpseSlot(uint32 RoF2Corpse) + { + //uint32 ServerCorpse; + return (RoF2Corpse - 1); + } +} +// end namespace RoF2 diff --git a/common/patches/rof2.h b/common/patches/rof2.h new file mode 100644 index 000000000..b39849048 --- /dev/null +++ b/common/patches/rof2.h @@ -0,0 +1,37 @@ +#ifndef RoF2_H_ +#define RoF2_H_ + +#include "../struct_strategy.h" + +class EQStreamIdentifier; + +namespace RoF2 { + + //these are the only public member of this namespace. + extern void Register(EQStreamIdentifier &into); + extern void Reload(); + + + + //you should not directly access anything below.. + //I just dont feel like making a seperate header for it. + + class Strategy : public StructStrategy { + public: + Strategy(); + + protected: + + virtual std::string Describe() const; + virtual const EQClientVersion ClientVersion() const; + + //magic macro to declare our opcode processors + #include "ss_declare.h" + #include "rof2_ops.h" + }; + +}; + + + +#endif /*RoF2_H_*/ diff --git a/common/patches/rof2_constants.h b/common/patches/rof2_constants.h new file mode 100644 index 000000000..1f8ff1a52 --- /dev/null +++ b/common/patches/rof2_constants.h @@ -0,0 +1,216 @@ +/* +EQEMu: Everquest Server Emulator + +Copyright (C) 2001-2014 EQEMu Development Team (http://eqemulator.net) + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY except by those people which sell it, which +are required to give you total support for your newly bought product; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#ifndef RoF2_CONSTANTS_H_ +#define RoF2_CONSTANTS_H_ + +#include "../types.h" + +namespace RoF2 { + namespace maps { + typedef enum : int16 { + MapPossessions = 0, + MapBank, + MapSharedBank, + MapTrade, + MapWorld, + MapLimbo, + MapTribute, + MapTrophyTribute, + MapGuildTribute, + MapMerchant, + MapDeleted, + MapCorpse, + MapBazaar, + MapInspect, + MapRealEstate, + MapViewMODPC, + MapViewMODBank, + MapViewMODSharedBank, + MapViewMODLimbo, + MapAltStorage, + MapArchived, + MapMail, + MapGuildTrophyTribute, + MapOther, + _MapCount + } InventoryMaps; + } + + namespace slots { + typedef enum : int16 { + MainCharm = 0, + MainEar1, + MainHead, + MainFace, + MainEar2, + MainNeck, + MainShoulders, + MainArms, + MainBack, + MainWrist1, + MainWrist2, + MainRange, + MainHands, + MainPrimary, + MainSecondary, + MainFinger1, + MainFinger2, + MainChest, + MainLegs, + MainFeet, + MainWaist, + MainPowerSource, + MainAmmo, + MainGeneral1, + MainGeneral2, + MainGeneral3, + MainGeneral4, + MainGeneral5, + MainGeneral6, + MainGeneral7, + MainGeneral8, + MainGeneral9, + MainGeneral10, + MainCursor, + _MainCount, + _MainEquipmentBegin = MainCharm, + _MainEquipmentEnd = MainAmmo, + _MainEquipmentCount = (_MainEquipmentEnd - _MainEquipmentBegin + 1), + _MainGeneralBegin = MainGeneral1, + _MainGeneralEnd = MainGeneral10, + _MainGeneralCount = (_MainGeneralEnd - _MainGeneralBegin + 1) + } EquipmentSlots; + } + + namespace consts { + static const uint16 MAP_POSSESSIONS_SIZE = slots::_MainCount; + static const uint16 MAP_BANK_SIZE = 24; + static const uint16 MAP_SHARED_BANK_SIZE = 2; + static const uint16 MAP_TRADE_SIZE = 8; + static const uint16 MAP_WORLD_SIZE = 10; + static const uint16 MAP_LIMBO_SIZE = 36; + static const uint16 MAP_TRIBUTE_SIZE = 0; //? + static const uint16 MAP_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 MAP_GUILD_TRIBUTE_SIZE = 0; + static const uint16 MAP_MERCHANT_SIZE = 0; + static const uint16 MAP_DELETED_SIZE = 0; + static const uint16 MAP_CORPSE_SIZE = slots::_MainCount; + static const uint16 MAP_BAZAAR_SIZE = 200; + static const uint16 MAP_INSPECT_SIZE = slots::_MainEquipmentCount; + static const uint16 MAP_REAL_ESTATE_SIZE = 0; + static const uint16 MAP_VIEW_MOD_PC_SIZE = MAP_POSSESSIONS_SIZE; + static const uint16 MAP_VIEW_MOD_BANK_SIZE = MAP_BANK_SIZE; + static const uint16 MAP_VIEW_MOD_SHARED_BANK_SIZE = MAP_SHARED_BANK_SIZE; + static const uint16 MAP_VIEW_MOD_LIMBO_SIZE = MAP_LIMBO_SIZE; + static const uint16 MAP_ALT_STORAGE_SIZE = 0; + static const uint16 MAP_ARCHIVED_SIZE = 0; + static const uint16 MAP_MAIL_SIZE = 0; + static const uint16 MAP_GUILD_TROPHY_TRIBUTE_SIZE = 0; + static const uint16 MAP_KRONO_SIZE = NOT_USED; + static const uint16 MAP_OTHER_SIZE = 0; + + // most of these definitions will go away with the structure-based system..this maintains compatibility for now + // (bag slots and main slots beyond Possessions are assigned for compatibility with current server coding) + static const int16 EQUIPMENT_BEGIN = slots::MainCharm; + static const int16 EQUIPMENT_END = slots::MainAmmo; + static const uint16 EQUIPMENT_SIZE = slots::_MainEquipmentCount; + + static const int16 GENERAL_BEGIN = slots::MainGeneral1; + static const int16 GENERAL_END = slots::MainGeneral10; + static const uint16 GENERAL_SIZE = slots::_MainGeneralCount; + static const int16 GENERAL_BAGS_BEGIN = 251; + static const int16 GENERAL_BAGS_END_OFFSET = 99; + static const int16 GENERAL_BAGS_END = GENERAL_BAGS_BEGIN + GENERAL_BAGS_END_OFFSET; + + static const int16 CURSOR = slots::MainCursor; + static const int16 CURSOR_BAG_BEGIN = 351; + static const int16 CURSOR_BAG_END_OFFSET = 9; + static const int16 CURSOR_BAG_END = CURSOR_BAG_BEGIN + CURSOR_BAG_END_OFFSET; + + static const int16 BANK_BEGIN = 2000; + static const int16 BANK_END = 2023; + static const int16 BANK_BAGS_BEGIN = 2031; + static const int16 BANK_BAGS_END_OFFSET = 239; + static const int16 BANK_BAGS_END = BANK_BAGS_BEGIN + BANK_BAGS_END_OFFSET; + + static const int16 SHARED_BANK_BEGIN = 2500; + static const int16 SHARED_BANK_END = 2501; + static const int16 SHARED_BANK_BAGS_BEGIN = 2531; + static const int16 SHARED_BANK_BAGS_END_OFFSET = 19; + static const int16 SHARED_BANK_BAGS_END = SHARED_BANK_BAGS_BEGIN + SHARED_BANK_BAGS_END_OFFSET; + + static const int16 TRADE_BEGIN = 3000; + static const int16 TRADE_END = 3007; + static const int16 TRADE_NPC_END = 3003; + static const int16 TRADE_BAGS_BEGIN = 3031; + static const int16 TRADE_BAGS_END_OFFSET = 79; + static const int16 TRADE_BAGS_END = TRADE_BAGS_BEGIN + TRADE_BAGS_END_OFFSET; + + static const int16 WORLD_BEGIN = 4000; + static const int16 WORLD_END = 4009; + + static const int16 TRIBUTE_BEGIN = 400; + static const int16 TRIBUTE_END = 404; + + static const int16 CORPSE_BEGIN = slots::MainGeneral1; + static const int16 CORPSE_END = slots::MainGeneral1 + slots::MainCursor; + + static const uint16 ITEM_COMMON_SIZE = 6; + static const uint16 ITEM_CONTAINER_SIZE = 255; // 255; (server max will be 255..unsure what actual client is - test) + + static const uint32 BANDOLIERS_COUNT = 20; // count = number of bandolier instances + static const uint32 BANDOLIER_SIZE = 4; // size = number of equipment slots in bandolier instance + static const uint32 POTION_BELT_SIZE = 5; + } + + namespace limits { + static const bool ALLOWS_EMPTY_BAG_IN_BAG = true; + static const bool ALLOWS_CLICK_CAST_FROM_BAG = true; + static const bool COIN_HAS_WEIGHT = false; + } + +}; //end namespace RoF2 + +#endif /*RoF2_CONSTANTS_H_*/ + +/* +RoF2 Notes: + ** Structure-based inventory ** +ok Possessions: ( 0, { 0 .. 33 }, -1, -1 ) (Corpse: { 23 .. 56 } [Offset 23]) +ok [Equipment: ( 0, { 0 .. 22 }, -1, -1 )] +ok [General: ( 0, { 23 .. 32 }, -1, -1 )] +ok [Cursor: ( 0, 33, -1, -1 )] + General Bags: ( 0, { 23 .. 32 }, { 0 .. (maxsize - 1) }, -1 ) + Cursor Bags: ( 0, 33, { 0 .. (maxsize - 1) }, -1 ) + + Bank: ( 1, { 0 .. 23 }, -1, -1 ) + Bank Bags: ( 1, { 0 .. 23 }, { 0 .. (maxsize - 1)}, -1 ) + + Shared Bank: ( 2, { 0 .. 1 }, -1, -1 ) + Shared Bank Bags: ( 2, { 0 .. 1 }, { 0 .. (maxsize - 1) }, -1 ) + + Trade: ( 3, { 0 .. 8 }, -1, -1 ) + (Trade Bags: 3031 - 3110 -- server values) + + World: ( 4, { 0 .. 10 }, -1, -1 ) + +*/ diff --git a/common/patches/rof2_itemfields.h b/common/patches/rof2_itemfields.h new file mode 100644 index 000000000..ccba333b5 --- /dev/null +++ b/common/patches/rof2_itemfields.h @@ -0,0 +1,439 @@ +/* + + +These fields must be in the order of how they are serialized! + + + +*/ +#define NEW_TRY +#ifdef NEW_TRY +//* 000 */ I(ItemClass) // Leave this one off on purpose +/* 001 */ S(Name) +/* 002 */ S(Lore) +//* 003 */ C("")//lorefile - Newly Added - Field is Null +/* 004 */ S(IDFile) +/* 005 */ I(ID) +/* 006 */ I(Weight) +/* 007 */ I(NoRent) +/* 008 */ I(NoDrop) +/* 009 */ I(Size) +/* 010 */ I(Slots) +/* 011 */ I(Price) +/* 012 */ I(Icon) +/* 013 */ C("0")//UNK013 +/* 014 */ C("0")//UNK014 +/* 015 */ I(BenefitFlag) +/* 016 */ I(Tradeskills) +/* 017 */ I(CR) +/* 018 */ I(DR) +/* 019 */ I(PR) +/* 020 */ I(MR) +/* 021 */ I(FR) +/* 022 */ C("0")//svcorruption - Newly Added +/* 023 */ I(AStr) +/* 024 */ I(ASta) +/* 025 */ I(AAgi) +/* 026 */ I(ADex) +/* 027 */ I(ACha) +/* 028 */ I(AInt) +/* 029 */ I(AWis) +/* 030 */ I(HP) +/* 031 */ I(Mana) +/* 032 */ I(Endur) //endur - Relocated +/* 033 */ I(AC) +/* 034 */ I(Classes)//classes - Relocated +/* 035 */ I(Races)//races - Relocated +/* 036 */ I(Deity) +/* 037 */ I(SkillModValue) +/* 038 */ C("0")//UNK038 - Default is 0 +/* 039 */ I(SkillModType) +/* 040 */ I(BaneDmgRace) +/* 041 */ I(BaneDmgBody)//banedmgbody - Relocated +/* 042 */ I(BaneDmgRaceAmt)//banedmgraceamt - Relocated +/* 043 */ I(BaneDmgAmt)//banedmgamt - Relocated +/* 044 */ I(Magic) +/* 045 */ I(CastTime_) +/* 046 */ I(ReqLevel) +/* 047 */ I(RecLevel)//reclevel - Relocated +/* 048 */ I(RecSkill)//recskill - Relocated +/* 049 */ I(BardType) +/* 050 */ I(BardValue) +/* 051 */ I(Light) +/* 052 */ I(Delay) +/* 053 */ I(ElemDmgType) +/* 054 */ I(ElemDmgAmt) +/* 055 */ I(Range) +/* 056 */ I(Damage) +/* 057 */ I(Color) +/* 058 */ I(ItemType) +/* 059 */ I(Material) +/* 060 */ C("0")//UNK060 - Default is 0 +/* 061 */ C("0")//UNK061 - Default is 0 +/* 062 */ F(SellRate) +/* 063 */ I(CombatEffects) +/* 064 */ I(Shielding) +/* 065 */ I(StunResist) +/* 066 */ I(StrikeThrough) +/* 067 */ I(ExtraDmgSkill) +/* 068 */ I(ExtraDmgAmt) +/* 069 */ I(SpellShield) +/* 070 */ I(Avoidance) +/* 071 */ I(Accuracy) +/* 072 */ I(CharmFileID) +/* 073 */ I(FactionMod1)//Swapped these so Faction Amt comes after each Faction Mod +/* 074 */ I(FactionAmt1)//Swapped these so Faction Amt comes after each Faction Mod +/* 075 */ I(FactionMod2)//Swapped these so Faction Amt comes after each Faction Mod +/* 076 */ I(FactionAmt2)//Swapped these so Faction Amt comes after each Faction Mod +/* 077 */ I(FactionMod3)//Swapped these so Faction Amt comes after each Faction Mod +/* 078 */ I(FactionAmt3)//Swapped these so Faction Amt comes after each Faction Mod +/* 079 */ I(FactionMod4)//Swapped these so Faction Amt comes after each Faction Mod +/* 080 */ I(FactionAmt4)//Swapped these so Faction Amt comes after each Faction Mod +/* 081 */ S(CharmFile) +/* 082 */ I(AugType) +/* 083 */ I(AugRestrict)//augrestrict - Relocated +/* 084 */ I(AugDistiller)//augdistiller - Relocated +/* 085 */ I(AugSlotType[0]) +/* 086 */ I(AugSlotVisible[0])//augslot1visible - Default 1 +/* 087 */ C("0")//augslot1unk2 - Newly Added - Default 0 +/* 088 */ I(AugSlotType[1]) +/* 089 */ I(AugSlotVisible[1]) +/* 090 */ C("0")//augslot2unk2 - Newly Added +/* 091 */ I(AugSlotType[2]) +/* 092 */ I(AugSlotVisible[2]) +/* 093 */ C("0")//augslot3unk2 - Newly Added +/* 094 */ I(AugSlotType[3]) +/* 095 */ I(AugSlotVisible[3]) +/* 096 */ C("0")//augslot4unk2 - Newly Added +/* 097 */ I(AugSlotType[4]) +/* 098 */ I(AugSlotVisible[4]) +/* 099 */ C("0")//augslot5unk2 - Newly Added +/* 100 */ I(PointType)//pointtype - Relocated +/* 101 */ I(LDoNTheme) +/* 102 */ I(LDoNPrice) +/* 103 */ C("70")//UNK098 - Newly Added - Default 70, but some are set to 0 +/* 104 */ I(LDoNSold) +/* 105 */ I(BagType) +/* 106 */ I(BagSlots) +/* 107 */ I(BagSize) +/* 108 */ I(BagWR) +/* 109 */ I(Book) +/* 110 */ I(BookType) +/* 111 */ S(Filename) +/* 112 */ I(LoreGroup) +/* 113 */ I(ArtifactFlag) +/* 114 */ C("0")//I(PendingLoreFlag)?//UNK109 - Default 0, but a few are 1 +/* 115 */ I(Favor) +/* 116 */ I(GuildFavor)//guildfavor - Relocated +/* 117 */ I(FVNoDrop) +/* 118 */ I(DotShielding) +/* 119 */ I(Attack) +/* 120 */ I(Regen) +/* 121 */ I(ManaRegen) +/* 122 */ I(EnduranceRegen) +/* 123 */ I(Haste) +/* 124 */ I(DamageShield) +/* 125 */ C("-1") //UNK120 - Default is -1 +/* 126 */ C("0") //UNK121 - Default is 0 +/* 127 */ I(Attuneable) +/* 128 */ I(NoPet) +/* 129 */ C("0") //UNK124 - Default 0, but a few are 1 +/* 130 */ I(PotionBelt) +/* 131 */ C("0") //potionbeltslots - Default 0, but a few are 1 +/* 132 */ I(StackSize) +/* 133 */ I(NoTransfer) +/* 134 */ I(Stackable)//UNK129 - Default is 0, but some are much higher +/* 135 */ I(QuestItemFlag)//questitemflag - Default is 0 (off), flag on = 1 +/* 136 */ C("0")//UNK131 - Default is 0, but there is an item set to 1 +/* 137 */ C("0")//UNK132 - Default is 0? 0000000000000000000? +/* 138 */ I(Click.Effect) +/* 139 */ I(Click.Type) +/* 140 */ I(Click.Level2) +/* 141 */ I(Click.Level) +/* 142 */ I(MaxCharges)//maxcharges - Relocated +/* 143 */ I(CastTime_)//casttime - Relocated - Note Duplicate Entries for CastTime_ and none for CastTime +/* 144 */ I(RecastDelay)//recastdelay - Relocated +/* 145 */ I(RecastType)//recasttype - Relocated +/* 146 */ C("0")//clickunk5 - Newly Added - Default is 0 +/* 147 */ C("")//clickname - Newly Added - Default is Null +/* 148 */ C("-1")//clickunk7 - Newly Added - Default is -1, but some set to 0 and some much higher +/* 149 */ I(Proc.Effect) +/* 150 */ I(Proc.Type) +/* 151 */ I(Proc.Level2) +/* 152 */ I(Proc.Level) +/* 153 */ C("0")//procunk1 - Newly Added - Default is 0, but some set to -1 and 1 +/* 154 */ C("0")//procunk2 - Newly Added - Default is 0 +/* 155 */ C("0")//procunk3 - Newly Added - Default is 0 +/* 156 */ C("0")//procunk4 - Newly Added - Default is 0 +/* 157 */ I(ProcRate)//procrate - Relocated +/* 158 */ C("")//procname - Newly Added - Default is Null +/* 159 */ C("-1")//procunk7 - Newly Added - Default is -1, but some set to 0 +/* 160 */ I(Worn.Effect) +/* 161 */ I(Worn.Type) +/* 162 */ I(Worn.Level2) +/* 163 */ I(Worn.Level) +/* 164 */ C("0")//wornunk1 - Newly Added - Default is 0 +/* 165 */ C("0")//wornunk2 - Newly Added - Default is 0 +/* 166 */ C("0")//wornunk3 - Newly Added - Default is 0 +/* 167 */ C("0")//wornunk4 - Newly Added - Default is 0 +/* 168 */ C("0")//wornunk5 - Newly Added - Default is 0 +/* 169 */ C("")//wornname - Newly Added - Default is Null +/* 170 */ C("-1")//wornunk7 - Newly Added - Default is -1, but some set to 0 +/* 171 */ I(Focus.Effect) +/* 172 */ I(Focus.Type) +/* 173 */ I(Focus.Level2) +/* 174 */ I(Focus.Level) +/* 175 */ C("0")//focusunk1 - Newly Added - Default is 0 +/* 176 */ C("0")//focusunk2 - Newly Added - Default is 0 +/* 177 */ C("0")//focusunk3 - Newly Added - Default is 0 +/* 178 */ C("0")//focusunk4 - Newly Added - Default is 0 +/* 179 */ C("0")//focusunk5 - Newly Added - Default is 0 +/* 180 */ C("")//focusname - Newly Added - Default is Null +/* 181 */ C("-1")//focusunk7 - Newly Added - Default is -1, but some set to 0 +/* 182 */ I(Scroll.Effect) +/* 183 */ I(Scroll.Type) +/* 184 */ I(Scroll.Level2) +/* 185 */ I(Scroll.Level) +/* 186 */ C("0")//scrollunk1 - Renumber this*** +/* 187 */ C("0")//scrollunk2 - Newly Added - Default is 0 +/* 188 */ C("0")//scrollunk3 - Newly Added - Default is 0 +/* 189 */ C("0")//scrollunk4 - Newly Added - Default is 0 +/* 190 */ C("0")//scrollunk5 - Newly Added - Default is 0 +/* 191 */ C("")//scrollname - Newly Added - Default is Null +/* 192 */ C("-1")//scrollunk7 - Newly Added - Default is -1, but some set to 0 +/* 193 */ C("0")//UNK193 - Default is 0 +/* 194 */ C("0")//purity - Newly Added - Default is 0, but some go up to 75 +/* 195 */ C("0")//dsmitigation - Newly Added - Default is 0, but some are up to 2 +/* 196 */ C("0")//heroic_str - Newly Added - Default is 0 +/* 197 */ C("0")//heroic_int - Newly Added - Default is 0 +/* 198 */ C("0")//heroic_wis - Newly Added - Default is 0 +/* 199 */ C("0")//heroic_agi - Newly Added - Default is 0 +/* 200 */ C("0")//heroic_dex - Newly Added - Default is 0 +/* 201 */ C("0")//heroic_sta - Newly Added - Default is 0 +/* 202 */ C("0")//heroic_cha - Newly Added - Default is 0 +/* 203 */ C("0")//HeroicSvPoison - Newly Added - Default is 0 +/* 204 */ C("0")//HeroicSvMagic - Newly Added - Default is 0 +/* 205 */ C("0")//HeroicSvFire - Newly Added - Default is 0 +/* 206 */ C("0")//HeroicSvDisease - Newly Added - Default is 0 +/* 207 */ C("0")//HeroicSvCold - Newly Added - Default is 0 +/* 208 */ C("0")//HeroicSvCorruption - Newly Added - Default is 0 +/* 209 */ C("0")//healamt - Newly Added - Default is 0, but some are up to 9 +/* 210 */ C("0")//spelldmg - Newly Added - Default is 0, but some are up to 9 +/* 211 */ C("0")//clairvoyance - Newly Added - Default is 0, but some are up to 10 +/* 212 */ C("0")//backstabdmg - Newly Added - Default is 0, but some are up to 65 +//* 213 */ C("0")//evolvinglevel - Newly Added - Default is 0, but some are up to 7 +//* 214 */ C("0")//MaxPower - Newly Added +//* 215 */ C("0")//Power - Newly Added + +//This doesn't appear to be used /* 102 */ S(verified)//verified +//This doesn't appear to be used /* 102 */ S(serialized)//created +//Unsure where this goes right now (or if it is even used) /* 108 */ I(SummonedFlag) + +#else +/* 000 */ //I(ItemClass) Leave this one off on purpose +/* 001 */ S(Name) +/* 002 */ S(Lore) +/* 003 */ C("") //LoreFile? +/* 003 */ S(IDFile) +/* 004 */ I(ID) +/* 005 */ I(Weight) +/* 006 */ I(NoRent) +/* 007 */ I(NoDrop) +/* 008 */ I(Size) +/* 009 */ I(Slots) +/* 010 */ I(Price) +/* 011 */ I(Icon) +/* 013 */ C("0") +/* 014 */ C("0") +/* 014 */ I(BenefitFlag) +/* 015 */ I(Tradeskills) +/* 016 */ I(CR) +/* 017 */ I(DR) +/* 018 */ I(PR) +/* 019 */ I(MR) +/* 020 */ I(FR) + C("0") //svcorruption +/* 021 */ I(AStr) +/* 022 */ I(ASta) +/* 023 */ I(AAgi) +/* 024 */ I(ADex) +/* 025 */ I(ACha) +/* 026 */ I(AInt) +/* 027 */ I(AWis) +/* 028 */ I(HP) +/* 029 */ I(Mana) + I(Endur) +/* 030 */ I(AC) +/* 052 */ I(Classes) +/* 053 */ I(Races) +/* 031 */ I(Deity) +/* 032 */ I(SkillModValue) +/* 033 */ C("0") +/* 034 */ I(SkillModType) +/* 035 */ I(BaneDmgRace) +/* 037 */ I(BaneDmgBody) +/* 036 */ I(BaneDmgRaceAmt) +/* 036 */ I(BaneDmgAmt) +/* 038 */ I(Magic) +/* 039 */ I(CastTime_) +/* 040 */ I(ReqLevel) +/* 045 */ I(RecLevel) +/* 046 */ I(RecSkill) +/* 041 */ I(BardType) +/* 042 */ I(BardValue) +/* 043 */ I(Light) +/* 044 */ I(Delay) +/* 047 */ I(ElemDmgType) +/* 048 */ I(ElemDmgAmt) +/* 049 */ I(Range) +/* 050 */ I(Damage) +/* 051 */ I(Color) +/* 056 */ I(ItemType) +/* 057 */ I(Material) +/* 060 */ C("0") +/* 061 */ C("0") +/* 058 */ F(SellRate) +/* 063 */ I(CombatEffects) +/* 064 */ I(Shielding) +/* 065 */ I(StunResist) +/* 059 */ //C("0") +/* 061 */ //C("0") +/* 066 */ I(StrikeThrough) +/* 067 */ I(ExtraDmgSkill) +/* 068 */ I(ExtraDmgAmt) +/* 069 */ I(SpellShield) +/* 070 */ I(Avoidance) +/* 071 */ I(Accuracy) +/* 072 */ I(CharmFileID) +/* 073 */ I(FactionMod1) +/* 077 */ I(FactionAmt1) +/* 074 */ I(FactionMod2) +/* 078 */ I(FactionAmt2) +/* 075 */ I(FactionMod3) +/* 079 */ I(FactionAmt3) +/* 076 */ I(FactionMod4) +/* 080 */ I(FactionAmt4) +/* 081 */ S(CharmFile) +/* 082 */ I(AugType) +/* 082 */ I(AugRestrict) +/* 082 */ I(AugDistiller) +/* 083 */ I(AugSlotType[0]) +/* 084 */ I(AugSlotVisible[0]) +/* 084 */ I(AugSlotUnk2[0]) +/* 085 */ I(AugSlotType[1]) +/* 086 */ I(AugSlotVisible[1]) +/* 086 */ I(AugSlotUnk2[1]) +/* 087 */ I(AugSlotType[2]) +/* 088 */ I(AugSlotVisible[2]) +/* 088 */ I(AugSlotUnk2[2]) +/* 089 */ I(AugSlotType[3]) +/* 090 */ I(AugSlotVisible[3]) +/* 090 */ I(AugSlotUnk2[3]) +/* 091 */ I(AugSlotType[4]) +/* 092 */ I(AugSlotVisible[4]) +/* 092 */ I(AugSlotUnk2[4]) +/* 093 */ I(PointType) +/* 093 */ I(LDoNTheme) +/* 094 */ I(LDoNPrice) +/* 094 */ C("0") +/* 095 */ I(LDoNSold) +/* 096 */ I(BagType) +/* 097 */ I(BagSlots) +/* 098 */ I(BagSize) +/* 099 */ I(BagWR) +/* 100 */ I(Book) +/* 101 */ I(BookType) +/* 102 */ S(Filename) +/* 105 */ I(LoreGroup) +/* 106 */ //I(PendingLoreFlag) +/* 107 */ I(ArtifactFlag) +/* 094 */ C("0") +/* 108 */ //I(SummonedFlag) +/* 109 */ I(Favor) +/* 121 */ I(GuildFavor) +/* 110 */ I(FVNoDrop) +/* 112 */ I(DotShielding) +/* 113 */ I(Attack) +/* 114 */ I(Regen) +/* 115 */ I(ManaRegen) +/* 116 */ I(EnduranceRegen) +/* 117 */ I(Haste) +/* 118 */ I(DamageShield) +/* 120 */ C("0") +/* 121 */ C("0") +/* 125 */ I(Attuneable) +/* 126 */ I(NoPet) +/* 124 */ C("0") +/* 129 */ I(PotionBelt) +/* 130 */ I(PotionBeltSlots) +/* 131 */ I(StackSize) +/* 132 */ I(NoTransfer) +/* 129 */ C("0") +/* 132 */ I(QuestItemFlag) +/* 131 */ C("0") +/* 132 */ C("00000000000000000000000000000000000000") +/* 134 */ I(Click.Effect) +/* 135 */ I(Click.Type) +/* 136 */ I(Click.Level2) +/* 137 */ I(Click.Level) +/* 055 */ I(MaxCharges) +/* 060 */ I(CastTime) +/* 119 */ I(RecastDelay) +/* 120 */ I(RecastType) +/* 138 */ C("0") //clickunk5 (prolly ProcRate) +/* 138 */ C("") //clickunk6 +/* 138 */ C("-1") //clickunk7 +/* 139 */ I(Proc.Effect) +/* 140 */ I(Proc.Type) +/* 141 */ I(Proc.Level2) +/* 142 */ I(Proc.Level) +/* 143 */ C("0") //procunk1 (prolly MaxCharges) +/* 143 */ C("0") //procunk2 (prolly CastTime) +/* 143 */ C("0") //procunk3 (prolly RecastDelay) +/* 143 */ C("0") //procunk4 (prolly RecastType) +/* 062 */ I(ProcRate) +/* 143 */ C("") //procunk6 +/* 143 */ C("-1") //procunk7 +/* 144 */ I(Worn.Effect) +/* 145 */ I(Worn.Type) +/* 146 */ I(Worn.Level2) +/* 147 */ I(Worn.Level) +/* 143 */ C("0") //wornunk1 (prolly MaxCharges) +/* 143 */ C("0") //wornunk2 (prolly CastTime) +/* 143 */ C("0") //wornunk3 (prolly RecastDelay) +/* 143 */ C("0") //wornunk4 (prolly RecastType) +/* 143 */ C("0") //wornunk5 (prolly ProcRate) +/* 143 */ C("") //wornunk6 +/* 143 */ C("-1") //wornunk7 +/* 149 */ I(Focus.Effect) +/* 150 */ I(Focus.Type) +/* 151 */ I(Focus.Level2) +/* 152 */ I(Focus.Level) +/* 143 */ C("0") //focusunk1 (prolly MaxCharges) +/* 143 */ C("0") //focusunk2 (prolly CastTime) +/* 143 */ C("0") //focusunk3 (prolly RecastDelay) +/* 143 */ C("0") //focusunk4 (prolly RecastType) +/* 143 */ C("0") //focusunk5 (prolly ProcRate) +/* 143 */ C("") //focusunk6 +/* 143 */ C("-1") //focusunk7 +/* 154 */ I(Scroll.Effect) +/* 155 */ I(Scroll.Type) +/* 156 */ I(Scroll.Level2) +/* 157 */ I(Scroll.Level) +/* 143 */ C("0") //scrollunk1 (prolly MaxCharges) +/* 143 */ C("0") //scrollunk2 (prolly CastTime) +/* 143 */ C("0") //scrollunk3 (prolly RecastDelay) +/* 143 */ C("0") //scrollunk4 (prolly RecastType) +/* 143 */ C("0") //scrollunk5 (prolly ProcRate) +/* 143 */ C("") //scrollunk6 +/* 143 */ C("-1") //scrollunk7 +/* 193 */ C("0") //Power Source Capacity +/* 194 */ C("0") //purity + +#endif + +#undef I +#undef C +#undef S +#undef F + diff --git a/common/patches/rof2_ops.h b/common/patches/rof2_ops.h new file mode 100644 index 000000000..fbdd20575 --- /dev/null +++ b/common/patches/rof2_ops.h @@ -0,0 +1,173 @@ +// out-going packets that require an ENCODE translation: +// Begin RoF2 Encodes + +// incoming packets that require a DECODE translation: +// Begin RoF2 Decodes + + +// End RoF2 Encodes/Decodes + +// These require Encodes/Decodes for RoF, so they do for RoF2 as well +// Begin RoF Encodes +E(OP_Action) +E(OP_AdventureMerchantSell) +E(OP_AltCurrency) +E(OP_AltCurrencySell) +E(OP_Animation) +E(OP_ApplyPoison) +E(OP_AugmentInfo) +E(OP_Barter) +E(OP_BazaarSearch) +E(OP_BeginCast) +E(OP_BlockedBuffs) +E(OP_Buff) +E(OP_BuffCreate) +E(OP_CancelTrade) +E(OP_CastSpell) +E(OP_ChannelMessage) +E(OP_CharInventory) +E(OP_ClickObjectAction) +E(OP_ClientUpdate) +E(OP_Consider) +E(OP_Damage) +E(OP_DeleteCharge) +E(OP_DeleteItem) +E(OP_DeleteSpawn) +E(OP_DisciplineUpdate) +E(OP_DzCompass) +E(OP_DzExpeditionEndsWarning) +E(OP_DzExpeditionInfo) +E(OP_DzExpeditionList) +E(OP_DzJoinExpeditionConfirm) +E(OP_DzLeaderStatus) +E(OP_DzMemberList) +E(OP_ExpansionInfo) +E(OP_GMLastName) +E(OP_GMTrainSkillConfirm) +E(OP_GroundSpawn) +E(OP_GroupCancelInvite) +E(OP_GroupFollow) +E(OP_GroupFollow2) +E(OP_GroupInvite) +E(OP_GroupUpdate) +E(OP_GuildMemberList) +E(OP_GuildMemberUpdate) +E(OP_GuildsList) +E(OP_HPUpdate) +E(OP_Illusion) +E(OP_InspectBuffs) +E(OP_InspectRequest) +E(OP_InterruptCast) +E(OP_ItemLinkResponse) +E(OP_ItemPacket) +E(OP_ItemVerifyReply) +E(OP_LeadershipExpUpdate) +E(OP_LogServer) +E(OP_LootItem) +E(OP_ManaChange) +E(OP_MercenaryDataResponse) +E(OP_MercenaryDataUpdate) +E(OP_MoveItem) +E(OP_NewSpawn) +E(OP_NewZone) +E(OP_OnLevelMessage) +//E(OP_OpenNewTasksWindow) +E(OP_PetBuffWindow) +E(OP_PlayerProfile) +E(OP_RaidJoin) +E(OP_RaidUpdate) +E(OP_ReadBook) +E(OP_RecipeAutoCombine) +E(OP_RemoveBlockedBuffs) +E(OP_RequestClientZoneChange) +E(OP_RespondAA) +E(OP_RezzRequest) +E(OP_SendAATable) +E(OP_SendCharInfo) +E(OP_SendMembership) +E(OP_SendZonepoints) +E(OP_SetGuildRank) +E(OP_ShopPlayerBuy) +E(OP_ShopPlayerSell) +E(OP_ShopRequest) +E(OP_SkillUpdate) +E(OP_SomeItemPacketMaybe) +E(OP_SpawnAppearance) +E(OP_SpawnDoor) +E(OP_Stun) +E(OP_TargetBuffs) +E(OP_TaskDescription) +E(OP_TaskHistoryReply) +E(OP_Track) +E(OP_Trader) +E(OP_TraderBuy) +E(OP_TributeInfo) +E(OP_TributeItem) +E(OP_VetRewardsAvaliable) +E(OP_WearChange) +E(OP_WhoAllResponse) +E(OP_ZoneChange) +E(OP_ZoneEntry) +E(OP_ZonePlayerToBind) +E(OP_ZoneServerInfo) +E(OP_ZoneSpawns) +// Begin RoF Decodes +D(OP_AdventureMerchantSell) +D(OP_AltCurrencySell) +D(OP_AltCurrencySellSelection) +D(OP_ApplyPoison) +D(OP_AugmentInfo) +D(OP_AugmentItem) +D(OP_BazaarSearch) +D(OP_BlockedBuffs) +D(OP_Buff) +D(OP_BuffRemoveRequest) +D(OP_CastSpell) +D(OP_ChannelMessage) +D(OP_CharacterCreate) +D(OP_ClientUpdate) +D(OP_Consider) +D(OP_ConsiderCorpse) +D(OP_Consume) +D(OP_Damage) +D(OP_DeleteItem) +D(OP_EnvDamage) +D(OP_FaceChange) +D(OP_FindPersonRequest) +D(OP_GMLastName) +D(OP_GroupCancelInvite) +D(OP_GroupDisband) +D(OP_GroupFollow) +D(OP_GroupFollow2) +D(OP_GroupInvite) +D(OP_GroupInvite2) +D(OP_GuildDemote) +D(OP_GuildRemove) +D(OP_GuildStatus) +D(OP_InspectRequest) +D(OP_ItemLinkClick) +D(OP_ItemVerifyRequest) +D(OP_LoadSpellSet) +D(OP_LootItem) +D(OP_MoveItem) +D(OP_PetCommands) +D(OP_RaidInvite) +D(OP_ReadBook) +D(OP_RecipeAutoCombine) +D(OP_RemoveBlockedBuffs) +D(OP_RezzAnswer) +D(OP_Save) +D(OP_SetServerFilter) +D(OP_ShopPlayerBuy) +D(OP_ShopPlayerSell) +D(OP_ShopRequest) +D(OP_Trader) +D(OP_TraderBuy) +D(OP_TradeSkillCombine) +D(OP_TributeItem) +D(OP_WhoAllRequest) +D(OP_ZoneChange) +D(OP_ZoneEntry) +// End RoF Encodes/Decodes +#undef E +#undef D diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h new file mode 100644 index 000000000..b75faee91 --- /dev/null +++ b/common/patches/rof2_structs.h @@ -0,0 +1,4922 @@ +#ifndef RoF2_STRUCTS_H_ +#define RoF2_STRUCTS_H_ + +namespace RoF2 { + namespace structs { + +/* +** Compiler override to ensure +** byte aligned structures +*/ +#pragma pack(1) + +struct LoginInfo_Struct { +/*000*/ char login_info[64]; +/*064*/ uint8 unknown064[124]; +/*188*/ uint8 zoning; // 01 if zoning, 00 if not +/*189*/ uint8 unknown189[275]; +/*488*/ +}; + +struct EnterWorld_Struct { +/*000*/ char name[64]; +/*064*/ uint32 tutorial; // 01 on "Enter Tutorial", 00 if not +/*068*/ uint32 return_home; // 01 on "Return Home", 00 if not +}; + +//New For SoF +struct WorldObjectsSent_Struct { +}; + +// New for RoF2 - Size: 12 +struct ItemSlotStruct { +/*000*/ int16 SlotType; // Worn and Normal inventory = 0, Bank = 1, Shared Bank = 2, Delete Item = -1 +/*002*/ int16 Unknown02; +/*004*/ int16 MainSlot; +/*006*/ int16 SubSlot; +/*008*/ int16 AugSlot; // Guessing - Seen 0xffff +/*010*/ int16 Unknown01; // Normally 0 - Seen 13262 when deleting an item, but didn't match item ID +/*012*/ +}; + +// New for RoF2 - Used for Merchant_Purchase_Struct +// Can't sellfrom other than main inventory so Slot Type is not needed. +struct MainInvItemSlotStruct { +/*000*/ int16 MainSlot; +/*002*/ int16 SubSlot; +/*004*/ int16 AugSlot; +/*006*/ int16 Unknown01; +/*008*/ +}; + +/* Name Approval Struct */ +/* Len: */ +/* Opcode: 0x8B20*/ +struct NameApproval +{ + char name[64]; + uint32 race; + uint32 class_; + uint32 deity; +}; + +/* +** Entity identification struct +** Size: 4 bytes +** OPCodes: OP_DeleteSpawn, OP_Assist +*/ +struct EntityId_Struct +{ +/*00*/ uint32 entity_id; +/*04*/ +}; + +struct Duel_Struct +{ + uint32 duel_initiator; + uint32 duel_target; +}; + +struct DuelResponse_Struct +{ + uint32 target_id; + uint32 entity_id; + uint32 unknown; +}; + +//Adventure stuff,not a net one,just one for our use +static const uint32 ADVENTURE_COLLECT = 0; +static const uint32 ADVENTURE_MASSKILL = 1; +static const uint32 ADVENTURE_NAMED = 2; +static const uint32 ADVENTURE_RESCUE = 3; + +static const uint32 BUFF_COUNT = 42; // was 25 +static const uint32 BLOCKED_BUFF_COUNT = 30; // was 20 + +static const uint32 MAX_PLAYER_TRIBUTES = 5; +static const uint32 MAX_TRIBUTE_TIERS = 10; +static const uint32 TRIBUTE_NONE = 0xFFFFFFFF; + +static const uint32 MAX_PLAYER_BANDOLIER = 20; +static const uint32 MAX_PLAYER_BANDOLIER_ITEMS = 4; + +static const uint32 MAX_POTIONS_IN_BELT = 5; + +static const uint32 MAX_GROUP_LEADERSHIP_AA_ARRAY = 16; +static const uint32 MAX_RAID_LEADERSHIP_AA_ARRAY = 16; +static const uint32 MAX_LEADERSHIP_AA_ARRAY = (MAX_GROUP_LEADERSHIP_AA_ARRAY+MAX_RAID_LEADERSHIP_AA_ARRAY); + +static const uint32 MAX_NUMBER_GUILDS = 1500; + +// Used primarily in the Player Profile: +static const uint32 MAX_PP_LANGUAGE = 32; // was 25 +static const uint32 MAX_PP_SPELLBOOK = 720; // was 480 +static const uint32 MAX_PP_MEMSPELL = 16; // was 12 +static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size +static const uint32 MAX_PP_AA_ARRAY = 300; +static const uint32 MAX_PP_DISCIPLINES = 200; // was 100 +static const uint32 MAX_GROUP_MEMBERS = 6; +static const uint32 MAX_RECAST_TYPES = 20; + +struct AdventureInfo { + uint32 QuestID; + uint32 NPCID; + bool in_use; + uint32 status; + bool ShowCompass; + uint32 Objetive;// can be item to collect,mobs to kill,boss to kill and someone to rescue. + uint32 ObjetiveValue;// number of items,or number of needed mob kills. + char text[512]; + uint8 type; + uint32 minutes; + uint32 points; + float x; + float y; + uint32 zoneid; + uint32 zonedungeonid; +}; +/////////////////////////////////////////////////////////////////////////////// + + +/* +** Color_Struct +** Size: 4 bytes +** Used for convenience +** Merth: Gave struct a name so gcc 2.96 would compile +** +*/ +struct Color_Struct +{ + union + { + struct + { + uint8 blue; + uint8 green; + uint8 red; + uint8 use_tint; // if there's a tint this is FF + } rgb; + uint32 color; + }; +}; + +struct CharSelectEquip { + //totally guessed; + uint32 equip0; + uint32 equip1; + uint32 equip2; + uint32 itemid; + uint32 equip3; + Color_Struct color; +}; + +struct CharacterSelectEntry_Struct { +/*0000*/ char name[1]; // Name null terminated +/*0000*/ uint8 class_; +/*0000*/ uint32 race; +/*0000*/ uint8 level; +/*0000*/ uint8 class_2; +/*0000*/ uint32 race2; +/*0000*/ uint16 zone; +/*0000*/ uint16 instance; +/*0000*/ uint8 gender; +/*0000*/ uint8 face; +/*0000*/ CharSelectEquip equip[9]; +/*0000*/ uint8 u15; // Seen FF +/*0000*/ uint8 u19; // Seen FF +/*0000*/ uint32 drakkin_tattoo; +/*0000*/ uint32 drakkin_details; +/*0000*/ uint32 deity; +/*0000*/ uint32 primary; +/*0000*/ uint32 secondary; +/*0000*/ uint8 haircolor; +/*0000*/ uint8 beardcolor; +/*0000*/ uint8 eyecolor1; +/*0000*/ uint8 eyecolor2; +/*0000*/ uint8 hairstyle; +/*0000*/ uint8 beard; +/*0000*/ uint8 char_enabled; +/*0000*/ uint8 tutorial; // Seen 1 for new char or 0 for existing +/*0000*/ uint32 drakkin_heritage; +/*0000*/ uint8 unknown1; // Seen 0 +/*0000*/ uint8 gohome; // Seen 0 for new char and 1 for existing +/*0000*/ uint32 LastLogin; +/*0000*/ uint8 unknown2; // Seen 0 +}; + +/* +** Character Selection Struct +** +*/ +struct CharacterSelect_Struct { +/*000*/ uint32 char_count; //number of chars in this packet +/*004*/ CharacterSelectEntry_Struct entries[0]; +}; + +struct Membership_Entry_Struct +{ +/*000*/ uint32 purchase_id; // Seen 1, then increments 90287 to 90300 +/*004*/ uint32 bitwise_entry; // Seen 16 to 65536 - Skips 4096 +/*008*/ +}; + +struct Membership_Setting_Struct +{ +/*000*/ uint32 setting_index; // 0, 1, or 2 +/*004*/ uint32 setting_id; // 0 to 21 +/*008*/ int32 setting_value; // All can be 0, 1, or -1 +/*012*/ +}; + +struct Membership_Details_Struct +{ +/*0000*/ uint32 membership_setting_count; // Seen 66 +/*0016*/ Membership_Setting_Struct settings[66]; +/*0012*/ uint32 race_entry_count; // Seen 15 +/*1044*/ Membership_Entry_Struct membership_races[15]; +/*0012*/ uint32 class_entry_count; // Seen 15 +/*1044*/ Membership_Entry_Struct membership_classes[15]; +/*1044*/ uint32 exit_url_length; // Length of the exit_url string (0 for none) +/*1048*/ //char exit_url[42]; // Upgrade to Silver or Gold Membership URL +/*1048*/ uint32 exit_url_length2; // Length of the exit_url2 string (0 for none) +/*0000*/ //char exit_url2[49]; // Upgrade to Gold Membership URL +}; + +struct Membership_Struct +{ +/*000*/ uint32 membership; // Seen 2 on Gold Account +/*004*/ uint32 races; // Seen ff ff 01 00 +/*008*/ uint32 classes; // Seen ff ff 01 01 +/*012*/ uint32 entrysize; // Seen 22 +/*016*/ int32 entries[22]; // Most -1, 1, and 0 for Gold Status +/*104*/ +}; + + +/* +* Visible equiptment. +* Size: 20 Octets +*/ +struct EquipStruct { +/*00*/ uint32 equip0; +/*04*/ uint32 equip1; +/*08*/ uint32 equip2; +/*12*/ uint32 itemId; +/*16*/ uint32 equip3; // Same as equip0? +/*20*/ +}; + + +/* +** Generic Spawn Struct +** Length: 897 Octets +** Used in: +** spawnZoneStruct +** dbSpawnStruct +** petStruct +** newSpawnStruct +*/ +/* +showeq -> eqemu +sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g' +*/ + +struct Spawn_Struct_Bitfields +{ +/*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster) +/*02*/ unsigned ispet:1; // Guessed based on observing live spawns +/*03*/ unsigned afk:1; // 0=no, 1=afk +/*04*/ unsigned anon:2; // 0=normal, 1=anon, 2=roleplay +/*06*/ unsigned gm:1; +/*06*/ unsigned sneak:1; +/*08*/ unsigned lfg:1; +/*09*/ unsigned unknown09:1; +/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which +/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below +/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis +/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis +/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis +/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis +/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis +/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis +/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis +/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis +/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis +/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis +/*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2 +/*23*/ unsigned showhelm:1; +/*24*/ unsigned unknown24:1; // Prefixes name with ! +/*25*/ unsigned trader:1; +/*26*/ unsigned unknown26:1; +/*27*/ unsigned targetable:1; +/*28*/ unsigned targetable_with_hotkey:1; +/*29*/ unsigned showname:1; +/*30*/ unsigned unknown30:1; +/*30*/ unsigned untargetable:1; // Untargetable with mouse + /* + // Unknown in RoF2 + unsigned betabuffed:1; + unsigned buyer:1; + unsigned buyer:1; + */ +}; + +/* +struct Spawn_Struct_Position +{ + signed padding0000:12; + signed y:19; + signed padding0001:1; + + signed deltaX:13; // change in x + signed deltaHeading:10;// change in heading + signed padding0008:9; + + signed deltaY:13; + signed z:19; + + signed x:19; + signed animation:10; // animation + signed padding0016:3; + + signed heading:12; + signed deltaZ:13; // change in z + signed padding0020:7; +}; +*/ + +struct Spawn_Struct_Position +{ + signed padding0000:12; + signed y:19; + signed padding0001:1; + + signed deltaZ:13; // change in z + signed deltaX:13; // change in x + signed padding0008:6; + + signed x:19; + signed heading:12; + signed padding0016:1; + + signed deltaHeading:10;// change in heading + signed z:19; + signed padding0020:3; + + signed animation:10; // animation + signed deltaY:13; + signed padding0023:9; +}; + +struct Spawn_Struct +{ +// Note this struct is not used as such, it is here for reference. As the struct is variable sized, the packets +// are constructed in Live.cpp +// +/*0000*/ char name[1]; //name[64]; +/*0000*/ //uint8 nullterm1; // hack to null terminate name +/*0064*/ uint32 spawnId; +/*0068*/ uint8 level; +/*0069*/ float unknown1; +/*0073*/ uint8 NPC; // 0=player,1=npc,2=pc corpse,3=npc corpse + Spawn_Struct_Bitfields Bitfields; +/*0000*/ uint8 otherData; // & 4 - has title, & 8 - has suffix, & 1 - it's a chest or untargetable +/*0000*/ float unknown3; // seen -1 +/*0000*/ float unknown4; +/*0000*/ float size; +/*0000*/ uint8 face; +/*0000*/ float walkspeed; +/*0000*/ float runspeed; +/*0000*/ uint32 race; +/*0000*/ uint8 showname; // for body types - was charProperties +/*0000*/ uint32 bodytype; +/*0000*/ //uint32 bodytype2; // this is only present if charProperties==2 + // are there more than two possible properties? +/*0000*/ uint8 curHp; +/*0000*/ uint8 haircolor; +/*0000*/ uint8 beardcolor; +/*0000*/ uint8 eyecolor1; +/*0000*/ uint8 eyecolor2; +/*0000*/ uint8 hairstyle; +/*0000*/ uint8 beard; +/*0000*/ uint32 drakkin_heritage; +/*0000*/ uint32 drakkin_tattoo; +/*0000*/ uint32 drakkin_details; +/*0000*/ uint8 statue; // was holding +/*0000*/ uint32 deity; +/*0000*/ uint32 guildID; +/*0000*/ uint32 guildrank; // 0=member, 1=officer, 2=leader, -1=not guilded +/*0000*/ uint8 class_; +/*0000*/ uint8 pvp; // 0 = normal name color, 2 = PVP name color +/*0000*/ uint8 StandState; // stand state - 0x64 for normal animation +/*0000*/ uint8 light; +/*0000*/ uint8 flymode; +/*0000*/ uint8 equip_chest2; +/*0000*/ uint8 unknown9; +/*0000*/ uint8 unknown10; +/*0000*/ uint8 helm; +/*0000*/ char lastName[1]; +/*0000*/ //uint8 lastNameNull; //hack! +/*0000*/ uint32 aatitle; // 0=none, 1=general, 2=archtype, 3=class was AARank +/*0000*/ uint8 unknown12; +/*0000*/ uint32 petOwnerId; +/*0000*/ uint8 unknown13; +/*0000*/ uint32 unknown14; // Stance 64 = normal 4 = aggressive 40 = stun/mezzed +/*0000*/ uint32 unknown15; +/*0000*/ uint32 unknown16; +/*0000*/ uint32 unknown17; +/*0000*/ //uint8 unknownRoF23; +/*0000*/ uint32 unknown18; +/*0000*/ uint32 unknown19; + Spawn_Struct_Position Position; +/*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 + }; + +// skip these bytes if not a valid player race +/*0000*/ union + { + struct + { + /*0000*/ EquipStruct equip_helmet; // Equiptment: Helmet visual + /*0000*/ EquipStruct equip_chest; // Equiptment: Chest visual + /*0000*/ EquipStruct equip_arms; // Equiptment: Arms visual + /*0000*/ EquipStruct equip_bracers; // Equiptment: Wrist visual + /*0000*/ EquipStruct equip_hands; // Equiptment: Hands visual + /*0000*/ EquipStruct equip_legs; // Equiptment: Legs visual + /*0000*/ EquipStruct equip_feet; // Equiptment: Boots visual + /*0000*/ EquipStruct equip_primary; // Equiptment: Main visual + /*0000*/ EquipStruct equip_secondary; // Equiptment: Off visual + } equip; + /*0000*/ EquipStruct equipment[9]; + }; + +/*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) +/*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8) + char unknown20[8]; + uint8 IsMercenary; // If NPC == 1 and this == 1, then the NPC name is Orange. +/*0000*/ char unknown21[55]; +}; + + +/* +** Generic Spawn Struct +** Fields from old struct not yet found: +** uint8 traptype; // 65 is disarmable trap, 66 and 67 are invis triggers/traps +** uint8 is_pet; // 0=no, 1=yes +** uint8 afk; // 0=no, 1=afk +** uint8 is_npc; // 0=no, 1=yes +** uint8 max_hp; // (name prolly wrong)takes on the value 100 for players, 100 or 110 for NPCs and 120 for PC corpses... +** uint8 guildrank; // 0=normal, 1=officer, 2=leader +** uint8 eyecolor2; //not sure, may be face +** uint8 aaitle; // 0=none, 1=general, 2=archtype, 3=class +*/ + +/* +** New Spawn +** Length: 176 Bytes +** OpCode: 4921 +*/ +struct NewSpawn_Struct +{ + struct Spawn_Struct spawn; // Spawn Information +}; + + +/* +** Client Zone Entry struct +** Length: 68 Octets +** OpCode: ZoneEntryCode (when direction == client) +*/ +struct ClientZoneEntry_Struct { +/*00*/ uint32 unknown00; // ***Placeholder +/*04*/ char char_name[64]; // Player firstname [32] +/*68*/ uint32 unknown68; +/*72*/ uint32 unknown72; +}; + + +/* +** Server Zone Entry Struct +** Length: 452 Bytes +** OPCodes: OP_ServerZoneEntry +** +*/ +struct ServerZoneEntry_Struct //Adjusted from SEQ Everquest.h Struct +{ + struct NewSpawn_Struct player; +}; + + +//New Zone Struct - Size: 948 +struct NewZone_Struct { +/*0000*/ char char_name[64]; // Character Name +/*0064*/ char zone_short_name[32]; // Zone Short Name +/*0096*/ char unknown0096[96]; +/*0192*/ char zone_long_name[278]; // Zone Long Name +/*0470*/ uint8 ztype; // Zone type (usually FF) +/*0471*/ uint8 fog_red[4]; // Zone fog (red) +/*0475*/ uint8 fog_green[4]; // Zone fog (green) +/*0479*/ uint8 fog_blue[4]; // Zone fog (blue) +/*0483*/ uint8 unknown323; +/*0484*/ float fog_minclip[4]; +/*0500*/ float fog_maxclip[4]; +/*0516*/ float gravity; +/*0520*/ uint8 time_type; +/*0521*/ uint8 rain_chance[4]; +/*0525*/ uint8 rain_duration[4]; +/*0529*/ uint8 snow_chance[4]; +/*0533*/ uint8 snow_duration[4]; +/*0537*/ uint8 unknown537[33]; +/*0570*/ uint8 sky; // Sky Type +/*0571*/ uint8 unknown571[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 min_z; // Guessed - NEW - Seen 0 +/*0604*/ float max_z; // Guessed +/*0608*/ float underworld; // Underworld, min z (Not Sure?) +/*0612*/ float minclip; // Minimum View Distance +/*0616*/ float maxclip; // Maximum View DIstance +/*0620*/ uint8 unknown620[84]; // ***Placeholder +/*0704*/ char zone_short_name2[96]; //zone file name? excludes instance number which can be in previous version. +/*0800*/ int32 unknown800; //seen -1 +/*0804*/ char unknown804[40]; // +/*0844*/ int32 unknown844; //seen 600 +/*0848*/ int32 unknown848; +/*0852*/ uint16 zone_id; +/*0854*/ uint16 zone_instance; +/*0856*/ char unknown856[20]; +/*0876*/ uint32 SuspendBuffs; +/*0880*/ uint32 unknown880; // Seen 50 +/*0884*/ uint32 unknown884; // Seen 10 +/*0888*/ uint8 unknown888; // Seen 1 +/*0889*/ uint8 unknown889; // Seen 0 (POK) or 1 (rujj) +/*0890*/ uint8 unknown890; // Seen 1 +/*0891*/ uint8 unknown891; // Seen 0 +/*0892*/ uint8 unknown892; // Seen 0 +/*0893*/ uint8 unknown893; // Seen 0 - 00 +/*0894*/ uint8 fall_damage; // 0 = Fall Damage on, 1 = Fall Damage off +/*0895*/ uint8 unknown895; // Seen 0 - 00 +/*0896*/ uint32 unknown896; // Seen 180 +/*0900*/ uint32 unknown900; // Seen 180 +/*0904*/ uint32 unknown904; // Seen 180 +/*0908*/ uint32 unknown908; // Seen 2 +/*0912*/ uint32 unknown912; // Seen 2 +/*0916*/ float FogDensity; // Most zones have this set to 0.33 Blightfire had 0.16 +/*0920*/ uint32 unknown920; // Seen 0 +/*0924*/ uint32 unknown924; // Seen 0 +/*0928*/ uint32 unknown928; // Seen 0 +/*0932*/ int32 unknown932; // Seen -1 +/*0936*/ int32 unknown936; // Seen -1 +/*0940*/ uint32 unknown940; // Seen 0 +/*0944*/ float unknown944; // Seen 1.0 +/*0948*/ +}; + + +/* +** Memorize Spell Struct +** Length: 16 Bytes +** +*/ +struct MemorizeSpell_Struct { +uint32 slot; // Spot in the spell book/memorized slot +uint32 spell_id; // Spell id (200 or c8 is minor healing, etc) +uint32 scribing; // 1 if memorizing a spell, set to 0 if scribing to book, 2 if un-memming +uint32 unknown12; +}; + +/* +** Make Charmed Pet +** Length: 12 Bytes +** +*/ +struct Charm_Struct { +/*00*/ uint32 owner_id; +/*04*/ uint32 pet_id; +/*08*/ uint32 command; // 1: make pet, 0: release pet +/*12*/ +}; + +struct InterruptCast_Struct +{ + uint32 spawnid; + uint32 messageid; + //char message[0]; +}; + +struct DeleteSpell_Struct +{ +/*000*/int16 spell_slot; +/*002*/uint8 unknowndss002[2]; +/*004*/uint8 success; +/*005*/uint8 unknowndss006[3]; +/*008*/ +}; + +struct ManaChange_Struct +{ + uint32 new_mana; // New Mana AMount + uint32 stamina; + uint32 spell_id; + uint32 unknown12; + uint32 unknown16; +}; + +struct SwapSpell_Struct +{ + uint32 from_slot; + uint32 to_slot; +}; + +struct BeginCast_Struct +{ +/*000*/ uint32 spell_id; +/*004*/ uint16 caster_id; +/*006*/ uint32 cast_time; // in miliseconds +/*010*/ +}; + +struct CastSpell_Struct +{ +/*00*/ uint32 slot; +/*04*/ uint32 spell_id; +/*08*/ ItemSlotStruct inventoryslot; // slot for clicky item, Seen unknown of 131 = normal cast +/*20*/ uint32 target_id; +/*24*/ uint32 cs_unknown[5]; +/*44*/ +}; + +/* +** SpawnAppearance_Struct +** Changes client appearance for all other clients in zone +** Size: 8 bytes +** Used in: OP_SpawnAppearance +** +*/ +struct SpawnAppearance_Struct +{ +/*0000*/ uint16 spawn_id; // ID of the spawn +/*0002*/ uint16 type; // Values associated with the type +/*0004*/ uint32 parameter; // Type of data sent +/*0008*/ +}; + +struct SpellBuff_Struct +{ +/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise +/*001*/ float unknown004; // Seen 1 for no buff +/*005*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages +/*009*/ uint32 unknown016; +/*013*/ uint8 bard_modifier; +/*014*/ uint32 duration; +/*018*/ uint8 level; +/*019*/ uint32 spellid; +/*023*/ uint32 counters; +/*027*/ uint8 unknown0028[53]; +/*080*/ +}; + +struct SpellBuff_Struct_Old +{ +/*000*/ uint8 slotid; // badly named... seems to be 2 for a real buff, 0 otherwise +/*001*/ uint8 level; +/*002*/ uint8 bard_modifier; +/*003*/ uint8 effect; // not real +/*004*/ float unknown004; // Seen 1 for no buff +/*008*/ uint32 spellid; +/*012*/ uint32 duration; +/*016*/ uint32 unknown016; +/*020*/ uint32 player_id; // 'global' ID of the caster, for wearoff messages +/*024*/ uint32 counters; +/*028*/ uint8 unknown0028[60]; +/*088*/ +}; + +// Not functional yet, but this is what the packet looks like on Live +struct SpellBuffFade_Struct_Live { +/*000*/ uint32 entityid; // Player id who cast the buff +/*004*/ uint8 unknown004; +/*005*/ uint8 level; +/*006*/ uint8 effect; +/*007*/ uint8 unknown007; +/*008*/ float unknown008; +/*012*/ uint32 spellid; +/*016*/ uint32 duration; +/*020*/ uint32 playerId; // Global player ID? +/*024*/ uint32 num_hits; +/*028*/ uint8 unknown0028[64]; +/*092*/ uint32 slotid; +/*096*/ uint32 bufffade; +/*100*/ +}; + +struct SpellBuffFade_Struct { +/*000*/ uint32 entityid; +/*004*/ uint8 slot; +/*005*/ uint8 level; +/*006*/ uint8 effect; +/*007*/ uint8 unknown7; +/*008*/ uint32 spellid; +/*012*/ uint32 duration; +/*016*/ uint32 num_hits; +/*020*/ uint32 unknown020; // Global player ID? +/*024*/ uint32 playerId; // Player id who cast the buff +/*028*/ uint32 slotid; +/*032*/ uint32 bufffade; +/*036*/ +}; + +struct BuffRemoveRequest_Struct +{ +/*00*/ uint32 SlotID; +/*04*/ uint32 EntityID; +/*08*/ +}; + +#if 0 +// not in use +struct BuffIconEntry_Struct { +/*000*/ uint32 buff_slot; +/*004*/ uint32 spell_id; +/*008*/ uint32 tics_remaining; +/*012*/ uint32 num_hits; +// char name[0]; caster name is also here sometimes +// uint8 unknownend; 1 when single, 0 when all opposite of all_buffs? +}; + +// not in use +struct BuffIcon_Struct { +/*000*/ uint32 entity_id; +/*004*/ uint32 unknown004; +/*008*/ uint8 all_buffs; // 1 when updating all buffs, 0 when doing one +/*009*/ uint16 count; +/*011*/ BuffIconEntry_Struct entires[0]; +}; +#endif + +struct GMTrainee_Struct +{ + /*000*/ uint32 npcid; + /*004*/ uint32 playerid; + /*008*/ uint32 skills[PACKET_SKILL_ARRAY_SIZE]; + /*408*/ uint8 unknown408[40]; + /*448*/ +}; + +struct GMTrainEnd_Struct +{ + /*000*/ uint32 npcid; + /*004*/ uint32 playerid; + /*008*/ +}; + +struct GMSkillChange_Struct { +/*000*/ uint16 npcid; +/*002*/ uint8 unknown1[2]; // something like PC_ID, but not really. stays the same thru the session though +/*002*/ uint16 skillbank; // 0 if normal skills, 1 if languages +/*002*/ uint8 unknown2[2]; +/*008*/ uint16 skill_id; +/*010*/ uint8 unknown3[2]; +/*012*/ +}; + +struct GMTrainSkillConfirm_Struct { // SoF+ only +/*000*/ uint32 SkillID; +/*004*/ uint32 Cost; +/*008*/ uint8 NewSkill; // Set to 1 for 'You have learned the basics' message. +/*009*/ char TrainerName[64]; +/*073*/ uint8 Unknown073[3]; +/*076*/ +}; + +struct ConsentResponse_Struct { + char grantname[64]; + char ownername[64]; + uint8 permission; + char zonename[64]; +}; + +/* +** Name Generator Struct +** Length: 72 bytes +** OpCode: 0x0290 +*/ +struct NameGeneration_Struct +{ +/*0000*/ uint32 race; +/*0004*/ uint32 gender; +/*0008*/ char name[64]; +/*0072*/ +}; + +/* +** Character Creation struct +** Length: 96 Bytes +*/ +struct CharCreate_Struct +{ +/*0000*/ uint32 gender; +/*0004*/ uint32 race; +/*0008*/ uint32 class_; +/*0012*/ uint32 deity; +/*0016*/ uint32 start_zone; +/*0020*/ uint32 haircolor; +/*0024*/ uint32 beard; +/*0028*/ uint32 beardcolor; +/*0032*/ uint32 hairstyle; +/*0036*/ uint32 face; +/*0040*/ uint32 eyecolor1; +/*0044*/ uint32 eyecolor2; +/*0048*/ uint32 drakkin_heritage; +/*0052*/ uint32 drakkin_tattoo; +/*0056*/ uint32 drakkin_details; +/*0060*/ uint32 STR; +/*0064*/ uint32 STA; +/*0068*/ uint32 AGI; +/*0073*/ uint32 DEX; +/*0076*/ uint32 WIS; +/*0080*/ uint32 INT; +/*0084*/ uint32 CHA; +/*0088*/ uint32 tutorial; +/*0092*/ uint32 unknown0092; +/*0096*/ +}; + +/* +** Character Creation struct +** Length: 0 Bytes +** OpCode: 0x +*/ +struct CharCreate_Struct_Temp //Size is now 0 +{ +}; + +/* + *Used in PlayerProfile + */ +struct AA_Array +{ + uint32 AA; + uint32 value; + uint32 unknown08; // Looks like AA_Array is now 12 bytes in Live +}; + +struct Disciplines_Struct { + uint32 values[MAX_PP_DISCIPLINES]; +}; + + + +struct Tribute_Struct { + uint32 tribute; + uint32 tier; +}; + +struct BandolierItem_Struct { + char item_name[1]; // Variable Length + uint32 item_id; + uint32 icon; +}; + +//len = 72 +struct BandolierItem_Struct_Old { + uint32 item_id; + uint32 icon; + char item_name[64]; +}; + +//len = 320 +enum { //bandolier item positions + bandolierMainHand = 0, + bandolierOffHand, + bandolierRange, + bandolierAmmo +}; +struct Bandolier_Struct { + char name[1]; // Variable Length + BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS]; +}; + +struct Bandolier_Struct_Old { + char name[32]; + BandolierItem_Struct items[MAX_PLAYER_BANDOLIER_ITEMS]; +}; + +struct PotionBelt_Struct { + BandolierItem_Struct items[MAX_POTIONS_IN_BELT]; +}; + +struct GroupLeadershipAA_Struct { + union { + struct { + uint32 groupAAMarkNPC; + uint32 groupAANPCHealth; + uint32 groupAADelegateMainAssist; + uint32 groupAADelegateMarkNPC; + uint32 groupAA4; + uint32 groupAA5; + uint32 groupAAInspectBuffs; + uint32 groupAA7; + uint32 groupAASpellAwareness; + uint32 groupAAOffenseEnhancement; + uint32 groupAAManaEnhancement; + uint32 groupAAHealthEnhancement; + uint32 groupAAHealthRegeneration; + uint32 groupAAFindPathToPC; + uint32 groupAAHealthOfTargetsTarget; + uint32 groupAA15; + }; + uint32 ranks[MAX_GROUP_LEADERSHIP_AA_ARRAY]; + }; +}; + +struct RaidLeadershipAA_Struct { + union { + struct { + uint32 raidAAMarkNPC; + uint32 raidAANPCHealth; + uint32 raidAADelegateMainAssist; + uint32 raidAADelegateMarkNPC; + uint32 raidAA4; + uint32 raidAA5; + uint32 raidAA6; + uint32 raidAASpellAwareness; + uint32 raidAAOffenseEnhancement; + uint32 raidAAManaEnhancement; + uint32 raidAAHealthEnhancement; + uint32 raidAAHealthRegeneration; + uint32 raidAAFindPathToPC; + uint32 raidAAHealthOfTargetsTarget; + uint32 raidAA14; + uint32 raidAA15; + }; + uint32 ranks[MAX_RAID_LEADERSHIP_AA_ARRAY]; + }; +}; + +struct LeadershipAA_Struct { + union { + struct { + GroupLeadershipAA_Struct group; + RaidLeadershipAA_Struct raid; + }; + uint32 ranks[MAX_LEADERSHIP_AA_ARRAY]; + }; +}; + + /** +* A bind point. +* Size: 20 Octets +*/ +struct BindStruct { + /*000*/ uint32 zoneId; + /*004*/ float x; + /*008*/ float y; + /*012*/ float z; + /*016*/ float heading; + /*020*/ +}; + + +// Player Profile - Variable Length as of Oct 12 2012 patch +struct PlayerProfile_Struct +{ +/*00000*/ uint32 checksum; // +/*00004*/ uint32 checksum_size; // Value = ( Packet Size - 9 ) +/*00008*/ uint8 checksum_byte; // +/*00009*/ uint8 unknown_rof1[3]; // +/*00012*/ uint32 unknown_rof2; // +/*00016*/ uint8 gender; // Player Gender - 0 Male, 1 Female +/*00017*/ uint32 race; // Player race +/*00021*/ uint8 class_; // Player class +/*00022*/ uint8 level; // Level of player +/*00023*/ uint8 level1; // Level of player (again?) +/*00024*/ uint32 bind_count; // Seen 5 +/*00028*/ BindStruct binds[5]; // Bind points (primary is first) 5 fields = 100 bytes +/*00128*/ uint32 deity; // deity +/*00132*/ uint32 unknown_rof3; // Maybe Drakkin Heritage? +/*00136*/ uint32 unknown4_count; // Seen 10 +/*00140*/ uint32 unknown_rof4[10]; // Seen all 0s +/*00180*/ uint32 equip_count; // Seen 22 +union +{ + struct + { + /*00184*/ EquipStruct equip_helmet; // Equiptment: Helmet visual + /*00204*/ EquipStruct equip_chest; // Equiptment: Chest visual + /*00224*/ EquipStruct equip_arms; // Equiptment: Arms visual + /*00244*/ EquipStruct equip_bracers; // Equiptment: Wrist visual + /*00264*/ EquipStruct equip_hands; // Equiptment: Hands visual + /*00284*/ EquipStruct equip_legs; // Equiptment: Legs visual + /*00304*/ EquipStruct equip_feet; // Equiptment: Boots visual + /*00324*/ EquipStruct equip_primary; // Equiptment: Main visual + /*00344*/ EquipStruct equip_secondary; // Equiptment: Off visual + // Below slots are just guesses, but all 0s anyway... + /*00364*/ EquipStruct equip_charm; // Equiptment: Non-visual + /*00384*/ EquipStruct equip_ear1; // Equiptment: Non-visual + /*00404*/ EquipStruct equip_ear2; // Equiptment: Non-visual + /*00424*/ EquipStruct equip_face; // Equiptment: Non-visual + /*00444*/ EquipStruct equip_neck; // Equiptment: Non-visual + /*00464*/ EquipStruct equip_shoulder; // Equiptment: Non-visual + /*00484*/ EquipStruct equip_bracer2; // Equiptment: Non-visual + /*00504*/ EquipStruct equip_range; // Equiptment: Non-visual + /*00524*/ EquipStruct equip_ring1; // Equiptment: Non-visual + /*00544*/ EquipStruct equip_ring2; // Equiptment: Non-visual + /*00564*/ EquipStruct equip_waist; // Equiptment: Non-visual + /*00584*/ EquipStruct equip_powersource; // Equiptment: Non-visual + /*00604*/ EquipStruct equip_ammo; // Equiptment: Non-visual + } equip; + /*00184*/ EquipStruct equipment[22]; +}; +/*00624*/ uint32 equip2_count; // Seen 9 +/*00628*/ EquipStruct equipment2[9]; // Appears to be Visible slots, but all 0s +/*00808*/ uint32 tint_count; // Seen 9 +/*00812*/ Color_Struct item_tint[9]; // RR GG BB 00 +/*00848*/ uint32 tint_count2; // Seen 9 +/*00852*/ Color_Struct item_tint2[9]; // RR GG BB 00 +/*00888*/ uint8 haircolor; // Player hair color +/*00889*/ uint8 beardcolor; // Player beard color +/*00890*/ uint32 unknown_rof5; // +/*00894*/ uint8 eyecolor1; // Player left eye color +/*00895*/ uint8 eyecolor2; // Player right eye color +/*00896*/ uint8 hairstyle; // Player hair style +/*00897*/ uint8 beard; // Player beard type +/*00898*/ uint8 face; // Player face +/*00899*/ uint32 drakkin_heritage; // +/*00903*/ uint32 drakkin_tattoo; // +/*00907*/ uint32 drakkin_details; // +/*00911*/ uint8 unknown_rof6; // +/*00912*/ int8 unknown_rof7; // seen -1 +/*00913*/ uint8 unknown_rof8; // +/*00914*/ uint8 unknown_rof9; // +/*00915*/ uint8 unknown_rof10; // Seen 1 or 0 (on a female?) +/*00916*/ float height; // Seen 7.0 (barb), 5.0 (woodelf), 5.5 (halfelf) +/*00920*/ float unknown_rof11; // Seen 3.0 +/*00924*/ float unknown_rof12; // Seen 2.5 +/*00928*/ float unknown_rof13; // Seen 5.5 +/*00932*/ uint32 primary; // Seen 10528 +/*00936*/ uint32 secondary; // Seen 10006 +/*00940*/ uint32 points; // Unspent Practice points - RELOCATED??? +/*00944*/ uint32 mana; // Current mana +/*00948*/ uint32 cur_hp; // Current HP without +HP equipment +/*00952*/ uint32 STR; // Strength - 6e 00 00 00 - 110 +/*00956*/ uint32 STA; // Stamina - 73 00 00 00 - 115 +/*00960*/ uint32 CHA; // Charisma - 37 00 00 00 - 55 +/*00964*/ uint32 DEX; // Dexterity - 50 00 00 00 - 80 +/*00968*/ uint32 INT; // Intelligence - 3c 00 00 00 - 60 +/*00972*/ uint32 AGI; // Agility - 5f 00 00 00 - 95 +/*00976*/ uint32 WIS; // Wisdom - 46 00 00 00 - 70 +/*00980*/ uint32 unknown_rof14[7]; // Probably base resists? +/*01008*/ uint32 aa_count; // Seen 300 +/*01012*/ AA_Array aa_array[MAX_PP_AA_ARRAY]; // [300] 3600 bytes - AAs 12 bytes each +/*04612*/ uint32 skill_count; // Seen 100 +/*04616*/ uint32 skills[MAX_PP_SKILL]; // [100] 400 bytes - List of skills +/*05016*/ uint32 unknown15_count; // Seen 25 +/*05020*/ uint32 unknown_rof15[25]; // Most are 255 or 0 +/*05120*/ uint32 discipline_count; // Seen 200 +/*05124*/ Disciplines_Struct disciplines; // [200] 800 bytes Known disciplines +/*05924*/ uint32 timestamp_count; // Seen 20 +/*05928*/ uint32 timestamps[20]; // Unknown Unix Timestamps - maybe recast related? +/*06008*/ uint32 recast_count; // Seen 20 +/*06012*/ uint32 recastTimers[MAX_RECAST_TYPES];// [20] 80 bytes - Timers (UNIX Time of last use) +/*06092*/ uint32 timestamp2_count; // Seen 100 +/*06096*/ uint32 timestamps2[100]; // Unknown Unix Timestamps - maybe Skill related? +/*06496*/ uint32 spell_book_count; // Seen 720 +/*06500*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes] +/*09380*/ uint32 mem_spell_count; // Seen 16 +/*09384*/ int32 mem_spells[MAX_PP_MEMSPELL]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s +/*09448*/ uint32 unknown16_count; // Seen 13 +/*09452*/ uint32 unknown_rof16[13]; // Possibly spell or buff related +/*09504*/ uint8 unknown_rof17; // Seen 0 or 8 +/*09505*/ uint32 buff_count; // Seen 42 +/*09509*/ SpellBuff_Struct buffs[BUFF_COUNT]; // [42] 3360 bytes - Buffs currently on the player (42 Max) - (Each Size 80) +/*12869*/ uint32 platinum; // Platinum Pieces on player +/*12873*/ uint32 gold; // Gold Pieces on player +/*12877*/ uint32 silver; // Silver Pieces on player +/*12881*/ uint32 copper; // Copper Pieces on player +/*12885*/ uint32 platinum_cursor; // Platinum Pieces on cursor +/*12889*/ uint32 gold_cursor; // Gold Pieces on cursor +/*12893*/ uint32 silver_cursor; // Silver Pieces on cursor +/*12897*/ uint32 copper_cursor; // Copper Pieces on cursor +/*12901*/ uint32 intoxication; // Alcohol level (in ticks till sober?) - Position Guessed +/*12905*/ uint32 toxicity; // Potion Toxicity (15=too toxic, each potion adds 3) - Position Guessed +/*12909*/ uint32 unknown_rof19; // +/*12913*/ uint32 thirst_level; // Drink (ticks till next drink) - Position Guessed +/*12917*/ uint32 hunger_level; // Food (ticks till next eat) - Position Guessed +/*12921*/ uint32 aapoints_spent; // Number of spent AA points +/*12925*/ uint32 aapoint_count; // Seen 5 - Unsure what this is exactly +/*12929*/ uint32 aapoints_assigned; // Number of Assigned AA points - Seen 206 (total of the 4 fields below) +/*12933*/ uint32 aa_spent_general; // Seen 63 +/*12937*/ uint32 aa_spent_archetype; // Seen 40 +/*12941*/ uint32 aa_spent_class; // Seen 103 +/*12945*/ uint32 aa_spent_special; // Seen 0 +/*12949*/ uint32 aapoints; // Unspent AA points - Seen 1 +/*12953*/ uint16 unknown_rof20; // +/*12955*/ uint32 bandolier_count; // Seen 20 +/*12959*/ Bandolier_Struct bandoliers[MAX_PLAYER_BANDOLIER]; // [20] 740 bytes (Variable Name Sizes) - bandolier contents +/*13699*/ uint32 potionbelt_count; // Seen 5 +/*13703*/ PotionBelt_Struct potionbelt; // [5] 45 bytes potion belt - (Variable Name Sizes) +/*13748*/ int32 unknown_rof21; // Seen -1 +/*13752*/ int32 hp_total; // Guessed - Seen 20 on level 1 new mage +/*13756*/ int32 endurance_total; // Guessed - Seen 20 on level 1 new mage +/*13760*/ int32 mana_total; // Guessed - Only seen on casters so far - Matches above field if caster +/*13764*/ uint32 unknown_rof22[12]; // Same for all seen PPs - 48 bytes: +/* +19 00 00 00 19 00 00 00 19 00 00 00 0f 00 00 00 +0f 00 00 00 0f 00 00 00 0f 00 00 00 1f 85 eb 3e +33 33 33 3f 08 00 00 00 02 00 00 00 01 00 00 00 +*/ +/*13812*/ uint32 unknown_rof23; // Seen 5, 19, and 20 in examples +/*13816*/ uint32 unknown_rof24[4]; // +/*13832*/ uint32 unknown_rof25[2]; // Seen random numbers from 0 to 2165037 +/*13840*/ uint32 unknown_rof26; // Seen 106 +//END SUB-STRUCT used for shrouding. +/*13844*/ uint32 name_str_len; // Seen 64 +/*13848*/ char name[64]; // Name of player - 19960 for Live 1180 difference +/*13912*/ uint32 last_name_str_len; // Seen 32 +/*13916*/ char last_name[32]; // Last name of player +/*13948*/ uint32 birthday; // character birthday +/*13952*/ uint32 account_startdate; // Date the Account was started +/*13956*/ uint32 lastlogin; // character last save time +/*13960*/ uint32 timePlayedMin; // time character played +/*13964*/ uint32 timeentitledonaccount; +/*13968*/ uint32 expansions; // Bitmask for expansions ff 7f 00 00 - SoD +/*13972*/ uint32 language_count; // Seen 32 +/*13976*/ uint8 languages[MAX_PP_LANGUAGE]; // [32] 32 bytes - List of languages +/*14008*/ uint16 zone_id; // see zones.h +/*14010*/ uint16 zoneInstance; // Instance id +/*14012*/ float y; // Players y position (NOT positive about this switch) +/*14016*/ float x; // Players x position +/*14020*/ float z; // Players z position +/*14024*/ float heading; // Players heading +/*14028*/ uint32 air_remaining; // Air supply (seconds) +/*14032*/ int32 unknown_rof28; // Seen -1 +/*14036*/ uint8 unknown_rof29[10]; // +/*14046*/ uint32 unknown_rof30; // Random large number or 0 +/*14050*/ uint32 unknown_rof31; // +/*14054*/ uint32 unknown32_count; // Seen 5 +/*14058*/ uint8 unknown_rof32[29]; // +/*14087*/ uint32 unknown33_count; // Seen 32 for melee/hybrid and 21 for druid, 34 for mage +/*14091*/ uint32 unknown_rof33[64]; // Struct contains 2 ints, so double 32 count (Variable Sized) +// Position Varies after this point - Really starts varying at Bandolier names, but if no names set it starts here +/*00000*/ int32 unknown_rof34; // Seen -1 +/*00000*/ int32 unknown_rof35; // Seen -1 +/*00000*/ uint8 unknown_rof36[18]; // +/*00000*/ uint32 unknown37_count; // Seen 5 +/*00000*/ int32 unknown_rof37[10]; // Alternates -1 and 0 - Struct contains 2 ints +/*00000*/ uint32 unknown38_count; // Seen 10 +/*00000*/ int32 unknown_rof38[20]; // Alternates -1 and 0 - Struct contains 2 ints +/*00000*/ uint8 unknown_rof39[137]; // +/*00000*/ float unknown_rof40; // Seen 1.0 +/*00000*/ uint32 unknown_rof41[9]; // +/*00000*/ uint32 unknown_rof42; // Seen 0 or 1 +/*00000*/ uint32 unknown_string1_count; // Seen 64 +/*00000*/ char unknown_string1[64]; // +/*00000*/ uint8 unknown_rof43[30]; // +/*00000*/ uint32 unknown_string2_count; // Seen 64 +/*00000*/ char unknown_string2[64]; // +/*00000*/ uint32 unknown_string3_count; // Seen 64 +/*00000*/ char unknown_string3[64]; // +/*00000*/ uint32 unknown_rof44; // Seen 0 or 50 +/*00000*/ uint8 unknown_rof45[663]; // +/*00000*/ uint32 char_id; // Guessed based on char creation date and values +/*00000*/ uint8 unknown_rof46; // Seen 0 or 1 +/*00000*/ uint32 unknown_rof47; // Seen 6 +/*00000*/ uint32 unknown_rof48[13]; // Seen all 0s or some mix of ints and float? +/*00000*/ uint32 unknown_rof49; // Seen 64 +/*00000*/ uint8 unknown_rof50[256]; // Seen mostly 0s, but one example had a 2 in the middle +/*00000*/ uint32 unknown_rof51; // Seen 100 or 0 +/*00000*/ uint8 unknown_rof52[82]; // +/*00000*/ uint32 unknown_rof53; // Seen 50 + +uint8 unknown_rof54[1325]; // Unknown Section + +// Bottom of Struct: +/*00000*/ uint8 groupAutoconsent; // 0=off, 1=on +/*00000*/ uint8 raidAutoconsent; // 0=off, 1=on +/*00000*/ uint8 guildAutoconsent; // 0=off, 1=on +/*00000*/ uint8 unknown_rof55; // Seen 1 +/*00000*/ uint32 level3; // SoF looks at the level here to determine how many leadership AA you can bank. +/*00000*/ uint32 showhelm; // 0=no, 1=yes +/*00000*/ uint32 RestTimer; +/*00000*/ uint8 unknown_rof56; +/*00000*/ uint32 unknown_rof57; // Seen 49 +/*00000*/ uint8 unknown_rof58[1045]; // Seen all 0s + +/* +///////////////////// - Haven't identified the below fields in the PP yet +uint8 pvp; // 1=pvp, 0=not pvp +uint8 anon; // 2=roleplay, 1=anon, 0=not anon +uint8 gm; // 0=no, 1=yes (guessing!) +uint32 guild_id; // guildid +uint8 guildrank; // 0=member, 1=officer, 2=guildleader -1=no guild +uint32 guildbanker; +uint32 available_slots; +uint32 endurance; // Current endurance +uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 bytes Each * 16 = 64 bytes +uint32 abilitySlotRefresh; +/////////////////////// + +uint32 platinum_bank; // Platinum Pieces in Bank +uint32 gold_bank; // Gold Pieces in Bank +uint32 silver_bank; // Silver Pieces in Bank +uint32 copper_bank; // Copper Pieces in Bank +uint32 platinum_shared; // Shared platinum pieces + +uint32 autosplit; // 0 = off, 1 = on + +char groupMembers[MAX_GROUP_MEMBERS][64];// 384 all the members in group, including self +char groupLeader[64]; // Leader of the group ? +uint32 entityid; + +uint32 leadAAActive; // 0 = leader AA off, 1 = leader AA on +int32 ldon_points_guk; // Earned GUK points +int32 ldon_points_mir; // Earned MIR points +int32 ldon_points_mmc; // Earned MMC points +int32 ldon_points_ruj; // Earned RUJ points +int32 ldon_points_tak; // Earned TAK points +int32 ldon_points_available;// Available LDON points +float tribute_time_remaining;// Time remaining on tribute (millisecs) +uint32 career_tribute_points;// Total favor points for this char +uint32 tribute_points; // Current tribute points +uint32 tribute_active; // 0 = off, 1=on +Tribute_Struct tributes[MAX_PLAYER_TRIBUTES]; // [40] Current tribute loadout +double group_leadership_exp; // Current group lead exp points +double raid_leadership_exp; // Current raid lead AA exp points +uint32 group_leadership_points; // Unspent group lead AA points +uint32 raid_leadership_points; // Unspent raid lead AA points +LeadershipAA_Struct leader_abilities; // [128]Leader AA ranks 19332 + +uint32 PVPKills; +uint32 PVPDeaths; +uint32 PVPCurrentPoints; +uint32 PVPCareerPoints; +uint32 PVPBestKillStreak; +uint32 PVPWorstDeathStreak; +uint32 PVPCurrentKillStreak; +PVPStatsEntry_Struct PVPLastKill; // size 88 +PVPStatsEntry_Struct PVPLastDeath; // size 88 +uint32 PVPNumberOfKillsInLast24Hours; +PVPStatsEntry_Struct PVPRecentKills[50]; // size 4400 - 88 each +uint32 expAA; // Exp earned in current AA point +uint32 currentRadCrystals; // Current count of radiant crystals +uint32 careerRadCrystals; // Total count of radiant crystals ever +uint32 currentEbonCrystals; // Current count of ebon crystals +uint32 careerEbonCrystals; // Total count of ebon crystals ever +*/ + +}; + +/* +** Client Target Struct +** Length: 2 Bytes +** OpCode: 6221 +*/ +struct ClientTarget_Struct { +/*000*/ uint32 new_target; // Target ID +}; + +/* +** Target Rejection Struct +** Length: 12 Bytes +** OpCode: OP_TargetReject +*/ +struct TargetReject_Struct { +/*00*/ uint8 unknown00[12]; +}; + +struct PetCommand_Struct { +/*00*/ uint32 command; +/*04*/ uint32 unknown04; +/*08*/ uint32 unknown08; +}; + +/* +** Delete Spawn +** Length: 5 Bytes +** OpCode: OP_DeleteSpawn +*/ +struct DeleteSpawn_Struct +{ +/*00*/ uint32 spawn_id; // Spawn ID to delete +/*04*/ uint8 unknown04; // Seen 1 +/*05*/ +}; + +/* +** Channel Message received or sent +** Length: 144 Bytes + Variable Length + 1 +** OpCode: OP_ChannelMessage +** +*/ +struct ChannelMessage_Struct +{ +/*000*/ char targetname[64]; // Tell recipient +/*064*/ char sender[64]; // The senders name (len might be wrong) +/*128*/ uint32 language; // Language +/*132*/ uint32 chan_num; // Channel +/*136*/ uint32 cm_unknown4[2]; // ***Placeholder +/*144*/ uint32 skill_in_language; // The players skill in this language? might be wrong +/*148*/ char message[0]; // Variable length message +}; + +/* +** Special Message +** Length: 4 Bytes + Variable Text Length + 1 +** OpCode: OP_SpecialMesg +** +*/ +/* + Theres something wrong with this... example live packet: +Server->Client: [ Opcode: OP_SpecialMesg (0x0fab) Size: 244 ] + 0: 01 02 00 0A 00 00 00 09 - 05 00 00 42 61 72 73 74 | ...........Barst + 16: 72 65 20 53 6F 6E 67 77 - 65 61 76 65 72 00 7C F9 | re Songweaver.|. + 32: FF FF 84 FF FF FF 03 00 - 00 00 47 72 65 65 74 69 | ..........Greeti + +*/ +struct SpecialMesg_Struct +{ +/*00*/ char header[3]; // 04 04 00 <-- for #emote style msg +/*03*/ uint32 msg_type; // Color of text (see MT_*** below) +/*07*/ uint32 target_spawn_id; // Who is it being said to? +/*11*/ char sayer[1]; // Who is the source of the info - Was 1 +/*12*/ uint8 unknown12[12]; +/*24*/ char message[128]; // What is being said? - was 128 +}; + +/* +** When somebody changes what they're wearing +** or give a pet a weapon (model changes) +** Length: 19 Bytes +*/ +struct WearChange_Struct{ +/*000*/ uint16 spawn_id; +/*002*/ uint32 material; +/*006*/ uint32 unknown06; +/*010*/ uint32 elite_material; // 1 for Drakkin Elite Material +/*014*/ uint32 hero_forge_model; // New to VoA +/*018*/ uint32 unknown18; // New to RoF2 +/*022*/ Color_Struct color; +/*026*/ uint8 wear_slot_id; +/*027*/ +}; + +/* +** Type: Bind Wound Structure +** Length: 8 Bytes +*/ +//Fixed for 7-14-04 patch +struct BindWound_Struct +{ +/*000*/ uint16 to; // TargetID +/*002*/ uint16 unknown2; // ***Placeholder +/*004*/ uint16 type; +/*006*/ uint16 unknown6; +}; + + +/* +** Type: Zone Change Request (before hand) +** Length: 88 bytes +** OpCode: a320 +*/ + +struct ZoneChange_Struct { +/*000*/ char char_name[64]; // Character Name +/*064*/ uint16 zoneID; +/*066*/ uint16 instanceID; +/*068*/ uint32 Unknown068; +/*072*/ uint32 Unknown072; +/*076*/ float y; +/*080*/ float x; +/*084*/ float z; +/*088*/ uint32 zone_reason; //0x0A == death, I think +/*092*/ int32 success; // =0 client->server, =1 server->client, -X=specific error +/*096*/ uint32 Unknown096; // Not sure the extra 4 bytes goes here or earlier in the struct. +/*100*/ +}; + +struct RequestClientZoneChange_Struct { +/*000*/ uint16 zone_id; +/*002*/ uint16 instance_id; +/*004*/ uint32 unknown004; +/*008*/ float y; +/*012*/ float x; +/*016*/ float z; +/*020*/ float heading; +/*024*/ uint32 type; //unknown... values +/*032*/ uint8 unknown032[144]; +/*172*/ uint32 unknown172; +/*176*/ +}; + +struct Animation_Struct { +/*00*/ uint16 spawnid; +/*02*/ uint8 value; +/*03*/ uint8 action; +/*04*/ +}; + +// solar: this is what causes the caster to animate and the target to +// get the particle effects around them when a spell is cast +// also causes a buff icon +struct Action_Struct +{ +/*00*/ uint16 target; // id of target +/*02*/ uint16 source; // id of caster +/*04*/ uint16 level; // level of caster - Seen 0 +/*06*/ uint32 unknown06; +/*10*/ float instrument_mod; +/*14*/ uint32 bard_focus_id; // seen 0 +/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again +/*22*/ uint32 unknown22; +/*26*/ uint8 type; +/*27*/ uint32 damage; +/*31*/ uint16 unknown31; +/*33*/ uint32 spell; // spell id being cast +/*37*/ uint8 level2; // level of caster again? Or maybe the castee +/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time? +/*39*/ +}; + +// 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 ActionAlt_Struct +{ +/*00*/ uint16 target; // id of target +/*02*/ uint16 source; // id of caster +/*04*/ uint16 level; // level of caster - Seen 0 +/*06*/ uint32 unknown06; +/*10*/ float instrument_mod; +/*14*/ uint32 bard_focus_id; // seen 0 +/*18*/ float knockback_angle; //seems to go from 0-512 then it rolls over again +/*22*/ uint32 unknown22; +/*26*/ uint8 type; +/*27*/ uint32 damage; +/*31*/ uint16 unknown31; +/*33*/ uint32 spell; // spell id being cast +/*37*/ uint8 level2; // level of caster again? Or maybe the castee +/*38*/ uint8 effect_flag; // if this is 4, the effect is valid: or if two are sent at the same time? +/*39*/ uint32 unknown39; // New field to Underfoot - Seen 14 +/*43*/ uint8 unknown43; // New field to Underfoot - Seen 0 +/*44*/ uint8 unknown44; // New field to Underfoot - Seen 17 +/*45*/ uint8 unknown45; // New field to Underfoot - Seen 0 +/*46*/ int32 unknown46; // New field to Underfoot - Seen -1 +/*50*/ uint32 unknown50; // New field to Underfoot - Seen 0 +/*54*/ uint16 unknown54; // New field to Underfoot - Seen 0 +/*56*/ +}; + +// solar: this is what prints the You have been struck. and the regular +// melee messages like You try to pierce, etc. It's basically the melee +// and spell damage message +struct CombatDamage_Struct +{ +/* 00 */ uint16 target; +/* 02 */ uint16 source; +/* 04 */ uint8 type; //slashing, etc. 231 (0xE7) for spells +/* 05 */ uint32 spellid; +/* 09 */ int32 damage; +/* 13 */ float unknown11; // cd cc cc 3d +/* 17 */ float sequence; // see above notes in Action_Struct +/* 21 */ uint8 unknown19[9]; // was [9] +/* 30 */ +}; + + +/* +** Consider Struct +** Length: 20 Bytes +*/ +struct Consider_Struct{ +/*000*/ uint32 playerid; // PlayerID +/*004*/ uint32 targetid; // TargetID +/*008*/ uint32 faction; // Faction +/*012*/ uint32 level; // Level +/*016*/ uint8 pvpcon; // Pvp con flag 0/1 +/*017*/ uint8 unknown017[3]; // +/*020*/ +}; + +/* +** Spawn Death Blow +** Length: 32 Bytes +** OpCode: 0114 +*/ +struct Death_Struct +{ +/*000*/ uint32 spawn_id; +/*004*/ uint32 killer_id; +/*008*/ uint32 corpseid; // was corpseid +/*012*/ uint32 attack_skill; // was type +/*016*/ uint32 spell_id; +/*020*/ uint32 bindzoneid; //bindzoneid? +/*024*/ uint32 damage; +/*028*/ uint32 unknown028; +}; + +struct BecomeCorpse_Struct { + uint32 spawn_id; + float y; + float x; + float z; +}; + +struct ZonePlayerToBind_Struct { +/*000*/ uint16 bind_zone_id; +/*002*/ uint16 bind_instance_id; +/*004*/ float x; +/*008*/ float y; +/*012*/ float z; +/*016*/ float heading; +/*020*/ char zone_name[1]; // Or "Bind Location" +/*000*/ uint8 unknown021; // Seen 1 - Maybe 0 would be to force a rezone and 1 is just respawn +/*000*/ uint32 unknown022; // Seen 32 or 59 +/*000*/ uint32 unknown023; // Seen 0 +/*000*/ uint32 unknown024; // Seen 21 or 43 +}; + +struct ZonePlayerToBindHeader_Struct +{ + /*000*/ uint16 bind_zone_id; + /*002*/ uint16 bind_instance_id; + /*004*/ float x; + /*008*/ float y; + /*012*/ float z; + /*016*/ float heading; + /*020*/ char zone_name[1]; // Or "Bind Location" +}; + +struct ZonePlayerToBindFooter_Struct +{ + /*000*/ uint8 unknown021; // Seen 1 - Maybe 0 would be to force a rezone and 1 is just respawn + /*000*/ uint32 unknown022; // Seen 32 or 59 + /*000*/ uint32 unknown023; // Seen 0 + /*000*/ uint32 unknown024; // Seen 21 or 43 +}; + +typedef struct { +/*000*/ uint32 bind_number; // Number of this bind in the iteration +/*004*/ uint32 bind_zone_id; // ID of the zone for this bind point or resurect point +/*008*/ float x; // X loc for this bind point +/*012*/ float y; // Y loc for this bind point +/*016*/ float z; // Z loc for this bind point +/*020*/ float heading; // Heading for this bind point +/*024*/ char bind_zone_name[1]; // Or "Bind Location" or "Resurrect" +/*000*/ uint8 validity; // 0 = valid choice, 1 = not a valid choice at this time (resurrection) +} RespawnOptions_Struct; + +struct RespawnWindow_Struct { +/*000*/ uint32 unknown000; // Seen 0 +/*004*/ uint32 time_remaining; // Total time before respawn in milliseconds +/*008*/ uint32 unknown008; // Seen 0 +/*012*/ uint32 total_binds; // Total Bind Point Options? - Seen 2 +/*016*/ RespawnOptions_Struct bind_points; +// First bind point is "Bind Location" and the last one is "Ressurect" +}; + + +/* +** Spawn position update - Size: 22 +** Struct sent from server->client to update position of +** another spawn's position update in zone (whether NPC or PC) +** +*/ +struct PlayerPositionUpdateServer_Struct +{ + uint16 spawn_id; + uint16 spawnId2; + signed padding0004:12; + signed y_pos:19; // y coord + unsigned padding:1; + signed delta_z:13; // change in z + signed delta_x:13; // change in x + signed padding0008:6; + signed x_pos:19; // x coord + unsigned heading:12; // heading + signed padding0016:1; + signed delta_heading:10; // change in heading + signed z_pos:19; // z coord + signed padding0020:3; + signed animation:10; // animation + signed delta_y:13; // change in y + signed padding0024:9; +}; + +/* +** Player position update - Size: 40 +** Struct sent from client->server to update +** player position on server +** +*/ +struct PlayerPositionUpdateClient_Struct +{ + uint16 sequence; // increments one each packet - Verified + uint16 spawn_id; // Player's spawn id + uint8 unknown0004[6]; // ***Placeholder + float delta_x; // Change in x + unsigned heading:12; // Directional heading + unsigned padding0040:20; // ***Placeholder + float x_pos; // x coord (2nd loc value) + float delta_z; // Change in z + float z_pos; // z coord (3rd loc value) + float y_pos; // y coord (1st loc value) + unsigned animation:10; // ***Placeholder + unsigned padding0024:22; // animation + float delta_y; // Change in y + signed delta_heading:10; // change in heading + unsigned padding0041:22; // ***Placeholder +}; + +/* +** Spawn HP Update +** Length: 10 Bytes +** OpCode: OP_HPUpdate +*/ +struct SpawnHPUpdate_Struct +{ +/*00*/ int16 spawn_id; +/*02*/ uint32 cur_hp; +/*06*/ int32 max_hp; +/*10*/ +}; + +/* +** SendExpZonein +** Length: 152 Bytes +** OpCode: OP_SendExpZonein +*/ +struct SendExpZonein_Struct +{ +/*0000*/ uint16 spawn_id; // ID of the spawn +/*0002*/ uint16 type; // Values associated with the type +/*0004*/ uint32 parameter; // Type of data sent +/*0008*/ uint32 exp; // Current experience ratio from 0 to 330 +/*0012*/ uint32 expAA; +/*0016*/ uint8 unknown0016[4]; +/*0020*/ char name[64]; +/*0084*/ char last_name[64]; +/*00148*/ uint32 unknown132; +/*00152*/ +}; + +/* +** SendExpZonein +** Length: 0 Bytes +** OpCode: OP_SendExpZonein +*/ +//struct SendExpZonein_Struct {}; + +struct SpawnHPUpdate_Struct2 +{ +/*01*/ int16 spawn_id; +/*00*/ uint8 hp; +}; +/* +** Stamina +** Length: 8 Bytes +** OpCode: 5721 +*/ +struct Stamina_Struct { +/*00*/ uint32 food; // (low more hungry 127-0) +/*02*/ uint32 water; // (low more thirsty 127-0) +}; + +/* +** Level Update +** Length: 12 Bytes +*/ +struct LevelUpdate_Struct +{ +/*00*/ uint32 level; // New level +/*04*/ uint32 level_old; // Old level +/*08*/ uint32 exp; // Current Experience +}; + +/* +** Experience Update +** Length: 14 Bytes +** OpCode: 9921 +*/ +struct ExpUpdate_Struct +{ +/*0000*/ uint32 exp; // Current experience ratio from 0 to 330 +/*0004*/ uint32 aaxp; // @BP ?? +}; + +/* +** Item Packet Struct - Works on a variety of opcodes +** Packet Types: See ItemPacketType enum +** +*/ +enum ItemPacketType +{ + ItemPacketViewLink = 0x00, + ItemPacketTradeView = 0x65, + ItemPacketLoot = 0x66, + ItemPacketTrade = 0x67, + ItemPacketCharInventory = 0x69, + ItemPacketSummonItem = 0x6A, + ItemPacketTributeItem = 0x6C, + ItemPacketMerchant = 0x64, + ItemPacketWorldContainer = 0x6B +}; +struct ItemPacket_Struct +{ +/*00*/ ItemPacketType PacketType; +/*04*/ char SerializedItem[1]; //was 1 +/*xx*/ +}; + +struct BulkItemPacket_Struct +{ +/*00*/ char SerializedItem[0]; +/*xx*/ +}; + +struct Consume_Struct +{ +/*000*/ ItemSlotStruct slot; +/*012*/ uint32 auto_consumed; // 0xffffffff when auto eating e7030000 when right click +/*016*/ uint32 type; // 0x01=Food 0x02=Water +/*020*/ uint32 c_unknown1; // Seen 2 +/*024*/ +}; + +struct ItemNamePacket_Struct { +/*000*/ uint32 item_id; +/*004*/ uint32 unkown004; +/*008*/ char name[64]; +/*072*/ +}; + +// Length: 16 +struct ItemProperties_Struct_Old { + +/*000*/ uint8 unknown01[2]; +/*002*/ uint8 charges; +/*003*/ uint8 unknown02[13]; +/*016*/ +}; + +// Length: 8 +struct ItemProperties_Struct { + +/*000*/ uint8 unknown01[4]; +/*004*/ uint8 charges; +/*005*/ uint8 unknown02[3]; +/*008*/ +}; + +struct DeleteItem_Struct { +/*0000*/ ItemSlotStruct from_slot; +/*0012*/ ItemSlotStruct to_slot; +/*0024*/ uint32 number_in_stack; +/*0028*/ +}; + +struct MoveItem_Struct { +/*0000*/ ItemSlotStruct from_slot; +/*0012*/ ItemSlotStruct to_slot; +/*0024*/ uint32 number_in_stack; +/*0028*/ +}; + +// +// from_slot/to_slot +// -1 - destroy +// 0 - cursor +// 1 - inventory +// 2 - bank +// 3 - trade +// 4 - shared bank +// +// cointype +// 0 - copeer +// 1 - silver +// 2 - gold +// 3 - platinum +// +static const uint32 COINTYPE_PP = 3; +static const uint32 COINTYPE_GP = 2; +static const uint32 COINTYPE_SP = 1; +static const uint32 COINTYPE_CP = 0; + +struct MoveCoin_Struct +{ + int32 from_slot; + int32 to_slot; + int32 cointype1; + int32 cointype2; + int32 amount; +}; +struct TradeCoin_Struct{ + uint32 trader; + uint8 slot; + uint16 unknown5; + uint8 unknown7; + uint32 amount; +}; +struct TradeMoneyUpdate_Struct{ + uint32 trader; + uint32 type; + uint32 amount; +}; +/* +** Surname struct +** Size: 100 bytes +*/ +struct Surname_Struct +{ +/*0000*/ char name[64]; +/*0064*/ uint32 unknown0064; +/*0068*/ char lastname[32]; +/*0100*/ +}; + +struct GuildsListEntry_Struct { + char name[64]; +}; + +struct GuildsList_Struct { + uint8 head[64]; // First on guild list seems to be empty... + GuildsListEntry_Struct Guilds[MAX_NUMBER_GUILDS]; +}; + +struct GuildUpdate_Struct { + uint32 guildID; + GuildsListEntry_Struct entry; +}; + +/* +** Money Loot +** Length: 22 Bytes +** OpCode: 5020 +*/ +struct moneyOnCorpseStruct { +/*0000*/ uint8 response; // 0 = someone else is, 1 = OK, 2 = not at this time +/*0001*/ uint8 unknown1; // = 0x5a +/*0002*/ uint8 unknown2; // = 0x40 +/*0003*/ uint8 unknown3; // = 0 +/*0004*/ uint32 platinum; // Platinum Pieces +/*0008*/ uint32 gold; // Gold Pieces + +/*0012*/ uint32 silver; // Silver Pieces +/*0016*/ uint32 copper; // Copper Pieces +}; + +struct LootingItem_Struct { +/*000*/ uint32 lootee; +/*004*/ uint32 looter; +/*008*/ uint16 slot_id; +/*010*/ uint16 unknown10; +/*012*/ uint32 auto_loot; +/*016*/ uint32 unknown16; +/*020*/ +}; + +struct GuildManageStatus_Struct{ + uint32 guildid; + uint32 oldrank; + uint32 newrank; + char name[64]; +}; +// Guild invite, remove +struct GuildJoin_Struct{ +/*000*/ uint32 guild_id; +/*004*/ uint32 unknown04; +/*008*/ uint32 level; +/*012*/ uint32 class_; +/*016*/ uint32 rank;//0 member, 1 officer, 2 leader +/*020*/ uint32 zoneid; +/*024*/ uint32 unknown24; +/*028*/ char name[64]; +/*092*/ +}; +struct GuildInviteAccept_Struct { + char inviter[64]; + char newmember[64]; + uint32 response; + uint32 guildeqid; +}; +struct GuildManageRemove_Struct { + uint32 guildeqid; + char member[64]; +}; +struct GuildCommand_Struct { +/*000*/ char othername[64]; +/*064*/ char myname[64]; +/*128*/ uint16 guildeqid; +/*130*/ uint8 unknown[2]; // for guildinvite all 0's, for remove 0=0x56, 2=0x02 +/*132*/ uint32 officer; +/*136*/ uint32 unknown136; // New in RoF2 +/*140*/ +}; + +// Opcode OP_GMZoneRequest +// Size = 88 bytes +struct GMZoneRequest_Struct { +/*0000*/ char charname[64]; +/*0064*/ uint32 zone_id; +/*0068*/ float x; +/*0072*/ float y; +/*0076*/ float z; +/*0080*/ char unknown0080[4]; +/*0084*/ uint32 success; // 0 if command failed, 1 if succeeded? +/*0088*/ +// /*072*/ int8 success; // =0 client->server, =1 server->client, -X=specific error +// /*073*/ uint8 unknown0073[3]; // =0 ok, =ffffff error +}; + +struct GMSummon_Struct { +/* 0*/ char charname[64]; +/* 30*/ char gmname[64]; +/* 60*/ uint32 success; +/* 61*/ uint32 zoneID; +/*92*/ int32 y; +/*96*/ int32 x; +/*100*/ int32 z; +/*104*/ uint32 unknown2; // E0 E0 56 00 +}; + +struct GMGoto_Struct { // x,y is swapped as compared to summon and makes sense as own packet +/* 0*/ char charname[64]; + +/* 64*/ char gmname[64]; +/* 128*/ uint32 success; +/* 132*/ uint32 zoneID; + +/*136*/ int32 y; +/*140*/ int32 x; +/*144*/ int32 z; +/*148*/ uint32 unknown2; // E0 E0 56 00 +}; + +struct GMLastName_Struct { +/*000*/ char name[64]; +/*064*/ char gmname[64]; +/*128*/ char lastname[64]; +/*192*/ uint16 unknown[4]; // 0x00, 0x00, 0x01, 0x00 = Update the clients +/*200*/ uint32 unknown200[8]; +/*232*/ +}; + +struct OnLevelMessage_Struct { +/*0000*/ uint32 Title_Count; +/*0000*/ char Title[128]; +/*0000*/ uint32 Text_Count; +/*0000*/ char Text[4096]; +/*0000*/ uint32 ButtonName0_Count; +/*0000*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively +/*0000*/ uint32 ButtonName1_Count; +/*0000*/ char ButtonName1[25]; +/*0000*/ uint8 Buttons; +/*0000*/ uint8 Unknown4275; // Something to do with audio controls +/*0000*/ uint32 Duration; +/*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button +/*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button +/*0000*/ uint32 Unknown4288; +/*0000*/ uint8 Unknown4276; +/*0000*/ uint8 Unknown4277; +/*0000*/ +}; + +//Combat Abilities +struct CombatAbility_Struct { + uint32 m_target; //the ID of the target mob + uint32 m_atk; + uint32 m_skill; +}; + +//Instill Doubt +struct Instill_Doubt_Struct { + uint8 i_id; + uint8 ia_unknown; + uint8 ib_unknown; + uint8 ic_unknown; + uint8 i_atk; + + uint8 id_unknown; + uint8 ie_unknown; + uint8 if_unknown; + uint8 i_type; + uint8 ig_unknown; + uint8 ih_unknown; + uint8 ii_unknown; +}; + +struct GiveItem_Struct { + uint16 to_entity; + int16 to_equipSlot; + uint16 from_entity; + int16 from_equipSlot; +}; + +struct RandomReq_Struct { + uint32 low; + uint32 high; +}; + +/* solar: 9/23/03 reply to /random command; struct from Zaphod */ +struct RandomReply_Struct { +/* 00 */ uint32 low; +/* 04 */ uint32 high; +/* 08 */ uint32 result; +/* 12 */ char name[64]; +/* 76 */ +}; + +/* +** LFG_Appearance_Struct +** Packet sent to clients to notify when someone in zone toggles LFG flag +** Size: 8 bytes +** Used in: OP_LFGAppearance +** +*/ +struct LFG_Appearance_Struct +{ +/*0000*/ uint32 spawn_id; // ID of the client +/*0004*/ uint8 lfg; // 1=LFG, 0=Not LFG +/*0005*/ char unknown0005[3]; // +/*0008*/ +}; + + +// EverQuest Time Information: +// 72 minutes per EQ Day +// 3 minutes per EQ Hour +// 6 seconds per EQ Tick (2 minutes EQ Time) +// 3 seconds per EQ Minute + +struct TimeOfDay_Struct { + uint8 hour; + uint8 minute; + uint8 day; + uint8 month; + uint16 year; +/*0006*/ uint16 unknown0016; // Placeholder +/*0008*/ +}; + +// Darvik: shopkeeper structs +struct Merchant_Click_Struct { +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ uint32 playerid; +/*008*/ uint32 command; // 1=open, 0=cancel/close +/*012*/ float rate; // cost multiplier, dosent work anymore +/*016*/ int32 unknown01; // Seen 3 from Server or -1 from Client +/*020*/ int32 unknown02; // Seen 2592000 from Server or -1 from Client +/*024*/ +}; +/* +Unknowns: +0 is e7 from 01 to // MAYBE SLOT IN PURCHASE +1 is 03 +2 is 00 +3 is 00 +4 is ?? +5 is ?? +6 is 00 from a0 to +7 is 00 from 3f to */ +/* +0 is F6 to 01 +1 is CE CE +4A 4A +00 00 +00 E0 +00 CB +00 90 +00 3F +*/ + +struct Merchant_Sell_Struct { +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ uint32 playerid; // Player's entity id +/*008*/ uint32 itemslot; // Merchant Slot / Item Instance ID +/*012*/ uint32 unknown12; +/*016*/ uint32 quantity; // Already sold +/*020*/ uint32 unknown20; +/*024*/ uint32 price; +/*028*/ uint32 unknown28; // Normally 0, but seen 84 c5 63 00 as well +/*032*/ +}; + +struct Merchant_Purchase_Struct { +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ MainInvItemSlotStruct itemslot; +/*012*/ uint32 quantity; +/*016*/ uint32 price; +/*020*/ +}; + +struct Merchant_DelItem_Struct{ +/*000*/ uint32 npcid; // Merchant NPC's entity id +/*004*/ uint32 playerid; // Player's entity id +/*008*/ uint32 itemslot; +}; + +struct AltCurrencyDefinition_Struct { + uint32 id; + uint32 item_id; +}; + +//One packet i didn't include here is the alt currency merchant window. +//it works much like the adventure merchant window +//it is formated like: dbstringid|1|dbstringid|count +//ex for a blank crowns window you would send: +//999999|1|999999|0 +//any items come after in much the same way adventure merchant items do except there is no theme included + +//Server -> Client +//Populates the initial Alternate Currency Window +struct AltCurrencyPopulateEntry_Struct +{ +/*000*/ uint32 currency_number; // corresponds to a dbstr id as well, the string matches what shows up in the "alternate currency" tab. +/*004*/ uint32 unknown00; // always 1 +/*008*/ uint32 currency_number2; // always same as currency number +/*012*/ uint32 item_id; // appears to be the item id +/*016*/ uint32 item_icon; // actual icon +/*020*/ uint32 stack_size; // most are set to 1000, the stack size for the item; should match db i think or there will be problems. +/*024*/ uint8 display; // If set to 0, will not display by default. +/*025*/ +}; + +struct AltCurrencyPopulate_Struct { +/*000*/ uint32 opcode; // 8 for populate +/*004*/ uint32 count; // number of entries +/*008*/ AltCurrencyPopulateEntry_Struct entries[0]; +}; + +//Server -> Client +//Updates the value of a specific Alternate Currency +struct AltCurrencyUpdate_Struct { +/*000*/ uint32 opcode; //7 for update +/*004*/ char name[64]; //name of client (who knows why just do it) +/*068*/ uint32 currency_number; //matches currency_number from populate entry +/*072*/ uint32 unknown072; //always 1 +/*076*/ uint32 amount; //new amount +/*080*/ uint32 unknown080; //seen 0 +/*084*/ uint32 unknown084; //seen 0 +}; + +//Client -> Server +//When an item is selected while the alt currency merchant window is open +struct AltCurrencySelectItem_Struct { +/*000*/ uint32 merchant_entity_id; +/*004*/ //uint32 slot_id; + ItemSlotStruct slot_id; +/*008*/ uint32 unknown008; +/*012*/ uint32 unknown012; +/*016*/ uint32 unknown016; +/*020*/ uint32 unknown020; +/*024*/ uint32 unknown024; +/*028*/ uint32 unknown028; +/*032*/ uint32 unknown032; +/*036*/ uint32 unknown036; +/*040*/ uint32 unknown040; +/*044*/ uint32 unknown044; +/*048*/ uint32 unknown048; +/*052*/ uint32 unknown052; +/*056*/ uint32 unknown056; +/*060*/ uint32 unknown060; +/*064*/ uint32 unknown064; +/*068*/ uint32 unknown068; +/*072*/ uint32 unknown072; +/*076*/ uint32 unknown076; +}; + +//Server -> Client +//As setup it makes it so that item can't be sold to the merchant. +//eg: "I will give you no doubloons for a cloth cap." +//Probably also sends amounts somewhere +struct AltCurrencySelectItemReply_Struct { +/*000*/ uint32 unknown000; +/*004*/ uint8 unknown004; //0xff +/*005*/ uint8 unknown005; //0xff +/*006*/ uint8 unknown006; //0xff +/*007*/ uint8 unknown007; //0xff +/*008*/ char item_name[64]; +/*072*/ uint32 unknown074; +/*076*/ uint32 cost; +/*080*/ uint32 unknown080; +/*084*/ uint32 unknown084; +}; + +//Client -> Server +//Requests purchase of a specific item from the vendor +struct AltCurrencyPurchaseItem_Struct { +/*000*/ uint32 merchant_entity_id; +/*004*/ uint32 item_id; +/*008*/ uint32 unknown008; //1 +}; + +//Client -> Server +//Reclaims / Create currency button pushed. +struct AltCurrencyReclaim_Struct { +/*000*/ uint32 currency_id; +/*004*/ uint32 unknown004; +/*008*/ uint32 count; +/*012*/ uint32 reclaim_flag; //1 = this is reclaim +}; + +struct AltCurrencySellItem_Struct { +/*000*/ uint32 merchant_entity_id; +/*004*/ //uint32 slot_id; + ItemSlotStruct slot_id; +/*008*/ uint32 charges; +/*012*/ uint32 cost; +}; + +struct Adventure_Purchase_Struct { +/*000*/ uint32 some_flag; //set to 1 generally... +/*004*/ uint32 npcid; +/*008*/ uint32 itemid; +/*012*/ uint32 variable; +}; + +struct Adventure_Sell_Struct { +/*000*/ uint32 unknown000; //0x01 - Stack Size/Charges? +/*004*/ uint32 npcid; +/*008*/ MainInvItemSlotStruct slot; +/*016*/ uint32 charges; +/*020*/ uint32 sell_price; +/*024*/ +}; + +struct AdventurePoints_Update_Struct { +/*000*/ uint32 ldon_available_points; // Total available points +/*004*/ uint8 unkown_apu004[20]; +/*024*/ uint32 ldon_guk_points; // Earned Deepest Guk points +/*028*/ uint32 ldon_mirugal_points; // Earned Mirugal' Mebagerie points +/*032*/ uint32 ldon_mistmoore_points; // Earned Mismoore Catacombs Points +/*036*/ uint32 ldon_rujarkian_points; // Earned Rujarkian Hills points +/*040*/ uint32 ldon_takish_points; // Earned Takish points +/*044*/ uint8 unknown_apu042[216]; +}; + + +struct AdventureFinish_Struct{ + uint32 win_lose;//Cofruben: 00 is a lose,01 is win. + uint32 points; +}; +//OP_AdventureRequest +struct AdventureRequest_Struct{ + uint32 risk;//1 normal,2 hard. + uint32 entity_id; +}; +struct AdventureRequestResponse_Struct{ + uint32 unknown000; + char text[2048]; + uint32 timetoenter; + uint32 timeleft; + uint32 risk; + float x; + float y; + float z; + uint32 showcompass; + uint32 unknown2080; +}; + +//this is mostly right but something is off that causes the client to crash sometimes +//I don't really care enough about the feature to work on it anymore though. +struct AdventureLeaderboardEntry_Struct +{ +/*004*/ char name[64]; +/*008*/ uint32 success; +/*012*/ uint32 failure; +/*016*/ +}; + +struct AdventureLeaderboard_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint32 unknown004; +/*008*/ uint32 success; +/*012*/ uint32 failure; +/*016*/ uint32 our_rank; +/*020*/ +}; + +/*struct Item_Shop_Struct { + uint16 merchantid; + uint8 itemtype; + Item_Struct item; + uint8 iss_unknown001[6]; +};*/ + +struct Illusion_Struct { // Was size: 336 +/*000*/ uint32 spawnid; +/*004*/ char charname[64]; +/*068*/ uint16 race; +/*070*/ char unknown006[2]; // Weird green name +/*072*/ uint8 gender; +/*073*/ uint8 texture; +/*074*/ uint8 unknown074; +/*075*/ uint8 unknown075; +/*076*/ uint8 helmtexture; +/*077*/ uint8 unknown077; +/*078*/ uint8 unknown078; +/*079*/ uint8 unknown079; +/*080*/ uint32 face; +/*084*/ uint8 hairstyle; // Some Races don't change Hair Style Properly in SoF +/*085*/ uint8 haircolor; +/*086*/ uint8 beard; +/*087*/ uint8 beardcolor; +/*088*/ float size; +/*092*/ uint8 unknown092[148]; +/*240*/ uint32 unknown240; // Removes armor? +/*244*/ uint32 drakkin_heritage; +/*248*/ uint32 drakkin_tattoo; +/*252*/ uint32 drakkin_details; +/*256*/ uint8 unknown256[60]; // This and below are new to RoF2 +/*316*/ int32 unknown316; // Seen -1 +/*320*/ uint8 unknown320[16]; +/*336*/ +}; + +struct ZonePoint_Entry { //32 octets +/*0000*/ uint32 iterator; +/*0004*/ float y; +/*0008*/ float x; +/*0012*/ float z; +/*0016*/ float heading; +/*0020*/ uint16 zoneid; +/*0022*/ uint16 zoneinstance; // LDoN instance +/*0024*/ uint32 unknown024; +/*0028*/ uint32 unknown028; +/*0032*/ +}; + +struct ZonePoints { +/*0000*/ uint32 count; +/*0004*/ struct ZonePoint_Entry zpe[0]; // Always add one extra to the end after all zonepoints +//*0xxx*/ uint8 unknown0xxx[24]; //New from SEQ +}; + +struct SkillUpdate_Struct { +/*00*/ uint32 skillId; +/*04*/ uint32 value; +/*08*/ uint8 unknown08; // Seen 1 +/*09*/ uint8 unknown09; // Seen 80 +/*10*/ uint8 unknown10; // Seen 136 +/*11*/ uint8 unknown11; // Seen 54 +/*12*/ +}; + +struct ZoneUnavail_Struct { + //This actually varies, but... + char zonename[16]; + int16 unknown[4]; +}; + +struct GroupInvite_Struct { +/*0000*/ char invitee_name[64]; +/*0064*/ char inviter_name[64]; +/*0128*/ uint32 unknown0128; +/*0132*/ uint32 unknown0132; +/*0136*/ uint32 unknown0136; +/*0140*/ uint32 unknown0140; +/*0144*/ uint32 unknown0144; +/*0148*/ +}; + +struct GroupGeneric_Struct { +/*0000*/ char name1[64]; +/*0064*/ char name2[64]; +/*0128*/ uint32 unknown0128; +/*0132*/ uint32 unknown0132; +/*0136*/ uint32 unknown0136; +/*0140*/ uint32 unknown0140; +/*0144*/ uint32 unknown0144; +/*0148*/ +}; + +struct GroupCancel_Struct { +/*000*/ char name1[64]; +/*064*/ char name2[64]; +/*128*/ uint8 unknown128[20]; +/*148*/ uint32 toggle; +/*152*/ +}; + +struct GroupUpdate_Struct { +/*0000*/ uint32 action; +/*0004*/ char yourname[64]; +/*0068*/ char membername[5][64]; +/*0388*/ char leadersname[64]; +/*0452*/ +}; + +struct GroupUpdate2_Struct { +/*0000*/ uint32 action; +/*0004*/ char yourname[64]; +/*0068*/ char membername[5][64]; +/*0388*/ char leadersname[64]; +/*0452*/ GroupLeadershipAA_Struct leader_aas; +/*0516*/ uint8 unknown[252]; // Titanium uses [188] here +/*0768*/ +}; + +struct GroupUpdate_Struct_Live { // New for Live +/*0000*/ uint32 groupid; // Guess - Matches unknown0136 from GroupFollow_Struct +/*0004*/ uint32 totalmembers; // Guess +/*0000*/ //uint32 leadersname[0]; // Group Leader Name Null Terminated +/*0008*/ //GroupMembers_Struct groupmembers; +}; + +struct GroupMembers_Struct { // New for Live +/*0000*/ uint32 membernumber; // Guess - number of member in the group (0 to 5?) +/*0000*/ //char membername[0]; // Member Name Null Terminated +/*0000*/ uint8 unknown001[3]; // Seen 0 +/*0000*/ uint32 memberlevel; // Guess +/*0000*/ uint8 unknown002[11]; // Seen 0 +}; + +struct GroupJoin_Struct_Live { // New for Live +/*0000*/ uint32 unknown0000; // Matches unknown0136 from GroupFollow_Struct +/*0004*/ uint32 action; +/*0008*/ uint8 unknown0008[5]; // Seen 0 +/*0013*/ //char membername[0]; // Null Terminated? +/*0000*/ uint8 unknown0013[3]; // Seen 0 +/*0000*/ uint32 unknown0016; // Matches unknown0132 from GroupFollow_Struct +/*0000*/ uint8 unknown0020[11]; // Seen 0 +}; + +struct GroupJoin_Struct { +/*000*/ char unknown000[64]; +/*064*/ char membername[64]; +/*128*/ uint8 unknown128[20]; // Leadership AA ? +/*148*/ +}; + +struct GroupFollow_Struct { // Live Follow Struct +/*0000*/ char name1[64]; // inviter +/*0064*/ char name2[64]; // invitee +/*0128*/ uint32 unknown0128; // Seen 0 +/*0132*/ uint32 unknown0132; // Group ID or member level? +/*0136*/ uint32 unknown0136; // Maybe Voice Chat Channel or Group ID? +/*0140*/ uint32 unknown0140; // Seen 0 +/*0144*/ uint32 unknown0144; // Seen 0 +/*0148*/ uint32 unknown0148; +/*0152*/ +}; + +struct InspectBuffs_Struct { +/*000*/ uint32 spell_id[BUFF_COUNT]; +/*168*/ uint32 tics_remaining[BUFF_COUNT]; +}; + +struct LFG_Struct { +/*000*/ uint32 unknown000; +/*004*/ uint32 value; // 0x00 = off 0x01 = on +/*008*/ uint32 unknown008; +/*012*/ uint32 unknown012; +/*016*/ char name[64]; +}; + +struct FaceChange_Struct { +/*000*/ uint8 haircolor; +/*001*/ uint8 beardcolor; +/*002*/ uint8 eyecolor1; +/*003*/ uint8 eyecolor2; +/*004*/ uint8 hairstyle; +/*005*/ uint8 beard; +/*006*/ uint8 face; +/*007*/ uint8 unknown007; +/*008*/ uint32 drakkin_heritage; +/*012*/ uint32 drakkin_tattoo; +/*016*/ uint32 drakkin_details; +/*020*/ uint32 unknown020; +/*024*/ +}; +//there are only 10 faces for barbs changing woad just +//increase the face value by ten so if there were 8 woad +//designs then there would be 80 barb faces + +/* +** Trade request from one client to another +** Used to initiate a trade +** Size: 8 bytes +** Used in: OP_TradeRequest +*/ +struct TradeRequest_Struct { +/*00*/ uint32 to_mob_id; +/*04*/ uint32 from_mob_id; +/*08*/ +}; + +struct TradeAccept_Struct { +/*00*/ uint32 from_mob_id; +/*04*/ uint32 unknown4; //seems to be garbage +/*08*/ +}; + +/* +** Cancel Trade struct +** Sent when a player cancels a trade +** Size: 8 bytes +** Used In: OP_CancelTrade +** +*/ +struct CancelTrade_Struct { +/*00*/ uint32 fromid; +/*04*/ uint32 action; +/*08*/ +}; + +struct PetitionUpdate_Struct { + uint32 petnumber; // Petition Number + uint32 color; // 0x00 = green, 0x01 = yellow, 0x02 = red + uint32 status; + time_t senttime; // 4 has to be 0x1F + char accountid[32]; + char gmsenttoo[64]; + int32 quetotal; + char charname[64]; +}; + +struct Petition_Struct { + uint32 petnumber; + uint32 urgency; + char accountid[32]; + char lastgm[32]; + uint32 zone; + //char zone[32]; + char charname[64]; + uint32 charlevel; + uint32 charclass; + uint32 charrace; + uint32 unknown; + //time_t senttime; // Time? + uint32 checkouts; + uint32 unavail; + //uint8 unknown5[4]; + time_t senttime; + uint32 unknown2; + char petitiontext[1024]; + char gmtext[1024]; +}; + + +struct Who_All_Struct { // 156 length total +/*000*/ char whom[64]; +/*088*/ uint8 unknown088[64]; +/*064*/ uint32 wrace; // FF FF = no race +/*068*/ uint32 wclass; // FF FF = no class +/*072*/ uint32 lvllow; // FF FF = no numbers +/*076*/ uint32 lvlhigh; // FF FF = no numbers +/*080*/ uint32 gmlookup; // FF FF = not doing /who all gm +/*084*/ uint32 guildid; // Also used for Buyer/Trader/LFG +/*152*/ uint32 type; // 0 = /who 3 = /who all +/*156*/ +}; + +struct Stun_Struct { // 8 bytes total +/*000*/ uint32 duration; // Duration of stun +/*004*/ uint8 unknown004; // seen 0 +/*005*/ uint8 unknown005; // seen 163 +/*006*/ uint8 unknown006; // seen 67 +/*007*/ uint8 unknown007; // seen 0 +/*008*/ +}; + +struct AugmentItem_Struct { +/*00*/ uint32 dest_inst_id; // The unique serial number for the item instance that is being augmented +/*04*/ uint32 container_index; // Seen 0 +/*08*/ ItemSlotStruct container_slot; // Slot of the item being augmented +/*20*/ uint32 augment_index; // Seen 0 +/*24*/ ItemSlotStruct augment_slot; // Slot of the distiller to use (if one applies) +/*36*/ int32 augment_action; // Guessed - 0 = augment, 1 = remove with distiller, 3 = delete aug +/*36*/ //int32 augment_slot; +/*40*/ +}; + +// OP_Emote +struct Emote_Struct { +/*0000*/ uint32 unknown01; +/*0004*/ char message[1024]; // was 1024 +/*1028*/ +}; + +// Inspect +struct Inspect_Struct { + uint32 TargetID; + uint32 PlayerID; +}; + +//OP_InspectAnswer - Size: 1860 +struct InspectResponse_Struct{ +/*000*/ uint32 TargetID; +/*004*/ uint32 playerid; +/*008*/ char itemnames[23][64]; +/*1480*/uint32 itemicons[23]; +/*1572*/char text[288]; // Max number of chars in Inspect Window appears to be 254 +/*1860*/ +}; + +//OP_SetDataRate +struct SetDataRate_Struct { + float newdatarate; +}; + +//OP_SetServerFilter +struct SetServerFilter_Struct { + uint32 filters[35]; //see enum eqFilterType [31] +}; + +//Op_SetServerFilterAck +struct SetServerFilterAck_Struct { + uint8 blank[8]; +}; +struct IncreaseStat_Struct{ + /*0000*/ uint8 unknown0; + /*0001*/ uint8 str; + /*0002*/ uint8 sta; + /*0003*/ uint8 agi; + /*0004*/ uint8 dex; + /*0005*/ uint8 int_; + /*0006*/ uint8 wis; + /*0007*/ uint8 cha; + /*0008*/ uint8 fire; + /*0009*/ uint8 cold; + /*0010*/ uint8 magic; + /*0011*/ uint8 poison; + /*0012*/ uint8 disease; + /*0013*/ char unknown13[116]; + /*0129*/ uint8 str2; + /*0130*/ uint8 sta2; + /*0131*/ uint8 agi2; + /*0132*/ uint8 dex2; + /*0133*/ uint8 int_2; + /*0134*/ uint8 wis2; + /*0135*/ uint8 cha2; + /*0136*/ uint8 fire2; + /*0137*/ uint8 cold2; + /*0138*/ uint8 magic2; + /*0139*/ uint8 poison2; + /*0140*/ uint8 disease2; +}; + +struct GMName_Struct { + char oldname[64]; + char gmname[64]; + char newname[64]; + uint8 badname; + uint8 unknown[3]; +}; + +struct GMDelCorpse_Struct { + char corpsename[64]; + char gmname[64]; + uint8 unknown; +}; + +struct GMKick_Struct { + char name[64]; + char gmname[64]; + uint8 unknown; +}; + + +struct GMKill_Struct { + char name[64]; + char gmname[64]; + uint8 unknown; +}; + + +struct GMEmoteZone_Struct { + char text[512]; +}; + +// The BookText_Struct is not used in SoF and later clients. +// The BookRequest_Struct is used instead for both request and reply. +// +struct BookText_Struct { + uint8 window; // where to display the text (0xFF means new window) + uint8 type; //type: 0=scroll, 1=book, 2=item info.. prolly + char booktext[1]; // Variable Length - was 1 +}; +// This is the request to read a book. +// This is just a "text file" on the server +// or in our case, the 'name' column in our books table. +struct BookRequest_Struct { +/*0000*/ uint32 window; // where to display the text (0xFFFFFFFF means new window). +/*0004*/ uint16 invslot; // Is the slot, but the RoF2 conversion causes it to fail. Turned to 0 since it isnt required anyway. +/*0008*/ uint32 unknown006; // Seen FFFFFFFF +/*0010*/ uint16 unknown008; // seen 0000 +/*0012*/ uint32 type; // 0 = Scroll, 1 = Book, 2 = Item Info. Possibly others +/*0016*/ uint32 unknown0012; +/*0020*/ uint16 unknown0016; +/*0022*/ char txtfile[8194]; +}; + +/* +** Object/Ground Spawn struct +** Used for Forges, Ovens, ground spawns, items dropped to ground, etc +** Size: Variable +** OpCodes: OP_CreateObject +** +*/ +struct Object_Struct { +/*00*/ uint32 object_count; // Iteration count in the object list +/*00*/ char object_name[1]; // Name of object, usually something like IT63_ACTORDEF +/*00*/ uint16 zone_id; // Redudant, but: Zone the object appears in +/*00*/ uint16 zone_instance; // +/*00*/ uint32 drop_id; // Unique object id for zone +/*00*/ uint32 unknown024; // 53 9e f9 7e - same for all objects in the zone? +/*00*/ float heading; // heading +/*00*/ float unknown032[2]; // 00 00 00 00 00 00 00 00 +/*00*/ float size; // Size - default 1 +/*00*/ float z; // z coord +/*00*/ float x; // x coord +/*00*/ float y; // y coord +/*00*/ int32 object_type; // Type of object, not directly translated to OP_OpenObject +}; +// object_type - 01 = generic drop, 02 = armor, 19 = weapon +// 0xff seems to be indicative of the tradeskill/openable items that end up returning the old style item type in the OP_OpenObject + +/* +** Click Object Struct +** Client clicking on zone object (forge, groundspawn, etc) +** Size: 8 bytes +** Last Updated: Oct-17-2003 +** +*/ +struct ClickObject_Struct { +/*00*/ uint32 drop_id; // Appears to use the Object Count field now +/*04*/ uint32 player_id; +/*08*/ +}; + +struct Shielding_Struct { + uint32 target_id; +}; + +/* +** Click Object Acknowledgement Struct +** Response to client clicking on a World Container (ie, forge) +** +*/ +struct ClickObjectAction_Struct { +/*00*/ //uint32 player_id; // Appears to have been removed +/*00*/ uint32 drop_id; // Appears to use the object_count field now +/*04*/ int32 unknown04; // Seen -1 +/*08*/ int32 unknown08; // Seen -1 +/*08*/ //uint32 open; // 1=opening, 0=closing - Removed? +/*12*/ uint32 type; // See object.h, "Object Types" +/*16*/ uint32 unknown16; // +/*20*/ uint32 icon; // Icon to display for tradeskill containers +/*24*/ uint32 unknown24; // +/*28*/ char object_name[64]; // Object name to display +/*92*/ +}; + +/* +** This is different now, mostly unknown +** +*/ +struct CloseContainer_Struct { +/*00*/ uint32 player_id; // Entity Id of player who clicked object +/*04*/ uint32 drop_id; // Zone-specified unique object identifier +/*08*/ uint32 open; // 1=opening, 0=closing +/*12*/ uint32 unknown12[12]; +}; + +/* +** Generic Door Struct +** Length: 52 Octets +** Used in: +** cDoorSpawnsStruct(f721) +** +*/ +struct Door_Struct +{ +/*0000*/ char name[32]; // Filename of Door // Was 10char long before... added the 6 in the next unknown to it: Daeken M. BlackBlade +/*0032*/ float yPos; // y loc +/*0036*/ float xPos; // x loc +/*0040*/ float zPos; // z loc +/*0044*/ float heading; +/*0048*/ uint32 incline; // rotates the whole door +/*0052*/ uint32 size; // 100 is normal, smaller number = smaller model +/*0054*/ uint8 unknown0054[4]; // 00 00 00 00 +/*0060*/ uint8 doorId; // door's id # +/*0061*/ uint8 opentype; +/*0062*/ uint8 state_at_spawn; +/*0063*/ uint8 invert_state; // if this is 1, the door is normally open +/*0064*/ uint32 door_param; // normally ff ff ff ff (-1) +/*0068*/ uint32 unknown0068; // 00 00 00 00 +/*0072*/ uint32 unknown0072; // 00 00 00 00 +/*0076*/ uint8 unknown0076[4]; // New for RoF2 +/*0080*/ uint8 unknown0080; // seen 1 or 0 +/*0081*/ uint8 unknown0081; // seen 1 (always?) +/*0082*/ uint8 unknown0082; // seen 0 (always?) +/*0083*/ uint8 unknown0083; // seen 1 (always?) +/*0084*/ uint8 unknown0084; // seen 0 (always?) +/*0085*/ uint8 unknown0085; // seen 1 or 0 or rarely 2C or 90 or ED or 2D or A1 +/*0086*/ uint8 unknown0086; // seen 0 or rarely FF or FE or 10 or 5A or 82 +/*0087*/ uint8 unknown0087; // seen 0 or rarely 02 or 7C +/*0088*/ uint8 unknown0088[8]; // mostly 0s, the last 3 bytes are something tho +/*0096*/ +}; + +struct DoorSpawns_Struct { + struct Door_Struct doors[0]; +}; + +/* + OP Code: Op_ClickDoor + Size: 16 +*/ +struct ClickDoor_Struct { +/*000*/ uint8 doorid; +/*001*/ uint8 unknown001; // This may be some type of action setting +/*002*/ uint8 unknown002; // This is sometimes set after a lever is closed +/*003*/ uint8 unknown003; // Seen 0 +/*004*/ uint8 picklockskill; +/*005*/ uint8 unknown005[3]; +/*008*/ uint32 item_id; +/*012*/ uint16 player_id; +/*014*/ uint8 unknown014[2]; +/*016*/ +}; + +struct MoveDoor_Struct { + uint8 doorid; + uint8 action; +}; + + +struct BecomeNPC_Struct { + uint32 id; + int32 maxlevel; +}; + +struct Underworld_Struct { + float speed; + float y; + float x; + float z; +}; + +struct Resurrect_Struct +{ +/*000*/ uint32 unknown000; +/*004*/ uint16 zone_id; +/*006*/ uint16 instance_id; +/*008*/ float y; +/*012*/ float x; +/*016*/ float z; +/*020*/ uint32 unknown020; +/*024*/ char your_name[64]; +/*088*/ uint32 unknown088; +/*092*/ char rezzer_name[64]; +/*156*/ uint32 spellid; +/*160*/ char corpse_name[64]; +/*224*/ uint32 action; +/*228*/ uint32 unknown228; +/*232*/ +}; + +struct SetRunMode_Struct { + uint8 mode; //01=run 00=walk + uint8 unknown[3]; +}; + +// EnvDamage is EnvDamage2 without a few bytes at the end. +// Size: 37 bytes +struct EnvDamage2_Struct { +/*0000*/ uint32 id; +/*0004*/ uint16 unknown4; +/*0006*/ uint32 damage; +/*0010*/ float unknown10; // New to Underfoot - Seen 1 +/*0014*/ uint8 unknown14[12]; +/*0026*/ uint8 dmgtype; // FA = Lava; FC = Falling +/*0027*/ uint8 unknown27[4]; +/*0031*/ uint16 unknown31; // New to Underfoot - Seen 66 +/*0033*/ uint16 constant; // Always FFFF +/*0035*/ uint16 unknown35; +/*0037*/ +}; + +//Bazaar Stuff + +enum { + BazaarTrader_StartTraderMode = 1, + BazaarTrader_EndTraderMode = 2, + BazaarTrader_UpdatePrice = 3, + BazaarTrader_EndTransaction = 4, + BazaarSearchResults = 7, + BazaarWelcome = 9, + BazaarBuyItem = 10, + BazaarTrader_ShowItems = 11, + BazaarSearchDone = 12, + BazaarTrader_CustomerBrowsing = 13, + BazaarInspectItem = 18, + BazaarSearchDone2 = 19, + BazaarTrader_StartTraderMode2 = 22 +}; + +enum { + BazaarPriceChange_Fail = 0, + BazaarPriceChange_UpdatePrice = 1, + BazaarPriceChange_RemoveItem = 2, + BazaarPriceChange_AddItem = 3 +}; + +struct BazaarWindowStart_Struct { + uint8 Action; + uint8 Unknown001; + uint16 Unknown002; +}; + + +struct BazaarWelcome_Struct { + BazaarWindowStart_Struct Beginning; + uint32 Traders; + uint32 Items; + uint8 Unknown012[8]; +}; + +struct BazaarSearch_Struct { + BazaarWindowStart_Struct Beginning; + uint32 TraderID; + uint32 Class_; + uint32 Race; + uint32 ItemStat; + uint32 Slot; + uint32 Type; + char Name[64]; + uint32 MinPrice; + uint32 MaxPrice; + uint32 Minlevel; + uint32 MaxLlevel; +}; +struct BazaarInspect_Struct{ + uint32 ItemID; + uint32 Unknown004; + char Name[64]; +}; + +struct NewBazaarInspect_Struct { +/*000*/ BazaarWindowStart_Struct Beginning; +/*004*/ char Name[64]; +/*068*/ uint32 Unknown068; +/*072*/ int32 SerialNumber; +/*076*/ uint32 Unknown076; +/*080*/ uint32 SellerID; +/*084*/ uint32 Unknown084; +}; + +struct BazaarReturnDone_Struct{ + uint32 Type; + uint32 TraderID; + uint32 Unknown008; + uint32 Unknown012; + uint32 Unknown016; +}; + +struct BazaarSearchResults_Struct { +/*000*/ BazaarWindowStart_Struct Beginning; +/*004*/ uint32 SellerID; +/*008*/ char SellerName[64]; +/*072*/ uint32 NumItems; +/*076*/ uint32 ItemID; +/*080*/ uint32 SerialNumber; +/*084*/ uint32 Unknown084; +/*088*/ char ItemName[64]; +/*152*/ uint32 Cost; +/*156*/ uint32 ItemStat; +/*160*/ +}; + +struct ServerSideFilters_Struct { +uint8 clientattackfilters; // 0) No, 1) All (players) but self, 2) All (players) but group +uint8 npcattackfilters; // 0) No, 1) Ignore NPC misses (all), 2) Ignore NPC Misses + Attacks (all but self), 3) Ignores NPC Misses + Attacks (all but group) +uint8 clientcastfilters; // 0) No, 1) Ignore PC Casts (all), 2) Ignore PC Casts (not directed towards self) +uint8 npccastfilters; // 0) No, 1) Ignore NPC Casts (all), 2) Ignore NPC Casts (not directed towards self) +}; + +/* +** Client requesting item statistics +** Size: 52 bytes +** Used In: OP_ItemLinkClick +** Last Updated: 01/03/2012 +** +*/ +struct ItemViewRequest_Struct { +/*000*/ uint32 item_id; +/*004*/ uint32 augments[6]; +/*028*/ uint32 link_hash; +/*032*/ uint32 unknown028; //seems to always be 4 on SoF client +/*036*/ char unknown032[12]; //probably includes loregroup & evolving info. see Client::MakeItemLink() in zone/inventory.cpp:469 +/*048*/ uint16 icon; +/*050*/ char unknown046[2]; +/*052*/ +}; + +/* + * Client to server packet + */ +struct PickPocket_Struct { +// Size 18 + uint32 to; + uint32 from; + uint16 myskill; + uint8 type; // -1 you are being picked, 0 failed , 1 = plat, 2 = gold, 3 = silver, 4 = copper, 5 = item + uint8 unknown1; // 0 for response, unknown for input + uint32 coin; + uint8 lastsix[2]; +}; +/* + * Server to client packet + */ + +struct sPickPocket_Struct { + // Size 28 = coin/fail + uint32 to; + uint32 from; + uint32 myskill; + uint32 type; + uint32 coin; + char itemname[64]; +}; + + +struct LogServer_Struct { +// Op_Code OP_LOGSERVER +/*000*/ uint32 unknown000; +/*004*/ uint8 enable_pvp; +/*005*/ uint8 unknown005; +/*006*/ uint8 unknown006; +/*007*/ uint8 unknown007; +/*008*/ uint8 enable_FV; +/*009*/ uint8 unknown009; +/*010*/ uint8 unknown010; +/*011*/ uint8 unknown011; +/*012*/ uint32 unknown012; // htonl(1) on live +/*016*/ uint32 unknown016; // htonl(1) on live +/*020*/ uint8 unknown020[12]; +/*032*/ uint32 unknown032; +/*036*/ char worldshortname[32]; +/*068*/ uint8 unknown068[181]; +/*249*/ uint8 unknown249[27]; +/*276*/ float unknown276[7]; +/*304*/ uint8 unknown304[256]; +/*560*/ + +/* Currently lost + uint8 enablevoicemacros; + uint8 enablemail; +*/ +}; + +struct ApproveWorld_Struct { +// Size 544 +// Op_Code OP_ApproveWorld + uint8 unknown544[544]; +}; + +struct ClientError_Struct +{ +/*00001*/ char type; +/*00001*/ char unknown0001[69]; +/*00069*/ char character_name[64]; +/*00134*/ char unknown134[192]; +/*00133*/ char message[31994]; +/*32136*/ +}; + +struct MobHealth +{ + /*0000*/ uint8 hp; //health percent + /*0001*/ uint16 id;//mobs id +}; + +struct Track_Struct { + uint16 entityid; + uint16 y; + uint16 x; + uint16 z; +}; + +struct Tracking_Struct { + Track_Struct Entrys[0]; +}; + +// Looks like new tracking structures - Opcode: 0x57a7 +struct Tracking_Struct_New { + uint16 totalcount; // Total Count of mobs within tracking range + Track_Struct Entrys[0]; +}; + +struct Track_Struct_New { + uint16 entityid; // Entity ID + uint16 unknown002; // 00 00 + uint32 unknown004; // + uint8 level; // level of mob + uint8 unknown009; // 01 maybe type of mob? player/npc? + char name[1]; // name of mob +}; + + +/* +** ZoneServerInfo_Struct +** Zone server information +** Size: 130 bytes +** Used In: OP_ZoneServerInfo +** +*/ +struct ZoneServerInfo_Struct +{ +/*0000*/ char ip[128]; +/*0128*/ uint16 port; +}; + +struct WhoAllPlayer{ + uint32 formatstring; + uint32 pidstring; + int32 unknown64; // Seen -1 + char* name; + uint32 rankstring; + char* guild; + uint32 unknown80[2]; + uint32 zonestring; + uint32 zone; + uint32 class_; + uint32 level; + uint32 race; + char* account; + uint32 unknown100; +}; + +struct WhoAllReturnStruct { + uint32 id; + uint32 playerineqstring; + char line[27]; + uint8 unknown35; // 0A + uint32 unknown36; // Seen 208243456 + uint32 playersinzonestring; + uint32 unknown52; // Same as playercount? + uint32 unknown44[2]; // 0s + uint32 unknown56; // Same as playercount? + uint32 playercount; // Player Count in the who list + struct WhoAllPlayer player[0]; +}; + +// The following four structs are the WhoAllPlayer struct above broken down +// for use in World ClientList::SendFriendsWho to accomodate the user of variable +// length strings within the struct above. + +struct WhoAllPlayerPart1 { + uint32 FormatMSGID; + uint32 Unknown04; + uint32 Unknown08; + char Name[1]; +}; + +struct WhoAllPlayerPart2 { + uint32 RankMSGID; + char Guild[1]; +}; + +struct WhoAllPlayerPart3 { + uint32 Unknown80[2]; + uint32 ZoneMSGID; + uint32 Zone; + uint32 Class_; + uint32 Level; + uint32 Race; + char Account[1]; +}; + +struct WhoAllPlayerPart4 { + uint32 Unknown100; +}; + +struct TraderItemSerial_Struct { + char SerialNumber[17]; + uint8 Unknown18; +}; + +struct Trader_Struct { +/*0000*/ uint32 Code; +/*0004*/ TraderItemSerial_Struct items[200]; +/*3604*/ uint32 ItemCost[200]; +/*4404*/ +}; + +struct ClickTrader_Struct { +/*0000*/ uint32 Code; +/*0004*/ TraderItemSerial_Struct items[200]; +/*3604*/ uint32 ItemCost[200]; +/*4404*/ +}; + +struct GetItems_Struct { + uint32 items[200]; +}; + +struct BecomeTrader_Struct { + uint32 id; + uint32 code; +}; + +struct Trader_ShowItems_Struct { +/*000*/ uint32 Code; +/*004*/ char SerialNumber[17]; +/*021*/ uint8 Unknown21; +/*022*/ uint16 TraderID; +/*026*/ uint32 Stacksize; +/*030*/ uint32 Price; +/*032*/ +}; + +struct TraderStatus_Struct { +/*000*/ uint32 Code; +/*004*/ uint32 Uknown04; +/*008*/ uint32 Uknown08; +/*012*/ +}; + +struct TraderBuy_Struct { +/*000*/ uint32 Action; +/*004*/ uint32 Unknown004; +/*008*/ uint32 Price; +/*012*/ uint32 Unknown008; // Probably high order bits of a 64 bit price. +/*016*/ uint32 TraderID; +/*020*/ char ItemName[64]; +/*084*/ uint32 Unknown076; +/*088*/ uint32 ItemID; +/*092*/ uint32 AlreadySold; +/*096*/ uint32 Quantity; +/*100*/ uint32 Unknown092; +/*104*/ +}; + +struct TraderItemUpdate_Struct{ + uint32 unknown0; + uint32 traderid; + uint8 fromslot; + uint8 toslot; //7? + uint16 charges; +}; + +struct MoneyUpdate_Struct{ + int32 platinum; + int32 gold; + int32 silver; + int32 copper; +}; + +//struct MoneyUpdate_Struct +//{ +//*0000*/ uint32 spawn_id; // ***Placeholder +//*0004*/ uint32 cointype; // Coin Type +//*0008*/ uint32 amount; // Amount +//*0012*/ +//}; + + +struct TraderDelItem_Struct{ + uint32 slotid; + uint32 quantity; + uint32 unknown; +}; + +struct TraderClick_Struct{ + uint32 traderid; + uint32 unknown4[2]; + uint32 approval; +}; + +struct FormattedMessage_Struct{ + uint32 unknown0; + uint32 string_id; + uint32 type; + char message[0]; +//*0???*/ uint8 unknown0[8]; // ***Placeholder +}; +struct SimpleMessage_Struct{ + uint32 string_id; + uint32 color; + uint32 unknown8; +}; + +// Size: 52 + strings +// Other than the strings, all of this packet is network byte order (reverse from normal) +struct GuildMemberEntry_Struct { + char name[1]; // variable length + uint32 level; + uint32 banker; // 1=yes, 0=no + uint32 class_; + uint32 rank; + uint32 time_last_on; + uint32 tribute_enable; + uint32 unknown01; // Seen 0 + uint32 total_tribute; // total guild tribute donated, network byte order + uint32 last_tribute; // unix timestamp + uint32 unknown_one; // unknown, set to 1 + char public_note[1]; // variable length. + uint16 zoneinstance; // Seen 0s or -1 in RoF2 + uint16 zone_id; // Seen 0s or -1 in RoF2 + uint32 unknown_one2; // unknown, set to 1 + uint32 unknown04; // Seen 0 +}; + +//just for display purposes, this is not actually used in the message encoding other than for size. +struct GuildMembers_Struct { + char player_name[1]; // variable length. + uint32 guildid; // Was unknown02 - network byte order + uint32 count; // network byte order + GuildMemberEntry_Struct member[0]; +}; + +struct GuildMOTD_Struct{ +/*0000*/ uint32 unknown0; +/*0004*/ char name[64]; +/*0068*/ char setby_name[64]; +/*0132*/ uint32 unknown132; +/*0136*/ char motd[0]; //was 512 +}; + +struct GuildURL_Struct{ +/*0000*/ uint32 unknown0; //index? seen server send 0 w/ the Guild URL, followed by 1 with nothing. +/*0004*/ uint32 unknown4; +/*0008*/ uint32 unknown8; //seen 7 +/*0012*/ char setby_name[64]; +/*0076*/ uint32 unknown132; //seen 0xc7de +/*0136*/ char url[4040]; +}; + +struct GuildStatus_Struct +{ +/*000*/ char Name[64]; +/*064*/ uint8 Unknown064[76]; +}; + +struct GuildMemberUpdate_Struct { +/*00*/ uint32 GuildID; +/*04*/ char MemberName[64]; +/*68*/ uint16 ZoneID; +/*70*/ uint16 InstanceID; //speculated +/*72*/ uint32 LastSeen; //unix timestamp +/*76*/ uint32 Unknown76; +/*80*/ +}; + +struct GuildMemberLevelUpdate_Struct { +/*00*/ uint32 guild_id; +/*04*/ char member_name[64]; +/*68*/ uint32 level; //not sure +}; + +struct GuildUpdate_PublicNote { + uint32 unknown0; + char name[64]; + char target[64]; + char note[100]; //we are cutting this off at 100, actually around 252 +}; + +struct GuildDemoteStruct { +/*000*/ char name[64]; +/*064*/ char target[64]; +/*128*/ uint32 rank; // New in RoF2 +/*132*/ +}; + +struct GuildRemoveStruct { +/*000*/ char target[64]; +/*064*/ char name[64]; +/*128*/ uint32 GuildID; // Was unknown128 +/*132*/ uint32 leaderstatus; +/*136*/ uint32 unknown136; // New in RoF2 +/*140*/ +}; + +struct GuildMakeLeader { + char name[64]; + char target[64]; +}; + +// Server -> Client +// Update a guild members rank and banker status +struct GuildSetRank_Struct +{ +/*00*/ uint32 GuildID; // Was Unknown00 +/*04*/ uint32 Rank; +/*08*/ char MemberName[64]; +/*72*/ uint32 Banker; +/*76*/ uint32 Unknown76; // Seen 1 - Maybe Banker? +/*80*/ +}; + +struct BugStruct{ +/*0000*/ char chartype[64]; +/*0064*/ char name[96]; +/*0160*/ char ui[128]; +/*0288*/ float x; +/*0292*/ float y; +/*0296*/ float z; +/*0300*/ float heading; +/*0304*/ uint32 unknown304; +/*0308*/ uint32 type; +/*0312*/ char unknown312[2144]; +/*2456*/ char bug[1024]; +/*3480*/ char placeholder[2]; +/*3482*/ char system_info[4098]; +}; +struct Make_Pet_Struct { //Simple struct for getting pet info + uint8 level; + uint8 class_; + uint16 race; + uint8 texture; + uint8 pettype; + float size; + uint8 type; + uint32 min_dmg; + uint32 max_dmg; +}; +struct Ground_Spawn{ + float max_x; + float max_y; + float min_x; + float min_y; + float max_z; + float heading; + char name[16]; + uint32 item; + uint32 max_allowed; + uint32 respawntimer; +}; +struct Ground_Spawns { + struct Ground_Spawn spawn[50]; //Assigned max number to allow +}; +struct PetitionBug_Struct{ + uint32 petition_number; + uint32 unknown4; + char accountname[64]; + uint32 zoneid; + char name[64]; + uint32 level; + uint32 class_; + uint32 race; + uint32 unknown152[3]; + uint32 time; + uint32 unknown168; + char text[1028]; +}; + +struct DyeStruct +{ + union + { + struct + { + struct Color_Struct head; + struct Color_Struct chest; + struct Color_Struct arms; + struct Color_Struct wrists; + struct Color_Struct hands; + struct Color_Struct legs; + struct Color_Struct feet; + struct Color_Struct primary; // you can't actually dye this + struct Color_Struct secondary; // or this + } + dyes; + struct Color_Struct dye[9]; + }; +}; + +struct ApproveZone_Struct { + char name[64]; + uint32 zoneid; + uint32 approve; +}; +struct ZoneInSendName_Struct { + uint32 unknown0; + char name[64]; + char name2[64]; + uint32 unknown132; +}; +struct ZoneInSendName_Struct2 { + uint32 unknown0; + char name[64]; + uint32 unknown68[145]; +}; + +struct StartTribute_Struct { + uint32 client_id; + uint32 tribute_master_id; + uint32 response; +}; + +struct TributeLevel_Struct { + uint32 level; //backwards byte order! + uint32 tribute_item_id; //backwards byte order! + uint32 cost; //backwards byte order! +}; + +struct TributeAbility_Struct { +/*000*/ uint32 tribute_id; //backwards byte order! +/*004*/ uint32 tier_count; //backwards byte order! +/*008*/ TributeLevel_Struct tiers[MAX_TRIBUTE_TIERS]; +/*128*/ uint32 unknown128; // New to RoF2 +/*132*/ char name[0]; +}; + +struct GuildTributeAbility_Struct { + uint32 guild_id; + TributeAbility_Struct ability; +}; + +struct SelectTributeReq_Struct { + uint32 client_id; //? maybe action ID? + uint32 tribute_id; + uint32 unknown8; //seen E3 00 00 00 +}; + +struct SelectTributeReply_Struct { + uint32 client_id; //echoed from request. + uint32 tribute_id; + char desc[0]; +}; + +struct TributeInfo_Struct { + uint32 active; //0 == inactive, 1 == active + uint32 tributes[MAX_PLAYER_TRIBUTES]; //-1 == NONE + uint32 tiers[MAX_PLAYER_TRIBUTES]; //all 00's + uint32 tribute_master_id; +}; + +struct TributeItem_Struct +{ +/*00*/ ItemSlotStruct slot; +/*12*/ uint32 quantity; +/*16*/ uint32 tribute_master_id; +/*20*/ int32 tribute_points; +/*24*/ +}; + +struct TributePoint_Struct { + int32 tribute_points; + uint32 unknown04; + int32 career_tribute_points; + uint32 unknown12; +}; + +struct TributeMoney_Struct { + uint32 platinum; + uint32 tribute_master_id; + int32 tribute_points; +}; + + +struct Split_Struct +{ + uint32 platinum; + uint32 gold; + uint32 silver; + uint32 copper; +}; + + +/* +** New Combine Struct +** Client requesting to perform a tradeskill combine +** Size: 24 bytes +** Used In: OP_TradeSkillCombine +** Last Updated: 01-05-2013 +*/ +struct NewCombine_Struct { +/*00*/ ItemSlotStruct container_slot; +/*12*/ ItemSlotStruct guildtribute_slot; // Slot type is 8? (MapGuildTribute = 8 -U) +/*24*/ +}; + + +//client requesting favorite recipies +struct TradeskillFavorites_Struct { + uint32 object_type; + uint32 some_id; + uint32 favorite_recipes[500]; +}; + +//search request +struct RecipesSearch_Struct { + uint32 object_type; //same as in favorites + uint32 some_id; //same as in favorites + uint32 mintrivial; + uint32 maxtrivial; + char query[56]; + uint32 unknown4; //is set to 00 03 00 00 + uint32 unknown5; //is set to 4C DD 12 00 +/*80*/ +}; + +//one sent for each item, from server in reply to favorites or search +struct RecipeReply_Struct { + uint32 object_type; + uint32 some_id; //same as in favorites + uint32 component_count; + uint32 recipe_id; + uint32 trivial; + char recipe_name[64]; +/*84*/ +}; + +//received and sent back as an ACK with different reply_code +struct RecipeAutoCombine_Struct { +/*00*/ uint32 object_type; +/*04*/ uint32 some_id; +/*08*/ ItemSlotStruct container_slot; //echoed in reply - Was uint32 unknown1 +/*20*/ ItemSlotStruct unknown_slot; //echoed in reply +/*32*/ uint32 recipe_id; +/*36*/ uint32 reply_code; +/*40*/ +}; + +struct LevelAppearance_Struct { //Sends a little graphic on level up + uint32 spawn_id; + uint32 parm1; + uint32 value1a; + uint32 value1b; + uint32 parm2; + uint32 value2a; + uint32 value2b; + uint32 parm3; + uint32 value3a; + uint32 value3b; + uint32 parm4; + uint32 value4a; + uint32 value4b; + uint32 parm5; + uint32 value5a; + uint32 value5b; +/*64*/ +}; +struct MerchantList{ + uint32 id; + uint32 slot; + uint32 item; +}; +struct TempMerchantList{ + uint32 npcid; + uint32 slot; + uint32 item; + uint32 charges; //charges/quantity + uint32 origslot; +}; + + +struct FindPerson_Point { + float y; + float x; + float z; +}; + +struct FindPersonRequest_Struct { +/*00*/ uint32 unknown00; +/*04*/ uint32 npc_id; +/*08*/ uint32 unknown08; +/*12*/ uint32 unknown12; +/*16*/ FindPerson_Point client_pos; +/*28*/ uint32 unknown28; +/*32*/ uint32 unknown32; +/*36*/ uint32 unknown36; +}; + +//variable length packet of points +struct FindPersonResult_Struct { + FindPerson_Point dest; + FindPerson_Point path[0]; //last element must be the same as dest +}; + +struct MobRename_Struct { +/*000*/ char old_name[64]; +/*064*/ char old_name_again[64]; //not sure what the difference is +/*128*/ char new_name[64]; +/*192*/ uint32 unknown192; //set to 0 +/*196*/ uint32 unknown196; //set to 1 +/*200*/ +}; + +struct PlayMP3_Struct { + char filename[0]; +}; + +//this is for custom title display in the skill window +struct TitleEntry_Struct { + uint32 skill_id; + uint32 skill_value; + char title[1]; +}; + +struct Titles_Struct { + uint32 title_count; + TitleEntry_Struct titles[0]; +}; + +//this is for title selection by the client +struct TitleListEntry_Struct { + uint32 unknown0; //title ID + char prefix[1]; //variable length, null terminated + char postfix[1]; //variable length, null terminated +}; + +struct TitleList_Struct { + uint32 title_count; + TitleListEntry_Struct titles[0]; //list of title structs + //uint32 unknown_ending; seen 0x7265, 0 +}; + +struct SetTitle_Struct { + uint32 is_suffix; //guessed: 0 = prefix, 1 = suffix + uint32 title_id; +}; + +struct SetTitleReply_Struct { + uint32 is_suffix; //guessed: 0 = prefix, 1 = suffix + char title[32]; + uint32 entity_id; +}; + + +#if 0 +// Old struct not used by Task System implementation but left for reference +struct TaskDescription_Struct { +/*000*/ uint32 activity_count; //not right. +/*004*/ uint32 taskid; +/*008*/ uint8 unk; +/*009*/ uint32 id3; +/*013*/ uint32 unknown13; +/*017*/ char name[1]; //variable length, 0 terminated +/*018*/ uint32 unknown18; +/*022*/ uint32 unknown22; +/*026*/ uint32 unknown26; +/*030*/ char desc[1]; //variable length, 0 terminated +/*031*/ uint32 reward_count; //not sure +/*035*/ uint8 unknown31; +/*036*/ uint32 unknown31; +/*040*/ uint32 unknown35; +/*044*/ uint16 unknown39; +/*046*/ char reward_link[1]; //variable length, 0 terminated +/*047*/ uint32 unknown43; //maybe crystal count? +/*051*/ +}; +#endif + +struct TaskMemberList_Struct { +/*00*/ uint32 gopher_id; +/*04*/ uint32 unknown04; +/*08*/ uint32 member_count; //1 less than the number of members +/*12*/ char list_pointer[0]; +/* list is of the form: + char member_name[1] //null terminated string + uint8 task_leader //boolean flag +*/ +}; + +#if 0 +// Struct not used by Task System implentation but left for reference (current for RoF2) +struct TaskActivity_Struct { +/*000*/ uint32 TaskSequenceNumber; +/*004*/ uint32 unknown2; +/*008*/ uint32 TaskID; +/*012*/ uint32 ActivityID; +/*016*/ uint32 unknown3; +/*020*/ uint32 ActivityType; +/*024*/ uint32 Optional; +/*028*/ uint8 unknown5; +/*032*/ char Text1[1]; // Variable length - Null terminated +/*000*/ uint32 Text2Len; // Lenth of the following string +/*000*/ char Text2[1]; // Variable length - not Null terminated +/*000*/ uint32 GoalCount; +/*000*/ uint32 String1Len; // Lenth of the following string - Seen 2 +/*000*/ char String1[1]; // Numeric String - Seen "-1" - not Null terminated +/*000*/ uint32 String2Len; // Lenth of the following string - Seen 2 +/*000*/ char String2[1]; // Numeric String - Seen "-1" - not Null terminated +/*000*/ char ZoneIDString1[1]; // Numeric String - Seen "398" - Null terminated +/*000*/ uint32 unknown7; // Seen 0 +/*000*/ char Text3[1]; // Variable length - Null terminated +/*000*/ uint32 DoneCount; +/*000*/ uint8 unknown9; // Seen 1 +/*000*/ char ZoneIDString2[1]; // Numeric String - Seen "398" - Null terminated +}; + +struct TaskHistoryEntry_Struct { + uint32 task_id; + char name[1]; + uint32 completed_time; +}; +struct TaskHistory_Struct { + uint32 completed_count; + TaskHistoryEntry_Struct entries[0]; +}; +#endif + +struct AcceptNewTask_Struct { + uint32 unknown00; + uint32 task_id; //set to 0 for 'decline' + uint32 task_master_id; //entity ID +}; + +//was all 0's from client, server replied with same op, all 0's +struct CancelTask_Struct { + uint32 SequenceNumber; + uint32 unknown4; // Only seen 0x00000002 +}; + +#if 0 +// old struct, not used by Task System implementation but left for reference. +struct AvaliableTask_Struct { + uint32 task_index; //no idea, seen 0x1 + uint32 task_master_id; //entity ID + uint32 task_id; + uint32 unknown012; + uint32 activity_count; //not sure, seen 2 + char desc[1]; //variable length, 0 terminated + uint32 reward_platinum;//not sure on these + uint32 reward_gold; + uint32 reward_silver; + uint32 reward_copper; + char some_name[1]; //variable length, 0 terminated + uint8 unknown1; + uint32 unknown2; //0xFFFFFFFF + uint32 unknown3; //0xFFFFFFFF + uint32 unknown4; //seen 0x16 + uint8 unknown5; +}; +#endif + + +// Many of the Task System packets contain variable length strings, as well as variable numbers +// of records, hence splitting them into multiple structs (header, middle, trailer) etc. +// +struct AvailableTaskHeader_Struct { + uint32 TaskCount; + uint32 unknown1; + uint32 TaskGiver; +}; + +struct AvailableTaskData1_Struct { + uint32 TaskID; + uint32 unknown1; + uint32 TimeLimit; + uint32 unknown2; +}; + +struct AvailableTaskData2_Struct { + uint32 unknown1,unknown2,unknown3,unknown4; +}; + +struct AvailableTaskTrailer_Struct { + uint32 ItemCount; + uint32 unknown1, unknown2; + uint32 StartZone; +}; + +struct TaskDescriptionHeader_Struct { + uint32 SequenceNumber; // The order the tasks appear in the journal. 0 for first task, 1 for second, etc. + uint32 TaskID; + uint32 unknown2; + uint32 unknown3; + uint8 unknown4; +}; + +struct TaskDescriptionData1_Struct { + uint32 Duration; + uint32 unknown2; + uint32 StartTime; +}; + +struct TaskDescriptionData2_Struct { + uint32 RewardCount; // ?? + uint32 unknown1; + uint32 unknown2; + uint16 unknown3; + //uint8 unknown4; +}; + +struct TaskDescriptionTrailer_Struct { + //uint16 unknown1; // 0x0012 + uint32 Points; +}; + +struct TaskActivityHeader_Struct { + uint32 TaskSequenceNumber; + uint32 unknown2; // Seen 0x00000002 + uint32 TaskID; + uint32 ActivityID; + uint32 unknown3; + uint32 ActivityType; + uint32 Optional; + uint32 unknown5; +}; + +struct TaskActivityData1_Struct { + uint32 GoalCount; + uint32 unknown1; // 0xffffffff + uint32 unknown2; // 0xffffffff + uint32 ZoneID; // seen 0x36 + uint32 unknown3; +}; + +struct TaskActivityTrailer_Struct { + uint32 DoneCount; + uint32 unknown1; // Seen 1 +}; + +// The Short_Struct is sent for tasks that are hidden and act as a placeholder +struct TaskActivityShort_Struct { + uint32 TaskSequenceNumber; + uint32 unknown2; // Seen 0x00000002 + uint32 TaskID; + uint32 ActivityID; + uint32 unknown3; + uint32 ActivityType; // 0xffffffff for the short packet + uint32 unknown4; +}; + +struct TaskActivityComplete_Struct { + uint32 TaskIndex; + uint32 unknown2; // 0x00000002 + uint32 unknown3; + uint32 ActivityID; + uint32 unknown4; // 0x00000001 + uint32 unknown5; // 0x00000001 +}; + +#if 0 +// This is a dupe of the CancelTask struct +struct TaskComplete_Struct { + uint32 unknown00; // 0x00000000 + uint32 unknown04; // 0x00000002 +}; +#endif + +struct TaskHistoryRequest_Struct { + uint32 TaskIndex; // This is the sequence the task was sent in the Completed Tasks packet. +}; + +struct TaskHistoryReplyHeader_Struct { + uint32 TaskID; + uint32 ActivityCount; +}; + +struct TaskHistoryReplyData1_Struct { + uint32 ActivityType; +}; + +struct TaskHistoryReplyData2_Struct { + uint32 GoalCount; + uint32 unknown04; // 0xffffffff + uint32 unknown08; // 0xffffffff + uint32 ZoneID; + uint32 unknown16; +}; + +struct BankerChange_Struct { +/*00*/ uint32 platinum; +/*04*/ uint32 gold; +/*08*/ uint32 silver; +/*12*/ uint32 copper; +/*16*/ uint32 platinum_bank; +/*20*/ uint32 gold_bank; +/*24*/ uint32 silver_bank; +/*28*/ uint32 copper_bank; +/*32*/ +}; + +struct LeadershipExpUpdate_Struct { +/*00*/ double group_leadership_exp; +/*08*/ uint32 group_leadership_points; +/*12*/ uint32 Unknown12; +/*16*/ double raid_leadership_exp; +/*24*/ uint32 raid_leadership_points; +}; + +struct UpdateLeadershipAA_Struct { +/*00*/ uint32 ability_id; +/*04*/ uint32 new_rank; +/*08*/ uint32 unknown08; +/*12*/ +}; + +/** +* Leadership AA update +* Length: 32 Octets +* OpCode: LeadExpUpdate +*/ +struct leadExpUpdateStruct { + /*0000*/ uint32 unknown0000; // All zeroes? + /*0004*/ uint32 group_leadership_exp; // Group leadership exp value + /*0008*/ uint32 group_leadership_points; // Unspent group points + /*0012*/ uint32 unknown0012; // Type? + /*0016*/ uint32 unknown0016; // All zeroes? + /*0020*/ uint32 raid_leadership_exp; // Raid leadership exp value + /*0024*/ uint32 raid_leadership_points; // Unspent raid points + /*0028*/ uint32 unknown0028; +}; + +struct RaidGeneral_Struct { +/*00*/ uint32 action; +/*04*/ char player_name[64]; +/*68*/ uint32 unknown68; +/*72*/ char leader_name[64]; +/*136*/ uint32 parameter; +}; + +struct RaidAddMember_Struct { +/*000*/ RaidGeneral_Struct raidGen; //param = (group num-1); 0xFFFFFFFF = no group +/*136*/ uint8 _class; +/*137*/ uint8 level; +/*138*/ uint8 isGroupLeader; +/*139*/ uint8 flags[5]; //no idea if these are needed... +}; + +struct RaidMOTD_Struct { +/*000*/ RaidGeneral_Struct general; // leader_name and action only used +/*140*/ char motd[0]; // max size 1024, but reply is variable +}; + +struct RaidLeadershipUpdate_Struct { +/*000*/ uint32 action; +/*004*/ char player_name[64]; +/*068*/ uint32 Unknown068; +/*072*/ char leader_name[64]; +/*136*/ GroupLeadershipAA_Struct group; //unneeded +/*200*/ RaidLeadershipAA_Struct raid; +/*264*/ char Unknown264[128]; +}; + +struct RaidAdd_Struct { +/*000*/ uint32 action; //=0 +/*004*/ char player_name[64]; //should both be the player's name +/*068*/ char leader_name[64]; +/*132*/ uint8 _class; +/*133*/ uint8 level; +/*134*/ uint8 has_group; +/*135*/ uint8 unknown135; //seems to be 0x42 or 0 +}; + +struct RaidCreate_Struct { +/*00*/ uint32 action; //=8 +/*04*/ char leader_name[64]; +/*68*/ uint32 leader_id; +}; + +struct RaidMemberInfo_Struct { +/*00*/ uint8 group_number; +/*01*/ char member_name[1]; //dyanmic length, null terminated '\0' +/*00*/ uint8 unknown00; +/*01*/ uint8 _class; +/*02*/ uint8 level; +/*03*/ uint8 is_raid_leader; +/*04*/ uint8 is_group_leader; +/*05*/ uint8 main_tank; //not sure +/*06*/ uint8 unknown06[5]; //prolly more flags +}; + +struct RaidDetails_Struct { +/*000*/ uint32 action; //=6,20 +/*004*/ char leader_name[64]; +/*068*/ uint32 unknown68[4]; +/*084*/ LeadershipAA_Struct abilities; //ranks in backwards byte order +/*128*/ uint8 unknown128[142]; +/*354*/ uint32 leader_id; +}; + +struct RaidMembers_Struct { +/*000*/ RaidDetails_Struct details; +/*358*/ uint32 member_count; //including leader +/*362*/ RaidMemberInfo_Struct members[1]; +/*...*/ RaidMemberInfo_Struct empty; //seem to have an extra member with a 0 length name on the end +}; + +struct DynamicWall_Struct { +/*00*/ char name[32]; +/*32*/ float y; +/*36*/ float x; +/*40*/ float z; +/*44*/ uint32 something; +/*48*/ uint32 unknown48; //0 +/*52*/ uint32 one_hundred; //0x64 +/*56*/ uint32 unknown56; //0 +/*60*/ uint32 something2; +/*64*/ int32 unknown64; //-1 +/*68*/ uint32 unknown68; //0 +/*72*/ uint32 unknown72; //0 +/*76*/ uint32 unknown76; //0x100 +/*80*/ +}; + +enum { //bandolier actions + BandolierCreate = 0, + BandolierRemove = 1, + BandolierSet = 2 +}; + +struct BandolierCreate_Struct { +/*00*/ uint32 action; //0 for create +/*04*/ uint8 number; +/*05*/ char name[32]; +/*37*/ uint16 unknown37; //seen 0x93FD +/*39*/ uint8 unknown39; //0 +}; + +struct BandolierDelete_Struct { +/*00*/ uint32 action; +/*04*/ uint8 number; +/*05*/ uint8 unknown05[35]; +}; + +struct BandolierSet_Struct { +/*00*/ uint32 action; +/*04*/ uint8 number; +/*05*/ uint8 unknown05[35]; +}; + +struct Arrow_Struct { +/*000*/ float src_y; +/*004*/ float src_x; +/*008*/ float src_z; +/*012*/ uint8 unknown012[12]; +/*024*/ float velocity; //4 is normal, 20 is quite fast +/*028*/ float launch_angle; //0-450ish, not sure the units, 140ish is straight +/*032*/ float tilt; //on the order of 125 +/*036*/ uint8 unknown036[8]; +/*044*/ float arc; +/*048*/ uint32 source_id; +/*052*/ uint32 target_id; //entity ID +/*056*/ uint32 item_id; +/*060*/ uint32 unknown060; +/*064*/ uint32 unknown064; +/*068*/ uint8 unknown068; +/*069*/ uint8 unknown069; +/*070*/ uint8 unknown070; +/*071*/ uint8 item_type; +/*072*/ uint8 skill; +/*073*/ uint8 unknown073[16]; +/*089*/ char model_name[27]; +/*116*/ +}; + +//made a bunch of trivial structs for stuff for opcode finder to use +struct Consent_Struct { + char name[1]; //always at least a null - was 1 +}; + +struct AdventureMerchant_Struct { + uint32 unknown_flag; //seems to be 1 + uint32 entity_id; +}; + +// OP_Save - Size: 484 +struct Save_Struct { +/*000*/ uint8 unknown00[192]; +/*192*/ uint8 unknown0192[176]; +/*368*/ uint8 unknown0368[116]; +/*484*/ +}; + +struct GMToggle_Struct { + uint8 unknown0[64]; + uint32 toggle; +}; + +struct ColoredText_Struct { + uint32 color; + char msg[1]; //was 1 +/*0???*/ uint8 paddingXXX[3]; // always 0's +}; + +struct UseAA_Struct { + uint32 begin; + uint32 ability; + uint32 end; +}; + +struct AA_Ability { +/*00*/ uint32 skill_id; +/*04*/ uint32 base1; +/*08*/ uint32 base2; +/*12*/ uint32 slot; +/*16*/ +}; + +struct SendAA_Struct { +/*0000*/ uint32 id; +/*0004*/ uint8 unknown004; // uint32 unknown004; set to 1. +/*0005*/ int32 hotkey_sid; +/*0009*/ int32 hotkey_sid2; +/*0013*/ uint32 title_sid; +/*0017*/ uint32 desc_sid; +/*0021*/ uint32 class_type; +/*0025*/ uint32 cost; +/*0029*/ uint32 seq; +/*0033*/ uint32 current_level; //1s, MQ2 calls this AARankRequired +/*0037*/ uint32 unknown037; // Introduced during HoT +/*0041*/ uint32 prereq_skill; //is < 0, abs() is category # +/*0045*/ uint32 unknown045; // New Mar 21 2012 - Seen 1 +/*0049*/ uint32 prereq_minpoints; //min points in the prereq +/*0053*/ uint32 type; +/*0057*/ uint32 spellid; +/*0061*/ uint32 unknown057; // Introduced during HoT - Seen 1 - Maybe account status or enable/disable AA? +/*0065*/ uint32 spell_type; +/*0069*/ uint32 spell_refresh; +/*0073*/ uint16 classes; +/*0075*/ uint16 berserker; //seems to be 1 if its a berserker ability +/*0077*/ uint32 max_level; +/*0081*/ uint32 last_id; +/*0085*/ uint32 next_id; +/*0089*/ uint32 cost2; +/*0093*/ uint8 unknown80[7]; +/*0100*/ uint32 aa_expansion; +/*0104*/ uint32 special_category; +/*0108*/ uint32 unknown0096; +/*0112*/ uint32 total_abilities; +/*0116*/ AA_Ability abilities[0]; +}; + +struct AA_List { + SendAA_Struct* aa[0]; +}; + +struct AA_Action { +/*00*/ uint32 action; +/*04*/ uint32 ability; +/*08*/ uint32 unknown08; +/*12*/ uint32 exp_value; +/*16*/ +}; + +struct AA_Skills { //this should be removed and changed to AA_Array +/*00*/ uint32 aa_skill; // Total AAs Spent +/*04*/ uint32 aa_value; +/*08*/ uint32 unknown08; +/*12*/ +}; + +struct AAExpUpdate_Struct { +/*00*/ uint32 unknown00; //seems to be a value from AA_Action.ability +/*04*/ uint32 aapoints_unspent; +/*08*/ uint8 aaxp_percent; //% of exp that goes to AAs +/*09*/ uint8 unknown09[3]; //live doesn't always zero these, so they arnt part of aaxp_percent +/*12*/ +}; + +struct AltAdvStats_Struct { +/*000*/ uint32 experience; +/*004*/ uint16 unspent; +/*006*/ uint16 unknown006; +/*008*/ uint8 percentage; +/*009*/ uint8 unknown009[3]; +/*012*/ +}; + +struct PlayerAA_Struct { // Is this still used? + AA_Skills aa_list[MAX_PP_AA_ARRAY]; +}; + +struct AA_Values { +/*00*/ uint32 aa_skill; +/*04*/ uint32 aa_value; +/*08*/ uint32 unknown08; +/*12*/ +}; + +struct AATable_Struct { +/*00*/ uint32 aa_spent; // Total AAs Spent +/*04*/ uint32 aapoints_assigned; // Number of Assigned AA points - Seen 206 (total of the 4 fields below) +/*08*/ uint32 aa_spent_general; // Seen 63 +/*12*/ uint32 aa_spent_archetype; // Seen 40 +/*16*/ uint32 aa_spent_class; // Seen 103 +/*20*/ uint32 aa_spent_special; // Seen 0 +/*24*/ AA_Values aa_list[MAX_PP_AA_ARRAY]; +}; + +struct Weather_Struct { + uint32 val1; //generall 0x000000FF + uint32 type; //0x31=rain, 0x02=snow(i think), 0 = normal + uint32 mode; +}; + +struct ZoneInUnknown_Struct { + uint32 val1; + uint32 val2; + uint32 val3; +}; + +struct MobHealth_Struct { + uint16 entity_id; + uint8 hp; +}; + +struct AnnoyingZoneUnknown_Struct { + uint32 entity_id; + uint32 value; //always 4 +}; + +struct LoadSpellSet_Struct { + uint8 spell[12]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 + uint32 unknown; //Seen 12 - Maybe a gem count? +}; + +struct BlockedBuffs_Struct +{ +/*000*/ int32 SpellID[BLOCKED_BUFF_COUNT]; +/*120*/ uint32 Count; +/*124*/ uint8 Pet; +/*125*/ uint8 Initialise; +/*126*/ uint16 Flags; +}; + +//Size 24 Bytes +struct WorldObfuscator_Struct { +/*000*/ uint32 var1; +/*004*/ uint32 Unknown1; +/*008*/ uint32 Unknown2; +/*012*/ uint32 Unknown3; +/*016*/ uint32 var2; +/*020*/ uint32 Unknown4; +/*024*/ +}; + +struct ExpansionInfo_Struct { +/*000*/ char Unknown000[64]; +/*064*/ uint32 Expansions; +}; + +struct ApplyPoison_Struct { + MainInvItemSlotStruct inventorySlot; + uint32 success; +}; + +struct ItemVerifyRequest_Struct { +/*000*/ ItemSlotStruct slot; +/*012*/ uint32 target; // Target Entity ID +/*016*/ +}; + +struct ItemVerifyReply_Struct { +/*000*/ ItemSlotStruct slot; +/*012*/ uint32 spell; // Spell ID to cast if different than item effect +/*016*/ uint32 target; // Target Entity ID +/*020*/ +}; + + +struct RoF2SlotStruct +{ + uint8 Bank; + uint16 MainSlot; + uint16 SubSlot; +}; + +struct ItemSerializationHeader +{ +/*000*/ char unknown000[13]; // New for HoT. Looks like a string. +/*017*/ uint32 stacksize; +/*021*/ uint32 unknown004; +/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ? +/*026*/ uint16 main_slot; +/*028*/ uint16 sub_slot; +/*030*/ uint16 unknown013; // 0xffff +/*032*/ uint32 price; +/*036*/ uint32 merchant_slot; //1 if not a merchant item +/*040*/ uint32 scaled_value; //0 +/*044*/ uint32 instance_id; //unique instance id if not merchant item, else is merchant slot +/*048*/ uint32 unknown028; //0 +/*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0 +/*056*/ uint32 charges; //Total Charges an item has (-1 for unlimited) +/*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items) +/*064*/ uint32 unknown044; // 0 +/*068*/ uint32 unknown048; // 0 +/*072*/ uint32 unknown052; // 0 + uint8 isEvolving; +}; + +struct EvolvingItem { + uint8 unknown001; + uint8 unknown002; + uint8 unknown003; + uint8 unknown004; + int32 evoLevel; + double progress; + uint8 Activated; + int32 evomaxlevel; + uint8 unknown005[4]; +}; + +struct ItemSerializationHeaderFinish +{ + uint16 ornamentIcon; +/*081*/ uint8 unknown061; // 0 - Add Evolving Item struct if this isn't set to 0? +/*082*/ uint8 unknown062; // 0 +/*083*/ uint32 unknowna1; // 0xffffffff +/*087*/ uint32 unknowna2; // 0 +/*091*/ uint8 unknown063; // 0 +/*092*/ uint32 unknowna3; // 0 +/*096*/ uint32 unknowna4; // 0xffffffff +/*100*/ uint32 unknowna5; // 0 +/*104*/ uint8 ItemClass; //0, 1, or 2 +/*105*/ +}; + +struct ItemBodyStruct +{ + uint32 id; + int32 weight; // Seen an item on Live with -0.1 weight + uint8 norent; + uint8 nodrop; + uint8 attune; + uint8 size; + uint32 slots; + uint32 price; + uint32 icon; + uint8 unknown1; + uint8 unknown2; + uint32 BenefitFlag; + uint8 tradeskills; + int8 CR; + int8 DR; + int8 PR; + int8 MR; + int8 FR; + int8 SVCorruption; + int8 AStr; + int8 ASta; + int8 AAgi; + int8 ADex; + int8 ACha; + int8 AInt; + int8 AWis; + int32 HP; + int32 Mana; + uint32 Endur; + int32 AC; + int32 regen; + int32 mana_regen; + int32 end_regen; + uint32 Classes; + uint32 Races; + uint32 Deity; + int32 SkillModValue; + int32 SkillModMax; // Max skill point modification + int32 SkillModType; + uint32 SkillModExtra; // Adds a "+value" after the mod percentage + uint32 BaneDmgRace; + uint32 BaneDmgBody; + uint32 BaneDmgRaceAmt; + int32 BaneDmgAmt; + uint8 Magic; + int32 CastTime_; + uint32 ReqLevel; + uint32 RecLevel; + uint32 RecSkill; + uint32 BardType; + int32 BardValue; + uint8 Light; + uint8 Delay; + uint8 ElemDmgType; + uint8 ElemDmgAmt; + uint8 Range; + uint32 Damage; + uint32 Color; + uint32 Prestige; // New to March 21 2012 client + uint8 ItemType; + uint32 Material; + uint32 unknown7; + uint32 EliteMaterial; + uint32 unknown_RoF23; // New to March 21 2012 client + uint32 unknown_RoF24; // New to December 10th 2012 client - NEW + float SellRate; + int32 CombatEffects; + int32 Shielding; + int32 StunResist; + int32 StrikeThrough; + int32 ExtraDmgSkill; + int32 ExtraDmgAmt; + int32 SpellShield; + int32 Avoidance; + int32 Accuracy; + uint32 CharmFileID; + uint32 FactionMod1; + int32 FactionAmt1; + uint32 FactionMod2; + int32 FactionAmt2; + uint32 FactionMod3; + int32 FactionAmt3; + uint32 FactionMod4; + int32 FactionAmt4; +}; + +struct AugSlotStruct +{ + uint32 type; + uint8 visible; + uint8 unknown; +}; + +struct ItemSecondaryBodyStruct +{ + uint32 augtype; + // swapped augrestrict and augdistiller positions + // (this swap does show the proper augment restrictions in Item Information window now) + // unsure what the purpose of augdistiller is at this time -U 3/17/2014 + uint32 augdistiller; // New to December 10th 2012 client - NEW + uint32 augrestrict; + AugSlotStruct augslots[6]; + + uint32 ldonpoint_type; + uint32 ldontheme; + uint32 ldonprice; + uint32 ldonsellbackrate; + uint32 ldonsold; + + uint8 bagtype; + uint8 bagslots; + uint8 bagsize; + uint8 wreduction; + + uint8 book; + uint8 booktype; + //int32 filename; filename is either 0xffffffff/0x00000000 or the null term string ex: CREWizardNote\0 +}; + +struct ItemTertiaryBodyStruct +{ + int32 loregroup; + uint8 artifact; + uint8 summonedflag; + uint32 favor; + uint8 fvnodrop; + int32 dotshield; + int32 atk; + int32 haste; + int32 damage_shield; + uint32 guildfavor; + uint32 augdistil; + int32 unknown3; // 0xffffffff + uint32 unknown4; + uint8 no_pet; + uint8 unknown5; + + uint8 potion_belt_enabled; + uint32 potion_belt_slots; + + uint32 stacksize; + uint8 no_transfer; + uint16 expendablearrow; + + uint32 unknown8; + uint32 unknown9; + uint32 unknown10; + uint32 unknown11; + uint8 unknown12; + uint8 unknown13; + uint8 unknown14; +}; + +struct ClickEffectStruct +{ + int32 effect; + uint8 level2; + uint32 type; + uint8 level; + int32 max_charges; + int32 cast_time; + uint32 recast; + int32 recast_type; + uint32 clickunk5; + //uint8 effect_string; + //int32 clickunk7; +}; + +struct ProcEffectStruct +{ + uint32 effect; + uint8 level2; + uint32 type; + uint8 level; + uint32 unknown1; // poison? + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 procrate; + //uint8 effect_string; + //uint32 unknown5; +}; + +struct WornEffectStruct //worn, focus and scroll effect +{ + uint32 effect; + uint8 level2; + uint32 type; + uint8 level; + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 unknown5; + //uint8 effect_string; + //uint32 unknown6; +}; + +struct ItemQuaternaryBodyStruct +{ + uint32 scriptfileid; + uint8 quest_item; + uint32 Power; // Enables "Power" percentage field used by Power Sources + uint32 Purity; + uint8 unknown16; // RoF2 + uint32 BackstabDmg; + uint32 DSMitigation; + int32 HeroicStr; + int32 HeroicInt; + int32 HeroicWis; + int32 HeroicAgi; + int32 HeroicDex; + int32 HeroicSta; + int32 HeroicCha; + int32 HeroicMR; + int32 HeroicFR; + int32 HeroicCR; + int32 HeroicDR; + int32 HeroicPR; + int32 HeroicSVCorrup; + int32 HealAmt; + int32 SpellDmg; + int32 clairvoyance; + uint8 unknown18; //Power Source Capacity or evolve filename? + uint32 evolve_string; // Some String, but being evolution related is just a guess + uint8 unknown19; + uint32 unknown20; // Bard Stuff? + //uint32 unknown21; + uint8 unknown22; + uint32 unknown23; + uint32 unknown24; + uint32 unknown25; + float unknown26; + float unknown27; + uint32 unknown_RoF26; // 0 New to March 21 2012 client + uint32 unknown28; // 0xffffffff + uint16 unknown29; + uint32 unknown30; // 0xffffffff + uint16 unknown31; + uint32 unknown32; + float unknown33; + uint32 unknown34; + uint32 unknown35; + uint32 unknown36; + uint32 unknown37; + uint32 unknown_RoF27; + uint32 unknown_RoF28; + + // Begin RoF2 Test + uint8 unknown_TEST1; + // End RoF2 Test + + uint8 unknown38; // 0 + uint8 unknown39; // 1 + uint32 subitem_count; +}; + +struct AugmentInfo_Struct +{ +/*000*/ uint32 itemid; // id of the solvent needed +/*004*/ uint32 window; // window to display the information in +/*008*/ char augment_info[64]; // total packet length 76, all the rest were always 00 +/*072*/ uint32 unknown072; +}; + +struct VeteranRewardItem +{ +/*000*/ uint32 item_id; +/*004*/ uint32 charges; +/*008*/ char item_name[64]; +}; + +struct VeteranReward +{ +/*000*/ uint32 claim_id; +/*004*/ uint32 number_available; +/*008*/ uint32 claim_count; +/*012*/ VeteranRewardItem items[8]; +}; + +struct ExpeditionEntryHeader_Struct +{ +/*000*/ uint32 unknown000; +/*000*/ uint32 number_of_entries; +}; + +struct ExpeditionJoinPrompt_Struct +{ +/*000*/ uint32 clientid; +/*004*/ uint32 unknown004; +/*008*/ char player_name[64]; +/*072*/ char expedition_name[64]; +}; + +struct ExpeditionExpireWarning +{ +/*000*/ uint32 clientid; +/*004*/ uint32 unknown004; +/*008*/ uint32 minutes_remaining; +}; + +struct ExpeditionInfo_Struct +{ +/*000*/ uint32 clientid; +/*004*/ uint32 unknown004; +/*008*/ uint32 unknown008; +/*012*/ uint32 max_players; +/*016*/ char expedition_name[128]; +/*142*/ char leader_name[64]; +}; + +struct ExpeditionCompassEntry_Struct +{ +/*000*/ float unknown000; //seen *((uint32*)) = 1584791871 +/*004*/ uint32 enabled; //guess +/*008*/ uint32 unknown008; //seen 1019 +/*012*/ float y; +/*016*/ float x; +/*020*/ float z; +}; + +struct ExpeditionCompass_Struct +{ +/*000*/ uint32 clientid; +/*004*/ uint32 count; +/*008*/ ExpeditionCompassEntry_Struct entries[0]; +}; + +struct MaxCharacters_Struct +{ +/*000*/ uint32 max_chars; // Seen 4 on Silver Account (4 chars max) +/*004*/ uint32 unknown004; // Seen 0 +/*008*/ uint32 unknown008; // Seen 0 +}; + +// Used by MercenaryListEntry_Struct +struct MercenaryStance_Struct { +/*0000*/ uint32 StanceIndex; // Index of this stance (sometimes reverse reverse order - 3, 2, 1, 0 for 4 stances etc) +/*0004*/ uint32 Stance; // From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc +}; +// Used by MercenaryMerchantList_Struct +struct MercenaryListEntry_Struct { +/*0000*/ uint32 MercID; // ID unique to each type of mercenary (probably a DB id) +/*0004*/ uint32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300) +/*0008*/ uint32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan
Type: Healer
Confidence: High
Proficiency: Apprentice, Tier V... +/*0012*/ uint32 PurchaseCost; // Purchase Cost (in gold) +/*0016*/ uint32 UpkeepCost; // Upkeep Cost (in gold) +/*0020*/ uint32 Status; // Required Account Status (Free = 0, Silver = 1, Gold = 2) at merchants - Seen 0 (suspended) or 1 (unsuspended) on hired mercs ? +/*0024*/ uint32 AltCurrencyCost; // Alternate Currency Purchase Cost? (all seen costs show N/A Bayle Mark) - Seen 0 +/*0028*/ uint32 AltCurrencyUpkeep; // Alternate Currency Upkeep Cost? (all seen costs show 1 Bayle Mark) - Seen 1 +/*0032*/ uint32 AltCurrencyType; // Alternate Currency Type? - 19^17^Bayle Mark^0 - Seen 19 +/*0036*/ uint8 MercUnk01; // Unknown (always see 0) +/*0037*/ int32 TimeLeft; // Unknown (always see -1 at merchant) - Seen 900000 (15 minutes in ms for newly hired merc) +/*0041*/ uint32 MerchantSlot; // Merchant Slot? Increments, but not always by 1 - May be for Merc Window Options (Seen 5, 36, 1 for active mercs)? +/*0045*/ uint32 MercUnk02; // Unknown (normally see 1, but sometimes 2 or 0) +/*0049*/ uint32 StanceCount; // Iterations of MercenaryStance_Struct - Normally 2 to 4 seen +/*0053*/ int32 MercUnk03; // Unknown (always 0 at merchant) - Seen on active merc: 93 a4 03 77, b8 ed 2f 26, 88 d5 8b c3, and 93 a4 ad 77 +/*0057*/ uint8 MercUnk04; // Seen 1 +/*0058*/ char MercName[1]; // Null Terminated Mercenary Name (00 at merchants) +/*0000*/ MercenaryStance_Struct Stances[1]; // Count Varies - From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc +}; + +// Sent by the server when browsing the Mercenary Merchant +struct MercenaryMerchantList_Struct { +/*0000*/ uint32 MercTypeCount; // Number of Merc Types to follow +/*0004*/ uint32 MercTypes[1]; // Count varies, but hard set to 3 max for now - From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300) +/*0016*/ uint32 MercCount; // Number of MercenaryInfo_Struct to follow +/*0020*/ MercenaryListEntry_Struct Mercs[0]; // Data for individual mercenaries in the Merchant List +}; + +// OP_MercenaryDataRequest +// Right clicking merchant - shop request +struct MercenaryMerchantShopRequest_Struct { +/*0000*/ uint32 MercMerchantID; // Entity ID of the Mercenary Merchant +/*0004*/ +}; + +// Used by MercenaryDataUpdate_Struct +struct MercenaryData_Struct { +/*0000*/ uint32 MercID; // ID unique to each type of mercenary (probably a DB id) - (if 1, do not send MercenaryData_Struct - No merc hired) +/*0004*/ uint32 MercType; // From dbstr_us.txt - Apprentice (330000100), Journeyman (330000200), Master (330000300) +/*0008*/ uint32 MercSubType; // From dbstr_us.txt - 330020105^23^Race: Guktan
Type: Healer
Confidence: High
Proficiency: Apprentice, Tier V... +/*0012*/ uint32 PurchaseCost; // Purchase Cost (in gold) +/*0016*/ uint32 UpkeepCost; // Upkeep Cost (in gold) +/*0020*/ uint32 Status; // Required Account Status (Free = 0, Silver = 1, Gold = 2) at merchants - Seen 0 (suspended) or 1 (unsuspended) on hired mercs ? +/*0024*/ uint32 AltCurrencyCost; // Alternate Currency Purchase Cost? (all seen costs show N/A Bayle Mark) - Seen 0 +/*0028*/ uint32 AltCurrencyUpkeep; // Alternate Currency Upkeep Cost? (all seen costs show 1 Bayle Mark) - Seen 1 +/*0032*/ uint32 AltCurrencyType; // Alternate Currency Type? - 19^17^Bayle Mark^0 - Seen 19 +/*0036*/ uint8 MercUnk01; // Unknown (always see 0) +/*0037*/ int32 TimeLeft; // Unknown (always see -1 at merchant) - Seen 900000 (15 minutes in ms for newly hired merc) +/*0041*/ uint32 MerchantSlot; // Merchant Slot? Increments, but not always by 1 - May be for Merc Window Options (Seen 5, 36, 1 for active mercs)? +/*0045*/ uint32 MercUnk02; // Unknown (normally see 1, but sometimes 2 or 0) +/*0049*/ uint32 StanceCount; // Iterations of MercenaryStance_Struct - Normally 2 to 4 seen +/*0053*/ int32 MercUnk03; // Unknown (always 0 at merchant) - Seen on active merc: 93 a4 03 77, b8 ed 2f 26, 88 d5 8b c3, and 93 a4 ad 77 +/*0057*/ uint8 MercUnk04; // Seen 1 +/*0058*/ char MercName[1]; // Null Terminated Mercenary Name (00 at merchants) +/*0000*/ MercenaryStance_Struct Stances[1]; // Count Varies, but hard set to 2 for now - From dbstr_us.txt - 1^24^Passive^0, 2^24^Balanced^0, etc (1 to 9 as of April 2012) +/*0000*/ uint32 MercUnk05; // Seen 1 - Extra Merc Data field that differs from MercenaryListEntry_Struct +// MercUnk05 may be a field that is at the end of the packet only, even if multiple mercs are listed (haven't seen examples of multiple mercs owned at once) +}; + +// Should be named OP_MercenaryDataResponse, but the current opcode using that name should be renamed first +// Size varies if mercenary is hired or if browsing Mercenary Merchant +// This may also be the response for Client->Server 0x0327 (size 0) packet On Live as of April 2 2012 +struct MercenaryDataUpdate_Struct { +/*0000*/ int32 MercStatus; // Seen 0 with merc and -1 with no merc hired +/*0004*/ uint32 MercCount; // Seen 1 with 1 merc hired and 0 with no merc hired +/*0008*/ MercenaryData_Struct MercData[0]; // Data for individual mercenaries in the Merchant List +}; + +// Size 12 and sent on Zone-In if no mercenary is currently hired and when merc is dismissed +// (Same packet as MercAssign_Struct?) +struct NoMercenaryHired_Struct { +/*0000*/ int32 MercStatus; // Seen -1 with no merc hired +/*0004*/ uint32 MercCount; // Seen 0 with no merc hired +/*0008*/ uint32 MercID; // Seen 1 when no merc is hired - ID unique to each type of mercenary +/*0012*/ +}; + +// OP_MercenaryAssign (Same packet as NoMercenaryHired_Struct?) +// Not actually Merc related - This is actually a weapon equp packet +struct MercenaryAssign_Struct { +/*0000*/ uint32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137 +/*0004*/ uint32 MercUnk01; // +/*0008*/ uint32 MercUnk02; // +/*0012*/ +}; + +// OP_MercenaryTimer +// Sent on Zone-In, or after Dismissing, Suspending, or Unsuspending Mercs +struct MercenaryStatus_Struct { +/*0000*/ uint32 MercEntityID; // Seen 0 (no merc spawned) or 615843841 and 22779137 +/*0004*/ uint32 UpdateInterval; // Seen 900000 - Matches from 0x6537 packet (15 minutes in ms?) +/*0008*/ uint32 MercUnk01; // Seen 180000 - 3 minutes in milleseconds? Maybe next update interval? +/*0012*/ uint32 MercState; // Seen 5 (normal) or 1 (suspended) +/*0016*/ uint32 SuspendedTime; // Seen 0 (not suspended) or c9 c2 64 4f (suspended on Sat Mar 17 11:58:49 2012) - Unix Timestamp +/*0020*/ +}; + +// Sent from the client when using the Mercenary Window +struct MercenaryCommand_Struct { +/*0000*/ uint32 MercCommand; // Seen 0 (zone in with no merc or suspended), 1 (dismiss merc), 5 (normal state), 36 (zone in with merc) +/*0004*/ int32 Option; // Seen -1 (zone in with no merc), 0 (setting to passive stance), 1 (normal or setting to balanced stance) +/*0008*/ +}; + +// Requesting to suspend or unsuspend merc +struct SuspendMercenary_Struct { +/*0000*/ uint8 SuspendMerc; // Seen 30 (48) for suspending or unsuspending +/*0001*/ +}; + +// Response to suspend merc with timestamp +struct SuspendMercenaryResponse_Struct { +/*0000*/ uint32 SuspendTime; // Unix Timestamp - Seen a9 11 78 4f +/*0004*/ +}; + +// Sent by client when requesting to view Mercenary info or Hire a Mercenary +struct MercenaryMerchantRequest_Struct { +/*0000*/ uint32 MercID; // Seen 399 and 400 for merc ID +/*0004*/ uint32 MercUnk01; // Seen 1 +/*0008*/ uint32 MercMerchantID; // Entity ID for Mercenary Merchant +/*0012*/ uint32 MercUnk02; // Seen 65302016 (00 6e e4 03) - (probably actually individual uint8 fields), but seen as DWORD in Seeds client. +/*0016*/ +}; + +// Sent by Server in response to requesting to view Mercenary info or Hire a Mercenary +struct MercenaryMerchantResponse_Struct { +/*0000*/ uint32 ResponseType; +/*0004*/ +}; + + }; //end namespace structs +}; //end namespace RoF2 + +#endif /*RoF2_STRUCTS_H_*/ diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf new file mode 100644 index 000000000..589c47468 --- /dev/null +++ b/utils/patches/patch_RoF2.conf @@ -0,0 +1,660 @@ +# ShowEQ Import Notes: +# ZERO THE FILE first +# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf +# Unknown Mapping: +# OP_Action2 -> OP_Damage +# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake +# Name Differences: +# OP_CancelInvite -> OP_GroupCancelInvite +# OP_GMFind -> OP_FindPersonRequest +# OP_CommonMessage -> OP_ChannelMessage + +OP_Unknown=0x0000 +OP_ExploreUnknown=0x0000 # used for unknown explorer + +# world packets +# Required to reach Char Select: +OP_SendLoginInfo=0x7a09 +OP_ApproveWorld=0x7499 +OP_LogServer=0x7ceb +OP_SendCharInfo=0x00d2 +OP_ExpansionInfo=0x590d +OP_GuildsList=0x0000 +OP_EnterWorld=0x578f +OP_PostEnterWorld=0x6259 +OP_World_Client_CRC1=0x12cc +OP_World_Client_CRC2=0x0f13 +OP_SendSpellChecksum=0x0000 +OP_SendSkillCapsChecksum=0x0000 + +# Character Select Related: +OP_SendMaxCharacters=0x5475 +OP_SendMembership=0x7acc +OP_SendMembershipDetails=0x057b +OP_CharacterCreateRequest=0x6773 +OP_CharacterCreate=0x6bbf +OP_DeleteCharacter=0x1808 +OP_RandomNameGenerator=0x5954 +OP_ApproveName=0x56a2 +OP_MOTD=0x0c22 +OP_SetChatServer=0x1bc5 +OP_SetChatServer2=0x7eec +OP_ZoneServerInfo=0x4c44 +OP_WorldComplete=0x4493 +OP_WorldUnknown001=0x2301 +OP_FloatListThing=0x46c6 + +# Reasons for Disconnect: +OP_ZoneUnavail=0x4cb4 +OP_WorldClientReady=0x23c1 +OP_CharacterStillInZone=0x0000 +OP_WorldChecksumFailure=0x0000 +OP_WorldLoginFailed=0x0000 +OP_WorldLogout=0x0000 +OP_WorldLevelTooHigh=0x0000 +OP_CharInacessable=0x0000 +OP_UserCompInfo=0x0000 +OP_SendExeChecksum=0x0000 +OP_SendBaseDataChecksum=0x0000 + +# Zone in opcodes +OP_AckPacket=0x471d +OP_ZoneEntry=0x5089 +OP_ReqNewZone=0x7887 +OP_NewZone=0x1795 +OP_ZoneSpawns=0x5237 +OP_PlayerProfile=0x6506 +OP_TimeOfDay=0x5070 +OP_LevelUpdate=0x1eec +OP_Stamina=0x2a79 +OP_RequestClientZoneChange=0x3fcf +OP_ZoneChange=0x2d18 +OP_LockoutTimerInfo=0x0000 +OP_ZoneServerReady=0x0000 +OP_ZoneInUnknown=0x0000 +OP_LogoutReply=0x0000 +OP_PreLogoutReply=0x0000 + +# Required to fully log in +OP_SpawnAppearance=0x0971 +OP_ChangeSize=0x4707 +OP_TributeUpdate=0x5961 +OP_TributeTimer=0x073d +OP_SendTributes=0x729b +OP_SendGuildTributes=0x1877 +OP_TributeInfo=0x4254 +OP_Weather=0x661e +OP_ReqClientSpawn=0x35fa +OP_SpawnDoor=0x7291 +OP_GroundSpawn=0x6fca +OP_SendZonepoints=0x69a4 +OP_BlockedBuffs=0x3033 +OP_RemoveBlockedBuffs=0x0de7 +OP_ClearBlockedBuffs=0x34cb +OP_WorldObjectsSent=0x5ae2 +OP_SendExpZonein=0x5f8e +OP_SendAATable=0x66b5 +OP_RespondAA=0x7a27 +OP_UpdateAA=0x66f0 +OP_SendAAStats=0x43c8 +OP_AAExpUpdate=0x7d14 +OP_ExpUpdate=0x20ed +OP_HPUpdate=0x2828 +OP_ManaChange=0x43af +OP_TGB=0x0876 +OP_SpecialMesg=0x0083 +OP_GuildMemberList=0x12a6 +OP_GuildMOTD=0x3e13 +OP_CharInventory=0x5ca6 +OP_WearChange=0x7994 +OP_ClientUpdate=0x7dfc +OP_ClientReady=0x345d +OP_SetServerFilter=0x444d + +# Guild Opcodes - Disabled until crashes are resolved in RoF +OP_GetGuildMOTD=0x36e0 +OP_GetGuildMOTDReply=0x4f1f +OP_GuildMemberUpdate=0x69b9 +OP_GuildInvite=0x7099 +OP_GuildRemove=0x1444 +OP_GuildPeace=0x67e3 +OP_SetGuildMOTD=0x0b0b +OP_GuildList=0x507a +OP_GuildWar=0x1ffb +OP_GuildLeader=0x7e09 +OP_GuildDelete=0x3708 +OP_GuildInviteAccept=0x7053 +OP_GuildDemote=0x2d4e +OP_GuildPromote=0x0000 +OP_GuildPublicNote=0x5053 +OP_GuildManageBanker=0x748f +OP_GuildBank=0x5134 +OP_SetGuildRank=0x0b9c +OP_GuildUpdateURLAndChannel=0x2958 +OP_GuildStatus=0x7326 +OP_GuildCreate=0x1dc8 +OP_GuildMemberLevelUpdate=0x0000 # Unused? +OP_ZoneGuildList=0x0000 # Unused? +OP_GetGuildsList=0x0000 # Unused? +OP_LFGuild=0x0000 +OP_GuildManageRemove=0x0000 +OP_GuildManageAdd=0x0000 +OP_GuildManageStatus=0x0000 + +# GM/Guide Opcodes +OP_GMServers=0x08c1 +OP_GMBecomeNPC=0x3ae1 +OP_GMZoneRequest=0x62ac +OP_GMZoneRequest2=0x7e1a +OP_GMGoto=0x7d8e +OP_GMSearchCorpse=0x357c +OP_GMHideMe=0x79c5 +OP_GMDelCorpse=0x607e +OP_GMApproval=0x6db5 +OP_GMToggle=0x2097 +OP_GMSummon=0x486f +OP_GMEmoteZone=0x1cfd +OP_GMEmoteWorld=0x458e +OP_GMFind=0x4a8f +OP_GMKick=0x26a7 +OP_GMKill=0x51d3 +OP_GMNameChange=0x035f +OP_GMLastName=0x46ce + +# Misc Opcodes +OP_InspectRequest=0x57bc +OP_InspectAnswer=0x71ac +OP_InspectMessageUpdate=0x4d25 +OP_BeginCast=0x318f +OP_ColoredText=0x0000 +OP_ConsentResponse=0x384a +OP_MemorizeSpell=0x217c +OP_SwapSpell=0x0efa +OP_CastSpell=0x1287 +OP_Consider=0x742b +OP_FormattedMessage=0x1024 +OP_SimpleMessage=0x213f +OP_Buff=0x659c +OP_Illusion=0x312a +OP_MoneyOnCorpse=0x5f44 +OP_RandomReply=0x106b +OP_DenyResponse=0x2382 +OP_SkillUpdate=0x004c +OP_GMTrainSkillConfirm=0x66dd +OP_RandomReq=0x7b10 +OP_Death=0x6517 +OP_GMTraining=0x1966 +OP_GMEndTraining=0x4d6b +OP_GMTrainSkill=0x2a85 +OP_Animation=0x7177 +OP_Begging=0x6703 +OP_Consent=0x1fd1 +OP_ConsentDeny=0x7a45 +OP_AutoFire=0x241e +OP_PetCommands=0x0159 +OP_DeleteSpell=0x52e5 +OP_Surname=0x0423 +OP_ClearSurname=0x7d23 +OP_FaceChange=0x5578 +OP_SenseHeading=0x260a +OP_Action=0x744c +OP_ConsiderCorpse=0x5204 +OP_HideCorpse=0x49e1 +OP_CorpseDrag=0x0904 +OP_CorpseDrop=0x7037 +OP_Bug=0x73f4 +OP_Feedback=0x5602 +OP_Report=0x1414 +OP_Damage=0x6f15 +OP_ChannelMessage=0x2b2d +OP_Assist=0x4478 +OP_AssistGroup=0x27f8 +OP_MoveCoin=0x0bcf +OP_ZonePlayerToBind=0x0ecb +OP_KeyRing=0x6857 +OP_WhoAllRequest=0x65ab +OP_WhoAllResponse=0x7c88 +OP_FriendsWho=0x3956 +OP_ConfirmDelete=0x43a3 +OP_Logout=0x4ac6 +OP_Rewind=0x1745 +OP_TargetCommand=0x58e2 +OP_Hide=0x67fe +OP_Jump=0x2060 +OP_Camp=0x28ec +OP_Emote=0x373b +OP_SetRunMode=0x009f +OP_BankerChange=0x383c +OP_TargetMouse=0x075d +OP_MobHealth=0x37b1 +OP_InitialMobHealth=0x0000 # Unused? +OP_TargetHoTT=0x0272 +OP_XTargetResponse=0x672f +OP_XTargetRequest=0x45be +OP_XTargetAutoAddHaters=0x792c +OP_TargetBuffs=0x4f4b +OP_BuffCreate=0x3377 +OP_BuffRemoveRequest=0x64f2 +OP_DeleteSpawn=0x7280 +OP_AutoAttack=0x109d +OP_AutoAttack2=0x3526 +OP_Consume=0x4b70 +OP_MoveItem=0x32ee +OP_DeleteItem=0x18ad +OP_DeleteCharge=0x01b8 +OP_ItemPacket=0x368e +OP_ItemLinkResponse=0x633c +OP_ItemLinkClick=0x4cef +OP_ItemPreview=0x6b5c +OP_NewSpawn=0x6097 +OP_Track=0x17e5 +OP_TrackTarget=0x0029 +OP_TrackUnknown=0x4577 +OP_ClickDoor=0x3a8f +OP_MoveDoor=0x08e8 +OP_RemoveAllDoors=0x700c +OP_EnvDamage=0x51fd +OP_BoardBoat=0x4211 +OP_Forage=0x5306 +OP_LeaveBoat=0x7617 +OP_ControlBoat=0x0ae7 +OP_SafeFallSuccess=0x2219 +OP_RezzComplete=0x760d +OP_RezzRequest=0x3c21 +OP_RezzAnswer=0x701c +OP_Shielding=0x48c1 +OP_RequestDuel=0x3af1 +OP_MobRename=0x2c57 +OP_AugmentItem=0x661b +OP_WeaponEquip1=0x34a7 +OP_WeaponEquip2=0x559a +OP_WeaponUnequip2=0x2d25 +OP_ApplyPoison=0x31e6 +OP_Save=0x4a39 +OP_TestBuff=0x7cb8 +OP_CustomTitles=0x100e +OP_Split=0x3a54 +OP_YellForHelp=0x4e56 +OP_LoadSpellSet=0x261d +OP_Bandolier=0x7677 +OP_PotionBelt=0x1a3e +OP_DuelResponse=0x6a46 +OP_DuelResponse2=0x68d3 +OP_SaveOnZoneReq=0x600d +OP_ReadBook=0x72df +OP_Dye=0x23b9 +OP_InterruptCast=0x048c +OP_AAAction=0x424e +OP_LeadershipExpToggle=0x6c55 +OP_LeadershipExpUpdate=0x2797 +OP_PurchaseLeadershipAA=0x0026 +OP_UpdateLeadershipAA=0x026 +OP_MarkNPC=0x5a58 +OP_MarkRaidNPC=0x74bd #unimplemented +OP_ClearNPCMarks=0x2003 +OP_ClearRaidNPCMarks=0x20d3 #unimplemented +OP_DelegateAbility=0x76b8 +OP_SetGroupTarget=0x2814 +OP_Charm=0x5d92 +OP_Stun=0x36a4 +OP_SendFindableNPCs=0x3897 +OP_FindPersonRequest=0x5cea +OP_FindPersonReply=0x7e58 +OP_Sound=0x1a30 +OP_PetBuffWindow=0x5882 +OP_LevelAppearance=0x3bc9 +OP_Translocate=0x6580 +OP_Sacrifice=0x1821 +OP_PopupResponse=0x214a +OP_OnLevelMessage=0x4fd0 +OP_AugmentInfo=0x0afb +OP_Petition=0x5f03 +OP_SomeItemPacketMaybe=0x747c +OP_PVPStats=0x6f4b +OP_PVPLeaderBoardRequest=0x3707 +OP_PVPLeaderBoardReply=0x25b7 +OP_PVPLeaderBoardDetailsRequest=0x15a9 +OP_PVPLeaderBoardDetailsReply=0x04aa +OP_RestState=0x00f +OP_RespawnWindow=0x28bc +OP_LDoNButton=0x5327 +OP_SetStartCity=0x6326 +OP_VoiceMacroIn=0x17fd +OP_VoiceMacroOut=0x409a +OP_ItemViewUnknown=0x2289 +OP_VetRewardsAvaliable=0x590e +OP_VetClaimRequest=0x1126 +OP_VetClaimReply=0x16d4 +OP_DisciplineUpdate=0x759e +OP_DisciplineTimer=0x6989 +OP_BecomeCorpse=0x0000 # Unused? +OP_Action2=0x0000 # Unused? +OP_MobUpdate=0x2c84 +OP_NPCMoveUpdate=0x189c +OP_CameraEffect=0x127f +OP_SpellEffect=0x5936 +OP_RemoveNimbusEffect=0xc693 +OP_AltCurrency=0x7121 +OP_AltCurrencyMerchantRequest=0x6b6d +OP_AltCurrencyMerchantReply=0x74ec +OP_AltCurrencyPurchase=0x61cb +OP_AltCurrencySell=0x0165 +OP_AltCurrencySellSelection=0x5409 +OP_AltCurrencyReclaim=0x532a +OP_CrystalCountUpdate=0x467f +OP_CrystalCreate=0x7aee +OP_CrystalReclaim=0x2439 +OP_Untargetable=0x053c +OP_IncreaseStats=0x70a3 +OP_Weblink=0x18d3 +OP_OpenContainer=0x0000 +OP_Marquee=0x0000 +OP_ItemRecastDelay=0x08a6 +#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U + +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 +OP_DzAddPlayer=0x4701 +OP_DzRemovePlayer=0x1abc +OP_DzSwapPlayer=0x405b +OP_DzMakeLeader=0x543d +OP_DzPlayerList=0x14c6 +OP_DzJoinExpeditionConfirm=0x7f4b +OP_DzJoinExpeditionReply=0x1950 +OP_DzExpeditionInfo=0x9119 +OP_DzExpeditionList=0x205f +OP_DzMemberStatus=0x32f0 +OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 +OP_DzMemberList=0x5ae4 +OP_DzCompass=0x3e0e +OP_DzChooseZone=0x0000 + +# New Opcodes +OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? +OP_ManaUpdate=0x3791 +OP_EnduranceUpdate=0x5f42 +OP_MobManaUpdate=0x2404 +OP_MobEnduranceUpdate=0x1c81 + +# Mercenary Opcodes +OP_MercenaryDataUpdateRequest=0x7b89 +OP_MercenaryDataUpdate=0x61a4 +OP_MercenaryDataRequest=0x11c1 +OP_MercenaryDataResponse=0x72ce +OP_MercenaryHire=0x7169 +OP_MercenaryDismiss=0x6e83 +OP_MercenaryTimerRequest=0x31e4 +OP_MercenaryTimer=0x0763 +OP_MercenaryUnknown1=0x5d26 +OP_MercenaryCommand=0x27f2 +OP_MercenarySuspendRequest=0x4407 +OP_MercenarySuspendResponse=0x6f03 +OP_MercenaryUnsuspendResponse=0x27a0 + +# Looting +OP_LootRequest=0x0adf +OP_EndLootRequest=0x30f7 +OP_LootItem=0x4dc9 +OP_LootComplete=0x55c4 + +# bazaar trader stuff: +OP_BazaarSearch=0x39d6 +OP_TraderDelItem=0x0000 +OP_BecomeTrader=0x61b3 +OP_TraderShop=0x31df +OP_Trader=0x4ef5 +OP_TraderBuy=0x0000 +OP_Barter=0x243a +OP_ShopItem=0x0000 +OP_BazaarInspect=0x0000 +OP_Bazaar=0x0000 +OP_TraderItemUpdate=0x0000 + +# pc/npc trading +OP_TradeRequest=0x77b5 +OP_TradeAcceptClick=0x69e2 +OP_TradeRequestAck=0x14bf +OP_TradeCoins=0x4206 +OP_FinishTrade=0x3993 +OP_CancelTrade=0x354c +OP_TradeMoneyUpdate=0x68c2 +OP_MoneyUpdate=0x640c +OP_TradeBusy=0x5505 + +# Sent after canceling trade or after closing tradeskill object +OP_FinishWindow=0x7349 +OP_FinishWindow2=0x40ef + +# Sent on Live for what seems to be item existance verification +# Ex. Before Right Click Effect happens from items +OP_ItemVerifyRequest=0x097b +OP_ItemVerifyReply=0x2115 + +# merchant stuff +OP_ShopPlayerSell=0x1901 +OP_ShopRequest=0x4fed +OP_ShopEnd=0x30a8 +OP_ShopEndConfirm=0x3196 +OP_ShopPlayerBuy=0x04c +OP_ShopDelItem=0x724f + +# tradeskill stuff: +OP_ClickObject=0x4aa1 +OP_ClickObjectAction=0x0c1e +OP_ClearObject=0x7a11 +OP_RecipeDetails=0x40d7 +OP_RecipesFavorite=0x5c74 +OP_RecipesSearch=0x1db6 +OP_RecipeReply=0x6e02 +OP_RecipeAutoCombine=0x6261 +OP_TradeSkillCombine=0x579a + +# Tribute Packets: +OP_OpenGuildTributeMaster=0x378d +OP_OpenTributeMaster=0x7666 +OP_SelectTribute=0x79fc +OP_TributeItem=0x4f3e +OP_TributeMoney=0x58fb +OP_TributeToggle=0x241d +OP_TributePointUpdate=0x5300 +OP_TributeNPC=0x0000 +OP_GuildTributeInfo=0x0000 +OP_OpenTributeReply=0x0000 +OP_GuildTributeStatus=0x0000 + +# Adventure packets: +OP_LeaveAdventure=0x5d18 +OP_AdventureFinish=0x400f +OP_AdventureInfoRequest=0x3cb0 +OP_AdventureInfo=0x4c54 +OP_AdventureRequest=0x2c6c +OP_AdventureDetails=0x5648 +OP_AdventureData=0x7171 +OP_AdventureUpdate=0x1b01 +OP_AdventureMerchantRequest=0x6922 +OP_AdventureMerchantResponse=0x3e47 +OP_AdventureMerchantPurchase=0x5b72 +OP_AdventureMerchantSell=0x2f9b +OP_AdventurePointsUpdate=0x65c3 +OP_AdventureStatsRequest=0x5a62 +OP_AdventureStatsReply=0x2370 +OP_AdventureLeaderboardRequest=0x7093 +OP_AdventureLeaderboardReply=0x7f79 + +# Group Opcodes +OP_GroupDisband=0x4c10 +OP_GroupInvite=0x1649 +OP_GroupFollow=0x05ce +OP_GroupUpdate=0x3abb +OP_GroupUpdateB=0x6194 +OP_GroupCancelInvite=0x0000 +OP_GroupAcknowledge=0x7323 +OP_GroupDelete=0x0f6c +OP_CancelInvite=0x32c2 +OP_GroupFollow2=0x2a50 +OP_GroupInvite2=0x6c65 +OP_GroupDisbandYou=0x1ae5 +OP_GroupDisbandOther=0x74da +OP_GroupLeaderChange=0x21b4 +OP_GroupRoles=0x70e2 +OP_GroupMakeLeader=0x4229 +OP_DoGroupLeadershipAbility=0x1fb5 +OP_GroupLeadershipAAUpdate=0x02cf +OP_GroupMentor=0x5892 +OP_InspectBuffs=0x486c + +# LFG/LFP Opcodes +OP_LFGCommand=0x6060 +OP_LFGGetMatchesRequest=0x0340 +OP_LFGGetMatchesResponse=0x5048 +OP_LFPGetMatchesRequest=0x4d7d +OP_LFPGetMatchesResponse=0x22c6 +OP_LFPCommand=0x49a9 +OP_LFGAppearance=0x0000 +OP_LFGResponse=0x0000 + +# Raid Opcodes +OP_RaidInvite=0x55ac +OP_RaidUpdate=0x3973 +OP_RaidJoin=0x0000 + +# Button-push commands +OP_Taunt=0x2703 +OP_CombatAbility=0x3eba +OP_SenseTraps=0x02af +OP_PickPocket=0x39e8 +OP_DisarmTraps=0x78bf +OP_Disarm=0x5ec8 +OP_Sneak=0x5d55 +OP_Fishing=0x1e2a +OP_InstillDoubt=0x640e +OP_FeignDeath=0x52fa +OP_Mend=0x0ecf +OP_Bind_Wound=0x0386 +OP_LDoNOpen=0x3d5c + +# Task packets +OP_TaskDescription=0x083 +OP_TaskActivity=0x3714 +OP_CompletedTasks=0x4eba +OP_TaskActivityComplete=0x5e19 +OP_AcceptNewTask=0x0a23 +OP_CancelTask=0x08d3 +OP_TaskMemberList=0x5727 +OP_OpenNewTasksWindow=0x48a2 +OP_AvaliableTask=0x36e8 +OP_TaskHistoryRequest=0x5f1c +OP_TaskHistoryReply=0x3d05 +OP_DeclineAllTasks=0x0000 + +# Title opcodes +OP_NewTitlesAvailable=0x0d32 +OP_RequestTitles=0x6344 +OP_SendTitleList=0x2d08 +OP_SetTitle=0x6527 +OP_SetTitleReply=0x4c21 + +# mail opcodes +OP_Command=0x0000 +OP_MailboxHeader=0x0000 +OP_MailHeader=0x0000 +OP_MailBody=0x0000 +OP_NewMail=0x0000 +OP_SentConfirm=0x0000 + +########### Below this point should not be needed ########### + +# This section are all unknown in Titanium +OP_ForceFindPerson=0x0000 +OP_LocInfo=0x0000 +OP_ReloadUI=0x0000 +OP_ItemName=0x0000 +OP_ItemLinkText=0x0000 +OP_MultiLineMsg=0x0000 +OP_MendHPUpdate=0x0000 +OP_TargetReject=0x0000 +OP_SafePoint=0x0000 +OP_ApproveZone=0x0000 +OP_ZoneComplete=0x0000 +OP_ClientError=0x0000 +OP_DumpName=0x0000 +OP_Heartbeat=0x0000 +OP_CrashDump=0x0000 +OP_LoginComplete=0x0000 + +# discovered opcodes not yet used: +OP_PickLockSuccess=0x0000 +OP_PlayMP3=0x0000 +OP_ReclaimCrystals=0x0000 +OP_DynamicWall=0x0000 +OP_OpenDiscordMerchant=0x0000 +OP_DiscordMerchantInventory=0x0000 +OP_GiveMoney=0x0000 +OP_RequestKnowledgeBase=0x0000 +OP_KnowledgeBase=0x0000 +OP_SlashAdventure=0x0000 # /adventure +OP_BecomePVPPrompt=0x0000 +OP_MoveLogRequest=0x0000 # gone I think +OP_MoveLogDisregard=0x0000 # gone I think + +# named unknowns, to make looking for real unknown easier +OP_AnnoyingZoneUnknown=0x0000 +OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_QueryResponseThing=0x0000 + + +# realityincarnate: these are just here to stop annoying several thousand byte packet dumps +#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum +#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum + +# Petition Opcodes +OP_PetitionSearch=0x0000 search term for petition +OP_PetitionSearchResults=0x0000 (list of?) matches from search +OP_PetitionSearchText=0x0000 text results of search + +OP_PetitionUpdate=0x0000 +OP_PetitionCheckout=0x0000 +OP_PetitionCheckIn=0x0000 +OP_PetitionQue=0x0000 +OP_PetitionUnCheckout=0x0000 +OP_PetitionDelete=0x0000 +OP_DeletePetition=0x0000 +OP_PetitionResolve=0x0000 +OP_PDeletePetition=0x0000 +OP_PetitionBug=0x0000 +OP_PetitionRefresh=0x0000 +OP_PetitionCheckout2=0x0000 +OP_PetitionViewPetition=0x0000 + +# Login opcodes +OP_SessionReady=0x0000 +OP_Login=0x0000 +OP_ServerListRequest=0x0000 +OP_PlayEverquestRequest=0x0000 +OP_PlayEverquestResponse=0x0000 +OP_ChatMessage=0x0000 +OP_LoginAccepted=0x0000 +OP_ServerListResponse=0x0000 +OP_Poll=0x0000 +OP_EnterChat=0x0000 +OP_PollResponse=0x0000 + +# raw opcodes +OP_RAWSessionRequest=0x0000 +OP_RAWSessionResponse=0x0000 +OP_RAWCombined=0x0000 +OP_RAWSessionDisconnect=0x0000 +OP_RAWKeepAlive=0x0000 +OP_RAWSessionStatRequest=0x0000 +OP_RAWSessionStatResponse=0x0000 +OP_RAWPacket=0x0000 +OP_RAWFragment=0x0000 +OP_RAWOutOfOrderAck=0x0000 +OP_RAWAck=0x0000 +OP_RAWAppCombined=0x0000 +OP_RAWOutOfSession=0x0000 + +# we need to document the differences between these packets to make identifying them easier +OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs +OP_InitialHPUpdate=0x0000 \ No newline at end of file diff --git a/utils/scripts/opcode_scripts/conf_to_oplist.pl b/utils/scripts/opcode_scripts/conf_to_oplist.pl new file mode 100644 index 000000000..f79de1093 --- /dev/null +++ b/utils/scripts/opcode_scripts/conf_to_oplist.pl @@ -0,0 +1,66 @@ +#!/usr/bin/perl + +# File Name: conf_to_oplist.pl +# Converts a Patch File into the Opcode List with Opcode Names for the Spreadsheet. + +# Directions to use this script: +# 1. Paste the contents of the current patch file in the patch_OLD.conf file. +# 2. Run this script using "perl conf_to_oplist.pl" +# 3. This updates the opcodelist.txt with the values from the Patch File. + + +$stopmessage = "Failed to open file"; +open OpcodeFile, "<", "opcodelist.txt" or die $stopmessage; +open PatchFile, "<", "patch_OLD.conf" or die $stopmessage; + +my @OpcodeList = ; +my @PatchFile = ; +my %PatchHash = (); + +foreach $line (@PatchFile) +{ + @equalssplit = split(/=/, $line); + $ArraySize = @equalssplit; + if ($ArraySize > 1) + { + @OpcodeArray = split(//, $equalssplit[1]); + $CurOpcode = $OpcodeArray[0].$OpcodeArray[1].$OpcodeArray[2].$OpcodeArray[3].$OpcodeArray[4].$OpcodeArray[5]; + $CurOpcode = lc($CurOpcode); + # Opcode Name => Opcode + $PatchHash{ $CurOpcode } = $equalssplit[0]; + } +} + +close(OpcodeFile); +close(PatchFile); + +# Clear out file contents +open OpcodeResultFile, ">", "opcodelist.txt" or die $stopmessage; +print OpcodeResultFile ""; +close(OpcodeResultFile); + +open OpcodeResultFile, ">>", "opcodelist.txt" or die $stopmessage; + +while( my ($k, $v) = each %$PatchFile ) +{ + #print OpcodeResultFile "key: $k, value: $v.\n"; +} + + +$TabSpace = " "; # Tab +foreach $line (@OpcodeList) +{ + @LineSplit = split(//, $line); + $CurOpcode = $LineSplit[0].$LineSplit[1].$LineSplit[2].$LineSplit[3].$LineSplit[4].$LineSplit[5]; + $CurOpcode = lc($CurOpcode); + $OpcodeName = ""; # Tab + if ($PatchHash{$CurOpcode}) + { + $NameKey = $PatchHash{$CurOpcode}; + $OpcodeName = $NameKey; + } + $CurLine = $CurOpcode.$TabSpace.$OpcodeName."\n"; + print OpcodeResultFile $CurLine; +} + +close(OpcodeResultFile); diff --git a/utils/scripts/opcode_scripts/opcodelist.txt b/utils/scripts/opcode_scripts/opcodelist.txt new file mode 100644 index 000000000..6ef0916f9 --- /dev/null +++ b/utils/scripts/opcode_scripts/opcodelist.txt @@ -0,0 +1,1671 @@ +RoF2 Built May 10 2013 23:30:08 +0x04d6 +0x5efd +0x0cc1 +0x2c3d +0x7b25 +0x4f44 +0x7592 +0x2b1c +0x1fd1 OP_Consent +0x15a5 +0x3c7e +0x6262 +0x471d OP_AckPacket +0x64a8 +0x7c06 +0x2c5e +0x24ab +0x19b5 +0x72fa +0x0770 +0x4cef OP_ItemLinkClick +0x08c1 OP_GMServers +0x318f OP_BeginCast +0x5ec8 OP_Disarm +0x6ae3 +0x2b2d OP_ChannelMessage +0x1cb1 +0x5070 OP_TimeOfDay +0x7dfc OP_ClientUpdate +0x35ea +0x3b9a +0x148d +0x345d OP_ClientReady +0x5ae2 OP_WorldObjectsSent +0x03a4 +0x69e2 OP_TradeAcceptClick +0x354c OP_CancelTrade +0x3993 OP_FinishTrade +0x165b +0x2b95 +0x6fe2 +0x42fd +0x25d7 +0x7436 +0x4206 OP_TradeCoins +0x14bf OP_TradeRequestAck +0x7349 OP_FinishWindow +0x71fd +0x0b9c OP_SetGuildRank +0x0f7d +0x1bd3 +0x5053 OP_GuildPublicNote +0x01f9 +0x2c84 OP_MobUpdate +0x279d +0x5a94 +0x579a OP_TradeSkillCombine +0x56b1 +0x0f25 +0x3c14 +0x0c16 +0x4a8f OP_GMFind +0x2ad6 +0x0160 +0x7852 +0x41bf +0x40dd +0x3ec6 +0x6af4 +0x6d9d +0x2538 +0x0017 +0x017 +0x691a +0x0520 +0x200f +0x65ab OP_WhoAllRequest +0x674b +0x6a02 +0x0e48 +0x12a6 OP_GuildMemberList +0x0eae +0x2921 +0x7056 +0x507a OP_GuildList +0x6279 +0x5a26 +0x5b51 +0x0bad +0x59ad +0x2264 +0x004c OP_SkillUpdate +0x04c OP_ShopPlayerBuy +0x0ddd +0x4101 +0x5f03 OP_Petition +0x3de3 +0x1901 OP_ShopPlayerSell +0x791b +0x3a5d +0x7013 +0x47f1 +0x6506 OP_PlayerProfile +0x30a8 OP_ShopEnd +0x724f OP_ShopDelItem +0x5829 +0x1ce1 +0x47d6 +0x07cf +0x40c9 +0x38d4 +0x7eb9 +0x1e2c +0x3ae1 OP_GMBecomeNPC +0x4849 +0x376b +0x1e2a OP_Fishing +0x1eec OP_LevelUpdate +0x4958 +0x20ed OP_ExpUpdate +0x3ed4 +0x701c OP_RezzAnswer +0x640e OP_InstillDoubt +0x0ecf OP_Mend +0x09d3 +0x70a3 OP_IncreaseStats +0x178e +0x27e8 +0x61f8 +0x4322 +0x3f84 +0x40ef OP_FinishWindow2 +0x166c +0x106b OP_RandomReply +0x5bfd +0x11c8 +0x1753 +0x009f OP_SetRunMode +0x09f +0x4ae6 +0x3dbf +0x0399 +0x5c89 +0x012c +0x381c +0x4b36 +0x36d5 +0x5f21 +0x56f7 +0x46b1 +0x357c OP_GMSearchCorpse +0x2422 +0x084e +0x67e3 OP_GuildPeace +0x0f83 +0x4577 OP_TrackUnknown +0x5d55 OP_Sneak +0x67fe OP_Hide +0x12e5 +0x2c7a +0x600d OP_SaveOnZoneReq +0x16ce +0x46ce OP_GMLastName +0x1ffb OP_GuildWar +0x6718 +0x2f3e +0x7e09 OP_GuildLeader +0x5ce4 +0x5bcc +0x551d +0x6dbc +0x2219 OP_SafeFallSuccess +0x2686 +0x2022 +0x1c53 +0x33a2 +0x3541 +0x582e +0x3cba +0x190c +0x5067 +0x46d2 +0x49cf +0x1b0c + +0x31e6 OP_ApplyPoison +0x4211 OP_BoardBoat +0x7617 OP_LeaveBoat +0x4466 +0x1287 OP_CastSpell +0x5467 OP_ManaChange +0x43af OP_ManaChange +0x6a0d +0x217c OP_MemorizeSpell +0x260a OP_SenseHeading +0x5886 +0x7e8c +0x1a37 +0x0b6f +0x62ca +0x34a4 +0x6c83 +0x5d10 +0x21a0 +0x3537 +0x2acd +0x7c6d +0x6618 + + + +0x6c65 OP_GroupInvite2 +0x32c2 OP_CancelInvite +0x2a50 OP_GroupFollow2 +0x2060 OP_Jump +0x31f4 +0x4420 +0x1256 +0x4d38 +0x50f5 +0x79c5 OP_GMHideMe +0x2fab +0x57a5 +0x32a4 +0x590d OP_ExpansionInfo +0x6f15 OP_Damage +0x42ea +0x3091 +0x6b5a +0x3234 +0x30b4 +0x51fd OP_EnvDamage +0x15f4 +0x1808 OP_DeleteCharacter +0x1795 OP_NewZone +0x7887 OP_ReqNewZone +0x2414 +0x2eb3 +0x3db3 +0x4008 + +0x373b OP_Emote +0x7280 OP_DeleteSpawn +0x4bc2 +0x15bb +0x4fed OP_ShopRequest +0x0c2f +0x4aa1 OP_ClickObject +0x6fca OP_GroundSpawn +0x1045 +0x2a9e +0x2523 +0x6213 +0x4a39 OP_Save +0x0797 +0x35fa OP_ReqClientSpawn +0x5f8e OP_SendExpZonein +0x4c10 OP_GroupDisband +0x747c OP_SomeItemPacketMaybe +0x744c OP_Action +0x00d2 OP_SendCharInfo +0x0d2 +0x11d4 +0x6bbf OP_CharacterCreate +0x6517 OP_Death +0x19f6 +0x360f +0x1951 +0x51d3 OP_GMKill +0x26a7 OP_GMKick +0x7d8e OP_GMGoto +0x475e +0x5253 +0x3c79 +0x5065 +0x0337 +0x2ded +0x777b +0x4434 +0x0e90 +0x57da +0x150e +0x1ba8 +0x70eb +0x0adf OP_LootRequest +0x30f7 OP_EndLootRequest +0x5f44 OP_MoneyOnCorpse +0x3d54 +0x482d +0x58b2 +0x7361 +0x604f +0x3d87 +0x6909 +0x4f73 +0x0a0f +0x56a2 OP_ApproveName +0x69e6 +0x3a8f OP_ClickDoor +0x08e8 OP_MoveDoor +0x7dd1 +0x5c66 +0x312a OP_Illusion +0x2807 +0x4fe2 +0x2f2e +0x5824 +0x6661 +0x4742 +0x4d02 +0x2105 +0x19e9 +0x2268 +0x7994 OP_WearChange +0x0386 OP_Bind_Wound +0x5306 OP_Forage +0x0971 OP_SpawnAppearance +0x7099 OP_GuildInvite +0x7053 OP_GuildInviteAccept +0x1444 OP_GuildRemove +0x3708 OP_GuildDelete +0x7b22 +0x610f +0x324a +0x2889 +0x6f2a +0x2998 +0x700c OP_RemoveAllDoors +0x1966 OP_GMTraining +0x4d6b OP_GMEndTraining +0x6e8d +0x2b41 +0x4dc9 OP_LootItem +0x7177 OP_Animation +0x650e +0x2d18 OP_ZoneChange +0x707b +0x0803 +0x3fc3 +0x7326 OP_GuildStatus +0x0804 +0x3f86 +0x6d20 +0x04a3 +0x4714 +0x6703 OP_Begging +0x0ae7 OP_ControlBoat +0x27d7 +0x3c21 OP_RezzRequest +0x6f22 +0x32ee OP_MoveItem +0x0bcf OP_MoveCoin +0x2452 +0x0186 +0x0522 +0x3a54 OP_Split +0x659c OP_Buff +0x225b + +0x12cc OP_World_Client_CRC1 +0x661e OP_Weather +0x742b OP_Consider +0x102e +0x0f13 OP_World_Client_CRC2 +0x6944 +0x2703 OP_Taunt +0x5602 OP_Feedback +0x68c2 OP_TradeMoneyUpdate +0x07f7 +0x3fe7 +0x43a0 +0x314c +0x4b70 OP_Consume +0x2a79 OP_Stamina +0x402e +0x750e +0x0927 +0x36a4 OP_Stun +0x2b03 +0x68d3 OP_DuelResponse2 +0x6a46 OP_DuelResponse +0x5237 OP_ZoneSpawns +0x3eba OP_CombatAbility +0x109d OP_AutoAttack +0x075d OP_TargetMouse +0x05d2 +0x2a85 OP_GMTrainSkill +0x43a3 OP_ConfirmDelete +0x6c57 +0x3906 +0x55c4 OP_LootComplete +0x3196 OP_ShopEndConfirm +0x18ad OP_DeleteItem +0x01b8 OP_DeleteCharge +0x01d7 +0x4d28 +0x4fd9 +0x02c6 +0x3e30 +0x3fcf OP_RequestClientZoneChange +0x4e0e +0x1dee +0x62ac OP_GMZoneRequest +0x4ac6 OP_Logout +0x3526 OP_AutoAttack2 +0x7ceb OP_LogServer +0x0423 OP_Surname +0x3956 OP_FriendsWho +0x45dc +0x35e0 +0x173e +0x4853 +0x393b +0x0efa OP_SwapSpell +0x3588 +0x26e9 +0x4e56 OP_YellForHelp +0x2551 +0x38c8 +0x7499 OP_ApproveWorld +0x603a +0x7b10 OP_RandomReq +0x208f +0x607e OP_GMDelCorpse +0x1821 OP_Sacrifice +0x30d6 +0x760d OP_RezzComplete +0x4dd5 +0x0fe8 +0x6e5c +0x2228 +0x21bc +0x78c3 +0x3e57 +0x69d0 +0x1e3a +0x1a30 OP_Sound +0x61a0 +0x048c OP_InterruptCast +0x6e80 +0x3d29 +0x5d92 OP_Charm +0x0159 OP_PetCommands +0x486e +0x579e +0x49b3 +0x6db5 OP_GMApproval +0x4759 +0x0c22 OP_MOTD +0x2097 OP_GMToggle +0x72f7 +0x640c OP_MoneyUpdate +0x51e5 +0x1802 +0x5de1 +0x2e0c +0x58e2 OP_TargetCommand +0x444d OP_SetServerFilter +0x4478 OP_Assist +0x2a21 +0x7e59 +0x0b0b OP_SetGuildMOTD +0x3e13 OP_GuildMOTD +0x7a11 OP_ClearObject +0x6580 OP_Translocate +0x28ec OP_Camp +0x61b3 OP_BecomeTrader +0x31af +0x0876 OP_TGB +0x4ee1 +0x7e92 +0x7d14 OP_AAExpUpdate + +0x5578 OP_FaceChange +0x1a80 +0x42ff +0x7c2d +0x2c57 OP_MobRename +0x6dab +0x4568 +0x7776 +0x5029 +0x696c +0x23b9 OP_Dye +0x5204 OP_ConsiderCorpse +0x213f OP_SimpleMessage +0x1024 OP_FormattedMessage +0x2ce5 +0x5cc9 +0x3358 +0x52e5 OP_DeleteSpell +0x48c1 OP_Shielding +0x6f14 +0x1414 OP_Report +0x0e1c +0x1219 +0x6857 OP_KeyRing +0x55ac OP_RaidInvite +0x3973 OP_RaidUpdate +0x56fe +0x7f2d +0x31df OP_TraderShop +0x4ef5 OP_Trader +0x735d +0x019b +0x5930 +0x2d73 +0x39d6 OP_BazaarSearch +0x6a96 +0x424e OP_AAAction +0x7a27 OP_RespondAA +0x5eca +0x70c6 +0x0dd4 +0x4598 +0x19b6 +0x728a +0x5232 +0x77bd +0x70c0 +0x633c OP_ItemLinkResponse +0x63eb +0x4765 +0x6290 +0x1db6 OP_RecipesSearch +0x6e02 OP_RecipeReply +0x40d7 OP_RecipeDetails +0x6261 OP_RecipeAutoCombine +0x4015 OP_SetGroupLeadershipAbilities +0x6eae OP_SetRaidLeadershipAbilities +0x1fb5 OP_DoGroupLeadershipAbility +0x5a58 OP_MarkNPC +0x74bd OP_MarkRaidNPC +0x6c55 OP_LeadershipExpToggle +0x0026 OP_PurchaseLeadershipAA +0x026 OP_UpdateLeadershipAA +0x2814 OP_SetGroupTarget +0x4c9d OP_SetRaidTarget +0x76b8 OP_DelegateAbility +0x2b33 OP_DelegateRaidAbility +0x4786 OP_SenseNPCData +0x0eb4 OP_DelegateFailed +0x486c OP_InspectBuffs +0x0272 OP_TargetHoTT +0x2003 OP_ClearNPCMarks +0x20d3 OP_ClearRaidNPCMarks +0x1c89 +0x4ee2 +0x2797 OP_LeadershipExpUpdate +0x6da5 OP_ClearLeadershipAbilities +0x0ca6 +0x7717 +0x509d +0x6bee +0x0b04 +0x6097 OP_NewSpawn +0x758c +0x2b10 +0x4d09 +0x0083 OP_SpecialMesg +0x083 OP_TaskDescription +0x3714 OP_TaskActivity +0x08d3 OP_CancelTask +0x39f0 +0x5f7a OP_ItemScriptAdjustment +0x006a +0x06a +0x7465 +0x31c0 +0x14ba +0x25e0 +0x62a0 +0x407a +0x7c88 OP_WhoAllResponse +0x51b8 +0x578c +0x1197 +0x2dd3 +0x333a +0x2925 +0x37b1 OP_MobHealth +0x7314 +0x2404 OP_MobManaUpdate +0x5f5e +0x1c81 OP_MobEnduranceUpdate +0x4a78 +0x37a2 +0x5565 +0x2d09 +0x3141 +0x695e +0x0029 OP_TrackTarget +0x029 +0x1612 +0x3e69 +0x5c59 +0x7e1a OP_GMZoneRequest2 +0x24d9 +0x5089 OP_ZoneEntry +0x61db +0x542f +0x2006 +0x52fa OP_FeignDeath +0x39e8 OP_PickPocket +0x7c2e +0x2cdd +0x5e3a +0x4214 +0x2828 OP_HPUpdate +0x14b8 +0x3791 OP_ManaUpdate +0x0698 +0x5f42 OP_EnduranceUpdate +0x7eb5 +0x73f4 OP_Bug +0x69a4 OP_SendZonepoints +0x57bc OP_InspectRequest +0x71ac OP_InspectAnswer +0x4229 OP_GroupMakeLeader +0x54f7 +0x322b +0x3264 +0x202c +0x29ae +0x7a09 OP_SendLoginInfo +0x5206 +0x7fd2 +0x6259 OP_PostEnterWorld +0x0f70 +0x00d1 +0x0d1 +0x1eac +0x1b54 +0x5e23 +0x7910 +0x152e +0x7555 +0x05ce OP_GroupFollow +0x1649 OP_GroupInvite +0x6110 +0x0641 +0x578f OP_EnterWorld +0x6cb8 +0x6ef5 +0x4c44 OP_ZoneServerInfo +0x4cb4 OP_ZoneUnavail +0x74fb +0xbe6b +0x5ac7 +0x6281 +0x1bc5 OP_SetChatServer +0x48c8 +0x677b +0x6820 +0x2623 +0x69b9 OP_GuildMemberUpdate +0x2dcb +0x5e04 +0x1d3c +0x6060 OP_LFGCommand +0x0340 OP_LFGGetMatchesRequest +0x49a9 OP_LFPCommand +0x4d7d OP_LFPGetMatchesRequest +0x5048 OP_LFGGetMatchesResponse +0x22c6 OP_LFPGetMatchesResponse +0x499e +0x2d4e OP_GuildDemote +0x2009 +0x3b26 +0x69d4 +0x40b1 +0x587d +0x3747 +0x7a66 +0x2f03 +0x01ed +0x36e0 OP_GetGuildMOTD +0x4f1f OP_GetGuildMOTDReply +0x6087 +0x5f92 +0x439a +0x4334 +0x13c2 +0x7cb8 OP_TestBuff +0x17e5 OP_Track +0x5265 +0x1440 +0x7a4b +0x0648 +0x2529 +0x486f OP_GMSummon +0x458e OP_GMEmoteWorld +0x2549 +0x1cfd OP_GMEmoteZone +0x5ca6 OP_CharInventory +0x2710 +0x7291 OP_SpawnDoor +0x7afc +0x1f65 +0x3ddd +0x85fc +0x72df OP_ReadBook +0x3af1 OP_RequestDuel +0x52f7 +0x77b5 OP_TradeRequest +0x70f2 +0x207d +0x384a OP_ConsentResponse +0x5505 OP_TradeBusy +0x0c1e OP_ClickObjectAction +0x51eb +0x466b +0x41a3 +0x0682 +0x1242 +0x261d OP_LoadSpellSet +0x32a6 +0x2c6c OP_AdventureRequest +0x39e5 +0x5648 OP_AdventureDetails +0x5327 OP_LDoNButton +0x4524 +0x5954 OP_RandomNameGenerator +0x327d +0x2945 +0x33d7 +0x2651 +0x3b86 +0x0c6c +0x24d4 +0x4441 +0x4e42 +0x50d8 +0x1afb +0x6bd4 +0x3cb0 OP_AdventureInfoRequest +0x4c54 OP_AdventureInfo +0x7171 OP_AdventureData +0x35e8 +0x7d49 +0x1848 +0x2599 +0x0dab +0x6493 +0x34f2 +0x7d40 +0x0e00 +0x1cf3 +0x71f4 +0x5d18 OP_LeaveAdventure +0x4e25 +0x50c2 +0x400f OP_AdventureFinish +0x6368 +0x6192 +0x3aa4 +0x502e +0x1b01 OP_AdventureUpdate +0x0f24 +0x1015 +0x23a6 +0x5a74 +0x037a +0x7a45 OP_ConsentDeny +0x71bc +0x2382 OP_DenyResponse +0x02a0 +0x1126 OP_VetClaimRequest +0x0668 +0x16d4 OP_VetClaimReply +0x5cea OP_FindPersonRequest +0x0cc3 +0x7e58 OP_FindPersonReply +0x9be3 OP_PickLock +0x0438 +0x3d5c OP_LDoNOpen +0x15e7 +0x368e OP_ItemPacket +0x7331 +0x4936 +0x2c4e +0x78bf OP_DisarmTraps +0x02af OP_SenseTraps +0x65c3 OP_AdventurePointsUpdate +0x0dcb +0x661b OP_AugmentItem +0x5f68 +0x5278 +0x6b53 +0x5dd1 +0x559a OP_WeaponEquip2 +0x2d25 OP_WeaponUnequip2 +0x23c1 OP_WorldClientReady +0x5a62 OP_AdventureStatsRequest +0x7093 OP_AdventureLeaderboardRequest +0x2370 OP_AdventureStatsReply +0x7f79 OP_AdventureLeaderboardReply +0x4eb3 +0x3377 OP_BuffCreate +0x5882 OP_PetBuffWindow +0x4f4b OP_TargetBuffs +0x5961 OP_TributeUpdate +0x4f3e OP_TributeItem +0x5300 OP_TributePointUpdate +0x729b OP_SendTributes +0x4254 OP_TributeInfo +0x79fc OP_SelectTribute +0x073d OP_TributeTimer +0x08bf +0x7697 +0x4b65 +0x51ae +0x51a9 +0x7666 OP_OpenTributeMaster +0x4290 +0x759e OP_DisciplineUpdate +0x01c6 +0x6989 OP_DisciplineTimer +0x58fb OP_TributeMoney +0x7422 +0x0d25 +0x4de1 +0x46d0 +0x4f50 +0x2ddc +0x7441 +0x6a12 +0x29a8 +0x3f7f +0x150b +0x11e3 +0x1ad3 +0x59ca +0x4701 OP_DzAddPlayer +0x1abc OP_DzRemovePlayer +0x405b OP_DzSwapPlayer +0x543d OP_DzMakeLeader +0x14c6 OP_DzPlayerList +0x7f4b OP_DzJoinExpeditionConfirm +0x1950 OP_DzJoinExpeditionReply +0x64b5 +0x0398 +0x7b68 OP_DzListTimers +0x4f7e +0x9119 OP_DzExpeditionInfo +0x205f OP_DzExpeditionList +0xb2e3 OP_DzQuit +0x32f0 OP_DzMemberStatus +0x3de9 OP_DzLeaderStatus +0x5ae4 OP_DzMemberList +0x4d6e +0x4fd0 OP_OnLevelMessage +0x575b +0x7e94 +0x5189 OP_DzExpeditionEndsWarning +0x383c OP_BankerChange +0x791e +0x5c74 OP_RecipesFavorite +0x71b1 +0x20ab +0x025f +0x214a OP_PopupResponse +0x08a6 OP_ItemRecastDelay +0x15a9 OP_PVPLeaderBoardDetailsRequest +0x3707 OP_PVPLeaderBoardRequest +0x04aa OP_PVPLeaderBoardDetailsReply +0x25b7 OP_PVPLeaderBoardReply +0x071f +0x2dee +0x4e62 +0x0c91 +0x18d3 OP_Weblink +0x6f4b OP_PVPStats +0x4b15 +0x6755 +0x5c32 +0x5770 +0x7425 +0x5eed +0x574e +0x11b4 +0x4ed6 +0x0d9f +0x7d23 OP_ClearSurname +0x3fb0 +0xc693 OP_RemoveNimbusEffect +0x7b1e +0x20ae +0x0727 +0x3771 +0x7fe0 +0x4d5e +0x1877 OP_SendGuildTributes +0x649f +0x5f3f +0x5bcb +0x43d2 +0x49ea +0x378d OP_OpenGuildTributeMaster +0x7f8e +0x02bc +0x7dd2 +0x7c1d +0x7a41 +0x7db5 +0x7eec OP_SetChatServer2 +0x0904 OP_CorpseDrag +0x7037 OP_CorpseDrop +0x5e19 OP_TaskActivityComplete +0x4e32 +0x241d OP_TributeToggle +0x756a +0x7745 +0x039d +0x0f50 + +0x66b5 OP_SendAATable +0x0afb OP_AugmentInfo +0x10f6 +0x1013 + +0x6344 OP_RequestTitles +0x2d08 OP_SendTitleList +0x3719 +0x7a48 +0x0a23 OP_AcceptNewTask +0x705b +0x3bc9 OP_LevelAppearance +0x60ef +0x1619 +0x17fd OP_VoiceMacroIn +0x409a OP_VoiceMacroOut +0x4493 OP_WorldComplete +0x6527 OP_SetTitle +0x4c21 OP_SetTitleReply +0x127f OP_CameraEffect +0x0d32 OP_NewTitlesAvailable +0x34a7 OP_WeaponEquip1 +0x34cd +0x5936 OP_SpellEffect +0x241e OP_AutoFire +0x66f0 OP_UpdateAA +0x100e OP_CustomTitles +0x6b65 +0x12f5 +0x7677 OP_Bandolier +0x688f +0x7adf +0x0ed4 +0x243a OP_Barter +0x1a6a +0x5623 +0x43c8 OP_SendAAStats +0x655e +0x1a3e OP_PotionBelt +0x6326 OP_SetStartCity +0x7485 +0x5416 +0x3282 +0x3752 +0x425b +0x27c8 +0x2b19 +0x70ce +0x3165 +0x786b +0x0f26 +0x3500 +0x3d04 +0x5134 OP_GuildBank +0x0521 +0x7850 +0x108b +0x5671 +0x6d2b +0x732f +0x748f OP_GuildManageBanker +0x6858 +0x5e74 +0x3f35 +0x35e9 +0x2056 +0x6922 OP_AdventureMerchantRequest +0x5b72 OP_AdventureMerchantPurchase +0x2f9b OP_AdventureMerchantSell +0x3e47 OP_AdventureMerchantResponse +0x0b7d +0x2818 +0x35bd +0x51df +0x1ff7 +0x3926 +0x6265 +0x4ab0 +0x5e6c +0x1350 +0x6288 +0x7348 +0x48a2 OP_OpenNewTasksWindow +0x3010 +0x45db +0x36e8 OP_AvaliableTask +0x4865 +0x322e +0x7582 +0x5727 OP_TaskMemberList +0x6646 +0x37f2 +0x3444 +0x5ffc +0x5cb5 +0x0119 +0x35b5 +0x6cc6 +0x4926 +0x1b1d +0x7299 +0x0bf1 +0x08b4 +0x7f7a +0x3dab +0x1e7d +0x610a +0x04c8 +0x4811 +0x609e +0x65f0 +0x467f OP_CrystalCountUpdate +0x7aee OP_CrystalCreate +0x2439 OP_CrystalReclaim +0x39c1 +0x555e +0x7c9c +0x2c94 +0x2fc2 +0x2067 +0x059e +0x7f74 +0x68b2 +0x6f2b +0x01d6 +0x5182 +0x1da2 +0x5147 +0x51f8 +0x11f3 +0x0d07 +0x272f +0x413f +0x5968 +0x3e0e OP_DzCompass +0x282a +0x035f OP_GMNameChange +0x4013 +0x0e2f +0x099e +0x4eba OP_CompletedTasks +0x5f1c OP_TaskHistoryRequest +0x3d05 OP_TaskHistoryReply +0x2b8e +0x66d6 +0x0143 +0x6a5d +0x6e61 +0x2b0f +0x46c6 OP_FloatListThing +0x3a8d +0x15e5 +0x7d89 +0x4085 +0x1507 +0x5d93 +0x1669 +0x4664 +0x312d +0x2215 +0x1745 OP_Rewind +0x0cf1 +0x6567 +0x4405 +0x72d8 +0xaaba +0x27f8 OP_AssistGroup +0x7cfb +0x1a32 +0x14fd +0x77bb +0x36d1 +0x6193 +0x184c +0x3c47 +0x4e0b +0x7c15 +0x2ec3 OP_ShroudSelectionWindow +0x2b37 OP_ShroudRequestStats +0x6c04 OP_ShroudRespondStats +0x1cd0 OP_ShroudSelect +0x79da +0x7806 +0x541d OP_ShroudProgress +0x3823 +0x6562 OP_Shroud +0x4b25 +0x2507 +0x3acc +0x006e +0x06e +0x0728 +0x66cd +0x3c54 +0x2e8d +0x4eea +0x5a67 +0x3d20 +0x649c +0x21a6 +0x28bc OP_RespawnWindow +0x0ecb OP_ZonePlayerToBind +0x08d8 +0x7b71 +0x1115 +0x18cb +0x34f4 +0x5f08 +0x5bd2 +0x5052 +0x5e69 +0x2ccc +0x655c +0x6773 OP_CharacterCreateRequest +0x590e OP_VetRewardsAvaliable +0x6b0b +0x555a +0x7786 +0x67e8 +0x6381 +0x5628 +0xb52f +0x6084 +0x2958 OP_GuildUpdateURLAndChannel +0x2301 OP_WorldUnknown001 +0x610b +0x6f8b +0x4d25 OP_InspectMessageUpdate +0x3033 OP_BlockedBuffs +0x0de7 OP_RemoveBlockedBuffs +0x30e5 +0x618c +0x58e6 +0x1456 +0x053c OP_Untargetable +0x71da +0x333f +0x49bc +0x64f2 OP_BuffRemoveRequest +0x6b3d +0x34cb OP_ClearBlockedBuffs +0x5646 +0x7d13 +0x15e0 +0x5710 +0x172b +0x1888 +0x2956 +0x6a68 +0x7631 +0x298e +0x003c +0x03c +0x0b0f +0x5a72 +0x0767 +0x2f1a +0x6c7a +0x1660 +0x344f +0x028b +0x6eea +0x7707 +0x3fb2 +0x289e +0x3342 +0x5892 OP_GroupMentor +0x189c OP_NPCMoveUpdate +0x097b OP_ItemVerifyRequest +0x2115 OP_ItemVerifyReply +0x6411 +0x6471 +0x134a +0x1304 +0x5a79 +0x2dde +0x7d50 +0x1d47 +0x10ec +0x000f +0x00f OP_RestState +0x0f +0x465b +0x2289 OP_ItemViewUnknown +0x023b +0x4223 +0x7261 +0x2af9 +0x19aa +0x66dd OP_GMTrainSkillConfirm +0x4b64 +0x319e +0x1af3 +0x449c +0x8582 #OP_LoginUnknown1 +0x4b8d #OP_LoginUnknown2 +0x298d +0x06c8 +0x4f93 +0x412d +0x001f +0x01f +0x60f6 +0x1a9e +0x798e +0x17b7 +0x3042 +0x61bd +0x1f6e +0x65a6 +0x740d +0x48da +0x20d9 +0x5258 +0x1b5d +0x49f4 +0x7aa9 +0xb350 +0x6e2a +0x5d4e +0x6e4d +0x4ffc +0x1d15 +0x6f23 +0x2296 +0x765b +0x2e01 +0x26dd +0x72d3 +0x6981 +0x3b30 +0x14ac +0x0d92 +0x0001 +0x001 +0x01 +0x09bb +0x9e18 +0x0d9d +0x7f2b +0x3651 +0x645d +0x3af2 +0x4377 +0x39c9 +0x4924 +0x1e50 +0x4683 +0x0276 +0x6dec +0x56c9 +0x3ee6 +0x7121 OP_AltCurrency +0x62ab +0x5d88 +0x05f0 OP_MercenaryAssign +0x6b6d OP_AltCurrencyMerchantRequest +0x61cb OP_AltCurrencyPurchase +0x0165 OP_AltCurrencySell +0x74ec OP_AltCurrencyMerchantReply +0x5409 OP_AltCurrencySellSelection +0x3788 +0x40b6 +0x27a2 +0x532a OP_AltCurrencyReclaim +0x3899 +0x7567 +0x4820 +0x0339 +0x0c12 +0x074d +0x47ba +0x55c8 +0x4c89 +0x18b7 +0x2950 +0x44cb +0x4477 +0x6146 +0x40cf +0x2405 +0x49e2 +0x2aff +0x0bfa +0x26c0 +0x7d39 +0x259f +0x086b +0x6dc1 +0x6f80 +0x042e +0x2ad4 +0x317b +0x73ac +0x18d7 +0x5b8b +0x5c83 +0x1f51 +0x62f7 +0x1c46 +0x2a44 +0x3e7a +0x4374 +0x3b23 +0x1df4 +0x3ed8 +0x4b50 +0x36eb +0x65c7 +0x5620 +0x587e +0x3897 OP_SendFindableNPCs +0x7e62 +0x67ae +0x74f4 +0x4613 +0x2a92 +0x6d6e +0x2c01 +0x1243 +0x133e +0x67fc +0x49e1 OP_HideCorpse +0x0e44 +0x239a +0x1a0a +0x398f +0x1ff4 +0x88a1 +0x74da OP_GroupDisbandOther +0x21b4 OP_GroupLeaderChange +0x62b7 +0x4ced +0x3abb OP_GroupUpdate +0x0f6c OP_GroupDelete +0x0cbc +0x6194 OP_GroupUpdateB +0x7fe6 +0x04d0 +0x7323 OP_GroupAcknowledge +0x1ae5 OP_GroupDisbandYou +0x4d9f +0x70e2 OP_GroupRoles +0x6875 +0x6298 +0x02cf OP_GroupLeadershipAAUpdate +0x22b8 OP_MercenarySuspend2 +0x7bff +0x5512 +0x2b57 +0x1380 +0x2bcb +0x7b89 OP_MercenaryDataUpdateRequest +0x61a4 OP_MercenaryDataUpdate +0x11c1 OP_MercenaryDataRequest +0x72ce OP_MercenaryDataResponse +0x7169 OP_MercenaryHire +0x6e83 OP_MercenaryDismiss +0x31e4 OP_MercenaryTimerRequest +0x0763 OP_MercenaryTimer +0x78f6 +0x1b37 +0x27f2 OP_MercenaryCommand +0x5df8 +0x4333 +0x69ca +0x6e9f +0x4407 OP_MercenarySuspendRequest +0x6f03 OP_MercenarySuspendResponse +0x27a0 OP_MercenaryUnsuspendResponse +0x5f88 +0x2749 +0x038f +0x0e52 +0x20b9 +0x5d26 OP_MercenaryUnknown1 +0x69e7 +0x66b9 +0x0b72 +0x7e6f +0x29ec +0x6248 +0x702b +0x2b4f +0x6e6d +0x1e9f +0x5bd5 +0x4b7f +0x1490 +0x075e +0x4263 +0x1eba +0x4a74 +0x0a37 +0x3289 +0x3171 +0x0114 +0x5148 +0x76c3 +0x09bf +0x356f +0x77a7 +0x479a +0x209f +0x54e6 +0x6c3e +0xee80 +0x40e5 +0x76d9 +0x1dc8 OP_GuildCreate +0x794a +0x35c5 +0x137d +0x004a +0x04a +0x29b4 +0x18f1 +0x17fc +0x4707 OP_ChangeSize +0x3e15 +0x7248 +0x57c6 +0x7679 +0x6c8b +0x14c3 +0x3a02 +0x7900 +0x5688 +0x3a58 +0x75dd +0x39e1 +0x47cb +0x171e +0xdab0 +0x618f +0x27b1 +0x3d0c +0x0d2a +0x8c30 +0x2b42 +0x17f8 +0x1665 +0x059d +0x72c9 +0x675d +0x28e0 +0x61df +0x3ef8 +0x4d59 +0x3763 +0x672f OP_XTargetResponse +0x45be OP_XTargetRequest +0x792c OP_XTargetAutoAddHaters +0x66bf +0x66df +0x2aa7 +0x76c6 +0x6032 +0x3e00 +0x0c13 +0x0a59 +0x393a +0x45ed +0x507f +0x68ba +0x5a63 +0x6fd0 +0x63fd +0x4f09 +0x485d +0x3968 +0x69e1 +0x3d94 +0x0351 +0x5f0a +0x36be +0x59f9 +0x7075 +0x6ee6 +0x2691 +0x3c8b +0x01df +0x218c +0x233b +0x2cf7 +0x1097 +0x1baf +0x6f35 +0x1228 +0x1cef +0x7d28 +0x087f +0x1967 +0x6917 +0x613d +0x37d9 +0x58c7 +0x21ec +0x3424 +0x2036 +0x7ad1 +0x01c3 +0x626e +0x711a +0x5b41 +0x21ba +0x2933 +0x050c +0x51e3 +0x64a3 +0x3146 +0x2aa6 +0x16df +0x2698 +0x21ea +0x796c +0x7bb1 +0x6af6 +0x499a +0x3c44 +0x3cbc +0x6561 +0x12f7 +0x6292 +0x3de0 +0x1409 +0x4604 +0x0ca1 +0x754e +0x4f2b +0x6995 +0x3745 +0x789b +0xcadf +0x4abe +0x6014 +0x7fff +0x6228 +0x10e0 +0x7452 +0x6d9f +0x7f80 +0xb07f +0x6b5c OP_ItemPreview +0x02b4 +0x3bd3 +0x3036 +0x5c3f +0x433d +0x78e2 +0x543f +0x58b4 +0x2563 +0x1820 +0x40be +0x62d6 +0x0d68 +0x6d10 +0x3a32 +0x2fed +0x1303 +0x49df +0x3e24 +0x2b35 +0x0910 +0x3849 +0x6873 +0x15e2 +0x2d85 +0x39bb +0x42e9 +0x6860 +0x15a8 +0x52b5 +0x3311 +0x58df +0x2a7f +0x6573 +0x7a4d +0x7497 +0x1fcc +0x7c23 +0x2d28 +0x5dab +0x005a +0x05a +0x4506 +0x046d +0x36db +0x5a40 +0x4cd9 +0x63d7 +0x48d4 +0x035d +0x11f5 +0x7b84 +0x4f05 +0x7369 +0x7b32 +0x4fe6 +0x6cd0 +0x6770 +0x5c24 +0x063a +0x0d93 +0x4c2a +0x2235 +0x7b95 +0x6a1f +0x46f0 +0x2de2 +0xadd7 +0x2cc6 +0x7db7 +0x7588 +0x4957 +0x6a98 + +0x057b OP_SendMembershipDetails +0x7acc OP_SendMembership +0x431f +0x42c4 +0x05a8 +0x5475 OP_SendMaxCharacters +0x4ad2 +0x03d9 +0x771e +0x2a34 +0x7273 +0x1c9e +0x5f17 +0x37a9 +0x6530 +0x3157 +0x1f5e +0x2bc8 +0x593a +0x1643 +0x16bc +0x1781 +0x53d3 +0x5369 +0x25b3 +0x2fa0 +0x73a9 +0x1595 +0x6b6f +0x65f2 +0x3562 +0x309d +0x4efa +0x1da9 +0x6678 +0x16e8 diff --git a/utils/scripts/opcode_scripts/oplist_to_conf.pl b/utils/scripts/opcode_scripts/oplist_to_conf.pl new file mode 100644 index 000000000..0d808707d --- /dev/null +++ b/utils/scripts/opcode_scripts/oplist_to_conf.pl @@ -0,0 +1,88 @@ +#!/usr/bin/perl + +# File Name: oplist_to_conf.pl +# Converts the Opcode List with Opcode Names from the Spreadsheet into a Patch File. + +# Directions to use this script: +# 1. Copy the opcodes and opcode names columns from the opcode spreadsheet +# for the columns you want to create a new .conf file from into the file. +# 2. Remove the header row entries in the newly created text file and save it. +# 3. Paste the contents of the current patch file in the patch_OLD.conf file. +# 4. Run this script using "perl oplist_to_conf.pl" +# 5. This creates a new .conf file named patch_NEW.conf +# 6. Rename patch_NEW.conf to the desired name and you are all done + + +$stopmessage = "Failed to open file"; +# Open the text file that contains the opcode and opcode name rows for a single client from the opcode list spreadsheet +open OpcodeFile, "<", "opcodelist.txt" or die $stopmessage; +# Open the .conf file to copy from +open PatchFile, "<", "patch_OLD.conf" or die $stopmessage; + +# Read these files into arrays for looping and close the files +my @OpcodeList = ; +my @PatchFile = ; +close(OpcodeFile); +close(PatchFile); + +# Open the new/destination .conf file and clear out file contents +open OpcodeResultFile, ">", "patch_NEW.conf" or die $stopmessage; +print OpcodeResultFile ""; +# Close out the newly cleared .conf file +close(OpcodeResultFile); + +# Open the new/destination .conf file again for appending +open OpcodeResultFile, ">>", "patch_NEW.conf" or die $stopmessage; + +my %PatchHash = (); + +foreach $line (@OpcodeList) +{ + @equalssplit = split(/ /, $line); + $ArraySize = @equalssplit; + if ($ArraySize > 1) + { + my $CurOpcode = ""; + my $CurOpcodeName = ""; + @OpcodeArray = split(//, $equalssplit[0]); + if ($equalssplit[1] =~ /^OP_(.*)/i) + { + $CurOpcodeName = "OP_".$1; + } + foreach $Letter (@OpcodeArray) + { + if ($Letter =~ /[A-Za-z0-9]/) + { + $CurOpcode .= $Letter; + } + } + if ($CurOpcode && $CurOpcodeName) + { + $CurOpcode = lc($CurOpcode); + $PatchHash{ $CurOpcodeName } = $CurOpcode; + #print $CurOpcodeName."=". $CurOpcode."\n"; + } + } +} + +$TabSpace = " "; # Tab +foreach $line (@PatchFile) +{ + $CurLine = $line; + if ($line =~ /^OP_([^\=]+)=([^\s]+)(.*)/i) + { + $NewOpcode = "0x0000"; + $OpcodeName = "OP_".$1; + + if ($PatchHash{$OpcodeName}) + { + $NewOpcode = $PatchHash{$OpcodeName}; + } + + $CurLine = $OpcodeName."=".$NewOpcode.$3."\n"; + } + print OpcodeResultFile $CurLine; +} + + +close(OpcodeResultFile); diff --git a/utils/scripts/opcode_scripts/patch_NEW.conf b/utils/scripts/opcode_scripts/patch_NEW.conf new file mode 100644 index 000000000..148d00ba9 --- /dev/null +++ b/utils/scripts/opcode_scripts/patch_NEW.conf @@ -0,0 +1,661 @@ +# ShowEQ Import Notes: +# ZERO THE FILE first +# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf +# Unknown Mapping: +# OP_Action2 -> OP_Damage +# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake +# Name Differences: +# OP_CancelInvite -> OP_GroupCancelInvite +# OP_GMFind -> OP_FindPersonRequest +# OP_CommonMessage -> OP_ChannelMessage + +OP_Unknown=0x0000 +OP_ExploreUnknown=0x0000 used for unknown explorer + +# world packets +# Required to reach Char Select: +OP_SendLoginInfo=0x7a09 +OP_ApproveWorld=0x7499 +OP_LogServer=0x7ceb +OP_SendCharInfo=0x00d2 +OP_ExpansionInfo=0x590d +OP_GuildsList=0x0000 +OP_EnterWorld=0x578f +OP_PostEnterWorld=0x6259 +OP_World_Client_CRC1=0x12cc +OP_World_Client_CRC2=0x0f13 +OP_SendSpellChecksum=0x0000 +OP_SendSkillCapsChecksum=0x0000 + +# Character Select Related: +OP_SendMaxCharacters=0x5475 +OP_SendMembership=0x7acc +OP_SendMembershipDetails=0x057b +OP_CharacterCreateRequest=0x6773 +OP_CharacterCreate=0x6bbf +OP_DeleteCharacter=0x1808 +OP_RandomNameGenerator=0x5954 +OP_ApproveName=0x56a2 +OP_MOTD=0x0c22 +OP_SetChatServer=0x1bc5 +OP_SetChatServer2=0x7eec +OP_ZoneServerInfo=0x4c44 +OP_WorldComplete=0x4493 +OP_WorldUnknown001=0x2301 +OP_FloatListThing=0x46c6 + +# Reasons for Disconnect: +OP_ZoneUnavail=0x4cb4 +OP_WorldClientReady=0x23c1 +OP_CharacterStillInZone=0x0000 +OP_WorldChecksumFailure=0x0000 +OP_WorldLoginFailed=0x0000 +OP_WorldLogout=0x0000 +OP_WorldLevelTooHigh=0x0000 +OP_CharInacessable=0x0000 +OP_UserCompInfo=0x0000 +OP_SendExeChecksum=0x0000 +OP_SendBaseDataChecksum=0x0000 + +# Zone in opcodes +OP_AckPacket=0x471d +OP_ZoneEntry=0x5089 +OP_ReqNewZone=0x7887 +OP_NewZone=0x1795 +OP_ZoneSpawns=0x5237 +OP_PlayerProfile=0x6506 +OP_TimeOfDay=0x5070 +OP_LevelUpdate=0x1eec +OP_Stamina=0x2a79 +OP_RequestClientZoneChange=0x3fcf +OP_ZoneChange=0x2d18 +OP_LockoutTimerInfo=0x0000 +OP_ZoneServerReady=0x0000 +OP_ZoneInUnknown=0x0000 +OP_LogoutReply=0x0000 +OP_PreLogoutReply=0x0000 + +# Required to fully log in +OP_SpawnAppearance=0x0971 +OP_ChangeSize=0x4707 +OP_TributeUpdate=0x5961 +OP_TributeTimer=0x073d +OP_SendTributes=0x729b +OP_SendGuildTributes=0x1877 +OP_TributeInfo=0x4254 +OP_Weather=0x661e +OP_ReqClientSpawn=0x35fa +OP_SpawnDoor=0x7291 +OP_GroundSpawn=0x6fca +OP_SendZonepoints=0x69a4 +OP_BlockedBuffs=0x3033 +OP_RemoveBlockedBuffs=0x0de7 +OP_ClearBlockedBuffs=0x34cb +OP_WorldObjectsSent=0x5ae2 +OP_SendExpZonein=0x5f8e +OP_SendAATable=0x66b5 +OP_RespondAA=0x7a27 +OP_UpdateAA=0x66f0 +OP_SendAAStats=0x43c8 +OP_AAExpUpdate=0x7d14 +OP_ExpUpdate=0x20ed +OP_HPUpdate=0x2828 +OP_ManaChange=0x43af +OP_TGB=0x0876 +OP_SpecialMesg=0x0083 +OP_GuildMemberList=0x12a6 +OP_GuildMOTD=0x3e13 +OP_CharInventory=0x5ca6 +OP_WearChange=0x7994 +OP_ClientUpdate=0x7dfc +OP_ClientReady=0x345d # 0x422d +OP_SetServerFilter=0x444d + +# Guild Opcodes - Disabled until crashes are resolved in RoF +OP_GetGuildMOTD=0x36e0 # Was 0x35dc +OP_GetGuildMOTDReply=0x4f1f # Was 0x4586 +OP_GuildMemberUpdate=0x69b9 # Was 0x5643 +OP_GuildInvite=0x7099 +OP_GuildRemove=0x1444 +OP_GuildPeace=0x67e3 +OP_SetGuildMOTD=0x0b0b +OP_GuildList=0x507a +OP_GuildWar=0x1ffb +OP_GuildLeader=0x7e09 +OP_GuildDelete=0x3708 +OP_GuildInviteAccept=0x7053 +OP_GuildDemote=0x2d4e +OP_GuildPromote=0x0000 +OP_GuildPublicNote=0x5053 +OP_GuildManageBanker=0x748f # Was 0x0737 +OP_GuildBank=0x5134 # Was 0x10c3 +OP_SetGuildRank=0x0b9c +OP_GuildUpdateURLAndChannel=0x2958 +OP_GuildStatus=0x7326 +OP_GuildCreate=0x1dc8 # or maybe 0x086e +OP_GuildMemberLevelUpdate=0x0000 # Unused? +OP_ZoneGuildList=0x0000 # Unused? +OP_GetGuildsList=0x0000 # Unused? +OP_LFGuild=0x0000 +OP_GuildManageRemove=0x0000 +OP_GuildManageAdd=0x0000 +OP_GuildManageStatus=0x0000 + +# GM/Guide Opcodes +OP_GMServers=0x08c1 +OP_GMBecomeNPC=0x3ae1 +OP_GMZoneRequest=0x62ac +OP_GMZoneRequest2=0x7e1a +OP_GMGoto=0x7d8e +OP_GMSearchCorpse=0x357c +OP_GMHideMe=0x79c5 +OP_GMDelCorpse=0x607e +OP_GMApproval=0x6db5 +OP_GMToggle=0x2097 +OP_GMSummon=0x486f # Was 0x684f +OP_GMEmoteZone=0x1cfd # Was 0x0655 +OP_GMEmoteWorld=0x458e # Was 0x1935 +OP_GMFind=0x4a8f +OP_GMKick=0x26a7 +OP_GMKill=0x51d3 +OP_GMNameChange=0x035f # Was 0x4434 +OP_GMLastName=0x46ce # Was 0x3077 + +# Misc Opcodes +OP_InspectRequest=0x57bc +OP_InspectAnswer=0x71ac +OP_InspectMessageUpdate=0x4d25 +OP_BeginCast=0x318f +OP_ColoredText=0x0000 +OP_ConsentResponse=0x384a +OP_MemorizeSpell=0x217c +OP_SwapSpell=0x0efa +OP_CastSpell=0x1287 +OP_Consider=0x742b +OP_FormattedMessage=0x1024 +OP_SimpleMessage=0x213f +OP_Buff=0x659c +OP_Illusion=0x312a +OP_MoneyOnCorpse=0x5f44 +OP_RandomReply=0x106b +OP_DenyResponse=0x2382 +OP_SkillUpdate=0x004c +OP_GMTrainSkillConfirm=0x66dd # 0x3960 +OP_RandomReq=0x7b10 +OP_Death=0x6517 +OP_GMTraining=0x1966 +OP_GMEndTraining=0x4d6b +OP_GMTrainSkill=0x2a85 +OP_Animation=0x7177 +OP_Begging=0x6703 +OP_Consent=0x1fd1 +OP_ConsentDeny=0x7a45 +OP_AutoFire=0x241e +OP_PetCommands=0x0159 +OP_DeleteSpell=0x52e5 +OP_Surname=0x0423 +OP_ClearSurname=0x7d23 +OP_FaceChange=0x5578 +OP_SenseHeading=0x260a +OP_Action=0x744c +OP_ConsiderCorpse=0x5204 +OP_HideCorpse=0x49e1 +OP_CorpseDrag=0x0904 +OP_CorpseDrop=0x7037 +OP_Bug=0x73f4 +OP_Feedback=0x5602 +OP_Report=0x1414 +OP_Damage=0x6f15 +OP_ChannelMessage=0x2b2d +OP_Assist=0x4478 +OP_AssistGroup=0x27f8 +OP_MoveCoin=0x0bcf +OP_ZonePlayerToBind=0x0ecb +OP_KeyRing=0x6857 +OP_WhoAllRequest=0x65ab +OP_WhoAllResponse=0x7c88 +OP_FriendsWho=0x3956 +OP_ConfirmDelete=0x43a3 +OP_Logout=0x4ac6 +OP_Rewind=0x1745 +OP_TargetCommand=0x58e2 +OP_Hide=0x67fe +OP_Jump=0x2060 +OP_Camp=0x28ec +OP_Emote=0x373b +OP_SetRunMode=0x009f +OP_BankerChange=0x383c +OP_TargetMouse=0x075d +OP_MobHealth=0x37b1 +OP_InitialMobHealth=0x0000 # Unused? +OP_TargetHoTT=0x0272 +OP_XTargetResponse=0x672f +OP_XTargetRequest=0x45be +OP_XTargetAutoAddHaters=0x792c +OP_TargetBuffs=0x4f4b +OP_BuffCreate=0x3377 +OP_BuffRemoveRequest=0x64f2 +OP_DeleteSpawn=0x7280 +OP_AutoAttack=0x109d +OP_AutoAttack2=0x3526 +OP_Consume=0x4b70 +OP_MoveItem=0x32ee +OP_DeleteItem=0x18ad +OP_DeleteCharge=0x01b8 +OP_ItemPacket=0x368e +OP_ItemLinkResponse=0x633c +OP_ItemLinkClick=0x4cef +OP_ItemPreview=0x6b5c +OP_NewSpawn=0x6097 +OP_Track=0x17e5 +OP_TrackTarget=0x0029 +OP_TrackUnknown=0x4577 +OP_ClickDoor=0x3a8f +OP_MoveDoor=0x08e8 +OP_RemoveAllDoors=0x700c +OP_EnvDamage=0x51fd +OP_BoardBoat=0x4211 +OP_Forage=0x5306 +OP_LeaveBoat=0x7617 +OP_ControlBoat=0x0ae7 +OP_SafeFallSuccess=0x2219 +OP_RezzComplete=0x760d +OP_RezzRequest=0x3c21 +OP_RezzAnswer=0x701c +OP_Shielding=0x48c1 +OP_RequestDuel=0x3af1 +OP_MobRename=0x2c57 +OP_AugmentItem=0x661b # Was 0x37cb +OP_WeaponEquip1=0x34a7 +OP_WeaponEquip2=0x559a # Was 0x6022 +OP_WeaponUnequip2=0x2d25 # Was 0x0110 +OP_ApplyPoison=0x31e6 +OP_Save=0x4a39 +OP_TestBuff=0x7cb8 # Was 0x3772 +OP_CustomTitles=0x100e +OP_Split=0x3a54 +OP_YellForHelp=0x4e56 +OP_LoadSpellSet=0x261d +OP_Bandolier=0x7677 +OP_PotionBelt=0x1a3e # Was 0x4d3b +OP_DuelResponse=0x6a46 +OP_DuelResponse2=0x68d3 +OP_SaveOnZoneReq=0x600d +OP_ReadBook=0x72df +OP_Dye=0x23b9 +OP_InterruptCast=0x048c +OP_AAAction=0x424e +OP_LeadershipExpToggle=0x6c55 +OP_LeadershipExpUpdate=0x2797 +OP_PurchaseLeadershipAA=0x0026 +OP_UpdateLeadershipAA=0x026 +OP_MarkNPC=0x5a58 +OP_MarkRaidNPC=0x74bd #unimplemented +OP_ClearNPCMarks=0x2003 +OP_ClearRaidNPCMarks=0x20d3 #unimplemented +OP_DelegateAbility=0x76b8 +OP_SetGroupTarget=0x2814 +OP_Charm=0x5d92 +OP_Stun=0x36a4 +OP_SendFindableNPCs=0x3897 +OP_FindPersonRequest=0x5cea +OP_FindPersonReply=0x7e58 +OP_Sound=0x1a30 +OP_PetBuffWindow=0x5882 +OP_LevelAppearance=0x3bc9 +OP_Translocate=0x6580 +OP_Sacrifice=0x1821 +OP_PopupResponse=0x214a +OP_OnLevelMessage=0x4fd0 +OP_AugmentInfo=0x0afb +OP_Petition=0x5f03 +OP_SomeItemPacketMaybe=0x747c +OP_PVPStats=0x6f4b # Unsure +OP_PVPLeaderBoardRequest=0x3707 +OP_PVPLeaderBoardReply=0x25b7 +OP_PVPLeaderBoardDetailsRequest=0x15a9 +OP_PVPLeaderBoardDetailsReply=0x04aa +OP_RestState=0x00f +OP_RespawnWindow=0x28bc +OP_LDoNButton=0x5327 +OP_SetStartCity=0x6326 # Was 0x2d1b +OP_VoiceMacroIn=0x17fd +OP_VoiceMacroOut=0x409a +OP_ItemViewUnknown=0x2289 +OP_VetRewardsAvaliable=0x590e +OP_VetClaimRequest=0x1126 +OP_VetClaimReply=0x16d4 +OP_DisciplineUpdate=0x759e # Was 0x2f05 +OP_DisciplineTimer=0x6989 # Was 0x5e3f +OP_BecomeCorpse=0x0000 # Unused? +OP_Action2=0x0000 # Unused? +OP_MobUpdate=0x2c84 +OP_NPCMoveUpdate=0x189c +OP_CameraEffect=0x127f +OP_SpellEffect=0x5936 +OP_RemoveNimbusEffect=0xc693 +OP_AltCurrency=0x7121 +OP_AltCurrencyMerchantRequest=0x6b6d +OP_AltCurrencyMerchantReply=0x74ec +OP_AltCurrencyPurchase=0x61cb +OP_AltCurrencySell=0x0165 +OP_AltCurrencySellSelection=0x5409 +OP_AltCurrencyReclaim=0x532a +OP_CrystalCountUpdate=0x467f # Was 0x3f60 +OP_CrystalCreate=0x7aee # Was 0x5a82 +OP_CrystalReclaim=0x2439 # Was 0x7616 +OP_Untargetable=0x053c +OP_IncreaseStats=0x70a3 +OP_Weblink=0x18d3 +#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U +OP_OpenContainer=0x0000 +OP_Marquee=0x0000 + +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 +OP_DzAddPlayer=0x4701 +OP_DzRemovePlayer=0x1abc +OP_DzSwapPlayer=0x405b +OP_DzMakeLeader=0x543d +OP_DzPlayerList=0x14c6 +OP_DzJoinExpeditionConfirm=0x7f4b +OP_DzJoinExpeditionReply=0x1950 +OP_DzExpeditionInfo=0x9119 +OP_DzExpeditionList=0x205f +OP_DzMemberStatus=0x32f0 +OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 +OP_DzMemberList=0x5ae4 +OP_DzCompass=0x3e0e # Was 0x4f09 +OP_DzChooseZone=0x0000 # Maybe 0x29d6 + +# New Opcodes +OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? +OP_ManaUpdate=0x3791 +OP_EnduranceUpdate=0x5f42 +OP_MobManaUpdate=0x2404 +OP_MobEnduranceUpdate=0x1c81 + +# Mercenary Opcodes +OP_MercenaryDataUpdateRequest=0x7b89 +OP_MercenaryDataUpdate=0x61a4 +OP_MercenaryDataRequest=0x11c1 +OP_MercenaryDataResponse=0x72ce +OP_MercenaryHire=0x7169 +OP_MercenaryDismiss=0x6e83 +OP_MercenaryTimerRequest=0x31e4 +OP_MercenaryTimer=0x0763 +OP_MercenaryUnknown1=0x5d26 +OP_MercenaryCommand=0x27f2 +OP_MercenarySuspendRequest=0x4407 +OP_MercenarySuspendResponse=0x6f03 +OP_MercenaryUnsuspendResponse=0x27a0 + +# Looting +OP_LootRequest=0x0adf +OP_EndLootRequest=0x30f7 +OP_LootItem=0x4dc9 +OP_LootComplete=0x55c4 + +# bazaar trader stuff: +OP_BazaarSearch=0x39d6 +OP_TraderDelItem=0x0000 +OP_BecomeTrader=0x61b3 +OP_TraderShop=0x31df +OP_Trader=0x4ef5 # Was 0x6790 +OP_TraderBuy=0x0000 +OP_Barter=0x243a +OP_ShopItem=0x0000 +OP_BazaarInspect=0x0000 +OP_Bazaar=0x0000 +OP_TraderItemUpdate=0x0000 + +# pc/npc trading +OP_TradeRequest=0x77b5 +OP_TradeAcceptClick=0x69e2 +OP_TradeRequestAck=0x14bf +OP_TradeCoins=0x4206 +OP_FinishTrade=0x3993 +OP_CancelTrade=0x354c +OP_TradeMoneyUpdate=0x68c2 +OP_MoneyUpdate=0x640c +OP_TradeBusy=0x5505 + +# Sent after canceling trade or after closing tradeskill object +OP_FinishWindow=0x7349 +OP_FinishWindow2=0x40ef + +# Sent on Live for what seems to be item existance verification +# Ex. Before Right Click Effect happens from items +OP_ItemVerifyRequest=0x097b +OP_ItemVerifyReply=0x2115 + +# merchant stuff +OP_ShopPlayerSell=0x1901 +OP_ShopRequest=0x4fed +OP_ShopEnd=0x30a8 +OP_ShopEndConfirm=0x3196 +OP_ShopPlayerBuy=0x04c +OP_ShopDelItem=0x724f + +# tradeskill stuff: +OP_ClickObject=0x4aa1 +OP_ClickObjectAction=0x0c1e +OP_ClearObject=0x7a11 +OP_RecipeDetails=0x40d7 +OP_RecipesFavorite=0x5c74 +OP_RecipesSearch=0x1db6 +OP_RecipeReply=0x6e02 +OP_RecipeAutoCombine=0x6261 +OP_TradeSkillCombine=0x579a + +# Tribute Packets: +OP_OpenGuildTributeMaster=0x378d +OP_OpenTributeMaster=0x7666 # Was 0x40f5 +OP_SelectTribute=0x79fc +OP_TributeItem=0x4f3e +OP_TributeMoney=0x58fb # Was 0x6fed +OP_TributeToggle=0x241d +OP_TributePointUpdate=0x5300 +OP_TributeNPC=0x0000 +OP_GuildTributeInfo=0x0000 +OP_OpenTributeReply=0x0000 +OP_GuildTributeStatus=0x0000 + +# Adventure packets: +OP_LeaveAdventure=0x5d18 +OP_AdventureFinish=0x400f +OP_AdventureInfoRequest=0x3cb0 +OP_AdventureInfo=0x4c54 +OP_AdventureRequest=0x2c6c +OP_AdventureDetails=0x5648 +OP_AdventureData=0x7171 +OP_AdventureUpdate=0x1b01 +OP_AdventureMerchantRequest=0x6922 # Was 654d +OP_AdventureMerchantResponse=0x3e47 # Was 7949 +OP_AdventureMerchantPurchase=0x5b72 # Was 155a +OP_AdventureMerchantSell=0x2f9b # Was 389c +OP_AdventurePointsUpdate=0x65c3 # Was 7589 +OP_AdventureStatsRequest=0x5a62 +OP_AdventureStatsReply=0x2370 +OP_AdventureLeaderboardRequest=0x7093 +OP_AdventureLeaderboardReply=0x7f79 + +# Group Opcodes +OP_GroupDisband=0x4c10 +OP_GroupInvite=0x1649 +OP_GroupFollow=0x05ce +OP_GroupUpdate=0x3abb +OP_GroupUpdateB=0x6194 +OP_GroupCancelInvite=0x0000 +OP_GroupAcknowledge=0x7323 +OP_GroupDelete=0x0f6c +OP_CancelInvite=0x32c2 +OP_GroupFollow2=0x2a50 +OP_GroupInvite2=0x6c65 +OP_GroupDisbandYou=0x1ae5 +OP_GroupDisbandOther=0x74da +OP_GroupLeaderChange=0x21b4 +OP_GroupRoles=0x70e2 +OP_GroupMakeLeader=0x4229 +OP_DoGroupLeadershipAbility=0x1fb5 +OP_GroupLeadershipAAUpdate=0x02cf +OP_GroupMentor=0x5892 +OP_InspectBuffs=0x486c + +# LFG/LFP Opcodes +OP_LFGCommand=0x6060 +OP_LFGGetMatchesRequest=0x0340 +OP_LFGGetMatchesResponse=0x5048 +OP_LFPGetMatchesRequest=0x4d7d +OP_LFPGetMatchesResponse=0x22c6 +OP_LFPCommand=0x49a9 +OP_LFGAppearance=0x0000 +OP_LFGResponse=0x0000 + +# Raid Opcodes +OP_RaidInvite=0x55ac +OP_RaidUpdate=0x3973 +OP_RaidJoin=0x0000 + +# Button-push commands +OP_Taunt=0x2703 +OP_CombatAbility=0x3eba +OP_SenseTraps=0x02af # Was 0x2ee0 +OP_PickPocket=0x39e8 +OP_DisarmTraps=0x78bf +OP_Disarm=0x5ec8 +OP_Sneak=0x5d55 +OP_Fishing=0x1e2a +OP_InstillDoubt=0x640e +OP_FeignDeath=0x52fa +OP_Mend=0x0ecf +OP_Bind_Wound=0x0386 +OP_LDoNOpen=0x3d5c + +# Task packets +OP_TaskDescription=0x083 +OP_TaskActivity=0x3714 +OP_CompletedTasks=0x4eba +OP_TaskActivityComplete=0x5e19 +OP_AcceptNewTask=0x0a23 +OP_CancelTask=0x08d3 +OP_TaskMemberList=0x5727 # Was 0x1656 +OP_OpenNewTasksWindow=0x48a2 # Was 0x11de +OP_AvaliableTask=0x36e8 # Was 0x2377 +OP_TaskHistoryRequest=0x5f1c +OP_TaskHistoryReply=0x3d05 +OP_DeclineAllTasks=0x0000 + +# Title opcodes +OP_NewTitlesAvailable=0x0d32 +OP_RequestTitles=0x6344 +OP_SendTitleList=0x2d08 +OP_SetTitle=0x6527 +OP_SetTitleReply=0x4c21 + +# mail opcodes +OP_Command=0x0000 +OP_MailboxHeader=0x0000 +OP_MailHeader=0x0000 +OP_MailBody=0x0000 +OP_NewMail=0x0000 +OP_SentConfirm=0x0000 + +########### Below this point should not be needed ########### + +# This section are all unknown in Titanium +OP_ForceFindPerson=0x0000 +OP_LocInfo=0x0000 +OP_ReloadUI=0x0000 +OP_ItemName=0x0000 +OP_ItemLinkText=0x0000 +OP_MultiLineMsg=0x0000 +OP_MendHPUpdate=0x0000 +OP_TargetReject=0x0000 +OP_SafePoint=0x0000 +OP_ApproveZone=0x0000 +OP_ZoneComplete=0x0000 +OP_ClientError=0x0000 +OP_DumpName=0x0000 +OP_Heartbeat=0x0000 +OP_CrashDump=0x0000 +OP_LoginComplete=0x0000 + +# discovered opcodes not yet used: +OP_PickLockSuccess=0x0000 +OP_PlayMP3=0x0000 +OP_ReclaimCrystals=0x0000 +OP_DynamicWall=0x0000 +OP_OpenDiscordMerchant=0x0000 +OP_DiscordMerchantInventory=0x0000 +OP_GiveMoney=0x0000 +OP_RequestKnowledgeBase=0x0000 +OP_KnowledgeBase=0x0000 +OP_SlashAdventure=0x0000 # /adventure +OP_BecomePVPPrompt=0x0000 +OP_MoveLogRequest=0x0000 # gone I think +OP_MoveLogDisregard=0x0000 # gone I think + +# named unknowns, to make looking for real unknown easier +OP_AnnoyingZoneUnknown=0x0000 +OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_QueryResponseThing=0x0000 + + +# realityincarnate: these are just here to stop annoying several thousand byte packet dumps +#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum +#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum + +# Petition Opcodes +OP_PetitionSearch=0x0000 search term for petition +OP_PetitionSearchResults=0x0000 (list of?) matches from search +OP_PetitionSearchText=0x0000 text results of search + +OP_PetitionUpdate=0x0000 +OP_PetitionCheckout=0x0000 +OP_PetitionCheckIn=0x0000 +OP_PetitionQue=0x0000 +OP_PetitionUnCheckout=0x0000 +OP_PetitionDelete=0x0000 +OP_DeletePetition=0x0000 +OP_PetitionResolve=0x0000 +OP_PDeletePetition=0x0000 +OP_PetitionBug=0x0000 +OP_PetitionRefresh=0x0000 +OP_PetitionCheckout2=0x0000 +OP_PetitionViewPetition=0x0000 + +# Login opcodes +OP_SessionReady=0x0000 +OP_Login=0x0000 +OP_ServerListRequest=0x0000 +OP_PlayEverquestRequest=0x0000 +OP_PlayEverquestResponse=0x0000 +OP_ChatMessage=0x0000 +OP_LoginAccepted=0x0000 +OP_ServerListResponse=0x0000 +OP_Poll=0x0000 +OP_EnterChat=0x0000 +OP_PollResponse=0x0000 + +# raw opcodes +OP_RAWSessionRequest=0x0000 +OP_RAWSessionResponse=0x0000 +OP_RAWCombined=0x0000 +OP_RAWSessionDisconnect=0x0000 +OP_RAWKeepAlive=0x0000 +OP_RAWSessionStatRequest=0x0000 +OP_RAWSessionStatResponse=0x0000 +OP_RAWPacket=0x0000 +OP_RAWFragment=0x0000 +OP_RAWOutOfOrderAck=0x0000 +OP_RAWAck=0x0000 +OP_RAWAppCombined=0x0000 +OP_RAWOutOfSession=0x0000 + +# we need to document the differences between these packets to make identifying them easier +OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs +OP_InitialHPUpdate=0x0000 + +OP_ItemRecastDelay=0x08a6 diff --git a/utils/scripts/opcode_scripts/patch_OLD.conf b/utils/scripts/opcode_scripts/patch_OLD.conf new file mode 100644 index 000000000..4bc1f9097 --- /dev/null +++ b/utils/scripts/opcode_scripts/patch_OLD.conf @@ -0,0 +1,661 @@ +# ShowEQ Import Notes: +# ZERO THE FILE first +# perl -pi -e 's/0x[0-9a-fA-F]{4}/0x0000/g' opcodes.conf +# Unknown Mapping: +# OP_Action2 -> OP_Damage +# OP_EnvDamage -> OP_Damage ---> might have been a one time mistake +# Name Differences: +# OP_CancelInvite -> OP_GroupCancelInvite +# OP_GMFind -> OP_FindPersonRequest +# OP_CommonMessage -> OP_ChannelMessage + +OP_Unknown=0x0000 +OP_ExploreUnknown=0x0000 used for unknown explorer + +# world packets +# Required to reach Char Select: +OP_SendLoginInfo=0x7a09 +OP_ApproveWorld=0x7499 +OP_LogServer=0x7ceb +OP_SendCharInfo=0x00d2 +OP_ExpansionInfo=0x590d +OP_GuildsList=0x7056 +OP_EnterWorld=0x0641 +OP_PostEnterWorld=0x6259 +OP_World_Client_CRC1=0x12cc +OP_World_Client_CRC2=0x0f13 +OP_SendSpellChecksum=0x0000 +OP_SendSkillCapsChecksum=0x0000 + +# Character Select Related: +OP_SendMaxCharacters=0x05a8 +OP_SendMembership=0x057b +OP_SendMembershipDetails=0x6a98 +OP_CharacterCreateRequest=0x655c +OP_CharacterCreate=0x6bbf +OP_DeleteCharacter=0x1808 +OP_RandomNameGenerator=0x5954 +OP_ApproveName=0x56a2 +OP_MOTD=0x0c22 +OP_SetChatServer=0x1bc5 +OP_SetChatServer2=0x7db5 +OP_ZoneServerInfo=0x6ef5 +OP_WorldComplete=0x4493 +OP_WorldUnknown001=0x2958 +OP_FloatListThing=0x46c6 + +# Reasons for Disconnect: +OP_ZoneUnavail=0x4c44 +OP_WorldClientReady=0x23c1 +OP_CharacterStillInZone=0x0000 +OP_WorldChecksumFailure=0x0000 +OP_WorldLoginFailed=0x0000 +OP_WorldLogout=0x0000 +OP_WorldLevelTooHigh=0x0000 +OP_CharInacessable=0x0000 +OP_UserCompInfo=0x0000 +OP_SendExeChecksum=0x0000 +OP_SendBaseDataChecksum=0x0000 + +# Zone in opcodes +OP_AckPacket=0x471d +OP_ZoneEntry=0x5089 +OP_ReqNewZone=0x7887 +OP_NewZone=0x1795 +OP_ZoneSpawns=0x5237 +OP_PlayerProfile=0x6506 +OP_TimeOfDay=0x5070 +OP_LevelUpdate=0x1eec +OP_Stamina=0x2a79 +OP_RequestClientZoneChange=0x3fcf +OP_ZoneChange=0x2d18 +OP_LockoutTimerInfo=0x0000 +OP_ZoneServerReady=0x0000 +OP_ZoneInUnknown=0x0000 +OP_LogoutReply=0x0000 +OP_PreLogoutReply=0x0000 + +# Required to fully log in +OP_SpawnAppearance=0x0971 +OP_ChangeSize=0x4707 +OP_TributeUpdate=0x5961 +OP_TributeTimer=0x073d +OP_SendTributes=0x729b +OP_SendGuildTributes=0x4d5e +OP_TributeInfo=0x4254 +OP_Weather=0x661e +OP_ReqClientSpawn=0x35fa +OP_SpawnDoor=0x7291 +OP_GroundSpawn=0x6fca +OP_SendZonepoints=0x69a4 +OP_BlockedBuffs=0x4d25 +OP_RemoveBlockedBuffs=0x3033 +OP_ClearBlockedBuffs=0x6b3d +OP_WorldObjectsSent=0x5ae2 +OP_SendExpZonein=0x5f8e +OP_SendAATable=0x66b5 +OP_RespondAA=0x7a27 +OP_UpdateAA=0x66f0 +OP_SendAAStats=0x43c8 +OP_AAExpUpdate=0x7e92 +OP_ExpUpdate=0x20ed +OP_HPUpdate=0x2828 +OP_ManaChange=0x1287 +OP_TGB=0x0000 +OP_SpecialMesg=0x0000 +OP_GuildMemberList=0x0e48 +OP_GuildMOTD=0x3e13 +OP_CharInventory=0x5ca6 +OP_WearChange=0x7994 +OP_ClientUpdate=0x7dfc +OP_ClientReady=0x345d # 0x422d +OP_SetServerFilter=0x444d + +# Guild Opcodes - Disabled until crashes are resolved in RoF +OP_GetGuildMOTD=0x36e0 # Was 0x35dc +OP_GetGuildMOTDReply=0x4f1f # Was 0x4586 +OP_GuildMemberUpdate=0x69b9 # Was 0x5643 +OP_GuildInvite=0x7099 +OP_GuildRemove=0x1444 +OP_GuildPeace=0x084e +OP_SetGuildMOTD=0x0b0b +OP_GuildList=0x0000 +OP_GuildWar=0x46ce +OP_GuildLeader=0x2f3e +OP_GuildDelete=0x3708 +OP_GuildInviteAccept=0x7053 +OP_GuildDemote=0x2d4e +OP_GuildPromote=0x0000 +OP_GuildPublicNote=0x5053 +OP_GuildManageBanker=0x748f # Was 0x0737 +OP_GuildBank=0x5134 # Was 0x10c3 +OP_SetGuildRank=0x0b9c +OP_GuildUpdateURLAndChannel=0x6084 +OP_GuildStatus=0x7326 +OP_GuildCreate=0x1dc8 # or maybe 0x086e +OP_GuildMemberLevelUpdate=0x0000 # Unused? +OP_ZoneGuildList=0x0000 # Unused? +OP_GetGuildsList=0x0000 # Unused? +OP_LFGuild=0x0000 +OP_GuildManageRemove=0x0000 +OP_GuildManageAdd=0x0000 +OP_GuildManageStatus=0x0000 + +# GM/Guide Opcodes +OP_GMServers=0x08c1 +OP_GMBecomeNPC=0x3ae1 +OP_GMZoneRequest=0x62ac +OP_GMZoneRequest2=0x7e1a +OP_GMGoto=0x7d8e +OP_GMSearchCorpse=0x46b1 +OP_GMHideMe=0x79c5 +OP_GMDelCorpse=0x607e +OP_GMApproval=0x6db5 +OP_GMToggle=0x2097 +OP_GMSummon=0x486f # Was 0x684f +OP_GMEmoteZone=0x1cfd # Was 0x0655 +OP_GMEmoteWorld=0x458e # Was 0x1935 +OP_GMFind=0x4a8f +OP_GMKick=0x26a7 +OP_GMKill=0x51d3 +OP_GMNameChange=0x035f # Was 0x4434 +OP_GMLastName=0x16ce # Was 0x3077 + +# Misc Opcodes +OP_InspectRequest=0x57bc +OP_InspectAnswer=0x71ac +OP_InspectMessageUpdate=0x6f8b +OP_BeginCast=0x318f +OP_ColoredText=0x0000 +OP_ConsentResponse=0x384a +OP_MemorizeSpell=0x6a0d +OP_SwapSpell=0x0efa +OP_CastSpell=0x4466 +OP_Consider=0x742b +OP_FormattedMessage=0x1024 +OP_SimpleMessage=0x213f +OP_Buff=0x3a54 +OP_Illusion=0x312a +OP_MoneyOnCorpse=0x5f44 +OP_RandomReply=0x106b +OP_DenyResponse=0x2382 +OP_SkillUpdate=0x2264 +OP_GMTrainSkillConfirm=0x19aa # 0x3960 +OP_RandomReq=0x7b10 +OP_Death=0x6517 +OP_GMTraining=0x1966 +OP_GMEndTraining=0x4d6b +OP_GMTrainSkill=0x2a85 +OP_Animation=0x7177 +OP_Begging=0x6703 +OP_Consent=0x1fd1 +OP_ConsentDeny=0x7a45 +OP_AutoFire=0x241e +OP_PetCommands=0x0159 +OP_DeleteSpell=0x52e5 +OP_Surname=0x0423 +OP_ClearSurname=0x7d23 +OP_FaceChange=0x5578 +OP_SenseHeading=0x217c +OP_Action=0x744c +OP_ConsiderCorpse=0x5204 +OP_HideCorpse=0x67fc +OP_CorpseDrag=0x7eec +OP_CorpseDrop=0x0904 +OP_Bug=0x73f4 +OP_Feedback=0x5602 +OP_Report=0x1414 +OP_Damage=0x6f15 +OP_ChannelMessage=0x2b2d +OP_Assist=0x4478 +OP_AssistGroup=0x27f8 +OP_MoveCoin=0x0bcf +OP_ZonePlayerToBind=0x0ecb +OP_KeyRing=0x6857 +OP_WhoAllRequest=0x65ab +OP_WhoAllResponse=0x407a +OP_FriendsWho=0x3956 +OP_ConfirmDelete=0x43a3 +OP_Logout=0x4ac6 +OP_Rewind=0x1745 +OP_TargetCommand=0x58e2 +OP_Hide=0x5d55 +OP_Jump=0x2060 +OP_Camp=0x28ec +OP_Emote=0x373b +OP_SetRunMode=0x009f +OP_BankerChange=0x383c +OP_TargetMouse=0x075d +OP_MobHealth=0x2dd3 +OP_InitialMobHealth=0x0000 # Unused? +OP_TargetHoTT=0x486c +OP_XTargetResponse=0x4d59 +OP_XTargetRequest=0x3763 +OP_XTargetAutoAddHaters=0x672f +OP_TargetBuffs=0x4f4b +OP_BuffCreate=0x3377 +OP_BuffRemoveRequest=0x49bc +OP_DeleteSpawn=0x7280 +OP_AutoAttack=0x109d +OP_AutoAttack2=0x3526 +OP_Consume=0x4b70 +OP_MoveItem=0x32ee +OP_DeleteItem=0x18ad +OP_DeleteCharge=0x01b8 +OP_ItemPacket=0x368e +OP_ItemLinkResponse=0x70c0 +OP_ItemLinkClick=0x4cef +OP_ItemPreview=0x7f80 +OP_NewSpawn=0x0b04 +OP_Track=0x17e5 +OP_TrackTarget=0x0029 +OP_TrackUnknown=0x0f83 +OP_ClickDoor=0x3a8f +OP_MoveDoor=0x08e8 +OP_RemoveAllDoors=0x700c +OP_EnvDamage=0x51fd +OP_BoardBoat=0x31e6 +OP_Forage=0x5306 +OP_LeaveBoat=0x4211 +OP_ControlBoat=0x0ae7 +OP_SafeFallSuccess=0x6dbc +OP_RezzComplete=0x760d +OP_RezzRequest=0x3c21 +OP_RezzAnswer=0x701c +OP_Shielding=0x48c1 +OP_RequestDuel=0x3af1 +OP_MobRename=0x2c57 +OP_AugmentItem=0x661b # Was 0x37cb +OP_WeaponEquip1=0x34a7 +OP_WeaponEquip2=0x559a # Was 0x6022 +OP_WeaponUnequip2=0x2d25 # Was 0x0110 +OP_ApplyPoison=0x1b0c +OP_Save=0x4a39 +OP_TestBuff=0x7cb8 # Was 0x3772 +OP_CustomTitles=0x100e +OP_Split=0x0522 +OP_YellForHelp=0x4e56 +OP_LoadSpellSet=0x261d +OP_Bandolier=0x7677 +OP_PotionBelt=0x1a3e # Was 0x4d3b +OP_DuelResponse=0x6a46 +OP_DuelResponse2=0x68d3 +OP_SaveOnZoneReq=0x2c7a +OP_ReadBook=0x72df +OP_Dye=0x23b9 +OP_InterruptCast=0x048c +OP_AAAction=0x424e +OP_LeadershipExpToggle=0x74bd +OP_LeadershipExpUpdate=0x4ee2 +OP_PurchaseLeadershipAA=0x6c55 +OP_UpdateLeadershipAA=0x0026 +OP_MarkNPC=0x5a58 +OP_MarkRaidNPC=0x0000 #unimplemented +OP_ClearNPCMarks=0x0272 +OP_ClearRaidNPCMarks=0x0000 #unimplemented +OP_DelegateAbility=0x4c9d +OP_SetGroupTarget=0x026 +OP_Charm=0x5d92 +OP_Stun=0x36a4 +OP_SendFindableNPCs=0x587e +OP_FindPersonRequest=0x5cea +OP_FindPersonReply=0x7e58 +OP_Sound=0x1a30 +OP_PetBuffWindow=0x5882 +OP_LevelAppearance=0x3bc9 +OP_Translocate=0x6580 +OP_Sacrifice=0x1821 +OP_PopupResponse=0x214a +OP_OnLevelMessage=0x4fd0 +OP_AugmentInfo=0x0afb +OP_Petition=0x4101 +OP_SomeItemPacketMaybe=0x747c +OP_PVPStats=0x6f4b # Unsure +OP_PVPLeaderBoardRequest=0x3707 +OP_PVPLeaderBoardReply=0x25b7 +OP_PVPLeaderBoardDetailsRequest=0x15a9 +OP_PVPLeaderBoardDetailsReply=0x04aa +OP_RestState=0x000f +OP_RespawnWindow=0x28bc +OP_LDoNButton=0x5327 +OP_SetStartCity=0x6326 # Was 0x2d1b +OP_VoiceMacroIn=0x17fd +OP_VoiceMacroOut=0x409a +OP_ItemViewUnknown=0x465b +OP_VetRewardsAvaliable=0x6773 +OP_VetClaimRequest=0x1126 +OP_VetClaimReply=0x16d4 +OP_DisciplineUpdate=0x759e # Was 0x2f05 +OP_DisciplineTimer=0x6989 # Was 0x5e3f +OP_BecomeCorpse=0x0000 # Unused? +OP_Action2=0x0000 # Unused? +OP_MobUpdate=0x2c84 +OP_NPCMoveUpdate=0x5892 +OP_CameraEffect=0x127f +OP_SpellEffect=0x5936 +OP_RemoveNimbusEffect=0xc693 +OP_AltCurrency=0x3ee6 +OP_AltCurrencyMerchantRequest=0x05f0 +OP_AltCurrencyMerchantReply=0x0165 +OP_AltCurrencyPurchase=0x6b6d +OP_AltCurrencySell=0x61cb +OP_AltCurrencySellSelection=0x74ec +OP_AltCurrencyReclaim=0x27a2 +OP_CrystalCountUpdate=0x467f # Was 0x3f60 +OP_CrystalCreate=0x7aee # Was 0x5a82 +OP_CrystalReclaim=0x2439 # Was 0x7616 +OP_Untargetable=0x1456 +OP_IncreaseStats=0x70a3 +OP_Weblink=0x18d3 +#OP_OpenInventory=0x0000 # Likely does not exist in RoF -U +OP_OpenContainer=0x0000 +OP_Marquee=0x0000 + +OP_DzQuit=0xb2e3 +OP_DzListTimers=0x7b68 +OP_DzAddPlayer=0x4701 +OP_DzRemovePlayer=0x1abc +OP_DzSwapPlayer=0x405b +OP_DzMakeLeader=0x543d +OP_DzPlayerList=0x14c6 +OP_DzJoinExpeditionConfirm=0x7f4b +OP_DzJoinExpeditionReply=0x1950 +OP_DzExpeditionInfo=0x9119 +OP_DzExpeditionList=0x205f +OP_DzMemberStatus=0x32f0 +OP_DzLeaderStatus=0x3de9 +OP_DzExpeditionEndsWarning=0x5189 +OP_DzMemberList=0x0000 +OP_DzCompass=0x3e0e # Was 0x4f09 +OP_DzChooseZone=0x0000 # Maybe 0x29d6 + +# New Opcodes +OP_SpawnPositionUpdate=0x0000 # Actually OP_MobUpdate ? +OP_ManaUpdate=0x3791 +OP_EnduranceUpdate=0x5f42 +OP_MobManaUpdate=0x2925 +OP_MobEnduranceUpdate=0x7314 + +# Mercenary Opcodes +OP_MercenaryDataUpdateRequest=0x2bcb +OP_MercenaryDataUpdate=0x7b89 +OP_MercenaryDataRequest=0x61a4 +OP_MercenaryDataResponse=0x11c1 +OP_MercenaryHire=0x72ce +OP_MercenaryDismiss=0x7169 +OP_MercenaryTimerRequest=0x6e83 +OP_MercenaryTimer=0x31e4 +OP_MercenaryUnknown1=0x20b9 +OP_MercenaryCommand=0x1b37 +OP_MercenarySuspendRequest=0x6e9f +OP_MercenarySuspendResponse=0x4407 +OP_MercenaryUnsuspendResponse=0x6f03 + +# Looting +OP_LootRequest=0x0adf +OP_EndLootRequest=0x30f7 +OP_LootItem=0x4dc9 +OP_LootComplete=0x55c4 + +# bazaar trader stuff: +OP_BazaarSearch=0x39d6 +OP_TraderDelItem=0x0000 +OP_BecomeTrader=0x61b3 +OP_TraderShop=0x5eca +OP_Trader=0x4ef5 # Was 0x6790 +OP_TraderBuy=0x0000 +OP_Barter=0x243a +OP_ShopItem=0x0000 +OP_BazaarInspect=0x0000 +OP_Bazaar=0x0000 +OP_TraderItemUpdate=0x0000 + +# pc/npc trading +OP_TradeRequest=0x77b5 +OP_TradeAcceptClick=0x69e2 +OP_TradeRequestAck=0x14bf +OP_TradeCoins=0x4206 +OP_FinishTrade=0x3993 +OP_CancelTrade=0x354c +OP_TradeMoneyUpdate=0x68c2 +OP_MoneyUpdate=0x640c +OP_TradeBusy=0x5505 + +# Sent after canceling trade or after closing tradeskill object +OP_FinishWindow=0x7349 +OP_FinishWindow2=0x40ef + +# Sent on Live for what seems to be item existance verification +# Ex. Before Right Click Effect happens from items +OP_ItemVerifyRequest=0x189c +OP_ItemVerifyReply=0x097b + +# merchant stuff +OP_ShopPlayerSell=0x3de3 +OP_ShopRequest=0x4fed +OP_ShopEnd=0x30a8 +OP_ShopEndConfirm=0x3196 +OP_ShopPlayerBuy=0x004c +OP_ShopDelItem=0x724f + +# tradeskill stuff: +OP_ClickObject=0x4aa1 +OP_ClickObjectAction=0x0c1e +OP_ClearObject=0x7a11 +OP_RecipeDetails=0x6e02 +OP_RecipesFavorite=0x5c74 +OP_RecipesSearch=0x6290 +OP_RecipeReply=0x1db6 +OP_RecipeAutoCombine=0x40d7 +OP_TradeSkillCombine=0x579a + +# Tribute Packets: +OP_OpenGuildTributeMaster=0x49ea +OP_OpenTributeMaster=0x7666 # Was 0x40f5 +OP_SelectTribute=0x79fc +OP_TributeItem=0x4f3e +OP_TributeMoney=0x58fb # Was 0x6fed +OP_TributeToggle=0x4e32 +OP_TributePointUpdate=0x5300 +OP_TributeNPC=0x0000 +OP_GuildTributeInfo=0x0000 +OP_OpenTributeReply=0x0000 +OP_GuildTributeStatus=0x0000 + +# Adventure packets: +OP_LeaveAdventure=0x5d18 +OP_AdventureFinish=0x400f +OP_AdventureInfoRequest=0x3cb0 +OP_AdventureInfo=0x4c54 +OP_AdventureRequest=0x2c6c +OP_AdventureDetails=0x5648 +OP_AdventureData=0x7171 +OP_AdventureUpdate=0x1b01 +OP_AdventureMerchantRequest=0x6922 # Was 654d +OP_AdventureMerchantResponse=0x3e47 # Was 7949 +OP_AdventureMerchantPurchase=0x5b72 # Was 155a +OP_AdventureMerchantSell=0x2f9b # Was 389c +OP_AdventurePointsUpdate=0x65c3 # Was 7589 +OP_AdventureStatsRequest=0x5a62 +OP_AdventureStatsReply=0x2370 +OP_AdventureLeaderboardRequest=0x7093 +OP_AdventureLeaderboardReply=0x7f79 + +# Group Opcodes +OP_GroupDisband=0x4c10 +OP_GroupInvite=0x1649 +OP_GroupFollow=0x05ce +OP_GroupUpdate=0x4ced +OP_GroupUpdateB=0x0cbc +OP_GroupCancelInvite=0x0000 +OP_GroupAcknowledge=0x04d0 +OP_GroupDelete=0x3abb +OP_CancelInvite=0x32c2 +OP_GroupFollow2=0x2a50 +OP_GroupInvite2=0x6c65 +OP_GroupDisbandYou=0x7323 +OP_GroupDisbandOther=0x88a1 +OP_GroupLeaderChange=0x74da +OP_GroupRoles=0x4d9f +OP_GroupMakeLeader=0x4229 +OP_DoGroupLeadershipAbility=0x6eae +OP_GroupLeadershipAAUpdate=0x6298 +OP_GroupMentor=0x3342 +OP_InspectBuffs=0x0000 + +# LFG/LFP Opcodes +OP_LFGCommand=0x6060 +OP_LFGGetMatchesRequest=0x0340 +OP_LFGGetMatchesResponse=0x5048 +OP_LFPGetMatchesRequest=0x4d7d +OP_LFPGetMatchesResponse=0x22c6 +OP_LFPCommand=0x49a9 +OP_LFGAppearance=0x0000 +OP_LFGResponse=0x0000 + +# Raid Opcodes +OP_RaidInvite=0x3973 +OP_RaidUpdate=0x56fe +OP_RaidJoin=0x0000 + +# Button-push commands +OP_Taunt=0x2703 +OP_CombatAbility=0x3eba +OP_SenseTraps=0x02af # Was 0x2ee0 +OP_PickPocket=0x39e8 +OP_DisarmTraps=0x0000 +OP_Disarm=0x5ec8 +OP_Sneak=0x4577 +OP_Fishing=0x1e2a +OP_InstillDoubt=0x640e +OP_FeignDeath=0x52fa +OP_Mend=0x0ecf +OP_Bind_Wound=0x0386 +OP_LDoNOpen=0x3d5c + +# Task packets +OP_TaskDescription=0x0083 +OP_TaskActivity=0x083 +OP_CompletedTasks=0x4eba +OP_TaskActivityComplete=0x7037 +OP_AcceptNewTask=0x0a23 +OP_CancelTask=0x3714 +OP_TaskMemberList=0x5727 # Was 0x1656 +OP_OpenNewTasksWindow=0x48a2 # Was 0x11de +OP_AvaliableTask=0x36e8 # Was 0x2377 +OP_TaskHistoryRequest=0x5f1c +OP_TaskHistoryReply=0x3d05 +OP_DeclineAllTasks=0x0000 + +# Title opcodes +OP_NewTitlesAvailable=0x0d32 +OP_RequestTitles=0x6344 +OP_SendTitleList=0x2d08 +OP_SetTitle=0x6527 +OP_SetTitleReply=0x4c21 + +# mail opcodes +OP_Command=0x0000 +OP_MailboxHeader=0x0000 +OP_MailHeader=0x0000 +OP_MailBody=0x0000 +OP_NewMail=0x0000 +OP_SentConfirm=0x0000 + +########### Below this point should not be needed ########### + +# This section are all unknown in Titanium +OP_ForceFindPerson=0x0000 +OP_LocInfo=0x0000 +OP_ReloadUI=0x0000 +OP_ItemName=0x0000 +OP_ItemLinkText=0x0000 +OP_MultiLineMsg=0x0000 +OP_MendHPUpdate=0x0000 +OP_TargetReject=0x0000 +OP_SafePoint=0x0000 +OP_ApproveZone=0x0000 +OP_ZoneComplete=0x0000 +OP_ClientError=0x0000 +OP_DumpName=0x0000 +OP_Heartbeat=0x0000 +OP_CrashDump=0x0000 +OP_LoginComplete=0x0000 + +# discovered opcodes not yet used: +OP_PickLockSuccess=0x0000 +OP_PlayMP3=0x0000 +OP_ReclaimCrystals=0x0000 +OP_DynamicWall=0x0000 +OP_OpenDiscordMerchant=0x0000 +OP_DiscordMerchantInventory=0x0000 +OP_GiveMoney=0x0000 +OP_RequestKnowledgeBase=0x0000 +OP_KnowledgeBase=0x0000 +OP_SlashAdventure=0x0000 # /adventure +OP_BecomePVPPrompt=0x0000 +OP_MoveLogRequest=0x0000 # gone I think +OP_MoveLogDisregard=0x0000 # gone I think + +# named unknowns, to make looking for real unknown easier +OP_AnnoyingZoneUnknown=0x0000 +OP_Some6ByteHPUpdate=0x0000 seems to happen when you target group members +OP_QueryResponseThing=0x0000 + + +# realityincarnate: these are just here to stop annoying several thousand byte packet dumps +#OP_LoginUnknown1=0x46d3 # OP_SendSpellChecksum +#OP_LoginUnknown2=0x040b # OP_SendSkillCapsChecksum + +# Petition Opcodes +OP_PetitionSearch=0x0000 search term for petition +OP_PetitionSearchResults=0x0000 (list of?) matches from search +OP_PetitionSearchText=0x0000 text results of search + +OP_PetitionUpdate=0x0000 +OP_PetitionCheckout=0x0000 +OP_PetitionCheckIn=0x0000 +OP_PetitionQue=0x0000 +OP_PetitionUnCheckout=0x0000 +OP_PetitionDelete=0x0000 +OP_DeletePetition=0x0000 +OP_PetitionResolve=0x0000 +OP_PDeletePetition=0x0000 +OP_PetitionBug=0x0000 +OP_PetitionRefresh=0x0000 +OP_PetitionCheckout2=0x0000 +OP_PetitionViewPetition=0x0000 + +# Login opcodes +OP_SessionReady=0x0000 +OP_Login=0x0000 +OP_ServerListRequest=0x0000 +OP_PlayEverquestRequest=0x0000 +OP_PlayEverquestResponse=0x0000 +OP_ChatMessage=0x0000 +OP_LoginAccepted=0x0000 +OP_ServerListResponse=0x0000 +OP_Poll=0x0000 +OP_EnterChat=0x0000 +OP_PollResponse=0x0000 + +# raw opcodes +OP_RAWSessionRequest=0x0000 +OP_RAWSessionResponse=0x0000 +OP_RAWCombined=0x0000 +OP_RAWSessionDisconnect=0x0000 +OP_RAWKeepAlive=0x0000 +OP_RAWSessionStatRequest=0x0000 +OP_RAWSessionStatResponse=0x0000 +OP_RAWPacket=0x0000 +OP_RAWFragment=0x0000 +OP_RAWOutOfOrderAck=0x0000 +OP_RAWAck=0x0000 +OP_RAWAppCombined=0x0000 +OP_RAWOutOfSession=0x0000 + +# we need to document the differences between these packets to make identifying them easier +OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs +OP_InitialHPUpdate=0x0000 + +OP_ItemRecastDelay=0x08a6