diff --git a/zone/attack.cpp b/zone/attack.cpp index a41f0911a..d5cd9005c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2357,9 +2357,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQ::skills::SkillTy give_exp_client->GetCleanName(), GetNPCTypeID() ); - give_exp_client - ->GetTaskState() - ->HandleUpdateTasksOnKill(give_exp_client, GetNPCTypeID()); + task_manager->HandleUpdateTasksOnKill(give_exp_client, GetNPCTypeID()); } if (kr) { diff --git a/zone/client.cpp b/zone/client.cpp index 8d64cd019..3845357a6 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -10529,3 +10529,41 @@ void Client::SetDoorToolEntityId(uint16 door_tool_entity_id) { Client::m_door_tool_entity_id = door_tool_entity_id; } + +// this will fetch raid clients if exists +// fallback to group if raid doesn't exist +// fallback to self if group doesn't exist +std::vector Client::GetPartyMembers() +{ + // get clients to update + std::vector clients_to_update = {}; + + // raid + Raid *raid = entity_list.GetRaidByClient(this); + if (raid) { + for (auto &e : raid->members) { + if (e.member && e.member->IsClient()) { + clients_to_update.push_back(e.member->CastToClient()); + } + } + } + + // group + if (clients_to_update.empty()) { + Group *group = entity_list.GetGroupByClient(this); + if (group) { + for (auto &m : group->members) { + if (m && m->IsClient()) { + clients_to_update.push_back(m->CastToClient()); + } + } + } + } + + // solo + if (clients_to_update.empty()) { + clients_to_update.push_back(this); + } + + return clients_to_update; +} diff --git a/zone/client.h b/zone/client.h index 5e84cf96b..aa703f050 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1040,6 +1040,7 @@ public: void SendTaskRequestCooldownTimerMessage(); void StartTaskRequestCooldownTimer(); inline ClientTaskState *GetTaskState() const { return task_state; } + inline bool HasTaskState() { if (task_state) { return true; } return false; } inline void CancelTask(int task_index, TaskType task_type) { if (task_state) { @@ -1094,15 +1095,6 @@ public: ); } } - inline void UpdateTasksOnKill(int npc_type_id) - { - if (task_state) { - task_state->UpdateTasksOnKill( - this, - npc_type_id - ); - } - } inline void UpdateTasksForItem( TaskActivityType activity_type, int item_id, @@ -1281,6 +1273,9 @@ public: bool m_shared_task_update = false; bool m_requested_shared_task_removal = false; + std::vector GetPartyMembers(); + void HandleUpdateTasksOnKill(uint32 npc_type_id); + inline const EQ::versions::ClientVersion ClientVersion() const { return m_ClientVersion; } inline const uint32 ClientVersionBit() const { return m_ClientVersionBit; } inline void SetClientVersion(EQ::versions::ClientVersion client_version) { m_ClientVersion = client_version; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 513cd5942..d751fad8b 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -67,6 +67,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/repositories/criteria/content_filter_criteria.h" #include "../common/shared_tasks.h" #include "gm_commands/door_manipulation.h" +#include "client.h" + #ifdef BOTS #include "bot.h" diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 293bd5aca..d995044a7 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -581,11 +581,6 @@ bool ClientTaskState::UnlockActivities(int character_id, ClientTaskInformation & return false; } -void ClientTaskState::UpdateTasksOnKill(Client *client, int npc_type_id) -{ - UpdateTasksByNPC(client, TaskActivityType::Kill, npc_type_id); -} - bool ClientTaskState::UpdateTasksOnSpeakWith(Client *client, int npc_type_id) { return UpdateTasksByNPC(client, TaskActivityType::SpeakWith, npc_type_id); @@ -2734,112 +2729,6 @@ void ClientTaskState::SyncSharedTaskZoneClientDoneCountState( } } -void ClientTaskState::HandleUpdateTasksOnKill(Client *client, uint32 npc_type_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 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) { - 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())) { - LogTasks( - "[HandleUpdateTasksOnKill] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", - client->GetName(), - current_task->task_id, - activity_id, - static_cast(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 (!task_manager->m_goal_list_manager.IsInList( - activity_info->goal_id, - (int) npc_type_id - )) { - 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"); - - Raid *raid = entity_list.GetRaidByClient(client); - if (raid) { - for (auto &e : raid->members) { - if (e.member && e.member->IsClient()) { - Client *c = e.member->CastToClient(); - c->UpdateTasksOnKill(npc_type_id); - } - } - return; - } - - Group *group = entity_list.GetGroupByClient(client); - if (group) { - for (auto &m : group->members) { - if (m && m->IsClient()) { - Client *c = m->CastToClient(); - c->UpdateTasksOnKill(npc_type_id); - } - } - return; - } - } - - LogTasksDetail("[HandleUpdateTasksOnKill] Shared update"); - - // shared tasks only require one client to receive an update to propagate - client->UpdateTasksOnKill(npc_type_id); - } - } -} bool ClientTaskState::HasActiveTasks() { if (!task_manager) { diff --git a/zone/task_client_state.h b/zone/task_client_state.h index f45a522c9..ab3ad1044 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -34,7 +34,6 @@ public: 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 UpdateTasksOnKill(Client *client, 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); @@ -74,8 +73,6 @@ public: const ClientTaskInformation &GetActiveSharedTask() const; bool HasActiveSharedTask(); - - void HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id); private: void AddReplayTimer(Client *client, ClientTaskInformation& client_task, TaskInformation& task); diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 7616753e8..9204f4ee6 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -1814,3 +1814,96 @@ void TaskManager::SyncClientSharedTaskStateToLocal( } } } + +void TaskManager::HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id) +{ + for (auto &c: client->GetPartyMembers()) { + if (!c->ClientDataLoaded() || !c->HasTaskState()) { + continue; + } + + 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())) { + LogTasks( + "[HandleUpdateTasksOnKill] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", + client->GetName(), + current_task->task_id, + activity_id, + static_cast(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 + )) { + 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); + } + } + } + } +} diff --git a/zone/task_manager.h b/zone/task_manager.h index 0914fe888..16eb51fcd 100644 --- a/zone/task_manager.h +++ b/zone/task_manager.h @@ -72,6 +72,8 @@ public: // shared tasks void SyncClientSharedTaskState(Client *c, ClientTaskState *cts); + void HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id); + private: TaskGoalListManager m_goal_list_manager; TaskProximityManager m_proximity_manager;