diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 6a426cae1..eb5a6bc4d 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -207,7 +207,6 @@ SET(repositories repositories/base/base_friends_repository.h repositories/base/base_global_loot_repository.h repositories/base/base_gm_ips_repository.h - repositories/base/base_goallists_repository.h repositories/base/base_graveyard_repository.h repositories/base/base_ground_spawns_repository.h repositories/base/base_group_id_repository.h @@ -384,7 +383,6 @@ SET(repositories repositories/friends_repository.h repositories/global_loot_repository.h repositories/gm_ips_repository.h - repositories/goallists_repository.h repositories/graveyard_repository.h repositories/ground_spawns_repository.h repositories/group_id_repository.h diff --git a/common/database_schema.h b/common/database_schema.h index a70c31251..781b46a95 100644 --- a/common/database_schema.h +++ b/common/database_schema.h @@ -197,7 +197,6 @@ namespace DatabaseSchema { "fishing", "forage", "global_loot", - "goallists", "graveyard", "grid", "grid_entries", diff --git a/common/repositories/base/base_goallists_repository.h b/common/repositories/base/base_goallists_repository.h deleted file mode 100644 index 8c098d0d7..000000000 --- a/common/repositories/base/base_goallists_repository.h +++ /dev/null @@ -1,333 +0,0 @@ -/** - * DO NOT MODIFY THIS FILE - * - * This repository was automatically generated and is NOT to be modified directly. - * Any repository modifications are meant to be made to the repository extending the base. - * Any modifications to base repositories are to be made by the generator only - * - * @generator ./utils/scripts/generators/repository-generator.pl - * @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories - */ - -#ifndef EQEMU_BASE_GOALLISTS_REPOSITORY_H -#define EQEMU_BASE_GOALLISTS_REPOSITORY_H - -#include "../../database.h" -#include "../../strings.h" -#include - -class BaseGoallistsRepository { -public: - struct Goallists { - uint32_t listid; - uint32_t entry; - }; - - static std::string PrimaryKey() - { - return std::string("listid"); - } - - static std::vector Columns() - { - return { - "listid", - "entry", - }; - } - - static std::vector SelectColumns() - { - return { - "listid", - "entry", - }; - } - - static std::string ColumnsRaw() - { - return std::string(Strings::Implode(", ", Columns())); - } - - static std::string SelectColumnsRaw() - { - return std::string(Strings::Implode(", ", SelectColumns())); - } - - static std::string TableName() - { - return std::string("goallists"); - } - - static std::string BaseSelect() - { - return fmt::format( - "SELECT {} FROM {}", - SelectColumnsRaw(), - TableName() - ); - } - - static std::string BaseInsert() - { - return fmt::format( - "INSERT INTO {} ({}) ", - TableName(), - ColumnsRaw() - ); - } - - static Goallists NewEntity() - { - Goallists e{}; - - e.listid = 0; - e.entry = 0; - - return e; - } - - static Goallists GetGoallists( - const std::vector &goallistss, - int goallists_id - ) - { - for (auto &goallists : goallistss) { - if (goallists.listid == goallists_id) { - return goallists; - } - } - - return NewEntity(); - } - - static Goallists FindOne( - Database& db, - int goallists_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE id = {} LIMIT 1", - BaseSelect(), - goallists_id - ) - ); - - auto row = results.begin(); - if (results.RowCount() == 1) { - Goallists e{}; - - e.listid = static_cast(strtoul(row[0], nullptr, 10)); - e.entry = static_cast(strtoul(row[1], nullptr, 10)); - - return e; - } - - return NewEntity(); - } - - static int DeleteOne( - Database& db, - int goallists_id - ) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {} = {}", - TableName(), - PrimaryKey(), - goallists_id - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int UpdateOne( - Database& db, - const Goallists &e - ) - { - std::vector v; - - auto columns = Columns(); - - v.push_back(columns[0] + " = " + std::to_string(e.listid)); - v.push_back(columns[1] + " = " + std::to_string(e.entry)); - - auto results = db.QueryDatabase( - fmt::format( - "UPDATE {} SET {} WHERE {} = {}", - TableName(), - Strings::Implode(", ", v), - PrimaryKey(), - e.listid - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static Goallists InsertOne( - Database& db, - Goallists e - ) - { - std::vector v; - - v.push_back(std::to_string(e.listid)); - v.push_back(std::to_string(e.entry)); - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES ({})", - BaseInsert(), - Strings::Implode(",", v) - ) - ); - - if (results.Success()) { - e.listid = results.LastInsertedID(); - return e; - } - - e = NewEntity(); - - return e; - } - - static int InsertMany( - Database& db, - const std::vector &entries - ) - { - std::vector insert_chunks; - - for (auto &e: entries) { - std::vector v; - - v.push_back(std::to_string(e.listid)); - v.push_back(std::to_string(e.entry)); - - insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); - } - - std::vector v; - - auto results = db.QueryDatabase( - fmt::format( - "{} VALUES {}", - BaseInsert(), - Strings::Implode(",", insert_chunks) - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static std::vector All(Database& db) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{}", - BaseSelect() - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Goallists e{}; - - e.listid = static_cast(strtoul(row[0], nullptr, 10)); - e.entry = static_cast(strtoul(row[1], nullptr, 10)); - - all_entries.push_back(e); - } - - return all_entries; - } - - static std::vector GetWhere(Database& db, const std::string &where_filter) - { - std::vector all_entries; - - auto results = db.QueryDatabase( - fmt::format( - "{} WHERE {}", - BaseSelect(), - where_filter - ) - ); - - all_entries.reserve(results.RowCount()); - - for (auto row = results.begin(); row != results.end(); ++row) { - Goallists e{}; - - e.listid = static_cast(strtoul(row[0], nullptr, 10)); - e.entry = static_cast(strtoul(row[1], nullptr, 10)); - - all_entries.push_back(e); - } - - return all_entries; - } - - static int DeleteWhere(Database& db, const std::string &where_filter) - { - auto results = db.QueryDatabase( - fmt::format( - "DELETE FROM {} WHERE {}", - TableName(), - where_filter - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int Truncate(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "TRUNCATE TABLE {}", - TableName() - ) - ); - - return (results.Success() ? results.RowsAffected() : 0); - } - - static int64 GetMaxId(Database& db) - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT COALESCE(MAX({}), 0) FROM {}", - PrimaryKey(), - TableName() - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } - - static int64 Count(Database& db, const std::string &where_filter = "") - { - auto results = db.QueryDatabase( - fmt::format( - "SELECT COUNT(*) FROM {} {}", - TableName(), - (where_filter.empty() ? "" : "WHERE " + where_filter) - ) - ); - - return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); - } - -}; - -#endif //EQEMU_BASE_GOALLISTS_REPOSITORY_H diff --git a/common/repositories/base/base_task_activities_repository.h b/common/repositories/base/base_task_activities_repository.h index a28063f18..e0bb196a6 100644 --- a/common/repositories/base/base_task_activities_repository.h +++ b/common/repositories/base/base_task_activities_repository.h @@ -28,11 +28,7 @@ public: uint32_t goalmethod; int32_t goalcount; std::string description_override; - uint32_t npc_id; - uint32_t npc_goal_id; std::string npc_match_list; - uint32_t item_id; - uint32_t item_goal_id; std::string item_id_list; std::string item_list; int32_t dz_switch_id; @@ -66,11 +62,7 @@ public: "goalmethod", "goalcount", "description_override", - "npc_id", - "npc_goal_id", "npc_match_list", - "item_id", - "item_goal_id", "item_id_list", "item_list", "dz_switch_id", @@ -100,11 +92,7 @@ public: "goalmethod", "goalcount", "description_override", - "npc_id", - "npc_goal_id", "npc_match_list", - "item_id", - "item_goal_id", "item_id_list", "item_list", "dz_switch_id", @@ -168,11 +156,7 @@ public: e.goalmethod = 0; e.goalcount = 1; e.description_override = ""; - e.npc_id = 0; - e.npc_goal_id = 0; e.npc_match_list = ""; - e.item_id = 0; - e.item_goal_id = 0; e.item_id_list = ""; e.item_list = ""; e.dz_switch_id = 0; @@ -231,25 +215,21 @@ public: e.goalmethod = static_cast(strtoul(row[6], nullptr, 10)); e.goalcount = static_cast(atoi(row[7])); e.description_override = row[8] ? row[8] : ""; - e.npc_id = static_cast(strtoul(row[9], nullptr, 10)); - e.npc_goal_id = static_cast(strtoul(row[10], nullptr, 10)); - e.npc_match_list = row[11] ? row[11] : ""; - e.item_id = static_cast(strtoul(row[12], nullptr, 10)); - e.item_goal_id = static_cast(strtoul(row[13], nullptr, 10)); - e.item_id_list = row[14] ? row[14] : ""; - e.item_list = row[15] ? row[15] : ""; - e.dz_switch_id = static_cast(atoi(row[16])); - e.min_x = strtof(row[17], nullptr); - e.min_y = strtof(row[18], nullptr); - e.min_z = strtof(row[19], nullptr); - e.max_x = strtof(row[20], nullptr); - e.max_y = strtof(row[21], nullptr); - e.max_z = strtof(row[22], nullptr); - e.skill_list = row[23] ? row[23] : ""; - e.spell_list = row[24] ? row[24] : ""; - e.zones = row[25] ? row[25] : ""; - e.zone_version = static_cast(atoi(row[26])); - e.optional = static_cast(atoi(row[27])); + e.npc_match_list = row[9] ? row[9] : ""; + e.item_id_list = row[10] ? row[10] : ""; + e.item_list = row[11] ? row[11] : ""; + e.dz_switch_id = static_cast(atoi(row[12])); + e.min_x = strtof(row[13], nullptr); + e.min_y = strtof(row[14], nullptr); + e.min_z = strtof(row[15], nullptr); + e.max_x = strtof(row[16], nullptr); + e.max_y = strtof(row[17], nullptr); + e.max_z = strtof(row[18], nullptr); + e.skill_list = row[19] ? row[19] : ""; + e.spell_list = row[20] ? row[20] : ""; + e.zones = row[21] ? row[21] : ""; + e.zone_version = static_cast(atoi(row[22])); + e.optional = static_cast(atoi(row[23])); return e; } @@ -292,25 +272,21 @@ public: v.push_back(columns[6] + " = " + std::to_string(e.goalmethod)); v.push_back(columns[7] + " = " + std::to_string(e.goalcount)); v.push_back(columns[8] + " = '" + Strings::Escape(e.description_override) + "'"); - v.push_back(columns[9] + " = " + std::to_string(e.npc_id)); - v.push_back(columns[10] + " = " + std::to_string(e.npc_goal_id)); - v.push_back(columns[11] + " = '" + Strings::Escape(e.npc_match_list) + "'"); - v.push_back(columns[12] + " = " + std::to_string(e.item_id)); - v.push_back(columns[13] + " = " + std::to_string(e.item_goal_id)); - v.push_back(columns[14] + " = '" + Strings::Escape(e.item_id_list) + "'"); - v.push_back(columns[15] + " = '" + Strings::Escape(e.item_list) + "'"); - v.push_back(columns[16] + " = " + std::to_string(e.dz_switch_id)); - v.push_back(columns[17] + " = " + std::to_string(e.min_x)); - v.push_back(columns[18] + " = " + std::to_string(e.min_y)); - v.push_back(columns[19] + " = " + std::to_string(e.min_z)); - v.push_back(columns[20] + " = " + std::to_string(e.max_x)); - v.push_back(columns[21] + " = " + std::to_string(e.max_y)); - v.push_back(columns[22] + " = " + std::to_string(e.max_z)); - v.push_back(columns[23] + " = '" + Strings::Escape(e.skill_list) + "'"); - v.push_back(columns[24] + " = '" + Strings::Escape(e.spell_list) + "'"); - v.push_back(columns[25] + " = '" + Strings::Escape(e.zones) + "'"); - v.push_back(columns[26] + " = " + std::to_string(e.zone_version)); - v.push_back(columns[27] + " = " + std::to_string(e.optional)); + v.push_back(columns[9] + " = '" + Strings::Escape(e.npc_match_list) + "'"); + v.push_back(columns[10] + " = '" + Strings::Escape(e.item_id_list) + "'"); + v.push_back(columns[11] + " = '" + Strings::Escape(e.item_list) + "'"); + v.push_back(columns[12] + " = " + std::to_string(e.dz_switch_id)); + v.push_back(columns[13] + " = " + std::to_string(e.min_x)); + v.push_back(columns[14] + " = " + std::to_string(e.min_y)); + v.push_back(columns[15] + " = " + std::to_string(e.min_z)); + v.push_back(columns[16] + " = " + std::to_string(e.max_x)); + v.push_back(columns[17] + " = " + std::to_string(e.max_y)); + v.push_back(columns[18] + " = " + std::to_string(e.max_z)); + v.push_back(columns[19] + " = '" + Strings::Escape(e.skill_list) + "'"); + v.push_back(columns[20] + " = '" + Strings::Escape(e.spell_list) + "'"); + v.push_back(columns[21] + " = '" + Strings::Escape(e.zones) + "'"); + v.push_back(columns[22] + " = " + std::to_string(e.zone_version)); + v.push_back(columns[23] + " = " + std::to_string(e.optional)); auto results = db.QueryDatabase( fmt::format( @@ -341,11 +317,7 @@ public: v.push_back(std::to_string(e.goalmethod)); v.push_back(std::to_string(e.goalcount)); v.push_back("'" + Strings::Escape(e.description_override) + "'"); - v.push_back(std::to_string(e.npc_id)); - v.push_back(std::to_string(e.npc_goal_id)); v.push_back("'" + Strings::Escape(e.npc_match_list) + "'"); - v.push_back(std::to_string(e.item_id)); - v.push_back(std::to_string(e.item_goal_id)); v.push_back("'" + Strings::Escape(e.item_id_list) + "'"); v.push_back("'" + Strings::Escape(e.item_list) + "'"); v.push_back(std::to_string(e.dz_switch_id)); @@ -398,11 +370,7 @@ public: v.push_back(std::to_string(e.goalmethod)); v.push_back(std::to_string(e.goalcount)); v.push_back("'" + Strings::Escape(e.description_override) + "'"); - v.push_back(std::to_string(e.npc_id)); - v.push_back(std::to_string(e.npc_goal_id)); v.push_back("'" + Strings::Escape(e.npc_match_list) + "'"); - v.push_back(std::to_string(e.item_id)); - v.push_back(std::to_string(e.item_goal_id)); v.push_back("'" + Strings::Escape(e.item_id_list) + "'"); v.push_back("'" + Strings::Escape(e.item_list) + "'"); v.push_back(std::to_string(e.dz_switch_id)); @@ -459,25 +427,21 @@ public: e.goalmethod = static_cast(strtoul(row[6], nullptr, 10)); e.goalcount = static_cast(atoi(row[7])); e.description_override = row[8] ? row[8] : ""; - e.npc_id = static_cast(strtoul(row[9], nullptr, 10)); - e.npc_goal_id = static_cast(strtoul(row[10], nullptr, 10)); - e.npc_match_list = row[11] ? row[11] : ""; - e.item_id = static_cast(strtoul(row[12], nullptr, 10)); - e.item_goal_id = static_cast(strtoul(row[13], nullptr, 10)); - e.item_id_list = row[14] ? row[14] : ""; - e.item_list = row[15] ? row[15] : ""; - e.dz_switch_id = static_cast(atoi(row[16])); - e.min_x = strtof(row[17], nullptr); - e.min_y = strtof(row[18], nullptr); - e.min_z = strtof(row[19], nullptr); - e.max_x = strtof(row[20], nullptr); - e.max_y = strtof(row[21], nullptr); - e.max_z = strtof(row[22], nullptr); - e.skill_list = row[23] ? row[23] : ""; - e.spell_list = row[24] ? row[24] : ""; - e.zones = row[25] ? row[25] : ""; - e.zone_version = static_cast(atoi(row[26])); - e.optional = static_cast(atoi(row[27])); + e.npc_match_list = row[9] ? row[9] : ""; + e.item_id_list = row[10] ? row[10] : ""; + e.item_list = row[11] ? row[11] : ""; + e.dz_switch_id = static_cast(atoi(row[12])); + e.min_x = strtof(row[13], nullptr); + e.min_y = strtof(row[14], nullptr); + e.min_z = strtof(row[15], nullptr); + e.max_x = strtof(row[16], nullptr); + e.max_y = strtof(row[17], nullptr); + e.max_z = strtof(row[18], nullptr); + e.skill_list = row[19] ? row[19] : ""; + e.spell_list = row[20] ? row[20] : ""; + e.zones = row[21] ? row[21] : ""; + e.zone_version = static_cast(atoi(row[22])); + e.optional = static_cast(atoi(row[23])); all_entries.push_back(e); } @@ -511,25 +475,21 @@ public: e.goalmethod = static_cast(strtoul(row[6], nullptr, 10)); e.goalcount = static_cast(atoi(row[7])); e.description_override = row[8] ? row[8] : ""; - e.npc_id = static_cast(strtoul(row[9], nullptr, 10)); - e.npc_goal_id = static_cast(strtoul(row[10], nullptr, 10)); - e.npc_match_list = row[11] ? row[11] : ""; - e.item_id = static_cast(strtoul(row[12], nullptr, 10)); - e.item_goal_id = static_cast(strtoul(row[13], nullptr, 10)); - e.item_id_list = row[14] ? row[14] : ""; - e.item_list = row[15] ? row[15] : ""; - e.dz_switch_id = static_cast(atoi(row[16])); - e.min_x = strtof(row[17], nullptr); - e.min_y = strtof(row[18], nullptr); - e.min_z = strtof(row[19], nullptr); - e.max_x = strtof(row[20], nullptr); - e.max_y = strtof(row[21], nullptr); - e.max_z = strtof(row[22], nullptr); - e.skill_list = row[23] ? row[23] : ""; - e.spell_list = row[24] ? row[24] : ""; - e.zones = row[25] ? row[25] : ""; - e.zone_version = static_cast(atoi(row[26])); - e.optional = static_cast(atoi(row[27])); + e.npc_match_list = row[9] ? row[9] : ""; + e.item_id_list = row[10] ? row[10] : ""; + e.item_list = row[11] ? row[11] : ""; + e.dz_switch_id = static_cast(atoi(row[12])); + e.min_x = strtof(row[13], nullptr); + e.min_y = strtof(row[14], nullptr); + e.min_z = strtof(row[15], nullptr); + e.max_x = strtof(row[16], nullptr); + e.max_y = strtof(row[17], nullptr); + e.max_z = strtof(row[18], nullptr); + e.skill_list = row[19] ? row[19] : ""; + e.spell_list = row[20] ? row[20] : ""; + e.zones = row[21] ? row[21] : ""; + e.zone_version = static_cast(atoi(row[22])); + e.optional = static_cast(atoi(row[23])); all_entries.push_back(e); } diff --git a/common/repositories/base/base_tasks_repository.h b/common/repositories/base/base_tasks_repository.h index d5b6d0dc0..de00cff57 100644 --- a/common/repositories/base/base_tasks_repository.h +++ b/common/repositories/base/base_tasks_repository.h @@ -25,15 +25,15 @@ public: int8_t duration_code; std::string title; std::string description; - std::string reward; - uint32_t rewardid; - uint32_t cashreward; - int32_t xpreward; - uint8_t rewardmethod; + std::string reward_text; + std::string reward_id_list; + uint32_t cash_reward; + int32_t exp_reward; + uint8_t reward_method; int32_t reward_points; int32_t reward_point_type; - uint8_t minlevel; - uint8_t maxlevel; + uint8_t min_level; + uint8_t max_level; uint32_t level_spread; uint32_t min_players; uint32_t max_players; @@ -63,15 +63,15 @@ public: "duration_code", "title", "description", - "reward", - "rewardid", - "cashreward", - "xpreward", - "rewardmethod", + "reward_text", + "reward_id_list", + "cash_reward", + "exp_reward", + "reward_method", "reward_points", "reward_point_type", - "minlevel", - "maxlevel", + "min_level", + "max_level", "level_spread", "min_players", "max_players", @@ -97,15 +97,15 @@ public: "duration_code", "title", "description", - "reward", - "rewardid", - "cashreward", - "xpreward", - "rewardmethod", + "reward_text", + "reward_id_list", + "cash_reward", + "exp_reward", + "reward_method", "reward_points", "reward_point_type", - "minlevel", - "maxlevel", + "min_level", + "max_level", "level_spread", "min_players", "max_players", @@ -165,15 +165,15 @@ public: e.duration_code = 0; e.title = ""; e.description = ""; - e.reward = ""; - e.rewardid = 0; - e.cashreward = 0; - e.xpreward = 0; - e.rewardmethod = 2; + e.reward_text = ""; + e.reward_id_list = ""; + e.cash_reward = 0; + e.exp_reward = 0; + e.reward_method = 0; e.reward_points = 0; e.reward_point_type = 0; - e.minlevel = 0; - e.maxlevel = 0; + e.min_level = 0; + e.max_level = 0; e.level_spread = 0; e.min_players = 0; e.max_players = 0; @@ -228,15 +228,15 @@ public: e.duration_code = static_cast(atoi(row[3])); e.title = row[4] ? row[4] : ""; e.description = row[5] ? row[5] : ""; - e.reward = row[6] ? row[6] : ""; - e.rewardid = static_cast(strtoul(row[7], nullptr, 10)); - e.cashreward = static_cast(strtoul(row[8], nullptr, 10)); - e.xpreward = static_cast(atoi(row[9])); - e.rewardmethod = static_cast(strtoul(row[10], nullptr, 10)); + e.reward_text = row[6] ? row[6] : ""; + e.reward_id_list = row[7] ? row[7] : ""; + e.cash_reward = static_cast(strtoul(row[8], nullptr, 10)); + e.exp_reward = static_cast(atoi(row[9])); + e.reward_method = static_cast(strtoul(row[10], nullptr, 10)); e.reward_points = static_cast(atoi(row[11])); e.reward_point_type = static_cast(atoi(row[12])); - e.minlevel = static_cast(strtoul(row[13], nullptr, 10)); - e.maxlevel = static_cast(strtoul(row[14], nullptr, 10)); + e.min_level = static_cast(strtoul(row[13], nullptr, 10)); + e.max_level = static_cast(strtoul(row[14], nullptr, 10)); e.level_spread = static_cast(strtoul(row[15], nullptr, 10)); e.min_players = static_cast(strtoul(row[16], nullptr, 10)); e.max_players = static_cast(strtoul(row[17], nullptr, 10)); @@ -289,15 +289,15 @@ public: v.push_back(columns[3] + " = " + std::to_string(e.duration_code)); v.push_back(columns[4] + " = '" + Strings::Escape(e.title) + "'"); v.push_back(columns[5] + " = '" + Strings::Escape(e.description) + "'"); - v.push_back(columns[6] + " = '" + Strings::Escape(e.reward) + "'"); - v.push_back(columns[7] + " = " + std::to_string(e.rewardid)); - v.push_back(columns[8] + " = " + std::to_string(e.cashreward)); - v.push_back(columns[9] + " = " + std::to_string(e.xpreward)); - v.push_back(columns[10] + " = " + std::to_string(e.rewardmethod)); + v.push_back(columns[6] + " = '" + Strings::Escape(e.reward_text) + "'"); + v.push_back(columns[7] + " = '" + Strings::Escape(e.reward_id_list) + "'"); + v.push_back(columns[8] + " = " + std::to_string(e.cash_reward)); + v.push_back(columns[9] + " = " + std::to_string(e.exp_reward)); + v.push_back(columns[10] + " = " + std::to_string(e.reward_method)); v.push_back(columns[11] + " = " + std::to_string(e.reward_points)); v.push_back(columns[12] + " = " + std::to_string(e.reward_point_type)); - v.push_back(columns[13] + " = " + std::to_string(e.minlevel)); - v.push_back(columns[14] + " = " + std::to_string(e.maxlevel)); + v.push_back(columns[13] + " = " + std::to_string(e.min_level)); + v.push_back(columns[14] + " = " + std::to_string(e.max_level)); v.push_back(columns[15] + " = " + std::to_string(e.level_spread)); v.push_back(columns[16] + " = " + std::to_string(e.min_players)); v.push_back(columns[17] + " = " + std::to_string(e.max_players)); @@ -338,15 +338,15 @@ public: v.push_back(std::to_string(e.duration_code)); v.push_back("'" + Strings::Escape(e.title) + "'"); v.push_back("'" + Strings::Escape(e.description) + "'"); - v.push_back("'" + Strings::Escape(e.reward) + "'"); - v.push_back(std::to_string(e.rewardid)); - v.push_back(std::to_string(e.cashreward)); - v.push_back(std::to_string(e.xpreward)); - v.push_back(std::to_string(e.rewardmethod)); + v.push_back("'" + Strings::Escape(e.reward_text) + "'"); + v.push_back("'" + Strings::Escape(e.reward_id_list) + "'"); + v.push_back(std::to_string(e.cash_reward)); + v.push_back(std::to_string(e.exp_reward)); + v.push_back(std::to_string(e.reward_method)); v.push_back(std::to_string(e.reward_points)); v.push_back(std::to_string(e.reward_point_type)); - v.push_back(std::to_string(e.minlevel)); - v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); v.push_back(std::to_string(e.level_spread)); v.push_back(std::to_string(e.min_players)); v.push_back(std::to_string(e.max_players)); @@ -395,15 +395,15 @@ public: v.push_back(std::to_string(e.duration_code)); v.push_back("'" + Strings::Escape(e.title) + "'"); v.push_back("'" + Strings::Escape(e.description) + "'"); - v.push_back("'" + Strings::Escape(e.reward) + "'"); - v.push_back(std::to_string(e.rewardid)); - v.push_back(std::to_string(e.cashreward)); - v.push_back(std::to_string(e.xpreward)); - v.push_back(std::to_string(e.rewardmethod)); + v.push_back("'" + Strings::Escape(e.reward_text) + "'"); + v.push_back("'" + Strings::Escape(e.reward_id_list) + "'"); + v.push_back(std::to_string(e.cash_reward)); + v.push_back(std::to_string(e.exp_reward)); + v.push_back(std::to_string(e.reward_method)); v.push_back(std::to_string(e.reward_points)); v.push_back(std::to_string(e.reward_point_type)); - v.push_back(std::to_string(e.minlevel)); - v.push_back(std::to_string(e.maxlevel)); + v.push_back(std::to_string(e.min_level)); + v.push_back(std::to_string(e.max_level)); v.push_back(std::to_string(e.level_spread)); v.push_back(std::to_string(e.min_players)); v.push_back(std::to_string(e.max_players)); @@ -456,15 +456,15 @@ public: e.duration_code = static_cast(atoi(row[3])); e.title = row[4] ? row[4] : ""; e.description = row[5] ? row[5] : ""; - e.reward = row[6] ? row[6] : ""; - e.rewardid = static_cast(strtoul(row[7], nullptr, 10)); - e.cashreward = static_cast(strtoul(row[8], nullptr, 10)); - e.xpreward = static_cast(atoi(row[9])); - e.rewardmethod = static_cast(strtoul(row[10], nullptr, 10)); + e.reward_text = row[6] ? row[6] : ""; + e.reward_id_list = row[7] ? row[7] : ""; + e.cash_reward = static_cast(strtoul(row[8], nullptr, 10)); + e.exp_reward = static_cast(atoi(row[9])); + e.reward_method = static_cast(strtoul(row[10], nullptr, 10)); e.reward_points = static_cast(atoi(row[11])); e.reward_point_type = static_cast(atoi(row[12])); - e.minlevel = static_cast(strtoul(row[13], nullptr, 10)); - e.maxlevel = static_cast(strtoul(row[14], nullptr, 10)); + e.min_level = static_cast(strtoul(row[13], nullptr, 10)); + e.max_level = static_cast(strtoul(row[14], nullptr, 10)); e.level_spread = static_cast(strtoul(row[15], nullptr, 10)); e.min_players = static_cast(strtoul(row[16], nullptr, 10)); e.max_players = static_cast(strtoul(row[17], nullptr, 10)); @@ -508,15 +508,15 @@ public: e.duration_code = static_cast(atoi(row[3])); e.title = row[4] ? row[4] : ""; e.description = row[5] ? row[5] : ""; - e.reward = row[6] ? row[6] : ""; - e.rewardid = static_cast(strtoul(row[7], nullptr, 10)); - e.cashreward = static_cast(strtoul(row[8], nullptr, 10)); - e.xpreward = static_cast(atoi(row[9])); - e.rewardmethod = static_cast(strtoul(row[10], nullptr, 10)); + e.reward_text = row[6] ? row[6] : ""; + e.reward_id_list = row[7] ? row[7] : ""; + e.cash_reward = static_cast(strtoul(row[8], nullptr, 10)); + e.exp_reward = static_cast(atoi(row[9])); + e.reward_method = static_cast(strtoul(row[10], nullptr, 10)); e.reward_points = static_cast(atoi(row[11])); e.reward_point_type = static_cast(atoi(row[12])); - e.minlevel = static_cast(strtoul(row[13], nullptr, 10)); - e.maxlevel = static_cast(strtoul(row[14], nullptr, 10)); + e.min_level = static_cast(strtoul(row[13], nullptr, 10)); + e.max_level = static_cast(strtoul(row[14], nullptr, 10)); e.level_spread = static_cast(strtoul(row[15], nullptr, 10)); e.min_players = static_cast(strtoul(row[16], nullptr, 10)); e.max_players = static_cast(strtoul(row[17], nullptr, 10)); diff --git a/common/repositories/goallists_repository.h b/common/repositories/goallists_repository.h deleted file mode 100644 index a38f5727a..000000000 --- a/common/repositories/goallists_repository.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef EQEMU_GOALLISTS_REPOSITORY_H -#define EQEMU_GOALLISTS_REPOSITORY_H - -#include "../database.h" -#include "../strings.h" -#include "base/base_goallists_repository.h" - -class GoallistsRepository: public BaseGoallistsRepository { -public: - - /** - * This file was auto generated and can be modified and extended upon - * - * Base repository methods are automatically - * generated in the "base" version of this repository. The base repository - * is immutable and to be left untouched, while methods in this class - * are used as extension methods for more specific persistence-layer - * accessors or mutators. - * - * Base Methods (Subject to be expanded upon in time) - * - * Note: Not all tables are designed appropriately to fit functionality with all base methods - * - * InsertOne - * UpdateOne - * DeleteOne - * FindOne - * GetWhere(std::string where_filter) - * DeleteWhere(std::string where_filter) - * InsertMany - * All - * - * Example custom methods in a repository - * - * GoallistsRepository::GetByZoneAndVersion(int zone_id, int zone_version) - * GoallistsRepository::GetWhereNeverExpires() - * GoallistsRepository::GetWhereXAndY() - * GoallistsRepository::DeleteWhereXAndY() - * - * Most of the above could be covered by base methods, but if you as a developer - * find yourself re-using logic for other parts of the code, its best to just make a - * method that can be re-used easily elsewhere especially if it can use a base repository - * method and encapsulate filters there - */ - - // Custom extended repository methods here - -}; - -#endif //EQEMU_GOALLISTS_REPOSITORY_H diff --git a/common/strings.cpp b/common/strings.cpp index 5e288e722..fbec8d985 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -64,7 +64,7 @@ std::vector Strings::Split(const std::string &str, const char delim } // this one takes delimiter length into consideration -std::vector Strings::Split(std::string s, std::string delimiter) +std::vector Strings::Split(const std::string& s, const std::string& delimiter) { size_t pos_start = 0, pos_end, delim_len = delimiter.length(); std::string token; @@ -674,3 +674,7 @@ std::string Strings::ConvertToDigit(int n, std::string suffix) return NUM_TO_ENGLISH_X[n] + suffix; } } +bool Strings::Contains(const std::string& subject, const std::string& search) +{ + return subject.find(search) != std::string::npos; +} diff --git a/common/strings.h b/common/strings.h index 471f02e32..ce4ad7f37 100644 --- a/common/strings.h +++ b/common/strings.h @@ -84,6 +84,7 @@ namespace EQ { class Strings { public: static bool Contains(std::vector container, std::string element); + static bool Contains(const std::string& subject, const std::string& search); static bool IsNumber(const std::string &s); static const std::string ToLower(std::string s); static const std::string ToUpper(std::string s); @@ -105,7 +106,7 @@ public: static std::string SecondsToTime(int duration, bool is_milliseconds = false); static std::string::size_type SearchDelim(const std::string &haystack, const std::string &needle, const char deliminator = ','); static std::vector Split(const std::string &s, const char delim = ','); - static std::vector Split(std::string s, std::string delimiter); + static std::vector Split(const std::string& s, const std::string& delimiter); static std::vector Wrap(std::vector &src, std::string character); static void FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string); diff --git a/common/tasks.h b/common/tasks.h index 991214349..e88d0603d 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -1,6 +1,7 @@ #ifndef EQEMU_TASKS_H #define EQEMU_TASKS_H +#include "../common/strings.h" #include "serialize_buffer.h" #include #include @@ -16,12 +17,10 @@ // Command Codes for worldserver ServerOP_ReloadTasks #define RELOADTASKS 0 -#define RELOADTASKGOALLISTS 1 #define RELOADTASKSETS 2 typedef enum { METHODSINGLEID = 0, - METHODLIST = 1, METHODQUEST = 2 } TaskMethodType; @@ -77,11 +76,7 @@ struct ActivityInformation { int spell_id; // older clients, first id from above TaskMethodType goal_method; int goal_count; - uint32_t npc_id; - uint32_t npc_goal_id; std::string npc_match_list; // delimited by '|' for partial name matches but also supports ids - uint32_t item_id; - uint32_t item_goal_id; std::string item_id_list; // delimited by '|' to support multiple item ids int dz_switch_id; float min_x; @@ -207,15 +202,15 @@ enum class DurationCode { struct TaskInformation { TaskType type; - int duration{}; + uint32_t duration{}; DurationCode duration_code; // description for time investment for when duration == 0 std::string title{}; // max length 64 std::string description{}; // max length 4000, 2048 on Tit std::string reward{}; std::string item_link{}; // max length 128 older clients, item link gets own string std::string completion_emote{}; // emote after completing task, yellow. Maybe should make more generic ... but yellow for now! - int reward_id{}; - int cash_reward{}; // Expressed in copper + std::string reward_id_list{}; + uint32_t cash_reward{}; // Expressed in copper int experience_reward{}; int faction_reward{}; // npc_faction_id if amount == 0, otherwise primary faction ID int faction_amount{}; // faction hit value @@ -225,14 +220,14 @@ struct TaskInformation { int activity_count{}; uint8_t min_level{}; uint8_t max_level{}; - int level_spread; - int min_players; - int max_players; + uint32_t level_spread; + uint32_t min_players; + uint32_t max_players; bool repeatable{}; - int replay_timer_group; - int replay_timer_seconds; - int request_timer_group; - int request_timer_seconds; + uint32_t replay_timer_group; + uint32_t replay_timer_seconds; + uint32_t request_timer_group; + uint32_t request_timer_seconds; ActivityInformation activity_information[MAXACTIVITIESPERTASK]; void SerializeSelector(SerializeBuffer& out, EQ::versions::ClientVersion client_version) const @@ -420,6 +415,31 @@ namespace Tasks { return result; } + + static bool IsInMatchList(const std::string& match_list, const std::string& entry) + { + for (auto &s: Strings::Split(match_list, '|')) { + if (s == entry) { + return true; + } + } + + return false; + } + + static bool IsInMatchListPartial(const std::string &match_list, const std::string &entry) + { + std::string entry_match = Strings::ToLower(entry); + for (auto &s: Strings::Split(match_list, '|')) { + if (entry_match.find(Strings::ToLower(s)) != std::string::npos) { + return true; + } + } + + return false; + } + + } namespace TaskStr { diff --git a/common/version.h b/common/version.h index fe1424612..10feef34f 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9207 +#define CURRENT_BINARY_DATABASE_VERSION 9208 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9029 diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 5ac089d9d..646b79977 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -461,6 +461,7 @@ 9205|2022_09_03_fix_starting_point_heading.sql|SELECT * FROM db_version WHERE version >= 9205|empty| 9206|2022_09_03_fix_door_destination_headings.sql|SELECT * FROM db_version WHERE version >= 9206|empty| 9207|2022_09_03_fix_zone_point_heading_data.sql|SELECT * FROM db_version WHERE version >= 9207|empty| +9208|2022_09_25_task_concat_matchlists.sql|SHOW COLUMNS FROM `task_activities` LIKE 'npc_id'|not_empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql b/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql new file mode 100644 index 000000000..84b712f48 --- /dev/null +++ b/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql @@ -0,0 +1,69 @@ +SET SESSION group_concat_max_len = 1048576; + +-- backup original(s) +CREATE TABLE `goallists_backup_9_25_2022` LIKE `goallists`; +INSERT INTO `goallists_backup_9_25_2022` SELECT * FROM `goallists`; +CREATE TABLE `tasks_backup_9_25_2022` LIKE `tasks`; +INSERT INTO `tasks_backup_9_25_2022` SELECT * FROM `tasks`; + +-- npc id +UPDATE `task_activities` +SET `task_activities`.`npc_match_list` = CONCAT_WS('|', `npc_match_list`, `npc_id`) +WHERE npc_id != 0; + +-- npc_goal_id goallists +UPDATE `task_activities` +INNER JOIN +( + SELECT `goallists`.`listid`, GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids` + FROM `goallists` + GROUP BY `goallists`.`listid` +) AS `goallist_group` + ON `task_activities`.`npc_goal_id` = `goallist_group`.`listid` +SET `task_activities`.`npc_match_list` = CONCAT_WS('|', `npc_match_list`, `goallist_ids`) +WHERE npc_goal_id != 0; + +-- item id +UPDATE `task_activities` +SET `task_activities`.`item_id_list` = CONCAT_WS('|', `item_id_list`, `item_id`) +WHERE item_id != 0; + +-- item_goal_id goallists +UPDATE `task_activities` +INNER JOIN +( + SELECT `goallists`.`listid`, GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids` + FROM `goallists` + GROUP BY `goallists`.`listid` +) AS `goallist_group` + ON `task_activities`.`item_goal_id` = `goallist_group`.`listid` +SET `task_activities`.`item_id_list` = CONCAT_WS('|', `item_id_list`, `goallist_ids`) +WHERE item_goal_id != 0; + +ALTER TABLE `task_activities` + DROP COLUMN `npc_id`, + DROP COLUMN `npc_goal_id`, + DROP COLUMN `item_id`, + DROP COLUMN `item_goal_id`; + + +-- Reward cleanup and task table cleanup + +ALTER TABLE `tasks` + CHANGE COLUMN `reward` `reward_text` varchar(64) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `description`, + CHANGE COLUMN `rewardid` `reward_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL AFTER `reward_text`, + CHANGE COLUMN `cashreward` `cash_reward` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `reward_id_list`, + CHANGE COLUMN `rewardmethod` `reward_method` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `xpreward`, + CHANGE COLUMN `minlevel` `min_level` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `reward_point_type`, + CHANGE COLUMN `maxlevel` `max_level` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `min_level`; + +ALTER Table `tasks` CHANGE COLUMN `xpreward` `exp_reward` int(10) NOT NULL DEFAULT 0 AFTER `cash_reward`; + +UPDATE tasks SET reward_id_list = + ( + SELECT GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids` FROM `goallists` WHERE listid = reward_id_list) +WHERE +reward_method = 1; + +-- deprecated table +DROP table goallists; diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index afe3582d7..48095c82b 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -1287,13 +1287,13 @@ bool SharedTaskManager::CanRequestSharedTask(uint32_t task_id, const SharedTaskR } // check if any party member's minimum level is too low (pre-2014 this was average level) - if (task.minlevel > 0 && request.lowest_level < task.minlevel) { + if (task.min_level > 0 && request.lowest_level < task.min_level) { client_list.SendCharacterMessage(request.leader_id, Chat::Red, TaskStr::Get(TaskStr::LVL_TOO_LOW)); return false; } // check if any party member's maximum level is too high (pre-2014 this was average level) - if (task.maxlevel > 0 && request.highest_level > task.maxlevel) { + if (task.max_level > 0 && request.highest_level > task.max_level) { client_list.SendCharacterMessage(request.leader_id, Chat::Red, TaskStr::Get(TaskStr::LVL_TOO_HIGH)); return false; } @@ -1472,13 +1472,13 @@ bool SharedTaskManager::CanAddPlayer(SharedTask *s, uint32_t character_id, std:: } // check if player is below minimum level of task (pre-2014 this was average level) - if (s->GetTaskData().minlevel > 0 && cle->level() < s->GetTaskData().minlevel) { + if (s->GetTaskData().min_level > 0 && cle->level() < s->GetTaskData().min_level) { SendLeaderMessage(s, Chat::Red, TaskStr::Get(TaskStr::CANT_ADD_MIN_LEVEL)); allow_invite = false; } // check if player is above maximum level of task (pre-2014 this was average level) - if (s->GetTaskData().maxlevel > 0 && cle->level() > s->GetTaskData().maxlevel) { + if (s->GetTaskData().max_level > 0 && cle->level() > s->GetTaskData().max_level) { SendLeaderMessage(s, Chat::Red, TaskStr::Get(TaskStr::CANT_ADD_MAX_LEVEL)); allow_invite = false; } diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 8e0c9b591..502006c58 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -140,7 +140,6 @@ SET(zone_sources spell_effects.cpp spells.cpp task_client_state.cpp - task_goal_list_manager.cpp task_manager.cpp tasks.cpp titles.cpp @@ -265,7 +264,6 @@ SET(zone_headers spawngroup.h string_ids.h task_client_state.h - task_goal_list_manager.h task_manager.h tasks.h titles.h diff --git a/zone/gm_commands/findtask.cpp b/zone/gm_commands/findtask.cpp index 15c66b800..a643b28a3 100755 --- a/zone/gm_commands/findtask.cpp +++ b/zone/gm_commands/findtask.cpp @@ -13,30 +13,31 @@ void command_findtask(Client *c, const Seperator *sep) if (sep->IsNumber(1)) { auto task_id = std::stoul(sep->arg[1]); auto task_name = task_manager->GetTaskName(task_id); - auto task_message = ( + + std::string task_message = ( !task_name.empty() ? fmt::format( "Task {}: {}", task_id, task_name - ).c_str() : + ) : fmt::format( "Task ID {} was not found.", task_id - ).c_str() + ) ); c->Message( Chat::White, - task_message + task_message.c_str() ); } else { std::string search_criteria = Strings::ToLower(sep->argplus[1]); if (!search_criteria.empty()) { - int found_count = 0; - for (const auto& task : task_manager->GetTaskData()) { - auto task_name = task.second.title; + int found_count = 0; + for (const auto &task: task_manager->GetTaskData()) { + auto task_name = task.second.title; std::string task_name_lower = Strings::ToLower(task_name); if (task_name_lower.find(search_criteria) == std::string::npos) { continue; diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index cc436939b..6ae2c7d69 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -191,12 +191,7 @@ void command_task(Client *c, const Seperator *sep) return; } else if (is_reload) { if (arguments >= 2) { - if (!strcasecmp(sep->arg[2], "lists")) { - c->Message(Chat::Yellow, "Attempting to reload goal lists."); - worldserver.SendReloadTasks(RELOADTASKGOALLISTS); - c->Message(Chat::Yellow, "Successfully reloaded goal lists."); - return; - } else if (!strcasecmp(sep->arg[2], "sets")) { + if (!strcasecmp(sep->arg[2], "sets")) { c->Message(Chat::Yellow, "Attempting to reload task sets."); worldserver.SendReloadTasks(RELOADTASKSETS); c->Message(Chat::Yellow, "Successfully reloaded task sets."); diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 362e1f542..039d582f2 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -492,19 +492,6 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter, return false; } - // item is only checked for updates that provide an item (unlike npc which may be null for non-npcs) - if (activity.item_id != 0 && filter.item_id != 0 && activity.item_id != filter.item_id) - { - LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed item id filter", client->GetName(), task_id, client_activity.activity_id); - return false; - } - - if (activity.npc_id != 0 && (!filter.npc || activity.npc_id != filter.npc->GetNPCTypeID())) - { - LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed npc id filter", client->GetName(), task_id, client_activity.activity_id); - return false; - } - if (!activity.CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed zone filter", client->GetName(), task_id, client_activity.activity_id); @@ -523,32 +510,19 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter, } } - if (activity.item_goal_id != 0 && filter.item_id != 0 && - !task_manager->m_goal_list_manager.IsInList(activity.item_goal_id, filter.item_id)) - { - LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed item goallist filter", client->GetName(), task_id, client_activity.activity_id); - return false; - } - + // item is only checked for updates that provide an item to check (unlike npc which may be null for non-npcs) if (!activity.item_id_list.empty() && filter.item_id != 0 && - !TaskGoalListManager::IsInMatchList(activity.item_id_list, std::to_string(filter.item_id))) + !Tasks::IsInMatchList(activity.item_id_list, std::to_string(filter.item_id))) { LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed item match filter", client->GetName(), task_id, client_activity.activity_id); return false; } - if (activity.npc_goal_id != 0 && (!filter.npc || - !task_manager->m_goal_list_manager.IsInList(activity.npc_goal_id, filter.npc->GetNPCTypeID()))) - { - LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed npc goallist filter", client->GetName(), task_id, client_activity.activity_id); - return false; - } - // npc filter supports both npc names and ids in match lists if (!activity.npc_match_list.empty() && (!filter.npc || - (!TaskGoalListManager::IsInMatchListPartial(activity.npc_match_list, filter.npc->GetName()) && - !TaskGoalListManager::IsInMatchListPartial(activity.npc_match_list, filter.npc->GetCleanName()) && - !TaskGoalListManager::IsInMatchList(activity.npc_match_list, std::to_string(filter.npc->GetNPCTypeID()))))) + (!Tasks::IsInMatchListPartial(activity.npc_match_list, filter.npc->GetName()) && + !Tasks::IsInMatchListPartial(activity.npc_match_list, filter.npc->GetCleanName()) && + !Tasks::IsInMatchList(activity.npc_match_list, std::to_string(filter.npc->GetNPCTypeID()))))) { LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed npc match filter", client->GetName(), task_id, client_activity.activity_id); return false; @@ -985,76 +959,68 @@ void ClientTaskState::DispatchEventTaskComplete(Client* client, ClientTaskInform parse->EventPlayer(EVENT_TASK_COMPLETE, client, export_string, 0); } -void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_information, ClientTaskInformation& client_task) +void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTaskInformation& client_task) { - - if (!task_information || !client || client_task.was_rewarded) { + if (!ti || !c || client_task.was_rewarded) { return; } client_task.was_rewarded = true; client_task.updated = true; - if (!task_information->completion_emote.empty()) { - client->Message(Chat::Yellow, task_information->completion_emote.c_str()); + if (!ti->completion_emote.empty()) { + c->Message(Chat::Yellow, ti->completion_emote.c_str()); } // TODO: this function should sometimes use QuestReward_Struct and CashReward_Struct // assumption is they use QuestReward_Struct when there is more than 1 thing getting rewarded - - const EQ::ItemData *item_data; - std::vector reward_list; - - switch (task_information->reward_method) { - case METHODSINGLEID: { - if (task_information->reward_id) { - int16_t slot = client->GetInv().FindFreeSlot(false, true); - client->SummonItem(task_information->reward_id, -1, 0, 0, 0, 0, 0, 0, false, slot); - item_data = database.GetItem(task_information->reward_id); - if (item_data) { - client->MessageString(Chat::Yellow, YOU_HAVE_BEEN_GIVEN, item_data->Name); + if (ti->reward_method != METHODQUEST) { + for (const auto &i: Strings::Split(ti->reward_id_list, "|")) { + // handle charges + int16 charges = -1; + uint32 item_id = Strings::IsNumber(i) ? std::stoi(i) : 0; + if (Strings::Contains(i, ",")) { + auto s = Strings::Split(i, ","); + if (!s.empty() && s.size() == 2) { + item_id = Strings::IsNumber(s[0]) ? std::stoi(s[0]) : 0; + charges = Strings::IsNumber(s[1]) ? std::stoi(s[1]) : 0; } } - break; - } - case METHODLIST: { - reward_list = task_manager->m_goal_list_manager.GetListContents(task_information->reward_id); - for (int item_id : reward_list) { - int16_t slot = client->GetInv().FindFreeSlot(false, true); - client->SummonItem(item_id, -1, 0, 0, 0, 0, 0, 0, false, slot); - item_data = database.GetItem(item_id); - if (item_data) { - client->MessageString(Chat::Yellow, YOU_HAVE_BEEN_GIVEN, item_data->Name); + + if (item_id > 0) { + std::unique_ptr inst(database.CreateItem(item_id, charges)); + if (inst && inst->GetItem()) { + bool stacked = c->TryStacking(inst.get()); + if (!stacked) { + int16_t slot = c->GetInv().FindFreeSlot(inst->IsClassBag(), true, inst->GetItem()->Size); + c->SummonItem(item_id, charges, 0, 0, 0, 0, 0, 0, false, slot); + } + c->MessageString(Chat::Yellow, YOU_HAVE_BEEN_GIVEN, inst->GetItem()->Name); } } - break; - } - default: { - // Nothing special done for METHODQUEST - break; } } // just use normal NPC faction ID stuff - if (task_information->faction_reward && task_information->faction_amount == 0) { - client->SetFactionLevel( - client->CharacterID(), - task_information->faction_reward, - client->GetBaseClass(), - client->GetBaseRace(), - client->GetDeity() + if (ti->faction_reward && ti->faction_amount == 0) { + c->SetFactionLevel( + c->CharacterID(), + ti->faction_reward, + c->GetBaseClass(), + c->GetBaseRace(), + c->GetDeity() ); - } else if (task_information->faction_reward != 0 && task_information->faction_amount != 0) { - client->RewardFaction( - task_information->faction_reward, - task_information->faction_amount + } else if (ti->faction_reward != 0 && ti->faction_amount != 0) { + c->RewardFaction( + ti->faction_reward, + ti->faction_amount ); } - if (task_information->cash_reward) { + if (ti->cash_reward) { int platinum, gold, silver, copper; - copper = task_information->cash_reward; + copper = ti->cash_reward; platinum = copper / 1000; copper = copper - (platinum * 1000); @@ -1063,11 +1029,11 @@ void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_inf silver = copper / 10; copper = copper - (silver * 10); - client->CashReward(copper, silver, gold, platinum); + c->CashReward(copper, silver, gold, platinum); } - int32 experience_reward = task_information->experience_reward; + int32 experience_reward = ti->experience_reward; if (experience_reward > 0) { - client->AddEXP(experience_reward); + c->AddEXP(experience_reward); } if (experience_reward < 0) { uint32 pos_reward = experience_reward * -1; @@ -1075,19 +1041,19 @@ void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_inf if (pos_reward > 100 && pos_reward < 25700) { uint8 max_level = pos_reward / 100; uint8 exp_percent = pos_reward - (max_level * 100); - client->AddLevelBasedExp(exp_percent, max_level); + c->AddLevelBasedExp(exp_percent, max_level); } } - if (task_information->reward_points > 0) + if (ti->reward_points > 0) { - if (task_information->reward_point_type == AltCurrencyType::RadiantCrystal) + if (ti->reward_point_type == AltCurrencyType::RadiantCrystal) { - client->AddCrystals(task_information->reward_points, 0); + c->AddCrystals(ti->reward_points, 0); } - else if (task_information->reward_point_type == AltCurrencyType::EbonCrystal) + else if (ti->reward_point_type == AltCurrencyType::EbonCrystal) { - client->AddCrystals(0, task_information->reward_points); + c->AddCrystals(0, ti->reward_points); } } } diff --git a/zone/task_client_state.h b/zone/task_client_state.h index 374c233eb..7937abe55 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -65,7 +65,7 @@ public: bool TaskOutOfTime(TaskType task_type, int index); void TaskPeriodicChecks(Client *client); void SendTaskHistory(Client *client, int task_index); - void RewardTask(Client* client, const TaskInformation* task_information, ClientTaskInformation& client_task); + void RewardTask(Client* c, const TaskInformation* ti, ClientTaskInformation& client_task); void EnableTask(int character_id, int task_count, int *task_list); void DisableTask(int character_id, int task_count, int *task_list); bool IsTaskEnabled(int task_id); diff --git a/zone/task_goal_list_manager.cpp b/zone/task_goal_list_manager.cpp deleted file mode 100644 index 24c90ac27..000000000 --- a/zone/task_goal_list_manager.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "../common/global_define.h" -#include "../common/misc_functions.h" -#include "../common/repositories/goallists_repository.h" -#include "../common/rulesys.h" -#include "client.h" -#include "mob.h" -#include "quest_parser_collection.h" -#include "task_goal_list_manager.h" -#include "tasks.h" -#include "zonedb.h" - -TaskGoalListManager::TaskGoalListManager() -{ - m_goal_lists_count = 0; -} - -TaskGoalListManager::~TaskGoalListManager() {} - -bool TaskGoalListManager::LoadLists() -{ - m_task_goal_lists.clear(); - m_goal_lists_count = 0; - - std::string query = "SELECT `listid`, COUNT(`entry`) FROM `goallists` GROUP by `listid` ORDER BY `listid`"; - auto results = content_db.QueryDatabase(query); - if (!results.Success()) { - return false; - } - - m_goal_lists_count = results.RowCount(); - LogTasks("Loaded [{}] GoalLists", m_goal_lists_count); - - m_task_goal_lists.reserve(m_goal_lists_count); - - int list_index = 0; - for (auto row = results.begin(); row != results.end(); ++row) { - int list_id = atoi(row[0]); - int list_size = atoi(row[1]); - - m_task_goal_lists.push_back({list_id, 0, 0}); - - m_task_goal_lists[list_index].GoalItemEntries.reserve(list_size); - - list_index++; - } - - auto goal_lists = GoallistsRepository::GetWhere(content_db, "TRUE ORDER BY listid, entry ASC"); - for (list_index = 0; list_index < m_goal_lists_count; list_index++) { - - int list_id = m_task_goal_lists[list_index].ListID; - - for (auto &entry: goal_lists) { - if (entry.listid == list_id) { - if (entry.entry < m_task_goal_lists[list_index].Min) { - m_task_goal_lists[list_index].Min = entry.entry; - } - - if (entry.entry > m_task_goal_lists[list_index].Max) { - m_task_goal_lists[list_index].Max = entry.entry; - } - - m_task_goal_lists[list_index].GoalItemEntries.push_back(entry.entry); - - LogTasksDetail( - "Goal list index [{}] loading list [{}] entry [{}]", - list_index, - list_id, - entry.entry - ); - } - } - } - - return true; - -} - -int TaskGoalListManager::GetListByID(int list_id) -{ - - // Find the list with the specified ListID and return the index - auto it = std::find_if( - m_task_goal_lists.begin(), - m_task_goal_lists.end(), - [list_id](const TaskGoalList_Struct &t) { return t.ListID == list_id; } - ); - - if (it == m_task_goal_lists.end()) { - return -1; - } - - return std::distance(m_task_goal_lists.begin(), it); -} - -int TaskGoalListManager::GetFirstEntry(int list_id) -{ - int list_by_id = GetListByID(list_id); - - if ((list_by_id < 0) || (list_by_id >= m_goal_lists_count)) { - return -1; - } - - if (m_task_goal_lists[list_by_id].GoalItemEntries.empty()) { - return -1; - } - - return m_task_goal_lists[list_by_id].GoalItemEntries[0]; -} - -std::vector TaskGoalListManager::GetListContents(int list_index) -{ - std::vector list_contents; - int list_by_id = GetListByID(list_index); - - if ((list_by_id < 0) || (list_by_id >= m_goal_lists_count)) { - return list_contents; - } - - list_contents = m_task_goal_lists[list_by_id].GoalItemEntries; - - return list_contents; -} - -bool TaskGoalListManager::IsInList(int list_id, int entry) -{ - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i)", list_id, entry); - - int list_index = GetListByID(list_id); - - if ((list_index < 0) || (list_index >= m_goal_lists_count)) { - return false; - } - - if ((entry < m_task_goal_lists[list_index].Min) || (entry > m_task_goal_lists[list_index].Max)) { - return false; - } - - int first_entry = 0; - auto &task = m_task_goal_lists[list_index]; - auto it = std::find(task.GoalItemEntries.begin(), task.GoalItemEntries.end(), entry); - - if (it == task.GoalItemEntries.end()) { - return false; - } - - Log(Logs::General, Logs::Tasks, "[UPDATE] TaskGoalListManager::IsInList(%i, %i) returning true", list_index, entry); - - return true; -} - -bool TaskGoalListManager::IsInMatchList(const std::string& match_list, const std::string& entry) -{ - for (auto &s: Strings::Split(match_list, '|')) { - if (s == entry) { - return true; - } - } - - return false; -} - -bool TaskGoalListManager::IsInMatchListPartial(const std::string &match_list, const std::string &entry) -{ - std::string entry_match = Strings::ToLower(entry); - for (auto &s: Strings::Split(match_list, '|')) { - if (entry_match.find(Strings::ToLower(s)) != std::string::npos) { - return true; - } - } - - return false; -} diff --git a/zone/task_goal_list_manager.h b/zone/task_goal_list_manager.h deleted file mode 100644 index b9c825123..000000000 --- a/zone/task_goal_list_manager.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef EQEMU_TASK_GOAL_LIST_MANAGER_H -#define EQEMU_TASK_GOAL_LIST_MANAGER_H - -#include "tasks.h" -#include "../common/types.h" -#include -#include -#include -#include - -struct TaskGoalList_Struct { - int ListID; - int Min, Max; - std::vector GoalItemEntries; -}; - -// This is used for handling lists, loading them from the database, searching them. -// Used for lists of NPCs to kill, items to loot, etc, as well as lists of items to -// reward the player with on completion of the task. -class TaskGoalListManager { - -public: - TaskGoalListManager(); - ~TaskGoalListManager(); - bool LoadLists(); - int GetListByID(int list_id); - bool IsInList(int list_id, int entry); - int GetFirstEntry(int list_id); - std::vector GetListContents(int list_index); - static bool IsInMatchList(const std::string& match_list, const std::string& entry); - static bool IsInMatchListPartial(const std::string& match_list, const std::string& entry); - -private: - std::vector m_task_goal_lists; - int m_goal_lists_count; -}; - - -#endif //EQEMU_TASK_GOAL_LIST_MANAGER_H diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 0b866af47..e7694ad79 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -41,22 +41,11 @@ bool TaskManager::LoadTaskSets() return true; } -void TaskManager::ReloadGoalLists() -{ - if (!m_goal_list_manager.LoadLists()) { - Log(Logs::Detail, Logs::Tasks, "TaskManager::LoadTasks LoadLists failed"); - } -} - bool TaskManager::LoadTasks(int single_task) { std::string task_query_filter = fmt::format("id = {}", single_task); std::string query; if (single_task == 0) { - if (!m_goal_list_manager.LoadLists()) { - LogTasks("[TaskManager::LoadTasks] LoadLists failed"); - } - if (!LoadTaskSets()) { LogTasks("[TaskManager::LoadTasks] LoadTaskSets failed"); } @@ -78,40 +67,40 @@ bool TaskManager::LoadTasks(int single_task) } // load task data - TaskInformation task_data{}; - task_data.type = static_cast(task.type); - task_data.duration = task.duration; - task_data.duration_code = static_cast(task.duration_code); - task_data.title = task.title; - task_data.description = task.description; - task_data.reward = task.reward; - task_data.reward_id = task.rewardid; - task_data.cash_reward = task.cashreward; - task_data.experience_reward = task.xpreward; - task_data.reward_method = (TaskMethodType) task.rewardmethod; - task_data.reward_points = task.reward_points; - task_data.reward_point_type = static_cast(task.reward_point_type); - task_data.faction_reward = task.faction_reward; - task_data.faction_amount = task.faction_amount; - task_data.min_level = task.minlevel; - task_data.max_level = task.maxlevel; - task_data.level_spread = task.level_spread; - task_data.min_players = task.min_players; - task_data.max_players = task.max_players; - task_data.repeatable = task.repeatable; - task_data.completion_emote = task.completion_emote; - task_data.replay_timer_group = task.replay_timer_group; - task_data.replay_timer_seconds = task.replay_timer_seconds; - task_data.request_timer_group = task.request_timer_group; - task_data.request_timer_seconds = task.request_timer_seconds; - task_data.activity_count = 0; + TaskInformation ti{}; + ti.type = static_cast(task.type); + ti.duration = task.duration; + ti.duration_code = static_cast(task.duration_code); + ti.title = task.title; + ti.description = task.description; + ti.reward = task.reward_text; + ti.reward_id_list = task.reward_id_list; + ti.cash_reward = task.cash_reward; + ti.experience_reward = task.exp_reward; + ti.reward_method = (TaskMethodType) task.reward_method; + ti.reward_points = task.reward_points; + ti.reward_point_type = static_cast(task.reward_point_type); + ti.faction_reward = task.faction_reward; + ti.faction_amount = task.faction_amount; + ti.min_level = task.min_level; + ti.max_level = task.max_level; + ti.level_spread = task.level_spread; + ti.min_players = task.min_players; + ti.max_players = task.max_players; + ti.repeatable = task.repeatable; + ti.completion_emote = task.completion_emote; + ti.replay_timer_group = task.replay_timer_group; + ti.replay_timer_seconds = task.replay_timer_seconds; + ti.request_timer_group = task.request_timer_group; + ti.request_timer_seconds = task.request_timer_seconds; + ti.activity_count = 0; - m_task_data.try_emplace(task_id, std::move(task_data)); + m_task_data.try_emplace(task_id, std::move(ti)); LogTasksDetail( "[LoadTasks] (Task) task_id [{}] type [{}] () duration [{}] duration_code [{}] title [{}] description [{}] " - " reward [{}] rewardid [{}] cashreward [{}] xpreward [{}] rewardmethod [{}] faction_reward [{}] minlevel [{}] " - " maxlevel [{}] level_spread [{}] min_players [{}] max_players [{}] repeatable [{}] completion_emote [{}]", + " reward_text [{}] reward_id_list [{}] cash_reward [{}] exp_reward [{}] reward_method [{}] faction_reward [{}] min_level [{}] " + " max_level [{}] level_spread [{}] min_players [{}] max_players [{}] repeatable [{}] completion_emote [{}]", " replay_group [{}] replay_timer_seconds [{}] request_group [{}] request_timer_seconds [{}]", task.id, task.type, @@ -119,14 +108,14 @@ bool TaskManager::LoadTasks(int single_task) task.duration_code, task.title, task.description, - task.reward, - task.rewardid, - task.cashreward, - task.xpreward, - task.rewardmethod, + task.reward_text, + task.reward_id_list, + task.cash_reward, + task.exp_reward, + task.reward_method, task.faction_reward, - task.minlevel, - task.maxlevel, + task.min_level, + task.max_level, task.level_spread, task.min_players, task.max_players, @@ -157,10 +146,10 @@ bool TaskManager::LoadTasks(int single_task) // load activity data auto task_activities = TaskActivitiesRepository::GetWhere(content_db, activities_query_filter); - for (auto &task_activity: task_activities) { - int task_id = task_activity.taskid; - int step = task_activity.step; - int activity_id = task_activity.activityid; + for (auto &a: task_activities) { + int task_id = a.taskid; + int step = a.step; + int activity_id = a.activityid; if (task_id <= 0 || activity_id < 0 || activity_id >= MAXACTIVITIESPERTASK) { @@ -185,7 +174,7 @@ bool TaskManager::LoadTasks(int single_task) // create pointer to activity data since declarations get unruly long int activity_index = task_data->activity_count; - ActivityInformation *activity_data = &task_data->activity_information[activity_index]; + ActivityInformation *ad = &task_data->activity_information[activity_index]; // Task Activities MUST be numbered sequentially from 0. If not, log an error // and set the task to nullptr. Subsequent activities for this task will raise @@ -202,53 +191,49 @@ bool TaskManager::LoadTasks(int single_task) } // set activity data - activity_data->req_activity_id = task_activity.req_activity_id; - activity_data->step = step; - activity_data->activity_type = static_cast(task_activity.activitytype); - activity_data->target_name = task_activity.target_name; - activity_data->item_list = task_activity.item_list; - activity_data->skill_list = task_activity.skill_list; - activity_data->skill_id = Strings::IsNumber(task_activity.skill_list) ? std::stoi(task_activity.skill_list) : 0; // for older clients - activity_data->spell_list = task_activity.spell_list; - activity_data->spell_id = Strings::IsNumber(task_activity.spell_list) ? std::stoi(task_activity.spell_list) : 0; // for older clients - activity_data->description_override = task_activity.description_override; - activity_data->npc_id = task_activity.npc_id; - activity_data->npc_goal_id = task_activity.npc_goal_id; - activity_data->npc_match_list = task_activity.npc_match_list; - activity_data->item_id = task_activity.item_id; - activity_data->item_goal_id = task_activity.item_goal_id; - activity_data->item_id_list = task_activity.item_id_list; - activity_data->dz_switch_id = task_activity.dz_switch_id; - activity_data->goal_method = (TaskMethodType) task_activity.goalmethod; - activity_data->goal_count = task_activity.goalcount; - activity_data->min_x = task_activity.min_x; - activity_data->min_y = task_activity.min_y; - activity_data->min_z = task_activity.min_z; - activity_data->max_x = task_activity.max_x; - activity_data->max_y = task_activity.max_y; - activity_data->max_z = task_activity.max_z; - activity_data->zone_version = task_activity.zone_version >= 0 ? task_activity.zone_version : -1; - activity_data->has_area = false; + ad->req_activity_id = a.req_activity_id; + ad->step = step; + ad->activity_type = static_cast(a.activitytype); + ad->target_name = a.target_name; + ad->item_list = a.item_list; + ad->skill_list = a.skill_list; + ad->skill_id = Strings::IsNumber(a.skill_list) ? std::stoi(a.skill_list) : 0; // for older clients + ad->spell_list = a.spell_list; + ad->spell_id = Strings::IsNumber(a.spell_list) ? std::stoi(a.spell_list) : 0; // for older clients + ad->description_override = a.description_override; + ad->npc_match_list = a.npc_match_list; + ad->item_id_list = a.item_id_list; + ad->dz_switch_id = a.dz_switch_id; + ad->goal_method = (TaskMethodType) a.goalmethod; + ad->goal_count = a.goalcount; + ad->min_x = a.min_x; + ad->min_y = a.min_y; + ad->min_z = a.min_z; + ad->max_x = a.max_x; + ad->max_y = a.max_y; + ad->max_z = a.max_z; + ad->zone_version = a.zone_version >= 0 ? a.zone_version : -1; + ad->has_area = false; - if (std::abs(task_activity.max_x - task_activity.min_x) > 0.0f && - std::abs(task_activity.max_y - task_activity.min_y) > 0.0f && - std::abs(task_activity.max_z - task_activity.min_z) > 0.0f) + if (std::abs(a.max_x - a.min_x) > 0.0f && + std::abs(a.max_y - a.min_y) > 0.0f && + std::abs(a.max_z - a.min_z) > 0.0f) { - activity_data->has_area = true; + ad->has_area = true; } // zones - activity_data->zones = task_activity.zones; + ad->zones = a.zones; auto zones = Strings::Split( - task_activity.zones, + a.zones, ';' ); for (auto &&e : zones) { - activity_data->zone_ids.push_back(std::stoi(e)); + ad->zone_ids.push_back(std::stoi(e)); } - activity_data->optional = task_activity.optional; + ad->optional = a.optional; LogTasksDetail( "[LoadTasks] (Activity) task_id [{}] activity_id [{}] slot [{}] activity_type [{}] goal_method [{}] goal_count [{}] zones [{}]" @@ -256,15 +241,15 @@ bool TaskManager::LoadTasks(int single_task) task_id, activity_id, task_data->activity_count, - static_cast(activity_data->activity_type), - activity_data->goal_method, - activity_data->goal_count, - activity_data->zones.c_str(), - activity_data->target_name.c_str(), - activity_data->item_list.c_str(), - activity_data->skill_list.c_str(), - activity_data->spell_list.c_str(), - activity_data->description_override.c_str() + static_cast(ad->activity_type), + ad->goal_method, + ad->goal_count, + ad->zones.c_str(), + ad->target_name.c_str(), + ad->item_list.c_str(), + ad->skill_list.c_str(), + ad->spell_list.c_str(), + ad->description_override.c_str() ); task_data->activity_count++; @@ -275,13 +260,13 @@ bool TaskManager::LoadTasks(int single_task) return true; } -bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_state) +bool TaskManager::SaveClientState(Client *client, ClientTaskState *cts) { // I am saving the slot in the ActiveTasks table, because unless a Task is cancelled/completed, the client // doesn't seem to like tasks moving slots between zoning and you can end up with 'bogus' activities if the task // previously in that slot had more activities than the one now occupying it. Hopefully retaining the slot // number for the duration of a session will overcome this. - if (!client || !client_task_state) { + if (!client || !cts) { return false; } @@ -291,10 +276,10 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s LogTasks("[SaveClientState] character_id [{}]", character_id); - if (client_task_state->m_active_task_count > 0 || - client_task_state->m_active_task.task_id != TASKSLOTEMPTY || - client_task_state->m_active_shared_task.task_id != TASKSLOTEMPTY) { - for (auto &active_task : client_task_state->m_active_tasks) { + if (cts->m_active_task_count > 0 || + cts->m_active_task.task_id != TASKSLOTEMPTY || + cts->m_active_shared_task.task_id != TASKSLOTEMPTY) { + for (auto &active_task : cts->m_active_tasks) { int task_id = active_task.task_id; if (task_id == TASKSLOTEMPTY) { continue; @@ -391,20 +376,20 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s } } - if (!RuleB(TaskSystem, RecordCompletedTasks) || (client_task_state->m_completed_tasks.size() <= - (unsigned int) client_task_state->m_last_completed_task_loaded)) { - client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + if (!RuleB(TaskSystem, RecordCompletedTasks) || (cts->m_completed_tasks.size() <= + (unsigned int) cts->m_last_completed_task_loaded)) { + cts->m_last_completed_task_loaded = cts->m_completed_tasks.size(); return true; } const char *completed_task_query = "REPLACE INTO completed_tasks (charid, completedtime, taskid, activityid) " "VALUES (%i, %i, %i, %i)"; - for (unsigned int task_index = client_task_state->m_last_completed_task_loaded; - task_index < client_task_state->m_completed_tasks.size(); + for (unsigned int task_index = cts->m_last_completed_task_loaded; + task_index < cts->m_completed_tasks.size(); task_index++) { - int task_id = client_task_state->m_completed_tasks[task_index].task_id; + int task_id = cts->m_completed_tasks[task_index].task_id; const auto task_data = GetTaskData(task_id); if (!task_data) { @@ -423,7 +408,7 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s std::string query = StringFormat( completed_task_query, character_id, - client_task_state->m_completed_tasks[task_index].completed_time, + cts->m_completed_tasks[task_index].completed_time, task_id, -1 ); @@ -442,14 +427,14 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s // Insert one record for each completed optional task. for (int activity_id = 0; activity_id < task_data->activity_count; activity_id++) { if (!task_data->activity_information[activity_id].optional || - !client_task_state->m_completed_tasks[task_index].activity_done[activity_id]) { + !cts->m_completed_tasks[task_index].activity_done[activity_id]) { continue; } query = StringFormat( completed_task_query, character_id, - client_task_state->m_completed_tasks[task_index].completed_time, + cts->m_completed_tasks[task_index].completed_time, task_id, activity_id ); @@ -460,7 +445,7 @@ bool TaskManager::SaveClientState(Client *client, ClientTaskState *client_task_s } } - client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + cts->m_last_completed_task_loaded = cts->m_completed_tasks.size(); return true; } @@ -767,14 +752,14 @@ void TaskManager::SendTaskSelector(Client* client, Mob* mob, const std::vectorGetTaskState()->ClearLastOffers(); int valid_tasks_count = 0; - for (int task_index = 0; task_index < task_list.size(); task_index++) { - if (!ValidateLevel(task_list[task_index], player_level)) { + for (int task_index : task_list) { + if (!ValidateLevel(task_index, player_level)) { continue; } - if (client->IsTaskActive(task_list[task_index])) { + if (client->IsTaskActive(task_index)) { continue; } - if (!IsTaskRepeatable(task_list[task_index]) && client->IsTaskCompleted(task_list[task_index])) { + if (!IsTaskRepeatable(task_index) && client->IsTaskCompleted(task_index)) { continue; } @@ -828,8 +813,7 @@ void TaskManager::SendSharedTaskSelector(Client* client, Mob* mob, const std::ve buf.WriteUInt32(static_cast(TaskType::Shared)); buf.WriteUInt32(mob->GetID()); // task giver entity id - for (int i = 0; i < task_list.size(); ++i) { - int task_id = task_list[i]; + for (int task_id: task_list) { buf.WriteUInt32(task_id); m_task_data[task_id].SerializeSelector(buf, client->ClientVersion()); client->GetTaskState()->AddOffer(task_id, mob->GetID()); @@ -861,22 +845,22 @@ bool TaskManager::IsTaskRepeatable(int task_id) return task_data->repeatable; } -void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state) +void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *cts) { int packet_length = 4; //vector::const_iterator iterator; // The client only display the first 50 Completed Tasks send, so send the 50 most recent int first_task_to_send = 0; - int last_task_to_send = client_task_state->m_completed_tasks.size(); + int last_task_to_send = cts->m_completed_tasks.size(); - if (client_task_state->m_completed_tasks.size() > 50) { - first_task_to_send = client_task_state->m_completed_tasks.size() - 50; + if (cts->m_completed_tasks.size() > 50) { + first_task_to_send = cts->m_completed_tasks.size() - 50; } LogTasks( "[SendCompletedTasksToClient] completed task count [{}] first tank to send is [{}] last is [{}]", - client_task_state->m_completed_tasks.size(), + cts->m_completed_tasks.size(), first_task_to_send, last_task_to_send ); @@ -889,7 +873,7 @@ void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_ } */ for (int i = first_task_to_send; i < last_task_to_send; i++) { - int task_id = client_task_state->m_completed_tasks[i].task_id; + int task_id = cts->m_completed_tasks[i].task_id; const auto task_data = GetTaskData(task_id); if (!task_data) { continue; } packet_length = packet_length + 8 + task_data->title.size() + 1; @@ -904,7 +888,7 @@ void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_ //for(iterator=activity_state->CompletedTasks.begin(); iterator!=activity_state->CompletedTasks.end(); iterator++) { // int task_id = (*iterator).task_id; for (int i = first_task_to_send; i < last_task_to_send; i++) { - int task_id = client_task_state->m_completed_tasks[i].task_id; + int task_id = cts->m_completed_tasks[i].task_id; const auto task_data = GetTaskData(task_id); if (!task_data) { continue; } *(uint32 *) buf = task_id; @@ -913,7 +897,7 @@ void TaskManager::SendCompletedTasksToClient(Client *c, ClientTaskState *client_ sprintf(buf, "%s", task_data->title.c_str()); buf = buf + strlen(buf) + 1; //*(uint32 *)buf = (*iterator).CompletedTime; - *(uint32 *) buf = client_task_state->m_completed_tasks[i].completed_time; + *(uint32 *) buf = cts->m_completed_tasks[i].completed_time; buf = buf + 4; } @@ -1130,30 +1114,22 @@ void TaskManager::SendActiveTaskDescription( bool bring_up_task_journal ) { - auto task_data = GetTaskData(task_id); - if (!task_data) { + auto t = GetTaskData(task_id); + if (!t) { return; } - int packet_length = sizeof(TaskDescriptionHeader_Struct) + task_data->title.length() + 1 - + sizeof(TaskDescriptionData1_Struct) + task_data->description.length() + 1 + int packet_length = sizeof(TaskDescriptionHeader_Struct) + t->title.length() + 1 + + sizeof(TaskDescriptionData1_Struct) + t->description.length() + 1 + sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct); // If there is an item make the reward text into a link to the item (only the first item if a list // is specified). I have been unable to get multiple item links to work. // - if (task_data->reward_id && task_data->item_link.empty()) { - int item_id = 0; - // If the reward is a list of items, and the first entry on the list is valid - if (task_data->reward_method == METHODSINGLEID) { - item_id = task_data->reward_id; - } - else if (task_data->reward_method == METHODLIST) { - item_id = m_goal_list_manager.GetFirstEntry(task_data->reward_id); - if (item_id < 0) { - item_id = 0; - } - } + if (!t->reward_id_list.empty() && t->item_link.empty()) { + auto items = Strings::Split(t->reward_id_list, "|"); + auto item = items.front(); + int item_id = Strings::IsNumber(items.front()) ? std::stoi(items.front()) : 0; if (item_id) { const EQ::ItemData *reward_item = database.GetItem(item_id); @@ -1162,11 +1138,11 @@ void TaskManager::SendActiveTaskDescription( linker.SetLinkType(EQ::saylink::SayLinkItemData); linker.SetItemData(reward_item); linker.SetTaskUse(); - task_data->item_link = linker.GenerateLink(); + t->item_link = linker.GenerateLink(); } } - packet_length += task_data->reward.length() + 1 + task_data->item_link.length() + 1; + packet_length += t->reward.length() + 1 + t->item_link.length() + 1; char *Ptr; TaskDescriptionHeader_Struct *task_description_header; @@ -1181,26 +1157,26 @@ void TaskManager::SendActiveTaskDescription( task_description_header->SequenceNumber = task_info.slot; task_description_header->TaskID = task_id; task_description_header->open_window = bring_up_task_journal; - task_description_header->task_type = static_cast(task_data->type); + task_description_header->task_type = static_cast(t->type); - task_description_header->reward_type = static_cast(task_data->reward_point_type); + task_description_header->reward_type = static_cast(t->reward_point_type); Ptr = (char *) task_description_header + sizeof(TaskDescriptionHeader_Struct); - sprintf(Ptr, "%s", task_data->title.c_str()); - Ptr += task_data->title.length() + 1; + sprintf(Ptr, "%s", t->title.c_str()); + Ptr += t->title.length() + 1; tdd1 = (TaskDescriptionData1_Struct *) Ptr; tdd1->Duration = duration; - tdd1->dur_code = static_cast(task_data->duration_code); + tdd1->dur_code = static_cast(t->duration_code); tdd1->StartTime = start_time; Ptr = (char *) tdd1 + sizeof(TaskDescriptionData1_Struct); - sprintf(Ptr, "%s", task_data->description.c_str()); - Ptr += task_data->description.length() + 1; + sprintf(Ptr, "%s", t->description.c_str()); + Ptr += t->description.length() + 1; tdd2 = (TaskDescriptionData2_Struct *) Ptr; @@ -1209,24 +1185,24 @@ void TaskManager::SendActiveTaskDescription( // "has_reward_selection" is after this bool! Smaller packet when this is 0 tdd2->has_rewards = 1; - tdd2->coin_reward = task_data->cash_reward; - tdd2->xp_reward = task_data->experience_reward ? 1 : 0; // just booled - tdd2->faction_reward = task_data->faction_reward ? 1 : 0; // faction booled + tdd2->coin_reward = t->cash_reward; + tdd2->xp_reward = t->experience_reward ? 1 : 0; // just booled + tdd2->faction_reward = t->faction_reward ? 1 : 0; // faction booled Ptr = (char *) tdd2 + sizeof(TaskDescriptionData2_Struct); // we actually have 2 strings here. One is max length 96 and not parsed for item links // We actually skipped past that string incorrectly before, so TODO: fix item link string - sprintf(Ptr, "%s", task_data->reward.c_str()); - Ptr += task_data->reward.length() + 1; + sprintf(Ptr, "%s", t->reward.c_str()); + Ptr += t->reward.length() + 1; // second string is parsed for item links - sprintf(Ptr, "%s", task_data->item_link.c_str()); - Ptr += task_data->item_link.length() + 1; + sprintf(Ptr, "%s", t->item_link.c_str()); + Ptr += t->item_link.length() + 1; tdt = (TaskDescriptionTrailer_Struct *) Ptr; // shared tasks show radiant/ebon crystal reward, non-shared tasks show generic points - tdt->Points = task_data->reward_points; + tdt->Points = t->reward_points; tdt->has_reward_selection = 0; // TODO: new rewards window @@ -1234,9 +1210,9 @@ void TaskManager::SendActiveTaskDescription( safe_delete(outapp); } -bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_state) +bool TaskManager::LoadClientState(Client *client, ClientTaskState *cts) { - if (!client || !client_task_state) { + if (!client || !cts) { return false; } @@ -1244,7 +1220,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s int character_id = client->CharacterID(); - client_task_state->m_active_task_count = 0; + cts->m_active_task_count = 0; LogTasks("[LoadClientState] for character_id [{}]", character_id); @@ -1276,7 +1252,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // client data bucket pointer // this actually fetches the proper task type instances to be loaded with data // whether it be quest / task / shared task - auto task_info = client_task_state->GetClientTaskInfo(type, slot); + auto task_info = cts->GetClientTaskInfo(type, slot); if (task_info == nullptr) { LogTasks( "[LoadClientState] Error: slot [{}] out of range while loading character tasks from database", @@ -1301,7 +1277,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // this check keeps a lot of core task updating code from working properly (shared or otherwise) if (type == TaskType::Quest) { - ++client_task_state->m_active_task_count; + ++cts->m_active_task_count; } LogTasks( @@ -1346,18 +1322,18 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // type: task ClientTaskInformation *task_info = nullptr; - if (client_task_state->m_active_task.task_id == task_id) { - task_info = &client_task_state->m_active_task; + if (cts->m_active_task.task_id == task_id) { + task_info = &cts->m_active_task; } // type: shared task - if (client_task_state->m_active_shared_task.task_id == task_id) { - task_info = &client_task_state->m_active_shared_task; + if (cts->m_active_shared_task.task_id == task_id) { + task_info = &cts->m_active_shared_task; } // type: quest if (task_info == nullptr) { - for (auto &active_quest : client_task_state->m_active_quests) { + for (auto &active_quest : cts->m_active_quests) { if (active_quest.task_id == task_id) { task_info = &active_quest; } @@ -1396,12 +1372,12 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s ); } - SyncClientSharedTaskState(client, client_task_state); + SyncClientSharedTaskState(client, cts); if (RuleB(TaskSystem, RecordCompletedTasks)) { - CompletedTaskInformation completed_task_information{}; + CompletedTaskInformation cti{}; - for (bool &i : completed_task_information.activity_done) { + for (bool &i : cti.activity_done) { i = false; } @@ -1434,14 +1410,14 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s int completed_time = character_completed_task.completedtime; if ((previous_task_id != -1) && ((task_id != previous_task_id) || (completed_time != previous_completed_time))) { - client_task_state->m_completed_tasks.push_back(completed_task_information); - for (bool &activity_done : completed_task_information.activity_done) { + cts->m_completed_tasks.push_back(cti); + for (bool &activity_done : cti.activity_done) { activity_done = false; } } - completed_task_information.task_id = previous_task_id = task_id; - completed_task_information.completed_time = previous_completed_time = completed_time; + cti.task_id = previous_task_id = task_id; + cti.completed_time = previous_completed_time = completed_time; // If activity_id is -1, Mark all the non-optional tasks as completed. if (activity_id < 0) { @@ -1452,20 +1428,20 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s for (int i = 0; i < task_data->activity_count; i++) { if (!task_data->activity_information[i].optional) { - completed_task_information.activity_done[i] = true; + cti.activity_done[i] = true; } } } else { - completed_task_information.activity_done[activity_id] = true; + cti.activity_done[activity_id] = true; } } if (previous_task_id != -1) { - client_task_state->m_completed_tasks.push_back(completed_task_information); + cts->m_completed_tasks.push_back(cti); } - client_task_state->m_last_completed_task_loaded = client_task_state->m_completed_tasks.size(); + cts->m_last_completed_task_loaded = cts->m_completed_tasks.size(); } std::string query = StringFormat( @@ -1479,7 +1455,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s if (results.Success()) { for (auto row = results.begin(); row != results.end(); ++row) { int task_id = atoi(row[0]); - client_task_state->m_enabled_tasks.push_back(task_id); + cts->m_enabled_tasks.push_back(task_id); LogTasksDetail("[LoadClientState] Adding task_id [{}] to enabled tasks", task_id); } } @@ -1488,7 +1464,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // This should only break if a ServerOP adds or deletes activites for a task that players already // have active, or due to a bug. for (int task_index = 0; task_index < MAXACTIVEQUESTS + 1; task_index++) { - int task_id = client_task_state->m_active_tasks[task_index].task_id; + int task_id = cts->m_active_tasks[task_index].task_id; if (task_id == TASKSLOTEMPTY) { continue; } @@ -1503,11 +1479,11 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s ); LogError("[LoadClientState] Character [{}] has task [{}] which does not exist", character_id, task_id); - client_task_state->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; + cts->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; continue; } for (int activity_index = 0; activity_index < task_data->activity_count; activity_index++) { - if (client_task_state->m_active_tasks[task_index].activity[activity_index].activity_id != activity_index) { + if (cts->m_active_tasks[task_index].activity[activity_index].activity_id != activity_index) { client->Message( Chat::Red, "Active Task %i, %s. activity_information count does not match expected value." @@ -1521,7 +1497,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s activity_index, task_id ); - client_task_state->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; + cts->m_active_tasks[task_index].task_id = TASKSLOTEMPTY; break; } } @@ -1529,34 +1505,34 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s LogTasksDetail( "[LoadClientState] m_active_task task_id is [{}] slot [{}]", - client_task_state->m_active_task.task_id, - client_task_state->m_active_task.slot + cts->m_active_task.task_id, + cts->m_active_task.slot ); - if (client_task_state->m_active_task.task_id != TASKSLOTEMPTY) { - client_task_state->UnlockActivities(client, client_task_state->m_active_task); + if (cts->m_active_task.task_id != TASKSLOTEMPTY) { + cts->UnlockActivities(client, cts->m_active_task); // purely debugging LogTasksDetail( "[LoadClientState] Fetching task info for character_id [{}] task [{}] slot [{}] accepted_time [{}] updated [{}]", character_id, - client_task_state->m_active_task.task_id, - client_task_state->m_active_task.slot, - client_task_state->m_active_task.accepted_time, - client_task_state->m_active_task.updated + cts->m_active_task.task_id, + cts->m_active_task.slot, + cts->m_active_task.accepted_time, + cts->m_active_task.updated ); - const auto task_data = GetTaskData(client_task_state->m_active_task.task_id); + const auto task_data = GetTaskData(cts->m_active_task.task_id); if (task_data) { for (int i = 0; i < task_data->activity_count; i++) { - if (client_task_state->m_active_task.activity[i].activity_id >= 0) { + if (cts->m_active_task.activity[i].activity_id >= 0) { LogTasksDetail( "[LoadClientState] -- character_id [{}] task [{}] activity_id [{}] done_count [{}] activity_state [{}] updated [{}]", character_id, - client_task_state->m_active_task.task_id, - client_task_state->m_active_task.activity[i].activity_id, - client_task_state->m_active_task.activity[i].done_count, - client_task_state->m_active_task.activity[i].activity_state, - client_task_state->m_active_task.activity[i].updated + cts->m_active_task.task_id, + cts->m_active_task.activity[i].activity_id, + cts->m_active_task.activity[i].done_count, + cts->m_active_task.activity[i].activity_state, + cts->m_active_task.activity[i].updated ); } } @@ -1566,17 +1542,17 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s // shared task LogTasksDetail( "[LoadClientState] m_active_shared_task task_id is [{}] slot [{}]", - client_task_state->m_active_shared_task.task_id, - client_task_state->m_active_shared_task.slot + cts->m_active_shared_task.task_id, + cts->m_active_shared_task.slot ); - if (client_task_state->m_active_shared_task.task_id != TASKSLOTEMPTY) { - client_task_state->UnlockActivities(client, client_task_state->m_active_shared_task); + if (cts->m_active_shared_task.task_id != TASKSLOTEMPTY) { + cts->UnlockActivities(client, cts->m_active_shared_task); } // quests (max 20 or 40 depending on client) - for (auto &active_quest : client_task_state->m_active_quests) { + for (auto &active_quest : cts->m_active_quests) { if (active_quest.task_id != TASKSLOTEMPTY) { - client_task_state->UnlockActivities(client, active_quest); + cts->UnlockActivities(client, active_quest); } } diff --git a/zone/task_manager.h b/zone/task_manager.h index 882e60e47..a7a586548 100644 --- a/zone/task_manager.h +++ b/zone/task_manager.h @@ -3,7 +3,6 @@ #include "tasks.h" #include "task_client_state.h" -#include "task_goal_list_manager.h" #include "../common/types.h" #include "../common/repositories/character_tasks_repository.h" #include @@ -20,10 +19,9 @@ class TaskManager { public: int GetActivityCount(int task_id); bool LoadTasks(int single_task = 0); - void ReloadGoalLists(); bool LoadTaskSets(); - bool LoadClientState(Client *client, ClientTaskState *client_task_state); - bool SaveClientState(Client *client, ClientTaskState *client_task_state); + bool LoadClientState(Client *client, ClientTaskState *cts); + bool SaveClientState(Client *client, ClientTaskState *cts); void SendTaskSelector(Client* client, Mob* mob, const std::vector& tasks); bool ValidateLevel(int task_id, int player_level); std::string GetTaskName(uint32 task_id); @@ -47,7 +45,7 @@ public: int client_task_index, bool task_complete = false ); - void SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state); + void SendCompletedTasksToClient(Client *c, ClientTaskState *cts); int FirstTaskInSet(int task_set); int LastTaskInSet(int task_set); int NextTaskInSet(int task_set, int task_id); @@ -69,8 +67,7 @@ public: } private: - TaskGoalListManager m_goal_list_manager; - std::vector m_task_sets[MAXTASKSETS]; + std::vector m_task_sets[MAXTASKSETS]; std::unordered_map m_task_data; void SendActiveTaskDescription( Client *client, diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 76ada31f8..32caea764 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -3465,12 +3465,6 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack) break; } - case RELOADTASKGOALLISTS: - { - LogTasks("Global reload of all Task Goal Lists"); - task_manager->ReloadGoalLists(); - break; - } case RELOADTASKSETS: { LogTasks("Global reload of all Task Sets");