mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Tasks] Schema simplification (#2449)
* Combine task_activity item and npc fields This will make tooling easier. While denormalizing goallists may not be ideal, it decouples tasks from rewards which share the table and removes a redundant column in favor of a using the delimited string which better matches live packet data. * [Tasks] Deprecate goallists table, migrate reward goal lists, simplify logic * Update 2022_09_25_task_concat_matchlists.sql * Update 2022_09_25_task_concat_matchlists.sql * Tweaks * Fix reward column name in conversion script * Task reward stacking * Update task_client_state.cpp * Implement stack counts * Fix reward item instance memory leak * Validate reward item instance * Fix item reward message * Fix findtask Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
parent
d22fca7593
commit
e883703b2f
@ -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
|
||||
|
||||
@ -197,7 +197,6 @@ namespace DatabaseSchema {
|
||||
"fishing",
|
||||
"forage",
|
||||
"global_loot",
|
||||
"goallists",
|
||||
"graveyard",
|
||||
"grid",
|
||||
"grid_entries",
|
||||
|
||||
@ -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 <ctime>
|
||||
|
||||
class BaseGoallistsRepository {
|
||||
public:
|
||||
struct Goallists {
|
||||
uint32_t listid;
|
||||
uint32_t entry;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
{
|
||||
return std::string("listid");
|
||||
}
|
||||
|
||||
static std::vector<std::string> Columns()
|
||||
{
|
||||
return {
|
||||
"listid",
|
||||
"entry",
|
||||
};
|
||||
}
|
||||
|
||||
static std::vector<std::string> 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<Goallists> &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<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.entry = static_cast<uint32_t>(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<std::string> 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<std::string> 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<Goallists> &entries
|
||||
)
|
||||
{
|
||||
std::vector<std::string> insert_chunks;
|
||||
|
||||
for (auto &e: entries) {
|
||||
std::vector<std::string> 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<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"{} VALUES {}",
|
||||
BaseInsert(),
|
||||
Strings::Implode(",", insert_chunks)
|
||||
)
|
||||
);
|
||||
|
||||
return (results.Success() ? results.RowsAffected() : 0);
|
||||
}
|
||||
|
||||
static std::vector<Goallists> All(Database& db)
|
||||
{
|
||||
std::vector<Goallists> 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<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.entry = static_cast<uint32_t>(strtoul(row[1], nullptr, 10));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
return all_entries;
|
||||
}
|
||||
|
||||
static std::vector<Goallists> GetWhere(Database& db, const std::string &where_filter)
|
||||
{
|
||||
std::vector<Goallists> 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<uint32_t>(strtoul(row[0], nullptr, 10));
|
||||
e.entry = static_cast<uint32_t>(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
|
||||
@ -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<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.goalcount = static_cast<int32_t>(atoi(row[7]));
|
||||
e.description_override = row[8] ? row[8] : "";
|
||||
e.npc_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
|
||||
e.npc_goal_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
|
||||
e.npc_match_list = row[11] ? row[11] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
|
||||
e.item_goal_id = static_cast<uint32_t>(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<int32_t>(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<int32_t>(atoi(row[26]));
|
||||
e.optional = static_cast<int8_t>(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<int32_t>(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<int32_t>(atoi(row[22]));
|
||||
e.optional = static_cast<int8_t>(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<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.goalcount = static_cast<int32_t>(atoi(row[7]));
|
||||
e.description_override = row[8] ? row[8] : "";
|
||||
e.npc_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
|
||||
e.npc_goal_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
|
||||
e.npc_match_list = row[11] ? row[11] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
|
||||
e.item_goal_id = static_cast<uint32_t>(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<int32_t>(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<int32_t>(atoi(row[26]));
|
||||
e.optional = static_cast<int8_t>(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<int32_t>(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<int32_t>(atoi(row[22]));
|
||||
e.optional = static_cast<int8_t>(atoi(row[23]));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@ -511,25 +475,21 @@ public:
|
||||
e.goalmethod = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
|
||||
e.goalcount = static_cast<int32_t>(atoi(row[7]));
|
||||
e.description_override = row[8] ? row[8] : "";
|
||||
e.npc_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
|
||||
e.npc_goal_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
|
||||
e.npc_match_list = row[11] ? row[11] : "";
|
||||
e.item_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
|
||||
e.item_goal_id = static_cast<uint32_t>(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<int32_t>(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<int32_t>(atoi(row[26]));
|
||||
e.optional = static_cast<int8_t>(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<int32_t>(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<int32_t>(atoi(row[22]));
|
||||
e.optional = static_cast<int8_t>(atoi(row[23]));
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
|
||||
@ -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<int8_t>(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<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||
e.cashreward = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.xpreward = static_cast<int32_t>(atoi(row[9]));
|
||||
e.rewardmethod = static_cast<uint8_t>(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<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.exp_reward = static_cast<int32_t>(atoi(row[9]));
|
||||
e.reward_method = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
|
||||
e.reward_points = static_cast<int32_t>(atoi(row[11]));
|
||||
e.reward_point_type = static_cast<int32_t>(atoi(row[12]));
|
||||
e.minlevel = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
|
||||
e.maxlevel = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
|
||||
e.min_level = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
|
||||
e.max_level = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
|
||||
e.level_spread = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
|
||||
e.min_players = static_cast<uint32_t>(strtoul(row[16], nullptr, 10));
|
||||
e.max_players = static_cast<uint32_t>(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<int8_t>(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<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||
e.cashreward = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.xpreward = static_cast<int32_t>(atoi(row[9]));
|
||||
e.rewardmethod = static_cast<uint8_t>(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<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.exp_reward = static_cast<int32_t>(atoi(row[9]));
|
||||
e.reward_method = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
|
||||
e.reward_points = static_cast<int32_t>(atoi(row[11]));
|
||||
e.reward_point_type = static_cast<int32_t>(atoi(row[12]));
|
||||
e.minlevel = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
|
||||
e.maxlevel = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
|
||||
e.min_level = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
|
||||
e.max_level = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
|
||||
e.level_spread = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
|
||||
e.min_players = static_cast<uint32_t>(strtoul(row[16], nullptr, 10));
|
||||
e.max_players = static_cast<uint32_t>(strtoul(row[17], nullptr, 10));
|
||||
@ -508,15 +508,15 @@ public:
|
||||
e.duration_code = static_cast<int8_t>(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<uint32_t>(strtoul(row[7], nullptr, 10));
|
||||
e.cashreward = static_cast<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.xpreward = static_cast<int32_t>(atoi(row[9]));
|
||||
e.rewardmethod = static_cast<uint8_t>(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<uint32_t>(strtoul(row[8], nullptr, 10));
|
||||
e.exp_reward = static_cast<int32_t>(atoi(row[9]));
|
||||
e.reward_method = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
|
||||
e.reward_points = static_cast<int32_t>(atoi(row[11]));
|
||||
e.reward_point_type = static_cast<int32_t>(atoi(row[12]));
|
||||
e.minlevel = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
|
||||
e.maxlevel = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
|
||||
e.min_level = static_cast<uint8_t>(strtoul(row[13], nullptr, 10));
|
||||
e.max_level = static_cast<uint8_t>(strtoul(row[14], nullptr, 10));
|
||||
e.level_spread = static_cast<uint32_t>(strtoul(row[15], nullptr, 10));
|
||||
e.min_players = static_cast<uint32_t>(strtoul(row[16], nullptr, 10));
|
||||
e.max_players = static_cast<uint32_t>(strtoul(row[17], nullptr, 10));
|
||||
|
||||
@ -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
|
||||
@ -64,7 +64,7 @@ std::vector<std::string> Strings::Split(const std::string &str, const char delim
|
||||
}
|
||||
|
||||
// this one takes delimiter length into consideration
|
||||
std::vector<std::string> Strings::Split(std::string s, std::string delimiter)
|
||||
std::vector<std::string> 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;
|
||||
}
|
||||
|
||||
@ -84,6 +84,7 @@ namespace EQ {
|
||||
class Strings {
|
||||
public:
|
||||
static bool Contains(std::vector<std::string> 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<std::string> Split(const std::string &s, const char delim = ',');
|
||||
static std::vector<std::string> Split(std::string s, std::string delimiter);
|
||||
static std::vector<std::string> Split(const std::string& s, const std::string& delimiter);
|
||||
static std::vector<std::string> Wrap(std::vector<std::string> &src, std::string character);
|
||||
static void FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string);
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#ifndef EQEMU_TASKS_H
|
||||
#define EQEMU_TASKS_H
|
||||
|
||||
#include "../common/strings.h"
|
||||
#include "serialize_buffer.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
69
utils/sql/git/required/2022_09_25_task_concat_matchlists.sql
Normal file
69
utils/sql/git/required/2022_09_25_task_concat_matchlists.sql
Normal file
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.");
|
||||
|
||||
@ -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<int> 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<EQ::ItemInstance> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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<int> TaskGoalListManager::GetListContents(int list_index)
|
||||
{
|
||||
std::vector<int> 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;
|
||||
}
|
||||
@ -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 <list>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
struct TaskGoalList_Struct {
|
||||
int ListID;
|
||||
int Min, Max;
|
||||
std::vector<int> 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<int> 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<TaskGoalList_Struct> m_task_goal_lists;
|
||||
int m_goal_lists_count;
|
||||
};
|
||||
|
||||
|
||||
#endif //EQEMU_TASK_GOAL_LIST_MANAGER_H
|
||||
@ -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<TaskType>(task.type);
|
||||
task_data.duration = task.duration;
|
||||
task_data.duration_code = static_cast<DurationCode>(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<AltCurrencyType>(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<TaskType>(task.type);
|
||||
ti.duration = task.duration;
|
||||
ti.duration_code = static_cast<DurationCode>(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<AltCurrencyType>(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<TaskActivityType>(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<TaskActivityType>(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<int32_t>(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<int32_t>(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::vector<i
|
||||
client->GetTaskState()->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<uint32_t>(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<CompletedTaskInformation>::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<uint32>(task_data->type);
|
||||
task_description_header->task_type = static_cast<uint32>(t->type);
|
||||
|
||||
task_description_header->reward_type = static_cast<int>(task_data->reward_point_type);
|
||||
task_description_header->reward_type = static_cast<int>(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<uint32>(task_data->duration_code);
|
||||
tdd1->dur_code = static_cast<uint32>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 <list>
|
||||
@ -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<int>& 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<int> m_task_sets[MAXTASKSETS];
|
||||
std::vector<int> m_task_sets[MAXTASKSETS];
|
||||
std::unordered_map<uint32_t, TaskInformation> m_task_data;
|
||||
void SendActiveTaskDescription(
|
||||
Client *client,
|
||||
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user