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_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/tasks.h b/common/tasks.h index 27ef6aaae..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; @@ -203,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 @@ -221,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 @@ -416,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/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql b/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql index cb15a338a..fc86863e8 100644 --- a/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql +++ b/utils/sql/git/required/2022_09_25_task_concat_matchlists.sql @@ -1,3 +1,11 @@ +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`) @@ -37,3 +45,25 @@ ALTER TABLE `task_activities` 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 NULL DEFAULT 0 AFTER `reward_text`, + CHANGE COLUMN `cashreward` `cash_reward` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `reward_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/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 bed35b882..35cd666ad 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -512,7 +512,7 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter, // 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; @@ -520,9 +520,9 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter, // 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; @@ -979,33 +979,13 @@ void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_inf 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); - } - } - 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); - } - } - break; - } - default: { - // Nothing special done for METHODQUEST - break; + for (auto &i: Strings::Split("|", task_information->reward_id_list)) { + auto item_id = std::stoi(i); + 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); } } 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 86fadab3e..4e4dc3102 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,49 +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_match_list = task_activity.npc_match_list; - 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 [{}]" @@ -252,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++; @@ -271,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; } @@ -287,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; @@ -387,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) { @@ -419,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 ); @@ -438,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 ); @@ -456,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; } @@ -763,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; } @@ -824,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()); @@ -857,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 ); @@ -885,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; @@ -900,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; @@ -909,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; } @@ -1126,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 = std::stoi(items.front()); if (item_id) { const EQ::ItemData *reward_item = database.GetItem(item_id); @@ -1158,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; @@ -1177,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; @@ -1205,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 @@ -1230,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; } @@ -1240,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); @@ -1272,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", @@ -1297,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( @@ -1342,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; } @@ -1392,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; } @@ -1430,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) { @@ -1448,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( @@ -1475,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); } } @@ -1484,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; } @@ -1499,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." @@ -1517,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; } } @@ -1525,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 ); } } @@ -1562,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");