From 2497c719ee7472bfa86843844bedd5aaa474b3fa Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 26 Sep 2014 12:43:34 -0400 Subject: [PATCH 1/2] Rename Name variable in SendBazaarResults to temp_buffer fixes #253 --- zone/trading.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/zone/trading.cpp b/zone/trading.cpp index ec9e652cc..376d2cb14 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1861,7 +1861,7 @@ void Client::SendBazaarResults(uint32 TraderID, uint32 Class_, uint32 Race, uint int Action = BazaarSearchResults; uint32 Cost = 0; int32 SerialNumber = 0; - char Name[64] = {0}; + char temp_buffer[64] = {0}; int Count = 0; uint32 StatValue=0; @@ -1887,23 +1887,23 @@ void Client::SendBazaarResults(uint32 TraderID, uint32 Class_, uint32 Race, uint bool Stackable = atoi(row[10]); if(Stackable) { int Charges = atoi(row[9]); - sprintf(Name, "%s(%i)", row[7], Charges); + sprintf(temp_buffer, "%s(%i)", row[7], Charges); } else - sprintf(Name,"%s(%i)",row[7], Count); + sprintf(temp_buffer,"%s(%i)",row[7], Count); - memcpy(bufptr,&Name, strlen(Name)); + memcpy(bufptr,&temp_buffer, strlen(temp_buffer)); bufptr += 64; // Extra fields for SoD+ // if(Trader2) - sprintf(Name, "%s", Trader2->GetName()); + sprintf(temp_buffer, "%s", Trader2->GetName()); else - sprintf(Name, "Unknown"); + sprintf(temp_buffer, "Unknown"); - memcpy(bufptr,&Name, strlen(Name)); + memcpy(bufptr,&temp_buffer, strlen(temp_buffer)); bufptr += 64; From 837ce8ab4a3fffbc2cece765276930abe849861d Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 26 Sep 2014 20:51:42 -0400 Subject: [PATCH 2/2] Re-ordered client patch ENCODES and DECODES - snuck in a bitswap change for SoF+ item_struct::Slots translations --- common/patches/client62.cpp | 1951 +++---- common/patches/rof.cpp | 9677 +++++++++++++++++----------------- common/patches/sod.cpp | 6385 +++++++++++----------- common/patches/sof.cpp | 5586 ++++++++++---------- common/patches/titanium.cpp | 2799 +++++----- common/patches/underfoot.cpp | 7013 ++++++++++++------------ 6 files changed, 16915 insertions(+), 16496 deletions(-) diff --git a/common/patches/client62.cpp b/common/patches/client62.cpp index 494049876..65ebe3600 100644 --- a/common/patches/client62.cpp +++ b/common/patches/client62.cpp @@ -1,4 +1,3 @@ - #include "../debug.h" #include "client62.h" #include "../opcodemgr.h" @@ -13,1061 +12,1087 @@ #include "../clientversions.h" #include "client62_structs.h" -namespace Client62 { +namespace Client62 +{ + static const char *name = "6.2"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; -static const char *name = "6.2"; -static OpcodeManager *opcodes = nullptr; -static Strategy struct_strategy; + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); -char *SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + // server to client inventory location converters + static inline uint32 ServerToClient62Slot(uint32 ServerSlot); + static inline uint32 ServerToClient62CorpseSlot(uint32 ServerCorpse); -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; + // client to server inventory location converters + static inline uint32 Client62ToServerSlot(uint32 Client62Slot); + static inline uint32 Client62ToServerCorpseSlot(uint32 Client62Corpse); + + 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); } } - //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 "client62_ops.h" } -} + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } - -Strategy::Strategy() -: StructStrategy() -{ - //all opcodes default to passthrough. - #include "ss_register.h" - #include "client62_ops.h" -} - -std::string Strategy::Describe() const { - std::string r; - r += "Patch "; - r += name; - return(r); -} - -const EQClientVersion Strategy::ClientVersion() const -{ - return EQClient62; -} + const EQClientVersion Strategy::ClientVersion() const + { + return EQClient62; + } #include "ss_define.h" +// ENCODE methods + EAT_ENCODE(OP_GuildMemberLevelUpdate); // added ; -/* -// Converts Server Slot IDs to Client62 Slot IDs for use in Encodes -static inline uint32 ServerToClient62Slot(uint32 ServerSlot) { - uint32 Client62Slot; - // reserved -} -*/ -/* -// Converts Client62 Slot IDs to Server Slot IDs for use in Decodes -static inline uint32 Client62ToServerSlot(uint32 Client62Slot) { - uint32 ServerSlot; - // reserved -} -*/ -/* -// Converts Server Corpse Slot IDs to Client62 Corpse Slot IDs for use in Encodes -static inline uint32 ServerToClient62CorpseSlot(uint32 ServerCorpse) { - uint32 Client62Corpse; - // reserved -} -*/ -/* -// Converts Client62 Corpse Slot IDs to Server Corpse Slot IDs for use in Decodes -static inline uint32 Client62ToServerCorpseSlot(uint32 Client62Corpse) { - uint32 ServerCorpse; - // reserved -} -*/ - - -EAT_ENCODE(OP_ZoneServerReady) -EAT_ENCODE(OP_GuildMemberLevelUpdate) - -ENCODE(OP_SendCharInfo) { - ENCODE_LENGTH_EXACT(CharacterSelect_Struct); - SETUP_DIRECT_ENCODE(CharacterSelect_Struct, structs::CharacterSelect_Struct); - int r; - for(r = 0; r < 10; r++) { - OUT(zone[r]); - OUT(eyecolor1[r]); - OUT(eyecolor2[r]); - OUT(hairstyle[r]); - OUT(primary[r]); - OUT(race[r]); - OUT(class_[r]); - OUT_str(name[r]); - OUT(gender[r]); - OUT(level[r]); - OUT(secondary[r]); - OUT(face[r]); - OUT(beard[r]); - int k; - for(k = 0; k < 9; k++) { - OUT(equip[r][k]); - OUT(cs_colors[r][k].color); - } - OUT(haircolor[r]); - OUT(gohome[r]); - OUT(deity[r]); - OUT(beardcolor[r]); - } - 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 2 is for 6.2 - if (emu->clientver <= 2 ) + EAT_ENCODE(OP_ZoneServerReady); // added ; + + ENCODE(OP_Action) { - OUT(id); - OUT(hotkey_sid); - OUT(hotkey_sid2); - OUT(title_sid); - OUT(desc_sid); - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); + + OUT(target); + OUT(source); + OUT(level); + OUT(instrument_mod); + OUT(sequence); OUT(type); - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - OUT(unknown80[0]); - OUT(unknown80[1]); - 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); - } + //OUT(damage); + OUT(spell); + OUT(buff_unknown); // if this is 4, a buff icon is made + + FINISH_ENCODE(); } - 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_DeleteSpawn) { - SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); - OUT(spawn_id); - FINISH_ENCODE(); -} - -ENCODE(OP_PlayerProfile) { - SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); - - uint32 r; - - memset(eq->unknown3224, 0xff, 448); - memset(eq->unknown3704, 0xff, 32); - -// OUT(checksum); - OUT(gender); - OUT(race); - OUT(class_); - OUT(level); - eq->level2 = emu->level; - - eq->bind_zone_id = emu->binds[0].zoneId; - eq->bind_x[0] = emu->binds[0].x; - eq->bind_y[0] = emu->binds[0].y; - eq->bind_z[0] = emu->binds[0].z; - eq->bind_heading[0] = emu->binds[0].heading; - //just making this up base on organization of struct: - eq->zone_safe_x = emu->binds[4].x; - eq->zone_safe_y = emu->binds[4].y; - eq->zone_safe_z = emu->binds[4].z; - eq->zone_safe_heading = emu->binds[4].heading; - - - OUT(deity); - OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); - OUT(abilitySlotRefresh); -// OUT(unknown0166[4]); - OUT(haircolor); - OUT(beardcolor); - OUT(eyecolor1); - OUT(eyecolor2); - OUT(hairstyle); - OUT(beard); - for(r = 0; r < 9; r++) { - OUT(item_material[r]); - OUT(item_tint[r].color); - } - for(r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { - OUT(aa_array[r].AA); - OUT(aa_array[r].value); - } - OUT(points); - OUT(mana); - OUT(cur_hp); - OUT(STR); - OUT(STA); - OUT(CHA); - OUT(DEX); - OUT(INT); - OUT(AGI); - OUT(WIS); - OUT(face); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); - OUT(platinum); - OUT(gold); - OUT(silver); - OUT(copper); - OUT(platinum_cursor); - OUT(gold_cursor); - OUT(silver_cursor); - OUT(copper_cursor); - - OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) - - OUT(toxicity); - OUT(thirst_level); - OUT(hunger_level); - for(r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); - OUT(buffs[r].level); - OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); - OUT(buffs[r].spellid); - OUT(buffs[r].duration); - OUT(buffs[r].counters); -// OUT(buffs[r].player_id); - } - for(r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { - OUT(disciplines.values[r]); - } -// OUT_array(recastTimers, structs::MAX_RECAST_TYPES); - OUT(endurance); - OUT(aapoints_spent); - OUT(aapoints); - for(r = 0; r < structs::MAX_PLAYER_BANDOLIER; r++) { - OUT_str(bandoliers[r].name); - uint32 k; - for(k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { - OUT(bandoliers[r].items[k].item_id); - OUT(bandoliers[r].items[k].icon); - OUT_str(bandoliers[r].items[k].item_name); - } - } - for(r = 0; r < structs::MAX_PLAYER_BANDOLIER_ITEMS; r++) { - OUT(potionbelt.items[r].item_id); - OUT(potionbelt.items[r].icon); - OUT_str(potionbelt.items[r].item_name); - } -// OUT(available_slots); - OUT_str(name); - OUT_str(last_name); - OUT(guild_id); - OUT(birthday); - OUT(lastlogin); - OUT(timePlayedMin); - OUT(pvp); - OUT(anon); - OUT(gm); - OUT(guildrank); - OUT(exp); - OUT_array(languages, structs::MAX_PP_LANGUAGE); - OUT(x); - OUT(y); - OUT(z); - OUT(heading); - OUT(platinum_bank); - OUT(gold_bank); - OUT(silver_bank); - OUT(copper_bank); - OUT(platinum_shared); - OUT(expansions); - OUT(autosplit); - OUT(zone_id); - OUT(zoneInstance); - for(r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { - OUT_str(groupMembers[r]); - } -// OUT_str(groupLeader); //this is prolly right after groupMembers, but I dont feel like checking. -// OUT(leadAAActive); - OUT(ldon_points_guk); - OUT(ldon_points_mir); - OUT(ldon_points_mmc); - OUT(ldon_points_ruj); - OUT(ldon_points_tak); - OUT(ldon_points_available); - OUT(tribute_time_remaining); - OUT(career_tribute_points); - OUT(tribute_points); - OUT(tribute_active); - for(r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { - OUT(tributes[r].tribute); - OUT(tributes[r].tier); - } - OUT(group_leadership_exp); - OUT(raid_leadership_exp); - OUT(group_leadership_points); - OUT(raid_leadership_points); - OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); - OUT(air_remaining); - OUT(entityid); - OUT(leadAAActive); - OUT(expAA); - OUT(currentRadCrystals); - OUT(careerRadCrystals); - OUT(currentEbonCrystals); - OUT(careerEbonCrystals); - OUT(groupAutoconsent); - OUT(raidAutoconsent); - OUT(guildAutoconsent); -// OUT(showhelm); - - //set the checksum... - CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct)-4); - - FINISH_ENCODE(); -} - -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) + ENCODE(OP_BazaarSearch) { - _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; + 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(NumItems); + OUT(SerialNumber); + OUT(SellerID); + OUT(Cost); + OUT(ItemStat); + memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); } - in->size = sizeof(structs::Track_Struct) * EntryCount; - in->pBuffer = new unsigned char[in->size]; - structs::Track_Struct *eq = (structs::Track_Struct *) in->pBuffer; - - for(int i = 0; i < EntryCount; ++i, ++eq, ++emu) + ENCODE(OP_BecomeTrader) { - OUT(entityid); - OUT(padding002); - OUT(distance); + ENCODE_LENGTH_EXACT(BecomeTrader_Struct); + SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct); + + OUT(ID); + OUT(Code); + + FINISH_ENCODE(); } - delete[] __emu_buffer; + ENCODE(OP_CharInventory) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; - dest->FastQueuePacket(&in, ack_req); -} + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; -ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); } -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; - } - - //make the EQ struct. - in->size = sizeof(structs::Spawn_Struct)*entrycount; - in->pBuffer = new unsigned char[in->size]; - structs::Spawn_Struct *eq = (structs::Spawn_Struct *) in->pBuffer; - - //zero out the packet. We could avoid this memset by setting all fields (including unknowns) - //in the loop. - memset(in->pBuffer, 0, in->size); - - //do the transform... - int r; - int k; - for(r = 0; r < entrycount; r++, eq++, emu++) { - eq->gm = emu->gm; - eq->aaitle = emu->aaitle; - eq->anon = emu->anon; - eq->face = emu->face; - strcpy(eq->name, emu->name); - eq->deity = emu->deity; - eq->size = emu->size; - eq->NPC = emu->NPC; - eq->invis = emu->invis; - eq->haircolor = emu->haircolor; - eq->curHp = emu->curHp; - eq->max_hp = emu->max_hp; - eq->findable = emu->findable; - eq->deltaHeading = emu->deltaHeading; - eq->x = emu->x; - eq->y = emu->y; - eq->animation = emu->animation; - eq->z = emu->z; - eq->deltaY = emu->deltaY; - eq->deltaX = emu->deltaX; - eq->heading = emu->heading; - eq->deltaZ = emu->deltaZ; - eq->eyecolor1 = emu->eyecolor1; -// eq->showhelm = emu->showhelm; - eq->is_npc = emu->is_npc; - eq->hairstyle = emu->hairstyle; - eq->beard = emu->beard; - eq->level = emu->level; - eq->beardcolor = emu->beardcolor; - strcpy(eq->suffix, emu->suffix); - eq->petOwnerId = emu->petOwnerId; - eq->guildrank = emu->guildrank; - for(k = 0; k < 9; k++) { - eq->equipment[k] = emu->equipment[k]; - eq->colors[k].color = emu->colors[k].color; + 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; } - for(k = 0; k < 8; k++) { - eq->set_to_0xFF[k] = 0xFF; - } - eq->runspeed = emu->runspeed; - eq->afk = emu->afk; - eq->guildID = emu->guildID; - strcpy(eq->title, emu->title); - eq->helm = emu->helm; - eq->race = emu->race; - strcpy(eq->lastName, emu->lastName); - eq->walkspeed = emu->walkspeed; - eq->is_pet = emu->is_pet; - eq->light = emu->light; - eq->class_ = emu->class_; - eq->eyecolor2 = emu->eyecolor2; - eq->gender = emu->gender; - eq->bodytype = emu->bodytype; - eq->equip_chest2 = emu->equip_chest2; - eq->spawnId = emu->spawnId; - eq->lfg = emu->lfg; - eq->flymode = emu->flymode; - } + InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; - //kill off the emu structure and send the eq packet. - delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); -} + //do the transform... + int r; + std::string serial_string; + for (r = 0; r < itemcount; r++, eq++) { + uint32 length; + char *serialized = SerializeItem((ItemInst*)eq->inst, eq->slot_id, &length, 0); + if (serialized) { + serial_string.append(serialized, length + 1); + safe_delete_array(serialized); + } + else { + _log(NET__STRUCTS, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + } -ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } -ENCODE(OP_ItemPacket) { - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; - - //store away the emu struct - 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((const 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+5; // ItemPacketType + Serialization + \0 - 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+1); - - delete[] __emu_buffer; - safe_delete_array(serialized); - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_CharInventory) { - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; - - //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; - - //do the transform... - int r; - std::string serial_string; - for(r = 0; r < itemcount; r++, eq++) { - uint32 length; - char *serialized=SerializeItem((ItemInst*)eq->inst,eq->slot_id,&length,0); - if (serialized) { - serial_string.append(serialized,length+1); - safe_delete_array(serialized); - } else { - _log(NET__STRUCTS, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.",eq->slot_id); } + in->size = serial_string.length(); + in->pBuffer = new unsigned char[in->size]; + memcpy(in->pBuffer, serial_string.c_str(), serial_string.length()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); } - in->size = serial_string.length(); - in->pBuffer = new unsigned char[in->size]; - memcpy(in->pBuffer,serial_string.c_str(),serial_string.length()); + ENCODE(OP_DeleteSpawn) + { + SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); - delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); -} + OUT(spawn_id); -ENCODE(OP_GuildMemberList) { - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; + FINISH_ENCODE(); + } - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - Internal_GuildMembers_Struct *emu = (Internal_GuildMembers_Struct *) in->pBuffer; + 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. - //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; - 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++; - //easier way to setup GuildMembers_Struct - //set prefix name - strcpy((char *)buffer, emu->player_name); - buffer += pnl; - *buffer = '\0'; - buffer++; + //add member count. + *((uint32 *)buffer) = htonl(emu->count); + 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 + 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 + + 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; + structs::GuildMemberEntry_Struct *e = (structs::GuildMemberEntry_Struct *) buffer; - uint32 r; - for(r = 0; r < emu->count; r++, emu_e++) { + uint32 r; + for (r = 0; r < emu->count; r++, emu_e++) { - //the order we set things here must match the struct + //the order we set things here must match the struct - //nice helper macro - /*#define SlideStructString(field, str) \ - strcpy(e->field, str.c_str()); \ - e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ + //nice helper macro + /*#define SlideStructString(field, str) \ + strcpy(e->field, str.c_str()); \ + e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ #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) + { \ + 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_); - PutFieldN(rank); - PutFieldN(time_last_on); - PutFieldN(tribute_enable); - PutFieldN(total_tribute); - PutFieldN(last_tribute); - SlideStructString( public_note, emu_note ); - e->zoneinstance = 0; - e->zone_id = htons(emu_e->zone_id); + SlideStructString(name, emu_name); + PutFieldN(level); + PutFieldN(banker); + PutFieldN(class_); + PutFieldN(rank); + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + PutFieldN(total_tribute); + PutFieldN(last_tribute); + SlideStructString(public_note, emu_note); + e->zoneinstance = 0; + e->zone_id = htons(emu_e->zone_id); #undef SlideStructString #undef PutFieldN - e++; + e++; + } } - } - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_ReadBook) { - - EQApplicationPacket *in = *p; - *p = nullptr; - - unsigned char *__emu_buffer = in->pBuffer; - - BookText_Struct *emu_BookText_Struct = (BookText_Struct *)__emu_buffer; - - in->size = sizeof(structs::BookText_Struct) + strlen(emu_BookText_Struct->booktext); - - in->pBuffer = new unsigned char[in->size]; - - structs::BookText_Struct *eq_BookText_Struct = (structs::BookText_Struct*)in->pBuffer; - - eq_BookText_Struct->window = emu_BookText_Struct->window; - eq_BookText_Struct->type = emu_BookText_Struct->type; - strcpy(eq_BookText_Struct->booktext, emu_BookText_Struct->booktext); - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); - -} - -ENCODE(OP_Illusion) { - ENCODE_LENGTH_EXACT(Illusion_Struct); - SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct); - OUT(spawnid); - OUT_str(charname); - if(emu->race > 473){ - eq->race = 1; - } - else { - OUT(race); - } - OUT(gender); - OUT(texture); - OUT(helmtexture); - OUT(face); - OUT(hairstyle); - OUT(haircolor); - OUT(beard); - OUT(beardcolor); - OUT(size); - - FINISH_ENCODE(); -} - -ENCODE(OP_BazaarSearch) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - char *Buffer = (char *)in->pBuffer; - - uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); - - if(SubAction != BazaarSearchResults) - { + delete[] __emu_buffer; 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) + ENCODE(OP_Illusion) { - _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; + ENCODE_LENGTH_EXACT(Illusion_Struct); + SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct); + + OUT(spawnid); + OUT_str(charname); + + if (emu->race > 473) + eq->race = 1; + else + OUT(race); + + OUT(gender); + OUT(texture); + OUT(helmtexture); + OUT(face); + OUT(hairstyle); + OUT(haircolor); + OUT(beard); + OUT(beardcolor); + OUT(size); + + FINISH_ENCODE(); } - in->size = EntryCount * sizeof(structs::BazaarSearchResults_Struct); - in->pBuffer = new unsigned char[in->size]; + ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } - memset(in->pBuffer, 0, in->size); - - structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *)in->pBuffer; - - for(int i = 0; i < EntryCount; ++i, ++emu, ++eq) + ENCODE(OP_ItemPacket) { - OUT(Beginning.Action); - OUT(NumItems); - OUT(SerialNumber); - OUT(SellerID); - OUT(Cost); - OUT(ItemStat); - memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + 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((const 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 + 5; // ItemPacketType + Serialization + \0 + 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 + 1); + + delete[] __emu_buffer; + safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); } - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_RespondAA) { - ENCODE_LENGTH_EXACT(AATable_Struct); - SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); - - unsigned int r; - for(r = 0; r < MAX_PP_AA_ARRAY; r++) { - OUT(aa_list[r].aa_skill); - OUT(aa_list[r].aa_value); - } - - FINISH_ENCODE(); -} - -ENCODE(OP_WearChange) { - ENCODE_LENGTH_EXACT(WearChange_Struct); - SETUP_DIRECT_ENCODE(WearChange_Struct, structs::WearChange_Struct); - OUT(spawn_id); - OUT(material); - OUT(color.color); - OUT(wear_slot_id); - FINISH_ENCODE(); -} - -ENCODE(OP_Action) { - ENCODE_LENGTH_EXACT(Action_Struct); - SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); - OUT(target); - OUT(source); - OUT(level); - OUT(instrument_mod); - OUT(sequence); - OUT(type); - //OUT(damage); - OUT(spell); - OUT(buff_unknown); // if this is 4, a buff icon is made - FINISH_ENCODE(); -} - -ENCODE(OP_BecomeTrader) -{ - ENCODE_LENGTH_EXACT(BecomeTrader_Struct); - SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct); - OUT(ID); - OUT(Code); - FINISH_ENCODE(); -} - -ENCODE(OP_PetBuffWindow) -{ - ENCODE_LENGTH_EXACT(PetBuff_Struct); - SETUP_DIRECT_ENCODE(PetBuff_Struct, PetBuff_Struct); - - OUT(petid); - OUT(buffcount); - - int EQBuffSlot = 0; - - for(uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) + ENCODE(OP_LeadershipExpUpdate) { - if(emu->spellid[EmuBuffSlot]) + 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_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + OUT_str(Title); + OUT_str(Text); + OUT(Buttons); + OUT(Duration); + OUT(PopupID); + + eq->unknown4236 = 0x00000000; + eq->unknown4240 = 0xffffffff; + + FINISH_ENCODE(); + } + + ENCODE(OP_PetBuffWindow) + { + ENCODE_LENGTH_EXACT(PetBuff_Struct); + SETUP_DIRECT_ENCODE(PetBuff_Struct, PetBuff_Struct); + + OUT(petid); + OUT(buffcount); + + int EQBuffSlot = 0; + + for (uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) { - eq->spellid[EQBuffSlot] = emu->spellid[EmuBuffSlot]; - eq->ticsremaining[EQBuffSlot++] = emu->ticsremaining[EmuBuffSlot]; + if (emu->spellid[EmuBuffSlot]) + { + eq->spellid[EQBuffSlot] = emu->spellid[EmuBuffSlot]; + eq->ticsremaining[EQBuffSlot++] = emu->ticsremaining[EmuBuffSlot]; + } } + + FINISH_ENCODE(); } - FINISH_ENCODE(); -} + ENCODE(OP_PlayerProfile) + { + SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); -ENCODE(OP_OnLevelMessage) -{ - ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); - SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); - OUT_str(Title); - OUT_str(Text); - OUT(Buttons); - OUT(Duration); - OUT(PopupID); + uint32 r; - eq->unknown4236 = 0x00000000; - eq->unknown4240 = 0xffffffff; + memset(eq->unknown3224, 0xff, 448); + memset(eq->unknown3704, 0xff, 32); - FINISH_ENCODE(); -} + // OUT(checksum); + OUT(gender); + OUT(race); + OUT(class_); + OUT(level); + eq->level2 = emu->level; -DECODE(OP_WearChange) { - DECODE_LENGTH_EXACT(structs::WearChange_Struct); - SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); - IN(spawn_id); - IN(material); - IN(color.color); - IN(wear_slot_id); - FINISH_DIRECT_DECODE(); -} + eq->bind_zone_id = emu->binds[0].zoneId; + eq->bind_x[0] = emu->binds[0].x; + eq->bind_y[0] = emu->binds[0].y; + eq->bind_z[0] = emu->binds[0].z; + eq->bind_heading[0] = emu->binds[0].heading; + //just making this up base on organization of struct: + eq->zone_safe_x = emu->binds[4].x; + eq->zone_safe_y = emu->binds[4].y; + eq->zone_safe_z = emu->binds[4].z; + eq->zone_safe_heading = emu->binds[4].heading; -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]); - } - IN(link_hash); - - 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 < 25; r++) { - IN(filters[r]); - } - emu->filters[25] = 1; - emu->filters[26] = 1; - emu->filters[27] = 1; - emu->filters[28] = 1; - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_CharacterCreate) { - DECODE_LENGTH_EXACT(structs::CharCreate_Struct); - SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - IN(class_); - IN(beardcolor); - IN(beard); - IN(haircolor); - IN(gender); - IN(race); - IN(start_zone); - IN(hairstyle); - IN(deity); - IN(STR); - IN(STA); - IN(AGI); - IN(DEX); - IN(WIS); - IN(INT); - IN(CHA); - IN(face); - IN(eyecolor1); - IN(eyecolor2); - 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); - emu->type = 3; - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ReadBook) { - DECODE_LENGTH_ATLEAST(structs::BookRequest_Struct); - SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); - - IN(window); - IN(type); - strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); - - 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); - - FINISH_DIRECT_DECODE(); -} - -char *SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth) { - char *serialization = nullptr; - char *instance = nullptr; - const char *protection=(const char *)"\\\\\\\\\\"; - char *sub_items[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; - bool stackable=inst->IsStackable(); - uint32 merchant_slot=inst->GetMerchantSlot(); - int16 charges=inst->GetCharges(); - const Item_Struct *item=inst->GetItem(); - int i; - uint32 sub_length; - - MakeAnyLenString(&instance, - "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", - stackable ? charges : 1, - 0, - (merchant_slot==0) ? slot_id : merchant_slot, - inst->GetPrice(), - (merchant_slot==0) ? 1 : inst->GetMerchantCount(), - 0, - //merchant_slot, //instance ID, bullshit for now - // The 'Merchant Slot' needs to be some unique id for bazaar to work properly - (merchant_slot==0) ? inst->GetSerialNumber() : merchant_slot, - inst->IsInstNoDrop() ? 1 : 0, //not sure where this field is - (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? charges : 0) : charges), - 0 - ); - - for(i=0;i<10;i++) { - ItemInst *sub=inst->GetItem(i); - if (sub) { - sub_items[i]=SerializeItem(sub,0,&sub_length,depth+1); + OUT(deity); + OUT(intoxication); + OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT(abilitySlotRefresh); + // OUT(unknown0166[4]); + OUT(haircolor); + OUT(beardcolor); + OUT(eyecolor1); + OUT(eyecolor2); + OUT(hairstyle); + OUT(beard); + for (r = 0; r < 9; r++) { + OUT(item_material[r]); + OUT(item_tint[r].color); } + for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { + OUT(aa_array[r].AA); + OUT(aa_array[r].value); + } + OUT(points); + OUT(mana); + OUT(cur_hp); + OUT(STR); + OUT(STA); + OUT(CHA); + OUT(DEX); + OUT(INT); + OUT(AGI); + OUT(WIS); + OUT(face); + OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + OUT(platinum); + OUT(gold); + OUT(silver); + OUT(copper); + OUT(platinum_cursor); + OUT(gold_cursor); + OUT(silver_cursor); + OUT(copper_cursor); + + OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) + + OUT(toxicity); + OUT(thirst_level); + OUT(hunger_level); + for (r = 0; r < structs::BUFF_COUNT; r++) { + OUT(buffs[r].slotid); + OUT(buffs[r].level); + OUT(buffs[r].bard_modifier); + OUT(buffs[r].effect); + OUT(buffs[r].spellid); + OUT(buffs[r].duration); + OUT(buffs[r].counters); + // OUT(buffs[r].player_id); + } + for (r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { + OUT(disciplines.values[r]); + } + // OUT_array(recastTimers, structs::MAX_RECAST_TYPES); + OUT(endurance); + OUT(aapoints_spent); + OUT(aapoints); + for (r = 0; r < structs::MAX_PLAYER_BANDOLIER; r++) { + OUT_str(bandoliers[r].name); + uint32 k; + for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { + OUT(bandoliers[r].items[k].item_id); + OUT(bandoliers[r].items[k].icon); + OUT_str(bandoliers[r].items[k].item_name); + } + } + for (r = 0; r < structs::MAX_PLAYER_BANDOLIER_ITEMS; r++) { + OUT(potionbelt.items[r].item_id); + OUT(potionbelt.items[r].icon); + OUT_str(potionbelt.items[r].item_name); + } + // OUT(available_slots); + OUT_str(name); + OUT_str(last_name); + OUT(guild_id); + OUT(birthday); + OUT(lastlogin); + OUT(timePlayedMin); + OUT(pvp); + OUT(anon); + OUT(gm); + OUT(guildrank); + OUT(exp); + OUT_array(languages, structs::MAX_PP_LANGUAGE); + OUT(x); + OUT(y); + OUT(z); + OUT(heading); + OUT(platinum_bank); + OUT(gold_bank); + OUT(silver_bank); + OUT(copper_bank); + OUT(platinum_shared); + OUT(expansions); + OUT(autosplit); + OUT(zone_id); + OUT(zoneInstance); + for (r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { + OUT_str(groupMembers[r]); + } + // OUT_str(groupLeader); //this is prolly right after groupMembers, but I dont feel like checking. + // OUT(leadAAActive); + OUT(ldon_points_guk); + OUT(ldon_points_mir); + OUT(ldon_points_mmc); + OUT(ldon_points_ruj); + OUT(ldon_points_tak); + OUT(ldon_points_available); + OUT(tribute_time_remaining); + OUT(career_tribute_points); + OUT(tribute_points); + OUT(tribute_active); + for (r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { + OUT(tributes[r].tribute); + OUT(tributes[r].tier); + } + OUT(group_leadership_exp); + OUT(raid_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_points); + OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); + OUT(air_remaining); + OUT(entityid); + OUT(leadAAActive); + OUT(expAA); + OUT(currentRadCrystals); + OUT(careerRadCrystals); + OUT(currentEbonCrystals); + OUT(careerEbonCrystals); + OUT(groupAutoconsent); + OUT(raidAutoconsent); + OUT(guildAutoconsent); + // OUT(showhelm); + + //set the checksum... + CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); + + FINISH_ENCODE(); } + ENCODE(OP_ReadBook) + { + EQApplicationPacket *in = *p; + *p = nullptr; - *length=MakeAnyLenString(&serialization, - "%.*s%s" // For leading quotes (and protection) if a subitem; - "%s" // Instance data - "%.*s\"" // Quotes (and protection, if needed) around static data - "%i" // item->ItemClass so we can do |%s instead of %s| + unsigned char *__emu_buffer = in->pBuffer; + + BookText_Struct *emu_BookText_Struct = (BookText_Struct *)__emu_buffer; + + in->size = sizeof(structs::BookText_Struct) + strlen(emu_BookText_Struct->booktext); + + in->pBuffer = new unsigned char[in->size]; + + structs::BookText_Struct *eq_BookText_Struct = (structs::BookText_Struct*)in->pBuffer; + + eq_BookText_Struct->window = emu_BookText_Struct->window; + eq_BookText_Struct->type = emu_BookText_Struct->type; + strcpy(eq_BookText_Struct->booktext, emu_BookText_Struct->booktext); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_RespondAA) + { + ENCODE_LENGTH_EXACT(AATable_Struct); + SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); + + unsigned int r; + for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + OUT(aa_list[r].aa_skill); + OUT(aa_list[r].aa_value); + } + + 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 2 is for 6.2 + if (emu->clientver <= 2) + { + OUT(id); + OUT(hotkey_sid); + OUT(hotkey_sid2); + OUT(title_sid); + OUT(desc_sid); + OUT(class_type); + OUT(cost); + OUT(seq); + OUT(current_level); + OUT(prereq_skill); + OUT(prereq_minpoints); + OUT(type); + OUT(spellid); + OUT(spell_type); + OUT(spell_refresh); + OUT(classes); + OUT(berserker); + OUT(max_level); + OUT(last_id); + OUT(next_id); + OUT(cost2); + OUT(unknown80[0]); + OUT(unknown80[1]); + 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); + } + } + + FINISH_ENCODE(); + } + + ENCODE(OP_SendCharInfo) + { + ENCODE_LENGTH_EXACT(CharacterSelect_Struct); + SETUP_DIRECT_ENCODE(CharacterSelect_Struct, structs::CharacterSelect_Struct); + + int r; + for (r = 0; r < 10; r++) { + OUT(zone[r]); + OUT(eyecolor1[r]); + OUT(eyecolor2[r]); + OUT(hairstyle[r]); + OUT(primary[r]); + OUT(race[r]); + OUT(class_[r]); + OUT_str(name[r]); + OUT(gender[r]); + OUT(level[r]); + OUT(secondary[r]); + OUT(face[r]); + OUT(beard[r]); + int k; + for (k = 0; k < 9; k++) { + OUT(equip[r][k]); + OUT(cs_colors[r][k].color); + } + OUT(haircolor[r]); + OUT(gohome[r]); + OUT(deity[r]); + OUT(beardcolor[r]); + } + + FINISH_ENCODE(); + } + + 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; + } + + in->size = sizeof(structs::Track_Struct) * EntryCount; + in->pBuffer = new unsigned char[in->size]; + structs::Track_Struct *eq = (structs::Track_Struct *) in->pBuffer; + + for (int i = 0; i < EntryCount; ++i, ++eq, ++emu) + { + OUT(entityid); + OUT(padding002); + OUT(distance); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_WearChange) + { + ENCODE_LENGTH_EXACT(WearChange_Struct); + SETUP_DIRECT_ENCODE(WearChange_Struct, structs::WearChange_Struct); + + OUT(spawn_id); + OUT(material); + OUT(color.color); + OUT(wear_slot_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } + + 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; + } + + //make the EQ struct. + in->size = sizeof(structs::Spawn_Struct)*entrycount; + in->pBuffer = new unsigned char[in->size]; + structs::Spawn_Struct *eq = (structs::Spawn_Struct *) in->pBuffer; + + //zero out the packet. We could avoid this memset by setting all fields (including unknowns) + //in the loop. + memset(in->pBuffer, 0, in->size); + + //do the transform... + int r; + int k; + for (r = 0; r < entrycount; r++, eq++, emu++) { + eq->gm = emu->gm; + eq->aaitle = emu->aaitle; + eq->anon = emu->anon; + eq->face = emu->face; + strcpy(eq->name, emu->name); + eq->deity = emu->deity; + eq->size = emu->size; + eq->NPC = emu->NPC; + eq->invis = emu->invis; + eq->haircolor = emu->haircolor; + eq->curHp = emu->curHp; + eq->max_hp = emu->max_hp; + eq->findable = emu->findable; + eq->deltaHeading = emu->deltaHeading; + eq->x = emu->x; + eq->y = emu->y; + eq->animation = emu->animation; + eq->z = emu->z; + eq->deltaY = emu->deltaY; + eq->deltaX = emu->deltaX; + eq->heading = emu->heading; + eq->deltaZ = emu->deltaZ; + eq->eyecolor1 = emu->eyecolor1; + // eq->showhelm = emu->showhelm; + eq->is_npc = emu->is_npc; + eq->hairstyle = emu->hairstyle; + eq->beard = emu->beard; + eq->level = emu->level; + eq->beardcolor = emu->beardcolor; + strcpy(eq->suffix, emu->suffix); + eq->petOwnerId = emu->petOwnerId; + eq->guildrank = emu->guildrank; + for (k = 0; k < 9; k++) { + eq->equipment[k] = emu->equipment[k]; + eq->colors[k].color = emu->colors[k].color; + } + for (k = 0; k < 8; k++) { + eq->set_to_0xFF[k] = 0xFF; + } + eq->runspeed = emu->runspeed; + eq->afk = emu->afk; + eq->guildID = emu->guildID; + strcpy(eq->title, emu->title); + eq->helm = emu->helm; + eq->race = emu->race; + strcpy(eq->lastName, emu->lastName); + eq->walkspeed = emu->walkspeed; + eq->is_pet = emu->is_pet; + eq->light = emu->light; + eq->class_ = emu->class_; + eq->eyecolor2 = emu->eyecolor2; + eq->gender = emu->gender; + eq->bodytype = emu->bodytype; + eq->equip_chest2 = emu->equip_chest2; + eq->spawnId = emu->spawnId; + eq->lfg = emu->lfg; + eq->flymode = emu->flymode; + } + + //kill off the emu structure and send the eq packet. + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + +// DECODE methods + DECODE(OP_CharacterCreate) + { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(class_); + IN(beardcolor); + IN(beard); + IN(haircolor); + IN(gender); + IN(race); + IN(start_zone); + IN(hairstyle); + IN(deity); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + + 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); + + 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]); + } + IN(link_hash); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ReadBook) + { + DECODE_LENGTH_ATLEAST(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(window); + IN(type); + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + 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 < 25; r++) { + IN(filters[r]); + } + emu->filters[25] = 1; + emu->filters[26] = 1; + emu->filters[27] = 1; + emu->filters[28] = 1; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_WearChange) + { + DECODE_LENGTH_EXACT(structs::WearChange_Struct); + SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); + IN(spawn_id); + IN(material); + IN(color.color); + IN(wear_slot_id); + 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); + emu->type = 3; + + FINISH_DIRECT_DECODE(); + } + +// file scope helper methods + char *SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth) + { + char *serialization = nullptr; + char *instance = nullptr; + const char *protection = (const char *)"\\\\\\\\\\"; + char *sub_items[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + bool stackable = inst->IsStackable(); + uint32 merchant_slot = inst->GetMerchantSlot(); + int16 charges = inst->GetCharges(); + const Item_Struct *item = inst->GetItem(); + int i; + uint32 sub_length; + + MakeAnyLenString(&instance, + "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", + stackable ? charges : 1, + 0, + (merchant_slot == 0) ? slot_id : merchant_slot, + inst->GetPrice(), + (merchant_slot == 0) ? 1 : inst->GetMerchantCount(), + 0, + //merchant_slot, //instance ID, bullshit for now + // The 'Merchant Slot' needs to be some unique id for bazaar to work properly + (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot, + inst->IsInstNoDrop() ? 1 : 0, //not sure where this field is + (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? charges : 0) : charges), + 0 + ); + + for (i = 0; i<10; i++) { + ItemInst *sub = inst->GetItem(i); + if (sub) { + sub_items[i] = SerializeItem(sub, 0, &sub_length, depth + 1); + } + } + + + *length = MakeAnyLenString(&serialization, + "%.*s%s" // For leading quotes (and protection) if a subitem; + "%s" // Instance data + "%.*s\"" // Quotes (and protection, if needed) around static data + "%i" // item->ItemClass so we can do |%s instead of %s| #define I(field) "|%i" #define C(field) "|%s" #define S(field) "|%s" #define F(field) "|%f" #include "client62_itemfields.h" - "%.*s\"" // Quotes (and protection, if needed) around static data - "|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" // Sub items - "%.*s%s" // For trailing quotes (and protection) if a subitem; - ,depth ? depth-1 : 0,protection,(depth) ? "\"" : "" - ,instance - ,depth,protection - ,item->ItemClass + "%.*s\"" // Quotes (and protection, if needed) around static data + "|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" // Sub items + "%.*s%s" // For trailing quotes (and protection) if a subitem; + , depth ? depth - 1 : 0, protection, (depth) ? "\"" : "" + , instance + , depth, protection + , item->ItemClass #define I(field) ,item->field #define C(field) ,field #define S(field) ,item->field #define F(field) ,item->field #include "client62_itemfields.h" - ,depth,protection - ,sub_items[0] ? sub_items[0] : "" - ,sub_items[1] ? sub_items[1] : "" - ,sub_items[2] ? sub_items[2] : "" - ,sub_items[3] ? sub_items[3] : "" - ,sub_items[4] ? sub_items[4] : "" - ,sub_items[5] ? sub_items[5] : "" - ,sub_items[6] ? sub_items[6] : "" - ,sub_items[7] ? sub_items[7] : "" - ,sub_items[8] ? sub_items[8] : "" - ,sub_items[9] ? sub_items[9] : "" - ,(depth) ? depth-1 : 0,protection,(depth) ? "\"" : "" - ); + , depth, protection + , sub_items[0] ? sub_items[0] : "" + , sub_items[1] ? sub_items[1] : "" + , sub_items[2] ? sub_items[2] : "" + , sub_items[3] ? sub_items[3] : "" + , sub_items[4] ? sub_items[4] : "" + , sub_items[5] ? sub_items[5] : "" + , sub_items[6] ? sub_items[6] : "" + , sub_items[7] ? sub_items[7] : "" + , sub_items[8] ? sub_items[8] : "" + , sub_items[9] ? sub_items[9] : "" + , (depth) ? depth - 1 : 0, protection, (depth) ? "\"" : "" + ); - for(i=0;i<10;i++) { - if (sub_items[i]) - safe_delete_array(sub_items[i]); + for (i = 0; i < 10; i++) { + if (sub_items[i]) + safe_delete_array(sub_items[i]); + } + + safe_delete_array(instance); + + return serialization; } - safe_delete_array(instance); + static inline uint32 ServerToClient62Slot(uint32 ServerSlot) + { + //uint32 Client62Slot; + } + + static inline uint32 ServerToClient62CorpseSlot(uint32 ServerCorpse) + { + //uint32 Client62Corpse; + } - return serialization; + static inline uint32 Client62ToServerSlot(uint32 Client62Slot) + { + //uint32 ServerSlot; + } + + static inline uint32 Client62ToServerCorpseSlot(uint32 Client62Corpse) + { + //uint32 ServerCorpse; + } } - - -} //end namespace Client62 - - - - - - +// end namespace Client62 diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 9e81e8878..2643b909e 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -15,542 +15,1690 @@ #include #include -namespace RoF { +namespace RoF +{ + static const char *name = "RoF"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; -static const char *name = "RoF"; -static OpcodeManager *opcodes = nullptr; -static Strategy struct_strategy; + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); -char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + // server to client inventory location converters + static inline structs::ItemSlotStruct ServerToRoFSlot(uint32 ServerSlot); + static inline structs::MainInvItemSlotStruct ServerToRoFMainInvSlot(uint32 ServerSlot); + static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse); -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; + // client to server inventory location converters + static inline uint32 RoFToServerSlot(structs::ItemSlotStruct RoFSlot); + static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot); + static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse); + + 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); } } - //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); + } - -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 EQClientRoF; -} + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientRoF; + } #include "ss_define.h" +// ENCODE methods + ENCODE(OP_Action) + { + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::ActionAlt_Struct); -// Converts Server Slot IDs to RoF Slot IDs for use in Encodes -static inline structs::ItemSlotStruct ServerToRoFSlot(uint32 ServerSlot) { - structs::ItemSlotStruct RoFSlot; - RoFSlot.SlotType = INVALID_INDEX; - RoFSlot.Unknown02 = NOT_USED; - RoFSlot.MainSlot = INVALID_INDEX; - RoFSlot.SubSlot = INVALID_INDEX; - RoFSlot.AugSlot = INVALID_INDEX; - RoFSlot.Unknown01 = NOT_USED; + 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; - uint32 TempSlot = 0; - - if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // Main Inventory and Cursor - RoFSlot.SlotType = maps::MapPossessions; - RoFSlot.MainSlot = ServerSlot; - - if (ServerSlot == MainPowerSource) - RoFSlot.MainSlot = slots::MainPowerSource; - - else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory - RoFSlot.MainSlot += 3; - - else if (ServerSlot >= MainAmmo) // (> 20) - RoFSlot.MainSlot += 1; + FINISH_ENCODE(); } - /*else if (ServerSlot < 51) { // Cursor Buffer - RoFSlot.SlotType = maps::MapLimbo; - RoFSlot.MainSlot = ServerSlot - 31; + 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 = ServerToRoFMainInvSlot(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 = ServerToRoFSlot(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 = ServerToRoFMainInvSlot(emu->inventorySlot); + OUT(success); + + 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 RoF. We should really be encoding for the older clients, not RoF, 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); + 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(1); // 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 RoF 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(0); // Unknown + __packet->WriteString(""); + } + __packet->WriteUInt8(0); // 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 = ServerToRoFSlot(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 = ServerToRoFSlot(emu->from_slot); + eq->to_slot = ServerToRoFSlot(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(); }*/ - else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { // (> 250 && < 341) - RoFSlot.SlotType = maps::MapPossessions; - TempSlot = ServerSlot - 1; - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); - - if (RoFSlot.MainSlot >= slots::MainGeneral9) // (> 30) - RoFSlot.MainSlot = slots::MainCursor; - } - - else if (ServerSlot >= EmuConstants::TRIBUTE_BEGIN && ServerSlot <= EmuConstants::TRIBUTE_END) { // Tribute - RoFSlot.SlotType = maps::MapTribute; - RoFSlot.MainSlot = ServerSlot - EmuConstants::TRIBUTE_BEGIN; - } - - else if (ServerSlot >= EmuConstants::BANK_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) { - RoFSlot.SlotType = maps::MapBank; - TempSlot = ServerSlot - EmuConstants::BANK_BEGIN; - RoFSlot.MainSlot = TempSlot; - - if (TempSlot > 30) { // (> 30) - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); - } - } - - else if (ServerSlot >= EmuConstants::SHARED_BANK_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) { - RoFSlot.SlotType = maps::MapSharedBank; - TempSlot = ServerSlot - EmuConstants::SHARED_BANK_BEGIN; - RoFSlot.MainSlot = TempSlot; - - if (TempSlot > 30) { // (> 30) - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); - } - } - - else if (ServerSlot >= EmuConstants::TRADE_BEGIN && ServerSlot <= EmuConstants::TRADE_BAGS_END) { - RoFSlot.SlotType = maps::MapTrade; - TempSlot = ServerSlot - EmuConstants::TRADE_BEGIN; - RoFSlot.MainSlot = TempSlot; - - if (TempSlot > 30) { - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); - } - - /* - // OLD CODE: - if (TempSlot > 99) { - if (TempSlot > 100) - RoFSlot.MainSlot = int((TempSlot - 100) / 10); - - else - RoFSlot.MainSlot = 0; - - RoFSlot.SubSlot = TempSlot - (100 + RoFSlot.MainSlot); - } - */ - } - - else if (ServerSlot >= EmuConstants::WORLD_BEGIN && ServerSlot <= EmuConstants::WORLD_END) { - RoFSlot.SlotType = maps::MapWorld; - TempSlot = ServerSlot - EmuConstants::WORLD_BEGIN; - RoFSlot.MainSlot = TempSlot; - } - - _log(NET__ERROR, "Convert Server Slot %i to RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", ServerSlot, RoFSlot.SlotType, RoFSlot.Unknown02, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01); - - return RoFSlot; -} - -// Converts RoF Slot IDs to Server Slot IDs for use in Decodes -static inline uint32 RoFToServerSlot(structs::ItemSlotStruct RoFSlot) { - uint32 ServerSlot = INVALID_INDEX; - uint32 TempSlot = 0; - - if (RoFSlot.SlotType == maps::MapPossessions && RoFSlot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 51) - if (RoFSlot.MainSlot == slots::MainPowerSource) - TempSlot = MainPowerSource; - - else if (RoFSlot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory - TempSlot = RoFSlot.MainSlot - 3; - - /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF 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 RoF, 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 (RoFSlot.MainSlot >= slots::MainAmmo) // Ammo and Main Inventory - TempSlot = RoFSlot.MainSlot - 1; - - else // Worn Slots - TempSlot = RoFSlot.MainSlot; - - if (RoFSlot.SubSlot >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; - - ServerSlot = TempSlot; - } - - else if (RoFSlot.SlotType == maps::MapBank) { - TempSlot = EmuConstants::BANK_BEGIN; - - if (RoFSlot.SubSlot >= SUB_BEGIN) - TempSlot += ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; - - else - TempSlot += RoFSlot.MainSlot; - - ServerSlot = TempSlot; - } - - else if (RoFSlot.SlotType == maps::MapSharedBank) { - TempSlot = EmuConstants::SHARED_BANK_BEGIN; - - if (RoFSlot.SubSlot >= SUB_BEGIN) - TempSlot += ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; - - else - TempSlot += RoFSlot.MainSlot; - - ServerSlot = TempSlot; - } - - else if (RoFSlot.SlotType == maps::MapTrade) { - TempSlot = EmuConstants::TRADE_BEGIN; - - if (RoFSlot.SubSlot >= SUB_BEGIN) - TempSlot += ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; - // OLD CODE: - //TempSlot += 100 + (RoFSlot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; - - else - TempSlot += RoFSlot.MainSlot; - - ServerSlot = TempSlot; - } - - else if (RoFSlot.SlotType == maps::MapWorld) { - TempSlot = EmuConstants::WORLD_BEGIN; - - if (RoFSlot.MainSlot >= SUB_BEGIN) - TempSlot += RoFSlot.MainSlot; - - ServerSlot = TempSlot; - } - - /*else if (RoFSlot.SlotType == maps::MapLimbo) { // Cursor Buffer - TempSlot = 31; - - if (RoFSlot.MainSlot >= 0) - TempSlot += RoFSlot.MainSlot; - - ServerSlot = TempSlot; - }*/ - - _log(NET__ERROR, "Convert RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoFSlot.SlotType, RoFSlot.Unknown02, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01, ServerSlot); - - return ServerSlot; -} - -// Converts Server MainInv Slot IDs to RoF MainInv Slot IDs for use in Encodes -static inline structs::MainInvItemSlotStruct ServerToRoFMainInvSlot(uint32 ServerSlot) { - structs::MainInvItemSlotStruct RoFSlot; - RoFSlot.MainSlot = INVALID_INDEX; - RoFSlot.SubSlot = INVALID_INDEX; - RoFSlot.AugSlot = INVALID_INDEX; - RoFSlot.Unknown01 = NOT_USED; - - uint32 TempSlot = 0; - - if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // (< 52) - RoFSlot.MainSlot = ServerSlot; - - if (ServerSlot == MainPowerSource) - RoFSlot.MainSlot = slots::MainPowerSource; - - else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory - RoFSlot.MainSlot += 3; - - else if (ServerSlot >= MainAmmo) // Ammo and Personl Inventory - RoFSlot.MainSlot += 1; - - /*else if (ServerSlot >= MainCursor) { // Cursor - RoFSlot.MainSlot = slots::MainCursor; - - if (ServerSlot > 30) - RoFSlot.SubSlot = (ServerSlot + 3) - 33; - }*/ - } - - else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { - TempSlot = ServerSlot - 1; - RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; - RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); - } - - _log(NET__ERROR, "Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", ServerSlot, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01); - - return RoFSlot; -} - -// Converts RoF MainInv Slot IDs to Server MainInv Slot IDs for use in Decodes -static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot) { - uint32 ServerSlot = INVALID_INDEX; - uint32 TempSlot = 0; - - if (RoFSlot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 33) - if (RoFSlot.MainSlot == slots::MainPowerSource) - TempSlot = MainPowerSource; - - else if (RoFSlot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory - TempSlot = RoFSlot.MainSlot - 3; - - /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF inventory slots - // Need to figure out what to do when we get these - - // Same as above - }*/ - - else if (RoFSlot.MainSlot >= slots::MainAmmo) // Main Inventory and Ammo Slots - TempSlot = RoFSlot.MainSlot - 1; - - else - TempSlot = RoFSlot.MainSlot; - - if (RoFSlot.SubSlot >= SUB_BEGIN) // Bag Slots - TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; - - ServerSlot = TempSlot; - } - - _log(NET__ERROR, "Convert RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01, ServerSlot); - - return ServerSlot; -} - -/* -// Converts Server Corpse Slot IDs to RoF Corpse Slot IDs for use in Encodes -static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse) { - uint32 RoFCorpse; - // reserved -} -*/ -/* -// Converts RoF Corpse Slot IDs to Server Corpse Slot IDs for use in Decodes -static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse) { - uint32 ServerCorpse; - // reserved -} -*/ - - -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) + ENCODE(OP_InspectRequest) { - Text1Length = 0; - Text2Length = 0; - Text3Length = 0; + ENCODE_LENGTH_EXACT(Inspect_Struct); + SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - in->ReadUInt32(); // Activity type + OUT(TargetID); + OUT(PlayerID); - // 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)); + FINISH_ENCODE(); } - 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) + ENCODE(OP_InterruptCast) { - Text1Length = 0; - Text2Length = 0; - Text3Length = 0; + ENCODE_LENGTH_EXACT(InterruptCast_Struct); + SETUP_DIRECT_ENCODE(InterruptCast_Struct, structs::InterruptCast_Struct); - outapp->WriteUInt32(in->ReadUInt32()); // ActivityType + OUT(spawnid); + OUT(messageid); - // 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); + FINISH_ENCODE(); } - delete in; + ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } - dest->FastQueuePacket(&outapp, ack_req); -} + ENCODE(OP_ItemPacket) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; -ENCODE(OP_TaskDescription) -{ - 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); - 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()); + uint32 length; + char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0); - // Copy Title - while(uint8 c = in->ReadUInt8()) - outapp->WriteUInt8(c); - outapp->WriteUInt8(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); - outapp->WriteUInt32(in->ReadUInt32()); // Duration - outapp->WriteUInt32(in->ReadUInt32()); // Unknown - uint32 StartTime = in->ReadUInt32(); - outapp->WriteUInt32(time(nullptr) - StartTime); // RoF has elapsed time here rather than starttime + delete[] __emu_buffer; + safe_delete_array(serialized); + dest->FastQueuePacket(&in, ack_req); + } - // Copy the rest of the packet verbatim - uint32 BytesLeftToCopy = in->size - in->GetReadPosition(); - memcpy(outapp->pBuffer + outapp->GetWritePosition(), in->pBuffer + in->GetReadPosition(), BytesLeftToCopy); + ENCODE(OP_ItemVerifyReply) + { + ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); + SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - delete in; + eq->slot = ServerToRoFSlot(emu->slot); + OUT(spell); + OUT(target); - dest->FastQueuePacket(&outapp, ack_req); -} + FINISH_ENCODE(); + } -/* -ENCODE(OP_OpenNewTasksWindow) { + 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 = emu->slot_id + 1; + 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 = ServerToRoFSlot(emu->from_slot); + eq->to_slot = ServerToRoFSlot(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; @@ -593,1260 +1741,1855 @@ ENCODE(OP_OpenNewTasksWindow) { for(uint32 i=0; i<__emu_AvailableTaskHeader->TaskCount; i++) { - __emu_AvailableTaskData1 = (AvailableTaskData1_Struct*)__emu_Ptr; - __eq_AvailableTaskData1 = (structs::AvailableTaskData1_Struct*)__eq_ptr; + __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 RoF 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; + __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 RoF 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); + __emu_Ptr += sizeof(AvailableTaskData1_Struct); + __eq_ptr += sizeof(structs::AvailableTaskData1_Struct); - strcpy(__eq_ptr, __emu_Ptr); // Title + strcpy(__eq_ptr, __emu_Ptr); // Title - __emu_Ptr += strlen(__emu_Ptr) + 1; - __eq_ptr += strlen(__eq_ptr) + 1; + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; - strcpy(__eq_ptr, __emu_Ptr); // Description + strcpy(__eq_ptr, __emu_Ptr); // Description - __emu_Ptr += strlen(__emu_Ptr) + 1; - __eq_ptr += strlen(__eq_ptr) + 1; + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; - __eq_ptr[0] = 0; - __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; + __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; + __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); + __emu_Ptr += sizeof(AvailableTaskData2_Struct); + __eq_ptr += sizeof(structs::AvailableTaskData2_Struct); - strcpy(__eq_ptr, __emu_Ptr); // Unknown string + strcpy(__eq_ptr, __emu_Ptr); // Unknown string - __emu_Ptr += strlen(__emu_Ptr) + 1; - __eq_ptr += strlen(__eq_ptr) + 1; + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; - strcpy(__eq_ptr, __emu_Ptr); // Unknown string + strcpy(__eq_ptr, __emu_Ptr); // Unknown string - __emu_Ptr += strlen(__emu_Ptr) + 1; - __eq_ptr += strlen(__eq_ptr) + 1; + __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; + __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; + __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); + __emu_Ptr += sizeof(AvailableTaskTrailer_Struct); + __eq_ptr += sizeof(structs::AvailableTaskTrailer_Struct); - strcpy(__eq_ptr, __emu_Ptr); // Unknown string + strcpy(__eq_ptr, __emu_Ptr); // Unknown string - __emu_Ptr += strlen(__emu_Ptr) + 1; - __eq_ptr += strlen(__eq_ptr) + 1; + __emu_Ptr += strlen(__emu_Ptr) + 1; + __eq_ptr += strlen(__eq_ptr) + 1; } delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); -} -*/ - -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_ZoneServerInfo) { - SETUP_DIRECT_ENCODE(ZoneServerInfo_Struct, ZoneServerInfo_Struct); - OUT_str(ip); - OUT(port); - 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_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_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_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++) + ENCODE(OP_PetBuffWindow) { - outapp->WriteUInt32(0); // Unknown - } + // The format of the RoF packet is identical to the OP_BuffCreate packet. - outapp->WriteUInt32(structs::MAX_PP_DISCIPLINES); // Discipline count + SETUP_VAR_ENCODE(PetBuff_Struct); - for(uint32 r = 0; r < MAX_PP_DISCIPLINES; r++) - { - outapp->WriteUInt32(emu->disciplines.values[r]); - } + uint32 sz = 12 + (17 * emu->buffcount); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); - // Write zeroes for the rest of the disciplines - for(uint32 r = 0; r < structs::MAX_PP_DISCIPLINES - MAX_PP_DISCIPLINES; r++) - { - outapp->WriteUInt32(0); - } + __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); - 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) + for (uint16 i = 0; i < BUFF_COUNT; ++i) { - instrument_mod = 1.0f + (emu->buffs[r].bard_modifier - 10) / 10.0f; - slotid = 2; - player_id = 0x000717fd; + if (emu->spellid[i]) + { + __packet->WriteUInt32(i); + __packet->WriteUInt32(emu->spellid[i]); + __packet->WriteUInt32(emu->ticsremaining[i]); + __packet->WriteUInt32(0); // Unknown + __packet->WriteString(""); + } } - 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 ? + __packet->WriteUInt8(0); // Unknown - for(uint32 j = 0; j < 44; ++j) - outapp->WriteUInt8(0); // Unknown + FINISH_ENCODE(); } - for(uint32 r = 0; r < structs::BUFF_COUNT - BUFF_COUNT; r++) + ENCODE(OP_PlayerProfile) { - // 80 bytes of zeroes - for(uint32 j = 0; j < 20; ++j) + 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); - - } - - 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(""); + // Write zeroes for the next 13 equipment slots - for(uint32 j = 0; j < EmuConstants::BANDOLIER_SIZE; ++j) + 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(structs::MAX_POTIONS_IN_BELT); + 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 - 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); - } + 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 - for(uint32 r = 0; r < structs::MAX_POTIONS_IN_BELT - EmuConstants::POTION_BELT_SIZE; r++) - { - outapp->WriteString(""); - outapp->WriteUInt32(0); - outapp->WriteUInt32(0); - } + outapp->WriteUInt32(64); // Name Length - outapp->WriteSInt32(-1); // Unknown; - outapp->WriteSInt32(123); // HP Total ? - outapp->WriteSInt32(234); // Endurance Total ? - outapp->WriteSInt32(345); // Mana Total ? + uint32 CurrentPosition = outapp->GetWritePosition(); + outapp->WriteString(emu->name); - 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->SetWritePosition(CurrentPosition + 64); - outapp->WriteUInt32(20); // Unknown - Expansion count ? + outapp->WriteUInt32(32); // Last Name Length - 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 + CurrentPosition = outapp->GetWritePosition(); - outapp->WriteUInt32(64); // Name Length + outapp->WriteString(emu->last_name); - uint32 CurrentPosition = outapp->GetWritePosition(); + outapp->SetWritePosition(CurrentPosition + 32); - outapp->WriteString(emu->name); + 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->SetWritePosition(CurrentPosition + 64); + outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); - outapp->WriteUInt32(32); // Last Name Length + for (uint32 r = 0; r < MAX_PP_LANGUAGE; r++) + { + outapp->WriteUInt8(emu->languages[r]); + } - CurrentPosition = outapp->GetWritePosition(); + for (uint32 r = 0; r < structs::MAX_PP_LANGUAGE - MAX_PP_LANGUAGE; r++) + { + outapp->WriteUInt8(0); + } - outapp->WriteString(emu->last_name); + outapp->WriteUInt16(emu->zone_id); + outapp->WriteUInt16(emu->zoneInstance); - outapp->SetWritePosition(CurrentPosition + 32); + outapp->WriteFloat(emu->y); + outapp->WriteFloat(emu->x); + outapp->WriteFloat(emu->z); + outapp->WriteFloat(emu->heading); - 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->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->pvp); + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(emu->gm); - outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); + 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 - for(uint32 r = 0; r < MAX_PP_LANGUAGE; r++) - { - outapp->WriteUInt8(emu->languages[r]); - } + outapp->WriteUInt64(emu->exp); + outapp->WriteUInt8(0); // Unknown - for(uint32 r = 0; r < structs::MAX_PP_LANGUAGE - MAX_PP_LANGUAGE; r++) - { - outapp->WriteUInt8(0); - } + outapp->WriteUInt32(emu->platinum_bank); + outapp->WriteUInt32(emu->gold_bank); + outapp->WriteUInt32(emu->silver_bank); + outapp->WriteUInt32(emu->copper_bank); - 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(0); // Unknown - outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(42); // The meaning of life ? - outapp->WriteUInt32(emu->career_tribute_points); - outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(emu->tribute_points); - outapp->WriteUInt32(0); // Unknown + for (uint32 r = 0; r < 42; r++) + { + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown + } - outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown - outapp->WriteUInt32(EmuConstants::TRIBUTE_SIZE); + outapp->WriteUInt32(emu->career_tribute_points); + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(emu->tribute_points); + outapp->WriteUInt32(0); // Unknown - 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->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 + outapp->WriteUInt32(EmuConstants::TRIBUTE_SIZE); - // Unknown String ? - outapp->WriteUInt32(64); // Unknown - for(uint32 r = 0; r < 64; r++) + 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->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(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 + outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - // Unknown String ? - outapp->WriteUInt32(64); // Unknown - for(uint32 r = 0; r < 64; r++) + outapp->WriteUInt32(0); // Unknown + + outapp->WriteUInt8(0); // Unknown + outapp->WriteUInt8(0); // Unknown outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(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->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(0); // Unknown + outapp->WriteUInt32(emu->level); // Level3 ? - outapp->WriteUInt8(emu->leadAAActive); + outapp->WriteUInt8(emu->showhelm); - 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->RestTimer); - outapp->WriteUInt32(emu->ldon_points_available); + outapp->WriteUInt32(1024); // Unknown Count - outapp->WriteDouble(emu->group_leadership_exp); - outapp->WriteDouble(emu->raid_leadership_exp); + // Block of 1024 unknown bytes + outapp->WriteUInt8(31); // Unknown - outapp->WriteUInt32(emu->group_leadership_points); - outapp->WriteUInt32(emu->raid_leadership_points); + for (uint32 r = 0; r < 1023; r++) + outapp->WriteUInt8(0); // Unknown - outapp->WriteUInt32(64); // Group of 64 int32s follow Group/Raid Leadership abilities ? + outapp->WriteUInt32(0); // Unknown + outapp->WriteUInt32(0); // Unknown - for(uint32 r = 0; r < MAX_LEADERSHIP_AA_ARRAY; r++) - outapp->WriteUInt32(emu->leader_abilities.ranks[r]); + // Think we need 1 byte of padding at the end - 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 + _log(NET__STRUCTS, "Player Profile Packet is %i bytes", outapp->GetWritePosition()); - // Think we need 1 byte of padding at the end + 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); - outapp->WriteUInt8(0); // Unknown + CRC32::SetEQChecksum(outapp->pBuffer, outapp->size - 1, 8); + //_hex(NET__ERROR, outapp->pBuffer, outapp->size); - - _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_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_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)); + dest->FastQueuePacket(&outapp, ack_req); 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) + ENCODE(OP_RaidJoin) { - 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); + 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; } - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_PetBuffWindow) -{ - // The format of the RoF 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) + ENCODE(OP_RaidUpdate) { - if(emu->spellid[i]) + 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 { - __packet->WriteUInt32(i); - __packet->WriteUInt32(emu->spellid[i]); - __packet->WriteUInt32(emu->ticsremaining[i]); - __packet->WriteUInt32(0); // Unknown - __packet->WriteString(""); + 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 + { + 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); + eq->invslot = 0; // Set to hard 0 since it's not required for the structure to work + 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 = ServerToRoFSlot(emu->unknown1); + structs::ItemSlotStruct RoFSlot; + RoFSlot.SlotType = 8; // Observed + RoFSlot.Unknown02 = 0; + RoFSlot.MainSlot = 0xffff; + RoFSlot.SubSlot = 0xffff; + RoFSlot.AugSlot = 0xffff; + RoFSlot.Unknown01 = 0; + eq->unknown_slot = RoFSlot; + 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 = ServerToRoFMainInvSlot(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); // RoF 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); } } - __packet->WriteUInt8(0); // Unknown - 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) + ENCODE(OP_TraderBuy) { - dest->FastQueuePacket(&in, ack_req); + ENCODE_LENGTH_EXACT(TraderBuy_Struct); + SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct); - 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); + OUT(Action); + OUT(Price); + OUT(TraderID); memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); - OUT(Cost); - OUT(ItemStat); + OUT(ItemID); + OUT(Quantity); + OUT(AlreadySold); + + FINISH_ENCODE(); } - delete[] __emu_buffer; + 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); - dest->FastQueuePacket(&in, ack_req); -} + OUT(tribute_id); + OUT(tier_count); -ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneSpawns) -{ + 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 = ServerToRoFSlot(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; + 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) { + 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; + emu = (Spawn_Struct *)__emu_buffer; //_log(NET__STRUCTS, "Spawn packet size is %i, entries = %i", in->size, entrycount); - char *Buffer = (char *) in->pBuffer, *BufferStart; - + char *Buffer = (char *)in->pBuffer, *BufferStart; int r; int k; - for(r = 0; r < entrycount; r++, emu++) { + for (r = 0; r < entrycount; r++, emu++) { int PacketSize = 206; @@ -1856,14 +3599,14 @@ ENCODE(OP_ZoneSpawns) emu->title[0] = 0; emu->suffix[0] = 0; - if(strlen(emu->title)) + if (strlen(emu->title)) PacketSize += strlen(emu->title) + 1; - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; bool ShowName = 1; - if(emu->bodytype >= 66) + if (emu->bodytype >= 66) { emu->race = 127; emu->bodytype = 11; @@ -1872,11 +3615,11 @@ ENCODE(OP_ZoneSpawns) } float SpawnSize = emu->size; - if(!((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + 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) + if (emu->size == 0) { emu->size = 6; SpawnSize = 6; @@ -1885,13 +3628,13 @@ ENCODE(OP_ZoneSpawns) else PacketSize += 216; - if(SpawnSize == 0) + if (SpawnSize == 0) { SpawnSize = 3; } EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); - Buffer = (char *) outapp->pBuffer; + Buffer = (char *)outapp->pBuffer; BufferStart = Buffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); @@ -1924,10 +3667,10 @@ ENCODE(OP_ZoneSpawns) uint8 OtherData = 0; - if(strlen(emu->title)) + if (strlen(emu->title)) OtherData = OtherData | 16; - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) OtherData = OtherData | 32; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); @@ -1962,10 +3705,9 @@ ENCODE(OP_ZoneSpawns) 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) + if (emu->NPC) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xFFFFFFFF); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); @@ -1976,10 +3718,10 @@ ENCODE(OP_ZoneSpawns) /* 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; } // + 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; } // } } @@ -2005,9 +3747,9 @@ ENCODE(OP_ZoneSpawns) 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)) + 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) + for (k = 0; k < 9; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color); @@ -2016,7 +3758,7 @@ ENCODE(OP_ZoneSpawns) structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; - for(k = 0; k < 9; k++) { + for (k = 0; k < 9; k++) { Equipment[k].equip0 = emu->equipment[k]; Equipment[k].equip1 = 0; Equipment[k].equip2 = 0; @@ -2047,7 +3789,6 @@ ENCODE(OP_ZoneSpawns) VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } - structs::Spawn_Struct_Position *Position = (structs::Spawn_Struct_Position*)Buffer; Position->deltaX = emu->deltaX; @@ -2062,12 +3803,12 @@ ENCODE(OP_ZoneSpawns) Buffer += sizeof(structs::Spawn_Struct_Position); - if(strlen(emu->title)) + if (strlen(emu->title)) { VARSTRUCT_ENCODE_STRING(Buffer, emu->title); } - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) { VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix); } @@ -2079,1989 +3820,620 @@ ENCODE(OP_ZoneSpawns) VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // 29 zero bytes follow Buffer += 29; - if(Buffer != (BufferStart + PacketSize)) + 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; -} - -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_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_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_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_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_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_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_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++) +// DECODE methods + DECODE(OP_AdventureMerchantSell) { - eq->entries[i] = emu->entries[i]; - } - eq->entries[21] = 0; + DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); + SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - FINISH_ENCODE(); -} + IN(npcid); + emu->slot = RoFToServerMainInvSlot(eq->slot); + IN(charges); + IN(sell_price); -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_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_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_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_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_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_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_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_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_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_ExpansionInfo) { - ENCODE_LENGTH_EXACT(ExpansionInfo_Struct); - SETUP_DIRECT_ENCODE(ExpansionInfo_Struct, structs::ExpansionInfo_Struct); - OUT(Expansions); - 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_Animation) { - ENCODE_LENGTH_EXACT(Animation_Struct); - SETUP_DIRECT_ENCODE(Animation_Struct, structs::Animation_Struct); - OUT(spawnid); - OUT(value); - OUT(action); - 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_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_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_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); - 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_CancelTrade) { - ENCODE_LENGTH_EXACT(CancelTrade_Struct); - SETUP_DIRECT_ENCODE(CancelTrade_Struct, structs::CancelTrade_Struct); - OUT(fromid); - OUT(action); - 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_ShopPlayerSell) { - ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); - SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); - OUT(npcid); - eq->itemslot = ServerToRoFMainInvSlot(emu->itemslot); - //OUT(itemslot); - OUT(quantity); - OUT(price); - FINISH_ENCODE(); -} - -ENCODE(OP_ApplyPoison) { - ENCODE_LENGTH_EXACT(ApplyPoison_Struct); - SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - eq->inventorySlot = ServerToRoFMainInvSlot(emu->inventorySlot); - OUT(success); - 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 = ServerToRoFSlot(emu->unknown1); - structs::ItemSlotStruct RoFSlot; - RoFSlot.SlotType = 8; // Observed - RoFSlot.Unknown02 = 0; - RoFSlot.MainSlot = 0xffff; - RoFSlot.SubSlot = 0xffff; - RoFSlot.AugSlot = 0xffff; - RoFSlot.Unknown01 = 0; - eq->unknown_slot = RoFSlot; - OUT(recipe_id); - OUT(reply_code); - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteItem) { - ENCODE_LENGTH_EXACT(DeleteItem_Struct); - SETUP_DIRECT_ENCODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - eq->from_slot = ServerToRoFSlot(emu->from_slot); - eq->to_slot = ServerToRoFSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } -ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToRoFSlot(emu->from_slot); - eq->to_slot = ServerToRoFSlot(emu->to_slot); - OUT(number_in_stack); - FINISH_ENCODE(); -} - -ENCODE(OP_ItemVerifyReply) { - ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); - SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - - eq->slot = ServerToRoFSlot(emu->slot); - OUT(spell); - OUT(target); - - FINISH_ENCODE(); -} - -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_LootItem) { - - ENCODE_LENGTH_EXACT(LootingItem_Struct); - SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - OUT(lootee); - OUT(looter); - eq->slot_id = emu->slot_id + 1; - OUT(auto_loot); - - FINISH_ENCODE(); -} - -ENCODE(OP_TributeItem) { - ENCODE_LENGTH_EXACT(TributeItem_Struct); - SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); - - eq->slot = ServerToRoFSlot(emu->slot); - OUT(quantity); - OUT(tribute_master_id); - OUT(tribute_points); - - 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_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); - eq->invslot = 0; // Set to hard 0 since it's not required for the structure to work - strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); - 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_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_AdventureMerchantSell) { - ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); - SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - eq->unknown000 = 1; - OUT(npcid); - eq->slot = ServerToRoFMainInvSlot(emu->slot); - OUT(charges); - OUT(sell_price); - - FINISH_ENCODE(); -} - -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 - { - 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_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_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); + FINISH_DIRECT_DECODE(); } - dest->FastQueuePacket(&outapp_create); - delete inapp; -} - -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) + DECODE(OP_AltCurrencySell) { - uint32 x; + DECODE_LENGTH_EXACT(structs::AltCurrencySellItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + IN(merchant_entity_id); + emu->slot_id = RoFToServerSlot(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 = RoFToServerSlot(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 = RoFToServerMainInvSlot(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 = RoFToServerSlot(eq->container_slot); + emu->augment_slot = RoFToServerSlot(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 = RoFToServerSlot(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; - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0xffffffff); - char Name[64]; + uint32 Language = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + uint32 Channel = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_DECODE_STRING(Name, InBuffer); // Char Name - VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + InBuffer += 5; - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_DECODE_STRING(Name, InBuffer); // Guild Name - VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; - for(int j = 0; j < 7; ++j) - { - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); - } + 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); - VARSTRUCT_DECODE_STRING(Name, InBuffer); // Account - VARSTRUCT_ENCODE_STRING(OutBuffer, Name); - - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + delete[] __eq_buffer; } - //_hex(NET__ERROR, outapp->pBuffer, outapp->size); - dest->FastQueuePacket(&outapp); + DECODE(OP_CharacterCreate) + { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - delete in; -} + IN(gender); + IN(race); + IN(class_); + IN(deity); -ENCODE(OP_InspectRequest) { - ENCODE_LENGTH_EXACT(Inspect_Struct); - SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - OUT(TargetID); - OUT(PlayerID); - FINISH_ENCODE(); -} + if (RuleB(World, EnableTutorialButton) && eq->tutorial) + emu->start_zone = RuleI(World, TutorialZoneID); + else + emu->start_zone = eq->start_zone; -/*ENCODE(OP_InspectAnswer) { - ENCODE_LENGTH_EXACT(InspectResponse_Struct); - SETUP_DIRECT_ENCODE(InspectResponse_Struct, structs::InspectResponse_Struct); + 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); - OUT(TargetID); - OUT(playerid); + 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 = RoFToServerSlot(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 = RoFToServerSlot(eq->from_slot); + emu->to_slot = RoFToServerSlot(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(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r])); + strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->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)); + 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++) { - OUT(itemicons[k]); + IN(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_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_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_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_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_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_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_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_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_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_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_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_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_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_TargetBuffs) { ENCODE_FORWARD(OP_BuffCreate); } -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(1); // 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 RoF 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(0); // Unknown - __packet->WriteString(""); - } - __packet->WriteUInt8(0); // Unknown - - FINISH_ENCODE(); -} - -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_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_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_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 = ServerToRoFSlot(emu->inventoryslot); - //OUT(inventoryslot); - OUT(target_id); - 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_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_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_AltCurrencySell) -{ - ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); - SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - - OUT(merchant_entity_id); - eq->slot_id = ServerToRoFSlot(emu->slot_id); - OUT(charges); - OUT(cost); - 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_HPUpdate) -{ - SETUP_DIRECT_ENCODE(SpawnHPUpdate_Struct, structs::SpawnHPUpdate_Struct); - OUT(spawn_id); - OUT(cur_hp); - OUT(max_hp); - FINISH_ENCODE(); -} - -ENCODE(OP_RemoveBlockedBuffs) { ENCODE_FORWARD(OP_BlockedBuffs); } - -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 RoF. We should really be encoding for the older clients, not RoF, 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_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_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_BeginCast) -{ - SETUP_DIRECT_ENCODE(BeginCast_Struct, structs::BeginCast_Struct); - - OUT(spell_id); - OUT(caster_id); - OUT(cast_time); - - 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(); -} - -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); + 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_PetCommands) -{ - DECODE_LENGTH_EXACT(structs::PetCommand_Struct); - SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); - - switch(eq->command) + 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 = RoFToServerSlot(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 = eq->slot_id - 1; + 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 = RoFToServerSlot(eq->from_slot); + emu->to_slot = RoFToServerSlot(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; @@ -4100,1312 +4472,1075 @@ DECODE(OP_PetCommands) break; default: emu->command = eq->command; - } - - 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 = RoFToServerSlot(eq->slot_id); - 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 = RoFToServerSlot(eq->slot_id); - IN(charges); - IN(cost); - 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_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_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_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_InspectRequest) { - DECODE_LENGTH_EXACT(structs::Inspect_Struct); - SETUP_DIRECT_DECODE(Inspect_Struct, structs::Inspect_Struct); - IN(TargetID); - IN(PlayerID); - 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_RaidInvite) { - 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(); -} - -DECODE(OP_AdventureMerchantSell) { - DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); - SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - IN(npcid); - emu->slot = RoFToServerMainInvSlot(eq->slot); - IN(charges); - IN(sell_price); - - FINISH_DIRECT_DECODE(); -} - - -DECODE(OP_ApplyPoison) { - DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); - SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - - emu->inventorySlot = RoFToServerMainInvSlot(eq->inventorySlot); - IN(success); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ItemVerifyRequest) { - DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); - SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); - - emu->slot = RoFToServerSlot(eq->slot); - IN(target); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_Consume) { - DECODE_LENGTH_EXACT(structs::Consume_Struct); - SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); - - emu->slot = RoFToServerSlot(eq->slot); - IN(auto_consumed); - IN(type); - - 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 = RoFToServerSlot(eq->inventoryslot); - //IN(inventoryslot); - IN(target_id); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_DeleteItem) -{ - DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); - SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - emu->from_slot = RoFToServerSlot(eq->from_slot); - emu->to_slot = RoFToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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 = RoFToServerSlot(eq->from_slot); - emu->to_slot = RoFToServerSlot(eq->to_slot); - IN(number_in_stack); - - _hex(NET__ERROR, eq, sizeof(structs::MoveItem_Struct)); - 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_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 RoF - IN(filters[r]); - } - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } -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_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_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_CharacterCreate) { - DECODE_LENGTH_EXACT(structs::CharCreate_Struct); - SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - - IN(gender); - IN(race); - IN(class_); - IN(deity); - - if(RuleB(World, EnableTutorialButton) && eq->tutorial) - emu->start_zone = RuleI(World, TutorialZoneID); - else - emu->start_zone = eq->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_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_GroupInvite2) -{ - //_log(NET__ERROR, "Received incoming OP_GroupInvite2. Forwarding"); - DECODE_FORWARD(OP_GroupInvite); -} - -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_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_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_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_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_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_ShopPlayerSell) { - DECODE_LENGTH_EXACT(structs::Merchant_Purchase_Struct); - SETUP_DIRECT_DECODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); - - IN(npcid); - emu->itemslot = RoFToServerMainInvSlot(eq->itemslot); - //IN(itemslot); - IN(quantity); - IN(price); - - 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_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_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; + DECODE(OP_RaidInvite) + { + 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(); } -} -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_LootItem) { - DECODE_LENGTH_EXACT(structs::LootingItem_Struct); - SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - IN(lootee); - IN(looter); - emu->slot_id = eq->slot_id - 1; - IN(auto_loot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TributeItem) { - DECODE_LENGTH_EXACT(structs::TributeItem_Struct); - SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); - - emu->slot = RoFToServerSlot(eq->slot); - IN(quantity); - IN(tribute_master_id); - IN(tribute_points); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ReadBook) { - DECODE_LENGTH_EXACT(structs::BookRequest_Struct); - SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); - - IN(type); - emu->invslot = 0; // Set to hard 0 since it's not required for the structure to work - emu->window = (uint8) eq->window; - strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TradeSkillCombine) { - DECODE_LENGTH_EXACT(structs::NewCombine_Struct); - SETUP_DIRECT_DECODE(NewCombine_Struct, structs::NewCombine_Struct); - - int16 slot_id = RoFToServerSlot(eq->container_slot); - if (slot_id == 4000) { - slot_id = legacy::SLOT_TRADESKILL; // 1000 - } - emu->container_slot = slot_id; - - 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 = RoFToServerSlot(eq->container_slot); - IN(recipe_id); - IN(reply_code); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_AugmentItem) { - DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); - SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); - - emu->container_slot = RoFToServerSlot(eq->container_slot); - emu->augment_slot = RoFToServerSlot(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_AugmentInfo) { - DECODE_LENGTH_EXACT(structs::AugmentInfo_Struct); - SETUP_DIRECT_DECODE(AugmentInfo_Struct, structs::AugmentInfo_Struct); - - IN(itemid); - IN(window); - - 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_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) + DECODE(OP_ReadBook) { - if (eq->spell[i] == 0) - emu->spell[i] = 0xFFFFFFFF; + DECODE_LENGTH_EXACT(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(type); + emu->invslot = 0; // Set to hard 0 since it's not required for the structure to work + 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 = RoFToServerSlot(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 RoF + 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 = RoFToServerMainInvSlot(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 = RoFToServerSlot(eq->container_slot); + if (slot_id == 4000) { + slot_id = legacy::SLOT_TRADESKILL; // 1000 + } + emu->container_slot = slot_id; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TributeItem) + { + DECODE_LENGTH_EXACT(structs::TributeItem_Struct); + SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); + + emu->slot = RoFToServerSlot(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 - emu->spell[i] = eq->spell[i]; + NextItemInstSerialNumber++; + + return NextItemInstSerialNumber; } - 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_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_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_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_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(); -} - -DECODE(OP_RemoveBlockedBuffs) { DECODE_FORWARD(OP_BlockedBuffs); } - -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_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_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(); -} - -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) { - 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->GetItem(); - //_log(NET__ERROR, "Serialize called for: %s", item->Name); - - RoF::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 = ServerToRoFSlot(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.unknown020 = 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.unknown056 = 0; - hdr.unknown060 = 0; - hdr.unknown061 = 0; - hdr.unknown062 = 0; - hdr.unknowna1 = 0xffffffff; - hdr.unknowna2 = 0; - hdr.unknown063 = 0; - hdr.unknowna3 = 0; - hdr.unknowna4 = 0xffffffff; - hdr.unknowna5 = 0; - hdr.ItemClass = item->ItemClass; - - ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); - - - if(strlen(item->Name) > 0) + char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth) { - ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } + uint8 null_term = 0; + bool stackable = inst->IsStackable(); + uint32 merchant_slot = inst->GetMerchantSlot(); + uint32 charges = inst->GetCharges(); + if (!stackable && charges > 254) + charges = 0xFFFFFFFF; - 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)); - } + std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - 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)); - } + const Item_Struct *item = inst->GetItem(); + //_log(NET__ERROR, "Serialize called for: %s", item->Name); - ss.write((const char*)&null_term, sizeof(uint8)); - //_log(NET__ERROR, "ItemBody struct is %i bytes", sizeof(RoF::structs::ItemBodyStruct)); - RoF::structs::ItemBodyStruct ibs; - memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct)); + RoF::structs::ItemSerializationHeader hdr; - uint32 adjusted_slots = item->Slots; + //sprintf(hdr.unknown000, "06e0002Y1W00"); - // Conversions for Ammo and Power Source Slots - if(item->Slots & (1 << 21) & (1 << 22)) - { - // Do nothing - } - else - { - if(item->Slots & (1 << 21)) // Ammo Slot from Database + snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%012d", item->ID); + + hdr.stacksize = stackable ? charges : 1; + hdr.unknown004 = 0; + + structs::ItemSlotStruct slot_id = ServerToRoFSlot(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.unknown020 = 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.unknown056 = 0; + hdr.unknown060 = 0; + hdr.unknown061 = 0; + hdr.unknown062 = 0; + hdr.unknowna1 = 0xffffffff; + hdr.unknowna2 = 0; + hdr.unknown063 = 0; + hdr.unknowna3 = 0; + hdr.unknowna4 = 0xffffffff; + hdr.unknowna5 = 0; + hdr.ItemClass = item->ItemClass; + + ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); + + if (strlen(item->Name) > 0) { - adjusted_slots -= (1 << 21); // Ammo Slot in Titanium - adjusted_slots += (1 << 22); // Ammo Slot in SoF + 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(item->Slots & (1 << 22)) // Power Source Slot from Database + if (strlen(item->Lore) > 0) { - adjusted_slots -= (1 << 22); // Non Existant Worn Slot in Titanium - adjusted_slots += (1 << 21); // Power Source Slot in SoF + ss.write(item->Lore, strlen(item->Lore)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); } - } - 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 = adjusted_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; + 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)); + } - 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_RoF3 = 0; - ibs.unknown_RoF4 = 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.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(RoF::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 struct is %i bytes", sizeof(RoF::structs::ItemBodyStruct)); + RoF::structs::ItemBodyStruct ibs; + memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct)); - //_log(NET__ERROR, "ItemBody secondary struct is %i bytes", sizeof(RoF::structs::ItemSecondaryBodyStruct)); - RoF::structs::ItemSecondaryBodyStruct isbs; - memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct)); + 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; - isbs.augtype = item->AugType; - isbs.augdistiller = 65535; - isbs.augrestrict = item->AugRestrict; - + 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_RoF3 = 0; + ibs.unknown_RoF4 = 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.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; - 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]; - } + ss.write((const char*)&ibs, sizeof(RoF::structs::ItemBodyStruct)); - // Increased to 6 max aug slots - isbs.augslots[5].type = 0; - isbs.augslots[5].visible = 1; - isbs.augslots[5].unknown = 0; + //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)); + } - isbs.ldonpoint_type = item->PointType; - isbs.ldontheme = item->LDoNTheme; - isbs.ldonprice = item->LDoNPrice; - isbs.ldonsellbackrate = item->LDoNSellBackRate; - isbs.ldonsold = item->LDoNSold; + //_log(NET__ERROR, "ItemBody secondary struct is %i bytes", sizeof(RoF::structs::ItemSecondaryBodyStruct)); + RoF::structs::ItemSecondaryBodyStruct isbs; + memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct)); - isbs.bagtype = item->BagType; - isbs.bagslots = item->BagSlots; - isbs.bagsize = item->BagSize; - isbs.wreduction = item->BagWR; + isbs.augtype = item->AugType; + isbs.augdistiller = 65535; + isbs.augrestrict = item->AugRestrict; - isbs.book = item->Book; - isbs.booktype = item->BookType; + 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]; + } - ss.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); + // Increased to 6 max aug slots + isbs.augslots[5].type = 0; + isbs.augslots[5].visible = 1; + isbs.augslots[5].unknown = 0; - 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)); - } + isbs.ldonpoint_type = item->PointType; + isbs.ldontheme = item->LDoNTheme; + isbs.ldonprice = item->LDoNPrice; + isbs.ldonsellbackrate = item->LDoNSellBackRate; + isbs.ldonsold = item->LDoNSold; - //_log(NET__ERROR, "ItemBody tertiary struct is %i bytes", sizeof(RoF::structs::ItemTertiaryBodyStruct)); - RoF::structs::ItemTertiaryBodyStruct itbs; - memset(&itbs, 0, sizeof(RoF::structs::ItemTertiaryBodyStruct)); + isbs.bagtype = item->BagType; + isbs.bagslots = item->BagSlots; + isbs.bagsize = item->BagSize; + isbs.wreduction = item->BagWR; - 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; + isbs.book = item->Book; + isbs.booktype = item->BookType; - 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; + ss.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); - itbs.unknown8 = 0; - itbs.unknown9 = 0; - itbs.unknown10 = 0; - itbs.unknown11 = 0; - itbs.unknown12 = 0; - itbs.unknown13 = 0; - itbs.unknown14 = 0; + 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)); + } - ss.write((const char*)&itbs, sizeof(RoF::structs::ItemTertiaryBodyStruct)); + //_log(NET__ERROR, "ItemBody tertiary struct is %i bytes", sizeof(RoF::structs::ItemTertiaryBodyStruct)); + RoF::structs::ItemTertiaryBodyStruct itbs; + memset(&itbs, 0, sizeof(RoF::structs::ItemTertiaryBodyStruct)); - // Effect Structures Broken down to allow variable length strings for effect names - int32 effect_unknown = 0; + 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; - //_log(NET__ERROR, "ItemBody Click effect struct is %i bytes", sizeof(RoF::structs::ClickEffectStruct)); - RoF::structs::ClickEffectStruct ices; - memset(&ices, 0, sizeof(RoF::structs::ClickEffectStruct)); + 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; - 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; + 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*)&ices, sizeof(RoF::structs::ClickEffectStruct)); + ss.write((const char*)&itbs, sizeof(RoF::structs::ItemTertiaryBodyStruct)); - 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)); - } + // Effect Structures Broken down to allow variable length strings for effect names + int32 effect_unknown = 0; - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + //_log(NET__ERROR, "ItemBody Click effect struct is %i bytes", sizeof(RoF::structs::ClickEffectStruct)); + RoF::structs::ClickEffectStruct ices; + memset(&ices, 0, sizeof(RoF::structs::ClickEffectStruct)); - //_log(NET__ERROR, "ItemBody proc effect struct is %i bytes", sizeof(RoF::structs::ProcEffectStruct)); - RoF::structs::ProcEffectStruct ipes; - memset(&ipes, 0, sizeof(RoF::structs::ProcEffectStruct)); + 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; - 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*)&ices, sizeof(RoF::structs::ClickEffectStruct)); - ss.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); + 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)); + } - 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)); // clickunk7 - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + //_log(NET__ERROR, "ItemBody proc effect struct is %i bytes", sizeof(RoF::structs::ProcEffectStruct)); + RoF::structs::ProcEffectStruct ipes; + memset(&ipes, 0, sizeof(RoF::structs::ProcEffectStruct)); - //_log(NET__ERROR, "ItemBody worn effect struct is %i bytes", sizeof(RoF::structs::WornEffectStruct)); - RoF::structs::WornEffectStruct iwes; - memset(&iwes, 0, sizeof(RoF::structs::WornEffectStruct)); + ipes.effect = item->Proc.Effect; + ipes.level2 = item->Proc.Level2; + ipes.type = item->Proc.Type; + ipes.level = item->Proc.Level; + ipes.procrate = item->ProcRate; - iwes.effect = item->Worn.Effect; - iwes.level2 = item->Worn.Level2; - iwes.type = item->Worn.Type; - iwes.level = item->Worn.Level; + ss.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); - ss.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); + 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)); + } - 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)); // unknown5 - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + //_log(NET__ERROR, "ItemBody worn effect struct is %i bytes", sizeof(RoF::structs::WornEffectStruct)); + RoF::structs::WornEffectStruct iwes; + memset(&iwes, 0, sizeof(RoF::structs::WornEffectStruct)); - RoF::structs::WornEffectStruct ifes; - memset(&ifes, 0, sizeof(RoF::structs::WornEffectStruct)); + iwes.effect = item->Worn.Effect; + iwes.level2 = item->Worn.Level2; + iwes.type = item->Worn.Type; + iwes.level = item->Worn.Level; - ifes.effect = item->Focus.Effect; - ifes.level2 = item->Focus.Level2; - ifes.type = item->Focus.Type; - ifes.level = item->Focus.Level; + ss.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); - ss.write((const char*)&ifes, sizeof(RoF::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)); + } - 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 - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + RoF::structs::WornEffectStruct ifes; + memset(&ifes, 0, sizeof(RoF::structs::WornEffectStruct)); - RoF::structs::WornEffectStruct ises; - memset(&ises, 0, sizeof(RoF::structs::WornEffectStruct)); + ifes.effect = item->Focus.Effect; + ifes.level2 = item->Focus.Level2; + ifes.type = item->Focus.Type; + ifes.level = item->Focus.Level; - ises.effect = item->Scroll.Effect; - ises.level2 = item->Scroll.Level2; - ises.type = item->Scroll.Type; - ises.level = item->Scroll.Level; + ss.write((const char*)&ifes, sizeof(RoF::structs::WornEffectStruct)); - ss.write((const char*)&ises, sizeof(RoF::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)); + } - 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 - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + RoF::structs::WornEffectStruct ises; + memset(&ises, 0, sizeof(RoF::structs::WornEffectStruct)); - // Bard Effect? - RoF::structs::WornEffectStruct ibes; - memset(&ibes, 0, sizeof(RoF::structs::WornEffectStruct)); + ises.effect = item->Scroll.Effect; + ises.level2 = item->Scroll.Level2; + ises.type = item->Scroll.Type; + ises.level = item->Scroll.Level; - ibes.effect = 0xffffffff; - ibes.level2 = 0; - ibes.type = 0; - ibes.level = 0; - //ibes.unknown6 = 0xffffffff; + ss.write((const char*)&ises, sizeof(RoF::structs::WornEffectStruct)); - ss.write((const char*)&ibes, sizeof(RoF::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)); + } - /* - if(strlen(item->BardName) > 0) - { + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + + // Bard Effect? + RoF::structs::WornEffectStruct ibes; + memset(&ibes, 0, sizeof(RoF::structs::WornEffectStruct)); + + ibes.effect = 0xffffffff; + ibes.level2 = 0; + ibes.type = 0; + ibes.level = 0; + //ibes.unknown6 = 0xffffffff; + + ss.write((const char*)&ibes, sizeof(RoF::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 */ + } + else */ ss.write((const char*)&null_term, sizeof(uint8)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - // End of Effects + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // End of Effects - //_log(NET__ERROR, "ItemBody Quaternary effect struct is %i bytes", sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - RoF::structs::ItemQuaternaryBodyStruct iqbs; - memset(&iqbs, 0, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); + //_log(NET__ERROR, "ItemBody Quaternary effect struct is %i bytes", sizeof(RoF::structs::ItemQuaternaryBodyStruct)); + RoF::structs::ItemQuaternaryBodyStruct iqbs; + memset(&iqbs, 0, sizeof(RoF::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; - iqbs.unknown30 = 0; - iqbs.unknown39 = 1; + 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; + iqbs.unknown30 = 0; + iqbs.unknown39 = 1; - iqbs.subitem_count = 0; + iqbs.subitem_count = 0; - char *SubSerializations[10]; // + char *SubSerializations[10]; // - uint32 SubLengths[10]; + uint32 SubLengths[10]; - for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { - SubSerializations[x] = nullptr; + SubSerializations[x] = nullptr; - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); + const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - if(subitem) { + if (subitem) { - int SubSlotNumber; + int SubSlotNumber; - iqbs.subitem_count++; + 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; // ??????? + 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(RoF::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 ServerToRoFSlot(uint32 ServerSlot) + { + structs::ItemSlotStruct RoFSlot; + RoFSlot.SlotType = INVALID_INDEX; + RoFSlot.Unknown02 = NOT_USED; + RoFSlot.MainSlot = INVALID_INDEX; + RoFSlot.SubSlot = INVALID_INDEX; + RoFSlot.AugSlot = INVALID_INDEX; + RoFSlot.Unknown01 = NOT_USED; + + uint32 TempSlot = 0; + + if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // Main Inventory and Cursor + RoFSlot.SlotType = maps::MapPossessions; + RoFSlot.MainSlot = ServerSlot; + + if (ServerSlot == MainPowerSource) + RoFSlot.MainSlot = slots::MainPowerSource; + + else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + RoFSlot.MainSlot += 3; + + else if (ServerSlot >= MainAmmo) // (> 20) + RoFSlot.MainSlot += 1; + } + + /*else if (ServerSlot < 51) { // Cursor Buffer + RoFSlot.SlotType = maps::MapLimbo; + RoFSlot.MainSlot = ServerSlot - 31; + }*/ + + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { // (> 250 && < 341) + RoFSlot.SlotType = maps::MapPossessions; + TempSlot = ServerSlot - 1; + RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + + if (RoFSlot.MainSlot >= slots::MainGeneral9) // (> 30) + RoFSlot.MainSlot = slots::MainCursor; + } + + else if (ServerSlot >= EmuConstants::TRIBUTE_BEGIN && ServerSlot <= EmuConstants::TRIBUTE_END) { // Tribute + RoFSlot.SlotType = maps::MapTribute; + RoFSlot.MainSlot = ServerSlot - EmuConstants::TRIBUTE_BEGIN; + } + + else if (ServerSlot >= EmuConstants::BANK_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) { + RoFSlot.SlotType = maps::MapBank; + TempSlot = ServerSlot - EmuConstants::BANK_BEGIN; + RoFSlot.MainSlot = TempSlot; + + if (TempSlot > 30) { // (> 30) + RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } + } + + else if (ServerSlot >= EmuConstants::SHARED_BANK_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) { + RoFSlot.SlotType = maps::MapSharedBank; + TempSlot = ServerSlot - EmuConstants::SHARED_BANK_BEGIN; + RoFSlot.MainSlot = TempSlot; + + if (TempSlot > 30) { // (> 30) + RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } + } + + else if (ServerSlot >= EmuConstants::TRADE_BEGIN && ServerSlot <= EmuConstants::TRADE_BAGS_END) { + RoFSlot.SlotType = maps::MapTrade; + TempSlot = ServerSlot - EmuConstants::TRADE_BEGIN; + RoFSlot.MainSlot = TempSlot; + + if (TempSlot > 30) { + RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 3; + RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE); + } /* - // TEST CODE: - SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + // OLD CODE: + if (TempSlot > 99) { + if (TempSlot > 100) + RoFSlot.MainSlot = int((TempSlot - 100) / 10); + + else + RoFSlot.MainSlot = 0; + + RoFSlot.SubSlot = TempSlot - (100 + RoFSlot.MainSlot); + } */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); } + + else if (ServerSlot >= EmuConstants::WORLD_BEGIN && ServerSlot <= EmuConstants::WORLD_END) { + RoFSlot.SlotType = maps::MapWorld; + TempSlot = ServerSlot - EmuConstants::WORLD_BEGIN; + RoFSlot.MainSlot = TempSlot; + } + + _log(NET__ERROR, "Convert Server Slot %i to RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i", ServerSlot, RoFSlot.SlotType, RoFSlot.Unknown02, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01); + + return RoFSlot; } - ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); + static inline structs::MainInvItemSlotStruct ServerToRoFMainInvSlot(uint32 ServerSlot) + { + structs::MainInvItemSlotStruct RoFSlot; + RoFSlot.MainSlot = INVALID_INDEX; + RoFSlot.SubSlot = INVALID_INDEX; + RoFSlot.AugSlot = INVALID_INDEX; + RoFSlot.Unknown01 = NOT_USED; - for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + uint32 TempSlot = 0; - if(SubSerializations[x]) { + if (ServerSlot < 56 || ServerSlot == MainPowerSource) { // (< 52) + RoFSlot.MainSlot = ServerSlot; - ss.write((const char*)&x, sizeof(uint32)); + if (ServerSlot == MainPowerSource) + RoFSlot.MainSlot = slots::MainPowerSource; - ss.write(SubSerializations[x], SubLengths[x]); + else if (ServerSlot >= MainCursor) // Cursor and Extended Corpse Inventory + RoFSlot.MainSlot += 3; - safe_delete_array(SubSerializations[x]); + else if (ServerSlot >= MainAmmo) // Ammo and Personl Inventory + RoFSlot.MainSlot += 1; + + /*else if (ServerSlot >= MainCursor) { // Cursor + RoFSlot.MainSlot = slots::MainCursor; + + if (ServerSlot > 30) + RoFSlot.SubSlot = (ServerSlot + 3) - 33; + }*/ } + + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) { + TempSlot = ServerSlot - 1; + RoFSlot.MainSlot = int(TempSlot / EmuConstants::ITEM_CONTAINER_SIZE) - 2; + RoFSlot.SubSlot = TempSlot - ((RoFSlot.MainSlot + 2) * EmuConstants::ITEM_CONTAINER_SIZE); + } + + _log(NET__ERROR, "Convert Server Slot %i to RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i", ServerSlot, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01); + + return RoFSlot; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + static inline uint32 ServerToRoFCorpseSlot(uint32 ServerCorpse) + { + //uint32 RoFCorpse; + } - *length = ss.tellp(); - return item_serial; + static inline uint32 RoFToServerSlot(structs::ItemSlotStruct RoFSlot) + { + uint32 ServerSlot = INVALID_INDEX; + uint32 TempSlot = 0; + + if (RoFSlot.SlotType == maps::MapPossessions && RoFSlot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 51) + if (RoFSlot.MainSlot == slots::MainPowerSource) + TempSlot = MainPowerSource; + + else if (RoFSlot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory + TempSlot = RoFSlot.MainSlot - 3; + + /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF 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 RoF, 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 (RoFSlot.MainSlot >= slots::MainAmmo) // Ammo and Main Inventory + TempSlot = RoFSlot.MainSlot - 1; + + else // Worn Slots + TempSlot = RoFSlot.MainSlot; + + if (RoFSlot.SubSlot >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; + + ServerSlot = TempSlot; + } + + else if (RoFSlot.SlotType == maps::MapBank) { + TempSlot = EmuConstants::BANK_BEGIN; + + if (RoFSlot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; + + else + TempSlot += RoFSlot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoFSlot.SlotType == maps::MapSharedBank) { + TempSlot = EmuConstants::SHARED_BANK_BEGIN; + + if (RoFSlot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; + + else + TempSlot += RoFSlot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoFSlot.SlotType == maps::MapTrade) { + TempSlot = EmuConstants::TRADE_BEGIN; + + if (RoFSlot.SubSlot >= SUB_BEGIN) + TempSlot += ((RoFSlot.MainSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; + // OLD CODE: + //TempSlot += 100 + (RoFSlot.MainSlot * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot; + + else + TempSlot += RoFSlot.MainSlot; + + ServerSlot = TempSlot; + } + + else if (RoFSlot.SlotType == maps::MapWorld) { + TempSlot = EmuConstants::WORLD_BEGIN; + + if (RoFSlot.MainSlot >= SUB_BEGIN) + TempSlot += RoFSlot.MainSlot; + + ServerSlot = TempSlot; + } + + /*else if (RoFSlot.SlotType == maps::MapLimbo) { // Cursor Buffer + TempSlot = 31; + + if (RoFSlot.MainSlot >= 0) + TempSlot += RoFSlot.MainSlot; + + ServerSlot = TempSlot; + }*/ + + _log(NET__ERROR, "Convert RoF Slots: Type %i, Unk2 %i, Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoFSlot.SlotType, RoFSlot.Unknown02, RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01, ServerSlot); + + return ServerSlot; + } + + static inline uint32 RoFToServerMainInvSlot(structs::MainInvItemSlotStruct RoFSlot) + { + uint32 ServerSlot = INVALID_INDEX; + uint32 TempSlot = 0; + + if (RoFSlot.MainSlot < 57) { // Worn/Personal Inventory and Cursor (< 33) + if (RoFSlot.MainSlot == slots::MainPowerSource) + TempSlot = MainPowerSource; + + else if (RoFSlot.MainSlot >= slots::MainCursor) // Cursor and Extended Corpse Inventory + TempSlot = RoFSlot.MainSlot - 3; + + /*else if (RoFSlot.MainSlot == slots::MainGeneral9 || RoFSlot.MainSlot == slots::MainGeneral10) { // 9th and 10th RoF inventory slots + // Need to figure out what to do when we get these + + // Same as above + }*/ + + else if (RoFSlot.MainSlot >= slots::MainAmmo) // Main Inventory and Ammo Slots + TempSlot = RoFSlot.MainSlot - 1; + + else + TempSlot = RoFSlot.MainSlot; + + if (RoFSlot.SubSlot >= SUB_BEGIN) // Bag Slots + TempSlot = ((TempSlot + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + RoFSlot.SubSlot + 1; + + ServerSlot = TempSlot; + } + + _log(NET__ERROR, "Convert RoF Slots: Main %i, Sub %i, Aug %i, Unk1 %i to Server Slot %i", RoFSlot.MainSlot, RoFSlot.SubSlot, RoFSlot.AugSlot, RoFSlot.Unknown01, ServerSlot); + + return ServerSlot; + } + + static inline uint32 RoFToServerCorpseSlot(uint32 RoFCorpse) + { + //uint32 ServerCorpse; + } } - -} //end namespace RoF +// end namespace RoF diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index db2f1f989..69ec9f1cb 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1,4 +1,3 @@ - #include "../debug.h" #include "sod.h" #include "../opcodemgr.h" @@ -16,991 +15,2274 @@ #include #include -namespace SoD { +namespace SoD +{ + static const char *name = "SoD"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; -static const char *name = "SoD"; -static OpcodeManager *opcodes = nullptr; -static Strategy struct_strategy; + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); -char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + // server to client inventory location converters + static inline uint32 ServerToSoDSlot(uint32 ServerSlot); + static inline uint32 ServerToSoDCorpseSlot(uint32 ServerCorpse); -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; + // client to server inventory location converters + static inline uint32 SoDToServerSlot(uint32 SoDSlot); + static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse); + + 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); } } - //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 "sod_ops.h" } -} + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } - -Strategy::Strategy() -: StructStrategy() -{ - //all opcodes default to passthrough. - #include "ss_register.h" - #include "sod_ops.h" -} - -std::string Strategy::Describe() const { - std::string r; - r += "Patch "; - r += name; - return(r); -} - -const EQClientVersion Strategy::ClientVersion() const -{ - return EQClientSoD; -} + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientSoD; + } #include "ss_define.h" - -// Converts Server Slot IDs to SoD Slot IDs for use in Encodes -static inline uint32 ServerToSoDSlot(uint32 ServerSlot) { - uint32 SoDSlot = 0; - - if (ServerSlot >= MainAmmo && ServerSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots - SoDSlot = ServerSlot + 1; - - else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) - SoDSlot = ServerSlot + 11; - - else if (ServerSlot >= EmuConstants::BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) - SoDSlot = ServerSlot + 1; - - else if (ServerSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) - SoDSlot = ServerSlot + 1; - - else if (ServerSlot == MainPowerSource) - SoDSlot = slots::MainPowerSource; - - else - SoDSlot = ServerSlot; - - return SoDSlot; -} - -// Converts SoD Slot IDs to Server Slot IDs for use in Decodes -static inline uint32 SoDToServerSlot(uint32 SoDSlot) { - uint32 ServerSlot = 0; - - if(SoDSlot >= slots::MainAmmo && SoDSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots - ServerSlot = SoDSlot - 1; - - else if(SoDSlot >= consts::GENERAL_BAGS_BEGIN && SoDSlot <= consts::CURSOR_BAG_END) - ServerSlot = SoDSlot - 11; - - else if(SoDSlot >= consts::BANK_BAGS_BEGIN && SoDSlot <= consts::BANK_BAGS_END) - ServerSlot = SoDSlot - 1; - - else if(SoDSlot >= consts::SHARED_BANK_BAGS_BEGIN && SoDSlot <= consts::SHARED_BANK_BAGS_END) - ServerSlot = SoDSlot - 1; - - else if(SoDSlot == slots::MainPowerSource) - ServerSlot = MainPowerSource; - - else - ServerSlot = SoDSlot; - - return ServerSlot; -} - -/* -// Converts Server Corpse Slot IDs to SoD Corpse Slot IDs for use in Encodes -static inline uint32 ServerToSoDCorpseSlot(uint32 ServerCorpse) { - uint32 SoDCorpse; - // reserved -} -*/ -/* -// Converts SoD Corpse Slot IDs to Server Corpse Slot IDs for use in Decodes -static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse) { - uint32 ServerCorpse; - // reserved -} -*/ - - -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 Live 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_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; - eq2->level = emu->level[r]; - eq2->hairstyle = emu->hairstyle[r]; - eq2->gender = emu->gender[r]; - 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->beard = emu->beard[r]; - eq2->haircolor = emu->haircolor[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].itemid = 0; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; - } - eq2->primary = emu->primary[r]; - eq2->secondary = emu->secondary[r]; - eq2->tutorial = emu->tutorial[r]; // was u15 - eq2->u15 = 0xff; - eq2->deity = emu->deity[r]; - eq2->zone = emu->zone[r]; - eq2->u19 = 0xFF; - eq2->race = emu->race[r]; - eq2->gohome = emu->gohome[r]; - eq2->class_ = emu->class_[r]; - eq2->eyecolor1 = emu->eyecolor1[r]; - eq2->beardcolor = emu->beardcolor[r]; - eq2->eyecolor2 = emu->eyecolor2[r]; - eq2->drakkin_heritage = emu->drakkin_heritage[r]; - eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; - eq2->drakkin_details = emu->drakkin_details[r]; - } - bufptr += sizeof(structs::CharacterSelectEntry_Struct); - } - - FINISH_ENCODE(); - -} - -ENCODE(OP_ZoneServerInfo) { - SETUP_DIRECT_ENCODE(ZoneServerInfo_Struct, ZoneServerInfo_Struct); - OUT_str(ip); - OUT(port); - FINISH_ENCODE(); - - //this is SUCH bullshit to be doing from down here. but the - // new client requires us to close immediately following this - // packet, so do it. - //dest->Close(); -} - -//hack hack hack -ENCODE(OP_SendZonepoints) { - ENCODE_LENGTH_ATLEAST(ZonePoints); - - SETUP_VAR_ENCODE(ZonePoints); - ALLOC_VAR_ENCODE(structs::ZonePoints, __packet->size); - - memcpy(eq, emu, __packet->size); - - FINISH_ENCODE(); -// unknown0xxx[24]; - //this is utter crap... the client is waiting for this - //certain 0 length opcode to come after the reqclientspawn - //stuff... so this is a dirty way to put it in there. - // this needs to be done better - - //EQApplicationPacket hack_test(OP_PetitionUnCheckout, 0); - //dest->QueuePacket(&hack_test); - -} - -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 SoD - if (emu->clientver <= 5 ) +// ENCODE methods + ENCODE(OP_Action) { - 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)?0:(emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); + + OUT(target); + OUT(source); + OUT(level); + OUT(instrument_mod); + eq->sequence = emu->sequence; + OUT(type); + //OUT(damage); + OUT(spell); + eq->level2 = emu->level; + OUT(buff_unknown); // if this is 4, a buff icon is made + //eq->unknown0036 = -1; + //eq->unknown0040 = -1; + //eq->unknown0044 = -1; + + 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 = ServerToSoDSlot(emu->slot); + OUT(charges); + OUT(sell_price); + + FINISH_ENCODE(); + } + + ENCODE(OP_AltCurrencySell) + { + ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); + SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + OUT(merchant_entity_id); + eq->slot_id = ServerToSoDSlot(emu->slot_id); + OUT(charges); OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - 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); - } + + FINISH_ENCODE(); } - 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_PlayerProfile) { - SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); - - uint32 r; - - eq->available_slots=0xffffffff; - memset(eq->unknown4184, 0xff, sizeof(eq->unknown4184)); - memset(eq->unknown04396, 0xff, sizeof(eq->unknown04396)); - -// OUT(checksum); - OUT(gender); - OUT(race); - OUT(class_); -// OUT(unknown00016); - OUT(level); - eq->level1 = emu->level; -// OUT(unknown00022[2]); - for(r = 0; r < 5; r++) { - OUT(binds[r].zoneId); - OUT(binds[r].x); - OUT(binds[r].y); - OUT(binds[r].z); - OUT(binds[r].heading); - } - OUT(deity); - OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); - OUT(abilitySlotRefresh); - OUT(points); // Relocation Test -// OUT(unknown0166[4]); - OUT(haircolor); - OUT(beardcolor); - OUT(eyecolor1); - OUT(eyecolor2); - OUT(hairstyle); - OUT(beard); -// OUT(unknown00178[10]); - for(r = 0; r < 9; r++) { - eq->equipment[r].equip0 = emu->item_material[r]; - eq->equipment[r].equip1 = 0; - eq->equipment[r].itemId = 0; - //eq->colors[r].color = emu->colors[r].color; - } - for(r = 0; r < 7; r++) { - OUT(item_tint[r].color); - } -// OUT(unknown00224[48]); - //NOTE: new client supports 300 AAs, our internal rep/PP - //only supports 240.. - for(r = 0; r < MAX_PP_AA_ARRAY; r++) { - OUT(aa_array[r].AA); - OUT(aa_array[r].value); - } -// OUT(unknown02220[4]); - OUT(mana); - OUT(cur_hp); - OUT(STR); - OUT(STA); - OUT(CHA); - OUT(AGI); - OUT(INT); - OUT(DEX); - OUT(WIS); - OUT(face); -// OUT(unknown02264[47]); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); -// OUT(unknown4184[128]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); -// OUT(unknown04396[32]); - OUT(platinum); - OUT(gold); - OUT(silver); - OUT(copper); - OUT(platinum_cursor); - OUT(gold_cursor); - OUT(silver_cursor); - OUT(copper_cursor); - - OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) - -// OUT(unknown04760[236]); - OUT(toxicity); - OUT(thirst_level); - OUT(hunger_level); - for(r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); - OUT(buffs[r].level); - OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); - OUT(buffs[r].spellid); - OUT(buffs[r].duration); - OUT(buffs[r].counters); - OUT(buffs[r].player_id); - } - for(r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { - OUT(disciplines.values[r]); - } - OUT_array(recastTimers, structs::MAX_RECAST_TYPES); -// OUT(unknown08124[360]); - OUT(endurance); - OUT(aapoints_spent); - OUT(aapoints); -// OUT(unknown06160[4]); - //NOTE: new client supports 20 bandoliers, our internal rep - //only supports 4.. - for(r = 0; r < 4; r++) { - OUT_str(bandoliers[r].name); - uint32 k; - for(k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { - OUT(bandoliers[r].items[k].item_id); - OUT(bandoliers[r].items[k].icon); - OUT_str(bandoliers[r].items[k].item_name); - } - } -// OUT(unknown07444[5120]); - for(r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) { - OUT(potionbelt.items[r].item_id); - OUT(potionbelt.items[r].icon); - OUT_str(potionbelt.items[r].item_name); - } -// OUT(unknown12852[8]); -// OUT(unknown12864[76]); - OUT_str(name); - OUT_str(last_name); - OUT(guild_id); - OUT(birthday); - OUT(lastlogin); - OUT(timePlayedMin); - OUT(pvp); - OUT(anon); - OUT(gm); - OUT(guildrank); - OUT(guildbanker); -// OUT(unknown13054[12]); - OUT(exp); -// OUT(unknown13072[8]); - OUT(timeentitledonaccount); - OUT_array(languages, structs::MAX_PP_LANGUAGE); -// OUT(unknown13109[7]); - OUT(y); //reversed x and y - OUT(x); - OUT(z); - OUT(heading); -// OUT(unknown13132[4]); - OUT(platinum_bank); - OUT(gold_bank); - OUT(silver_bank); - OUT(copper_bank); - OUT(platinum_shared); -// OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 16383; -// OUT(unknown13244[12]); - OUT(autosplit); -// OUT(unknown13260[16]); - OUT(zone_id); - OUT(zoneInstance); - for(r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { - OUT_str(groupMembers[r]); - } - strcpy(eq->groupLeader, emu->groupMembers[0]); -// OUT_str(groupLeader); -// OUT(unknown13728[660]); - OUT(entityid); - OUT(leadAAActive); -// OUT(unknown14392[4]); - OUT(ldon_points_guk); - OUT(ldon_points_mir); - OUT(ldon_points_mmc); - OUT(ldon_points_ruj); - OUT(ldon_points_tak); - OUT(ldon_points_available); -// OUT(unknown14420[132]); - OUT(tribute_time_remaining); - OUT(career_tribute_points); -// OUT(unknown7208); - OUT(tribute_points); -// OUT(unknown7216); - OUT(tribute_active); - for(r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { - OUT(tributes[r].tribute); - OUT(tributes[r].tier); - } -// OUT(unknown14616[8]); - OUT(group_leadership_exp); -// OUT(unknown14628); - OUT(raid_leadership_exp); - OUT(group_leadership_points); - OUT(raid_leadership_points); - OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); -// OUT(unknown14772[128]); - OUT(air_remaining); - OUT(PVPKills); - OUT(PVPDeaths); - OUT(PVPCurrentPoints); - OUT(PVPCareerPoints); - OUT(PVPBestKillStreak); - OUT(PVPWorstDeathStreak); - OUT(PVPCurrentKillStreak); -// OUT(unknown17892[4580]); - OUT(expAA); -// OUT(unknown19516[40]); - OUT(currentRadCrystals); - OUT(careerRadCrystals); - OUT(currentEbonCrystals); - OUT(careerEbonCrystals); - OUT(groupAutoconsent); - OUT(raidAutoconsent); - OUT(guildAutoconsent); -// OUT(unknown19575[5]); - eq->level3 = emu->level; - eq->showhelm = emu->showhelm; - OUT(RestTimer); -// OUT(unknown19584[4]); -// OUT(unknown19588); - - -const uint8 bytes[] = { -0xa3,0x02,0x00,0x00,0x95,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x00,0x00, -0x19,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00, -0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1F,0x85,0xEB,0x3E,0x33,0x33,0x33,0x3F, -0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; - - memcpy(eq->unknown12864, bytes, sizeof(bytes)); - - - - //set the checksum... - CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct)-4); - - FINISH_ENCODE(); -} - -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); - /*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->FogDensity = emu->fog_density; - - FINISH_ENCODE(); -} - - -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) + ENCODE(OP_ApplyPoison) { - _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; + ENCODE_LENGTH_EXACT(ApplyPoison_Struct); + SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + eq->inventorySlot = ServerToSoDSlot(emu->inventorySlot); + OUT(success); + + FINISH_ENCODE(); } - 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) + ENCODE(OP_Barter) { - 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); - } + EQApplicationPacket *in = *p; + *p = nullptr; - delete[] __emu_buffer; + char *Buffer = (char *)in->pBuffer; + uint32 SubAction = VARSTRUCT_DECODE_TYPE(uint32, Buffer); - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_PetBuffWindow) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - unsigned char *__emu_buffer = in->pBuffer; - - PetBuff_Struct *emu = (PetBuff_Struct *) __emu_buffer; - - int PacketSize = 7 + (emu->buffcount * 13); - - in->size = PacketSize; - - in->pBuffer = new unsigned char[in->size]; - - char *Buffer = (char *)in->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petid); - VARSTRUCT_ENCODE_TYPE(uint16, Buffer, emu->buffcount); - - for(unsigned int i = 0; i < BUFF_COUNT; ++i) - { - if(emu->spellid[i]) + if (SubAction != Barter_BuyerAppearance) { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, i); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spellid[i]); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->ticsremaining[i]); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string. Name of the caster of the buff. + dest->FastQueuePacket(&in, ack_req); + + return; } - } - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); - delete[] __emu_buffer; + unsigned char *__emu_buffer = in->pBuffer; + in->size = 80; + in->pBuffer = new unsigned char[in->size]; + char *OutBuffer = (char *)in->pBuffer; + char Name[64]; - dest->FastQueuePacket(&in, ack_req); -} + 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); -ENCODE(OP_Barter) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - char *Buffer = (char *)in->pBuffer; - - uint32 SubAction = VARSTRUCT_DECODE_TYPE(uint32, Buffer); - - if(SubAction != Barter_BuyerAppearance) - { + delete[] __emu_buffer; 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_InspectRequest) { - ENCODE_LENGTH_EXACT(Inspect_Struct); - SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - OUT(TargetID); - OUT(PlayerID); - FINISH_ENCODE(); -} - -DECODE(OP_InspectRequest) { - DECODE_LENGTH_EXACT(structs::Inspect_Struct); - SETUP_DIRECT_DECODE(Inspect_Struct, structs::Inspect_Struct); - IN(TargetID); - IN(PlayerID); - FINISH_DIRECT_DECODE(); -} - -ENCODE(OP_BazaarSearch) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - char *Buffer = (char *)in->pBuffer; - - uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); - - if(SubAction != BazaarSearchResults) + 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); - - 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) + ENCODE(OP_Buff) { - _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; + ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); + SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + + OUT(entityid); + OUT(slot); + OUT(level); + OUT(effect); + //eq->unknown7 = 10; + OUT(spellid); + OUT(duration); + OUT(slotid); + OUT(bufffade); + + FINISH_ENCODE(); } - 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) + ENCODE(OP_CancelTrade) { - 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); + ENCODE_LENGTH_EXACT(CancelTrade_Struct); + SETUP_DIRECT_ENCODE(CancelTrade_Struct, structs::CancelTrade_Struct); + + OUT(fromid); + OUT(action); + + FINISH_ENCODE(); } - delete[] __emu_buffer; + ENCODE(OP_CharInventory) + { + //consume the packet + EQApplicationPacket *in = *p; - dest->FastQueuePacket(&in, ack_req); -} + *p = nullptr; -ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneSpawns) { + 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_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 = ServerToSoDSlot(emu->from_slot); + eq->to_slot = ServerToSoDSlot(emu->to_slot); + OUT(number_in_stack); + + 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; + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->leader_name, emu->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); + + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->player_name, emu->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_GroundSpawn) + { + ENCODE_LENGTH_EXACT(Object_Struct); + SETUP_DIRECT_ENCODE(Object_Struct, structs::Object_Struct); + + OUT(drop_id); + OUT(zone_id); + OUT(zone_instance); + OUT(heading); + OUT(x); + OUT(y); + OUT(z); + OUT_str(object_name); + OUT(object_type); + OUT(spawn_id); + + /*fill in some unknowns with observed values, hopefully it will help */ + eq->unknown020 = 0; + eq->unknown024 = 0; + eq->size = 1; //This forces all objects to standard size for now + eq->unknown088 = 0; + memset(eq->unknown096, 0xFF, sizeof(eq->unknown096)); + + FINISH_ENCODE(); + } + + 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; - Spawn_Struct *emu = (Spawn_Struct *) __emu_buffer; + 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++; + + //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) \ + strcpy(e->field, str.c_str()); \ + e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ +#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_); + PutFieldN(rank); + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + 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); +#undef SlideStructString +#undef PutFieldN + + e++; + } + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + 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); + + 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_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 = ServerToSoDSlot(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); + + strcpy(eq->worldshortname, emu->worldshortname); + + OUT(enablevoicemacros); + OUT(enablemail); + OUT(enable_pvp); + OUT(enable_FV); + + // These next two need to be set like this for the Tutorial Button to work. + eq->unknown263[0] = 0; + eq->unknown263[2] = 1; + + 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 = emu->slot_id + 1; + 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) - 4) * 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++) + { + if (emu->MercTypeCount > 0) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercGrades[r]); + } + } + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); + + if (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].AltCurrencyCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyUpkeep); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].StanceCount); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->Mercs[r].TimeLeft); + if (emu->Mercs[r].StanceCount > 0) + { + 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; + } + + // This packet does not appear to exist in SoD, but leaving it here just in case + 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; + } + + 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].AltCurrencyCost); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyUpkeep); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyType); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].StanceCount); + VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].TimeLeft); + 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, emu->MercData[r].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 = ServerToSoDSlot(emu->from_slot); + eq->to_slot = ServerToSoDSlot(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); + /*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->FogDensity = emu->fog_density; + + FINISH_ENCODE(); + } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + memcpy(eq->Title, emu->Title, sizeof(eq->Title)); + 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. + OUT_str(ButtonName0); + 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 Live 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) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + PetBuff_Struct *emu = (PetBuff_Struct *)__emu_buffer; + int PacketSize = 7 + (emu->buffcount * 13); + in->size = PacketSize; + in->pBuffer = new unsigned char[in->size]; + char *Buffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petid); + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, emu->buffcount); + + for (unsigned int i = 0; i < BUFF_COUNT; ++i) + { + if (emu->spellid[i]) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, i); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spellid[i]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->ticsremaining[i]); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string. Name of the caster of the buff. + } + } + + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_PlayerProfile) + { + SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); + + uint32 r; + + eq->available_slots = 0xffffffff; + memset(eq->unknown4184, 0xff, sizeof(eq->unknown4184)); + memset(eq->unknown04396, 0xff, sizeof(eq->unknown04396)); + + // OUT(checksum); + OUT(gender); + OUT(race); + OUT(class_); + // OUT(unknown00016); + OUT(level); + eq->level1 = emu->level; + // OUT(unknown00022[2]); + for (r = 0; r < 5; r++) { + OUT(binds[r].zoneId); + OUT(binds[r].x); + OUT(binds[r].y); + OUT(binds[r].z); + OUT(binds[r].heading); + } + OUT(deity); + OUT(intoxication); + OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT(abilitySlotRefresh); + OUT(points); // Relocation Test + // OUT(unknown0166[4]); + OUT(haircolor); + OUT(beardcolor); + OUT(eyecolor1); + OUT(eyecolor2); + OUT(hairstyle); + OUT(beard); + // OUT(unknown00178[10]); + for (r = 0; r < 9; r++) { + eq->equipment[r].equip0 = emu->item_material[r]; + eq->equipment[r].equip1 = 0; + eq->equipment[r].itemId = 0; + //eq->colors[r].color = emu->colors[r].color; + } + for (r = 0; r < 7; r++) { + OUT(item_tint[r].color); + } + // OUT(unknown00224[48]); + //NOTE: new client supports 300 AAs, our internal rep/PP + //only supports 240.. + for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + OUT(aa_array[r].AA); + OUT(aa_array[r].value); + } + // OUT(unknown02220[4]); + OUT(mana); + OUT(cur_hp); + OUT(STR); + OUT(STA); + OUT(CHA); + OUT(AGI); + OUT(INT); + OUT(DEX); + OUT(WIS); + OUT(face); + // OUT(unknown02264[47]); + OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + // OUT(unknown4184[128]); + OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + // OUT(unknown04396[32]); + OUT(platinum); + OUT(gold); + OUT(silver); + OUT(copper); + OUT(platinum_cursor); + OUT(gold_cursor); + OUT(silver_cursor); + OUT(copper_cursor); + + OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) + + // OUT(unknown04760[236]); + OUT(toxicity); + OUT(thirst_level); + OUT(hunger_level); + for (r = 0; r < structs::BUFF_COUNT; r++) { + OUT(buffs[r].slotid); + OUT(buffs[r].level); + OUT(buffs[r].bard_modifier); + OUT(buffs[r].effect); + OUT(buffs[r].spellid); + OUT(buffs[r].duration); + OUT(buffs[r].counters); + OUT(buffs[r].player_id); + } + for (r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { + OUT(disciplines.values[r]); + } + OUT_array(recastTimers, structs::MAX_RECAST_TYPES); + // OUT(unknown08124[360]); + OUT(endurance); + OUT(aapoints_spent); + OUT(aapoints); + // OUT(unknown06160[4]); + //NOTE: new client supports 20 bandoliers, our internal rep + //only supports 4.. + for (r = 0; r < 4; r++) { + OUT_str(bandoliers[r].name); + uint32 k; + for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { + OUT(bandoliers[r].items[k].item_id); + OUT(bandoliers[r].items[k].icon); + OUT_str(bandoliers[r].items[k].item_name); + } + } + // OUT(unknown07444[5120]); + for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) { + OUT(potionbelt.items[r].item_id); + OUT(potionbelt.items[r].icon); + OUT_str(potionbelt.items[r].item_name); + } + // OUT(unknown12852[8]); + // OUT(unknown12864[76]); + OUT_str(name); + OUT_str(last_name); + OUT(guild_id); + OUT(birthday); + OUT(lastlogin); + OUT(timePlayedMin); + OUT(pvp); + OUT(anon); + OUT(gm); + OUT(guildrank); + OUT(guildbanker); + // OUT(unknown13054[12]); + OUT(exp); + // OUT(unknown13072[8]); + OUT(timeentitledonaccount); + OUT_array(languages, structs::MAX_PP_LANGUAGE); + // OUT(unknown13109[7]); + OUT(y); //reversed x and y + OUT(x); + OUT(z); + OUT(heading); + // OUT(unknown13132[4]); + OUT(platinum_bank); + OUT(gold_bank); + OUT(silver_bank); + OUT(copper_bank); + OUT(platinum_shared); + // OUT(unknown13156[84]); + //OUT(expansions); + eq->expansions = 16383; + // OUT(unknown13244[12]); + OUT(autosplit); + // OUT(unknown13260[16]); + OUT(zone_id); + OUT(zoneInstance); + for (r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { + OUT_str(groupMembers[r]); + } + strcpy(eq->groupLeader, emu->groupMembers[0]); + // OUT_str(groupLeader); + // OUT(unknown13728[660]); + OUT(entityid); + OUT(leadAAActive); + // OUT(unknown14392[4]); + OUT(ldon_points_guk); + OUT(ldon_points_mir); + OUT(ldon_points_mmc); + OUT(ldon_points_ruj); + OUT(ldon_points_tak); + OUT(ldon_points_available); + // OUT(unknown14420[132]); + OUT(tribute_time_remaining); + OUT(career_tribute_points); + // OUT(unknown7208); + OUT(tribute_points); + // OUT(unknown7216); + OUT(tribute_active); + for (r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { + OUT(tributes[r].tribute); + OUT(tributes[r].tier); + } + // OUT(unknown14616[8]); + OUT(group_leadership_exp); + // OUT(unknown14628); + OUT(raid_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_points); + OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); + // OUT(unknown14772[128]); + OUT(air_remaining); + OUT(PVPKills); + OUT(PVPDeaths); + OUT(PVPCurrentPoints); + OUT(PVPCareerPoints); + OUT(PVPBestKillStreak); + OUT(PVPWorstDeathStreak); + OUT(PVPCurrentKillStreak); + // OUT(unknown17892[4580]); + OUT(expAA); + // OUT(unknown19516[40]); + OUT(currentRadCrystals); + OUT(careerRadCrystals); + OUT(currentEbonCrystals); + OUT(careerEbonCrystals); + OUT(groupAutoconsent); + OUT(raidAutoconsent); + OUT(guildAutoconsent); + // OUT(unknown19575[5]); + eq->level3 = emu->level; + eq->showhelm = emu->showhelm; + OUT(RestTimer); + // OUT(unknown19584[4]); + // OUT(unknown19588); + + const uint8 bytes[] = { + 0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + memcpy(eq->unknown12864, bytes, sizeof(bytes)); + + //set the checksum... + CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); + + FINISH_ENCODE(); + } + + 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 + { + 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); + eq->invslot = ServerToSoDSlot(emu->invslot); + strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); + + 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 SoD + 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) ? 0 : (emu->sof_next_skill); + eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (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); + OUT(prereq_skill); + OUT(prereq_minpoints); + eq->type = emu->sof_type; + OUT(spellid); + 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); + } + } + + 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; + eq2->level = emu->level[r]; + eq2->hairstyle = emu->hairstyle[r]; + eq2->gender = emu->gender[r]; + 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->beard = emu->beard[r]; + eq2->haircolor = emu->haircolor[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].itemid = 0; + eq2->equip[k].color.color = emu->cs_colors[r][k].color; + } + eq2->primary = emu->primary[r]; + eq2->secondary = emu->secondary[r]; + eq2->tutorial = emu->tutorial[r]; // was u15 + eq2->u15 = 0xff; + eq2->deity = emu->deity[r]; + eq2->zone = emu->zone[r]; + eq2->u19 = 0xFF; + eq2->race = emu->race[r]; + eq2->gohome = emu->gohome[r]; + eq2->class_ = emu->class_[r]; + eq2->eyecolor1 = emu->eyecolor1[r]; + eq2->beardcolor = emu->beardcolor[r]; + eq2->eyecolor2 = emu->eyecolor2[r]; + eq2->drakkin_heritage = emu->drakkin_heritage[r]; + eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; + eq2->drakkin_details = emu->drakkin_details[r]; + } + bufptr += sizeof(structs::CharacterSelectEntry_Struct); + } + + FINISH_ENCODE(); + } + + //hack hack hack + ENCODE(OP_SendZonepoints) + { + ENCODE_LENGTH_ATLEAST(ZonePoints); + SETUP_VAR_ENCODE(ZonePoints); + ALLOC_VAR_ENCODE(structs::ZonePoints, __packet->size); + + memcpy(eq, emu, __packet->size); + + FINISH_ENCODE(); + // unknown0xxx[24]; + //this is utter crap... the client is waiting for this + //certain 0 length opcode to come after the reqclientspawn + //stuff... so this is a dirty way to put it in there. + // this needs to be done better + + //EQApplicationPacket hack_test(OP_PetitionUnCheckout, 0); + //dest->QueuePacket(&hack_test); + } + + 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 = ServerToSoDSlot(emu->itemslot); + OUT(quantity); + OUT(price); + + 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); + + strcpy(eq->model_name, emu->model_name); + + FINISH_ENCODE(); + } + + 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++) { + strcpy(eq[r].name, emu[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].unknown0076 = 0; + eq[r].unknown0077 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0078 = 0; + eq[r].unknown0079 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0080 = 0; + eq[r].unknown0081 = 0; + eq[r].unknown0082 = 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) + { + SETUP_VAR_ENCODE(BuffIcon_Struct); + + uint32 sz = 7 + (13 * emu->count); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); + + uchar *ptr = __packet->pBuffer; + *((uint32*)ptr) = emu->entity_id; + ptr += sizeof(uint32); + + *((uint16*)ptr) = emu->count; + ptr += sizeof(uint16); + + for (uint16 i = 0; i < emu->count; ++i) + { + *((uint32*)ptr) = emu->entries[i].buff_slot; + ptr += sizeof(uint32); + *((uint32*)ptr) = emu->entries[i].spell_id; + ptr += sizeof(uint32); + *((uint32*)ptr) = emu->entries[i].tics_remaining; + ptr += sizeof(uint32); + ptr += 1; + } + /*std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + + uint8 write_var8 = 1; + ss.write((const char*)&emu->entity_id, sizeof(uint32)); + ss.write((const char*)&emu->count, sizeof(uint16)); + write_var8 = 0; + for(uint16 i = 0; i < emu->count; ++i) + { + ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32)); + ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32)); + ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32)); + ss.write((const char*)&write_var8, sizeof(uint8)); + } + + __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_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(TraderBuy_Struct)) { + EQApplicationPacket *in = *p; + *p = nullptr; + dest->FastQueuePacket(&in, ack_req); + return; + } + + 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_TributeItem) + { + ENCODE_LENGTH_EXACT(TributeItem_Struct); + SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); + + eq->slot = ServerToSoDSlot(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; + strcpy(vr->items[x].item_name, ivr->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(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; + + 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_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 = zps->bind_zone_id; + zph->bind_instance_id = zps->bind_instance_id; + strcpy(zph->zone_name, zps->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(); + + //this is SUCH bullshit to be doing from down here. but the + // new client requires us to close immediately following this + // packet, so do it. + //dest->Close(); + } + + 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) { + 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; + emu = (Spawn_Struct *)__emu_buffer; //_log(NET__STRUCTS, "Spawn packet size is %i, entries = %i", in->size, entrycount); - char *Buffer = (char *) in->pBuffer; - + char *Buffer = (char *)in->pBuffer; int r; int k; - for(r = 0; r < entrycount; r++, emu++) { + for (r = 0; r < entrycount; r++, emu++) { int PacketSize = sizeof(structs::Spawn_Struct); PacketSize += strlen(emu->name); PacketSize += strlen(emu->lastName); - if(strlen(emu->title)) + if (strlen(emu->title)) PacketSize += strlen(emu->title) + 1; - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - if(emu->DestructibleObject) + if (emu->DestructibleObject) { PacketSize = PacketSize - 4; // No bodytype PacketSize += 53; // Fixed portion @@ -1010,7 +2292,7 @@ ENCODE(OP_ZoneSpawns) { } bool ShowName = 1; - if(emu->bodytype >= 66) + if (emu->bodytype >= 66) { emu->race = 127; emu->bodytype = 11; @@ -1019,30 +2301,30 @@ ENCODE(OP_ZoneSpawns) { } float SpawnSize = emu->size; - if(!((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { PacketSize -= (sizeof(structs::EquipStruct) * 9); - if(emu->size == 0) + if (emu->size == 0) { emu->size = 6; SpawnSize = 6; } } - if(SpawnSize == 0) + if (SpawnSize == 0) { SpawnSize = 3; } EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); - Buffer = (char *) outapp->pBuffer; + Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000 } @@ -1073,10 +2355,10 @@ ENCODE(OP_ZoneSpawns) { Bitfields->showname = ShowName; - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x1d600000); - Buffer = Buffer -4; + Buffer = Buffer - 4; } Bitfields->ispet = emu->is_pet; @@ -1085,18 +2367,18 @@ ENCODE(OP_ZoneSpawns) { uint8 OtherData = 0; - if(strlen(emu->title)) + if (strlen(emu->title)) OtherData = OtherData | 0x04; - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) OtherData = OtherData | 0x08; - if(emu->DestructibleObject) + if (emu->DestructibleObject) OtherData = OtherData | 0xd1; // Live has 0xe1 for OtherData VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); } @@ -1106,7 +2388,7 @@ ENCODE(OP_ZoneSpawns) { } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); @@ -1138,15 +2420,15 @@ ENCODE(OP_ZoneSpawns) { /* if(emu->bodytype >=66) { - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // showname + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // showname } else { - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // showname + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // showname }*/ - if(!emu->DestructibleObject) + if (!emu->DestructibleObject) { // 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. @@ -1170,7 +2452,7 @@ ENCODE(OP_ZoneSpawns) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity); - if(emu->NPC) + if (emu->NPC) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xFFFFFFFF); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); @@ -1216,9 +2498,9 @@ ENCODE(OP_ZoneSpawns) { Buffer += sizeof(structs::Spawn_Struct_Position); - if((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu ->race == 130) || (emu->race == 330) || (emu->race == 522)) + 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) + for (k = 0; k < 9; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color); @@ -1241,11 +2523,11 @@ ENCODE(OP_ZoneSpawns) { } - if((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; - for(k = 0; k < 9; k++) { + for (k = 0; k < 9; k++) { Equipment[k].equip0 = emu->equipment[k]; Equipment[k].equip1 = 0; Equipment[k].itemId = 0; @@ -1253,12 +2535,12 @@ ENCODE(OP_ZoneSpawns) { Buffer += (sizeof(structs::EquipStruct) * 9); } - if(strlen(emu->title)) + if (strlen(emu->title)) { VARSTRUCT_ENCODE_STRING(Buffer, emu->title); } - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) { VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix); } @@ -1269,2294 +2551,1077 @@ ENCODE(OP_ZoneSpawns) { Buffer += 24; // Unknown; dest->FastQueuePacket(&outapp, ack_req); - } - - delete in; -} - -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) - 4) * 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++) - { - if(emu->MercTypeCount > 0) - { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercGrades[r]); } - } - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercCount); - - if(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].AltCurrencyCost); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyUpkeep); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].AltCurrencyType); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->Mercs[r].StanceCount); - VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->Mercs[r].TimeLeft); - if(emu->Mercs[r].StanceCount > 0) - { - 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; -} - -// This packet does not appear to exist in SoD, but leaving it here just in case -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; - } - - 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].AltCurrencyCost); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyUpkeep); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].AltCurrencyType); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->MercData[r].StanceCount); - VARSTRUCT_ENCODE_TYPE(int32, Buffer, emu->MercData[r].TimeLeft); - 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, emu->MercData[r].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_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_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_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++; - - //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) \ - strcpy(e->field, str.c_str()); \ - e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ -#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_); - PutFieldN(rank); - PutFieldN(time_last_on); - PutFieldN(tribute_enable); - 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); - - -#undef SlideStructString -#undef PutFieldN - - e++; - } - } - - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - - -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++) { - strcpy(eq[r].name, emu[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].unknown0076 = 0; - eq[r].unknown0077 = 1; // Both must be 1 to allow clicking doors - eq[r].unknown0078 = 0; - eq[r].unknown0079 = 1; // Both must be 1 to allow clicking doors - eq[r].unknown0080 = 0; - eq[r].unknown0081 = 0; - eq[r].unknown0082 = 0; - } - FINISH_ENCODE(); -} - -ENCODE(OP_GroundSpawn) { - ENCODE_LENGTH_EXACT(Object_Struct); - SETUP_DIRECT_ENCODE(Object_Struct, structs::Object_Struct); - OUT(drop_id); - OUT(zone_id); - OUT(zone_instance); - OUT(heading); - OUT(x); - OUT(y); - OUT(z); - OUT_str(object_name); - OUT(object_type); - OUT(spawn_id); - - /*fill in some unknowns with observed values, hopefully it will help */ - eq->unknown020 = 0; - eq->unknown024 = 0; - eq->size = 1; //This forces all objects to standard size for now - eq->unknown088 = 0; - memset(eq->unknown096, 0xFF, sizeof(eq->unknown096)); - 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_OnLevelMessage) -{ - ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); - SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); - memcpy(eq->Title, emu->Title, sizeof(eq->Title)); - 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. - OUT_str(ButtonName0); - OUT_str(ButtonName1); - 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); - - 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_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_ExpansionInfo) { - ENCODE_LENGTH_EXACT(ExpansionInfo_Struct); - SETUP_DIRECT_ENCODE(ExpansionInfo_Struct, structs::ExpansionInfo_Struct); - OUT(Expansions); - FINISH_ENCODE(); -} - -ENCODE(OP_LogServer) { - ENCODE_LENGTH_EXACT(LogServer_Struct); - SETUP_DIRECT_ENCODE(LogServer_Struct, structs::LogServer_Struct); - strcpy(eq->worldshortname, emu->worldshortname); - - OUT(enablevoicemacros); - OUT(enablemail); - OUT(enable_pvp); - OUT(enable_FV); - - // These next two need to be set like this for the Tutorial Button to work. - eq->unknown263[0] = 0; - eq->unknown263[2] = 1; - - 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_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_Action) { - ENCODE_LENGTH_EXACT(Action_Struct); - SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); - OUT(target); - OUT(source); - OUT(level); - OUT(instrument_mod); - eq->sequence = emu->sequence; - OUT(type); - //OUT(damage); - OUT(spell); - eq->level2 = emu->level; - OUT(buff_unknown); // if this is 4, a buff icon is made - //eq->unknown0036 = -1; - //eq->unknown0040 = -1; - //eq->unknown0044 = -1; - FINISH_ENCODE(); -} - -ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); - OUT(entityid); - OUT(slot); - OUT(level); - OUT(effect); - //eq->unknown7 = 10; - OUT(spellid); - OUT(duration); - OUT(slotid); - OUT(bufffade); - 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_ShopPlayerSell) { - ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); - SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); - OUT(npcid); - eq->itemslot = ServerToSoDSlot(emu->itemslot); - OUT(quantity); - OUT(price); - FINISH_ENCODE(); -} - -ENCODE(OP_ApplyPoison) { - ENCODE_LENGTH_EXACT(ApplyPoison_Struct); - SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - eq->inventorySlot = ServerToSoDSlot(emu->inventorySlot); - OUT(success); - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteItem) { - ENCODE_LENGTH_EXACT(DeleteItem_Struct); - SETUP_DIRECT_ENCODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - eq->from_slot = ServerToSoDSlot(emu->from_slot); - eq->to_slot = ServerToSoDSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } -ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToSoDSlot(emu->from_slot); - eq->to_slot = ServerToSoDSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_ItemVerifyReply) { - ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); - SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - - eq->slot = ServerToSoDSlot(emu->slot); - OUT(spell); - OUT(target); - - FINISH_ENCODE(); -} - -ENCODE(OP_Trader) { - - if((*p)->size != sizeof(TraderBuy_Struct)) { - EQApplicationPacket *in = *p; - *p = nullptr; - dest->FastQueuePacket(&in, ack_req); - return; - } - 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_LootItem) { - - ENCODE_LENGTH_EXACT(LootingItem_Struct); - SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - OUT(lootee); - OUT(looter); - eq->slot_id = emu->slot_id + 1; - OUT(auto_loot); - - FINISH_ENCODE(); -} - -ENCODE(OP_TributeItem) { - ENCODE_LENGTH_EXACT(TributeItem_Struct); - SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); - - eq->slot = ServerToSoDSlot(emu->slot); - OUT(quantity); - OUT(tribute_master_id); - OUT(tribute_points); - - 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); - - strcpy(eq->model_name, emu->model_name); - - FINISH_ENCODE(); -} - -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); - eq->invslot = ServerToSoDSlot(emu->invslot); - strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); - 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_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 = zps->bind_zone_id; - zph->bind_instance_id = zps->bind_instance_id; - strcpy(zph->zone_name, zps->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_AdventureMerchantSell) { - ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); - SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - eq->unknown000 = 1; - OUT(npcid); - eq->slot = ServerToSoDSlot(emu->slot); - OUT(charges); - OUT(sell_price); - - FINISH_ENCODE(); -} - -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 +// DECODE methods + DECODE(OP_AdventureMerchantSell) { - RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; + DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); + SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); - structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; + IN(npcid); + emu->slot = SoDToServerSlot(eq->slot); + IN(charges); + IN(sell_price); - 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 - { - 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_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_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; - strcpy(vr->items[x].item_name, ivr->items[x].item_name); - vr->items[x].charges = ivr->items[x].charges; - } - - old_data += sizeof(InternalVeteranReward); - data += sizeof(structs::VeteranReward); + FINISH_DIRECT_DECODE(); } - dest->FastQueuePacket(&outapp_create); - delete inapp; -} - -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; - - memcpy(OutBuffer, InBuffer, sizeof(WhoAllReturnStruct)); - - OutBuffer += sizeof(WhoAllReturnStruct); - InBuffer += sizeof(WhoAllReturnStruct); - - for(int i = 0; i < Count; ++i) + DECODE(OP_AltCurrencySell) { - uint32 x; + DECODE_LENGTH_EXACT(structs::AltCurrencySellItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + IN(merchant_entity_id); + emu->slot_id = SoDToServerSlot(eq->slot_id); + IN(charges); + IN(cost); - 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); + FINISH_DIRECT_DECODE(); } - //_hex(NET__ERROR, outapp->pBuffer, outapp->size); - dest->FastQueuePacket(&outapp); - - delete in; -} - -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_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_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_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; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); - 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) + DECODE(OP_AltCurrencySellSelection) { - OUT(entries[i].x); - OUT(entries[i].y); - OUT(entries[i].z); + DECODE_LENGTH_EXACT(structs::AltCurrencySelectItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); + + IN(merchant_entity_id); + emu->slot_id = SoDToServerSlot(eq->slot_id); + + FINISH_DIRECT_DECODE(); } - 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) + DECODE(OP_ApplyPoison) { - 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)); + DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); + SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + emu->inventorySlot = SoDToServerSlot(eq->inventorySlot); + IN(success); + + FINISH_DIRECT_DECODE(); } - __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_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) + DECODE(OP_AugmentInfo) { - 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)); + DECODE_LENGTH_EXACT(structs::AugmentInfo_Struct); + SETUP_DIRECT_DECODE(AugmentInfo_Struct, structs::AugmentInfo_Struct); + + IN(itemid); + IN(window); + + FINISH_DIRECT_DECODE(); } - __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_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_DzJoinExpeditionConfirm) -{ - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - FINISH_ENCODE(); -} - -ENCODE(OP_TargetBuffs) -{ - SETUP_VAR_ENCODE(BuffIcon_Struct); - - uint32 sz = 7 + (13 * emu->count); - __packet->size = sz; - __packet->pBuffer = new unsigned char[sz]; - memset(__packet->pBuffer, 0, sz); - - uchar *ptr = __packet->pBuffer; - *((uint32*)ptr) = emu->entity_id; - ptr += sizeof(uint32); - - *((uint16*)ptr) = emu->count; - ptr += sizeof(uint16); - - for(uint16 i = 0; i < emu->count; ++i) + DECODE(OP_AugmentItem) { - *((uint32*)ptr) = emu->entries[i].buff_slot; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].spell_id; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].tics_remaining; - ptr += sizeof(uint32); - ptr += 1; - } - /*std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); + SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); - uint8 write_var8 = 1; - ss.write((const char*)&emu->entity_id, sizeof(uint32)); - ss.write((const char*)&emu->count, sizeof(uint16)); - write_var8 = 0; - for(uint16 i = 0; i < emu->count; ++i) - { - ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32)); - ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32)); - ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32)); - ss.write((const char*)&write_var8, sizeof(uint8)); + emu->container_slot = SoDToServerSlot(eq->container_slot); + emu->augment_slot = eq->augment_slot; + + FINISH_DIRECT_DECODE(); } - __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_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)) + DECODE(OP_BazaarSearch) { - if((gjs->action == groupActDisband) || !strcmp(gjs->yourname, gjs->membername)) - { - //_log(NET__ERROR, "Group Leave, yourname = %s, membername = %s", gjs->yourname, gjs->membername); + char *Buffer = (char *)__packet->pBuffer; - 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; + uint8 SubAction = VARSTRUCT_DECODE_TYPE(uint8, Buffer); + if ((SubAction != BazaarInspectItem) || (__packet->size != sizeof(structs::NewBazaarInspect_Struct))) 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; + 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(); } - if(in->size == sizeof(GroupUpdate2_Struct)) + DECODE(OP_Buff) { - // Group Update2 - //_log(NET__ERROR, "Struct is GroupUpdate2"); + DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct); + SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); - unsigned char *__emu_buffer = in->pBuffer; - GroupUpdate2_Struct *gu2 = (GroupUpdate2_Struct*) __emu_buffer; + IN(entityid); + IN(slot); + IN(level); + IN(effect); + IN(spellid); + IN(duration); + IN(slotid); + IN(bufffade); - //_log(NET__ERROR, "Yourname is %s", gu2->yourname); + FINISH_DIRECT_DECODE(); + } - int MemberCount = 1; + DECODE(OP_Bug) + { + DECODE_LENGTH_EXACT(structs::BugStruct); + SETUP_DIRECT_DECODE(BugStruct, structs::BugStruct); - int PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; + strn0cpy(emu->chartype, eq->chartype, sizeof(emu->chartype)); + strn0cpy(emu->name, eq->name, sizeof(emu->name)); + strn0cpy(emu->ui, eq->ui, sizeof(emu->ui)); + IN(x); + IN(y); + IN(z); + IN(heading); + strn0cpy(emu->target_name, eq->target_name, sizeof(emu->target_name)); + strn0cpy(emu->bug, eq->bug, sizeof(emu->bug)); + strn0cpy(emu->system_info, eq->system_info, sizeof(emu->system_info)); - for(int i = 0; i < 5; ++i) + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_CastSpell) + { + DECODE_LENGTH_EXACT(structs::CastSpell_Struct); + SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); + + IN(slot); + IN(spell_id); + emu->inventoryslot = SoDToServerSlot(eq->inventoryslot); + IN(target_id); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_CharacterCreate) + { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(class_); + IN(beardcolor); + IN(beard); + IN(hairstyle); + IN(gender); + IN(race); + + if (RuleB(World, EnableTutorialButton) && eq->tutorial) + emu->start_zone = RuleI(World, TutorialZoneID); + else + emu->start_zone = eq->start_zone; + + IN(haircolor); + IN(deity); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); + + 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 = SoDToServerSlot(eq->slot); + IN(auto_consumed); + IN(type); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DeleteItem) + { + DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); + SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); + + emu->from_slot = SoDToServerSlot(eq->from_slot); + emu->to_slot = SoDToServerSlot(eq->to_slot); + IN(number_in_stack); + + 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_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_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]); + } + 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 = SoDToServerSlot(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 (uint32 i = 0; i < MAX_PP_MEMSPELL; ++i) + 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 = eq->slot_id - 1; + 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, eq->to_slot); + + emu->from_slot = SoDToServerSlot(eq->from_slot); + emu->to_slot = SoDToServerSlot(eq->to_slot); + IN(number_in_stack); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RaidInvite) + { + 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(); + } + + DECODE(OP_ReadBook) + { + DECODE_LENGTH_EXACT(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(type); + emu->invslot = SoDToServerSlot(eq->invslot); + emu->window = (uint8)eq->window; + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + 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++) { + 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 = SoDToServerSlot(eq->itemslot); + IN(quantity); + IN(price); + + 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); + + emu->container_slot = SoDToServerSlot(eq->container_slot); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TributeItem) + { + DECODE_LENGTH_EXACT(structs::TributeItem_Struct); + SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); + + emu->slot = SoDToServerSlot(eq->slot); + IN(quantity); + IN(tribute_master_id); + IN(tribute_points); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_WearChange) + { + DECODE_LENGTH_EXACT(structs::WearChange_Struct); + SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); + + IN(spawn_id); + IN(material); + IN(unknown06); + IN(elite_material); + IN(color.color); + IN(wear_slot_id); + emu->hero_forge_model = 0; + emu->unknown18 = 0; + + 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(); + } + +// 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) + { + 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->GetItem(); + //_log(NET__ERROR, "Serialize called for: %s", item->Name); + SoD::structs::ItemSerializationHeader hdr; + hdr.stacksize = stackable ? charges : 1; + hdr.unknown004 = 0; + + int32 slot_id = ServerToSoDSlot(slot_id_in); + + hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.price = inst->GetPrice(); + hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); + hdr.unknown020 = 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.unknown056 = 0; + hdr.unknown060 = 0; + hdr.unknown061 = 0; + hdr.unknown062 = 0; + hdr.ItemClass = item->ItemClass; + + ss.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); + + if (strlen(item->Name) > 0) { - //_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; + 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)); + } + + SoD::structs::ItemBodyStruct ibs; + memset(&ibs, 0, sizeof(SoD::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.unknown6 = 0; + ibs.SkillModType = item->SkillModType; + 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; + ibs.RecLevel = item->RecLevel; + 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.ItemType = item->ItemType; + ibs.Material = item->Material; + ibs.unknown7 = 0; + ibs.EliteMaterial = item->EliteMaterial; + 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.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(SoD::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)); + } + + SoD::structs::ItemSecondaryBodyStruct isbs; + memset(&isbs, 0, sizeof(SoD::structs::ItemSecondaryBodyStruct)); + + isbs.augtype = item->AugType; + isbs.augrestrict = item->AugRestrict; + + for (int x = 0; x < 5; ++x) + { + isbs.augslots[x].type = item->AugSlotType[x]; + isbs.augslots[x].visible = item->AugSlotVisible[x]; + isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + } + + 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(SoD::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)); + } + + SoD::structs::ItemTertiaryBodyStruct itbs; + memset(&itbs, 0, sizeof(SoD::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.no_pet = item->NoPet; + + 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; + + ss.write((const char*)&itbs, sizeof(SoD::structs::ItemTertiaryBodyStruct)); + + // Effect Structures Broken down to allow variable length strings for effect names + int32 effect_unknown = 0; + + SoD::structs::ClickEffectStruct ices; + memset(&ices, 0, sizeof(SoD::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(SoD::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 + + SoD::structs::ProcEffectStruct ipes; + memset(&ipes, 0, sizeof(SoD::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(SoD::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 + + SoD::structs::WornEffectStruct iwes; + memset(&iwes, 0, sizeof(SoD::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(SoD::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 + + SoD::structs::WornEffectStruct ifes; + memset(&ifes, 0, sizeof(SoD::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(SoD::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 + + SoD::structs::WornEffectStruct ises; + memset(&ises, 0, sizeof(SoD::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(SoD::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 + // End of Effects + + SoD::structs::ItemQuaternaryBodyStruct iqbs; + memset(&iqbs, 0, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); + + iqbs.scriptfileid = item->ScriptFileID; + iqbs.quest_item = item->QuestItemFlag; + iqbs.unknown15 = 0xffffffff; + + iqbs.Purity = item->Purity; + 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.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); } } - //_log(NET__ERROR, "Leadername is %s", gu2->leadersname); + ss.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_GroupUpdateB, PacketLength); + for (int x = 0; x < 10; ++x) { - char *Buffer = (char *)outapp->pBuffer; + if (SubSerializations[x]) { - // 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); + ss.write((const char*)&x, sizeof(uint32)); - // Leader - // + ss.write(SubSerializations[x], SubLengths[x]); - 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); + safe_delete_array(SubSerializations[x]); + } } - //_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; + 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; } - //_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_AltCurrencySell) -{ - ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); - SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - - OUT(merchant_entity_id); - eq->slot_id = ServerToSoDSlot(emu->slot_id); - OUT(charges); - OUT(cost); - FINISH_ENCODE(); -} - -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(color.color); - OUT(wear_slot_id); - FINISH_ENCODE(); -} - -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_RaidInvite) { - 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(); -} - -DECODE(OP_AdventureMerchantSell) { - DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); - SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - IN(npcid); - emu->slot = SoDToServerSlot(eq->slot); - IN(charges); - IN(sell_price); - - FINISH_DIRECT_DECODE(); -} - - -DECODE(OP_ApplyPoison) { - DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); - SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - - emu->inventorySlot = SoDToServerSlot(eq->inventorySlot); - IN(success); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ItemVerifyRequest) { - DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); - SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); - - emu->slot = SoDToServerSlot(eq->slot); - IN(target); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_Consume) { - DECODE_LENGTH_EXACT(structs::Consume_Struct); - SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); - - emu->slot = SoDToServerSlot(eq->slot); - IN(auto_consumed); - IN(type); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_CastSpell) { - DECODE_LENGTH_EXACT(structs::CastSpell_Struct); - SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - - IN(slot); - IN(spell_id); - emu->inventoryslot = SoDToServerSlot(eq->inventoryslot); - IN(target_id); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_DeleteItem) -{ - DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); - SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - emu->from_slot = SoDToServerSlot(eq->from_slot); - emu->to_slot = SoDToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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, eq->to_slot); - - emu->from_slot = SoDToServerSlot(eq->from_slot); - emu->to_slot = SoDToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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]); - } - IN(link_hash); - IN(icon); - - 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++) { - IN(filters[r]); - } - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } -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_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_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_CharacterCreate) { - DECODE_LENGTH_EXACT(structs::CharCreate_Struct); - SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - IN(class_); - IN(beardcolor); - IN(beard); - IN(hairstyle); - IN(gender); - IN(race); - - if(RuleB(World, EnableTutorialButton) && eq->tutorial) - emu->start_zone = RuleI(World, TutorialZoneID); - else - emu->start_zone = eq->start_zone; - - IN(haircolor); - IN(deity); - IN(STR); - IN(STA); - IN(AGI); - IN(DEX); - IN(WIS); - IN(INT); - IN(CHA); - IN(face); - IN(eyecolor1); - IN(eyecolor2); - IN(drakkin_heritage); - IN(drakkin_tattoo); - IN(drakkin_details); - - 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_GroupInvite2) -{ - //_log(NET__ERROR, "Received incoming OP_GroupInvite2. Forwarding"); - DECODE_FORWARD(OP_GroupInvite); -} - -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_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_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_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_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); - IN(entityid); - IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); - IN(slotid); - IN(bufffade); - 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 = SoDToServerSlot(eq->itemslot); - IN(quantity); - IN(price); - - 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_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_WearChange) { - DECODE_LENGTH_EXACT(structs::WearChange_Struct); - SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); - IN(spawn_id); - IN(material); - IN(unknown06); - IN(elite_material); - IN(color.color); - IN(wear_slot_id); - emu->hero_forge_model = 0; - emu->unknown18 = 0; - 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_LootItem) { - DECODE_LENGTH_EXACT(structs::LootingItem_Struct); - SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - IN(lootee); - IN(looter); - emu->slot_id = eq->slot_id - 1; - IN(auto_loot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TributeItem) { - DECODE_LENGTH_EXACT(structs::TributeItem_Struct); - SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); - - emu->slot = SoDToServerSlot(eq->slot); - IN(quantity); - IN(tribute_master_id); - IN(tribute_points); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ReadBook) { - DECODE_LENGTH_EXACT(structs::BookRequest_Struct); - SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); - - IN(type); - emu->invslot = SoDToServerSlot(eq->invslot); - emu->window = (uint8) eq->window; - strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TradeSkillCombine) { - DECODE_LENGTH_EXACT(structs::NewCombine_Struct); - SETUP_DIRECT_DECODE(NewCombine_Struct, structs::NewCombine_Struct); - - emu->container_slot = SoDToServerSlot(eq->container_slot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_AugmentItem) { - DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); - SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); - - emu->container_slot = SoDToServerSlot(eq->container_slot); - emu->augment_slot = eq->augment_slot; - - 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_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_LoadSpellSet) -{ - DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); - SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - - for(uint32 i = 0; i < MAX_PP_MEMSPELL; ++i) - emu->spell[i] = eq->spell[i]; - - FINISH_DIRECT_DECODE(); -} - -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) { - 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->GetItem(); - //_log(NET__ERROR, "Serialize called for: %s", item->Name); - SoD::structs::ItemSerializationHeader hdr; - hdr.stacksize = stackable ? charges : 1; - hdr.unknown004 = 0; - - int32 slot_id = ServerToSoDSlot(slot_id_in); - - hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; - hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.unknown020 = 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.unknown056 = 0; - hdr.unknown060 = 0; - hdr.unknown061 = 0; - hdr.unknown062 = 0; - hdr.ItemClass = item->ItemClass; - - ss.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); - - if(strlen(item->Name) > 0) + static inline uint32 ServerToSoDSlot(uint32 ServerSlot) { - ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); + uint32 SoDSlot = 0; + + if (ServerSlot >= MainAmmo && ServerSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + SoDSlot = ServerSlot + 1; + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) + SoDSlot = ServerSlot + 11; + else if (ServerSlot >= EmuConstants::BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) + SoDSlot = ServerSlot + 1; + else if (ServerSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) + SoDSlot = ServerSlot + 1; + else if (ServerSlot == MainPowerSource) + SoDSlot = slots::MainPowerSource; + else + SoDSlot = ServerSlot; + return SoDSlot; } - else + + static inline uint32 ServerToSoDCorpseSlot(uint32 ServerCorpse) { - ss.write((const char*)&null_term, sizeof(uint8)); + //uint32 SoDCorpse; } - if(strlen(item->Lore) > 0) + static inline uint32 SoDToServerSlot(uint32 SoDSlot) { - ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); + uint32 ServerSlot = 0; + + if (SoDSlot >= slots::MainAmmo && SoDSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + ServerSlot = SoDSlot - 1; + else if (SoDSlot >= consts::GENERAL_BAGS_BEGIN && SoDSlot <= consts::CURSOR_BAG_END) + ServerSlot = SoDSlot - 11; + else if (SoDSlot >= consts::BANK_BAGS_BEGIN && SoDSlot <= consts::BANK_BAGS_END) + ServerSlot = SoDSlot - 1; + else if (SoDSlot >= consts::SHARED_BANK_BAGS_BEGIN && SoDSlot <= consts::SHARED_BANK_BAGS_END) + ServerSlot = SoDSlot - 1; + else if (SoDSlot == slots::MainPowerSource) + ServerSlot = MainPowerSource; + else + ServerSlot = SoDSlot; + return ServerSlot; } - else + + static inline uint32 SoDToServerCorpseSlot(uint32 SoDCorpse) { - ss.write((const char*)&null_term, sizeof(uint8)); + //uint32 ServerCorpse; } - - 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)); - } - - SoD::structs::ItemBodyStruct ibs; - memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct)); - - uint32 adjusted_slots = item->Slots; - - // Conversions for Ammo and Power Source Slots - if(item->Slots & (1 << 21) & (1 << 22)) - { - // Do nothing - } - else - { - if(item->Slots & (1 << 21)) // Ammo Slot from Database - { - adjusted_slots -= (1 << 21); // Ammo Slot in Titanium - adjusted_slots += (1 << 22); // Ammo Slot in SoF - } - - if(item->Slots & (1 << 22)) // Power Source Slot from Database - { - adjusted_slots -= (1 << 22); // Non Existant Worn Slot in Titanium - adjusted_slots += (1 << 21); // Power Source Slot in SoF - } - } - - 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 = adjusted_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.unknown6 = 0; - ibs.SkillModType = item->SkillModType; - 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; - ibs.RecLevel = item->RecLevel; - 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.ItemType = item->ItemType; - ibs.Material = item->Material; - ibs.unknown7 = 0; - ibs.EliteMaterial = item->EliteMaterial; - 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.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(SoD::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)); - } - - SoD::structs::ItemSecondaryBodyStruct isbs; - memset(&isbs, 0, sizeof(SoD::structs::ItemSecondaryBodyStruct)); - - isbs.augtype = item->AugType; - isbs.augrestrict = item->AugRestrict; - - for(int x = 0; x < 5; ++x) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; - } - - 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(SoD::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)); - } - - SoD::structs::ItemTertiaryBodyStruct itbs; - memset(&itbs, 0, sizeof(SoD::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.no_pet = item->NoPet; - - 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; - - ss.write((const char*)&itbs, sizeof(SoD::structs::ItemTertiaryBodyStruct)); - - // Effect Structures Broken down to allow variable length strings for effect names - int32 effect_unknown = 0; - - SoD::structs::ClickEffectStruct ices; - memset(&ices, 0, sizeof(SoD::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(SoD::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 - - SoD::structs::ProcEffectStruct ipes; - memset(&ipes, 0, sizeof(SoD::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(SoD::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 - - SoD::structs::WornEffectStruct iwes; - memset(&iwes, 0, sizeof(SoD::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(SoD::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 - - SoD::structs::WornEffectStruct ifes; - memset(&ifes, 0, sizeof(SoD::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(SoD::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 - - SoD::structs::WornEffectStruct ises; - memset(&ises, 0, sizeof(SoD::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(SoD::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 - // End of Effects - - SoD::structs::ItemQuaternaryBodyStruct iqbs; - memset(&iqbs, 0, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); - - iqbs.scriptfileid = item->ScriptFileID; - iqbs.quest_item = item->QuestItemFlag; - iqbs.unknown15 = 0xffffffff; - - iqbs.Purity = item->Purity; - 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.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(SoD::structs::ItemQuaternaryBodyStruct)); - - for(int x = 0; x < 10; ++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; } - -DECODE(OP_Bug) -{ - DECODE_LENGTH_EXACT(structs::BugStruct); - SETUP_DIRECT_DECODE(BugStruct, structs::BugStruct); - strn0cpy(emu->chartype, eq->chartype, sizeof(emu->chartype)); - strn0cpy(emu->name, eq->name, sizeof(emu->name)); - strn0cpy(emu->ui, eq->ui, sizeof(emu->ui)); - IN(x); - IN(y); - IN(z); - IN(heading); - strn0cpy(emu->target_name, eq->target_name, sizeof(emu->target_name)); - strn0cpy(emu->bug, eq->bug, sizeof(emu->bug)); - strn0cpy(emu->system_info, eq->system_info, sizeof(emu->system_info)); - - 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 = SoDToServerSlot(eq->slot_id); - 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 = SoDToServerSlot(eq->slot_id); - IN(charges); - IN(cost); - FINISH_DIRECT_DECODE(); -} - - -} //end namespace SoD +// end namespace SoD diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 4116d3251..5e00a2870 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1,4 +1,3 @@ - #include "../debug.h" #include "sof.h" #include "../opcodemgr.h" @@ -7,6 +6,7 @@ #include "../crc32.h" #include "../eq_packet_structs.h" +#include "../misc_functions.h" #include "../string_util.h" #include "../item.h" #include "sof_structs.h" @@ -15,903 +15,1873 @@ #include #include -namespace SoF { +namespace SoF +{ + static const char *name = "SoF"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; -static const char *name = "SoF"; -static OpcodeManager *opcodes = nullptr; -static Strategy struct_strategy; + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); -char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + // server to client inventory location converters + static inline uint32 ServerToSoFSlot(uint32 ServerSlot); + static inline uint32 ServerToSoFCorpseSlot(uint32 ServerCorpse); -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; + // client to server inventory location converters + static inline uint32 SoFToServerSlot(uint32 SoFSlot); + static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse); + + 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); } } - //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 "sof_ops.h" } -} + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } - -Strategy::Strategy() -: StructStrategy() -{ - //all opcodes default to passthrough. - #include "ss_register.h" - #include "sof_ops.h" -} - -std::string Strategy::Describe() const { - std::string r; - r += "Patch "; - r += name; - return(r); -} - -const EQClientVersion Strategy::ClientVersion() const -{ - return EQClientSoF; -} + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientSoF; + } #include "ss_define.h" - -// Converts Server Slot IDs to SoF Slot IDs for use in Encodes -static inline uint32 ServerToSoFSlot(uint32 ServerSlot) { - uint32 SoFSlot = 0; - - if (ServerSlot >= MainAmmo && ServerSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots - SoFSlot = ServerSlot + 1; - - else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) - SoFSlot = ServerSlot + 11; - - else if (ServerSlot >= EmuConstants::BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) - SoFSlot = ServerSlot + 1; - - else if (ServerSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) - SoFSlot = ServerSlot + 1; - - else if (ServerSlot == MainPowerSource) - SoFSlot = slots::MainPowerSource; - - else - SoFSlot = ServerSlot; - - return SoFSlot; -} - -// Converts SoF Slot IDs to Server Slot IDs for use in Decodes -static inline uint32 SoFToServerSlot(uint32 SoFSlot) { - uint32 ServerSlot = 0; - - if(SoFSlot >= slots::MainAmmo && SoFSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots - ServerSlot = SoFSlot - 1; - - else if(SoFSlot >= consts::GENERAL_BAGS_BEGIN && SoFSlot <= consts::CURSOR_BAG_END) - ServerSlot = SoFSlot - 11; - - else if(SoFSlot >= consts::BANK_BAGS_BEGIN && SoFSlot <= consts::BANK_BAGS_END) - ServerSlot = SoFSlot - 1; - - else if(SoFSlot >= consts::SHARED_BANK_BAGS_BEGIN && SoFSlot <= consts::SHARED_BANK_BAGS_END) - ServerSlot = SoFSlot - 1; - - else if(SoFSlot == slots::MainPowerSource) - ServerSlot = MainPowerSource; - - else - ServerSlot = SoFSlot; - - - return ServerSlot; -} - -/* -// Converts Server Corpse Slot IDs to SoF Corpse Slot IDs for use in Encodes -static inline uint32 ServerToSoFCorpseSlot(uint32 ServerCorpse) { - uint32 SoFCorpse; - // reserved -} -*/ -/* -// Converts SoF Corpse Slot IDs to Server Corpse Slot IDs for use in Decodes -static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse) { - uint32 ServerCorpse; - // reserved -} -*/ - - -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 Live 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_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; - eq2->level = emu->level[r]; - eq2->hairstyle = emu->hairstyle[r]; - eq2->gender = emu->gender[r]; - 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->beard = emu->beard[r]; - eq2->haircolor = emu->haircolor[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].itemid = 0; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; - } - eq2->primary = emu->primary[r]; - eq2->secondary = emu->secondary[r]; - eq2->tutorial = emu->tutorial[r]; // was u15 - eq2->u15 = 0xff; - eq2->deity = emu->deity[r]; - eq2->zone = emu->zone[r]; - eq2->u19 = 0xFF; - eq2->race = emu->race[r]; - eq2->gohome = emu->gohome[r]; - eq2->class_ = emu->class_[r]; - eq2->eyecolor1 = emu->eyecolor1[r]; - eq2->beardcolor = emu->beardcolor[r]; - eq2->eyecolor2 = emu->eyecolor2[r]; - eq2->drakkin_heritage = emu->drakkin_heritage[r]; - eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; - eq2->drakkin_details = emu->drakkin_details[r]; - } - bufptr += sizeof(structs::CharacterSelectEntry_Struct); - } - - FINISH_ENCODE(); - -} - -ENCODE(OP_ZoneServerInfo) { - SETUP_DIRECT_ENCODE(ZoneServerInfo_Struct, ZoneServerInfo_Struct); - OUT_str(ip); - OUT(port); - FINISH_ENCODE(); - - //this is SUCH bullshit to be doing from down here. but the - // new client requires us to close immediately following this - // packet, so do it. - //dest->Close(); -} - -//hack hack hack -ENCODE(OP_SendZonepoints) { - ENCODE_LENGTH_ATLEAST(ZonePoints); - - SETUP_VAR_ENCODE(ZonePoints); - ALLOC_VAR_ENCODE(structs::ZonePoints, __packet->size); - - memcpy(eq, emu, __packet->size); - - FINISH_ENCODE(); -// unknown0xxx[24]; - //this is utter crap... the client is waiting for this - //certain 0 length opcode to come after the reqclientspawn - //stuff... so this is a dirty way to put it in there. - // this needs to be done better - - //EQApplicationPacket hack_test(OP_PetitionUnCheckout, 0); - //dest->QueuePacket(&hack_test); - -} - -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 4 is for SoF - if (emu->clientver <= 4 ) +// ENCODE methods + ENCODE(OP_Action) { - 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)?0:(emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); + + OUT(target); + OUT(source); + OUT(level); + OUT(instrument_mod); + eq->sequence = emu->sequence; + OUT(type); + //OUT(damage); + OUT(spell); + eq->level2 = emu->level; + OUT(buff_unknown); // if this is 4, a buff icon is made + //eq->unknown0036 = -1; + //eq->unknown0040 = -1; + //eq->unknown0044 = -1; + + 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 = ServerToSoFSlot(emu->slot); + OUT(charges); + OUT(sell_price); + + FINISH_ENCODE(); + } + + ENCODE(OP_AltCurrencySell) + { + ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); + SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + OUT(merchant_entity_id); + eq->slot_id = ServerToSoFSlot(emu->slot_id); + OUT(charges); OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; - OUT(spellid); - 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); - } + + FINISH_ENCODE(); } - 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_PlayerProfile) { - SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); - - uint32 r; - - eq->available_slots=0xffffffff; - memset(eq->unknown4184, 0xff, sizeof(eq->unknown4184)); - memset(eq->unknown04396, 0xff, sizeof(eq->unknown04396)); - -// OUT(checksum); - OUT(gender); - OUT(race); - OUT(class_); -// OUT(unknown00016); - OUT(level); - eq->level1 = emu->level; -// OUT(unknown00022[2]); - for(r = 0; r < 5; r++) { - OUT(binds[r].zoneId); - OUT(binds[r].x); - OUT(binds[r].y); - OUT(binds[r].z); - OUT(binds[r].heading); - } - OUT(deity); - OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); - OUT(abilitySlotRefresh); - OUT(points); // Relocation Test -// OUT(unknown0166[4]); - OUT(haircolor); - OUT(beardcolor); - OUT(eyecolor1); - OUT(eyecolor2); - OUT(hairstyle); - OUT(beard); -// OUT(unknown00178[10]); - for(r = 0; r < 9; r++) { - eq->equipment[r].equip0 = emu->item_material[r]; - eq->equipment[r].equip1 = 0; - eq->equipment[r].itemId = 0; - //eq->colors[r].color = emu->colors[r].color; - } - for(r = 0; r < 7; r++) { - OUT(item_tint[r].color); - } -// OUT(unknown00224[48]); - //NOTE: new client supports 300 AAs, our internal rep/PP - //only supports 240.. - for(r = 0; r < MAX_PP_AA_ARRAY; r++) { - OUT(aa_array[r].AA); - OUT(aa_array[r].value); - } -// OUT(unknown02220[4]); - OUT(mana); - OUT(cur_hp); - OUT(STR); - OUT(STA); - OUT(CHA); - OUT(AGI); - OUT(INT); - OUT(DEX); - OUT(WIS); - OUT(face); -// OUT(unknown02264[47]); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); -// OUT(unknown4184[128]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); -// OUT(unknown04396[32]); - OUT(platinum); - OUT(gold); - OUT(silver); - OUT(copper); - OUT(platinum_cursor); - OUT(gold_cursor); - OUT(silver_cursor); - OUT(copper_cursor); - - OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) - -// OUT(unknown04760[236]); - OUT(toxicity); - OUT(thirst_level); - OUT(hunger_level); - for(r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); - OUT(buffs[r].level); - OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); - OUT(buffs[r].spellid); - OUT(buffs[r].duration); - OUT(buffs[r].counters); - OUT(buffs[r].player_id); - } - for(r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { - OUT(disciplines.values[r]); - } - OUT_array(recastTimers, structs::MAX_RECAST_TYPES); -// OUT(unknown08124[360]); - OUT(endurance); - OUT(aapoints_spent); - OUT(aapoints); -// OUT(unknown06160[4]); - //NOTE: new client supports 20 bandoliers, our internal rep - //only supports 4.. - for(r = 0; r < 4; r++) { - OUT_str(bandoliers[r].name); - uint32 k; - for(k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { - OUT(bandoliers[r].items[k].item_id); - OUT(bandoliers[r].items[k].icon); - OUT_str(bandoliers[r].items[k].item_name); - } - } -// OUT(unknown07444[5120]); - for(r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) { - OUT(potionbelt.items[r].item_id); - OUT(potionbelt.items[r].icon); - OUT_str(potionbelt.items[r].item_name); - } -// OUT(unknown12852[8]); -// OUT(unknown12864[76]); - OUT_str(name); - OUT_str(last_name); - OUT(guild_id); - OUT(birthday); - OUT(lastlogin); - OUT(timePlayedMin); - OUT(pvp); - OUT(anon); - OUT(gm); - OUT(guildrank); - OUT(guildbanker); -// OUT(unknown13054[12]); - OUT(exp); -// OUT(unknown13072[8]); - OUT(timeentitledonaccount); - OUT_array(languages, structs::MAX_PP_LANGUAGE); -// OUT(unknown13109[7]); - OUT(y); //reversed x and y - OUT(x); - OUT(z); - OUT(heading); -// OUT(unknown13132[4]); - OUT(platinum_bank); - OUT(gold_bank); - OUT(silver_bank); - OUT(copper_bank); - OUT(platinum_shared); -// OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 16383; -// OUT(unknown13244[12]); - OUT(autosplit); -// OUT(unknown13260[16]); - OUT(zone_id); - OUT(zoneInstance); - for(r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { - OUT_str(groupMembers[r]); - } - strcpy(eq->groupLeader, emu->groupMembers[0]); -// OUT_str(groupLeader); -// OUT(unknown13728[660]); - OUT(entityid); - OUT(leadAAActive); -// OUT(unknown14392[4]); - OUT(ldon_points_guk); - OUT(ldon_points_mir); - OUT(ldon_points_mmc); - OUT(ldon_points_ruj); - OUT(ldon_points_tak); - OUT(ldon_points_available); -// OUT(unknown14420[132]); - OUT(tribute_time_remaining); - OUT(career_tribute_points); -// OUT(unknown7208); - OUT(tribute_points); -// OUT(unknown7216); - OUT(tribute_active); - for(r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { - OUT(tributes[r].tribute); - OUT(tributes[r].tier); - } -// OUT(unknown14616[8]); - OUT(group_leadership_exp); -// OUT(unknown14628); - OUT(raid_leadership_exp); - OUT(group_leadership_points); - OUT(raid_leadership_points); - OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); -// OUT(unknown14772[128]); - OUT(air_remaining); - OUT(PVPKills); - OUT(PVPDeaths); - OUT(PVPCurrentPoints); - OUT(PVPCareerPoints); - OUT(PVPBestKillStreak); - OUT(PVPWorstDeathStreak); - OUT(PVPCurrentKillStreak); -// OUT(unknown17892[4580]); - OUT(expAA); -// OUT(unknown19516[40]); - OUT(currentRadCrystals); - OUT(careerRadCrystals); - OUT(currentEbonCrystals); - OUT(careerEbonCrystals); - OUT(groupAutoconsent); - OUT(raidAutoconsent); - OUT(guildAutoconsent); -// OUT(unknown19575[5]); - eq->level3 = emu->level; - eq->showhelm = emu->showhelm; - OUT(RestTimer); -// OUT(unknown19584[4]); -// OUT(unknown19588); - - -const uint8 bytes[] = { -0xa3,0x02,0x00,0x00,0x95,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x00,0x00, -0x19,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00, -0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1F,0x85,0xEB,0x3E,0x33,0x33,0x33,0x3F, -0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; - - memcpy(eq->unknown12864, bytes, sizeof(bytes)); - - - - //set the checksum... - CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct)-4); - - FINISH_ENCODE(); -} - -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); - - /*fill in some unknowns with observed values, hopefully it will help */ - eq->unknown796 = -1; - eq->unknown840 = 600; - eq->unknown876 = 50; - eq->unknown880 = 10; - eq->unknown884 = 1; - eq->unknown885 = 0; - eq->unknown886 = 1; - eq->unknown887 = 0; - eq->unknown888 = 0; - eq->unknown889 = 0; - eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off - eq->unknown891 = 0; - eq->unknown892 = 180; - eq->unknown896 = 180; - eq->unknown900 = 180; - eq->unknown904 = 2; - eq->unknown908 = 2; - - FINISH_ENCODE(); -} - -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) + ENCODE(OP_ApplyPoison) { - _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; + ENCODE_LENGTH_EXACT(ApplyPoison_Struct); + SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + eq->inventorySlot = ServerToSoFSlot(emu->inventorySlot); + OUT(success); + + FINISH_ENCODE(); } - in->size = sizeof(structs::Track_Struct) * EntryCount; - in->pBuffer = new unsigned char[in->size]; - structs::Track_Struct *eq = (structs::Track_Struct *) in->pBuffer; - - for(int i = 0; i < EntryCount; ++i, ++eq, ++emu) + ENCODE(OP_BazaarSearch) { + if (((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) { + + EQApplicationPacket *in = *p; + *p = nullptr; + dest->FastQueuePacket(&in, ack_req); + return; + } + + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer; + + //determine and verify length + 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; + } + + //make the EQ struct. + in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount; + in->pBuffer = new unsigned char[in->size]; + structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer; + + //zero out the packet. We could avoid this memset by setting all fields (including unknowns) + //in the loop. + memset(in->pBuffer, 0, in->size); + + for (int i = 0; iBeginning.Action = emu->Beginning.Action; + eq->Beginning.Unknown001 = emu->Beginning.Unknown001; + eq->Beginning.Unknown002 = emu->Beginning.Unknown002; + eq->NumItems = emu->NumItems; + eq->SerialNumber = emu->SerialNumber; + eq->SellerID = emu->SellerID; + eq->Cost = emu->Cost; + eq->ItemStat = emu->ItemStat; + strcpy(eq->ItemName, emu->ItemName); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_BecomeTrader) + { + ENCODE_LENGTH_EXACT(BecomeTrader_Struct); + SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct); + + OUT(ID); + OUT(Code); + + FINISH_ENCODE(); + } + + ENCODE(OP_Buff) + { + ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); + SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + OUT(entityid); - OUT(padding002); - OUT(distance); + OUT(slot); + OUT(level); + OUT(effect); + //eq->unknown7 = 10; + OUT(spellid); + OUT(duration); + OUT(slotid); + OUT(bufffade); + + FINISH_ENCODE(); } - delete[] __emu_buffer; + ENCODE(OP_CancelTrade) + { + ENCODE_LENGTH_EXACT(CancelTrade_Struct); + SETUP_DIRECT_ENCODE(CancelTrade_Struct, structs::CancelTrade_Struct); - dest->FastQueuePacket(&in, ack_req); -} + OUT(fromid); + OUT(action); -ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); } -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; + FINISH_ENCODE(); } - //make the EQ struct. - in->size = sizeof(structs::Spawn_Struct)*entrycount; - in->pBuffer = new unsigned char[in->size]; - structs::Spawn_Struct *eq = (structs::Spawn_Struct *) in->pBuffer; + ENCODE(OP_CharInventory) + { + //consume the packet + EQApplicationPacket *in = *p; - //zero out the packet. We could avoid this memset by setting all fields (including unknowns) - //in the loop. - memset(in->pBuffer, 0, in->size); + *p = nullptr; - //do the transform... - int r; - int k; - for(r = 0; r < entrycount; r++, eq++, emu++) { + if (in->size == 0) { + in->size = 4; + in->pBuffer = new uchar[in->size]; + *((uint32 *)in->pBuffer) = 0; - eq->showname = 1; //New Field - Toggles Name Display on or off - 0 = off, 1 = on - eq->linkdead = 0; //New Field - Toggles LD on or off after name - 0 = off, 1 = on - eq->statue = 0; //New Field - 1 freezes animation - eq->showhelm = emu->showhelm; - eq->deity = emu->deity; - eq->drakkin_heritage = emu->drakkin_heritage; - eq->gender = emu->gender; - for(k = 0; k < 9; k++) { - eq->equipment[k].equip0 = emu->equipment[k]; - eq->equipment[k].equip1 = 0; - eq->equipment[k].itemId = 0; - eq->colors[k].color = emu->colors[k].color; + dest->FastQueuePacket(&in, ack_req); + return; } - eq->StandState = emu->StandState; - eq->guildID = emu->guildID; - eq->spelleffect = 0; - eq->spelleffect2 = 0; - eq->spelleffect3 = 0; - eq->spelleffect4 = 0; - eq->spelleffect5 = 0; - eq->spelleffect6 = 0; - eq->class_ = emu->class_; - eq->flymode = emu->flymode; - eq->gm = emu->gm; - eq->helm = emu->helm; - eq->drakkin_tattoo = emu->drakkin_tattoo; - eq->beardcolor = emu->beardcolor; - eq->runspeed = emu->runspeed; - eq->light = emu->light; - eq->level = emu->level; - eq->lfg = emu->lfg; - eq->hairstyle = emu->hairstyle; - eq->haircolor = emu->haircolor; - eq->race = emu->race; - strcpy(eq->suffix, emu->suffix); - eq->findable = emu->findable; - if(emu->bodytype >= 66) + + //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_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 = ServerToSoFSlot(emu->from_slot); + eq->to_slot = ServerToSoFSlot(emu->to_slot); + OUT(number_in_stack); + + FINISH_ENCODE(); + } + + ENCODE(OP_DeleteSpawn) + { + SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); + + OUT(spawn_id); + + 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) { - eq->bodytype = 11; //non-targetable - eq->showname = 0; //no visible name - eq->race = 127; //invisible man - eq->gender = 0; //invisible men are gender 0 + 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->enabled_max = 1; + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->leader_name, emu->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 (int 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); + + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->player_name, emu->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_GroundSpawn) + { + ENCODE_LENGTH_EXACT(Object_Struct); + SETUP_DIRECT_ENCODE(Object_Struct, structs::Object_Struct); + + OUT(drop_id); + OUT(zone_id); + OUT(zone_instance); + OUT(heading); + OUT(x); + OUT(y); + OUT(z); + OUT_str(object_name); + OUT(object_type); + OUT(spawn_id); + + /*fill in some unknowns with observed values, hopefully it will help */ + eq->unknown020 = 0; + eq->unknown024 = 0; + eq->size = 1; //This forces all objects to standard size for now + eq->unknown088 = 0; + memset(eq->unknown096, 0xFF, sizeof(eq->unknown096)); + + FINISH_ENCODE(); + } + + 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++; + + //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) \ + strcpy(e->field, str.c_str()); \ + e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ +#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_); + PutFieldN(rank); + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + 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); + +#undef SlideStructString +#undef PutFieldN + + e++; + } + } + + delete[] __emu_buffer; + + dest->FastQueuePacket(&in, ack_req); + } + + 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); + + 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_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 = ServerToSoFSlot(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); + + strcpy(eq->worldshortname, emu->worldshortname); + + OUT(enablevoicemacros); + OUT(enablemail); + OUT(enable_pvp); + OUT(enable_FV); + + // These next two need to be set like this for the Tutorial Button to work. + eq->unknown263[0] = 0; + eq->unknown263[2] = 1; + + 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 = emu->slot_id + 1; + 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_MoveItem) + { + ENCODE_LENGTH_EXACT(MoveItem_Struct); + SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + + eq->from_slot = ServerToSoFSlot(emu->from_slot); + eq->to_slot = ServerToSoFSlot(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); + + /*fill in some unknowns with observed values, hopefully it will help */ + eq->unknown796 = -1; + eq->unknown840 = 600; + eq->unknown876 = 50; + eq->unknown880 = 10; + eq->unknown884 = 1; + eq->unknown885 = 0; + eq->unknown886 = 1; + eq->unknown887 = 0; + eq->unknown888 = 0; + eq->unknown889 = 0; + eq->fall_damage = 0; // 0 = Fall Damage on, 1 = Fall Damage off + eq->unknown891 = 0; + eq->unknown892 = 180; + eq->unknown896 = 180; + eq->unknown900 = 180; + eq->unknown904 = 2; + eq->unknown908 = 2; + + FINISH_ENCODE(); + } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + OUT_str(Title); + OUT_str(Text); + OUT(Buttons); + OUT(Duration); + OUT(PopupID); + + eq->unknown4236 = 0x00000000; + eq->unknown4240 = 0xffffffff; + + 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 Live 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) + { + ENCODE_LENGTH_EXACT(PetBuff_Struct); + SETUP_DIRECT_ENCODE(PetBuff_Struct, PetBuff_Struct); + + OUT(petid); + OUT(buffcount); + + int EQBuffSlot = 0; + + for (uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) + { + if (emu->spellid[EmuBuffSlot]) + { + eq->spellid[EQBuffSlot] = emu->spellid[EmuBuffSlot]; + eq->ticsremaining[EQBuffSlot++] = emu->ticsremaining[EmuBuffSlot]; + } + } + + FINISH_ENCODE(); + } + + ENCODE(OP_PlayerProfile) + { + SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); + + uint32 r; + + eq->available_slots = 0xffffffff; + memset(eq->unknown4184, 0xff, sizeof(eq->unknown4184)); + memset(eq->unknown04396, 0xff, sizeof(eq->unknown04396)); + + // OUT(checksum); + OUT(gender); + OUT(race); + OUT(class_); + // OUT(unknown00016); + OUT(level); + eq->level1 = emu->level; + // OUT(unknown00022[2]); + for (r = 0; r < 5; r++) { + OUT(binds[r].zoneId); + OUT(binds[r].x); + OUT(binds[r].y); + OUT(binds[r].z); + OUT(binds[r].heading); + } + OUT(deity); + OUT(intoxication); + OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT(abilitySlotRefresh); + OUT(points); // Relocation Test + // OUT(unknown0166[4]); + OUT(haircolor); + OUT(beardcolor); + OUT(eyecolor1); + OUT(eyecolor2); + OUT(hairstyle); + OUT(beard); + // OUT(unknown00178[10]); + for (r = 0; r < 9; r++) { + eq->equipment[r].equip0 = emu->item_material[r]; + eq->equipment[r].equip1 = 0; + eq->equipment[r].itemId = 0; + //eq->colors[r].color = emu->colors[r].color; + } + for (r = 0; r < 7; r++) { + OUT(item_tint[r].color); + } + // OUT(unknown00224[48]); + //NOTE: new client supports 300 AAs, our internal rep/PP + //only supports 240.. + for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + OUT(aa_array[r].AA); + OUT(aa_array[r].value); + } + // OUT(unknown02220[4]); + OUT(mana); + OUT(cur_hp); + OUT(STR); + OUT(STA); + OUT(CHA); + OUT(AGI); + OUT(INT); + OUT(DEX); + OUT(WIS); + OUT(face); + // OUT(unknown02264[47]); + OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + // OUT(unknown4184[128]); + OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + // OUT(unknown04396[32]); + OUT(platinum); + OUT(gold); + OUT(silver); + OUT(copper); + OUT(platinum_cursor); + OUT(gold_cursor); + OUT(silver_cursor); + OUT(copper_cursor); + + OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) + + // OUT(unknown04760[236]); + OUT(toxicity); + OUT(thirst_level); + OUT(hunger_level); + for (r = 0; r < structs::BUFF_COUNT; r++) { + OUT(buffs[r].slotid); + OUT(buffs[r].level); + OUT(buffs[r].bard_modifier); + OUT(buffs[r].effect); + OUT(buffs[r].spellid); + OUT(buffs[r].duration); + OUT(buffs[r].counters); + OUT(buffs[r].player_id); + } + for (r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { + OUT(disciplines.values[r]); + } + OUT_array(recastTimers, structs::MAX_RECAST_TYPES); + // OUT(unknown08124[360]); + OUT(endurance); + OUT(aapoints_spent); + OUT(aapoints); + // OUT(unknown06160[4]); + //NOTE: new client supports 20 bandoliers, our internal rep + //only supports 4.. + for (r = 0; r < 4; r++) { + OUT_str(bandoliers[r].name); + uint32 k; + for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { + OUT(bandoliers[r].items[k].item_id); + OUT(bandoliers[r].items[k].icon); + OUT_str(bandoliers[r].items[k].item_name); + } + } + // OUT(unknown07444[5120]); + for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) { + OUT(potionbelt.items[r].item_id); + OUT(potionbelt.items[r].icon); + OUT_str(potionbelt.items[r].item_name); + } + // OUT(unknown12852[8]); + // OUT(unknown12864[76]); + OUT_str(name); + OUT_str(last_name); + OUT(guild_id); + OUT(birthday); + OUT(lastlogin); + OUT(timePlayedMin); + OUT(pvp); + OUT(anon); + OUT(gm); + OUT(guildrank); + OUT(guildbanker); + // OUT(unknown13054[12]); + OUT(exp); + // OUT(unknown13072[8]); + OUT(timeentitledonaccount); + OUT_array(languages, structs::MAX_PP_LANGUAGE); + // OUT(unknown13109[7]); + OUT(y); //reversed x and y + OUT(x); + OUT(z); + OUT(heading); + // OUT(unknown13132[4]); + OUT(platinum_bank); + OUT(gold_bank); + OUT(silver_bank); + OUT(copper_bank); + OUT(platinum_shared); + // OUT(unknown13156[84]); + //OUT(expansions); + eq->expansions = 16383; + // OUT(unknown13244[12]); + OUT(autosplit); + // OUT(unknown13260[16]); + OUT(zone_id); + OUT(zoneInstance); + for (r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { + OUT_str(groupMembers[r]); + } + strcpy(eq->groupLeader, emu->groupMembers[0]); + // OUT_str(groupLeader); + // OUT(unknown13728[660]); + OUT(entityid); + OUT(leadAAActive); + // OUT(unknown14392[4]); + OUT(ldon_points_guk); + OUT(ldon_points_mir); + OUT(ldon_points_mmc); + OUT(ldon_points_ruj); + OUT(ldon_points_tak); + OUT(ldon_points_available); + // OUT(unknown14420[132]); + OUT(tribute_time_remaining); + OUT(career_tribute_points); + // OUT(unknown7208); + OUT(tribute_points); + // OUT(unknown7216); + OUT(tribute_active); + for (r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { + OUT(tributes[r].tribute); + OUT(tributes[r].tier); + } + // OUT(unknown14616[8]); + OUT(group_leadership_exp); + // OUT(unknown14628); + OUT(raid_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_points); + OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); + // OUT(unknown14772[128]); + OUT(air_remaining); + OUT(PVPKills); + OUT(PVPDeaths); + OUT(PVPCurrentPoints); + OUT(PVPCareerPoints); + OUT(PVPBestKillStreak); + OUT(PVPWorstDeathStreak); + OUT(PVPCurrentKillStreak); + // OUT(unknown17892[4580]); + OUT(expAA); + // OUT(unknown19516[40]); + OUT(currentRadCrystals); + OUT(careerRadCrystals); + OUT(currentEbonCrystals); + OUT(careerEbonCrystals); + OUT(groupAutoconsent); + OUT(raidAutoconsent); + OUT(guildAutoconsent); + // OUT(unknown19575[5]); + eq->level3 = emu->level; + eq->showhelm = emu->showhelm; + OUT(RestTimer); + // OUT(unknown19584[4]); + // OUT(unknown19588); + + const uint8 bytes[] = { + 0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + memcpy(eq->unknown12864, bytes, sizeof(bytes)); + + //set the checksum... + CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); + + FINISH_ENCODE(); + } + + 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 { - eq->bodytype = emu->bodytype; + 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); } - //eq->bodytype2 = 0; - eq->equip_chest2 = emu->equip_chest2; - eq->curHp = emu->curHp; - eq->invis = emu->invis; - strcpy(eq->lastName, emu->lastName); - eq->eyecolor1 = emu->eyecolor1; - strcpy(eq->title, emu->title); - eq->beard = emu->beard; - eq->targetable = 1; //New Field - Toggle Targetable on or off - 0 = off, 1 = on - eq->NPC = emu->NPC; - eq->targetable_with_hotkey = 1;//New Field - Toggle Targetable on or off - 0 = off, 1 = on - eq->x = emu->x; - eq->deltaX = emu->deltaX; - eq->deltaY = emu->deltaY; - eq->z = emu->z; - eq->deltaHeading = emu->deltaHeading; - eq->y = emu->y; - eq->deltaZ = emu->deltaZ; - eq->animation = emu->animation; - eq->heading = emu->heading; - eq->spawnId = emu->spawnId; - eq->nonvisible = 0; - strcpy(eq->name, emu->name); - eq->petOwnerId = emu->petOwnerId; - eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name - for(k = 0; k < 9; k++) { - eq->colors[k].color = emu->colors[k].color; - } - eq->anon = emu->anon; - eq->face = emu->face; - eq->drakkin_details = emu->drakkin_details; - eq->size = emu->size; - eq->walkspeed = emu->walkspeed; - /* - //Uncomment this section to use this hack test with NPC last names - //Hack Test for finding more fields in the Struct: - if (emu->lastName[0] == '*') // Test NPC! + + 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); + eq->invslot = ServerToSoFSlot(emu->invslot); + strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); + + 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 4 is for SoF + if (emu->clientver <= 4) { + 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) ? 0 : (emu->sof_next_skill); + eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (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); + OUT(prereq_skill); + OUT(prereq_minpoints); + eq->type = emu->sof_type; + OUT(spellid); + 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); + } + } + + 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; + eq2->level = emu->level[r]; + eq2->hairstyle = emu->hairstyle[r]; + eq2->gender = emu->gender[r]; + 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->beard = emu->beard[r]; + eq2->haircolor = emu->haircolor[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].itemid = 0; + eq2->equip[k].color.color = emu->cs_colors[r][k].color; + } + eq2->primary = emu->primary[r]; + eq2->secondary = emu->secondary[r]; + eq2->tutorial = emu->tutorial[r]; // was u15 + eq2->u15 = 0xff; + eq2->deity = emu->deity[r]; + eq2->zone = emu->zone[r]; + eq2->u19 = 0xFF; + eq2->race = emu->race[r]; + eq2->gohome = emu->gohome[r]; + eq2->class_ = emu->class_[r]; + eq2->eyecolor1 = emu->eyecolor1[r]; + eq2->beardcolor = emu->beardcolor[r]; + eq2->eyecolor2 = emu->eyecolor2[r]; + eq2->drakkin_heritage = emu->drakkin_heritage[r]; + eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; + eq2->drakkin_details = emu->drakkin_details[r]; + } + bufptr += sizeof(structs::CharacterSelectEntry_Struct); + } + + FINISH_ENCODE(); + } + + //hack hack hack + ENCODE(OP_SendZonepoints) + { + ENCODE_LENGTH_ATLEAST(ZonePoints); + + SETUP_VAR_ENCODE(ZonePoints); + ALLOC_VAR_ENCODE(structs::ZonePoints, __packet->size); + + memcpy(eq, emu, __packet->size); + + FINISH_ENCODE(); + // unknown0xxx[24]; + //this is utter crap... the client is waiting for this + //certain 0 length opcode to come after the reqclientspawn + //stuff... so this is a dirty way to put it in there. + // this needs to be done better + + //EQApplicationPacket hack_test(OP_PetitionUnCheckout, 0); + //dest->QueuePacket(&hack_test); + } + + ENCODE(OP_ShopPlayerSell) + { + ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); + SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); + + OUT(npcid); + eq->itemslot = ServerToSoFSlot(emu->itemslot); + OUT(quantity); + OUT(price); + + 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); + + strcpy(eq->model_name, emu->model_name); + + FINISH_ENCODE(); + } + + 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++) { + strcpy(eq[r].name, emu[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].unknown0076 = 0; + eq[r].unknown0077 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0078 = 0; + eq[r].unknown0079 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0080 = 0; + eq[r].unknown0081 = 0; + eq[r].unknown0082 = 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_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; + } + + in->size = sizeof(structs::Track_Struct) * EntryCount; + in->pBuffer = new unsigned char[in->size]; + structs::Track_Struct *eq = (structs::Track_Struct *) in->pBuffer; + + for (int i = 0; i < EntryCount; ++i, ++eq, ++emu) + { + OUT(entityid); + OUT(padding002); + OUT(distance); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_Trader) + { + if ((*p)->size != sizeof(TraderBuy_Struct)) { + EQApplicationPacket *in = *p; + *p = nullptr; + dest->FastQueuePacket(&in, ack_req); + return; + } + + 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_TributeItem) + { + ENCODE_LENGTH_EXACT(TributeItem_Struct); + SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); + + eq->slot = ServerToSoFSlot(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 (uint32 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; + strcpy(vr->items[x].item_name, ivr->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(color.color); + OUT(wear_slot_id); + + 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 = zps->bind_zone_id; + zph->bind_instance_id = zps->bind_instance_id; + strcpy(zph->zone_name, zps->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(); + + //this is SUCH bullshit to be doing from down here. but the + // new client requires us to close immediately following this + // packet, so do it. + //dest->Close(); + } + + 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; + } + + //make the EQ struct. + in->size = sizeof(structs::Spawn_Struct)*entrycount; + in->pBuffer = new unsigned char[in->size]; + structs::Spawn_Struct *eq = (structs::Spawn_Struct *) in->pBuffer; + + //zero out the packet. We could avoid this memset by setting all fields (including unknowns) + //in the loop. + memset(in->pBuffer, 0, in->size); + + //do the transform... + int r; + int k; + for (r = 0; r < entrycount; r++, eq++, emu++) { + + eq->showname = 1; //New Field - Toggles Name Display on or off - 0 = off, 1 = on + eq->linkdead = 0; //New Field - Toggles LD on or off after name - 0 = off, 1 = on + eq->statue = 0; //New Field - 1 freezes animation + eq->showhelm = emu->showhelm; + eq->deity = emu->deity; + eq->drakkin_heritage = emu->drakkin_heritage; + eq->gender = emu->gender; + for (k = 0; k < 9; k++) { + eq->equipment[k].equip0 = emu->equipment[k]; + eq->equipment[k].equip1 = 0; + eq->equipment[k].itemId = 0; + eq->colors[k].color = emu->colors[k].color; + } + eq->StandState = emu->StandState; + eq->guildID = emu->guildID; + eq->spelleffect = 0; + eq->spelleffect2 = 0; + eq->spelleffect3 = 0; + eq->spelleffect4 = 0; + eq->spelleffect5 = 0; + eq->spelleffect6 = 0; + eq->class_ = emu->class_; + eq->flymode = emu->flymode; + eq->gm = emu->gm; + eq->helm = emu->helm; + eq->drakkin_tattoo = emu->drakkin_tattoo; + eq->beardcolor = emu->beardcolor; + eq->runspeed = emu->runspeed; + eq->light = emu->light; + eq->level = emu->level; + eq->lfg = emu->lfg; + eq->hairstyle = emu->hairstyle; + eq->haircolor = emu->haircolor; + eq->race = emu->race; + strcpy(eq->suffix, emu->suffix); + eq->findable = emu->findable; + if (emu->bodytype >= 66) + { + eq->bodytype = 11; //non-targetable + eq->showname = 0; //no visible name + eq->race = 127; //invisible man + eq->gender = 0; //invisible men are gender 0 + } + else + { + eq->bodytype = emu->bodytype; + } + //eq->bodytype2 = 0; + eq->equip_chest2 = emu->equip_chest2; + eq->curHp = emu->curHp; + eq->invis = emu->invis; + strcpy(eq->lastName, emu->lastName); + eq->eyecolor1 = emu->eyecolor1; + strcpy(eq->title, emu->title); + eq->beard = emu->beard; + eq->targetable = 1; //New Field - Toggle Targetable on or off - 0 = off, 1 = on + eq->NPC = emu->NPC; + eq->targetable_with_hotkey = 1;//New Field - Toggle Targetable on or off - 0 = off, 1 = on + eq->x = emu->x; + eq->deltaX = emu->deltaX; + eq->deltaY = emu->deltaY; + eq->z = emu->z; + eq->deltaHeading = emu->deltaHeading; + eq->y = emu->y; + eq->deltaZ = emu->deltaZ; + eq->animation = emu->animation; + eq->heading = emu->heading; + eq->spawnId = emu->spawnId; + eq->nonvisible = 0; + strcpy(eq->name, emu->name); + eq->petOwnerId = emu->petOwnerId; + eq->pvp = 0; // 0 = non-pvp colored name, 1 = red pvp name + for (k = 0; k < 9; k++) { + eq->colors[k].color = emu->colors[k].color; + } + eq->anon = emu->anon; + eq->face = emu->face; + eq->drakkin_details = emu->drakkin_details; + eq->size = emu->size; + eq->walkspeed = emu->walkspeed; + /* + //Uncomment this section to use this hack test with NPC last names + //Hack Test for finding more fields in the Struct: + if (emu->lastName[0] == '*') // Test NPC! + { char code = emu->lastName[1]; size_t len = strlen(emu->lastName); char* sep = (char*)memchr(&emu->lastName[2], '=', len - 2); @@ -921,29 +1891,29 @@ ENCODE(OP_ZoneSpawns) { uint8 rnd = rand() & 0x0F; if (sep == nullptr) { - ofs = 0; - if ((emu->lastName[2] < '0') || (emu->lastName[2] > '9')) - { - val = rnd; - } - else - { - val = atoi(&emu->lastName[2]); - } + ofs = 0; + if ((emu->lastName[2] < '0') || (emu->lastName[2] > '9')) + { + val = rnd; } else { - sep[0] = nullptr; - ofs = atoi(&emu->lastName[2]); - sep[0] = '='; - if ((sep[1] < '0') || (sep[1] > '9')) - { - val = rnd; - } - else - { - val = atoi(&sep[1]); - } + val = atoi(&emu->lastName[2]); + } + } + else + { + sep[0] = nullptr; + ofs = atoi(&emu->lastName[2]); + sep[0] = '='; + if ((sep[1] < '0') || (sep[1] > '9')) + { + val = rnd; + } + else + { + val = atoi(&sep[1]); + } } char hex[] = "0123456789ABCDEF"; @@ -962,1906 +1932,1018 @@ ENCODE(OP_ZoneSpawns) { switch (code) { - case 'a': - eq->unknown0001[ofs % 4] = val; break; - case 'b': - eq->unknown0008 = val; break; - case 'c': - eq->unknown0011[ofs % 3] = val; break; - case 'd': - eq->unknown0018[ofs % 4] = val; break; - case 'e': - eq->unknown0023[ofs % 4] = val; break; - case 'f': - eq->unknown0136 = val; break; - case 'g': - eq->unknown0166[ofs % 8] = val; break; - case 'h': - eq->unknown0175[ofs % 192] = val; break; - case 'i': - eq->unknown0370[ofs % 3] = val; break; - case 'j': - eq->unknown0374[ofs % 128] = val; break; - case 'k': - eq->unknown0507[ofs % 4] = val; break; - case 'l': - eq->unknown0512[ofs % 16] = val; break; - case 'm': - eq->unknown0529[ofs % 4] = val; break; - case 'n': - eq->unknown0539[ofs % 41] = val; break; - case 'o': - eq->unknown0614[ofs % 11] = val; break; - case 'p': - eq->unknown0626[ofs % 28] = val; break; - case 'q': - eq->unknown0690 = val; break; - case 'r': - eq->unknown0726[ofs % 4] = val; break; - case 's': - eq->unknown0731[ofs % 11] = val; break; - case 't': - eq->unknown0767[ofs % 3] = val; break; - case 'u': - eq->unknown0883[ofs % 4] = val; break; - case 'v': - eq->unknown0895[ofs % 2] = val; break; - case 'X': - ((uint8*)eq)[ofs % 897] = val; break; - case 'Z': - eq->size = (float)val; break; // Test w/ size. + case 'a': + eq->unknown0001[ofs % 4] = val; break; + case 'b': + eq->unknown0008 = val; break; + case 'c': + eq->unknown0011[ofs % 3] = val; break; + case 'd': + eq->unknown0018[ofs % 4] = val; break; + case 'e': + eq->unknown0023[ofs % 4] = val; break; + case 'f': + eq->unknown0136 = val; break; + case 'g': + eq->unknown0166[ofs % 8] = val; break; + case 'h': + eq->unknown0175[ofs % 192] = val; break; + case 'i': + eq->unknown0370[ofs % 3] = val; break; + case 'j': + eq->unknown0374[ofs % 128] = val; break; + case 'k': + eq->unknown0507[ofs % 4] = val; break; + case 'l': + eq->unknown0512[ofs % 16] = val; break; + case 'm': + eq->unknown0529[ofs % 4] = val; break; + case 'n': + eq->unknown0539[ofs % 41] = val; break; + case 'o': + eq->unknown0614[ofs % 11] = val; break; + case 'p': + eq->unknown0626[ofs % 28] = val; break; + case 'q': + eq->unknown0690 = val; break; + case 'r': + eq->unknown0726[ofs % 4] = val; break; + case 's': + eq->unknown0731[ofs % 11] = val; break; + case 't': + eq->unknown0767[ofs % 3] = val; break; + case 'u': + eq->unknown0883[ofs % 4] = val; break; + case 'v': + eq->unknown0895[ofs % 2] = val; break; + case 'X': + ((uint8*)eq)[ofs % 897] = val; break; + case 'Z': + eq->size = (float)val; break; // Test w/ size. } - }*/ - } + }*/ + } + //kill off the emu structure and send the eq packet. + delete[] __emu_buffer; - //kill off the emu structure and send the eq packet. - delete[] __emu_buffer; - - //_log(NET__ERROR, "Sending zone spawns"); - //_hex(NET__ERROR, in->pBuffer, in->size); - - dest->FastQueuePacket(&in, ack_req); -} - -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_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; + //_log(NET__ERROR, "Sending zone spawns"); + //_hex(NET__ERROR, in->pBuffer, in->size); 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_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++; - - //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) \ - strcpy(e->field, str.c_str()); \ - e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ -#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_); - PutFieldN(rank); - PutFieldN(time_last_on); - PutFieldN(tribute_enable); - 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); - - -#undef SlideStructString -#undef PutFieldN - - e++; - } - } - - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - - -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++) { - strcpy(eq[r].name, emu[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].unknown0076 = 0; - eq[r].unknown0077 = 1; // Both must be 1 to allow clicking doors - eq[r].unknown0078 = 0; - eq[r].unknown0079 = 1; // Both must be 1 to allow clicking doors - eq[r].unknown0080 = 0; - eq[r].unknown0081 = 0; - eq[r].unknown0082 = 0; - } - FINISH_ENCODE(); -} - -ENCODE(OP_GroundSpawn) { - ENCODE_LENGTH_EXACT(Object_Struct); - SETUP_DIRECT_ENCODE(Object_Struct, structs::Object_Struct); - OUT(drop_id); - OUT(zone_id); - OUT(zone_instance); - OUT(heading); - OUT(x); - OUT(y); - OUT(z); - OUT_str(object_name); - OUT(object_type); - OUT(spawn_id); - - /*fill in some unknowns with observed values, hopefully it will help */ - eq->unknown020 = 0; - eq->unknown024 = 0; - eq->size = 1; //This forces all objects to standard size for now - eq->unknown088 = 0; - memset(eq->unknown096, 0xFF, sizeof(eq->unknown096)); - 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_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); - - 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_ExpansionInfo) { - ENCODE_LENGTH_EXACT(ExpansionInfo_Struct); - SETUP_DIRECT_ENCODE(ExpansionInfo_Struct, structs::ExpansionInfo_Struct); - OUT(Expansions); - FINISH_ENCODE(); -} - -ENCODE(OP_LogServer) { - ENCODE_LENGTH_EXACT(LogServer_Struct); - SETUP_DIRECT_ENCODE(LogServer_Struct, structs::LogServer_Struct); - strcpy(eq->worldshortname, emu->worldshortname); - - OUT(enablevoicemacros); - OUT(enablemail); - OUT(enable_pvp); - OUT(enable_FV); - - // These next two need to be set like this for the Tutorial Button to work. - eq->unknown263[0] = 0; - eq->unknown263[2] = 1; - - 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_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_Action) { - ENCODE_LENGTH_EXACT(Action_Struct); - SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); - OUT(target); - OUT(source); - OUT(level); - OUT(instrument_mod); - eq->sequence = emu->sequence; - OUT(type); - //OUT(damage); - OUT(spell); - eq->level2 = emu->level; - OUT(buff_unknown); // if this is 4, a buff icon is made - //eq->unknown0036 = -1; - //eq->unknown0040 = -1; - //eq->unknown0044 = -1; - FINISH_ENCODE(); -} - -ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); - OUT(entityid); - OUT(slot); - OUT(level); - OUT(effect); - //eq->unknown7 = 10; - OUT(spellid); - OUT(duration); - OUT(slotid); - OUT(bufffade); - 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_ShopPlayerSell) { - ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); - SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); - OUT(npcid); - eq->itemslot = ServerToSoFSlot(emu->itemslot); - OUT(quantity); - OUT(price); - FINISH_ENCODE(); -} - -ENCODE(OP_ApplyPoison) { - ENCODE_LENGTH_EXACT(ApplyPoison_Struct); - SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - eq->inventorySlot = ServerToSoFSlot(emu->inventorySlot); - OUT(success); - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteItem) { - ENCODE_LENGTH_EXACT(DeleteItem_Struct); - SETUP_DIRECT_ENCODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - eq->from_slot = ServerToSoFSlot(emu->from_slot); - eq->to_slot = ServerToSoFSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } -ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToSoFSlot(emu->from_slot); - eq->to_slot = ServerToSoFSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_ItemVerifyReply) { - ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); - SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - - eq->slot = ServerToSoFSlot(emu->slot); - OUT(spell); - OUT(target); - - FINISH_ENCODE(); -} - -ENCODE(OP_BazaarSearch) { - - if(((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) { - - EQApplicationPacket *in = *p; - *p = nullptr; - dest->FastQueuePacket(&in, ack_req); - return; - } - - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *) __emu_buffer; - - //determine and verify length - 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; - } - - //make the EQ struct. - in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount; - in->pBuffer = new unsigned char[in->size]; - structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer; - - //zero out the packet. We could avoid this memset by setting all fields (including unknowns) - //in the loop. - memset(in->pBuffer, 0, in->size); - - for(int i=0; iBeginning.Action = emu->Beginning.Action; - eq->Beginning.Unknown001 = emu->Beginning.Unknown001; - eq->Beginning.Unknown002 = emu->Beginning.Unknown002; - eq->NumItems = emu->NumItems; - eq->SerialNumber = emu->SerialNumber; - eq->SellerID = emu->SellerID; - eq->Cost = emu->Cost; - eq->ItemStat = emu->ItemStat; - strcpy(eq->ItemName, emu->ItemName); - } - - delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); - - -} - -ENCODE(OP_Trader) { - - if((*p)->size != sizeof(TraderBuy_Struct)) { - EQApplicationPacket *in = *p; - *p = nullptr; - dest->FastQueuePacket(&in, ack_req); - return; - } - 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_LootItem) { - - ENCODE_LENGTH_EXACT(LootingItem_Struct); - SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - OUT(lootee); - OUT(looter); - eq->slot_id = emu->slot_id + 1; - OUT(auto_loot); - - FINISH_ENCODE(); -} - -ENCODE(OP_TributeItem) { - ENCODE_LENGTH_EXACT(TributeItem_Struct); - SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); - - eq->slot = ServerToSoFSlot(emu->slot); - OUT(quantity); - OUT(tribute_master_id); - OUT(tribute_points); - - 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); - - strcpy(eq->model_name, emu->model_name); - - FINISH_ENCODE(); -} - -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); - eq->invslot = ServerToSoFSlot(emu->invslot); - strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); - 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_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 = zps->bind_zone_id; - zph->bind_instance_id = zps->bind_instance_id; - strcpy(zph->zone_name, zps->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_AdventureMerchantSell) { - ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); - SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - eq->unknown000 = 1; - OUT(npcid); - eq->slot = ServerToSoFSlot(emu->slot); - OUT(charges); - OUT(sell_price); - - FINISH_ENCODE(); -} - -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 +// DECODE methods + DECODE(OP_AdventureMerchantSell) { - RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; + DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); + SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); - structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; + IN(npcid); + emu->slot = SoFToServerSlot(eq->slot); + IN(charges); + IN(sell_price); - 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); + FINISH_DIRECT_DECODE(); } - 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); + DECODE(OP_AltCurrencySell) + { + DECODE_LENGTH_EXACT(structs::AltCurrencySellItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); + + IN(merchant_entity_id); + emu->slot_id = SoFToServerSlot(eq->slot_id); + IN(charges); + IN(cost); + + FINISH_DIRECT_DECODE(); } - delete[] __emu_buffer; -} -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_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(uint32 i = 0; i < count; ++i) + DECODE(OP_AltCurrencySellSelection) { - structs::VeteranReward *vr = (structs::VeteranReward*)data; - InternalVeteranReward *ivr = (InternalVeteranReward*)old_data; + DECODE_LENGTH_EXACT(structs::AltCurrencySelectItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); - 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) + IN(merchant_entity_id); + emu->slot_id = SoFToServerSlot(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 = SoFToServerSlot(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 = SoFToServerSlot(eq->container_slot); + emu->augment_slot = eq->augment_slot; + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_Buff) + { + DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct); + SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); + + IN(entityid); + IN(slot); + IN(level); + IN(effect); + IN(spellid); + IN(duration); + IN(slotid); + IN(bufffade); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_CastSpell) + { + DECODE_LENGTH_EXACT(structs::CastSpell_Struct); + SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); + + IN(slot); + IN(spell_id); + emu->inventoryslot = SoFToServerSlot(eq->inventoryslot); + IN(target_id); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_CharacterCreate) + { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(class_); + IN(beardcolor); + IN(beard); + IN(hairstyle); + IN(gender); + IN(race); + + if (RuleB(World, EnableTutorialButton) && eq->tutorial) + emu->start_zone = RuleI(World, TutorialZoneID); + else + emu->start_zone = eq->start_zone; + + IN(haircolor); + IN(deity); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); + + 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 = SoFToServerSlot(eq->slot); + IN(auto_consumed); + IN(type); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_DeleteItem) + { + DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); + SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); + + emu->from_slot = SoFToServerSlot(eq->from_slot); + emu->to_slot = SoFToServerSlot(eq->to_slot); + IN(number_in_stack); + + 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_GroupFollow) + { + 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) + { + 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_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]); + } + 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 = SoFToServerSlot(eq->slot); + IN(target); + + 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 = eq->slot_id - 1; + 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, eq->to_slot); + + emu->from_slot = SoFToServerSlot(eq->from_slot); + emu->to_slot = SoFToServerSlot(eq->to_slot); + IN(number_in_stack); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_RaidInvite) + { + 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(); + } + + DECODE(OP_ReadBook) + { + DECODE_LENGTH_EXACT(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(type); + emu->invslot = SoFToServerSlot(eq->invslot); + emu->window = (uint8)eq->window; + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + 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++) { + IN(filters[r]); + } + + 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 = SoFToServerSlot(eq->itemslot); + IN(quantity); + IN(price); + + 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); + + emu->container_slot = SoFToServerSlot(eq->container_slot); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TributeItem) + { + DECODE_LENGTH_EXACT(structs::TributeItem_Struct); + SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); + + emu->slot = SoFToServerSlot(eq->slot); + IN(quantity); + IN(tribute_master_id); + IN(tribute_points); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_WearChange) + { + DECODE_LENGTH_EXACT(structs::WearChange_Struct); + SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); + + IN(spawn_id); + IN(material); + IN(unknown06); + IN(elite_material); + IN(color.color); + IN(wear_slot_id); + emu->hero_forge_model = 0; + emu->unknown18 = 0; + + 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(); + } + +// 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) + { + 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->GetItem(); + //_log(NET__ERROR, "Serialize called for: %s", item->Name); + SoF::structs::ItemSerializationHeader hdr; + hdr.stacksize = stackable ? charges : 1; + hdr.unknown004 = 0; + + int32 slot_id = ServerToSoFSlot(slot_id_in); + + hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.price = inst->GetPrice(); + hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); + hdr.unknown020 = 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.unknown056 = 0; + hdr.unknown060 = 0; + hdr.unknown061 = 0; + hdr.ItemClass = item->ItemClass; + + ss.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); + + if (strlen(item->Name) > 0) { - vr->items[x].item_id = ivr->items[x].item_id; - strcpy(vr->items[x].item_name, ivr->items[x].item_name); - vr->items[x].charges = ivr->items[x].charges; + ss.write(item->Name, strlen(item->Name)); + ss.write((const char*)&null_term, sizeof(uint8)); } - - old_data += sizeof(InternalVeteranReward); - data += sizeof(structs::VeteranReward); - } - - dest->FastQueuePacket(&outapp_create); - delete inapp; -} - -ENCODE(OP_DeleteSpawn) { - SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); - OUT(spawn_id); - 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->enabled_max = 1; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); - 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_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_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(int 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_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_DzJoinExpeditionConfirm) -{ - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - FINISH_ENCODE(); -} - -ENCODE(OP_BecomeTrader) -{ - ENCODE_LENGTH_EXACT(BecomeTrader_Struct); - SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct); - OUT(ID); - OUT(Code); - FINISH_ENCODE(); -} - -ENCODE(OP_PetBuffWindow) -{ - ENCODE_LENGTH_EXACT(PetBuff_Struct); - SETUP_DIRECT_ENCODE(PetBuff_Struct, PetBuff_Struct); - - OUT(petid); - OUT(buffcount); - - int EQBuffSlot = 0; - - for(uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) - { - if(emu->spellid[EmuBuffSlot]) + else { - eq->spellid[EQBuffSlot] = emu->spellid[EmuBuffSlot]; - eq->ticsremaining[EQBuffSlot++] = emu->ticsremaining[EmuBuffSlot]; + ss.write((const char*)&null_term, sizeof(uint8)); } - } - FINISH_ENCODE(); -} - -ENCODE(OP_OnLevelMessage) -{ - ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); - SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); - OUT_str(Title); - OUT_str(Text); - OUT(Buttons); - OUT(Duration); - OUT(PopupID); - - eq->unknown4236 = 0x00000000; - eq->unknown4240 = 0xffffffff; - - FINISH_ENCODE(); -} - -ENCODE(OP_AltCurrencySell) -{ - ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); - SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - - OUT(merchant_entity_id); - eq->slot_id = ServerToSoFSlot(emu->slot_id); - OUT(charges); - OUT(cost); - FINISH_ENCODE(); -} - -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(color.color); - OUT(wear_slot_id); - FINISH_ENCODE(); -} - -ENCODE(OP_InspectRequest) { - ENCODE_LENGTH_EXACT(Inspect_Struct); - SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - OUT(TargetID); - OUT(PlayerID); - FINISH_ENCODE(); -} - -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_RaidInvite) { - 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(); -} - -DECODE(OP_AdventureMerchantSell) { - DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); - SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - IN(npcid); - emu->slot = SoFToServerSlot(eq->slot); - IN(charges); - IN(sell_price); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ApplyPoison) { - DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); - SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - - emu->inventorySlot = SoFToServerSlot(eq->inventorySlot); - IN(success); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ItemVerifyRequest) { - DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); - SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); - - emu->slot = SoFToServerSlot(eq->slot); - IN(target); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_Consume) { - DECODE_LENGTH_EXACT(structs::Consume_Struct); - SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); - - emu->slot = SoFToServerSlot(eq->slot); - IN(auto_consumed); - IN(type); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_CastSpell) { - DECODE_LENGTH_EXACT(structs::CastSpell_Struct); - SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - - IN(slot); - IN(spell_id); - emu->inventoryslot = SoFToServerSlot(eq->inventoryslot); - IN(target_id); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_DeleteItem) -{ - DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); - SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - emu->from_slot = SoFToServerSlot(eq->from_slot); - emu->to_slot = SoFToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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, eq->to_slot); - - emu->from_slot = SoFToServerSlot(eq->from_slot); - emu->to_slot = SoFToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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]); - } - IN(link_hash); - IN(icon); - - 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++) { - IN(filters[r]); - } - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } -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_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_CharacterCreate) { - DECODE_LENGTH_EXACT(structs::CharCreate_Struct); - SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - IN(class_); - IN(beardcolor); - IN(beard); - IN(hairstyle); - IN(gender); - IN(race); - - if(RuleB(World, EnableTutorialButton) && eq->tutorial) - emu->start_zone = RuleI(World, TutorialZoneID); - else - emu->start_zone = eq->start_zone; - - IN(haircolor); - IN(deity); - IN(STR); - IN(STA); - IN(AGI); - IN(DEX); - IN(WIS); - IN(INT); - IN(CHA); - IN(face); - IN(eyecolor1); - IN(eyecolor2); - IN(drakkin_heritage); - IN(drakkin_tattoo); - IN(drakkin_details); - - 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_GroupFollow) { - 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) { - 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_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct); - IN(entityid); - IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); - IN(slotid); - IN(bufffade); - 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 = SoFToServerSlot(eq->itemslot); - IN(quantity); - IN(price); - - 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_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_WearChange) { - DECODE_LENGTH_EXACT(structs::WearChange_Struct); - SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); - IN(spawn_id); - IN(material); - IN(unknown06); - IN(elite_material); - IN(color.color); - IN(wear_slot_id); - emu->hero_forge_model = 0; - emu->unknown18 = 0; - 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_LootItem) { - DECODE_LENGTH_EXACT(structs::LootingItem_Struct); - SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - IN(lootee); - IN(looter); - emu->slot_id = eq->slot_id - 1; - IN(auto_loot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TributeItem) { - DECODE_LENGTH_EXACT(structs::TributeItem_Struct); - SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); - - emu->slot = SoFToServerSlot(eq->slot); - IN(quantity); - IN(tribute_master_id); - IN(tribute_points); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ReadBook) { - DECODE_LENGTH_EXACT(structs::BookRequest_Struct); - SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); - - IN(type); - emu->invslot = SoFToServerSlot(eq->invslot); - emu->window = (uint8) eq->window; - strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TradeSkillCombine) { - DECODE_LENGTH_EXACT(structs::NewCombine_Struct); - SETUP_DIRECT_DECODE(NewCombine_Struct, structs::NewCombine_Struct); - - emu->container_slot = SoFToServerSlot(eq->container_slot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_AugmentItem) { - DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); - SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); - - emu->container_slot = SoFToServerSlot(eq->container_slot); - emu->augment_slot = eq->augment_slot; - - 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_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(); -} - - -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) { - 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->GetItem(); - //_log(NET__ERROR, "Serialize called for: %s", item->Name); - SoF::structs::ItemSerializationHeader hdr; - hdr.stacksize = stackable ? charges : 1; - hdr.unknown004 = 0; - - int32 slot_id = ServerToSoFSlot(slot_id_in); - - hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; - hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.unknown020 = 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.unknown056 = 0; - hdr.unknown060 = 0; - hdr.unknown061 = 0; - hdr.ItemClass = item->ItemClass; - - ss.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); - - 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)); - } - - SoF::structs::ItemBodyStruct ibs; - memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct)); - - uint32 adjusted_slots = item->Slots; - - // Conversions for Ammo and Power Source Slots - if(item->Slots & (1 << 21) & (1 << 22)) - { - // Do nothing - } - else - { - if(item->Slots & (1 << 21)) // Ammo Slot from Database + if (strlen(item->Lore) > 0) { - adjusted_slots -= (1 << 21); // Ammo Slot in Titanium - adjusted_slots += (1 << 22); // Ammo Slot in SoF + ss.write(item->Lore, strlen(item->Lore)); + ss.write((const char*)&null_term, sizeof(uint8)); } - - if(item->Slots & (1 << 22)) // Power Source Slot from Database + else { - adjusted_slots -= (1 << 22); // Non Existant Worn Slot in Titanium - adjusted_slots += (1 << 21); // Power Source Slot in SoF + ss.write((const char*)&null_term, sizeof(uint8)); } - } - 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 = adjusted_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.unknown6 = 0; - ibs.SkillModType = item->SkillModType; - 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; - ibs.RecLevel = item->RecLevel; - 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.ItemType = item->ItemType; - ibs.Material = item->Material; - ibs.unknown7 = 0; - ibs.EliteMaterial = item->EliteMaterial; - 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.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(SoF::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)); - } - - SoF::structs::ItemSecondaryBodyStruct isbs; - memset(&isbs, 0, sizeof(SoF::structs::ItemSecondaryBodyStruct)); - - isbs.augtype = item->AugType; - isbs.augrestrict = item->AugRestrict; - - for(int x = 0; x < 5; ++x) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; - } - - 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(SoF::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)); - } - - SoF::structs::ItemTertiaryBodyStruct itbs; - memset(&itbs, 0, sizeof(SoF::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.no_pet = item->NoPet; - - 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; - - ss.write((const char*)&itbs, sizeof(SoF::structs::ItemTertiaryBodyStruct)); - - // Effect Structures Broken down to allow variable length strings for effect names - int32 effect_unknown = 0; - - SoF::structs::ClickEffectStruct ices; - memset(&ices, 0, sizeof(SoF::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(SoF::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 - - SoF::structs::ProcEffectStruct ipes; - memset(&ipes, 0, sizeof(SoF::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(SoF::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 - - SoF::structs::WornEffectStruct iwes; - memset(&iwes, 0, sizeof(SoF::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(SoF::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 - - SoF::structs::WornEffectStruct ifes; - memset(&ifes, 0, sizeof(SoF::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(SoF::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 - - SoF::structs::WornEffectStruct ises; - memset(&ises, 0, sizeof(SoF::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(SoF::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 - // End of Effects - - SoF::structs::ItemQuaternaryBodyStruct iqbs; - memset(&iqbs, 0, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); - - iqbs.scriptfileid = item->ScriptFileID; - iqbs.quest_item = item->QuestItemFlag; - iqbs.unknown15 = 0xffffffff; - - iqbs.Purity = item->Purity; - 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.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); + if (strlen(item->IDFile) > 0) + { + ss.write(item->IDFile, strlen(item->IDFile)); + ss.write((const char*)&null_term, sizeof(uint8)); } - } - - ss.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); - - for(int x = 0; x < 10; ++x) { - - if(SubSerializations[x]) { - - ss.write((const char*)&x, sizeof(uint32)); - - ss.write(SubSerializations[x], SubLengths[x]); - - safe_delete_array(SubSerializations[x]); + else + { + ss.write((const char*)&null_term, sizeof(uint8)); } + + SoF::structs::ItemBodyStruct ibs; + memset(&ibs, 0, sizeof(SoF::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.unknown6 = 0; + ibs.SkillModType = item->SkillModType; + 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; + ibs.RecLevel = item->RecLevel; + 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.ItemType = item->ItemType; + ibs.Material = item->Material; + ibs.unknown7 = 0; + ibs.EliteMaterial = item->EliteMaterial; + 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.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(SoF::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)); + } + + SoF::structs::ItemSecondaryBodyStruct isbs; + memset(&isbs, 0, sizeof(SoF::structs::ItemSecondaryBodyStruct)); + + isbs.augtype = item->AugType; + isbs.augrestrict = item->AugRestrict; + + for (int x = 0; x < 5; ++x) + { + isbs.augslots[x].type = item->AugSlotType[x]; + isbs.augslots[x].visible = item->AugSlotVisible[x]; + isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + } + + 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(SoF::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)); + } + + SoF::structs::ItemTertiaryBodyStruct itbs; + memset(&itbs, 0, sizeof(SoF::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.no_pet = item->NoPet; + + 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; + + ss.write((const char*)&itbs, sizeof(SoF::structs::ItemTertiaryBodyStruct)); + + // Effect Structures Broken down to allow variable length strings for effect names + int32 effect_unknown = 0; + + SoF::structs::ClickEffectStruct ices; + memset(&ices, 0, sizeof(SoF::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(SoF::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 + + SoF::structs::ProcEffectStruct ipes; + memset(&ipes, 0, sizeof(SoF::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(SoF::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 + + SoF::structs::WornEffectStruct iwes; + memset(&iwes, 0, sizeof(SoF::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(SoF::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 + + SoF::structs::WornEffectStruct ifes; + memset(&ifes, 0, sizeof(SoF::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(SoF::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 + + SoF::structs::WornEffectStruct ises; + memset(&ises, 0, sizeof(SoF::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(SoF::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 + // End of Effects + + SoF::structs::ItemQuaternaryBodyStruct iqbs; + memset(&iqbs, 0, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); + + iqbs.scriptfileid = item->ScriptFileID; + iqbs.quest_item = item->QuestItemFlag; + iqbs.unknown15 = 0xffffffff; + + iqbs.Purity = item->Purity; + 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.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(SoF::structs::ItemQuaternaryBodyStruct)); + + for (int x = 0; x < 10; ++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; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + static inline uint32 ServerToSoFSlot(uint32 ServerSlot) + { + uint32 SoFSlot = 0; - *length = ss.tellp(); - return item_serial; + if (ServerSlot >= MainAmmo && ServerSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + SoFSlot = ServerSlot + 1; + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) + SoFSlot = ServerSlot + 11; + else if (ServerSlot >= EmuConstants::BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) + SoFSlot = ServerSlot + 1; + else if (ServerSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) + SoFSlot = ServerSlot + 1; + else if (ServerSlot == MainPowerSource) + SoFSlot = slots::MainPowerSource; + else + SoFSlot = ServerSlot; + + return SoFSlot; + } + + static inline uint32 ServerToSoFCorpseSlot(uint32 ServerCorpse) + { + //uint32 SoFCorpse; + } + + static inline uint32 SoFToServerSlot(uint32 SoFSlot) + { + uint32 ServerSlot = 0; + + if (SoFSlot >= slots::MainAmmo && SoFSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + ServerSlot = SoFSlot - 1; + else if (SoFSlot >= consts::GENERAL_BAGS_BEGIN && SoFSlot <= consts::CURSOR_BAG_END) + ServerSlot = SoFSlot - 11; + else if (SoFSlot >= consts::BANK_BAGS_BEGIN && SoFSlot <= consts::BANK_BAGS_END) + ServerSlot = SoFSlot - 1; + else if (SoFSlot >= consts::SHARED_BANK_BAGS_BEGIN && SoFSlot <= consts::SHARED_BANK_BAGS_END) + ServerSlot = SoFSlot - 1; + else if (SoFSlot == slots::MainPowerSource) + ServerSlot = MainPowerSource; + else + ServerSlot = SoFSlot; + + return ServerSlot; + } + + static inline uint32 SoFToServerCorpseSlot(uint32 SoFCorpse) + { + //uint32 ServerCorpse; + } } - -DECODE(OP_AltCurrencySellSelection) -{ - DECODE_LENGTH_EXACT(structs::AltCurrencySelectItem_Struct); - SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); - IN(merchant_entity_id); - emu->slot_id = SoFToServerSlot(eq->slot_id); - 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 = SoFToServerSlot(eq->slot_id); - IN(charges); - IN(cost); - FINISH_DIRECT_DECODE(); -} - - -} //end namespace SoF - - - - +// end namespace SoF diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 77d87cb7d..eaa7b3b10 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1,4 +1,3 @@ - #include "../debug.h" #include "titanium.h" #include "../opcodemgr.h" @@ -13,1475 +12,1515 @@ #include "titanium_structs.h" #include -namespace Titanium { +namespace Titanium +{ + static const char *name = "Titanium"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; -static const char *name = "Titanium"; -static OpcodeManager *opcodes = nullptr; -static Strategy struct_strategy; + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); -char *SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + // server to client inventory location converters + static inline uint32 ServerToTitaniumSlot(uint32 ServerSlot); + static inline uint32 ServerToTitaniumCorpseSlot(uint32 ServerCorpse); -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; + // client to server inventory location converters + static inline uint32 TitaniumToServerSlot(uint32 TitaniumSlot); + static inline uint32 TitaniumToServerCorpseSlot(uint32 TitaniumCorpse); + + 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); } } - //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 "titanium_ops.h" } -} + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } - -Strategy::Strategy() -: StructStrategy() -{ - //all opcodes default to passthrough. - #include "ss_register.h" - #include "titanium_ops.h" -} - -std::string Strategy::Describe() const { - std::string r; - r += "Patch "; - r += name; - return(r); -} - -const EQClientVersion Strategy::ClientVersion() const -{ - return EQClientTitanium; -} + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientTitanium; + } #include "ss_define.h" +// ENCODE methods + EAT_ENCODE(OP_GuildMemberLevelUpdate); // added ; -/* -// Converts Server Slot IDs to Titanium Slot IDs for use in Encodes -static inline uint32 ServerToTitaniumSlot(uint32 ServerSlot) { - uint32 TitaniumSlot; - // reserved -} -*/ -/* -// Converts Titanium Slot IDs to Server Slot IDs for use in Decodes -static inline uint32 TitaniumToServerSlot(uint32 TitaniumSlot) { - uint32 ServerSlot; - // reserved -} -*/ -/* -// Converts Server Corpse Slot IDs to Titanium Corpse Slot IDs for use in Encodes -static inline uint32 ServerToTitaniumCorpseSlot(uint32 ServerCorpse) { - uint32 TitaniumCorpse; - // reserved -} -*/ -/* -// Converts Titanium Corpse Slot IDs to Server Corpse Slot IDs for use in Decodes -static inline uint32 TitaniumToServerCorpseSlot(uint32 TitaniumCorpse) { - uint32 ServerCorpse; - // reserved -} -*/ - - -EAT_ENCODE(OP_ZoneServerReady) -EAT_ENCODE(OP_GuildMemberLevelUpdate) - -ENCODE(OP_SendCharInfo) { - ENCODE_LENGTH_EXACT(CharacterSelect_Struct); - SETUP_DIRECT_ENCODE(CharacterSelect_Struct, structs::CharacterSelect_Struct); - int r; - for(r = 0; r < 10; r++) { - OUT(zone[r]); - OUT(eyecolor1[r]); - OUT(eyecolor2[r]); - OUT(hairstyle[r]); - OUT(primary[r]); - if(emu->race[r] > 473) - eq->race[r] = 1; - else - eq->race[r] = emu->race[r]; - OUT(class_[r]); - OUT_str(name[r]); - OUT(gender[r]); - OUT(level[r]); - OUT(secondary[r]); - OUT(face[r]); - OUT(beard[r]); - int k; - for(k = 0; k < 9; k++) { - OUT(equip[r][k]); - OUT(cs_colors[r][k].color); - } - OUT(haircolor[r]); - OUT(gohome[r]); - OUT(tutorial[r]); - OUT(deity[r]); - OUT(beardcolor[r]); - eq->unknown820[r] = 0xFF; - eq->unknown902[r] = 0xFF; - } - 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 Titanium - // clientver 1 is for all clients and 3 is for Titanium - if (emu->clientver <= 3 ) + EAT_ENCODE(OP_ZoneServerReady); // added ; + + ENCODE(OP_Action) { - 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; - OUT(class_type); - OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); + + OUT(target); + OUT(source); + OUT(level); + OUT(instrument_mod); + OUT(sequence); OUT(type); - OUT(spellid); - OUT(spell_type); - OUT(spell_refresh); - OUT(classes); - OUT(berserker); - OUT(max_level); - OUT(last_id); - OUT(next_id); - OUT(cost2); - OUT(unknown80[0]); - OUT(unknown80[1]); - 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); - } + //OUT(damage); + OUT(spell); + OUT(buff_unknown); // if this is 4, a buff icon is made + + FINISH_ENCODE(); } - 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_PlayerProfile) { - SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); - - uint32 r; - - eq->available_slots=0xffffffff; - memset(eq->unknown4184, 0xff, sizeof(eq->unknown4184)); - memset(eq->unknown04396, 0xff, sizeof(eq->unknown04396)); - -// OUT(checksum); - OUT(gender); - OUT(race); - OUT(class_); -// OUT(unknown00016); - OUT(level); - eq->level1 = emu->level; -// OUT(unknown00022[2]); - for(r = 0; r < 5; r++) { - OUT(binds[r].zoneId); - OUT(binds[r].x); - OUT(binds[r].y); - OUT(binds[r].z); - OUT(binds[r].heading); - } - OUT(deity); - OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); - OUT(abilitySlotRefresh); - OUT(haircolor); - OUT(beardcolor); - OUT(eyecolor1); - OUT(eyecolor2); - OUT(hairstyle); - OUT(beard); -// OUT(unknown00178[10]); - for(r = 0; r < 9; r++) { - OUT(item_material[r]); - OUT(item_tint[r].color); - } -// OUT(unknown00224[48]); - for(r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { - OUT(aa_array[r].AA); - OUT(aa_array[r].value); - } -// OUT(unknown02220[4]); - OUT(points); - OUT(mana); - OUT(cur_hp); - OUT(STR); - OUT(STA); - OUT(CHA); - OUT(DEX); - OUT(INT); - OUT(AGI); - OUT(WIS); - OUT(face); -// OUT(unknown02264[47]); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); -// OUT(unknown4184[448]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); -// OUT(unknown04396[32]); - OUT(platinum); - OUT(gold); - OUT(silver); - OUT(copper); - OUT(platinum_cursor); - OUT(gold_cursor); - OUT(silver_cursor); - OUT(copper_cursor); - - OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) - -// OUT(unknown04760[236]); - OUT(toxicity); - OUT(thirst_level); - OUT(hunger_level); - for(r = 0; r < structs::BUFF_COUNT; r++) { - OUT(buffs[r].slotid); - OUT(buffs[r].level); - OUT(buffs[r].bard_modifier); - OUT(buffs[r].effect); - OUT(buffs[r].spellid); - OUT(buffs[r].duration); - OUT(buffs[r].counters); - OUT(buffs[r].player_id); - } - for(r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { - OUT(disciplines.values[r]); - } -// OUT(unknown05008[360]); -// OUT_array(recastTimers, structs::MAX_RECAST_TYPES); - OUT(endurance); - OUT(aapoints_spent); - OUT(aapoints); -// OUT(unknown06160[4]); - for(r = 0; r < structs::MAX_PLAYER_BANDOLIER; r++) { - OUT_str(bandoliers[r].name); - uint32 k; - for(k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { - OUT(bandoliers[r].items[k].item_id); - OUT(bandoliers[r].items[k].icon); - OUT_str(bandoliers[r].items[k].item_name); - } - } -// OUT(unknown07444[5120]); - for(r = 0; r < structs::MAX_PLAYER_BANDOLIER_ITEMS; r++) { - OUT(potionbelt.items[r].item_id); - OUT(potionbelt.items[r].icon); - OUT_str(potionbelt.items[r].item_name); - } -// OUT(unknown12852[8]); -// OUT(unknown12864[76]); - OUT_str(name); - OUT_str(last_name); - OUT(guild_id); - OUT(birthday); - OUT(lastlogin); - OUT(timePlayedMin); - OUT(pvp); - OUT(anon); - OUT(gm); - OUT(guildrank); - OUT(guildbanker); -// OUT(unknown13054[8]); - OUT(exp); -// OUT(unknown13072[12]); - OUT(timeentitledonaccount); - OUT_array(languages, structs::MAX_PP_LANGUAGE); -// OUT(unknown13109[7]); - OUT(x); - OUT(y); - OUT(z); - OUT(heading); -// OUT(unknown13132[4]); - OUT(platinum_bank); - OUT(gold_bank); - OUT(silver_bank); - OUT(copper_bank); - OUT(platinum_shared); -// OUT(unknown13156[84]); - OUT(expansions); -// OUT(unknown13244[12]); - OUT(autosplit); -// OUT(unknown13260[16]); - OUT(zone_id); - OUT(zoneInstance); - for(r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { - OUT_str(groupMembers[r]); - } - strcpy(eq->groupLeader, emu->groupMembers[0]); -// OUT_str(groupLeader); -// OUT(unknown13728[660]); - OUT(entityid); - OUT(leadAAActive); -// OUT(unknown14392[4]); - OUT(ldon_points_guk); - OUT(ldon_points_mir); - OUT(ldon_points_mmc); - OUT(ldon_points_ruj); - OUT(ldon_points_tak); - OUT(ldon_points_available); -// OUT(unknown14420[132]); - OUT(tribute_time_remaining); - OUT(career_tribute_points); -// OUT(unknown7208); - OUT(tribute_points); -// OUT(unknown7216); - OUT(tribute_active); - for(r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { - OUT(tributes[r].tribute); - OUT(tributes[r].tier); - } -// OUT(unknown14616[8]); - OUT(group_leadership_exp); - OUT(raid_leadership_exp); - OUT(group_leadership_points); - OUT(raid_leadership_points); - OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); -// OUT(unknown14772[128]); - OUT(air_remaining); - OUT(PVPKills); - OUT(PVPDeaths); - OUT(PVPCurrentPoints); - OUT(PVPCareerPoints); - OUT(PVPBestKillStreak); - OUT(PVPWorstDeathStreak); - OUT(PVPCurrentKillStreak); -// OUT(unknown14932[4580]); - OUT(expAA); -// OUT(unknown19516[40]); - OUT(currentRadCrystals); - OUT(careerRadCrystals); - OUT(currentEbonCrystals); - OUT(careerEbonCrystals); - OUT(groupAutoconsent); - OUT(raidAutoconsent); - OUT(guildAutoconsent); -// OUT(unknown19575[5]); - eq->level3 = emu->level; - eq->showhelm = emu->showhelm; -// OUT(unknown19584[4]); -// OUT(unknown19588); - - -const uint8 bytes[] = { -0x78,0x03,0x00,0x00,0x1A,0x04,0x00,0x00,0x1A,0x04,0x00,0x00,0x19,0x00,0x00,0x00, -0x19,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00, -0x0F,0x00,0x00,0x00,0x1F,0x85,0xEB,0x3E,0x33,0x33,0x33,0x3F,0x09,0x00,0x00,0x00, -0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x14 -}; - memcpy(eq->unknown12864, bytes, sizeof(bytes)); - - - - //set the checksum... - CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct)-4); - - FINISH_ENCODE(); -} - -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) + ENCODE(OP_BazaarSearch) { - _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; - } + if (((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) { - in->size = sizeof(structs::Track_Struct) * EntryCount; - in->pBuffer = new unsigned char[in->size]; - structs::Track_Struct *eq = (structs::Track_Struct *) in->pBuffer; - - for(int i = 0; i < EntryCount; ++i, ++eq, ++emu) - { - OUT(entityid); - OUT(padding002); - OUT(distance); - } - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); } -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; - } - - //make the EQ struct. - in->size = sizeof(structs::Spawn_Struct)*entrycount; - in->pBuffer = new unsigned char[in->size]; - structs::Spawn_Struct *eq = (structs::Spawn_Struct *) in->pBuffer; - - //zero out the packet. We could avoid this memset by setting all fields (including unknowns) - //in the loop. - memset(in->pBuffer, 0, in->size); - - //do the transform... - int r; - int k; - for(r = 0; r < entrycount; r++, eq++, emu++) { -// eq->unknown0000 = emu->unknown0000; - eq->gm = emu->gm; -// eq->unknown0003 = emu->unknown0003; - eq->aaitle = emu->aaitle; -// eq->unknown0004 = emu->unknown0004; - eq->anon = emu->anon; - eq->face = emu->face; - strcpy(eq->name, emu->name); - eq->deity = emu->deity; -// eq->unknown0073 = emu->unknown0073; - eq->size = emu->size; -// eq->unknown0079 = emu->unknown0079; - eq->NPC = emu->NPC; - eq->invis = emu->invis; - eq->haircolor = emu->haircolor; - eq->curHp = emu->curHp; - eq->max_hp = emu->max_hp; - eq->findable = emu->findable; -// eq->unknown0089[5] = emu->unknown0089[5]; - eq->deltaHeading = emu->deltaHeading; - eq->x = emu->x; -// eq->padding0054 = emu->padding0054; - eq->y = emu->y; - eq->animation = emu->animation; -// eq->padding0058 = emu->padding0058; - eq->z = emu->z; - eq->deltaY = emu->deltaY; - eq->deltaX = emu->deltaX; - eq->heading = emu->heading; -// eq->padding0066 = emu->padding0066; - eq->deltaZ = emu->deltaZ; -// eq->padding0070 = emu->padding0070; - eq->eyecolor1 = emu->eyecolor1; -// eq->unknown0115[24] = emu->unknown0115[24]; - eq->showhelm = emu->showhelm; -// eq->unknown0140[4] = emu->unknown0140[4]; - eq->is_npc = emu->is_npc; - eq->hairstyle = emu->hairstyle; - - //if(emu->gender == 1){ - // eq->hairstyle = eq->hairstyle == 0xFF ? 0 : eq->hairstyle; - //} - - eq->beardcolor = emu->beardcolor; -// eq->unknown0147[4] = emu->unknown0147[4]; - eq->level = emu->level; -// eq->unknown0259[4] = emu->unknown0259[4]; - eq->beard = emu->beard; - strcpy(eq->suffix, emu->suffix); - eq->petOwnerId = emu->petOwnerId; - eq->guildrank = emu->guildrank; -// eq->unknown0194[3] = emu->unknown0194[3]; - for(k = 0; k < 9; k++) { - eq->equipment[k] = emu->equipment[k]; - eq->colors[k].color = emu->colors[k].color; - } - for(k = 0; k < 8; k++) { - eq->set_to_0xFF[k] = 0xFF; + EQApplicationPacket *in = *p; + *p = nullptr; + dest->FastQueuePacket(&in, ack_req); + return; } - eq->runspeed = emu->runspeed; - eq->afk = emu->afk; - eq->guildID = emu->guildID; - strcpy(eq->title, emu->title); -// eq->unknown0274 = emu->unknown0274; - eq->helm = emu->helm; - if(emu->race > 473) - eq->race = 1; - else - eq->race = emu->race; -// eq->unknown0288 = emu->unknown0288; - strcpy(eq->lastName, emu->lastName); - eq->walkspeed = emu->walkspeed; -// eq->unknown0328 = emu->unknown0328; - eq->is_pet = emu->is_pet; - eq->light = emu->light; - eq->class_ = emu->class_; - eq->eyecolor2 = emu->eyecolor2; -// eq->unknown0333 = emu->unknown0333; - eq->flymode = emu->flymode; - eq->gender = emu->gender; - eq->bodytype = emu->bodytype; -// eq->unknown0336[3] = emu->unknown0336[3]; - eq->equip_chest2 = emu->equip_chest2; - eq->spawnId = emu->spawnId; -// eq->unknown0344[4] = emu->unknown0344[4]; - eq->lfg = emu->lfg; - - /* - if (emu->face == 99) {eq->face = 0;} - if (emu->eyecolor1 == 99) {eq->eyecolor1 = 0;} - if (emu->eyecolor2 == 99) {eq->eyecolor2 = 0;} - if (emu->hairstyle == 99) {eq->hairstyle = 0;} - if (emu->haircolor == 99) {eq->haircolor = 0;} - if (emu->beard == 99) {eq->beard = 0;} - if (emu->beardcolor == 99) {eq->beardcolor = 0;} - */ - - } - - - //kill off the emu structure and send the eq packet. - delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } -ENCODE(OP_ItemPacket) { - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; - - //store away the emu struct - 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+5; // ItemPacketType + Serialization + \0 - 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+1); - - delete[] __emu_buffer; - safe_delete_array(serialized); - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_CharInventory) { - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; - - //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; - - //do the transform... - int r; - std::string serial_string; - for(r = 0; r < itemcount; r++, eq++) { - uint32 length; - char *serialized=SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0); - if (serialized) { - serial_string.append(serialized,length+1); - safe_delete_array(serialized); - } else { - _log(NET__STRUCTS, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.",eq->slot_id); - } - - } - - in->size = serial_string.length(); - in->pBuffer = new unsigned char[in->size]; - memcpy(in->pBuffer,serial_string.c_str(),serial_string.length()); - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_BazaarSearch) { - - if(((*p)->size == sizeof(BazaarReturnDone_Struct)) || ((*p)->size == sizeof(BazaarWelcome_Struct))) { - + //consume the packet EQApplicationPacket *in = *p; *p = nullptr; + + //store away the emu struct + unsigned char *__emu_buffer = in->pBuffer; + BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *)__emu_buffer; + + //determine and verify length + 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; + } + + //make the EQ struct. + in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount; + in->pBuffer = new unsigned char[in->size]; + structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer; + + //zero out the packet. We could avoid this memset by setting all fields (including unknowns) in the loop. + memset(in->pBuffer, 0, in->size); + + for (int i = 0; i < entrycount; i++, eq++, emu++) { + eq->Beginning.Action = emu->Beginning.Action; + eq->Beginning.Unknown001 = emu->Beginning.Unknown001; + eq->Beginning.Unknown002 = emu->Beginning.Unknown002; + eq->NumItems = emu->NumItems; + eq->SerialNumber = emu->SerialNumber; + eq->SellerID = emu->SellerID; + eq->Cost = emu->Cost; + eq->ItemStat = emu->ItemStat; + strcpy(eq->ItemName, emu->ItemName); + } + + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); - return; } - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; + ENCODE(OP_BecomeTrader) + { + ENCODE_LENGTH_EXACT(BecomeTrader_Struct); + SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct); - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - BazaarSearchResults_Struct *emu = (BazaarSearchResults_Struct *) __emu_buffer; + OUT(ID); + OUT(Code); - //determine and verify length - 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; + FINISH_ENCODE(); } - //make the EQ struct. - in->size = sizeof(structs::BazaarSearchResults_Struct)*entrycount; - in->pBuffer = new unsigned char[in->size]; - structs::BazaarSearchResults_Struct *eq = (structs::BazaarSearchResults_Struct *) in->pBuffer; - - //zero out the packet. We could avoid this memset by setting all fields (including unknowns) - //in the loop. - memset(in->pBuffer, 0, in->size); - - for(int i=0; iBeginning.Action = emu->Beginning.Action; - eq->Beginning.Unknown001 = emu->Beginning.Unknown001; - eq->Beginning.Unknown002 = emu->Beginning.Unknown002; - eq->NumItems = emu->NumItems; - eq->SerialNumber = emu->SerialNumber; - eq->SellerID = emu->SellerID; - eq->Cost = emu->Cost; - eq->ItemStat = emu->ItemStat; - strcpy(eq->ItemName, emu->ItemName); - } - - delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); - - -} - -ENCODE(OP_Trader) { - - if((*p)->size != sizeof(TraderBuy_Struct)) { + ENCODE(OP_CharInventory) + { + //consume the packet EQApplicationPacket *in = *p; *p = nullptr; + + //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; + + //do the transform... + int r; + std::string serial_string; + for (r = 0; r < itemcount; r++, eq++) { + uint32 length; + char *serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &length, 0); + if (serialized) { + serial_string.append(serialized, length + 1); + safe_delete_array(serialized); + } + else { + _log(NET__STRUCTS, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + } + + } + + in->size = serial_string.length(); + in->pBuffer = new unsigned char[in->size]; + memcpy(in->pBuffer, serial_string.c_str(), serial_string.length()); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); - return; } - ENCODE_FORWARD(OP_TraderBuy); -} -ENCODE(OP_TraderBuy) { + ENCODE(OP_DeleteSpawn) + { + SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); - ENCODE_LENGTH_EXACT(TraderBuy_Struct); - SETUP_DIRECT_ENCODE(TraderBuy_Struct, structs::TraderBuy_Struct); + OUT(spawn_id); - OUT(Action); - OUT(Price); - OUT(TraderID); - memcpy(eq->ItemName, emu->ItemName, sizeof(eq->ItemName)); - OUT(ItemID); - OUT(Quantity); - OUT(AlreadySold); + FINISH_ENCODE(); + } - 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); -ENCODE(OP_GuildMemberList) { - //consume the packet - EQApplicationPacket *in = *p; - *p = nullptr; + for (uint32 i = 0; i < emu->count; ++i) + { + OUT(entries[i].x); + OUT(entries[i].y); + OUT(entries[i].z); + } - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - Internal_GuildMembers_Struct *emu = (Internal_GuildMembers_Struct *) in->pBuffer; + FINISH_ENCODE(); + } + ENCODE(OP_DzExpeditionEndsWarning) + { + ENCODE_LENGTH_EXACT(ExpeditionExpireWarning); + SETUP_DIRECT_ENCODE(ExpeditionExpireWarning, structs::ExpeditionExpireWarning); + OUT(minutes_remaining); - //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. + FINISH_ENCODE(); + } - uint8 *buffer; - buffer = in->pBuffer; + ENCODE(OP_DzExpeditionInfo) + { + ENCODE_LENGTH_EXACT(ExpeditionInfo_Struct); + SETUP_DIRECT_ENCODE(ExpeditionInfo_Struct, structs::ExpeditionInfo_Struct); - //easier way to setup GuildMembers_Struct - //set prefix name - strcpy((char *)buffer, emu->player_name); - buffer += pnl; - *buffer = '\0'; - buffer++; + OUT(max_players); + eq->enabled_max = 1; + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->leader_name, emu->leader_name); - //add member count. - *((uint32 *) buffer) = htonl( emu->count ); - buffer += sizeof(uint32); + FINISH_ENCODE(); + } - 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 + 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); + + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->player_name, emu->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_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++; + + //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 + + 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; + structs::GuildMemberEntry_Struct *e = (structs::GuildMemberEntry_Struct *) buffer; - uint32 r; - for(r = 0; r < emu->count; r++, emu_e++) { + uint32 r; + for (r = 0; r < emu->count; r++, emu_e++) { - //the order we set things here must match the struct + //the order we set things here must match the struct -//nice helper macro -/*#define SlideStructString(field, str) \ - strcpy(e->field, str.c_str()); \ - e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ + //nice helper macro + /*#define SlideStructString(field, str) \ + strcpy(e->field, str.c_str()); \ + e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ #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_); - PutFieldN(rank); - PutFieldN(time_last_on); - PutFieldN(tribute_enable); - 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); + { \ + 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_); + PutFieldN(rank); + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + 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); #undef SlideStructString #undef PutFieldN - e++; + e++; + } } - } - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_ReadBook) { - - EQApplicationPacket *in = *p; - *p = nullptr; - - unsigned char *__emu_buffer = in->pBuffer; - - BookText_Struct *emu_BookText_Struct = (BookText_Struct *)__emu_buffer; - - in->size = sizeof(structs::BookText_Struct) + strlen(emu_BookText_Struct->booktext); - - in->pBuffer = new unsigned char[in->size]; - - structs::BookText_Struct *eq_BookText_Struct = (structs::BookText_Struct*)in->pBuffer; - - eq_BookText_Struct->window = emu_BookText_Struct->window; - eq_BookText_Struct->type = emu_BookText_Struct->type; - strcpy(eq_BookText_Struct->booktext, emu_BookText_Struct->booktext); - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); - -} - -ENCODE(OP_Illusion) { - ENCODE_LENGTH_EXACT(Illusion_Struct); - SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct); - OUT(spawnid); - OUT_str(charname); - if(emu->race > 473){ - eq->race = 1; - } - else { - OUT(race); - } - OUT(gender); - OUT(texture); - OUT(helmtexture); - OUT(face); - OUT(hairstyle); - OUT(haircolor); - OUT(beard); - OUT(beardcolor); - OUT(size); - /* - //Test code for identifying the structure - uint8 ofs; - uint8 val; - ofs = emu->texture; - val = emu->face; - ((uint8*)eq)[ofs % 168] = val; - */ - 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(uint32 i = 0; i < count; ++i) - { - structs::VeteranReward *vr = (structs::VeteranReward*)data; - InternalVeteranReward *ivr = (InternalVeteranReward*)old_data; - - vr->claim_id = ivr->claim_id; - vr->item.item_id = ivr->items[0].item_id; - strcpy(vr->item.item_name, ivr->items[0].item_name); - - old_data += sizeof(InternalVeteranReward); - data += sizeof(structs::VeteranReward); - } - - dest->FastQueuePacket(&outapp_create); - delete inapp; -} - -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 <= 20; r++) { - strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r])); - } - - // move arrow item down to last element in titanium array - strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21])); - - int k; - for (k = 0; k <= 20; k++) { - OUT(itemicons[k]); - } - - // move arrow icon down to last element in titanium array - eq->itemicons[21] = emu->itemicons[22]; - - strn0cpy(eq->text, emu->text, sizeof(eq->text)); - - FINISH_ENCODE(); -} - -ENCODE(OP_RespondAA) { - ENCODE_LENGTH_EXACT(AATable_Struct); - SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); - - unsigned int r; - for(r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { - OUT(aa_list[r].aa_skill); - OUT(aa_list[r].aa_value); - } - - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteSpawn) { - SETUP_DIRECT_ENCODE(DeleteSpawn_Struct, structs::DeleteSpawn_Struct); - OUT(spawn_id); - FINISH_ENCODE(); -} - -ENCODE(OP_WearChange) { - ENCODE_LENGTH_EXACT(WearChange_Struct); - SETUP_DIRECT_ENCODE(WearChange_Struct, structs::WearChange_Struct); - OUT(spawn_id); - OUT(material); - OUT(color.color); - OUT(wear_slot_id); - 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->enabled_max = 1; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); - 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_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_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_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_DzJoinExpeditionConfirm) -{ - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - FINISH_ENCODE(); -} - -ENCODE(OP_Action) { - ENCODE_LENGTH_EXACT(Action_Struct); - SETUP_DIRECT_ENCODE(Action_Struct, structs::Action_Struct); - OUT(target); - OUT(source); - OUT(level); - OUT(instrument_mod); - OUT(sequence); - OUT(type); - //OUT(damage); - OUT(spell); - OUT(buff_unknown); // if this is 4, a buff icon is made - FINISH_ENCODE(); -} - -ENCODE(OP_BecomeTrader) -{ - ENCODE_LENGTH_EXACT(BecomeTrader_Struct); - SETUP_DIRECT_ENCODE(BecomeTrader_Struct, structs::BecomeTrader_Struct); - OUT(ID); - OUT(Code); - FINISH_ENCODE(); -} - -ENCODE(OP_PetBuffWindow) -{ - ENCODE_LENGTH_EXACT(PetBuff_Struct); - SETUP_DIRECT_ENCODE(PetBuff_Struct, PetBuff_Struct); - - OUT(petid); - OUT(buffcount); - - int EQBuffSlot = 0; - - for(uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) - { - if(emu->spellid[EmuBuffSlot]) - { - eq->spellid[EQBuffSlot] = emu->spellid[EmuBuffSlot]; - eq->ticsremaining[EQBuffSlot++] = emu->ticsremaining[EmuBuffSlot]; - } - } - - FINISH_ENCODE(); -} - -ENCODE(OP_OnLevelMessage) -{ - ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); - SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); - OUT_str(Title); - OUT_str(Text); - OUT(Buttons); - OUT(Duration); - OUT(PopupID); - - eq->unknown4236 = 0x00000000; - eq->unknown4240 = 0xffffffff; - - FINISH_ENCODE(); -} - -ENCODE(OP_InspectRequest) { - ENCODE_LENGTH_EXACT(Inspect_Struct); - SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - OUT(TargetID); - OUT(PlayerID); - FINISH_ENCODE(); -} - -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_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 <= 20; r++) { - strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r])); - } - - // move arrow item up to last element in server array - strn0cpy(emu->itemnames[21], "", sizeof(emu->itemnames[21])); - strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22])); - - int k; - for (k = 0; k <= 20; k++) { - IN(itemicons[k]); - } - - // move arrow icon up to last element in server array - emu->itemicons[21] = 0xFFFFFFFF; - emu->itemicons[22] = eq->itemicons[21]; - - strn0cpy(emu->text, eq->text, sizeof(emu->text)); - - FINISH_DIRECT_DECODE(); -} - -ENCODE(OP_LFGuild) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - uint32 Command = in->ReadUInt32(); - - if(Command != 0) - { + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); - return; } - EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, sizeof(structs::LFGuild_PlayerToggle_Struct)); + ENCODE(OP_Illusion) + { + ENCODE_LENGTH_EXACT(Illusion_Struct); + SETUP_DIRECT_ENCODE(Illusion_Struct, structs::Illusion_Struct); - memcpy(outapp->pBuffer, in->pBuffer, sizeof(structs::LFGuild_PlayerToggle_Struct)); + OUT(spawnid); + OUT_str(charname); - dest->FastQueuePacket(&outapp, ack_req); + if (emu->race > 473) + eq->race = 1; + else + OUT(race); - delete in; -} + OUT(gender); + OUT(texture); + OUT(helmtexture); + OUT(face); + OUT(hairstyle); + OUT(haircolor); + OUT(beard); + OUT(beardcolor); + OUT(size); + /* + //Test code for identifying the structure + uint8 ofs; + uint8 val; + ofs = emu->texture; + val = emu->face; + ((uint8*)eq)[ofs % 168] = val; + */ -DECODE(OP_WearChange) { - DECODE_LENGTH_EXACT(structs::WearChange_Struct); - SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); - IN(spawn_id); - IN(material); - IN(color.color); - IN(wear_slot_id); - emu->unknown06 = 0; - emu->elite_material = 0; - emu->hero_forge_model = 0; - emu->unknown18 = 0; - 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_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]); + FINISH_ENCODE(); } - IN(link_hash); - FINISH_DIRECT_DECODE(); -} + ENCODE(OP_InspectAnswer) + { + ENCODE_LENGTH_EXACT(InspectResponse_Struct); + SETUP_DIRECT_ENCODE(InspectResponse_Struct, structs::InspectResponse_Struct); -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++) { - IN(filters[r]); - } - FINISH_DIRECT_DECODE(); -} + OUT(TargetID); + OUT(playerid); - -DECODE(OP_CharacterCreate) { - DECODE_LENGTH_EXACT(structs::CharCreate_Struct); - SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - IN(class_); - IN(beardcolor); - IN(beard); - IN(haircolor); - IN(gender); - IN(race); - IN(start_zone); - IN(hairstyle); - IN(deity); - IN(STR); - IN(STA); - IN(AGI); - IN(DEX); - IN(WIS); - IN(INT); - IN(CHA); - IN(face); - IN(eyecolor1); - IN(eyecolor2); - 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); - emu->type = 3; - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ReadBook) { - DECODE_LENGTH_ATLEAST(structs::BookRequest_Struct); - SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); - - IN(window); - IN(type); - strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); - - 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); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_LFGuild) -{ - uint32 Command = __packet->ReadUInt32(); - - if(Command != 0) - return; - - SETUP_DIRECT_DECODE(LFGuild_PlayerToggle_Struct, structs::LFGuild_PlayerToggle_Struct); - memcpy(emu, eq, sizeof(structs::LFGuild_PlayerToggle_Struct)); - memset(emu->Unknown612, 0, sizeof(emu->Unknown612)); - - FINISH_DIRECT_DECODE(); -} - -char *SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth) { - char *serialization = nullptr; - char *instance = nullptr; - const char *protection=(const char *)"\\\\\\\\\\"; - char *sub_items[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; - bool stackable=inst->IsStackable(); - uint32 merchant_slot=inst->GetMerchantSlot(); - int16 charges=inst->GetCharges(); - const Item_Struct *item=inst->GetItem(); - int i; - uint32 sub_length; - - MakeAnyLenString(&instance, - "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", - stackable ? charges : 0, - 0, - (merchant_slot==0) ? slot_id : merchant_slot, - inst->GetPrice(), - (merchant_slot==0) ? 1 : inst->GetMerchantCount(), - 0, - //merchant_slot, //instance ID, bullshit for now - (merchant_slot==0) ? inst->GetSerialNumber() : merchant_slot, - 0, - (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges), - inst->IsInstNoDrop() ? 1 : 0, - 0 - ); - - for(i=0;i<10;i++) { - ItemInst *sub=inst->GetItem(i); - if (sub) { - sub_items[i]=SerializeItem(sub,0,&sub_length,depth+1); + int r; + for (r = 0; r <= 20; r++) { + strn0cpy(eq->itemnames[r], emu->itemnames[r], sizeof(eq->itemnames[r])); } + + // move arrow item down to last element in titanium array + strn0cpy(eq->itemnames[21], emu->itemnames[22], sizeof(eq->itemnames[21])); + + int k; + for (k = 0; k <= 20; k++) { + OUT(itemicons[k]); + } + + // move arrow icon down to last element in titanium array + eq->itemicons[21] = emu->itemicons[22]; + strn0cpy(eq->text, emu->text, sizeof(eq->text)); + + FINISH_ENCODE(); } + ENCODE(OP_InspectRequest) + { + ENCODE_LENGTH_EXACT(Inspect_Struct); + SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - *length=MakeAnyLenString(&serialization, - "%.*s%s" // For leading quotes (and protection) if a subitem; - "%s" // Instance data - "%.*s\"" // Quotes (and protection, if needed) around static data - "%i" // item->ItemClass so we can do |%s instead of %s| + OUT(TargetID); + OUT(PlayerID); + + FINISH_ENCODE(); + } + + ENCODE(OP_ItemLinkResponse) { ENCODE_FORWARD(OP_ItemPacket); } + + ENCODE(OP_ItemPacket) + { + //consume the packet + EQApplicationPacket *in = *p; + *p = nullptr; + + //store away the emu struct + 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 + 5; // ItemPacketType + Serialization + \0 + 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 + 1); + + delete[] __emu_buffer; + safe_delete_array(serialized); + + dest->FastQueuePacket(&in, ack_req); + } + + 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_LFGuild) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + uint32 Command = in->ReadUInt32(); + + if (Command != 0) + { + dest->FastQueuePacket(&in, ack_req); + return; + } + + EQApplicationPacket *outapp = new EQApplicationPacket(OP_LFGuild, sizeof(structs::LFGuild_PlayerToggle_Struct)); + + memcpy(outapp->pBuffer, in->pBuffer, sizeof(structs::LFGuild_PlayerToggle_Struct)); + + dest->FastQueuePacket(&outapp, ack_req); + delete in; + } + + ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + OUT_str(Title); + OUT_str(Text); + OUT(Buttons); + OUT(Duration); + OUT(PopupID); + + eq->unknown4236 = 0x00000000; + eq->unknown4240 = 0xffffffff; + + FINISH_ENCODE(); + } + + ENCODE(OP_PetBuffWindow) + { + ENCODE_LENGTH_EXACT(PetBuff_Struct); + SETUP_DIRECT_ENCODE(PetBuff_Struct, PetBuff_Struct); + + OUT(petid); + OUT(buffcount); + + int EQBuffSlot = 0; + + for (uint32 EmuBuffSlot = 0; EmuBuffSlot < BUFF_COUNT; ++EmuBuffSlot) + { + if (emu->spellid[EmuBuffSlot]) + { + eq->spellid[EQBuffSlot] = emu->spellid[EmuBuffSlot]; + eq->ticsremaining[EQBuffSlot++] = emu->ticsremaining[EmuBuffSlot]; + } + } + + FINISH_ENCODE(); + } + + ENCODE(OP_PlayerProfile) + { + SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); + + uint32 r; + + eq->available_slots = 0xffffffff; + memset(eq->unknown4184, 0xff, sizeof(eq->unknown4184)); + memset(eq->unknown04396, 0xff, sizeof(eq->unknown04396)); + + // OUT(checksum); + OUT(gender); + OUT(race); + OUT(class_); + // OUT(unknown00016); + OUT(level); + eq->level1 = emu->level; + // OUT(unknown00022[2]); + for (r = 0; r < 5; r++) { + OUT(binds[r].zoneId); + OUT(binds[r].x); + OUT(binds[r].y); + OUT(binds[r].z); + OUT(binds[r].heading); + } + OUT(deity); + OUT(intoxication); + OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT(abilitySlotRefresh); + OUT(haircolor); + OUT(beardcolor); + OUT(eyecolor1); + OUT(eyecolor2); + OUT(hairstyle); + OUT(beard); + // OUT(unknown00178[10]); + for (r = 0; r < 9; r++) { + OUT(item_material[r]); + OUT(item_tint[r].color); + } + // OUT(unknown00224[48]); + for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { + OUT(aa_array[r].AA); + OUT(aa_array[r].value); + } + // OUT(unknown02220[4]); + OUT(points); + OUT(mana); + OUT(cur_hp); + OUT(STR); + OUT(STA); + OUT(CHA); + OUT(DEX); + OUT(INT); + OUT(AGI); + OUT(WIS); + OUT(face); + // OUT(unknown02264[47]); + OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + // OUT(unknown4184[448]); + OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + // OUT(unknown04396[32]); + OUT(platinum); + OUT(gold); + OUT(silver); + OUT(copper); + OUT(platinum_cursor); + OUT(gold_cursor); + OUT(silver_cursor); + OUT(copper_cursor); + + OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) + + // OUT(unknown04760[236]); + OUT(toxicity); + OUT(thirst_level); + OUT(hunger_level); + for (r = 0; r < structs::BUFF_COUNT; r++) { + OUT(buffs[r].slotid); + OUT(buffs[r].level); + OUT(buffs[r].bard_modifier); + OUT(buffs[r].effect); + OUT(buffs[r].spellid); + OUT(buffs[r].duration); + OUT(buffs[r].counters); + OUT(buffs[r].player_id); + } + for (r = 0; r < structs::MAX_PP_DISCIPLINES; r++) { + OUT(disciplines.values[r]); + } + // OUT(unknown05008[360]); + // OUT_array(recastTimers, structs::MAX_RECAST_TYPES); + OUT(endurance); + OUT(aapoints_spent); + OUT(aapoints); + // OUT(unknown06160[4]); + for (r = 0; r < structs::MAX_PLAYER_BANDOLIER; r++) { + OUT_str(bandoliers[r].name); + uint32 k; + for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { + OUT(bandoliers[r].items[k].item_id); + OUT(bandoliers[r].items[k].icon); + OUT_str(bandoliers[r].items[k].item_name); + } + } + // OUT(unknown07444[5120]); + for (r = 0; r < structs::MAX_PLAYER_BANDOLIER_ITEMS; r++) { + OUT(potionbelt.items[r].item_id); + OUT(potionbelt.items[r].icon); + OUT_str(potionbelt.items[r].item_name); + } + // OUT(unknown12852[8]); + // OUT(unknown12864[76]); + OUT_str(name); + OUT_str(last_name); + OUT(guild_id); + OUT(birthday); + OUT(lastlogin); + OUT(timePlayedMin); + OUT(pvp); + OUT(anon); + OUT(gm); + OUT(guildrank); + OUT(guildbanker); + // OUT(unknown13054[8]); + OUT(exp); + // OUT(unknown13072[12]); + OUT(timeentitledonaccount); + OUT_array(languages, structs::MAX_PP_LANGUAGE); + // OUT(unknown13109[7]); + OUT(x); + OUT(y); + OUT(z); + OUT(heading); + // OUT(unknown13132[4]); + OUT(platinum_bank); + OUT(gold_bank); + OUT(silver_bank); + OUT(copper_bank); + OUT(platinum_shared); + // OUT(unknown13156[84]); + OUT(expansions); + // OUT(unknown13244[12]); + OUT(autosplit); + // OUT(unknown13260[16]); + OUT(zone_id); + OUT(zoneInstance); + for (r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { + OUT_str(groupMembers[r]); + } + strcpy(eq->groupLeader, emu->groupMembers[0]); + // OUT_str(groupLeader); + // OUT(unknown13728[660]); + OUT(entityid); + OUT(leadAAActive); + // OUT(unknown14392[4]); + OUT(ldon_points_guk); + OUT(ldon_points_mir); + OUT(ldon_points_mmc); + OUT(ldon_points_ruj); + OUT(ldon_points_tak); + OUT(ldon_points_available); + // OUT(unknown14420[132]); + OUT(tribute_time_remaining); + OUT(career_tribute_points); + // OUT(unknown7208); + OUT(tribute_points); + // OUT(unknown7216); + OUT(tribute_active); + for (r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { + OUT(tributes[r].tribute); + OUT(tributes[r].tier); + } + // OUT(unknown14616[8]); + OUT(group_leadership_exp); + OUT(raid_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_points); + OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); + // OUT(unknown14772[128]); + OUT(air_remaining); + OUT(PVPKills); + OUT(PVPDeaths); + OUT(PVPCurrentPoints); + OUT(PVPCareerPoints); + OUT(PVPBestKillStreak); + OUT(PVPWorstDeathStreak); + OUT(PVPCurrentKillStreak); + // OUT(unknown14932[4580]); + OUT(expAA); + // OUT(unknown19516[40]); + OUT(currentRadCrystals); + OUT(careerRadCrystals); + OUT(currentEbonCrystals); + OUT(careerEbonCrystals); + OUT(groupAutoconsent); + OUT(raidAutoconsent); + OUT(guildAutoconsent); + // OUT(unknown19575[5]); + eq->level3 = emu->level; + eq->showhelm = emu->showhelm; + // OUT(unknown19584[4]); + // OUT(unknown19588); + + + const uint8 bytes[] = { + 0x78, 0x03, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x1A, 0x04, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, 0x09, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x14 + }; + memcpy(eq->unknown12864, bytes, sizeof(bytes)); + + //set the checksum... + CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); + + FINISH_ENCODE(); + } + + ENCODE(OP_ReadBook) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + + BookText_Struct *emu_BookText_Struct = (BookText_Struct *)__emu_buffer; + + in->size = sizeof(structs::BookText_Struct) + strlen(emu_BookText_Struct->booktext); + in->pBuffer = new unsigned char[in->size]; + + structs::BookText_Struct *eq_BookText_Struct = (structs::BookText_Struct*)in->pBuffer; + + eq_BookText_Struct->window = emu_BookText_Struct->window; + eq_BookText_Struct->type = emu_BookText_Struct->type; + strcpy(eq_BookText_Struct->booktext, emu_BookText_Struct->booktext); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_RespondAA) + { + ENCODE_LENGTH_EXACT(AATable_Struct); + SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); + + unsigned int r; + for (r = 0; r < structs::MAX_PP_AA_ARRAY; r++) { + OUT(aa_list[r].aa_skill); + OUT(aa_list[r].aa_value); + } + + 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 Titanium + // clientver 1 is for all clients and 3 is for Titanium + if (emu->clientver <= 3) + { + 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; + OUT(class_type); + OUT(cost); + OUT(seq); + OUT(current_level); + OUT(prereq_skill); + OUT(prereq_minpoints); + OUT(type); + OUT(spellid); + OUT(spell_type); + OUT(spell_refresh); + OUT(classes); + OUT(berserker); + OUT(max_level); + OUT(last_id); + OUT(next_id); + OUT(cost2); + OUT(unknown80[0]); + OUT(unknown80[1]); + 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); + } + } + + FINISH_ENCODE(); + } + + ENCODE(OP_SendCharInfo) + { + ENCODE_LENGTH_EXACT(CharacterSelect_Struct); + SETUP_DIRECT_ENCODE(CharacterSelect_Struct, structs::CharacterSelect_Struct); + + int r; + for (r = 0; r < 10; r++) { + OUT(zone[r]); + OUT(eyecolor1[r]); + OUT(eyecolor2[r]); + OUT(hairstyle[r]); + OUT(primary[r]); + if (emu->race[r] > 473) + eq->race[r] = 1; + else + eq->race[r] = emu->race[r]; + OUT(class_[r]); + OUT_str(name[r]); + OUT(gender[r]); + OUT(level[r]); + OUT(secondary[r]); + OUT(face[r]); + OUT(beard[r]); + int k; + for (k = 0; k < 9; k++) { + OUT(equip[r][k]); + OUT(cs_colors[r][k].color); + } + OUT(haircolor[r]); + OUT(gohome[r]); + OUT(tutorial[r]); + OUT(deity[r]); + OUT(beardcolor[r]); + eq->unknown820[r] = 0xFF; + eq->unknown902[r] = 0xFF; + } + + FINISH_ENCODE(); + } + + 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; + } + + in->size = sizeof(structs::Track_Struct) * EntryCount; + in->pBuffer = new unsigned char[in->size]; + structs::Track_Struct *eq = (structs::Track_Struct *) in->pBuffer; + + for (int i = 0; i < EntryCount; ++i, ++eq, ++emu) + { + OUT(entityid); + OUT(padding002); + OUT(distance); + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_Trader) + { + if ((*p)->size != sizeof(TraderBuy_Struct)) { + EQApplicationPacket *in = *p; + *p = nullptr; + dest->FastQueuePacket(&in, ack_req); + return; + } + + 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_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 (uint32 i = 0; i < count; ++i) + { + structs::VeteranReward *vr = (structs::VeteranReward*)data; + InternalVeteranReward *ivr = (InternalVeteranReward*)old_data; + + vr->claim_id = ivr->claim_id; + vr->item.item_id = ivr->items[0].item_id; + strcpy(vr->item.item_name, ivr->items[0].item_name); + + 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(color.color); + OUT(wear_slot_id); + + FINISH_ENCODE(); + } + + ENCODE(OP_ZoneEntry) { ENCODE_FORWARD(OP_ZoneSpawns); } + + 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; + } + + //make the EQ struct. + in->size = sizeof(structs::Spawn_Struct)*entrycount; + in->pBuffer = new unsigned char[in->size]; + structs::Spawn_Struct *eq = (structs::Spawn_Struct *) in->pBuffer; + + //zero out the packet. We could avoid this memset by setting all fields (including unknowns) + //in the loop. + memset(in->pBuffer, 0, in->size); + + //do the transform... + int r; + int k; + for (r = 0; r < entrycount; r++, eq++, emu++) { + // eq->unknown0000 = emu->unknown0000; + eq->gm = emu->gm; + // eq->unknown0003 = emu->unknown0003; + eq->aaitle = emu->aaitle; + // eq->unknown0004 = emu->unknown0004; + eq->anon = emu->anon; + eq->face = emu->face; + strcpy(eq->name, emu->name); + eq->deity = emu->deity; + // eq->unknown0073 = emu->unknown0073; + eq->size = emu->size; + // eq->unknown0079 = emu->unknown0079; + eq->NPC = emu->NPC; + eq->invis = emu->invis; + eq->haircolor = emu->haircolor; + eq->curHp = emu->curHp; + eq->max_hp = emu->max_hp; + eq->findable = emu->findable; + // eq->unknown0089[5] = emu->unknown0089[5]; + eq->deltaHeading = emu->deltaHeading; + eq->x = emu->x; + // eq->padding0054 = emu->padding0054; + eq->y = emu->y; + eq->animation = emu->animation; + // eq->padding0058 = emu->padding0058; + eq->z = emu->z; + eq->deltaY = emu->deltaY; + eq->deltaX = emu->deltaX; + eq->heading = emu->heading; + // eq->padding0066 = emu->padding0066; + eq->deltaZ = emu->deltaZ; + // eq->padding0070 = emu->padding0070; + eq->eyecolor1 = emu->eyecolor1; + // eq->unknown0115[24] = emu->unknown0115[24]; + eq->showhelm = emu->showhelm; + // eq->unknown0140[4] = emu->unknown0140[4]; + eq->is_npc = emu->is_npc; + eq->hairstyle = emu->hairstyle; + + //if(emu->gender == 1){ + // eq->hairstyle = eq->hairstyle == 0xFF ? 0 : eq->hairstyle; + //} + + eq->beardcolor = emu->beardcolor; + // eq->unknown0147[4] = emu->unknown0147[4]; + eq->level = emu->level; + // eq->unknown0259[4] = emu->unknown0259[4]; + eq->beard = emu->beard; + strcpy(eq->suffix, emu->suffix); + eq->petOwnerId = emu->petOwnerId; + eq->guildrank = emu->guildrank; + // eq->unknown0194[3] = emu->unknown0194[3]; + for (k = 0; k < 9; k++) { + eq->equipment[k] = emu->equipment[k]; + eq->colors[k].color = emu->colors[k].color; + } + for (k = 0; k < 8; k++) { + eq->set_to_0xFF[k] = 0xFF; + } + + eq->runspeed = emu->runspeed; + eq->afk = emu->afk; + eq->guildID = emu->guildID; + strcpy(eq->title, emu->title); + // eq->unknown0274 = emu->unknown0274; + eq->helm = emu->helm; + if (emu->race > 473) + eq->race = 1; + else + eq->race = emu->race; + // eq->unknown0288 = emu->unknown0288; + strcpy(eq->lastName, emu->lastName); + eq->walkspeed = emu->walkspeed; + // eq->unknown0328 = emu->unknown0328; + eq->is_pet = emu->is_pet; + eq->light = emu->light; + eq->class_ = emu->class_; + eq->eyecolor2 = emu->eyecolor2; + // eq->unknown0333 = emu->unknown0333; + eq->flymode = emu->flymode; + eq->gender = emu->gender; + eq->bodytype = emu->bodytype; + // eq->unknown0336[3] = emu->unknown0336[3]; + eq->equip_chest2 = emu->equip_chest2; + eq->spawnId = emu->spawnId; + // eq->unknown0344[4] = emu->unknown0344[4]; + eq->lfg = emu->lfg; + + /* + if (emu->face == 99) {eq->face = 0;} + if (emu->eyecolor1 == 99) {eq->eyecolor1 = 0;} + if (emu->eyecolor2 == 99) {eq->eyecolor2 = 0;} + if (emu->hairstyle == 99) {eq->hairstyle = 0;} + if (emu->haircolor == 99) {eq->haircolor = 0;} + if (emu->beard == 99) {eq->beard = 0;} + if (emu->beardcolor == 99) {eq->beardcolor = 0;} + */ + + } + + //kill off the emu structure and send the eq packet. + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + +// DECODE methods + DECODE(OP_CharacterCreate) + { + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(class_); + IN(beardcolor); + IN(beard); + IN(haircolor); + IN(gender); + IN(race); + IN(start_zone); + IN(hairstyle); + IN(deity); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + + 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); + + 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 <= 20; r++) { + strn0cpy(emu->itemnames[r], eq->itemnames[r], sizeof(emu->itemnames[r])); + } + + // move arrow item up to last element in server array + strn0cpy(emu->itemnames[21], "", sizeof(emu->itemnames[21])); + strn0cpy(emu->itemnames[22], eq->itemnames[21], sizeof(emu->itemnames[22])); + + int k; + for (k = 0; k <= 20; k++) { + IN(itemicons[k]); + } + + // move arrow icon up to last element in server array + emu->itemicons[21] = 0xFFFFFFFF; + emu->itemicons[22] = eq->itemicons[21]; + + strn0cpy(emu->text, eq->text, sizeof(emu->text)); + + 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]); + } + IN(link_hash); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_LFGuild) + { + uint32 Command = __packet->ReadUInt32(); + + if (Command != 0) + return; + + SETUP_DIRECT_DECODE(LFGuild_PlayerToggle_Struct, structs::LFGuild_PlayerToggle_Struct); + memcpy(emu, eq, sizeof(structs::LFGuild_PlayerToggle_Struct)); + memset(emu->Unknown612, 0, sizeof(emu->Unknown612)); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_ReadBook) + { + DECODE_LENGTH_ATLEAST(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(window); + IN(type); + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + 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++) { + IN(filters[r]); + } + + 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_WearChange) + { + DECODE_LENGTH_EXACT(structs::WearChange_Struct); + SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); + + IN(spawn_id); + IN(material); + IN(color.color); + IN(wear_slot_id); + emu->unknown06 = 0; + emu->elite_material = 0; + emu->hero_forge_model = 0; + emu->unknown18 = 0; + + 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); + emu->type = 3; + + FINISH_DIRECT_DECODE(); + } + +// file scope helper methods + char *SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth) + { + char *serialization = nullptr; + char *instance = nullptr; + const char *protection = (const char *)"\\\\\\\\\\"; + char *sub_items[10] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; + bool stackable = inst->IsStackable(); + uint32 merchant_slot = inst->GetMerchantSlot(); + int16 charges = inst->GetCharges(); + const Item_Struct *item = inst->GetItem(); + int i; + uint32 sub_length; + + MakeAnyLenString(&instance, + "%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|", + stackable ? charges : 0, + 0, + (merchant_slot == 0) ? slot_id : merchant_slot, + inst->GetPrice(), + (merchant_slot == 0) ? 1 : inst->GetMerchantCount(), + 0, + //merchant_slot, //instance ID, bullshit for now + (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot, + 0, + (stackable ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : charges), + inst->IsInstNoDrop() ? 1 : 0, + 0 + ); + + for (i = 0; i<10; i++) { + ItemInst *sub = inst->GetItem(i); + if (sub) { + sub_items[i] = SerializeItem(sub, 0, &sub_length, depth + 1); + } + } + + *length = MakeAnyLenString(&serialization, + "%.*s%s" // For leading quotes (and protection) if a subitem; + "%s" // Instance data + "%.*s\"" // Quotes (and protection, if needed) around static data + "%i" // item->ItemClass so we can do |%s instead of %s| #define I(field) "|%i" #define C(field) "|%s" #define S(field) "|%s" #define F(field) "|%f" #include "titanium_itemfields.h" - "%.*s\"" // Quotes (and protection, if needed) around static data - "|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" // Sub items - "%.*s%s" // For trailing quotes (and protection) if a subitem; - ,depth ? depth-1 : 0,protection,(depth) ? "\"" : "" - ,instance - ,depth,protection - ,item->ItemClass + "%.*s\"" // Quotes (and protection, if needed) around static data + "|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s" // Sub items + "%.*s%s" // For trailing quotes (and protection) if a subitem; + , depth ? depth - 1 : 0, protection, (depth) ? "\"" : "" + , instance + , depth, protection + , item->ItemClass #define I(field) ,item->field #define C(field) ,field #define S(field) ,item->field #define F(field) ,item->field #include "titanium_itemfields.h" - ,depth,protection - ,sub_items[0] ? sub_items[0] : "" - ,sub_items[1] ? sub_items[1] : "" - ,sub_items[2] ? sub_items[2] : "" - ,sub_items[3] ? sub_items[3] : "" - ,sub_items[4] ? sub_items[4] : "" - ,sub_items[5] ? sub_items[5] : "" - ,sub_items[6] ? sub_items[6] : "" - ,sub_items[7] ? sub_items[7] : "" - ,sub_items[8] ? sub_items[8] : "" - ,sub_items[9] ? sub_items[9] : "" - ,(depth) ? depth-1 : 0,protection,(depth) ? "\"" : "" - ); + , depth, protection + , sub_items[0] ? sub_items[0] : "" + , sub_items[1] ? sub_items[1] : "" + , sub_items[2] ? sub_items[2] : "" + , sub_items[3] ? sub_items[3] : "" + , sub_items[4] ? sub_items[4] : "" + , sub_items[5] ? sub_items[5] : "" + , sub_items[6] ? sub_items[6] : "" + , sub_items[7] ? sub_items[7] : "" + , sub_items[8] ? sub_items[8] : "" + , sub_items[9] ? sub_items[9] : "" + , (depth) ? depth - 1 : 0, protection, (depth) ? "\"" : "" + ); - for(i=0;i<10;i++) { - if (sub_items[i]) - safe_delete_array(sub_items[i]); + for (i = 0; i<10; i++) { + if (sub_items[i]) + safe_delete_array(sub_items[i]); + } + + safe_delete_array(instance); + return serialization; } - safe_delete_array(instance); - return serialization; + static inline uint32 ServerToTitaniumSlot(uint32 ServerSlot) + { + //uint32 TitaniumSlot; + } + + static inline uint32 ServerToTitaniumCorpseSlot(uint32 ServerCorpse) + { + //uint32 TitaniumCorpse; + } + + static inline uint32 TitaniumToServerSlot(uint32 TitaniumSlot) + { + //uint32 ServerSlot; + } + + static inline uint32 TitaniumToServerCorpseSlot(uint32 TitaniumCorpse) + { + //uint32 ServerCorpse; + } } - -} //end namespace Titanium - - - - +// end namespace Titanium diff --git a/common/patches/underfoot.cpp b/common/patches/underfoot.cpp index 524a4d23b..a1d16f077 100644 --- a/common/patches/underfoot.cpp +++ b/common/patches/underfoot.cpp @@ -1,4 +1,3 @@ - #include "../debug.h" #include "underfoot.h" #include "../opcodemgr.h" @@ -18,1001 +17,2548 @@ namespace Underfoot { + static const char *name = "Underfoot"; + static OpcodeManager *opcodes = nullptr; + static Strategy struct_strategy; -static const char *name = "Underfoot"; -static OpcodeManager *opcodes = nullptr; -static Strategy struct_strategy; + char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); -char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth); + // server to client inventory location converters + static inline uint32 ServerToUnderfootSlot(uint32 ServerSlot); + static inline uint32 ServerToUnderFootCorpseSlot(uint32 ServerCorpse); -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; + // client to server inventory location converters + static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot); + static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse); + + 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); } } - //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 "underfoot_ops.h" } -} + std::string Strategy::Describe() const + { + std::string r; + r += "Patch "; + r += name; + return(r); + } - -Strategy::Strategy() -: StructStrategy() -{ - //all opcodes default to passthrough. - #include "ss_register.h" - #include "underfoot_ops.h" -} - -std::string Strategy::Describe() const { - std::string r; - r += "Patch "; - r += name; - return(r); -} - -const EQClientVersion Strategy::ClientVersion() const -{ - return EQClientUnderfoot; -} + const EQClientVersion Strategy::ClientVersion() const + { + return EQClientUnderfoot; + } #include "ss_define.h" +// ENCODE methods + ENCODE(OP_Action) + { + ENCODE_LENGTH_EXACT(Action_Struct); + SETUP_DIRECT_ENCODE(Action_Struct, structs::ActionAlt_Struct); -// Converts Server Slot IDs to Underfoot Slot IDs for use in Encodes -static inline uint32 ServerToUnderfootSlot(uint32 ServerSlot) { - uint32 UnderfootSlot = 0; + OUT(target); + OUT(source); + OUT(level); + eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f; + eq->knockback_angle = emu->sequence; + OUT(type); + OUT(spell); + eq->level2 = eq->level; + eq->effect_flag = emu->buff_unknown; + eq->unknown37 = 0x01; + eq->unknown44 = 0xFFFFFFFF; + eq->unknown48 = 0xFFFFFFFF; + eq->unknown52 = 0xFFFFFFFF; - if (ServerSlot >= MainAmmo && ServerSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots - UnderfootSlot = ServerSlot + 1; - - else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) - UnderfootSlot = ServerSlot + 11; - - else if (ServerSlot >= EmuConstants::BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) - UnderfootSlot = ServerSlot + 1; - - else if (ServerSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) - UnderfootSlot = ServerSlot + 1; - - else if (ServerSlot == MainPowerSource) - UnderfootSlot = slots::MainPowerSource; - - else - UnderfootSlot = ServerSlot; + /*OUT(target); + OUT(source); + OUT(level); + OUT(instrument_mod); + eq->sequence = emu->sequence; + OUT(type); + //OUT(damage); + OUT(spell); + eq->level2 = emu->level; + OUT(buff_unknown); // if this is 4, a buff icon is made + //eq->unknown0036 = -1; + //eq->unknown0040 = -1; + //eq->unknown0044 = -1;*/ - return UnderfootSlot; -} - -// Converts Underfoot Slot IDs to Server Slot IDs for use in Decodes -static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot) { - uint32 ServerSlot = 0; - - if(UnderfootSlot >= slots::MainAmmo && UnderfootSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots - ServerSlot = UnderfootSlot - 1; - - else if(UnderfootSlot >= consts::GENERAL_BAGS_BEGIN && UnderfootSlot <= consts::CURSOR_BAG_END) - ServerSlot = UnderfootSlot - 11; - - else if(UnderfootSlot >= consts::BANK_BAGS_BEGIN && UnderfootSlot <= consts::BANK_BAGS_END) - ServerSlot = UnderfootSlot - 1; - - else if(UnderfootSlot >= consts::SHARED_BANK_BAGS_BEGIN && UnderfootSlot <= consts::SHARED_BANK_BAGS_END) - ServerSlot = UnderfootSlot - 1; - - else if(UnderfootSlot == slots::MainPowerSource) - ServerSlot = MainPowerSource; - - else - ServerSlot = UnderfootSlot; - - return ServerSlot; -} - -/* -// Converts Server Corpse Slot IDs to Underfoot Corpse Slot IDs for use in Encodes -static inline uint32 ServerToUnderFootCorpseSlot(uint32 ServerCorpse) { - uint32 UnderfootCorpse; - // reserved -} -*/ -/* -// Converts Underfoot Corpse Slot IDs to Server Corpse Slot IDs for use in Decodes -static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse) { - uint32 ServerCorpse; - // reserved -} -*/ - - -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 Underfoot 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; + FINISH_ENCODE(); } - delete[] __emu_buffer; + ENCODE(OP_AdventureMerchantSell) + { + ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); + SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - dest->FastQueuePacket(&in, ack_req); -} + eq->unknown000 = 1; + OUT(npcid); + eq->slot = ServerToUnderfootSlot(emu->slot); + OUT(charges); + OUT(sell_price); + FINISH_ENCODE(); + } -ENCODE(OP_SendCharInfo) { - ENCODE_LENGTH_EXACT(CharacterSelect_Struct); - SETUP_VAR_ENCODE(CharacterSelect_Struct); + ENCODE(OP_AltCurrency) + { + EQApplicationPacket *in = *p; + *p = nullptr; + unsigned char *emu_buffer = in->pBuffer; + uint32 opcode = *((uint32*)emu_buffer); - //EQApplicationPacket *packet = *p; - //const CharacterSelect_Struct *emu = (CharacterSelect_Struct *) packet->pBuffer; + if (opcode == 8) { + AltCurrencyPopulate_Struct *populate = (AltCurrencyPopulate_Struct*)emu_buffer; - 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]); - } + 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; - 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; - eq2->level = emu->level[r]; - eq2->hairstyle = emu->hairstyle[r]; - eq2->gender = emu->gender[r]; - 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->beard = emu->beard[r]; - eq2->haircolor = emu->haircolor[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].itemid = 0; - eq2->equip[k].color.color = emu->cs_colors[r][k].color; + 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].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].unknown00 = populate->entries[i].unknown00; } - eq2->primary = emu->primary[r]; - eq2->secondary = emu->secondary[r]; - eq2->tutorial = emu->tutorial[r]; // was u15 - eq2->u15 = 0xff; - eq2->deity = emu->deity[r]; - eq2->zone = emu->zone[r]; - eq2->u19 = 0xFF; - eq2->race = emu->race[r]; - eq2->gohome = emu->gohome[r]; - eq2->class_ = emu->class_[r]; - eq2->eyecolor1 = emu->eyecolor1[r]; - eq2->beardcolor = emu->beardcolor[r]; - eq2->eyecolor2 = emu->eyecolor2[r]; - eq2->drakkin_heritage = emu->drakkin_heritage[r]; - eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; - eq2->drakkin_details = emu->drakkin_details[r]; + + dest->FastQueuePacket(&outapp, ack_req); } - bufptr += sizeof(structs::CharacterSelectEntry_Struct); + 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; } - FINISH_ENCODE(); - -} - -ENCODE(OP_ZoneServerInfo) { - SETUP_DIRECT_ENCODE(ZoneServerInfo_Struct, ZoneServerInfo_Struct); - OUT_str(ip); - OUT(port); - 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) + ENCODE(OP_AltCurrencySell) { - 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; - } + ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); + SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - 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 6 is for Underfoot - if (emu->clientver <= 6 ) - { - 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)?0:(emu->sof_next_skill); - eq->hotkey_sid2 = (emu->hotkey_sid2==4294967295UL)?0:(emu->sof_next_skill); - eq->title_sid = emu->sof_next_skill; - eq->desc_sid = emu->sof_next_skill; - OUT(class_type); + OUT(merchant_entity_id); + eq->slot_id = ServerToUnderfootSlot(emu->slot_id); + OUT(charges); OUT(cost); - OUT(seq); - OUT(current_level); - OUT(prereq_skill); - OUT(prereq_minpoints); - eq->type = emu->sof_type; + + FINISH_ENCODE(); + } + + ENCODE(OP_ApplyPoison) + { + ENCODE_LENGTH_EXACT(ApplyPoison_Struct); + SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); + + eq->inventorySlot = ServerToUnderfootSlot(emu->inventorySlot); + OUT(success); + + 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_Buff) + { + ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); + SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Underfoot); + + OUT(entityid); + OUT(slot); + OUT(level); + OUT(effect); + //eq->unknown7 = 10; OUT(spellid); - 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); - } + OUT(duration); + OUT(slotid); + OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter. + eq->unknown008 = 1.0f; + + FINISH_ENCODE(); } - 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_RespondAA) { - SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); - - eq->aa_spent = emu->aa_spent; - eq->aa_assigned = emu->aa_spent; - eq->aa_spent3 = emu->aa_spent; - eq->unknown012 = 0; - eq->unknown016 = 0; - eq->unknown020 = 0; - - for(uint32 i = 0; i < MAX_PP_AA_ARRAY; ++i) + ENCODE(OP_BuffCreate) { - 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; - } + SETUP_VAR_ENCODE(BuffIcon_Struct); - FINISH_ENCODE(); -} + uint32 sz = 12 + (17 * emu->count); + __packet->size = sz; + __packet->pBuffer = new unsigned char[sz]; + memset(__packet->pBuffer, 0, sz); -ENCODE(OP_PlayerProfile) { - SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); + uchar *ptr = __packet->pBuffer; + *((uint32*)ptr) = emu->entity_id; + ptr += sizeof(uint32); + ptr += sizeof(uint32); + *((uint8*)ptr) = 1; + ptr += sizeof(uchar); + *((uint16*)ptr) = emu->count; + ptr += sizeof(uint16); - uint32 r; - - eq->available_slots=0xffffffff; - memset(eq->unknown07284, 0xff, sizeof(eq->unknown07284)); - -// OUT(checksum); - OUT(gender); - OUT(race); - OUT(class_); -// OUT(unknown00016); - OUT(level); - eq->level1 = emu->level; -// OUT(unknown00022[2]); - for(r = 0; r < 5; r++) { - OUT(binds[r].zoneId); - OUT(binds[r].x); - OUT(binds[r].y); - OUT(binds[r].z); - OUT(binds[r].heading); - } - OUT(deity); - OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); - OUT(abilitySlotRefresh); - OUT(points); // Relocation Test -// OUT(unknown0166[4]); - OUT(haircolor); - OUT(beardcolor); - OUT(eyecolor1); - OUT(eyecolor2); - OUT(hairstyle); - OUT(beard); -// OUT(unknown00178[10]); - for(r = 0; r < 9; r++) { - eq->equipment[r].equip0 = emu->item_material[r]; - eq->equipment[r].equip1 = 0; - eq->equipment[r].itemId = 0; - //eq->colors[r].color = emu->colors[r].color; - } - for(r = 0; r < 7; r++) { - OUT(item_tint[r].color); - } -// OUT(unknown00224[48]); - //NOTE: new client supports 300 AAs, our internal rep/PP - //only supports 240.. - for(r = 0; r < MAX_PP_AA_ARRAY; r++) { - OUT(aa_array[r].AA); - OUT(aa_array[r].value); - } -// OUT(unknown02220[4]); - OUT(mana); - OUT(cur_hp); - OUT(STR); - OUT(STA); - OUT(CHA); - OUT(AGI); - OUT(INT); - OUT(DEX); - OUT(WIS); - OUT(face); -// OUT(unknown02264[47]); - memset(eq->spell_book, 0xFF, sizeof(uint32)* structs::MAX_PP_SPELLBOOK); - OUT_array(spell_book, 480U); -// OUT(unknown4184[128]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); -// OUT(unknown04396[32]); - OUT(platinum); - OUT(gold); - OUT(silver); - OUT(copper); - OUT(platinum_cursor); - OUT(gold_cursor); - OUT(silver_cursor); - OUT(copper_cursor); - - OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) - -// OUT(unknown04760[236]); - OUT(toxicity); - OUT(thirst_level); - OUT(hunger_level); - //PS this needs to be figured out more; but it was 'good enough' - for(r = 0; r < structs::BUFF_COUNT; r++) - { - if(emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) + for (uint16 i = 0; i < emu->count; ++i) { - eq->buffs[r].unknown004 = 0x3f800000; - eq->buffs[r].slotid = 2; - eq->buffs[r].player_id = 0x000717fd; + uint16 buffslot = emu->entries[i].buff_slot; + if (emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) + { + buffslot += 5; + } + else if (emu->entries[i].buff_slot >= 37) + { + buffslot += 14; + } + + *((uint32*)ptr) = buffslot; + ptr += sizeof(uint32); + *((uint32*)ptr) = emu->entries[i].spell_id; + ptr += sizeof(uint32); + *((uint32*)ptr) = emu->entries[i].tics_remaining; + ptr += sizeof(uint32); + ptr += sizeof(uint32); + ptr += 1; } - else + + FINISH_ENCODE(); + /* + uint32 write_var32 = 60; + uint8 write_var8 = 1; + ss.write((const char*)&emu->entity_id, sizeof(uint32)); + ss.write((const char*)&write_var32, sizeof(uint32)); + ss.write((const char*)&write_var8, sizeof(uint8)); + ss.write((const char*)&emu->count, sizeof(uint16)); + write_var32 = 0; + write_var8 = 0; + for(uint16 i = 0; i < emu->count; ++i) { - eq->buffs[r].slotid = 0; - } - //OUT(buffs[r].slotid); - OUT(buffs[r].level); - //OUT(buffs[r].bard_modifier); - //OUT(buffs[r].effect); - OUT(buffs[r].spellid); - OUT(buffs[r].duration); - OUT(buffs[r].counters); - //OUT(buffs[r].player_id); - } - for(r = 0; r < MAX_PP_DISCIPLINES; r++) { - OUT(disciplines.values[r]); - } - OUT_array(recastTimers, structs::MAX_RECAST_TYPES); -// OUT(unknown08124[360]); - OUT(endurance); - OUT(aapoints_spent); - OUT(aapoints); -// OUT(unknown06160[4]); - //NOTE: new client supports 20 bandoliers, our internal rep - //only supports 4.. - for(r = 0; r < 4; r++) { - OUT_str(bandoliers[r].name); - uint32 k; - for(k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { - OUT(bandoliers[r].items[k].item_id); - OUT(bandoliers[r].items[k].icon); - OUT_str(bandoliers[r].items[k].item_name); - } - } -// OUT(unknown07444[5120]); - for(r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) { - OUT(potionbelt.items[r].item_id); - OUT(potionbelt.items[r].icon); - OUT_str(potionbelt.items[r].item_name); - } -// OUT(unknown12852[8]); -// OUT(unknown12864[76]); - OUT_str(name); - OUT_str(last_name); - OUT(guild_id); - OUT(birthday); - OUT(lastlogin); - OUT(timePlayedMin); - OUT(pvp); - OUT(anon); - OUT(gm); - OUT(guildrank); - OUT(guildbanker); -// OUT(unknown13054[12]); - OUT(exp); -// OUT(unknown13072[8]); - OUT(timeentitledonaccount); - OUT_array(languages, structs::MAX_PP_LANGUAGE); -// OUT(unknown13109[7]); - OUT(y); //reversed x and y - OUT(x); - OUT(z); - OUT(heading); -// OUT(unknown13132[4]); - OUT(platinum_bank); - OUT(gold_bank); - OUT(silver_bank); - OUT(copper_bank); - OUT(platinum_shared); -// OUT(unknown13156[84]); - //OUT(expansions); - eq->expansions = 0xffff; -// OUT(unknown13244[12]); - OUT(autosplit); -// OUT(unknown13260[16]); - OUT(zone_id); - OUT(zoneInstance); - for(r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { - OUT_str(groupMembers[r]); - } - strcpy(eq->groupLeader, emu->groupMembers[0]); -// OUT_str(groupLeader); -// OUT(unknown13728[660]); - OUT(entityid); - OUT(leadAAActive); -// OUT(unknown14392[4]); - OUT(ldon_points_guk); - OUT(ldon_points_mir); - OUT(ldon_points_mmc); - OUT(ldon_points_ruj); - OUT(ldon_points_tak); - OUT(ldon_points_available); -// OUT(unknown14420[132]); - OUT(tribute_time_remaining); - OUT(career_tribute_points); -// OUT(unknown7208); - OUT(tribute_points); -// OUT(unknown7216); - OUT(tribute_active); - for(r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { - OUT(tributes[r].tribute); - OUT(tributes[r].tier); - } -// OUT(unknown14616[8]); - OUT(group_leadership_exp); -// OUT(unknown14628); - OUT(raid_leadership_exp); - OUT(group_leadership_points); - OUT(raid_leadership_points); - OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); -// OUT(unknown14772[128]); - OUT(air_remaining); - OUT(PVPKills); - OUT(PVPDeaths); - OUT(PVPCurrentPoints); - OUT(PVPCareerPoints); - OUT(PVPBestKillStreak); - OUT(PVPWorstDeathStreak); - OUT(PVPCurrentKillStreak); -// OUT(unknown17892[4580]); - OUT(expAA); -// OUT(unknown19516[40]); - OUT(currentRadCrystals); - OUT(careerRadCrystals); - OUT(currentEbonCrystals); - OUT(careerEbonCrystals); - OUT(groupAutoconsent); - OUT(raidAutoconsent); - OUT(guildAutoconsent); -// OUT(unknown19575[5]); - eq->level3 = emu->level; - eq->showhelm = emu->showhelm; - OUT(RestTimer); -// OUT(unknown19584[4]); -// OUT(unknown19588); - - -const uint8 bytes[] = { -0xa3,0x02,0x00,0x00,0x95,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x00,0x00, -0x19,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00, -0x0F,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1F,0x85,0xEB,0x3E,0x33,0x33,0x33,0x3F, -0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x07,0x00,0x00,0x00, -0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -}; - - memcpy(eq->unknown18020, bytes, sizeof(bytes)); - - //set the checksum... - CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct)-4); - - FINISH_ENCODE(); -} - -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; - - FINISH_ENCODE(); -} - - -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_PetBuffWindow) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - unsigned char *__emu_buffer = in->pBuffer; - - PetBuff_Struct *emu = (PetBuff_Struct *) __emu_buffer; - - int PacketSize = 12 + (emu->buffcount * 17); - - in->size = PacketSize; - - in->pBuffer = new unsigned char[in->size]; - - char *Buffer = (char *)in->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petid); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); - VARSTRUCT_ENCODE_TYPE(uint16, Buffer, emu->buffcount); - - for(unsigned int i = 0; i < BUFF_COUNT; ++i) - { - if(emu->spellid[i]) + if(emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) { - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, i); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spellid[i]); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->ticsremaining[i]); + emu->entries[i].buff_slot += 5; + } + else if(emu->entries[i].buff_slot >= 37) + { + emu->entries[i].buff_slot += 14; + } + ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32)); + ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32)); + ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32)); + ss.write((const char*)&write_var32, sizeof(uint32)); + ss.write((const char*)&write_var8, sizeof(uint8)); + } + ss.write((const char*)&write_var8, sizeof(uint8)); + */ + } + + ENCODE(OP_CancelTrade) + { + ENCODE_LENGTH_EXACT(CancelTrade_Struct); + SETUP_DIRECT_ENCODE(CancelTrade_Struct, structs::CancelTrade_Struct); + + OUT(fromid); + OUT(action); + + 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_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 = ServerToUnderfootSlot(emu->from_slot); + eq->to_slot = ServerToUnderfootSlot(emu->to_slot); + OUT(number_in_stack); + + 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; + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->leader_name, emu->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); + + strcpy(eq->expedition_name, emu->expedition_name); + strcpy(eq->player_name, emu->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_GroundSpawn) + { + // We are not encoding the spawn_id field here, or a size 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) + 58; + 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, 0); // Unknown, observed 0x00006762 + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observer 0x7fffbb64 + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); + // This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this + // field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same + // issue. + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0 + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // This appears to be the size field. + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); + VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->object_type); // Unknown, observed 0x00000014 + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0xffffffff); // Unknown, observed 0xffffffff + VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0x00000014 + VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown, observed 0x00 + + 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_TYPE(uint8, Buffer, 0); // This is a string. Name of the caster of the buff. + 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); } - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); - delete[] __emu_buffer; - dest->FastQueuePacket(&in, ack_req); -} - -ENCODE(OP_Barter) -{ - EQApplicationPacket *in = *p; - *p = nullptr; - - char *Buffer = (char *)in->pBuffer; - - uint32 SubAction = VARSTRUCT_DECODE_TYPE(uint32, Buffer); - - if(SubAction != Barter_BuyerAppearance) + ENCODE(OP_GuildMemberList) { - 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_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } -ENCODE(OP_ZoneEntry){ ENCODE_FORWARD(OP_ZoneSpawns); } -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; + 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++; + + //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) \ + strcpy(e->field, str.c_str()); \ + e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ +#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_); + PutFieldN(rank); + PutFieldN(time_last_on); + PutFieldN(tribute_enable); + 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); + +#undef SlideStructString +#undef PutFieldN + + e++; + } + } + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + 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_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); + + 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_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 = ServerToUnderfootSlot(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); + + strcpy(eq->worldshortname, emu->worldshortname); + + OUT(enablevoicemacros); + OUT(enablemail); + OUT(enable_pvp); + OUT(enable_FV); + + eq->unknown016 = 1; + eq->unknown020[0] = 1; + + // These next two need to be set like this for the Tutorial Button to work. + eq->unknown263[0] = 0; + eq->unknown263[2] = 1; + eq->unknown263[4] = 1; + eq->unknown263[5] = 1; + eq->unknown263[6] = 1; + eq->unknown263[9] = 8; + eq->unknown263[19] = 0x80; + eq->unknown263[20] = 0x3f; + eq->unknown263[23] = 0x80; + eq->unknown263[24] = 0x3f; + eq->unknown263[33] = 1; + + 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 = emu->slot_id + 1; + 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].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); + 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; + } + + // This packet does not appear to exist in UF, but leaving it here just in case + 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; + } + + 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].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); + 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, emu->MercData[r].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 = ServerToUnderfootSlot(emu->from_slot); + eq->to_slot = ServerToUnderfootSlot(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; + + FINISH_ENCODE(); + } + + ENCODE(OP_OnLevelMessage) + { + ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); + SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); + + memcpy(eq->Title, emu->Title, sizeof(eq->Title)); + 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. + OUT_str(ButtonName0); + 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 Underfoot 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) + { + EQApplicationPacket *in = *p; + *p = nullptr; + + unsigned char *__emu_buffer = in->pBuffer; + + PetBuff_Struct *emu = (PetBuff_Struct *)__emu_buffer; + + int PacketSize = 12 + (emu->buffcount * 17); + + in->size = PacketSize; + in->pBuffer = new unsigned char[in->size]; + + char *Buffer = (char *)in->pBuffer; + + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petid); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); + VARSTRUCT_ENCODE_TYPE(uint16, Buffer, emu->buffcount); + + for (unsigned int i = 0; i < BUFF_COUNT; ++i) + { + if (emu->spellid[i]) + { + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, i); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spellid[i]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->ticsremaining[i]); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // This is a string. Name of the caster of the buff. + } + } + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->buffcount); + + delete[] __emu_buffer; + dest->FastQueuePacket(&in, ack_req); + } + + ENCODE(OP_PlayerProfile) + { + SETUP_DIRECT_ENCODE(PlayerProfile_Struct, structs::PlayerProfile_Struct); + + uint32 r; + + eq->available_slots = 0xffffffff; + memset(eq->unknown07284, 0xff, sizeof(eq->unknown07284)); + + // OUT(checksum); + OUT(gender); + OUT(race); + OUT(class_); + // OUT(unknown00016); + OUT(level); + eq->level1 = emu->level; + // OUT(unknown00022[2]); + for (r = 0; r < 5; r++) { + OUT(binds[r].zoneId); + OUT(binds[r].x); + OUT(binds[r].y); + OUT(binds[r].z); + OUT(binds[r].heading); + } + OUT(deity); + OUT(intoxication); + OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT(abilitySlotRefresh); + OUT(points); // Relocation Test + // OUT(unknown0166[4]); + OUT(haircolor); + OUT(beardcolor); + OUT(eyecolor1); + OUT(eyecolor2); + OUT(hairstyle); + OUT(beard); + // OUT(unknown00178[10]); + for (r = 0; r < 9; r++) { + eq->equipment[r].equip0 = emu->item_material[r]; + eq->equipment[r].equip1 = 0; + eq->equipment[r].itemId = 0; + //eq->colors[r].color = emu->colors[r].color; + } + for (r = 0; r < 7; r++) { + OUT(item_tint[r].color); + } + // OUT(unknown00224[48]); + //NOTE: new client supports 300 AAs, our internal rep/PP + //only supports 240.. + for (r = 0; r < MAX_PP_AA_ARRAY; r++) { + OUT(aa_array[r].AA); + OUT(aa_array[r].value); + } + // OUT(unknown02220[4]); + OUT(mana); + OUT(cur_hp); + OUT(STR); + OUT(STA); + OUT(CHA); + OUT(AGI); + OUT(INT); + OUT(DEX); + OUT(WIS); + OUT(face); + // OUT(unknown02264[47]); + memset(eq->spell_book, 0xFF, sizeof(uint32)* structs::MAX_PP_SPELLBOOK); + OUT_array(spell_book, 480U); + // OUT(unknown4184[128]); + OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + // OUT(unknown04396[32]); + OUT(platinum); + OUT(gold); + OUT(silver); + OUT(copper); + OUT(platinum_cursor); + OUT(gold_cursor); + OUT(silver_cursor); + OUT(copper_cursor); + + OUT_array(skills, structs::MAX_PP_SKILL); // 1:1 direct copy (100 dword) + + // OUT(unknown04760[236]); + OUT(toxicity); + OUT(thirst_level); + OUT(hunger_level); + //PS this needs to be figured out more; but it was 'good enough' + for (r = 0; r < structs::BUFF_COUNT; r++) + { + if (emu->buffs[r].spellid != 0xFFFF && emu->buffs[r].spellid != 0) + { + eq->buffs[r].unknown004 = 0x3f800000; + eq->buffs[r].slotid = 2; + eq->buffs[r].player_id = 0x000717fd; + } + else + { + eq->buffs[r].slotid = 0; + } + //OUT(buffs[r].slotid); + OUT(buffs[r].level); + //OUT(buffs[r].bard_modifier); + //OUT(buffs[r].effect); + OUT(buffs[r].spellid); + OUT(buffs[r].duration); + OUT(buffs[r].counters); + //OUT(buffs[r].player_id); + } + for (r = 0; r < MAX_PP_DISCIPLINES; r++) { + OUT(disciplines.values[r]); + } + OUT_array(recastTimers, structs::MAX_RECAST_TYPES); + // OUT(unknown08124[360]); + OUT(endurance); + OUT(aapoints_spent); + OUT(aapoints); + // OUT(unknown06160[4]); + //NOTE: new client supports 20 bandoliers, our internal rep + //only supports 4.. + for (r = 0; r < 4; r++) { + OUT_str(bandoliers[r].name); + uint32 k; + for (k = 0; k < structs::MAX_PLAYER_BANDOLIER_ITEMS; k++) { + OUT(bandoliers[r].items[k].item_id); + OUT(bandoliers[r].items[k].icon); + OUT_str(bandoliers[r].items[k].item_name); + } + } + // OUT(unknown07444[5120]); + for (r = 0; r < structs::MAX_POTIONS_IN_BELT; r++) { + OUT(potionbelt.items[r].item_id); + OUT(potionbelt.items[r].icon); + OUT_str(potionbelt.items[r].item_name); + } + // OUT(unknown12852[8]); + // OUT(unknown12864[76]); + OUT_str(name); + OUT_str(last_name); + OUT(guild_id); + OUT(birthday); + OUT(lastlogin); + OUT(timePlayedMin); + OUT(pvp); + OUT(anon); + OUT(gm); + OUT(guildrank); + OUT(guildbanker); + // OUT(unknown13054[12]); + OUT(exp); + // OUT(unknown13072[8]); + OUT(timeentitledonaccount); + OUT_array(languages, structs::MAX_PP_LANGUAGE); + // OUT(unknown13109[7]); + OUT(y); //reversed x and y + OUT(x); + OUT(z); + OUT(heading); + // OUT(unknown13132[4]); + OUT(platinum_bank); + OUT(gold_bank); + OUT(silver_bank); + OUT(copper_bank); + OUT(platinum_shared); + // OUT(unknown13156[84]); + //OUT(expansions); + eq->expansions = 0xffff; + // OUT(unknown13244[12]); + OUT(autosplit); + // OUT(unknown13260[16]); + OUT(zone_id); + OUT(zoneInstance); + for (r = 0; r < structs::MAX_GROUP_MEMBERS; r++) { + OUT_str(groupMembers[r]); + } + strcpy(eq->groupLeader, emu->groupMembers[0]); + // OUT_str(groupLeader); + // OUT(unknown13728[660]); + OUT(entityid); + OUT(leadAAActive); + // OUT(unknown14392[4]); + OUT(ldon_points_guk); + OUT(ldon_points_mir); + OUT(ldon_points_mmc); + OUT(ldon_points_ruj); + OUT(ldon_points_tak); + OUT(ldon_points_available); + // OUT(unknown14420[132]); + OUT(tribute_time_remaining); + OUT(career_tribute_points); + // OUT(unknown7208); + OUT(tribute_points); + // OUT(unknown7216); + OUT(tribute_active); + for (r = 0; r < structs::MAX_PLAYER_TRIBUTES; r++) { + OUT(tributes[r].tribute); + OUT(tributes[r].tier); + } + // OUT(unknown14616[8]); + OUT(group_leadership_exp); + // OUT(unknown14628); + OUT(raid_leadership_exp); + OUT(group_leadership_points); + OUT(raid_leadership_points); + OUT_array(leader_abilities.ranks, structs::MAX_LEADERSHIP_AA_ARRAY); + // OUT(unknown14772[128]); + OUT(air_remaining); + OUT(PVPKills); + OUT(PVPDeaths); + OUT(PVPCurrentPoints); + OUT(PVPCareerPoints); + OUT(PVPBestKillStreak); + OUT(PVPWorstDeathStreak); + OUT(PVPCurrentKillStreak); + // OUT(unknown17892[4580]); + OUT(expAA); + // OUT(unknown19516[40]); + OUT(currentRadCrystals); + OUT(careerRadCrystals); + OUT(currentEbonCrystals); + OUT(careerEbonCrystals); + OUT(groupAutoconsent); + OUT(raidAutoconsent); + OUT(guildAutoconsent); + // OUT(unknown19575[5]); + eq->level3 = emu->level; + eq->showhelm = emu->showhelm; + OUT(RestTimer); + // OUT(unknown19584[4]); + // OUT(unknown19588); + + const uint8 bytes[] = { + 0xa3, 0x02, 0x00, 0x00, 0x95, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, + 0x19, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x85, 0xEB, 0x3E, 0x33, 0x33, 0x33, 0x3F, + 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + memcpy(eq->unknown18020, bytes, sizeof(bytes)); + + //set the checksum... + CRC32::SetEQChecksum(__packet->pBuffer, sizeof(structs::PlayerProfile_Struct) - 4); + + FINISH_ENCODE(); + } + + 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 + { + 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); + eq->invslot = ServerToUnderfootSlot(emu->invslot); + strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); + + FINISH_ENCODE(); + } + + ENCODE(OP_RespondAA) + { + SETUP_DIRECT_ENCODE(AATable_Struct, structs::AATable_Struct); + + eq->aa_spent = emu->aa_spent; + eq->aa_assigned = emu->aa_spent; + eq->aa_spent3 = emu->aa_spent; + eq->unknown012 = 0; + eq->unknown016 = 0; + eq->unknown020 = 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_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 6 is for Underfoot + if (emu->clientver <= 6) + { + 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) ? 0 : (emu->sof_next_skill); + eq->hotkey_sid2 = (emu->hotkey_sid2 == 4294967295UL) ? 0 : (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); + OUT(prereq_skill); + OUT(prereq_minpoints); + eq->type = emu->sof_type; + OUT(spellid); + 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); + } + } + + 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; + eq2->level = emu->level[r]; + eq2->hairstyle = emu->hairstyle[r]; + eq2->gender = emu->gender[r]; + 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->beard = emu->beard[r]; + eq2->haircolor = emu->haircolor[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].itemid = 0; + eq2->equip[k].color.color = emu->cs_colors[r][k].color; + } + eq2->primary = emu->primary[r]; + eq2->secondary = emu->secondary[r]; + eq2->tutorial = emu->tutorial[r]; // was u15 + eq2->u15 = 0xff; + eq2->deity = emu->deity[r]; + eq2->zone = emu->zone[r]; + eq2->u19 = 0xFF; + eq2->race = emu->race[r]; + eq2->gohome = emu->gohome[r]; + eq2->class_ = emu->class_[r]; + eq2->eyecolor1 = emu->eyecolor1[r]; + eq2->beardcolor = emu->beardcolor[r]; + eq2->eyecolor2 = emu->eyecolor2[r]; + eq2->drakkin_heritage = emu->drakkin_heritage[r]; + eq2->drakkin_tattoo = emu->drakkin_tattoo[r]; + eq2->drakkin_details = emu->drakkin_details[r]; + } + + bufptr += sizeof(structs::CharacterSelectEntry_Struct); + } + + 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_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 = ServerToUnderfootSlot(emu->itemslot); + OUT(quantity); + OUT(price); + + 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 = 135; // This needs to be set to something, else we get a 1HS animation instead of ranged. + + OUT(item_type); + OUT(skill); + + strcpy(eq->model_name, emu->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++) { + strcpy(eq[r].name, emu[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].unknown0076 = 0; + eq[r].unknown0077 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0078 = 0; + eq[r].unknown0079 = 1; // Both must be 1 to allow clicking doors + eq[r].unknown0080 = 0; + eq[r].unknown0081 = 0; + eq[r].unknown0082 = 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_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(TraderBuy_Struct)) { + EQApplicationPacket *in = *p; + *p = nullptr; + dest->FastQueuePacket(&in, ack_req); + return; + } + + 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_TributeItem) + { + ENCODE_LENGTH_EXACT(TributeItem_Struct); + SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); + + eq->slot = ServerToUnderfootSlot(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; + strcpy(vr->items[x].item_name, ivr->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(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; + + 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_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 = zps->bind_zone_id; + zph->bind_instance_id = zps->bind_instance_id; + strcpy(zph->zone_name, zps->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) { + 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; + emu = (Spawn_Struct *)__emu_buffer; //_log(NET__STRUCTS, "Spawn packet size is %i, entries = %i", in->size, entrycount); - char *Buffer = (char *) in->pBuffer; - + char *Buffer = (char *)in->pBuffer; int r; int k; - for(r = 0; r < entrycount; r++, emu++) { + for (r = 0; r < entrycount; r++, emu++) { int PacketSize = sizeof(structs::Spawn_Struct); PacketSize += strlen(emu->name); PacketSize += strlen(emu->lastName); - if(strlen(emu->title)) + if (strlen(emu->title)) PacketSize += strlen(emu->title) + 1; - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - if(emu->DestructibleObject) + if (emu->DestructibleObject) { PacketSize = PacketSize - 4; // No bodytype PacketSize += 53; // Fixed portion @@ -1022,7 +2568,7 @@ ENCODE(OP_ZoneSpawns) { } bool ShowName = 1; - if(emu->bodytype >= 66) + if (emu->bodytype >= 66) { emu->race = 127; emu->bodytype = 11; @@ -1031,30 +2577,30 @@ ENCODE(OP_ZoneSpawns) { } float SpawnSize = emu->size; - if(!((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) + if (!((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522))) { PacketSize -= (sizeof(structs::EquipStruct) * 9); - if(emu->size == 0) + if (emu->size == 0) { emu->size = 6; SpawnSize = 6; } } - if(SpawnSize == 0) + if (SpawnSize == 0) { SpawnSize = 3; } EQApplicationPacket *outapp = new EQApplicationPacket(OP_ZoneEntry, PacketSize); - Buffer = (char *) outapp->pBuffer; + Buffer = (char *)outapp->pBuffer; VARSTRUCT_ENCODE_STRING(Buffer, emu->name); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000 } @@ -1085,10 +2631,10 @@ ENCODE(OP_ZoneSpawns) { Bitfields->showname = ShowName; - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x1d600000); - Buffer = Buffer -4; + Buffer = Buffer - 4; } Bitfields->ispet = emu->is_pet; @@ -1097,18 +2643,18 @@ ENCODE(OP_ZoneSpawns) { uint8 OtherData = 0; - if(strlen(emu->title)) + if (strlen(emu->title)) OtherData = OtherData | 0x04; - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) OtherData = OtherData | 0x08; - if(emu->DestructibleObject) + if (emu->DestructibleObject) OtherData = OtherData | 0xd1; // Live has 0xe1 for OtherData VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); } @@ -1118,7 +2664,7 @@ ENCODE(OP_ZoneSpawns) { } VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 - if(emu->DestructibleObject) + if (emu->DestructibleObject) { VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleModel); VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleName2); @@ -1150,15 +2696,15 @@ ENCODE(OP_ZoneSpawns) { /* if(emu->bodytype >=66) { - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // showname + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // showname } else { - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // showname + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // showname }*/ - if(!emu->DestructibleObject) + if (!emu->DestructibleObject) { // 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. @@ -1182,7 +2728,7 @@ ENCODE(OP_ZoneSpawns) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding' VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity); - if(emu->NPC) + if (emu->NPC) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xFFFFFFFF); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0x00000000); @@ -1213,7 +2759,6 @@ ENCODE(OP_ZoneSpawns) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 - structs::Spawn_Struct_Position *Position = (structs::Spawn_Struct_Position*)Buffer; Position->deltaX = emu->deltaX; @@ -1228,9 +2773,9 @@ ENCODE(OP_ZoneSpawns) { Buffer += sizeof(structs::Spawn_Struct_Position); - if((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu ->race == 130) || (emu->race == 330) || (emu->race == 522)) + 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) + for (k = 0; k < 9; ++k) { { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->colors[k].color); @@ -1252,12 +2797,11 @@ ENCODE(OP_ZoneSpawns) { VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); } - - if((emu->NPC == 0) || (emu->race <=12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) + if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { structs::EquipStruct *Equipment = (structs::EquipStruct *)Buffer; - for(k = 0; k < 9; k++) { + for (k = 0; k < 9; k++) { Equipment[k].equip0 = emu->equipment[k]; Equipment[k].equip1 = 0; Equipment[k].itemId = 0; @@ -1265,12 +2809,12 @@ ENCODE(OP_ZoneSpawns) { Buffer += (sizeof(structs::EquipStruct) * 9); } - if(strlen(emu->title)) + if (strlen(emu->title)) { VARSTRUCT_ENCODE_STRING(Buffer, emu->title); } - if(strlen(emu->suffix)) + if (strlen(emu->suffix)) { VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix); } @@ -1280,2083 +2824,503 @@ ENCODE(OP_ZoneSpawns) { Buffer += 28; // Unknown; dest->FastQueuePacket(&outapp, ack_req); - } - - delete in; -} - -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].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); - 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; -} - -// This packet does not appear to exist in UF, but leaving it here just in case -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; - } - - 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].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); - 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, emu->MercData[r].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_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_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_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++; - - //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) \ - strcpy(e->field, str.c_str()); \ - e = (GuildMemberEntry_Struct *) ( ((uint8 *)e) + str.length() )*/ -#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_); - PutFieldN(rank); - PutFieldN(time_last_on); - PutFieldN(tribute_enable); - 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); - - -#undef SlideStructString -#undef PutFieldN - - e++; - } - } - - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - - -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++) { - strcpy(eq[r].name, emu[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].unknown0076 = 0; - eq[r].unknown0077 = 1; // Both must be 1 to allow clicking doors - eq[r].unknown0078 = 0; - eq[r].unknown0079 = 1; // Both must be 1 to allow clicking doors - eq[r].unknown0080 = 0; - eq[r].unknown0081 = 0; - eq[r].unknown0082 = 0; - } - FINISH_ENCODE(); -} - -ENCODE(OP_GroundSpawn) -{ - - // We are not encoding the spawn_id field here, or a size 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) + 58; - - 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, 0); // Unknown, observed 0x00006762 - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observer 0x7fffbb64 - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); - // This next field is actually a float. There is a groundspawn in freeportwest (sack of money sitting on some barrels) which requires this - // field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same - // issue. - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0 - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // This appears to be the size field. - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); - VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->object_type); // Unknown, observed 0x00000014 - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0xffffffff); // Unknown, observed 0xffffffff - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0x00000014 - VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, 0); // Unknown, observed 0x00 - - delete[] __emu_buffer; - - dest->FastQueuePacket(&in, ack_req); -} - -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_OnLevelMessage) -{ - ENCODE_LENGTH_EXACT(OnLevelMessage_Struct); - SETUP_DIRECT_ENCODE(OnLevelMessage_Struct, structs::OnLevelMessage_Struct); - memcpy(eq->Title, emu->Title, sizeof(eq->Title)); - 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. - OUT_str(ButtonName0); - OUT_str(ButtonName1); - 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); - - 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_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_ExpansionInfo) { - ENCODE_LENGTH_EXACT(ExpansionInfo_Struct); - SETUP_DIRECT_ENCODE(ExpansionInfo_Struct, structs::ExpansionInfo_Struct); - OUT(Expansions); - FINISH_ENCODE(); -} - -ENCODE(OP_LogServer) { - ENCODE_LENGTH_EXACT(LogServer_Struct); - SETUP_DIRECT_ENCODE(LogServer_Struct, structs::LogServer_Struct); - strcpy(eq->worldshortname, emu->worldshortname); - - OUT(enablevoicemacros); - OUT(enablemail); - OUT(enable_pvp); - OUT(enable_FV); - - eq->unknown016 = 1; - eq->unknown020[0] = 1; - - // These next two need to be set like this for the Tutorial Button to work. - eq->unknown263[0] = 0; - eq->unknown263[2] = 1; - eq->unknown263[4] = 1; - eq->unknown263[5] = 1; - eq->unknown263[6] = 1; - eq->unknown263[9] = 8; - eq->unknown263[19] = 0x80; - eq->unknown263[20] = 0x3f; - eq->unknown263[23] = 0x80; - eq->unknown263[24] = 0x3f; - eq->unknown263[33] = 1; - - 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_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_Action) { - ENCODE_LENGTH_EXACT(Action_Struct); - SETUP_DIRECT_ENCODE(Action_Struct, structs::ActionAlt_Struct); - OUT(target); - OUT(source); - OUT(level); - eq->instrument_mod = 1.0f + (emu->instrument_mod - 10) / 10.0f; - eq->knockback_angle = emu->sequence; - OUT(type); - OUT(spell); - eq->level2 = eq->level; - eq->effect_flag = emu->buff_unknown; - eq->unknown37 = 0x01; - eq->unknown44 = 0xFFFFFFFF; - eq->unknown48 = 0xFFFFFFFF; - eq->unknown52 = 0xFFFFFFFF; - - /*OUT(target); - OUT(source); - OUT(level); - OUT(instrument_mod); - eq->sequence = emu->sequence; - OUT(type); - //OUT(damage); - OUT(spell); - eq->level2 = emu->level; - OUT(buff_unknown); // if this is 4, a buff icon is made - //eq->unknown0036 = -1; - //eq->unknown0040 = -1; - //eq->unknown0044 = -1;*/ - FINISH_ENCODE(); -} - -ENCODE(OP_Buff) { - ENCODE_LENGTH_EXACT(SpellBuffFade_Struct); - SETUP_DIRECT_ENCODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Underfoot); - OUT(entityid); - OUT(slot); - OUT(level); - OUT(effect); - //eq->unknown7 = 10; - OUT(spellid); - OUT(duration); - OUT(slotid); - OUT(bufffade); // Live (October 2011) sends a 2 rather than 0 when a buff is created, but it doesn't seem to matter. - eq->unknown008 = 1.0f; - 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_ShopPlayerSell) { - ENCODE_LENGTH_EXACT(Merchant_Purchase_Struct); - SETUP_DIRECT_ENCODE(Merchant_Purchase_Struct, structs::Merchant_Purchase_Struct); - OUT(npcid); - eq->itemslot = ServerToUnderfootSlot(emu->itemslot); - OUT(quantity); - OUT(price); - FINISH_ENCODE(); -} - -ENCODE(OP_ApplyPoison) { - ENCODE_LENGTH_EXACT(ApplyPoison_Struct); - SETUP_DIRECT_ENCODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - eq->inventorySlot = ServerToUnderfootSlot(emu->inventorySlot); - OUT(success); - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteItem) { - ENCODE_LENGTH_EXACT(DeleteItem_Struct); - SETUP_DIRECT_ENCODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - eq->from_slot = ServerToUnderfootSlot(emu->from_slot); - eq->to_slot = ServerToUnderfootSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_DeleteCharge) { ENCODE_FORWARD(OP_MoveItem); } -ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToUnderfootSlot(emu->from_slot); - eq->to_slot = ServerToUnderfootSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); -} - -ENCODE(OP_ItemVerifyReply) { - ENCODE_LENGTH_EXACT(ItemVerifyReply_Struct); - SETUP_DIRECT_ENCODE(ItemVerifyReply_Struct, structs::ItemVerifyReply_Struct); - - eq->slot = ServerToUnderfootSlot(emu->slot); - OUT(spell); - OUT(target); - - FINISH_ENCODE(); -} - -ENCODE(OP_Trader) { - - if((*p)->size != sizeof(TraderBuy_Struct)) { - EQApplicationPacket *in = *p; - *p = nullptr; - dest->FastQueuePacket(&in, ack_req); - return; - } - 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_LootItem) { - - ENCODE_LENGTH_EXACT(LootingItem_Struct); - SETUP_DIRECT_ENCODE(LootingItem_Struct, structs::LootingItem_Struct); - OUT(lootee); - OUT(looter); - eq->slot_id = emu->slot_id + 1; - OUT(auto_loot); - - FINISH_ENCODE(); -} - -ENCODE(OP_TributeItem) { - ENCODE_LENGTH_EXACT(TributeItem_Struct); - SETUP_DIRECT_ENCODE(TributeItem_Struct, structs::TributeItem_Struct); - - eq->slot = ServerToUnderfootSlot(emu->slot); - OUT(quantity); - OUT(tribute_master_id); - OUT(tribute_points); - - 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 = 135; // This needs to be set to something, else we get a 1HS animation instead of ranged. - - OUT(item_type); - OUT(skill); - - strcpy(eq->model_name, emu->model_name); - - FINISH_ENCODE(); -} - -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); - eq->invslot = ServerToUnderfootSlot(emu->invslot); - strn0cpy(eq->txtfile, emu->booktext, sizeof(eq->txtfile)); - 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_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 = zps->bind_zone_id; - zph->bind_instance_id = zps->bind_instance_id; - strcpy(zph->zone_name, zps->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_AdventureMerchantSell) { - ENCODE_LENGTH_EXACT(Adventure_Sell_Struct); - SETUP_DIRECT_ENCODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - eq->unknown000 = 1; - OUT(npcid); - eq->slot = ServerToUnderfootSlot(emu->slot); - OUT(charges); - OUT(sell_price); - - FINISH_ENCODE(); -} - -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 +// DECODE methods + DECODE(OP_AdventureMerchantSell) { - RaidAddMember_Struct* in_add_member = (RaidAddMember_Struct*)__emu_buffer; + DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); + SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - EQApplicationPacket *outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(structs::RaidAddMember_Struct)); - structs::RaidAddMember_Struct *add_member = (structs::RaidAddMember_Struct*)outapp->pBuffer; + IN(npcid); + emu->slot = UnderfootToServerSlot(eq->slot); + IN(charges); + IN(sell_price); - 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 - { - 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_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_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; - strcpy(vr->items[x].item_name, ivr->items[x].item_name); - vr->items[x].charges = ivr->items[x].charges; - } - - old_data += sizeof(InternalVeteranReward); - data += sizeof(structs::VeteranReward); + FINISH_DIRECT_DECODE(); } - dest->FastQueuePacket(&outapp_create); - delete inapp; -} - -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; - - memcpy(OutBuffer, InBuffer, sizeof(WhoAllReturnStruct)); - - OutBuffer += sizeof(WhoAllReturnStruct); - InBuffer += sizeof(WhoAllReturnStruct); - - for(int i = 0; i < Count; ++i) + DECODE(OP_AltCurrencySell) { - uint32 x; + DECODE_LENGTH_EXACT(structs::AltCurrencySellItem_Struct); + SETUP_DIRECT_DECODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + IN(merchant_entity_id); + emu->slot_id = UnderfootToServerSlot(eq->slot_id); + IN(charges); + IN(cost); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + 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 = UnderfootToServerSlot(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 = UnderfootToServerSlot(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 = UnderfootToServerSlot(eq->container_slot); + emu->augment_slot = eq->augment_slot; + + 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_Buff) + { + DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Underfoot); + SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Underfoot); + + 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 < 30) ? eq->SlotID : (eq->SlotID - 5); + + 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 = UnderfootToServerSlot(eq->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; - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0xffffffff); - char Name[64]; + uint32 Language = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + uint32 Channel = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); + InBuffer += 5; - VARSTRUCT_DECODE_STRING(Name, InBuffer); // Char Name - VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + uint32 Skill = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - x = VARSTRUCT_DECODE_TYPE(uint32, InBuffer); - VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, x); + __packet->size = sizeof(ChannelMessage_Struct)+strlen(InBuffer) + 1; + __packet->pBuffer = new unsigned char[__packet->size]; + ChannelMessage_Struct *emu = (ChannelMessage_Struct *)__packet->pBuffer; - VARSTRUCT_DECODE_STRING(Name, InBuffer); // Guild Name - VARSTRUCT_ENCODE_STRING(OutBuffer, Name); + 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); - 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); + delete[] __eq_buffer; } - //_hex(NET__ERROR, outapp->pBuffer, outapp->size); - dest->FastQueuePacket(&outapp); - - delete in; -} - -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_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_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_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)) + DECODE(OP_CharacterCreate) { - 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_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_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_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; - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->leader_name, emu->leader_name); - 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_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_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_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_DzJoinExpeditionConfirm) -{ - ENCODE_LENGTH_EXACT(ExpeditionJoinPrompt_Struct); - SETUP_DIRECT_ENCODE(ExpeditionJoinPrompt_Struct, structs::ExpeditionJoinPrompt_Struct); - strcpy(eq->expedition_name, emu->expedition_name); - strcpy(eq->player_name, emu->player_name); - FINISH_ENCODE(); -} - -ENCODE(OP_TargetBuffs) { ENCODE_FORWARD(OP_BuffCreate); } -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); - - uchar *ptr = __packet->pBuffer; - *((uint32*)ptr) = emu->entity_id; - ptr += sizeof(uint32); - ptr += sizeof(uint32); - *((uint8*)ptr) = 1; - ptr += sizeof(uchar); - *((uint16*)ptr) = emu->count; - ptr += sizeof(uint16); - - for(uint16 i = 0; i < emu->count; ++i) - { - uint16 buffslot = emu->entries[i].buff_slot; - if(emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) - { - buffslot += 5; - } - else if(emu->entries[i].buff_slot >= 37) - { - buffslot += 14; - } - - *((uint32*)ptr) = buffslot; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].spell_id; - ptr += sizeof(uint32); - *((uint32*)ptr) = emu->entries[i].tics_remaining; - ptr += sizeof(uint32); - ptr += sizeof(uint32); - ptr += 1; - } - FINISH_ENCODE(); - /* - uint32 write_var32 = 60; - uint8 write_var8 = 1; - ss.write((const char*)&emu->entity_id, sizeof(uint32)); - ss.write((const char*)&write_var32, sizeof(uint32)); - ss.write((const char*)&write_var8, sizeof(uint8)); - ss.write((const char*)&emu->count, sizeof(uint16)); - write_var32 = 0; - write_var8 = 0; - for(uint16 i = 0; i < emu->count; ++i) - { - if(emu->entries[i].buff_slot >= 25 && emu->entries[i].buff_slot < 37) - { - emu->entries[i].buff_slot += 5; - } - else if(emu->entries[i].buff_slot >= 37) - { - emu->entries[i].buff_slot += 14; - } - ss.write((const char*)&emu->entries[i].buff_slot, sizeof(uint32)); - ss.write((const char*)&emu->entries[i].spell_id, sizeof(uint32)); - ss.write((const char*)&emu->entries[i].tics_remaining, sizeof(uint32)); - ss.write((const char*)&write_var32, sizeof(uint32)); - ss.write((const char*)&write_var8, sizeof(uint8)); - } - ss.write((const char*)&write_var8, sizeof(uint8)); - */ -} - -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(color.color); - OUT(wear_slot_id); - 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_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_AltCurrencySell) -{ - ENCODE_LENGTH_EXACT(AltCurrencySellItem_Struct); - SETUP_DIRECT_ENCODE(AltCurrencySellItem_Struct, structs::AltCurrencySellItem_Struct); - - OUT(merchant_entity_id); - eq->slot_id = ServerToUnderfootSlot(emu->slot_id); - OUT(charges); - OUT(cost); - 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].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].unknown00 = populate->entries[i].unknown00; - } - - 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_InspectRequest) { - ENCODE_LENGTH_EXACT(Inspect_Struct); - SETUP_DIRECT_ENCODE(Inspect_Struct, structs::Inspect_Struct); - OUT(TargetID); - OUT(PlayerID); - FINISH_ENCODE(); -} - -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_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_RaidInvite) { - 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(); -} - -DECODE(OP_AdventureMerchantSell) { - DECODE_LENGTH_EXACT(structs::Adventure_Sell_Struct); - SETUP_DIRECT_DECODE(Adventure_Sell_Struct, structs::Adventure_Sell_Struct); - - IN(npcid); - emu->slot = UnderfootToServerSlot(eq->slot); - IN(charges); - IN(sell_price); - - FINISH_DIRECT_DECODE(); -} - - -DECODE(OP_ApplyPoison) { - DECODE_LENGTH_EXACT(structs::ApplyPoison_Struct); - SETUP_DIRECT_DECODE(ApplyPoison_Struct, structs::ApplyPoison_Struct); - - emu->inventorySlot = UnderfootToServerSlot(eq->inventorySlot); - IN(success); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ItemVerifyRequest) { - DECODE_LENGTH_EXACT(structs::ItemVerifyRequest_Struct); - SETUP_DIRECT_DECODE(ItemVerifyRequest_Struct, structs::ItemVerifyRequest_Struct); - - emu->slot = UnderfootToServerSlot(eq->slot); - IN(target); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_Consume) { - DECODE_LENGTH_EXACT(structs::Consume_Struct); - SETUP_DIRECT_DECODE(Consume_Struct, structs::Consume_Struct); - - emu->slot = UnderfootToServerSlot(eq->slot); - IN(auto_consumed); - IN(type); - - 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 = UnderfootToServerSlot(eq->inventoryslot); - IN(target_id); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_DeleteItem) -{ - DECODE_LENGTH_EXACT(structs::DeleteItem_Struct); - SETUP_DIRECT_DECODE(DeleteItem_Struct, structs::DeleteItem_Struct); - - emu->from_slot = UnderfootToServerSlot(eq->from_slot); - emu->to_slot = UnderfootToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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, eq->to_slot); - - emu->from_slot = UnderfootToServerSlot(eq->from_slot); - emu->to_slot = UnderfootToServerSlot(eq->to_slot); - IN(number_in_stack); - - 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]); - } - IN(link_hash); - IN(icon); - - 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++) { - IN(filters[r]); - } - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ConsiderCorpse) { DECODE_FORWARD(OP_Consider); } -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_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_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_CharacterCreate) { - DECODE_LENGTH_EXACT(structs::CharCreate_Struct); - SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); - IN(class_); - IN(beardcolor); - IN(beard); - IN(hairstyle); - IN(gender); - IN(race); - - if(RuleB(World, EnableTutorialButton) && eq->tutorial) - emu->start_zone = RuleI(World, TutorialZoneID); - else - emu->start_zone = eq->start_zone; - - IN(haircolor); - IN(deity); - IN(STR); - IN(STA); - IN(AGI); - IN(DEX); - IN(WIS); - IN(INT); - IN(CHA); - IN(face); - IN(eyecolor1); - IN(eyecolor2); - IN(drakkin_heritage); - IN(drakkin_tattoo); - IN(drakkin_details); - - 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_GroupInvite2) -{ - //_log(NET__ERROR, "Received incoming OP_GroupInvite2. Forwarding"); - DECODE_FORWARD(OP_GroupInvite); -} - -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_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_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_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_Buff) { - DECODE_LENGTH_EXACT(structs::SpellBuffFade_Struct_Underfoot); - SETUP_DIRECT_DECODE(SpellBuffFade_Struct, structs::SpellBuffFade_Struct_Underfoot); - IN(entityid); - IN(slot); - IN(level); - IN(effect); - IN(spellid); - IN(duration); - IN(slotid); - IN(bufffade); - 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 = UnderfootToServerSlot(eq->itemslot); - IN(quantity); - IN(price); - - 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_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_WearChange) { - DECODE_LENGTH_EXACT(structs::WearChange_Struct); - SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); - IN(spawn_id); - IN(material); - IN(unknown06); - IN(elite_material); - IN(color.color); - IN(wear_slot_id); - emu->hero_forge_model = 0; - emu->unknown18 = 0; - 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_LootItem) { - DECODE_LENGTH_EXACT(structs::LootingItem_Struct); - SETUP_DIRECT_DECODE(LootingItem_Struct, structs::LootingItem_Struct); - IN(lootee); - IN(looter); - emu->slot_id = eq->slot_id - 1; - IN(auto_loot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TributeItem) { - DECODE_LENGTH_EXACT(structs::TributeItem_Struct); - SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); - - emu->slot = UnderfootToServerSlot(eq->slot); - IN(quantity); - IN(tribute_master_id); - IN(tribute_points); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_ReadBook) { - DECODE_LENGTH_EXACT(structs::BookRequest_Struct); - SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); - - IN(type); - emu->invslot = UnderfootToServerSlot(eq->invslot); - emu->window = (uint8) eq->window; - strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_TradeSkillCombine) { - DECODE_LENGTH_EXACT(structs::NewCombine_Struct); - SETUP_DIRECT_DECODE(NewCombine_Struct, structs::NewCombine_Struct); - - emu->container_slot = UnderfootToServerSlot(eq->container_slot); - - FINISH_DIRECT_DECODE(); -} - -DECODE(OP_AugmentItem) { - DECODE_LENGTH_EXACT(structs::AugmentItem_Struct); - SETUP_DIRECT_DECODE(AugmentItem_Struct, structs::AugmentItem_Struct); - - emu->container_slot = UnderfootToServerSlot(eq->container_slot); - emu->augment_slot = eq->augment_slot; - - 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_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_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; + DECODE_LENGTH_EXACT(structs::CharCreate_Struct); + SETUP_DIRECT_DECODE(CharCreate_Struct, structs::CharCreate_Struct); + + IN(class_); + IN(beardcolor); + IN(beard); + IN(hairstyle); + IN(gender); + IN(race); + + if (RuleB(World, EnableTutorialButton) && eq->tutorial) + emu->start_zone = RuleI(World, TutorialZoneID); else - emu->spell[i] = eq->spell[i]; + emu->start_zone = eq->start_zone; - FINISH_DIRECT_DECODE(); -} + IN(haircolor); + IN(deity); + IN(STR); + IN(STA); + IN(AGI); + IN(DEX); + IN(WIS); + IN(INT); + IN(CHA); + IN(face); + IN(eyecolor1); + IN(eyecolor2); + IN(drakkin_heritage); + IN(drakkin_tattoo); + IN(drakkin_details); -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(); -} + 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_PetCommands) -{ - DECODE_LENGTH_EXACT(structs::PetCommand_Struct); - SETUP_DIRECT_DECODE(PetCommand_Struct, structs::PetCommand_Struct); - - switch(eq->command) + 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 = UnderfootToServerSlot(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 = UnderfootToServerSlot(eq->from_slot); + emu->to_slot = UnderfootToServerSlot(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_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_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]); + } + 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 = UnderfootToServerSlot(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 = eq->slot_id - 1; + 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, eq->to_slot); + + emu->from_slot = UnderfootToServerSlot(eq->from_slot); + emu->to_slot = UnderfootToServerSlot(eq->to_slot); + IN(number_in_stack); + + 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; @@ -3404,574 +3368,683 @@ DECODE(OP_PetCommands) break; default: emu->command = eq->command; - } - OUT(unknown); + } + OUT(unknown); - 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_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 < 30 ) ? eq->SlotID : (eq->SlotID - 5); - - IN(EntityID); - - FINISH_DIRECT_DECODE(); -} - -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) { - 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->GetItem(); - //_log(NET__ERROR, "Serialize called for: %s", item->Name); - Underfoot::structs::ItemSerializationHeader hdr; - hdr.stacksize = stackable ? charges : 1; - hdr.unknown004 = 0; - - int32 slot_id = ServerToUnderfootSlot(slot_id_in); - - hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; - hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.unknown020 = 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.unknown056 = 0; - hdr.unknown060 = 0; - hdr.unknown061 = 0; - hdr.unknown062 = 0; - hdr.ItemClass = item->ItemClass; - - ss.write((const char*)&hdr, sizeof(Underfoot::structs::ItemSerializationHeader)); - - 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)); + FINISH_DIRECT_DECODE(); } - if(strlen(item->Lore) > 0) + DECODE(OP_RaidInvite) { - ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); + 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(); } - if(strlen(item->IDFile) > 0) + DECODE(OP_ReadBook) { - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); + DECODE_LENGTH_EXACT(structs::BookRequest_Struct); + SETUP_DIRECT_DECODE(BookRequest_Struct, structs::BookRequest_Struct); + + IN(type); + emu->invslot = UnderfootToServerSlot(eq->invslot); + emu->window = (uint8)eq->window; + strn0cpy(emu->txtfile, eq->txtfile, sizeof(emu->txtfile)); + + FINISH_DIRECT_DECODE(); } - Underfoot::structs::ItemBodyStruct ibs; - memset(&ibs, 0, sizeof(Underfoot::structs::ItemBodyStruct)); - - uint32 adjusted_slots = item->Slots; - - // Conversions for Ammo and Power Source Slots - if(item->Slots & (1 << 21) & (1 << 22)) + DECODE(OP_Save) { - // Do nothing + 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(); } - else + + DECODE(OP_SetServerFilter) { - if(item->Slots & (1 << 21)) // Ammo Slot from Database - { - adjusted_slots -= (1 << 21); // Ammo Slot in Titanium - adjusted_slots += (1 << 22); // Ammo Slot in SoF + DECODE_LENGTH_EXACT(structs::SetServerFilter_Struct); + SETUP_DIRECT_DECODE(SetServerFilter_Struct, structs::SetServerFilter_Struct); + + int r; + for (r = 0; r < 29; r++) { + IN(filters[r]); } - if(item->Slots & (1 << 22)) // Power Source Slot from Database + 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 = UnderfootToServerSlot(eq->itemslot); + IN(quantity); + IN(price); + + 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); + + emu->container_slot = UnderfootToServerSlot(eq->container_slot); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_TributeItem) + { + DECODE_LENGTH_EXACT(structs::TributeItem_Struct); + SETUP_DIRECT_DECODE(TributeItem_Struct, structs::TributeItem_Struct); + + emu->slot = UnderfootToServerSlot(eq->slot); + IN(quantity); + IN(tribute_master_id); + IN(tribute_points); + + FINISH_DIRECT_DECODE(); + } + + DECODE(OP_WearChange) + { + DECODE_LENGTH_EXACT(structs::WearChange_Struct); + SETUP_DIRECT_DECODE(WearChange_Struct, structs::WearChange_Struct); + + IN(spawn_id); + IN(material); + IN(unknown06); + IN(elite_material); + IN(color.color); + IN(wear_slot_id); + emu->hero_forge_model = 0; + emu->unknown18 = 0; + + 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(); + } + +// 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) + { + 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->GetItem(); + //_log(NET__ERROR, "Serialize called for: %s", item->Name); + Underfoot::structs::ItemSerializationHeader hdr; + hdr.stacksize = stackable ? charges : 1; + hdr.unknown004 = 0; + + int32 slot_id = ServerToUnderfootSlot(slot_id_in); + + hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot; + hdr.price = inst->GetPrice(); + hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); + hdr.unknown020 = 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.unknown056 = 0; + hdr.unknown060 = 0; + hdr.unknown061 = 0; + hdr.unknown062 = 0; + hdr.ItemClass = item->ItemClass; + + ss.write((const char*)&hdr, sizeof(Underfoot::structs::ItemSerializationHeader)); + + if (strlen(item->Name) > 0) { - adjusted_slots -= (1 << 22); // Non Existant Worn Slot in Titanium - adjusted_slots += (1 << 21); // Power Source Slot in SoF + ss.write(item->Name, strlen(item->Name)); + ss.write((const char*)&null_term, sizeof(uint8)); + } + else + { + ss.write((const char*)&null_term, sizeof(uint8)); } - } - 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 = adjusted_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; + 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)); + } - 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.unknown5 = 0; - ibs.SkillModType = item->SkillModType; - 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; - ibs.RecLevel = item->RecLevel; - 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.ItemType = item->ItemType; - ibs.Material = item->Material; - ibs.unknown7 = 0; - ibs.EliteMaterial = item->EliteMaterial; - ibs.SellRate = item->SellRate; + 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)); + } - 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.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; + Underfoot::structs::ItemBodyStruct ibs; + memset(&ibs, 0, sizeof(Underfoot::structs::ItemBodyStruct)); - ss.write((const char*)&ibs, sizeof(Underfoot::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; - //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)); - } + 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.unknown5 = 0; + ibs.SkillModType = item->SkillModType; + 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; + ibs.RecLevel = item->RecLevel; + 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.ItemType = item->ItemType; + ibs.Material = item->Material; + ibs.unknown7 = 0; + ibs.EliteMaterial = item->EliteMaterial; + ibs.SellRate = item->SellRate; - Underfoot::structs::ItemSecondaryBodyStruct isbs; - memset(&isbs, 0, sizeof(Underfoot::structs::ItemSecondaryBodyStruct)); + 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.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; - isbs.augtype = item->AugType; - isbs.augrestrict = item->AugRestrict; + ss.write((const char*)&ibs, sizeof(Underfoot::structs::ItemBodyStruct)); - for(int x = 0; x < 5; ++x) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; - } + //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)); + } - isbs.ldonpoint_type = item->PointType; - isbs.ldontheme = item->LDoNTheme; - isbs.ldonprice = item->LDoNPrice; - isbs.ldonsellbackrate = item->LDoNSellBackRate; - isbs.ldonsold = item->LDoNSold; + Underfoot::structs::ItemSecondaryBodyStruct isbs; + memset(&isbs, 0, sizeof(Underfoot::structs::ItemSecondaryBodyStruct)); - isbs.bagtype = item->BagType; - isbs.bagslots = item->BagSlots; - isbs.bagsize = item->BagSize; - isbs.wreduction = item->BagWR; + isbs.augtype = item->AugType; + isbs.augrestrict = item->AugRestrict; - isbs.book = item->Book; - isbs.booktype = item->BookType; + for (int x = 0; x < 5; ++x) + { + isbs.augslots[x].type = item->AugSlotType[x]; + isbs.augslots[x].visible = item->AugSlotVisible[x]; + isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + } - ss.write((const char*)&isbs, sizeof(Underfoot::structs::ItemSecondaryBodyStruct)); + isbs.ldonpoint_type = item->PointType; + isbs.ldontheme = item->LDoNTheme; + isbs.ldonprice = item->LDoNPrice; + isbs.ldonsellbackrate = item->LDoNSellBackRate; + isbs.ldonsold = item->LDoNSold; - 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)); - } + isbs.bagtype = item->BagType; + isbs.bagslots = item->BagSlots; + isbs.bagsize = item->BagSize; + isbs.wreduction = item->BagWR; - Underfoot::structs::ItemTertiaryBodyStruct itbs; - memset(&itbs, 0, sizeof(Underfoot::structs::ItemTertiaryBodyStruct)); + isbs.book = item->Book; + isbs.booktype = item->BookType; - 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.no_pet = item->NoPet; + ss.write((const char*)&isbs, sizeof(Underfoot::structs::ItemSecondaryBodyStruct)); - 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; + 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)); + } - ss.write((const char*)&itbs, sizeof(Underfoot::structs::ItemTertiaryBodyStruct)); + Underfoot::structs::ItemTertiaryBodyStruct itbs; + memset(&itbs, 0, sizeof(Underfoot::structs::ItemTertiaryBodyStruct)); - // Effect Structures Broken down to allow variable length strings for effect names - int32 effect_unknown = 0; + 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.no_pet = item->NoPet; - Underfoot::structs::ClickEffectStruct ices; - memset(&ices, 0, sizeof(Underfoot::structs::ClickEffectStruct)); + 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; - 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*)&itbs, sizeof(Underfoot::structs::ItemTertiaryBodyStruct)); - ss.write((const char*)&ices, sizeof(Underfoot::structs::ClickEffectStruct)); + // Effect Structures Broken down to allow variable length strings for effect names + int32 effect_unknown = 0; - 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)); - } + Underfoot::structs::ClickEffectStruct ices; + memset(&ices, 0, sizeof(Underfoot::structs::ClickEffectStruct)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + 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; - Underfoot::structs::ProcEffectStruct ipes; - memset(&ipes, 0, sizeof(Underfoot::structs::ProcEffectStruct)); + ss.write((const char*)&ices, sizeof(Underfoot::structs::ClickEffectStruct)); - ipes.effect = item->Proc.Effect; - ipes.level2 = item->Proc.Level2; - ipes.type = item->Proc.Type; - ipes.level = item->Proc.Level; - ipes.procrate = item->ProcRate; + 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*)&ipes, sizeof(Underfoot::structs::ProcEffectStruct)); + ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 - 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)); - } + Underfoot::structs::ProcEffectStruct ipes; + memset(&ipes, 0, sizeof(Underfoot::structs::ProcEffectStruct)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ipes.effect = item->Proc.Effect; + ipes.level2 = item->Proc.Level2; + ipes.type = item->Proc.Type; + ipes.level = item->Proc.Level; + ipes.procrate = item->ProcRate; - Underfoot::structs::WornEffectStruct iwes; - memset(&iwes, 0, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&ipes, sizeof(Underfoot::structs::ProcEffectStruct)); - iwes.effect = item->Worn.Effect; - iwes.level2 = item->Worn.Level2; - iwes.type = item->Worn.Type; - iwes.level = item->Worn.Level; + 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*)&iwes, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 - 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)); - } + Underfoot::structs::WornEffectStruct iwes; + memset(&iwes, 0, sizeof(Underfoot::structs::WornEffectStruct)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + iwes.effect = item->Worn.Effect; + iwes.level2 = item->Worn.Level2; + iwes.type = item->Worn.Type; + iwes.level = item->Worn.Level; - Underfoot::structs::WornEffectStruct ifes; - memset(&ifes, 0, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&iwes, sizeof(Underfoot::structs::WornEffectStruct)); - ifes.effect = item->Focus.Effect; - ifes.level2 = item->Focus.Level2; - ifes.type = item->Focus.Type; - ifes.level = item->Focus.Level; + 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*)&ifes, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - 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)); - } + Underfoot::structs::WornEffectStruct ifes; + memset(&ifes, 0, sizeof(Underfoot::structs::WornEffectStruct)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ifes.effect = item->Focus.Effect; + ifes.level2 = item->Focus.Level2; + ifes.type = item->Focus.Type; + ifes.level = item->Focus.Level; - Underfoot::structs::WornEffectStruct ises; - memset(&ises, 0, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&ifes, sizeof(Underfoot::structs::WornEffectStruct)); - ises.effect = item->Scroll.Effect; - ises.level2 = item->Scroll.Level2; - ises.type = item->Scroll.Type; - ises.level = item->Scroll.Level; + 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*)&ises, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - 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)); - } + Underfoot::structs::WornEffectStruct ises; + memset(&ises, 0, sizeof(Underfoot::structs::WornEffectStruct)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ises.effect = item->Scroll.Effect; + ises.level2 = item->Scroll.Level2; + ises.type = item->Scroll.Type; + ises.level = item->Scroll.Level; - // Bard Effect? - Underfoot::structs::WornEffectStruct ibes; - memset(&ibes, 0, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&ises, sizeof(Underfoot::structs::WornEffectStruct)); - ibes.effect = item->Bard.Effect; - ibes.level2 = item->Bard.Level2; - ibes.type = item->Bard.Type; - ibes.level = item->Bard.Level; - //ibes.unknown6 = 0xffffffff; + 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*)&ibes, sizeof(Underfoot::structs::WornEffectStruct)); + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - /* - if(strlen(item->BardName) > 0) - { + // Bard Effect? + Underfoot::structs::WornEffectStruct ibes; + memset(&ibes, 0, sizeof(Underfoot::structs::WornEffectStruct)); + + ibes.effect = item->Bard.Effect; + ibes.level2 = item->Bard.Level2; + ibes.type = item->Bard.Type; + ibes.level = item->Bard.Level; + //ibes.unknown6 = 0xffffffff; + + ss.write((const char*)&ibes, sizeof(Underfoot::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 */ + } + else */ ss.write((const char*)&null_term, sizeof(uint8)); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - // End of Effects + ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // End of Effects - Underfoot::structs::ItemQuaternaryBodyStruct iqbs; - memset(&iqbs, 0, sizeof(Underfoot::structs::ItemQuaternaryBodyStruct)); + Underfoot::structs::ItemQuaternaryBodyStruct iqbs; + memset(&iqbs, 0, sizeof(Underfoot::structs::ItemQuaternaryBodyStruct)); - iqbs.scriptfileid = item->ScriptFileID; - iqbs.quest_item = item->QuestItemFlag; - iqbs.unknown15 = 0; + iqbs.scriptfileid = item->ScriptFileID; + iqbs.quest_item = item->QuestItemFlag; + iqbs.unknown15 = 0; - iqbs.Purity = item->Purity; - 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.Purity = item->Purity; + 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.subitem_count = 0; + iqbs.subitem_count = 0; - char *SubSerializations[10]; // + char *SubSerializations[10]; // - uint32 SubLengths[10]; + uint32 SubLengths[10]; - for(int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { - SubSerializations[x] = nullptr; + SubSerializations[x] = nullptr; - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); + const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - if(subitem) { + if (subitem) { - int SubSlotNumber; + int SubSlotNumber; - iqbs.subitem_count++; + 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; // ??????? + 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); - */ + /* + // TEST CODE: + SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x); + */ - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); + SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1); + } } + + ss.write((const char*)&iqbs, sizeof(Underfoot::structs::ItemQuaternaryBodyStruct)); + + for (int x = 0; x < 10; ++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; } - ss.write((const char*)&iqbs, sizeof(Underfoot::structs::ItemQuaternaryBodyStruct)); + static inline uint32 ServerToUnderfootSlot(uint32 ServerSlot) + { + uint32 UnderfootSlot = 0; - for(int x = 0; x < 10; ++x) { + if (ServerSlot >= MainAmmo && ServerSlot <= 53) // Cursor/Ammo/Power Source and Normal Inventory Slots + UnderfootSlot = ServerSlot + 1; + else if (ServerSlot >= EmuConstants::GENERAL_BAGS_BEGIN && ServerSlot <= EmuConstants::CURSOR_BAG_END) + UnderfootSlot = ServerSlot + 11; + else if (ServerSlot >= EmuConstants::BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::BANK_BAGS_END) + UnderfootSlot = ServerSlot + 1; + else if (ServerSlot >= EmuConstants::SHARED_BANK_BAGS_BEGIN && ServerSlot <= EmuConstants::SHARED_BANK_BAGS_END) + UnderfootSlot = ServerSlot + 1; + else if (ServerSlot == MainPowerSource) + UnderfootSlot = slots::MainPowerSource; + else + UnderfootSlot = ServerSlot; - if(SubSerializations[x]) { - - ss.write((const char*)&x, sizeof(uint32)); - - ss.write(SubSerializations[x], SubLengths[x]); - - safe_delete_array(SubSerializations[x]); - } + return UnderfootSlot; } - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); + static inline uint32 ServerToUnderFootCorpseSlot(uint32 ServerCorpse) + { + //uint32 UnderfootCorpse; + } - *length = ss.tellp(); - return item_serial; + static inline uint32 UnderfootToServerSlot(uint32 UnderfootSlot) + { + uint32 ServerSlot = 0; + + if (UnderfootSlot >= slots::MainAmmo && UnderfootSlot <= consts::CORPSE_END) // Cursor/Ammo/Power Source and Normal Inventory Slots + ServerSlot = UnderfootSlot - 1; + else if (UnderfootSlot >= consts::GENERAL_BAGS_BEGIN && UnderfootSlot <= consts::CURSOR_BAG_END) + ServerSlot = UnderfootSlot - 11; + else if (UnderfootSlot >= consts::BANK_BAGS_BEGIN && UnderfootSlot <= consts::BANK_BAGS_END) + ServerSlot = UnderfootSlot - 1; + else if (UnderfootSlot >= consts::SHARED_BANK_BAGS_BEGIN && UnderfootSlot <= consts::SHARED_BANK_BAGS_END) + ServerSlot = UnderfootSlot - 1; + else if (UnderfootSlot == slots::MainPowerSource) + ServerSlot = MainPowerSource; + else + ServerSlot = UnderfootSlot; + + return ServerSlot; + } + + static inline uint32 UnderfootToServerCorpseSlot(uint32 UnderfootCorpse) + { + //uint32 ServerCorpse; + } } - -DECODE(OP_AltCurrencySellSelection) -{ - DECODE_LENGTH_EXACT(structs::AltCurrencySelectItem_Struct); - SETUP_DIRECT_DECODE(AltCurrencySelectItem_Struct, structs::AltCurrencySelectItem_Struct); - IN(merchant_entity_id); - emu->slot_id = UnderfootToServerSlot(eq->slot_id); - 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 = UnderfootToServerSlot(eq->slot_id); - IN(charges); - IN(cost); - FINISH_DIRECT_DECODE(); -} - -} //end namespace Underfoot +// end namespace Underfoot