eqemu-server/zone/task_manager.h
hg 20c639c872
[Tasks] Reward clients on shared task completion sync (#2306)
If a member is offline (or possibly during a race while zoning?) when
the shared task is completed they will not receive the reward. On live
the character receives their reward (with an updated replay timer) if
they enter back into game while the shared task is still active. They
keep the original replay timer if the shared task is no longer active
and do not receive a reward.

This makes it so clients are issued rewards (and a task completed
event is dispatch) if the client's task state was out of sync with a
completed shared task. To prevent characters being rewarded more than
once in case of bad sync checks, a 'was_rewarded' field has been added
to the character_tasks table and updated when rewards are assigned.

This fixes a couple bugs so the character_activities table is correctly
updated with shared task states to better detect when out of sync:

- The character_activities table is now flagged to update after syncing
  shared task states. This table was not being updated if a client was
  offline or inaccessible for a shared task element update.

- The character_activities table is now updated when a task element is
  completed. This was only being updated for activity increments and on
  completing the entire task. SaveClientState is now called at the end
  of ClientTaskState::IncrementDoneCount to cover all cases.

This also has a cosmetic change to show replay timers before rewards
like live, though this will not work for shared tasks until refactoring
world code
2022-07-16 15:26:48 -05:00

103 lines
3.2 KiB
C++

#ifndef EQEMU_TASK_MANAGER_H
#define EQEMU_TASK_MANAGER_H
#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"
#include <list>
#include <vector>
#include <string>
#include <algorithm>
class Client;
class Mob;
class TaskManager {
public:
TaskManager();
~TaskManager();
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);
void SendTaskSelector(Client *client, Mob *mob, int task_count, int *task_list);
bool ValidateLevel(int task_id, int player_level);
std::string GetTaskName(uint32 task_id);
TaskType GetTaskType(uint32 task_id);
void TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id);
// task list provided by QuestManager (perl/lua)
void TaskQuestSetSelector(
Client *client,
ClientTaskState *client_task_state,
Mob *mob,
int count,
int *tasks
);
void SharedTaskSelector(Client* client, Mob* mob, int count, const int* tasks);
void SendActiveTasksToClient(Client *client, bool task_complete = false);
void SendSingleActiveTaskToClient(
Client *client,
ClientTaskInformation &task_info,
bool task_complete,
bool bring_up_task_journal = false
);
void SendTaskActivityShort(Client *client, int task_id, int activity_id, int client_task_index);
void SendTaskActivityLong(
Client *client,
int task_id,
int activity_id,
int client_task_index,
bool task_complete = false
);
void SendCompletedTasksToClient(Client *c, ClientTaskState *client_task_state);
void ExplainTask(Client *client, int task_id);
int FirstTaskInSet(int task_set);
int LastTaskInSet(int task_set);
int NextTaskInSet(int task_set, int task_id);
bool IsTaskRepeatable(int task_id);
bool IsActiveTaskComplete(ClientTaskInformation& client_task);
friend class ClientTaskState;
// shared tasks
void SyncClientSharedTaskState(Client *c, ClientTaskState *cts);
void HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, std::string npc_name);
private:
TaskGoalListManager m_goal_list_manager;
TaskProximityManager m_proximity_manager;
TaskInformation *m_task_data[MAXTASKS]{};
std::vector<int> m_task_sets[MAXTASKSETS];
void SendActiveTaskDescription(
Client *client,
int task_id,
ClientTaskInformation &task_info,
int start_time,
int duration,
bool bring_up_task_journal = false
);
void SendActiveTaskToClient(ClientTaskInformation *task, Client *client, int task_index, bool task_complete);
// shared tasks
void SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskState *cts);
void SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTaskState *cts);
void SendSharedTaskSelector(Client* client, Mob* mob, int task_count, int* task_list);
void SyncClientSharedTaskStateToLocal(Client *c);
};
#endif //EQEMU_TASK_MANAGER_H