diff --git a/common/emu_oplist.h b/common/emu_oplist.h index eefcdfee8..f91bf235f 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -574,6 +574,7 @@ N(OP_TradeRequestAck), N(OP_TraderItemUpdate), N(OP_TraderShop), N(OP_TradeSkillCombine), +N(OP_TradeSkillRecipeInspect), N(OP_Translocate), N(OP_TributeInfo), N(OP_TributeItem), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index f6e2b9ed1..0ad3bcbd3 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -4283,6 +4283,10 @@ struct NewCombine_Struct { /*04*/ }; +struct TradeSkillRecipeInspect_Struct { + uint32 recipe_id; + uint32 padding[17]; // unknown +}; //client requesting favorite recipies struct TradeskillFavorites_Struct { diff --git a/common/opcode_dispatch.h b/common/opcode_dispatch.h index 38212acb9..60e381320 100644 --- a/common/opcode_dispatch.h +++ b/common/opcode_dispatch.h @@ -197,6 +197,7 @@ IN(OP_RecipeDetails, uint32); //there is also a complicated OP_RecipeDetails reply struct OUT IN(OP_RecipeAutoCombine, RecipeAutoCombine_Struct); IN(OP_TradeSkillCombine, NewCombine_Struct); +IN(OP_TradeSkillRecipeInspect, TradeSkillRecipeInspect_Struct); IN(OP_ItemName, ItemNamePacket_Struct); IN(OP_AugmentItem, AugmentItem_Struct); IN(OP_ClickDoor, ClickDoor_Struct); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 4a8d277eb..5f1fe4252 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -3935,6 +3935,11 @@ struct NewCombine_Struct /*24*/ }; +struct TradeSkillRecipeInspect_Struct { + uint32 recipe_id; + uint32 padding[17]; +}; + //client requesting favorite recipies struct TradeskillFavorites_Struct { @@ -4736,7 +4741,7 @@ struct ItemSerializationHeader /*036*/ uint32 merchant_slot; // 1 if not a merchant item /*040*/ uint32 scaled_value; // 0 /*044*/ uint32 instance_id; // unique instance id if not merchant item, else is merchant slot - /*048*/ uint32 parcel_item_id; + /*048*/ uint32 parcel_item_id; /*052*/ uint32 last_cast_time; // Unix Time from PP of last cast for this recast type if recast delay > 0 /*056*/ uint32 charges; // Total Charges an item has (-1 for unlimited) /*060*/ uint32 inst_nodrop; // 1 if the item is no drop (attuned items) diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index a4e6d68ed..725d9d947 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -736,6 +736,8 @@ OP_PickZone=0xaaba #evolve item related OP_EvolveItem=0x7cfb +OP_TradeSkillRecipeInspect=0x4f7e + # This is bugged in ROF2 # OP_InvokeChangePetNameImmediate is supposed to write DisablePetNameChangeReminder=0 to reset the 'nag reminder' # It actually sets DisableNameChangeReminder=0 (player name change nag reminder). Additionally, clicking the @@ -743,4 +745,4 @@ OP_EvolveItem=0x7cfb # This can be fixed with a client patch. OP_InvokeChangePetNameImmediate=0x046d OP_InvokeChangePetName=0x4506 -OP_ChangePetName=0x5dab \ No newline at end of file +OP_ChangePetName=0x5dab diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index ae38c7bd2..3f5a6e49f 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -67,6 +67,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/repositories/guild_tributes_repository.h" #include "../common/repositories/buyer_buy_lines_repository.h" #include "../common/repositories/character_pet_name_repository.h" +#include "../common/repositories/tradeskill_recipe_entries_repository.h" #include "../common/events/player_event_logs.h" #include "../common/repositories/character_stats_record_repository.h" @@ -408,6 +409,7 @@ void MapOpcodes() ConnectedOpcodes[OP_TradeRequestAck] = &Client::Handle_OP_TradeRequestAck; ConnectedOpcodes[OP_TraderShop] = &Client::Handle_OP_TraderShop; ConnectedOpcodes[OP_TradeSkillCombine] = &Client::Handle_OP_TradeSkillCombine; + ConnectedOpcodes[OP_TradeSkillRecipeInspect] = &Client::Handle_OP_TradeSkillRecipeInspect; ConnectedOpcodes[OP_Translocate] = &Client::Handle_OP_Translocate; ConnectedOpcodes[OP_TributeItem] = &Client::Handle_OP_TributeItem; ConnectedOpcodes[OP_TributeMoney] = &Client::Handle_OP_TributeMoney; @@ -15644,6 +15646,40 @@ void Client::Handle_OP_TradeSkillCombine(const EQApplicationPacket *app) return; } +void Client::Handle_OP_TradeSkillRecipeInspect(const EQApplicationPacket* app) +{ + if (app->size != sizeof(TradeSkillRecipeInspect_Struct)) { + LogError( + "Invalid size for TradeSkillRecipeInspect_Struct: Expected: [{}] Got: [{}]", + sizeof(TradeSkillRecipeInspect_Struct), + app->size + ); + return; + } + + auto s = (TradeSkillRecipeInspect_Struct*) app->pBuffer; + + const auto& v = TradeskillRecipeEntriesRepository::GetWhere( + database, + fmt::format( + "`recipe_id` = {} AND `componentcount` = 0 AND `successcount` > 0 LIMIT 1", + s->recipe_id + ) + ); + + if (v.empty()) { + return; + } + + const uint32 item_id = v.front().item_id; + + auto inst = database.CreateItem(item_id); + if (inst) { + SendItemPacket(0, inst, ItemPacketViewLink); + safe_delete(inst); + } +} + void Client::Handle_OP_Translocate(const EQApplicationPacket *app) { if (app->size != sizeof(Translocate_Struct)) { diff --git a/zone/client_packet.h b/zone/client_packet.h index 587e14ac7..0840f5edc 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -310,6 +310,7 @@ void Handle_OP_TradeRequestAck(const EQApplicationPacket *app); void Handle_OP_TraderShop(const EQApplicationPacket *app); void Handle_OP_TradeSkillCombine(const EQApplicationPacket *app); + void Handle_OP_TradeSkillRecipeInspect(const EQApplicationPacket* app); void Handle_OP_Translocate(const EQApplicationPacket *app); void Handle_OP_TributeItem(const EQApplicationPacket *app); void Handle_OP_TributeMoney(const EQApplicationPacket *app); diff --git a/zone/lua_packet.cpp b/zone/lua_packet.cpp index 61f30e4a7..c9a20aab2 100644 --- a/zone/lua_packet.cpp +++ b/zone/lua_packet.cpp @@ -917,7 +917,8 @@ luabind::scope lua_register_packet_opcodes() { luabind::value("ClientTimeStamp", static_cast(OP_ClientTimeStamp)), luabind::value("GuildPromote", static_cast(OP_GuildPromote)), luabind::value("Fling", static_cast(OP_Fling)), - luabind::value("PickZoneWindow", static_cast(OP_PickZoneWindow)) + luabind::value("PickZoneWindow", static_cast(OP_PickZoneWindow)), + luabind::value("TradeSkillRecipeInspect", static_cast(OP_TradeSkillRecipeInspect)) )]; }