[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:
hg
2022-09-28 03:31:05 -04:00
committed by GitHub
parent d22fca7593
commit e883703b2f
23 changed files with 496 additions and 1111 deletions
-2
View File
@@ -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
+8 -7
View File
@@ -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;
+1 -6
View File
@@ -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.");
+51 -85
View File
@@ -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);
}
}
}
+1 -1
View File
@@ -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);
-172
View File
@@ -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;
}
-39
View File
@@ -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
+183 -207
View File
@@ -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);
}
}
+4 -7
View File
@@ -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,
-6
View File
@@ -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");