mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 18:52:22 +00:00
[Tasks] Replace task goals with explicit fields (#2402)
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.
This commit is contained in:
@@ -142,7 +142,6 @@ SET(zone_sources
|
||||
task_client_state.cpp
|
||||
task_goal_list_manager.cpp
|
||||
task_manager.cpp
|
||||
task_proximity_manager.cpp
|
||||
tasks.cpp
|
||||
titles.cpp
|
||||
tradeskills.cpp
|
||||
@@ -268,7 +267,6 @@ SET(zone_headers
|
||||
task_client_state.h
|
||||
task_goal_list_manager.h
|
||||
task_manager.h
|
||||
task_proximity_manager.h
|
||||
tasks.h
|
||||
titles.h
|
||||
trap.h
|
||||
|
||||
+1
-1
@@ -2474,7 +2474,7 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
|
||||
give_exp_client->GetCleanName(),
|
||||
GetNPCTypeID()
|
||||
);
|
||||
task_manager->HandleUpdateTasksOnKill(give_exp_client, GetNPCTypeID(), this);
|
||||
task_manager->HandleUpdateTasksOnKill(give_exp_client, this);
|
||||
}
|
||||
|
||||
if (kr) {
|
||||
|
||||
+1
-1
@@ -1193,7 +1193,7 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
|
||||
parse->EventNPC(EVENT_SAY, tar->CastToNPC(), this, message, language);
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
if(UpdateTasksOnSpeakWith(tar->GetNPCTypeID())) {
|
||||
if (UpdateTasksOnSpeakWith(tar)) {
|
||||
tar->DoQuestPause(this);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-37
@@ -1139,48 +1139,32 @@ public:
|
||||
}
|
||||
inline void UpdateTasksForItem(
|
||||
TaskActivityType activity_type,
|
||||
NPC* npc,
|
||||
int item_id,
|
||||
int count = 1
|
||||
)
|
||||
{
|
||||
if (task_state) {
|
||||
task_state->UpdateTasksForItem(this, activity_type, item_id, count);
|
||||
task_state->UpdateTasksForItem(this, activity_type, npc, item_id, count);
|
||||
}
|
||||
}
|
||||
inline void UpdateTasksOnExplore(int explore_id)
|
||||
inline void UpdateTasksOnExplore(const glm::vec4& pos)
|
||||
{
|
||||
if (task_state) {
|
||||
task_state->UpdateTasksOnExplore(
|
||||
this,
|
||||
explore_id
|
||||
);
|
||||
task_state->UpdateTasksOnExplore(this, pos);
|
||||
}
|
||||
}
|
||||
inline bool UpdateTasksOnSpeakWith(int npc_type_id)
|
||||
inline bool UpdateTasksOnSpeakWith(NPC* npc)
|
||||
{
|
||||
if (task_state) {
|
||||
return task_state->UpdateTasksOnSpeakWith(
|
||||
this,
|
||||
npc_type_id
|
||||
);
|
||||
}
|
||||
else { return false; }
|
||||
return task_state && task_state->UpdateTasksOnSpeakWith(this, npc);
|
||||
}
|
||||
inline bool UpdateTasksOnDeliver(
|
||||
std::list<EQ::ItemInstance *> &items,
|
||||
int cash,
|
||||
int npc_type_id
|
||||
NPC* npc
|
||||
)
|
||||
{
|
||||
if (task_state) {
|
||||
return task_state->UpdateTasksOnDeliver(
|
||||
this,
|
||||
items,
|
||||
cash,
|
||||
npc_type_id
|
||||
);
|
||||
}
|
||||
else { return false; }
|
||||
return task_state && task_state->UpdateTasksOnDeliver(this, items, cash, npc);
|
||||
}
|
||||
void UpdateTasksOnTouchSwitch(int dz_switch_id)
|
||||
{
|
||||
@@ -1235,12 +1219,7 @@ public:
|
||||
inline void ProcessTaskProximities(float x, float y, float z)
|
||||
{
|
||||
if (task_state) {
|
||||
task_state->ProcessTaskProximities(
|
||||
this,
|
||||
x,
|
||||
y,
|
||||
z
|
||||
);
|
||||
task_state->ProcessTaskProximities(this, x, y, z);
|
||||
}
|
||||
}
|
||||
inline void AssignTask(
|
||||
@@ -1252,22 +1231,19 @@ public:
|
||||
task_state->AcceptNewTask(this, task_id, npc_id, std::time(nullptr), enforce_level_requirement);
|
||||
}
|
||||
}
|
||||
inline int ActiveSpeakTask(int npc_type_id)
|
||||
inline int ActiveSpeakTask(NPC* npc)
|
||||
{
|
||||
if (task_state) {
|
||||
return task_state->ActiveSpeakTask(npc_type_id);
|
||||
return task_state->ActiveSpeakTask(this, npc);
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
inline int ActiveSpeakActivity(int npc_type_id, int task_id)
|
||||
inline int ActiveSpeakActivity(NPC* npc, int task_id)
|
||||
{
|
||||
if (task_state) {
|
||||
return task_state->ActiveSpeakActivity(
|
||||
npc_type_id,
|
||||
task_id
|
||||
);
|
||||
return task_state->ActiveSpeakActivity(this, npc, task_id);
|
||||
}
|
||||
else { return 0; }
|
||||
}
|
||||
|
||||
+1
-1
@@ -1381,7 +1381,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
|
||||
|
||||
/* Update any tasks that have an activity to loot this item */
|
||||
if (RuleB(TaskSystem, EnableTaskSystem))
|
||||
client->UpdateTasksForItem(TaskActivityType::Loot, item->ID);
|
||||
client->UpdateTasksForItem(TaskActivityType::Loot, IsNPCCorpse() ? CastToNPC() : nullptr, item->ID);
|
||||
|
||||
/* Remove it from Corpse */
|
||||
if (item_data) {
|
||||
|
||||
@@ -1162,11 +1162,6 @@ void Perl__resettaskactivity(int task_id, int activity_id)
|
||||
quest_manager.resettaskactivity(task_id, activity_id);
|
||||
}
|
||||
|
||||
void Perl__taskexploredarea(int explore_id)
|
||||
{
|
||||
quest_manager.taskexploredarea(explore_id);
|
||||
}
|
||||
|
||||
void Perl__assigntask(int task_id)
|
||||
{
|
||||
quest_manager.assigntask(task_id);
|
||||
@@ -4238,7 +4233,6 @@ void perl_register_quest()
|
||||
package.add("summonitem", (void(*)(int, int))&Perl__summonitem);
|
||||
package.add("surname", &Perl__surname);
|
||||
package.add("targlobal", &Perl__targlobal);
|
||||
package.add("taskexploredarea", &Perl__taskexploredarea);
|
||||
package.add("taskselector", &Perl__taskselector);
|
||||
package.add("task_setselector", &Perl__task_setselector);
|
||||
package.add("tasktimeleft", &Perl__tasktimeleft);
|
||||
|
||||
+2
-2
@@ -367,7 +367,7 @@ void Client::GoFish()
|
||||
PushItemOnCursor(*inst);
|
||||
SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketLimbo);
|
||||
if (RuleB(TaskSystem, EnableTaskSystem))
|
||||
UpdateTasksForItem(TaskActivityType::Fish, food_id);
|
||||
UpdateTasksForItem(TaskActivityType::Fish, nullptr, food_id);
|
||||
|
||||
safe_delete(inst);
|
||||
inst = m_inv.GetItem(EQ::invslot::slotCursor);
|
||||
@@ -486,7 +486,7 @@ void Client::ForageItem(bool guarantee) {
|
||||
PushItemOnCursor(*inst);
|
||||
SendItemPacket(EQ::invslot::slotCursor, inst, ItemPacketLimbo);
|
||||
if(RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
UpdateTasksForItem(TaskActivityType::Forage, foragedfood);
|
||||
UpdateTasksForItem(TaskActivityType::Forage, nullptr, foragedfood);
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
|
||||
@@ -45,13 +45,6 @@ void command_task(Client *c, const Seperator *sep)
|
||||
Saylink::Silent("#task reload lists", "reload lists")
|
||||
).c_str()
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"--- [{}] Reload proximity information",
|
||||
Saylink::Silent("#task reload prox", "reload prox")
|
||||
).c_str()
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -139,13 +132,6 @@ void command_task(Client *c, const Seperator *sep)
|
||||
Saylink::Silent("#task reload lists", "reload lists")
|
||||
).c_str()
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"--- [{}] Reload proximity information",
|
||||
Saylink::Silent("#task reload prox", "reload prox")
|
||||
).c_str()
|
||||
);
|
||||
c->Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
@@ -210,11 +196,6 @@ void command_task(Client *c, const Seperator *sep)
|
||||
worldserver.SendReloadTasks(RELOADTASKGOALLISTS);
|
||||
c->Message(Chat::Yellow, "Successfully reloaded goal lists.");
|
||||
return;
|
||||
} else if (!strcasecmp(sep->arg[2], "prox")) {
|
||||
c->Message(Chat::Yellow, "Attempting to reload task proximites.");
|
||||
worldserver.SendReloadTasks(RELOADTASKPROXIMITIES);
|
||||
c->Message(Chat::Yellow, "Successfully reloaded task proximites.");
|
||||
return;
|
||||
} else if (!strcasecmp(sep->arg[2], "sets")) {
|
||||
c->Message(Chat::Yellow, "Attempting to reload task sets.");
|
||||
worldserver.SendReloadTasks(RELOADTASKSETS);
|
||||
|
||||
@@ -699,10 +699,6 @@ void lua_reset_task_activity(int task, int activity) {
|
||||
quest_manager.resettaskactivity(task, activity);
|
||||
}
|
||||
|
||||
void lua_task_explored_area(int explore_id) {
|
||||
quest_manager.taskexploredarea(explore_id);
|
||||
}
|
||||
|
||||
void lua_assign_task(int task_id) {
|
||||
quest_manager.assigntask(task_id);
|
||||
}
|
||||
@@ -3717,7 +3713,6 @@ luabind::scope lua_register_general() {
|
||||
luabind::def("get_task_activity_done_count", &lua_get_task_activity_done_count),
|
||||
luabind::def("update_task_activity", &lua_update_task_activity),
|
||||
luabind::def("reset_task_activity", &lua_reset_task_activity),
|
||||
luabind::def("task_explored_area", &lua_task_explored_area),
|
||||
luabind::def("assign_task", &lua_assign_task),
|
||||
luabind::def("fail_task", &lua_fail_task),
|
||||
luabind::def("task_time_left", &lua_task_time_left),
|
||||
|
||||
+5
-12
@@ -2363,13 +2363,6 @@ void QuestManager::resettaskactivity(int task, int activity) {
|
||||
initiator->ResetTaskActivity(task, activity);
|
||||
}
|
||||
|
||||
void QuestManager::taskexploredarea(int exploreid) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem) && initiator)
|
||||
initiator->UpdateTasksOnExplore(exploreid);
|
||||
}
|
||||
|
||||
void QuestManager::assigntask(int taskid, bool enforce_level_requirement) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
|
||||
@@ -2432,16 +2425,16 @@ int QuestManager::nexttaskinset(int taskset, int taskid) {
|
||||
int QuestManager::activespeaktask() {
|
||||
QuestManagerCurrentQuestVars();
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner)
|
||||
return initiator->ActiveSpeakTask(owner->GetNPCTypeID());
|
||||
if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && owner->IsNPC())
|
||||
return initiator->ActiveSpeakTask(owner->CastToNPC());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QuestManager::activespeakactivity(int taskid) {
|
||||
QuestManagerCurrentQuestVars();
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner)
|
||||
return initiator->ActiveSpeakActivity(owner->GetNPCTypeID(), taskid);
|
||||
if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && owner->IsNPC())
|
||||
return initiator->ActiveSpeakActivity(owner->CastToNPC(), taskid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3720,4 +3713,4 @@ void QuestManager::LearnRecipe(uint32 recipe_id) {
|
||||
}
|
||||
|
||||
initiator->LearnRecipe(recipe_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,6 @@ public:
|
||||
int gettaskactivitydonecount(int task, int activity);
|
||||
void updatetaskactivity(int task, int activity, int count, bool ignore_quest_update = false);
|
||||
void resettaskactivity(int task, int activity);
|
||||
void taskexploredarea(int exploreid);
|
||||
void assigntask(int taskid, bool enforce_level_requirement = false);
|
||||
void failtask(int taskid);
|
||||
int tasktimeleft(int taskid);
|
||||
|
||||
+266
-467
@@ -364,11 +364,11 @@ static void DeleteCompletedTaskFromDatabase(int character_id, int task_id)
|
||||
);
|
||||
}
|
||||
|
||||
bool ClientTaskState::UnlockActivities(int character_id, ClientTaskInformation &task_info)
|
||||
bool ClientTaskState::UnlockActivities(Client* client, ClientTaskInformation& task_info)
|
||||
{
|
||||
LogTasksDetail(
|
||||
"[UnlockActivities] Fetching task info for character_id [{}] task [{}] slot [{}] accepted_time [{}] updated [{}]",
|
||||
character_id,
|
||||
client->CharacterID(),
|
||||
task_info.task_id,
|
||||
task_info.slot,
|
||||
task_info.accepted_time,
|
||||
@@ -386,7 +386,7 @@ bool ClientTaskState::UnlockActivities(int character_id, ClientTaskInformation &
|
||||
if (task_info.activity[i].activity_id >= 0) {
|
||||
LogTasksDetail(
|
||||
"[UnlockActivities] character_id [{}] task [{}] activity_id [{}] done_count [{}] activity_state [{}] updated [{}]",
|
||||
character_id,
|
||||
client->CharacterID(),
|
||||
task_info.task_id,
|
||||
task_info.activity[i].activity_id,
|
||||
task_info.activity[i].done_count,
|
||||
@@ -411,9 +411,12 @@ bool ClientTaskState::UnlockActivities(int character_id, ClientTaskInformation &
|
||||
|
||||
if (res.is_task_complete && RuleB(TaskSystem, RecordCompletedTasks))
|
||||
{
|
||||
RecordCompletedTask(character_id, *task, task_info);
|
||||
RecordCompletedTask(client->CharacterID(), *task, task_info);
|
||||
}
|
||||
|
||||
// check if client has an explore task in current zone to enable task explore processing
|
||||
m_has_explore_task = HasExploreTask(client);
|
||||
|
||||
return res.is_task_complete;
|
||||
}
|
||||
|
||||
@@ -456,188 +459,237 @@ void ClientTaskState::RecordCompletedTask(uint32_t character_id, const TaskInfor
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientTaskState::UpdateTasksOnSpeakWith(Client *client, int npc_type_id)
|
||||
const TaskInformation* ClientTaskState::GetTaskData(const ClientTaskInformation& client_task) const
|
||||
{
|
||||
return UpdateTasksByNPC(client, TaskActivityType::SpeakWith, npc_type_id);
|
||||
if (client_task.task_id == TASKSLOTEMPTY)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return task_manager->m_task_data[client_task.task_id];
|
||||
}
|
||||
|
||||
bool ClientTaskState::UpdateTasksByNPC(Client *client, TaskActivityType activity_type, int npc_type_id)
|
||||
bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter, int task_id,
|
||||
const ActivityInformation& activity, const ClientActivityInformation& client_activity) const
|
||||
{
|
||||
|
||||
int is_updating = false;
|
||||
|
||||
if (!HasActiveTasks()) {
|
||||
if (activity.goal_method == METHODQUEST && activity.goal_method != filter.method)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
// todo: some tasks do allow hidden/unlocked elements to silently update
|
||||
if (client_activity.activity_state != ActivityActive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if there are any active kill activities for this p_task_data
|
||||
auto p_task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
if (activity.activity_type != filter.type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (activity.dz_switch_id != 0 && activity.dz_switch_id != filter.dz_switch_id)
|
||||
{
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (activity.has_area && !filter.ignore_area && RuleB(TaskSystem, EnableTaskProximity))
|
||||
{
|
||||
const glm::vec4& pos = filter.use_pos ? filter.pos : client->GetPosition();
|
||||
if (pos.x < activity.min_x || pos.x > activity.max_x ||
|
||||
pos.y < activity.min_y || pos.y > activity.max_y ||
|
||||
pos.z < activity.min_z || pos.z > activity.max_z)
|
||||
{
|
||||
LogTasksDetail("[CanUpdate] client [{}] task [{}]-[{}] failed area filter", client->GetName(), task_id, client_activity.activity_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
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;
|
||||
}
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
// We are only interested in Kill activities
|
||||
if (activity_info->activity_type != activity_type) {
|
||||
continue;
|
||||
}
|
||||
// Is there a zone restriction on the activity_information ?
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
LogTasks(
|
||||
"[UPDATE] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check",
|
||||
client->GetName(),
|
||||
current_task->task_id,
|
||||
activity_id,
|
||||
static_cast<int32_t>(activity_type),
|
||||
npc_type_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information to kill this type of NPC ?
|
||||
switch (activity_info->goal_method) {
|
||||
case METHODSINGLEID:
|
||||
if (activity_info->goal_id != npc_type_id) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
if (!activity.item_id_list.empty() && filter.item_id != 0 &&
|
||||
!TaskGoalListManager::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;
|
||||
}
|
||||
|
||||
case METHODLIST:
|
||||
if (!task_manager->m_goal_list_manager.IsInList(
|
||||
activity_info->goal_id,
|
||||
npc_type_id
|
||||
) && !TaskGoalListManager::IsInMatchList(
|
||||
activity_info->goal_match_list,
|
||||
std::to_string(npc_type_id)
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
// If METHODQUEST, don't updated the activity_information here
|
||||
continue;
|
||||
// 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())))))
|
||||
{
|
||||
LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed npc match filter", client->GetName(), task_id, client_activity.activity_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientTaskState::UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count)
|
||||
{
|
||||
if (!task_manager)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool any_updated = false;
|
||||
|
||||
for (const auto& client_task : m_active_tasks)
|
||||
{
|
||||
const TaskInformation* task = GetTaskData(client_task);
|
||||
if (!task)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// legacy eqemu task update logic loops through group on kill of npc to update a single task
|
||||
// shared tasks only require one client to receive an update to propagate
|
||||
if (filter.type == TaskActivityType::Kill && task->type == TaskType::Shared && client != filter.exp_client)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const ClientActivityInformation& client_activity : client_task.activity)
|
||||
{
|
||||
const ActivityInformation& activity = task->activity_information[client_activity.activity_id];
|
||||
|
||||
if (CanUpdate(client, filter, client_task.task_id, activity, client_activity))
|
||||
{
|
||||
LogTasks("[UpdateTasks] client [{}] task [{}] activity [{}] increment [{}]",
|
||||
client->GetName(), client_task.task_id, client_activity.activity_id, count);
|
||||
|
||||
IncrementDoneCount(client, task, client_task.slot, client_activity.activity_id, count);
|
||||
any_updated = true;
|
||||
break; // only one element updated per task, move to next task
|
||||
}
|
||||
// We found an active p_task_data to kill this type of NPC, so increment the done count
|
||||
LogTasksDetail("Calling increment done count ByNPC");
|
||||
IncrementDoneCount(client, p_task_data, current_task->slot, activity_id);
|
||||
is_updating = true;
|
||||
}
|
||||
}
|
||||
|
||||
return is_updating;
|
||||
return any_updated;
|
||||
}
|
||||
|
||||
int ClientTaskState::ActiveSpeakTask(int npc_type_id)
|
||||
std::pair<int, int> ClientTaskState::FindTask(Client* client, const TaskUpdateFilter& filter) const
|
||||
{
|
||||
if (!task_manager)
|
||||
{
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
for (const auto& client_task : m_active_tasks)
|
||||
{
|
||||
const TaskInformation* task = GetTaskData(client_task);
|
||||
if (!task || (filter.task_id != 0 && client_task.task_id != filter.task_id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const ClientActivityInformation& client_activity : client_task.activity)
|
||||
{
|
||||
const ActivityInformation& activity = task->activity_information[client_activity.activity_id];
|
||||
if (CanUpdate(client, filter, client_task.task_id, activity, client_activity))
|
||||
{
|
||||
return std::make_pair(client_task.task_id, client_activity.activity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
bool ClientTaskState::HasExploreTask(Client* client) const
|
||||
{
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = TaskActivityType::Explore;
|
||||
filter.ignore_area = true; // we don't care if client is currently in the explore area
|
||||
|
||||
auto result = FindTask(client, filter);
|
||||
bool has_explore = result.first != 0;
|
||||
|
||||
LogTasksDetail("[HasExploreTask] client [{}] has explore task in current zone [{}]", client->GetName(), has_explore);
|
||||
return has_explore;
|
||||
}
|
||||
|
||||
bool ClientTaskState::UpdateTasksOnSpeakWith(Client* client, NPC* npc)
|
||||
{
|
||||
return UpdateTasksByNPC(client, TaskActivityType::SpeakWith, npc);
|
||||
}
|
||||
|
||||
bool ClientTaskState::UpdateTasksByNPC(Client* client, TaskActivityType type, NPC* npc)
|
||||
{
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = type;
|
||||
filter.npc = npc;
|
||||
|
||||
return UpdateTasks(client, filter);
|
||||
}
|
||||
|
||||
int ClientTaskState::ActiveSpeakTask(Client* client, NPC* npc)
|
||||
{
|
||||
// This method is to be used from Perl quests only and returns the task_id of the first
|
||||
// active task found which has an active SpeakWith activity_information for this NPC.
|
||||
if (!HasActiveTasks()) {
|
||||
return 0;
|
||||
}
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = TaskActivityType::SpeakWith;
|
||||
filter.npc = npc;
|
||||
filter.method = METHODQUEST;
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
if (activity_info->activity_type != TaskActivityType::SpeakWith) {
|
||||
continue;
|
||||
}
|
||||
// Is there a zone restriction on the activity_information ?
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information to speak with this type of NPC ?
|
||||
if (activity_info->goal_method == METHODQUEST && activity_info->goal_id == npc_type_id) {
|
||||
return current_task->task_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
auto result = FindTask(client, filter);
|
||||
return result.first; // task id
|
||||
}
|
||||
|
||||
int ClientTaskState::ActiveSpeakActivity(int npc_type_id, int task_id)
|
||||
int ClientTaskState::ActiveSpeakActivity(Client* client, NPC* npc, int task_id)
|
||||
{
|
||||
|
||||
// This method is to be used from Perl quests only and returns the activity_id of the first
|
||||
// active activity_information found in the specified task which is to SpeakWith this NPC.
|
||||
if (!HasActiveTasks()) {
|
||||
return -1;
|
||||
}
|
||||
if (task_id <= 0 || task_id >= MAXTASKS) {
|
||||
|
||||
if (task_id <= 0 || task_id >= MAXTASKS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id != task_id) {
|
||||
continue;
|
||||
}
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = TaskActivityType::SpeakWith;
|
||||
filter.npc = npc;
|
||||
filter.method = METHODQUEST;
|
||||
filter.task_id = task_id;
|
||||
|
||||
TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
if (activity_info->activity_type != TaskActivityType::SpeakWith) {
|
||||
continue;
|
||||
}
|
||||
// Is there a zone restriction on the activity_information ?
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is the activity_information to speak with this type of NPC ?
|
||||
if (activity_info->goal_method == METHODQUEST && activity_info->goal_id == npc_type_id) {
|
||||
return activity_id;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
auto result = FindTask(client, filter);
|
||||
return result.first != 0 ? result.second : -1; // activity id
|
||||
}
|
||||
|
||||
void ClientTaskState::UpdateTasksForItem(Client *client, TaskActivityType activity_type, int item_id, int count)
|
||||
void ClientTaskState::UpdateTasksForItem(Client* client, TaskActivityType type, NPC* npc, int item_id, int count)
|
||||
{
|
||||
|
||||
// This method updates the client's task activities of the specified type which relate
|
||||
@@ -645,269 +697,62 @@ void ClientTaskState::UpdateTasksForItem(Client *client, TaskActivityType activi
|
||||
//
|
||||
// Type should be one of ActivityLoot, ActivityTradeSkill, ActivityFish or ActivityForage
|
||||
|
||||
// If the client has no tasks, there is nothing further to check.
|
||||
LogTasks("[UpdateTasksForItem] activity_type [{}] item_id [{}]", static_cast<int>(type), item_id);
|
||||
|
||||
LogTasks(
|
||||
"[UpdateTasksForItem] activity_type [{}] item_id [{}]",
|
||||
static_cast<int32_t>(activity_type),
|
||||
item_id
|
||||
);
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = type;
|
||||
filter.npc = npc; // looting may filter on npc id or name
|
||||
filter.item_id = item_id;
|
||||
|
||||
if (!HasActiveTasks()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there are any active loot activities for this task
|
||||
|
||||
TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
// We are only interested in the ActivityType we were called with
|
||||
if (activity_info->activity_type != activity_type) {
|
||||
continue;
|
||||
}
|
||||
// Is there a zone restriction on the activity_information ?
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
LogTasks(
|
||||
"[UpdateTasksForItem] Error: Character [{}] activity_information type [{}] for Item [{}] failed zone check",
|
||||
client->GetName(),
|
||||
static_cast<int32_t>(activity_type),
|
||||
item_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information related to this item ?
|
||||
//
|
||||
switch (activity_info->goal_method) {
|
||||
|
||||
case METHODSINGLEID:
|
||||
if (activity_info->goal_id != item_id) { continue; }
|
||||
break;
|
||||
|
||||
case METHODLIST:
|
||||
if (!task_manager->m_goal_list_manager.IsInList(
|
||||
activity_info->goal_id,
|
||||
item_id
|
||||
) && !TaskGoalListManager::IsInMatchList(
|
||||
activity_info->goal_match_list,
|
||||
std::to_string(item_id)
|
||||
)) { continue; }
|
||||
break;
|
||||
|
||||
default:
|
||||
// If METHODQUEST, don't updated the activity_information here
|
||||
continue;
|
||||
}
|
||||
// We found an active task related to this item, so increment the done count
|
||||
LogTasksDetail("[UpdateTasksForItem] Calling increment done count ForItem");
|
||||
IncrementDoneCount(client, p_task_data, current_task->slot, activity_id, count);
|
||||
}
|
||||
}
|
||||
UpdateTasks(client, filter, count);
|
||||
}
|
||||
|
||||
void ClientTaskState::UpdateTasksOnExplore(Client *client, int explore_id)
|
||||
void ClientTaskState::UpdateTasksOnExplore(Client* client, const glm::vec4& pos)
|
||||
{
|
||||
LogTasks("[UpdateTasksOnExplore] explore_id [{}]", explore_id);
|
||||
LogTasksDetail("[UpdateTasksOnExplore] client [{}]", client->GetName());
|
||||
|
||||
if (!HasActiveTasks()) {
|
||||
return;
|
||||
}
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = TaskActivityType::Explore;
|
||||
filter.pos = pos;
|
||||
filter.use_pos = true;
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there are any active explore activities for this task
|
||||
|
||||
TaskInformation *task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (task_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
// We are only interested in explore activities
|
||||
if (activity_info->activity_type != TaskActivityType::Explore) {
|
||||
continue;
|
||||
}
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
LogTasks(
|
||||
"[UpdateTasksOnExplore] character [{}] explore_id [{}] failed zone check",
|
||||
client->GetName(),
|
||||
explore_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information to explore this area id ?
|
||||
switch (activity_info->goal_method) {
|
||||
|
||||
case METHODSINGLEID:
|
||||
if (activity_info->goal_id != explore_id) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case METHODLIST:
|
||||
if (!task_manager->m_goal_list_manager.IsInList(
|
||||
activity_info->goal_id,
|
||||
explore_id
|
||||
) && !TaskGoalListManager::IsInMatchList(
|
||||
activity_info->goal_match_list,
|
||||
std::to_string(explore_id)
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// If METHODQUEST, don't updated the activity_information here
|
||||
continue;
|
||||
}
|
||||
|
||||
// We found an active task to explore this area, so set done count to goal count
|
||||
// (Only a goal count of 1 makes sense for explore activities?)
|
||||
LogTasks(
|
||||
"[UpdateTasksOnExplore] character [{}] explore_id [{}] increment on explore",
|
||||
client->GetName(),
|
||||
explore_id
|
||||
);
|
||||
|
||||
IncrementDoneCount(
|
||||
client,
|
||||
task_data,
|
||||
current_task->slot,
|
||||
activity_id,
|
||||
activity_info->goal_count - current_task->activity[activity_id].done_count
|
||||
);
|
||||
}
|
||||
}
|
||||
UpdateTasks(client, filter);
|
||||
}
|
||||
|
||||
bool ClientTaskState::UpdateTasksOnDeliver(
|
||||
Client *client,
|
||||
std::list<EQ::ItemInstance *> &items,
|
||||
int cash,
|
||||
int npc_type_id
|
||||
NPC* npc
|
||||
)
|
||||
{
|
||||
LogTasks("[UpdateTasksOnDeliver] npc [{}]", npc->GetName());
|
||||
|
||||
bool is_updated = false;
|
||||
|
||||
LogTasks("[UpdateTasksOnDeliver] [{}]", npc_type_id);
|
||||
TaskUpdateFilter filter{};
|
||||
filter.npc = npc;
|
||||
|
||||
if (!HasActiveTasks()) {
|
||||
return false;
|
||||
if (cash != 0)
|
||||
{
|
||||
filter.type = TaskActivityType::GiveCash;
|
||||
if (UpdateTasks(client, filter, cash))
|
||||
{
|
||||
// todo: remove used coin and use Deliver with explicit coin fields instead of custom type
|
||||
is_updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (int i = 0; i < MAXACTIVEQUESTS + 1; i++) {
|
||||
auto current_task = &m_active_tasks[i];
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
filter.type = TaskActivityType::Deliver;
|
||||
for (EQ::ItemInstance* item : items)
|
||||
{
|
||||
filter.item_id = item->GetID();
|
||||
|
||||
// Check if there are any active deliver activities for this task
|
||||
TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We are only interested in Deliver activities
|
||||
if (activity_info->activity_type != TaskActivityType::Deliver &&
|
||||
activity_info->activity_type != TaskActivityType::GiveCash) {
|
||||
continue;
|
||||
}
|
||||
// Is there a zone restriction on the activity_information ?
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
Log(
|
||||
Logs::General, Logs::Tasks,
|
||||
"[UPDATE] Char: %s Deliver activity_information failed zone check (current zone %i, need zone "
|
||||
"%s",
|
||||
client->GetName(), zone->GetZoneID(), activity_info->zones.c_str());
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information to deliver to this NPCTypeID ?
|
||||
if (activity_info->deliver_to_npc != npc_type_id) {
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information related to these items ?
|
||||
//
|
||||
if ((activity_info->activity_type == TaskActivityType::GiveCash) && cash) {
|
||||
LogTasks("[UpdateTasksOnDeliver] Increment on GiveCash");
|
||||
IncrementDoneCount(client, p_task_data, i, activity_id, cash);
|
||||
is_updated = true;
|
||||
}
|
||||
else {
|
||||
for (auto &item : items) {
|
||||
switch (activity_info->goal_method) {
|
||||
case METHODSINGLEID:
|
||||
if (activity_info->goal_id != item->GetID()) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case METHODLIST:
|
||||
if (!task_manager->m_goal_list_manager.IsInList(
|
||||
activity_info->goal_id,
|
||||
item->GetID()
|
||||
) && !TaskGoalListManager::IsInMatchList(
|
||||
activity_info->goal_match_list,
|
||||
std::to_string(item->GetID())
|
||||
)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// If METHODQUEST, don't updated the activity_information here
|
||||
continue;
|
||||
}
|
||||
// We found an active task related to this item, so increment the done count
|
||||
LogTasks("[UpdateTasksOnDeliver] Increment on GiveItem");
|
||||
IncrementDoneCount(
|
||||
client,
|
||||
p_task_data,
|
||||
current_task->slot,
|
||||
activity_id,
|
||||
item->GetCharges() <= 0 ? 1 : item->GetCharges()
|
||||
);
|
||||
is_updated = true;
|
||||
}
|
||||
}
|
||||
int count = item->IsStackable() ? item->GetCharges() : 1;
|
||||
if (UpdateTasks(client, filter, count))
|
||||
{
|
||||
// todo: remove items used in update (highest in case multiple tasks consume same item)
|
||||
is_updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,69 +761,30 @@ bool ClientTaskState::UpdateTasksOnDeliver(
|
||||
|
||||
void ClientTaskState::UpdateTasksOnTouch(Client *client, int dz_switch_id)
|
||||
{
|
||||
// If the client has no tasks, there is nothing further to check.
|
||||
LogTasks("[UpdateTasksOnTouch] dz switch [{}] ", dz_switch_id);
|
||||
|
||||
LogTasks("[UpdateTasksOnTouch] [{}] ", dz_switch_id);
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = TaskActivityType::Touch;
|
||||
filter.dz_switch_id = dz_switch_id;
|
||||
|
||||
if (!HasActiveTasks()) {
|
||||
return;
|
||||
}
|
||||
UpdateTasks(client, filter);
|
||||
}
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
void ClientTaskState::UpdateTasksOnKill(Client* client, Client* exp_client, NPC* npc)
|
||||
{
|
||||
TaskUpdateFilter filter{};
|
||||
filter.type = TaskActivityType::Kill;
|
||||
filter.npc = npc;
|
||||
filter.pos = npc->GetPosition(); // or should areas be filtered by client position?
|
||||
filter.use_pos = true;
|
||||
filter.exp_client = exp_client;
|
||||
|
||||
// Check if there are any active explore activities for this task
|
||||
TaskInformation *p_task_data = task_manager->m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (current_task->activity[activity_id].activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
// We are only interested in touch activities
|
||||
if (activity_info->activity_type != TaskActivityType::Touch) {
|
||||
continue;
|
||||
}
|
||||
if (activity_info->goal_method != METHODSINGLEID) {
|
||||
continue;
|
||||
}
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
LogTasks(
|
||||
"[UpdateTasksOnTouch] character [{}] Touch activity_information failed zone check",
|
||||
client->GetName()
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (activity_info->goal_id != dz_switch_id) {
|
||||
continue;
|
||||
}
|
||||
// We found an active task to zone into this zone, so set done count to goal count
|
||||
// (Only a goal count of 1 makes sense for touch activities?)
|
||||
LogTasks("[UpdateTasksOnTouch] Increment on Touch");
|
||||
IncrementDoneCount(
|
||||
client,
|
||||
p_task_data,
|
||||
current_task->slot,
|
||||
activity_id,
|
||||
activity_info->goal_count - current_task->activity[activity_id].done_count
|
||||
);
|
||||
}
|
||||
}
|
||||
UpdateTasks(client, filter);
|
||||
}
|
||||
|
||||
void ClientTaskState::IncrementDoneCount(
|
||||
Client *client,
|
||||
TaskInformation *task_information,
|
||||
const TaskInformation* task_information,
|
||||
int task_index,
|
||||
int activity_id,
|
||||
int count,
|
||||
@@ -1024,7 +830,7 @@ void ClientTaskState::IncrementDoneCount(
|
||||
|
||||
SyncSharedTaskZoneClientDoneCountState(
|
||||
client,
|
||||
task_information,
|
||||
task_information->type,
|
||||
task_index,
|
||||
activity_id,
|
||||
r->done_count
|
||||
@@ -1065,7 +871,7 @@ void ClientTaskState::IncrementDoneCount(
|
||||
// Flag the activity_information as complete
|
||||
info->activity[activity_id].activity_state = ActivityCompleted;
|
||||
// Unlock subsequent activities for this task
|
||||
bool task_complete = UnlockActivities(client->CharacterID(), *info);
|
||||
bool task_complete = UnlockActivities(client, *info);
|
||||
LogTasks("[IncrementDoneCount] task_complete is [{}]", task_complete);
|
||||
// and by the 'Task Stage Completed' message
|
||||
client->SendTaskActivityComplete(info->task_id, activity_id, task_index, task_information->type);
|
||||
@@ -1159,7 +965,7 @@ void ClientTaskState::DispatchEventTaskComplete(Client* client, ClientTaskInform
|
||||
parse->EventPlayer(EVENT_TASK_COMPLETE, client, export_string, 0);
|
||||
}
|
||||
|
||||
void ClientTaskState::RewardTask(Client *client, TaskInformation *task_information, ClientTaskInformation& client_task)
|
||||
void ClientTaskState::RewardTask(Client *client, const TaskInformation *task_information, ClientTaskInformation& client_task)
|
||||
{
|
||||
|
||||
if (!task_information || !client || client_task.was_rewarded) {
|
||||
@@ -2000,6 +1806,7 @@ void ClientTaskState::CancelTask(Client *c, int sequence_number, TaskType task_t
|
||||
// persistence
|
||||
if (remove_from_db) {
|
||||
RemoveTask(c, sequence_number, task_type);
|
||||
m_has_explore_task = HasExploreTask(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2281,7 +2088,7 @@ void ClientTaskState::AcceptNewTask(
|
||||
active_slot->activity[activity_id].updated = true;
|
||||
}
|
||||
|
||||
UnlockActivities(client->CharacterID(), *active_slot);
|
||||
UnlockActivities(client, *active_slot);
|
||||
|
||||
if (task->type == TaskType::Quest) {
|
||||
m_active_task_count++;
|
||||
@@ -2332,6 +2139,10 @@ void ClientTaskState::AcceptNewTask(
|
||||
|
||||
void ClientTaskState::ProcessTaskProximities(Client *client, float x, float y, float z)
|
||||
{
|
||||
if (!m_has_explore_task) {
|
||||
return;
|
||||
}
|
||||
|
||||
float last_x = client->ProximityX();
|
||||
float last_y = client->ProximityY();
|
||||
float last_z = client->ProximityZ();
|
||||
@@ -2340,19 +2151,7 @@ void ClientTaskState::ProcessTaskProximities(Client *client, float x, float y, f
|
||||
return;
|
||||
}
|
||||
|
||||
LogTasksDetail("[ProcessTaskProximities] Checking proximities for Position x[{}] y[{}] z[{}]", x, y, z);
|
||||
int explore_id = task_manager->m_proximity_manager.CheckProximities(x, y, z);
|
||||
if (explore_id > 0) {
|
||||
LogTasksDetail(
|
||||
"[ProcessTaskProximities] Position x[{}] y[{}] z[{}] is within proximity explore_id [{}]",
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
explore_id
|
||||
);
|
||||
|
||||
UpdateTasksOnExplore(client, explore_id);
|
||||
}
|
||||
UpdateTasksOnExplore(client, glm::vec4(x, y, z, 0.0f));
|
||||
}
|
||||
|
||||
void ClientTaskState::SharedTaskIncrementDoneCount(
|
||||
@@ -2505,7 +2304,7 @@ void ClientTaskState::ListTaskTimers(Client* client)
|
||||
}
|
||||
}
|
||||
|
||||
void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& client_task, TaskInformation& task)
|
||||
void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& client_task, const TaskInformation& task)
|
||||
{
|
||||
if (task.replay_timer_seconds > 0)
|
||||
{
|
||||
@@ -2557,7 +2356,7 @@ void ClientTaskState::AddReplayTimer(Client* client, ClientTaskInformation& clie
|
||||
// zone-level before sending updates to world
|
||||
void ClientTaskState::SyncSharedTaskZoneClientDoneCountState(
|
||||
Client *p_client,
|
||||
TaskInformation *p_information,
|
||||
TaskType type,
|
||||
int task_index,
|
||||
int activity_id,
|
||||
uint32 done_count
|
||||
@@ -2566,7 +2365,7 @@ void ClientTaskState::SyncSharedTaskZoneClientDoneCountState(
|
||||
for (auto &e : entity_list.GetClientList()) {
|
||||
auto c = e.second;
|
||||
if (c->GetSharedTaskId() == p_client->GetSharedTaskId()) {
|
||||
auto t = c->GetTaskState()->GetClientTaskInfo(p_information->type, task_index);
|
||||
auto t = c->GetTaskState()->GetClientTaskInfo(type, task_index);
|
||||
if (t == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
+36
-14
@@ -16,6 +16,20 @@ struct TaskOffer
|
||||
uint16_t npc_entity_id;
|
||||
};
|
||||
|
||||
struct TaskUpdateFilter
|
||||
{
|
||||
int task_id = 0;
|
||||
int dz_switch_id = 0;
|
||||
uint32_t item_id = 0;
|
||||
glm::vec4 pos;
|
||||
bool use_pos = false; // if true uses pos instead of client position for area filters
|
||||
bool ignore_area = false; // if true, area check is disabled
|
||||
NPC* npc = nullptr;
|
||||
Client* exp_client = nullptr; // used by Kill tasks to filter shared task updates
|
||||
TaskActivityType type = TaskActivityType::None;
|
||||
TaskMethodType method = TaskMethodType::METHODSINGLEID;
|
||||
};
|
||||
|
||||
class ClientTaskState {
|
||||
|
||||
public:
|
||||
@@ -41,23 +55,23 @@ public:
|
||||
void CancelAllTasks(Client *client);
|
||||
void RemoveTask(Client *client, int sequence_number, TaskType task_type);
|
||||
void RemoveTaskByTaskID(Client *client, uint32 task_id);
|
||||
bool UpdateTasksByNPC(Client *client, TaskActivityType activity_type, int npc_type_id);
|
||||
void UpdateTasksForItem(Client *client, TaskActivityType activity_type, int item_id, int count = 1);
|
||||
void UpdateTasksOnExplore(Client *client, int explore_id);
|
||||
bool UpdateTasksOnSpeakWith(Client *client, int npc_type_id);
|
||||
bool UpdateTasksOnDeliver(Client *client, std::list<EQ::ItemInstance *> &items, int cash, int npc_type_id);
|
||||
bool UpdateTasksByNPC(Client* client, TaskActivityType type, NPC* npc);
|
||||
void UpdateTasksForItem(Client* client, TaskActivityType type, NPC* npc, int item_id, int count = 1);
|
||||
void UpdateTasksOnExplore(Client* client, const glm::vec4& loc);
|
||||
bool UpdateTasksOnSpeakWith(Client* client, NPC* npc);
|
||||
bool UpdateTasksOnDeliver(Client* client, std::list<EQ::ItemInstance*>& items, int cash, NPC* npc);
|
||||
void UpdateTasksOnTouch(Client *client, int dz_switch_id);
|
||||
void ProcessTaskProximities(Client *client, float x, float y, float z);
|
||||
bool TaskOutOfTime(TaskType task_type, int index);
|
||||
void TaskPeriodicChecks(Client *client);
|
||||
void SendTaskHistory(Client *client, int task_index);
|
||||
void RewardTask(Client *client, TaskInformation *task_information, ClientTaskInformation& client_task);
|
||||
void RewardTask(Client* client, const TaskInformation* task_information, 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);
|
||||
int EnabledTaskCount(int task_set_id);
|
||||
int ActiveSpeakTask(int npc_type_id);
|
||||
int ActiveSpeakActivity(int npc_type_id, int task_id);
|
||||
int ActiveSpeakTask(Client* client, NPC* npc);
|
||||
int ActiveSpeakActivity(Client* client, NPC* npc, int task_id);
|
||||
int ActiveTasksInSet(int task_set_id);
|
||||
int CompletedTasksInSet(int task_set_id);
|
||||
bool HasSlotForTask(TaskInformation *task);
|
||||
@@ -67,6 +81,7 @@ public:
|
||||
void LockSharedTask(Client* client, bool lock);
|
||||
void ClearLastOffers() { m_last_offers.clear(); }
|
||||
bool CanAcceptNewTask(Client* client, int task_id, int npc_entity_id) const;
|
||||
bool HasExploreTask(Client* client) const;
|
||||
|
||||
inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; }
|
||||
|
||||
@@ -85,21 +100,28 @@ public:
|
||||
bool HasActiveSharedTask();
|
||||
|
||||
private:
|
||||
void AddReplayTimer(Client *client, ClientTaskInformation& client_task, TaskInformation& task);
|
||||
void DispatchEventTaskComplete(Client* client, ClientTaskInformation& client_task, int activity_id);
|
||||
const TaskInformation* GetTaskData(const ClientTaskInformation& client_task) const;
|
||||
|
||||
void AddOffer(int task_id, uint16_t npc_entity_id) { m_last_offers.push_back({task_id, npc_entity_id}); };
|
||||
void AddReplayTimer(Client *client, ClientTaskInformation& client_task, const TaskInformation& task);
|
||||
bool CanUpdate(Client* client, const TaskUpdateFilter& filter, int task_id,
|
||||
const ActivityInformation& activity, const ClientActivityInformation& client_activity) const;
|
||||
void DispatchEventTaskComplete(Client* client, ClientTaskInformation& client_task, int activity_id);
|
||||
std::pair<int, int> FindTask(Client* client, const TaskUpdateFilter& filter) const;
|
||||
void RecordCompletedTask(uint32_t character_id, const TaskInformation& task, const ClientTaskInformation& client_task);
|
||||
void UpdateTasksOnKill(Client* client, Client* exp_client, NPC* npc);
|
||||
bool UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count = 1);
|
||||
|
||||
void IncrementDoneCount(
|
||||
Client *client,
|
||||
TaskInformation *task_information,
|
||||
const TaskInformation* task_information,
|
||||
int task_index,
|
||||
int activity_id,
|
||||
int count = 1,
|
||||
bool ignore_quest_update = false
|
||||
);
|
||||
|
||||
bool UnlockActivities(int character_id, ClientTaskInformation &task_info);
|
||||
bool UnlockActivities(Client* client, ClientTaskInformation& task_info);
|
||||
|
||||
inline ClientTaskInformation *GetClientTaskInfo(TaskType task_type, int index)
|
||||
{
|
||||
@@ -143,12 +165,13 @@ private:
|
||||
std::vector<CompletedTaskInformation> m_completed_tasks;
|
||||
int m_last_completed_task_loaded;
|
||||
std::vector<TaskOffer> m_last_offers;
|
||||
bool m_has_explore_task = false;
|
||||
|
||||
static void ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c);
|
||||
|
||||
void SyncSharedTaskZoneClientDoneCountState(
|
||||
Client *p_client,
|
||||
TaskInformation *p_information,
|
||||
TaskType type,
|
||||
int task_index,
|
||||
int activity_id,
|
||||
uint32 done_count
|
||||
@@ -156,5 +179,4 @@ private:
|
||||
bool HasActiveTasks();
|
||||
};
|
||||
|
||||
|
||||
#endif //EQEMU_TASK_CLIENT_STATE_H
|
||||
|
||||
+27
-99
@@ -225,12 +225,30 @@ bool TaskManager::LoadTasks(int single_task)
|
||||
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->goal_id = task_activity.goalid;
|
||||
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_match_list = task_activity.goal_match_list;
|
||||
activity_data->goal_count = task_activity.goalcount;
|
||||
activity_data->deliver_to_npc = task_activity.delivertonpc;
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
activity_data->has_area = true;
|
||||
}
|
||||
|
||||
// zones
|
||||
activity_data->zones = task_activity.zones;
|
||||
@@ -246,13 +264,12 @@ bool TaskManager::LoadTasks(int single_task)
|
||||
activity_data->optional = task_activity.optional;
|
||||
|
||||
LogTasksDetail(
|
||||
"[LoadTasks] (Activity) task_id [{}] activity_id [{}] slot [{}] activity_type [{}] goal_id [{}] goal_method [{}] goal_count [{}] zones [{}]"
|
||||
"[LoadTasks] (Activity) task_id [{}] activity_id [{}] slot [{}] activity_type [{}] goal_method [{}] goal_count [{}] zones [{}]"
|
||||
" target_name [{}] item_list [{}] skill_list [{}] spell_list [{}] description_override [{}]",
|
||||
task_id,
|
||||
activity_id,
|
||||
m_task_data[task_id]->activity_count,
|
||||
static_cast<int32_t>(activity_data->activity_type),
|
||||
activity_data->goal_id,
|
||||
activity_data->goal_method,
|
||||
activity_data->goal_count,
|
||||
activity_data->zones.c_str(),
|
||||
@@ -1515,7 +1532,7 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s
|
||||
client_task_state->m_active_task.slot
|
||||
);
|
||||
if (client_task_state->m_active_task.task_id != TASKSLOTEMPTY) {
|
||||
client_task_state->UnlockActivities(character_id, client_task_state->m_active_task);
|
||||
client_task_state->UnlockActivities(client, client_task_state->m_active_task);
|
||||
|
||||
// purely debugging
|
||||
LogTasksDetail(
|
||||
@@ -1552,13 +1569,13 @@ bool TaskManager::LoadClientState(Client *client, ClientTaskState *client_task_s
|
||||
client_task_state->m_active_shared_task.slot
|
||||
);
|
||||
if (client_task_state->m_active_shared_task.task_id != TASKSLOTEMPTY) {
|
||||
client_task_state->UnlockActivities(character_id, client_task_state->m_active_shared_task);
|
||||
client_task_state->UnlockActivities(client, client_task_state->m_active_shared_task);
|
||||
}
|
||||
|
||||
// quests (max 20 or 40 depending on client)
|
||||
for (auto &active_quest : client_task_state->m_active_quests) {
|
||||
if (active_quest.task_id != TASKSLOTEMPTY) {
|
||||
client_task_state->UnlockActivities(character_id, active_quest);
|
||||
client_task_state->UnlockActivities(client, active_quest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1781,7 +1798,7 @@ void TaskManager::SyncClientSharedTaskStateToLocal(
|
||||
}
|
||||
}
|
||||
|
||||
void TaskManager::HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, NPC* npc)
|
||||
void TaskManager::HandleUpdateTasksOnKill(Client* client, NPC* npc)
|
||||
{
|
||||
for (auto &c: client->GetPartyMembers()) {
|
||||
if (!c->ClientDataLoaded() || !c->HasTaskState()) {
|
||||
@@ -1790,96 +1807,7 @@ void TaskManager::HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, NP
|
||||
|
||||
LogTasksDetail("[HandleUpdateTasksOnKill] Looping through client [{}]", c->GetCleanName());
|
||||
|
||||
// loop over the union of tasks and quests
|
||||
for (auto &active_task : c->GetTaskState()->m_active_tasks) {
|
||||
auto current_task = &active_task;
|
||||
if (current_task->task_id == TASKSLOTEMPTY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if there are any active kill activities for this p_task_data
|
||||
auto p_task_data = m_task_data[current_task->task_id];
|
||||
if (p_task_data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int activity_id = 0; activity_id < p_task_data->activity_count; activity_id++) {
|
||||
ClientActivityInformation *client_activity = ¤t_task->activity[activity_id];
|
||||
ActivityInformation *activity_info = &p_task_data->activity_information[activity_id];
|
||||
|
||||
// We are not interested in completed or hidden activities
|
||||
if (client_activity->activity_state != ActivityActive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We are only interested in Kill activities
|
||||
if (activity_info->activity_type != TaskActivityType::Kill) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is there a zone restriction on the activity_information ?
|
||||
if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) {
|
||||
LogTasks(
|
||||
"[HandleUpdateTasksOnKill] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check",
|
||||
client->GetName(),
|
||||
current_task->task_id,
|
||||
activity_id,
|
||||
static_cast<int32_t>(TaskActivityType::Kill),
|
||||
npc_type_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Is the activity_information to kill this type of NPC ?
|
||||
switch (activity_info->goal_method) {
|
||||
case METHODSINGLEID:
|
||||
if (activity_info->goal_id != npc_type_id) {
|
||||
LogTasksDetail("[HandleUpdateTasksOnKill] Matched single goal");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case METHODLIST:
|
||||
if (!m_goal_list_manager.IsInList(
|
||||
activity_info->goal_id,
|
||||
(int) npc_type_id
|
||||
) && !TaskGoalListManager::IsInMatchList(
|
||||
activity_info->goal_match_list,
|
||||
std::to_string(npc_type_id)
|
||||
) && !TaskGoalListManager::IsInMatchListPartial(
|
||||
activity_info->goal_match_list,
|
||||
npc->GetCleanName()
|
||||
) && !TaskGoalListManager::IsInMatchListPartial(
|
||||
activity_info->goal_match_list,
|
||||
npc->GetName()
|
||||
)) {
|
||||
LogTasksDetail("[HandleUpdateTasksOnKill] Matched list goal");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// If METHODQUEST, don't updated the activity_information here
|
||||
continue;
|
||||
}
|
||||
|
||||
LogTasksDetail("[HandleUpdateTasksOnKill] passed checks");
|
||||
|
||||
// handle actual update
|
||||
// legacy eqemu task update logic loops through group on kill of npc to update a single task
|
||||
if (p_task_data->type != TaskType::Shared) {
|
||||
LogTasksDetail("[HandleUpdateTasksOnKill] Non-Shared Update");
|
||||
c->GetTaskState()->IncrementDoneCount(c, p_task_data, current_task->slot, activity_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
LogTasksDetail("[HandleUpdateTasksOnKill] Shared update");
|
||||
|
||||
// shared tasks only require one client to receive an update to propagate
|
||||
if (c == client) {
|
||||
c->GetTaskState()->IncrementDoneCount(c, p_task_data, current_task->slot, activity_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
c->GetTaskState()->UpdateTasksOnKill(c, client, npc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-7
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "tasks.h"
|
||||
#include "task_client_state.h"
|
||||
#include "task_proximity_manager.h"
|
||||
#include "task_goal_list_manager.h"
|
||||
#include "../common/types.h"
|
||||
#include "../common/repositories/character_tasks_repository.h"
|
||||
@@ -24,10 +23,6 @@ public:
|
||||
int GetActivityCount(int task_id);
|
||||
bool LoadTasks(int single_task = 0);
|
||||
void ReloadGoalLists();
|
||||
inline void LoadProximities(int zone_id)
|
||||
{
|
||||
m_proximity_manager.LoadProximities(zone_id);
|
||||
}
|
||||
bool LoadTaskSets();
|
||||
bool LoadClientState(Client *client, ClientTaskState *client_task_state);
|
||||
bool SaveClientState(Client *client, ClientTaskState *client_task_state);
|
||||
@@ -72,11 +67,10 @@ public:
|
||||
// shared tasks
|
||||
void SyncClientSharedTaskState(Client *c, ClientTaskState *cts);
|
||||
|
||||
void HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, NPC* npc);
|
||||
void HandleUpdateTasksOnKill(Client* client, NPC* npc);
|
||||
|
||||
private:
|
||||
TaskGoalListManager m_goal_list_manager;
|
||||
TaskProximityManager m_proximity_manager;
|
||||
TaskInformation *m_task_data[MAXTASKS]{};
|
||||
std::vector<int> m_task_sets[MAXTASKSETS];
|
||||
void SendActiveTaskDescription(
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
#include "../common/global_define.h"
|
||||
#include "../common/repositories/proximities_repository.h"
|
||||
#include "../common/rulesys.h"
|
||||
#include "client.h"
|
||||
#include "mob.h"
|
||||
#include "quest_parser_collection.h"
|
||||
#include "task_proximity_manager.h"
|
||||
#include "tasks.h"
|
||||
#include "zonedb.h"
|
||||
|
||||
TaskProximityManager::TaskProximityManager()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
TaskProximityManager::~TaskProximityManager()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool TaskProximityManager::LoadProximities(int zone_id)
|
||||
{
|
||||
TaskProximity proximity{};
|
||||
m_task_proximities.clear();
|
||||
|
||||
auto proximities = ProximitiesRepository::GetWhere(
|
||||
content_db,
|
||||
fmt::format("zoneid = {} ORDER BY `zoneid` ASC", zone_id)
|
||||
);
|
||||
|
||||
for (auto &row: proximities) {
|
||||
proximity.explore_id = row.exploreid;
|
||||
proximity.min_x = row.minx;
|
||||
proximity.max_x = row.maxx;
|
||||
proximity.min_y = row.miny;
|
||||
proximity.max_y = row.maxy;
|
||||
proximity.min_z = row.minz;
|
||||
proximity.max_z = row.maxz;
|
||||
|
||||
m_task_proximities.push_back(proximity);
|
||||
}
|
||||
|
||||
LogTasks("Loaded [{}] Task Proximities", proximities.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int TaskProximityManager::CheckProximities(float x, float y, float z)
|
||||
{
|
||||
for (auto &task_proximity : m_task_proximities) {
|
||||
|
||||
TaskProximity *p_proximity = &task_proximity;
|
||||
|
||||
Log(
|
||||
Logs::General,
|
||||
Logs::Tasks,
|
||||
"[Proximity] Checking %8.3f, %8.3f, %8.3f against %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f",
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
p_proximity->min_x,
|
||||
p_proximity->max_x,
|
||||
p_proximity->min_y,
|
||||
p_proximity->max_y,
|
||||
p_proximity->min_z,
|
||||
p_proximity->max_z
|
||||
);
|
||||
|
||||
if (x < p_proximity->min_x || x > p_proximity->max_x || y < p_proximity->min_y || y > p_proximity->max_y ||
|
||||
z < p_proximity->min_z || z > p_proximity->max_z) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return p_proximity->explore_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef EQEMU_TASK_PROXIMITY_MANAGER_H
|
||||
#define EQEMU_TASK_PROXIMITY_MANAGER_H
|
||||
|
||||
struct TaskProximity {
|
||||
int explore_id;
|
||||
float min_x;
|
||||
float max_x;
|
||||
float min_y;
|
||||
float max_y;
|
||||
float min_z;
|
||||
float max_z;
|
||||
};
|
||||
|
||||
// This class is used for managing proximities so that Quest NPC proximities don't need to be used.
|
||||
class TaskProximityManager {
|
||||
|
||||
public:
|
||||
TaskProximityManager();
|
||||
~TaskProximityManager();
|
||||
bool LoadProximities(int zone_id);
|
||||
int CheckProximities(float x, float y, float z);
|
||||
|
||||
private:
|
||||
std::vector <TaskProximity> m_task_proximities;
|
||||
};
|
||||
|
||||
#endif //EQEMU_TASK_PROXIMITY_MANAGER_H
|
||||
@@ -1096,7 +1096,7 @@ bool Client::TradeskillExecute(DBTradeskillRecipe_Struct *spec) {
|
||||
}
|
||||
|
||||
if (RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
UpdateTasksForItem(TaskActivityType::TradeSkill, itr->first, itr->second);
|
||||
UpdateTasksForItem(TaskActivityType::TradeSkill, nullptr, itr->first, itr->second);
|
||||
}
|
||||
|
||||
++itr;
|
||||
|
||||
+1
-1
@@ -947,7 +947,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
||||
|
||||
if(RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
int Cash = trade->cp + (trade->sp * 10) + (trade->gp * 100) + (trade->pp * 1000);
|
||||
if(UpdateTasksOnDeliver(items, Cash, tradingWith->GetNPCTypeID())) {
|
||||
if (UpdateTasksOnDeliver(items, Cash, tradingWith->CastToNPC())) {
|
||||
if(!tradingWith->IsMoving())
|
||||
tradingWith->FaceTarget(this);
|
||||
|
||||
|
||||
@@ -3451,10 +3451,6 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack)
|
||||
task_manager = new TaskManager;
|
||||
task_manager->LoadTasks();
|
||||
|
||||
if (zone) {
|
||||
task_manager->LoadProximities(zone->GetZoneID());
|
||||
}
|
||||
|
||||
entity_list.ReloadAllClientsTaskState();
|
||||
} else {
|
||||
LogTasks("Global reload of Task ID [{}]", rts->task_id);
|
||||
@@ -3464,15 +3460,6 @@ void WorldServer::HandleReloadTasks(ServerPacket *pack)
|
||||
|
||||
break;
|
||||
}
|
||||
case RELOADTASKPROXIMITIES:
|
||||
{
|
||||
if (zone) {
|
||||
LogTasks("Global reload of all Task Proximities");
|
||||
task_manager->LoadProximities(zone->GetZoneID());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RELOADTASKGOALLISTS:
|
||||
{
|
||||
LogTasks("Global reload of all Task Goal Lists");
|
||||
|
||||
@@ -977,10 +977,6 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
||||
tradevar = 0;
|
||||
lootvar = 0;
|
||||
|
||||
if (RuleB(TaskSystem, EnableTaskSystem)) {
|
||||
task_manager->LoadProximities(zoneid);
|
||||
}
|
||||
|
||||
short_name = strcpy(new char[strlen(in_short_name)+1], in_short_name);
|
||||
strlwr(short_name);
|
||||
memset(file_name, 0, sizeof(file_name));
|
||||
|
||||
Reference in New Issue
Block a user