From 268879b414cbe2c7effbf06fbc7d8de5cedee56a Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Tue, 7 Feb 2023 21:42:34 -0500 Subject: [PATCH] [Quest API] Add Recipe-based methods to Perl/Lua. (#2844) * [Quest API] Add Recipe-based methods to Perl/Lua. # Perl - Add `quest::get_recipe_component_item_ids(recipe_id)`. - Add `quest::get_recipe_container_item_ids(recipe_id)`. - Add `quest::get_recipe_fail_item_ids(recipe_id)`. - Add `quest::get_recipe_salvage_item_ids(recipe_id)`. - Add `quest::get_recipe_success_item_ids(recipe_id)`. - Add `quest::get_recipe_component_count(recipe_id, item_id)`. - Add `quest::get_recipe_fail_count(recipe_id, item_id)`. - Add `quest::get_recipe_salvage_count(recipe_id, item_id)`. - Add `quest::get_recipe_success_count(recipe_id, item_id)`. # Lua - Add `eq.get_recipe_component_item_ids(recipe_id)`. - Add `eq.get_recipe_container_item_ids(recipe_id)`. - Add `eq.get_recipe_fail_item_ids(recipe_id)`. - Add `eq.get_recipe_salvage_item_ids(recipe_id)`. - Add `eq.get_recipe_success_item_ids(recipe_id)`. - Add `eq.get_recipe_component_count(recipe_id, item_id)`. - Add `eq.get_recipe_fail_count(recipe_id, item_id)`. - Add `eq.get_recipe_salvage_count(recipe_id, item_id)`. - Add `eq.get_recipe_success_count(recipe_id, item_id)`. # Notes - Before these methods, you would have to use DBI from Perl or Lua in order to get the components and their counts, these methods allow easy access to these values via the scripting API. - These should be used sparingly as they're each an individual database hit and could go crazy in a hot path. * Update eq_constants.h * Update zonedb.h * Update tradeskills.cpp * Reserve. --- common/eq_constants.h | 9 ++++ zone/embparser_api.cpp | 114 +++++++++++++++++++++++++++++++++++++++++ zone/lua_general.cpp | 107 ++++++++++++++++++++++++++++++++++++++ zone/tradeskills.cpp | 81 +++++++++++++++++++++++++++++ zone/zonedb.h | 2 + 5 files changed, 313 insertions(+) diff --git a/common/eq_constants.h b/common/eq_constants.h index 39ba461f0..2ab28bdca 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -1028,6 +1028,15 @@ enum ZoningMessage : int8 ZoneNoExperience = -7 }; +enum class RecipeCountType : uint8 +{ + Component, + Container, + Fail, + Salvage, + Success +}; + #define ALT_CURRENCY_ID_RADIANT 4 #define ALT_CURRENCY_ID_EBON 5 diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index b46a4c920..1342ddf54 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3986,6 +3986,111 @@ int8 Perl__does_augment_fit_slot(EQ::ItemInstance* inst, uint32 augment_id, uint return quest_manager.DoesAugmentFit(inst, augment_id, augment_slot); } +perl::array Perl__GetRecipeComponentItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Component, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeContainerItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Container, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeFailItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto &l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Fail, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeSalvageItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Salvage, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +perl::array Perl__GetRecipeSuccessItemIDs(uint32 recipe_id) +{ + perl::array result; + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Success, recipe_id); + + if (!l.empty()) { + result.reserve(l.size()); + + for (int i = 0; i < l.size(); i++) { + result.push_back(l[i]); + } + } + + return result; +} + +int8 Perl__GetRecipeComponentCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Component, recipe_id, item_id); +} + +int8 Perl__GetRecipeFailCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Fail, recipe_id, item_id); +} + +int8 Perl__GetRecipeSalvageCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Salvage, recipe_id, item_id); +} + +int8 Perl__GetRecipeSuccessCount(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Success, recipe_id, item_id); +} + void perl_register_quest() { perl::interpreter perl(PERL_GET_THX); @@ -4396,6 +4501,15 @@ void perl_register_quest() package.add("getgroupidbycharid", &Perl__getgroupidbycharid); package.add("getinventoryslotname", &Perl__getinventoryslotname); package.add("getraididbycharid", &Perl__getraididbycharid); + package.add("get_recipe_component_item_ids", &Perl__GetRecipeComponentItemIDs); + package.add("get_recipe_container_item_ids", &Perl__GetRecipeContainerItemIDs); + package.add("get_recipe_fail_item_ids", &Perl__GetRecipeFailItemIDs); + package.add("get_recipe_salvage_item_ids", &Perl__GetRecipeSalvageItemIDs); + package.add("get_recipe_success_item_ids", &Perl__GetRecipeSuccessItemIDs); + package.add("get_recipe_component_count", &Perl__GetRecipeComponentCount); + package.add("get_recipe_fail_count", &Perl__GetRecipeFailCount); + package.add("get_recipe_salvage_count", &Perl__GetRecipeSalvageCount); + package.add("get_recipe_success_count", &Perl__GetRecipeSuccessCount); package.add("getracename", &Perl__getracename); package.add("getremainingtimeMS", &Perl__getremainingtimeMS); package.add("getspell", &Perl__getspell); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 7d0396ff2..0b4f5b035 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -3705,6 +3705,104 @@ int8 lua_does_augment_fit_slot(Lua_ItemInst inst, uint32 augment_id, uint8 augme return quest_manager.DoesAugmentFit(inst, augment_id, augment_slot); } +luabind::object lua_get_recipe_component_item_ids(lua_State* L, uint32 recipe_id) +{ + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Component, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_container_item_ids(lua_State* L, uint32 recipe_id) +{ + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Container, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_fail_item_ids(lua_State* L, uint32 recipe_id) +{ + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Fail, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_salvage_item_ids(lua_State* L, uint32 recipe_id) { + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Salvage, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +luabind::object lua_get_recipe_success_item_ids(lua_State* L, uint32 recipe_id) { + auto lua_table = luabind::newtable(L); + + const auto& l = content_db.GetRecipeComponentItemIDs(RecipeCountType::Success, recipe_id); + if (!l.empty()) { + int index = 1; + for (const auto& i : l) { + lua_table[index] = i; + index++; + } + } + + return lua_table; +} + +int8 lua_get_recipe_component_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Component, recipe_id, item_id); +} + +int8 lua_get_recipe_fail_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Fail, recipe_id, item_id); +} + +int8 lua_get_recipe_salvage_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Salvage, recipe_id, item_id); +} + +int8 lua_get_recipe_success_count(uint32 recipe_id, uint32 item_id) +{ + return content_db.GetRecipeComponentCount(RecipeCountType::Success, recipe_id, item_id); +} + #define LuaCreateNPCParse(name, c_type, default_value) do { \ cur = table[#name]; \ if(luabind::type(cur) != LUA_TNIL) { \ @@ -4224,6 +4322,15 @@ luabind::scope lua_register_general() { luabind::def("do_augment_slots_match", &lua_do_augment_slots_match), luabind::def("does_augment_fit", (int8(*)(Lua_ItemInst, uint32))&lua_does_augment_fit), luabind::def("does_augment_fit_slot", (int8(*)(Lua_ItemInst, uint32, uint8))&lua_does_augment_fit_slot), + luabind::def("get_recipe_component_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_component_item_ids), + luabind::def("get_recipe_container_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_container_item_ids), + luabind::def("get_recipe_fail_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_fail_item_ids), + luabind::def("get_recipe_salvage_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_salvage_item_ids), + luabind::def("get_recipe_success_item_ids", (luabind::object(*)(lua_State*,uint32))&lua_get_recipe_success_item_ids), + luabind::def("get_recipe_component_count", (int8(*)(uint32,uint32))&lua_get_recipe_component_count), + luabind::def("get_recipe_fail_count", (int8(*)(uint32,uint32))&lua_get_recipe_fail_count), + luabind::def("get_recipe_salvage_count", (int8(*)(uint32,uint32))&lua_get_recipe_salvage_count), + luabind::def("get_recipe_success_count", (int8(*)(uint32,uint32))&lua_get_recipe_success_count), /* Cross Zone */ diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 69f3e5bbb..52ec95947 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -36,6 +36,7 @@ #include "../common/repositories/char_recipe_list_repository.h" #include "../common/zone_store.h" #include "../common/repositories/tradeskill_recipe_repository.h" +#include "../common/repositories/tradeskill_recipe_entries_repository.h" extern QueryServ* QServ; @@ -1634,6 +1635,86 @@ void Client::LearnRecipe(uint32 recipe_id) ); } +std::vector ZoneDatabase::GetRecipeComponentItemIDs(RecipeCountType count_type, uint32 recipe_id) +{ + std::vector l; + + const auto& tr = TradeskillRecipeRepository::FindOne(content_db, recipe_id); + if (!tr.id) { + return l; + } + + std::string c; + switch (count_type) { + case RecipeCountType::Success: + c = "successcount"; + break; + case RecipeCountType::Fail: + c = "failcount"; + break; + case RecipeCountType::Component: + c = "componentcount"; + break; + case RecipeCountType::Salvage: + c = "salvagecount"; + break; + case RecipeCountType::Container: + c = "iscontainer"; + break; + } + + const auto& tre = TradeskillRecipeEntriesRepository::GetWhere( + content_db, + fmt::format( + "recipe_id = {} AND {} >= 1 ORDER BY id ASC", + recipe_id, + c + ) + ); + if (tre.empty()) { + return l; + } + + for (const auto& e : tre) { + l.emplace_back(e.item_id); + } + + return l; +} + +int8 ZoneDatabase::GetRecipeComponentCount(RecipeCountType count_type, uint32 recipe_id, uint32 item_id) +{ + const auto& tr = TradeskillRecipeRepository::FindOne(content_db, recipe_id); + if (!tr.id) { + return -1; + } + + const auto& tre = TradeskillRecipeEntriesRepository::GetWhere( + content_db, + fmt::format( + "recipe_id = {} AND item_id = {} ORDER BY id ASC LIMIT 1", + recipe_id, + item_id + ) + ); + if (tre.empty()) { + return -1; + } + + switch (count_type) { + case RecipeCountType::Success: + return tre[0].successcount; + case RecipeCountType::Fail: + return tre[0].failcount; + case RecipeCountType::Component: + return tre[0].componentcount; + case RecipeCountType::Salvage: + return tre[0].salvagecount; + default: + return -1; + } +} + bool Client::CanIncreaseTradeskill(EQ::skills::SkillType tradeskill) { uint32 rawskill = GetRawSkill(tradeskill); uint16 maxskill = MaxSkill(tradeskill); diff --git a/zone/zonedb.h b/zone/zonedb.h index 56d67849c..2256ca90d 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -563,6 +563,8 @@ public: void UpdateRecipeMadecount(uint32 recipe_id, uint32 char_id, uint32 madecount); bool EnableRecipe(uint32 recipe_id); bool DisableRecipe(uint32 recipe_id); + std::vector GetRecipeComponentItemIDs(RecipeCountType count_type, uint32 recipe_id); + int8 GetRecipeComponentCount(RecipeCountType count_type, uint32 recipe_id, uint32 item_id); /* Tribute */ bool LoadTributes();