mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
The task goal system made implementing tasks a little confusing since the goal could be ambiguous depending on type. This also didn't support filtering on multiple goals (e.g. looting items from matching npc names inside an area). Deliver types could specify an npc id in `delivertonpc` but the database may have multiple npcs with the same name or a task might want to match partial npc names. This replaces goalids with explicit fields for npcs, items, proximity areas, and touch switch ids. These changes make managing task data easier without needing to update multiple tables and allows filtering task updates by multiple criteria. To mitigate any performance impact from merging task proximities, only clients with explore tasks in the current zone are checked during client movement updates. Items and npcs still support goallists but it would be possible to denormalize entries into delimited strings to combine with the match lists. This would also decouple task goals from reward lists. The client task update functions were refactored to run through a single filtering function which significantly reduces duplicated code from the legacy task system. This will also make it easier to later implement any unhandled types. Since the new fields will handle filtering single entries and lists based on having values set, `goalmethod` now only distinguishes quest controlled from source controlled. This is a breaking api change, `taskexploredarea` has been removed since explore ids no longer exist.
319 lines
8.7 KiB
C++
Executable File
319 lines
8.7 KiB
C++
Executable File
#include "../client.h"
|
|
#include "../worldserver.h"
|
|
|
|
extern WorldServer worldserver;
|
|
|
|
#include "../../common/shared_tasks.h"
|
|
#include "../../common/repositories/completed_tasks_repository.h"
|
|
|
|
void command_task(Client *c, const Seperator *sep)
|
|
{
|
|
int arguments = sep->argnum;
|
|
if (!arguments) {
|
|
c->Message(Chat::White, "Syntax: #task [subcommand]");
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(Chat::White, "# Task System Commands");
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] List active tasks for a client",
|
|
Saylink::Silent("#task show", "show")
|
|
).c_str()
|
|
);
|
|
c->Message(Chat::White, "--- update <task_id> <activity_id> [count] | Updates task");
|
|
c->Message(Chat::White, "--- assign <task_id> | Assigns task to client");
|
|
c->Message(Chat::White, "--- uncomplete <task_id> | Uncompletes a task if a client has completed it");
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Reload all Task information from the database",
|
|
Saylink::Silent("#task reloadall", "reloadall")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] <task_id> Reload Task and Activity information for a single task",
|
|
Saylink::Silent("#task reload task", "reload task")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Reload goal/reward list information",
|
|
Saylink::Silent("#task reload lists", "reload lists")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Reload task set information",
|
|
Saylink::Silent("#task reload sets", "reload sets")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Purges targeted characters task timers",
|
|
Saylink::Silent("#task purgetimers", "purgetimers")
|
|
).c_str()
|
|
);
|
|
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(Chat::White, "# Shared Task System Commands");
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Purges all active Shared Tasks in memory and database ",
|
|
Saylink::Silent("#task sharedpurge", "sharedpurge")
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
|
|
Client *target = c;
|
|
if (c->GetTarget() && c->GetTarget()->IsClient()) {
|
|
target = c->GetTarget()->CastToClient();
|
|
}
|
|
|
|
bool is_assign = !strcasecmp(sep->arg[1], "assign");
|
|
bool is_purgetimers = !strcasecmp(sep->arg[1], "purgetimers");
|
|
bool is_reload = !strcasecmp(sep->arg[1], "reload");
|
|
bool is_reloadall = !strcasecmp(sep->arg[1], "reloadall");
|
|
bool is_sharedpurge = !strcasecmp(sep->arg[1], "sharedpurge");
|
|
bool is_show = !strcasecmp(sep->arg[1], "show");
|
|
bool is_uncomplete = !strcasecmp(sep->arg[1], "uncomplete");
|
|
bool is_update = !strcasecmp(sep->arg[1], "update");
|
|
|
|
if (
|
|
!is_assign &&
|
|
!is_purgetimers &&
|
|
!is_reload &&
|
|
!is_reloadall &&
|
|
!is_sharedpurge &&
|
|
!is_show &&
|
|
!is_uncomplete &&
|
|
!is_update
|
|
) {
|
|
c->Message(Chat::White, "Syntax: #task [subcommand]");
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(Chat::White, "# Task System Commands");
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] List active tasks for a client",
|
|
Saylink::Silent("#task show", "show")
|
|
).c_str()
|
|
);
|
|
c->Message(Chat::White, "--- update <task_id> <activity_id> [count] | Updates task");
|
|
c->Message(Chat::White, "--- assign <task_id> | Assigns task to client");
|
|
c->Message(Chat::White, "--- uncomplete <task_id> | Uncompletes a task if a client has completed it");
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Reload all Task information from the database",
|
|
Saylink::Silent("#task reloadall", "reloadall")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] <task_id> Reload Task and Activity information for a single task",
|
|
Saylink::Silent("#task reload task", "reload task")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Reload goal/reward list information",
|
|
Saylink::Silent("#task reload lists", "reload lists")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Reload task set information",
|
|
Saylink::Silent("#task reload sets", "reload sets")
|
|
).c_str()
|
|
);
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Purges targeted characters task timers",
|
|
Saylink::Silent("#task purgetimers", "purgetimers")
|
|
).c_str()
|
|
);
|
|
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(Chat::White, "# Shared Task System Commands");
|
|
c->Message(Chat::White, "------------------------------------------------");
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"--- [{}] Purges all active Shared Tasks in memory and database ",
|
|
Saylink::Silent("#task sharedpurge", "sharedpurge")
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (is_assign) {
|
|
auto task_id = std::strtoul(sep->arg[2], nullptr, 10);
|
|
if (task_id && task_id < MAXTASKS) {
|
|
target->AssignTask(task_id, 0, false);
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"Assigned task ID {} to {}.",
|
|
task_id,
|
|
c->GetTargetDescription(target)
|
|
).c_str()
|
|
);
|
|
}
|
|
return;
|
|
} else if (is_purgetimers) {
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"Task timers have been purged for {}.",
|
|
c->GetTargetDescription(target)
|
|
).c_str()
|
|
);
|
|
|
|
if (c != target) {
|
|
target->Message(Chat::Yellow, "Your task timers have been purged by a GM.");
|
|
}
|
|
|
|
target->PurgeTaskTimers();
|
|
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")) {
|
|
c->Message(Chat::Yellow, "Attempting to reload task sets.");
|
|
worldserver.SendReloadTasks(RELOADTASKSETS);
|
|
c->Message(Chat::Yellow, "Successfully reloaded task sets.");
|
|
return;
|
|
} else if (!strcasecmp(sep->arg[2], "task") && arguments == 3) {
|
|
int task_id = std::strtoul(sep->arg[3], nullptr, 10);
|
|
if (task_id && task_id < MAXTASKS) {
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"Attempted to reload task ID {}.",
|
|
task_id
|
|
).c_str()
|
|
);
|
|
worldserver.SendReloadTasks(RELOADTASKS, task_id);
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"Successfully reloaded task ID {}.",
|
|
task_id
|
|
).c_str()
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
} else if (is_reloadall) {
|
|
c->Message(Chat::Yellow, "Attempting to reload tasks.");
|
|
worldserver.SendReloadTasks(RELOADTASKS);
|
|
c->Message(Chat::Yellow, "Successfully reloaded tasks.");
|
|
return;
|
|
} else if (is_sharedpurge) {
|
|
if (!strcasecmp(sep->arg[2], "confirm")) {
|
|
LogTasksDetail("Sending purge request");
|
|
auto pack = new ServerPacket(ServerOP_SharedTaskPurgeAllCommand, 0);
|
|
worldserver.SendPacket(pack);
|
|
safe_delete(pack);
|
|
return;
|
|
}
|
|
|
|
c->Message(
|
|
Chat::White,
|
|
fmt::format(
|
|
"[WARNING] This will purge all active Shared Tasks [{}]?",
|
|
Saylink::Silent("#task sharedpurge confirm", "confirm")
|
|
).c_str()
|
|
);
|
|
|
|
return;
|
|
} else if (is_show) {
|
|
target->ShowClientTasks(c);
|
|
return;
|
|
} else if (is_uncomplete) {
|
|
if (sep->IsNumber(2)) {
|
|
auto task_id = std::stoul(sep->arg[2]);
|
|
if (!task_id || task_id > MAXTASKS) {
|
|
c->Message(Chat::White, "Invalid task ID specified.");
|
|
return;
|
|
}
|
|
|
|
if (
|
|
CompletedTasksRepository::DeleteWhere(
|
|
database,
|
|
fmt::format(
|
|
"charid = {} AND taskid = {}",
|
|
target->CharacterID(),
|
|
task_id
|
|
)
|
|
)
|
|
) {
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"Successfully uncompleted task ID {} for {}.",
|
|
task_id,
|
|
c->GetTargetDescription(target)
|
|
).c_str()
|
|
);
|
|
} else {
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"{} {} not completed task ID {}.",
|
|
c->GetTargetDescription(target, TargetDescriptionType::UCYou),
|
|
c == target ? "have" : "has",
|
|
task_id
|
|
).c_str()
|
|
);
|
|
}
|
|
}
|
|
} else if (is_update) {
|
|
if (arguments >= 3) {
|
|
auto task_id = std::strtoul(sep->arg[2], nullptr, 10);
|
|
auto activity_id = std::strtoul(sep->arg[3], nullptr, 10);
|
|
int count = 1;
|
|
|
|
if (arguments >= 4) {
|
|
count = std::strtol(sep->arg[4], nullptr, 10);
|
|
if (count <= 0) {
|
|
count = 1;
|
|
}
|
|
}
|
|
|
|
c->Message(
|
|
Chat::Yellow,
|
|
fmt::format(
|
|
"Updating task ID {}, activity {} with a count of {} for {}.",
|
|
task_id,
|
|
activity_id,
|
|
count,
|
|
c->GetTargetDescription(target)
|
|
).c_str()
|
|
);
|
|
|
|
target->UpdateTaskActivity(task_id, activity_id, count);
|
|
target->ShowClientTasks(c);
|
|
}
|
|
}
|
|
}
|