[Tasks] Make Task Selector Cooldown Optional (#2420)

Some live npcs ignore the request cooldown timer (tutorialb)

A separate function had to be used for perl because the apis use an
array instead of array reference which won't allow a bool overload

This also replaces the fixed array and count args with a vector
This commit is contained in:
hg 2022-09-03 13:20:03 -04:00 committed by GitHub
parent 5e9a9e8afe
commit aa3c72c1de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 120 additions and 112 deletions

View File

@ -1166,27 +1166,16 @@ public:
{ {
if (task_state) { task_state->UpdateTasksOnTouch(this, dz_switch_id); } if (task_state) { task_state->UpdateTasksOnTouch(this, dz_switch_id); }
} }
inline void TaskSetSelector(Mob *mob, int task_set_id) inline void TaskSetSelector(Mob* mob, int task_set_id, bool ignore_cooldown)
{ {
if (task_manager) { if (task_manager && task_state) {
task_manager->TaskSetSelector( task_manager->TaskSetSelector(this, mob, task_set_id, ignore_cooldown);
this,
task_state,
mob,
task_set_id
);
} }
} }
inline void TaskQuestSetSelector(Mob *mob, int count, int *tasks) inline void TaskQuestSetSelector(Mob* mob, const std::vector<int>& tasks, bool ignore_cooldown)
{ {
if (task_manager) { if (task_manager && task_state) {
task_manager->TaskQuestSetSelector( task_manager->TaskQuestSetSelector(this, mob, tasks, ignore_cooldown);
this,
task_state,
mob,
count,
tasks
);
} }
} }
inline void EnableTask(int task_count, int *task_list) inline void EnableTask(int task_count, int *task_list)

View File

@ -1088,12 +1088,22 @@ void Perl__taskselector(perl::array task_ids)
throw std::runtime_error(fmt::format("Exceeded max number of task offers [{}]", MAXCHOOSERENTRIES)); throw std::runtime_error(fmt::format("Exceeded max number of task offers [{}]", MAXCHOOSERENTRIES));
} }
int tasks[MAXCHOOSERENTRIES]; std::vector<int> tasks;
for (int i = 0; i < task_ids.size(); ++i) for (int i = 0; i < task_ids.size(); ++i)
{ {
tasks[i] = task_ids[i]; tasks.push_back(task_ids[i]);
} }
quest_manager.taskselector(static_cast<int>(task_ids.size()), tasks); quest_manager.taskselector(tasks);
}
void Perl__taskselector_nocooldown(perl::array task_ids)
{
std::vector<int> tasks;
for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i)
{
tasks.push_back(task_ids[i]);
}
quest_manager.taskselector(tasks, true);
} }
void Perl__task_setselector(int task_set_id) void Perl__task_setselector(int task_set_id)
@ -1101,6 +1111,11 @@ void Perl__task_setselector(int task_set_id)
quest_manager.tasksetselector(task_set_id); quest_manager.tasksetselector(task_set_id);
} }
void Perl__task_setselector(int task_set_id, bool ignore_cooldown)
{
quest_manager.tasksetselector(task_set_id, ignore_cooldown);
}
void Perl__enabletask(perl::array task_ids) void Perl__enabletask(perl::array task_ids)
{ {
int count = 0; int count = 0;
@ -4240,7 +4255,9 @@ void perl_register_quest()
package.add("surname", &Perl__surname); package.add("surname", &Perl__surname);
package.add("targlobal", &Perl__targlobal); package.add("targlobal", &Perl__targlobal);
package.add("taskselector", &Perl__taskselector); package.add("taskselector", &Perl__taskselector);
package.add("task_setselector", &Perl__task_setselector); package.add("taskselector_nocooldown", &Perl__taskselector_nocooldown);
package.add("task_setselector", (void(*)(int))&Perl__task_setselector);
package.add("task_setselector", (void(*)(int, bool))&Perl__task_setselector);
package.add("tasktimeleft", &Perl__tasktimeleft); package.add("tasktimeleft", &Perl__tasktimeleft);
package.add("toggle_spawn_event", &Perl__toggle_spawn_event); package.add("toggle_spawn_event", &Perl__toggle_spawn_event);
package.add("toggledoorstate", &Perl__toggledoorstate); package.add("toggledoorstate", &Perl__toggledoorstate);

View File

@ -2512,32 +2512,25 @@ int Lua_Client::GetSpellDamage() {
} }
void Lua_Client::TaskSelector(luabind::adl::object table) { void Lua_Client::TaskSelector(luabind::adl::object table) {
TaskSelector(table, false);
}
void Lua_Client::TaskSelector(luabind::adl::object table, bool ignore_cooldown) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
if(luabind::type(table) != LUA_TTABLE) { if(luabind::type(table) != LUA_TTABLE) {
return; return;
} }
int tasks[MAXCHOOSERENTRIES] = { 0 }; std::vector<int> tasks;
int task_count = 0;
for(int i = 1; i <= MAXCHOOSERENTRIES; ++i) { for(int i = 1; i <= MAXCHOOSERENTRIES; ++i) {
auto cur = table[i]; auto cur = table[i];
int cur_value = 0; if (luabind::type(cur) == LUA_TNUMBER) {
if(luabind::type(cur) != LUA_TNIL) { tasks.push_back(luabind::object_cast<int>(cur));
try {
cur_value = luabind::object_cast<int>(cur);
} catch(luabind::cast_failed &) {
}
} else {
task_count = i - 1;
break;
} }
tasks[i - 1] = cur_value;
} }
self->TaskQuestSetSelector(self, task_count, tasks); self->TaskQuestSetSelector(self, tasks, ignore_cooldown);
} }
bool Lua_Client::TeleportToPlayerByCharID(uint32 character_id) { bool Lua_Client::TeleportToPlayerByCharID(uint32 character_id) {
@ -2983,6 +2976,7 @@ luabind::scope lua_register_client() {
.def("TakePlatinum", (bool(Lua_Client::*)(uint32))&Lua_Client::TakePlatinum) .def("TakePlatinum", (bool(Lua_Client::*)(uint32))&Lua_Client::TakePlatinum)
.def("TakePlatinum", (bool(Lua_Client::*)(uint32,bool))&Lua_Client::TakePlatinum) .def("TakePlatinum", (bool(Lua_Client::*)(uint32,bool))&Lua_Client::TakePlatinum)
.def("TaskSelector", (void(Lua_Client::*)(luabind::adl::object))&Lua_Client::TaskSelector) .def("TaskSelector", (void(Lua_Client::*)(luabind::adl::object))&Lua_Client::TaskSelector)
.def("TaskSelector", (void(Lua_Client::*)(luabind::adl::object, bool))&Lua_Client::TaskSelector)
.def("TeleportToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportToPlayerByCharID) .def("TeleportToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportToPlayerByCharID)
.def("TeleportToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportToPlayerByName) .def("TeleportToPlayerByName", (bool(Lua_Client::*)(std::string))&Lua_Client::TeleportToPlayerByName)
.def("TeleportGroupToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportGroupToPlayerByCharID) .def("TeleportGroupToPlayerByCharID", (bool(Lua_Client::*)(uint32))&Lua_Client::TeleportGroupToPlayerByCharID)

View File

@ -437,6 +437,7 @@ public:
void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetPrimaryWeaponOrnamentation(uint32 model_id);
void SetSecondaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id);
void TaskSelector(luabind::adl::object table); void TaskSelector(luabind::adl::object table);
void TaskSelector(luabind::adl::object table, bool ignore_cooldown);
void SetClientMaxLevel(uint8 max_level); void SetClientMaxLevel(uint8 max_level);
uint8 GetClientMaxLevel(); uint8 GetClientMaxLevel();

View File

@ -597,30 +597,35 @@ bool lua_bury_player_corpse(uint32 char_id) {
return quest_manager.buryplayercorpse(char_id); return quest_manager.buryplayercorpse(char_id);
} }
void lua_task_selector(luabind::adl::object table) { void lua_task_selector(luabind::adl::object table, bool ignore_cooldown) {
if(luabind::type(table) != LUA_TTABLE) { if(luabind::type(table) != LUA_TTABLE) {
return; return;
} }
int tasks[MAXCHOOSERENTRIES] = { 0 }; std::vector<int> tasks;
int count = 0;
for (int i = 1; i <= MAXCHOOSERENTRIES; ++i) for (int i = 1; i <= MAXCHOOSERENTRIES; ++i)
{ {
if (luabind::type(table[i]) == LUA_TNUMBER) if (luabind::type(table[i]) == LUA_TNUMBER)
{ {
tasks[i - 1] = luabind::object_cast<int>(table[i]); tasks.push_back(luabind::object_cast<int>(table[i]));
++count;
} }
} }
quest_manager.taskselector(count, tasks); quest_manager.taskselector(tasks, ignore_cooldown);
}
void lua_task_selector(luabind::adl::object table) {
lua_task_selector(table, false);
} }
void lua_task_set_selector(int task_set) { void lua_task_set_selector(int task_set) {
quest_manager.tasksetselector(task_set); quest_manager.tasksetselector(task_set);
} }
void lua_task_set_selector(int task_set, bool ignore_cooldown) {
quest_manager.tasksetselector(task_set, ignore_cooldown);
}
void lua_enable_task(luabind::adl::object table) { void lua_enable_task(luabind::adl::object table) {
if(luabind::type(table) != LUA_TTABLE) { if(luabind::type(table) != LUA_TTABLE) {
return; return;
@ -3703,8 +3708,10 @@ luabind::scope lua_register_general() {
luabind::def("get_player_corpse_count_by_zone_id", &lua_get_player_corpse_count_by_zone_id), luabind::def("get_player_corpse_count_by_zone_id", &lua_get_player_corpse_count_by_zone_id),
luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count), luabind::def("get_player_buried_corpse_count", &lua_get_player_buried_corpse_count),
luabind::def("bury_player_corpse", &lua_bury_player_corpse), luabind::def("bury_player_corpse", &lua_bury_player_corpse),
luabind::def("task_selector", &lua_task_selector), luabind::def("task_selector", (void(*)(luabind::adl::object))&lua_task_selector),
luabind::def("task_set_selector", &lua_task_set_selector), luabind::def("task_selector", (void(*)(luabind::adl::object, bool))&lua_task_selector),
luabind::def("task_set_selector", (void(*)(int))&lua_task_set_selector),
luabind::def("task_set_selector", (void(*)(int, bool))&lua_task_set_selector),
luabind::def("enable_task", &lua_enable_task), luabind::def("enable_task", &lua_enable_task),
luabind::def("disable_task", &lua_disable_task), luabind::def("disable_task", &lua_disable_task),
luabind::def("is_task_enabled", &lua_is_task_enabled), luabind::def("is_task_enabled", &lua_is_task_enabled),

View File

@ -2407,16 +2407,24 @@ int Perl_Client_GetSpellDamage(Client* self)
void Perl_Client_TaskSelector(Client* self, perl::array task_ids) void Perl_Client_TaskSelector(Client* self, perl::array task_ids)
{ {
int tasks[MAXCHOOSERENTRIES] = { 0 }; std::vector<int> tasks;
int task_count = 0;
for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i) for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i)
{ {
tasks[i] = task_ids[i]; tasks.push_back(task_ids[i]);
++task_count;
} }
self->TaskQuestSetSelector(self, task_count, tasks); self->TaskQuestSetSelector(self, tasks, false);
}
void Perl_Client_TaskSelectorNoCooldown(Client* self, perl::array task_ids)
{
std::vector<int> tasks;
for (int i = 0; i < task_ids.size() && i < MAXCHOOSERENTRIES; ++i)
{
tasks.push_back(task_ids[i]);
}
self->TaskQuestSetSelector(self, tasks, true);
} }
bool Perl_Client_TeleportToPlayerByCharacterID(Client* self, uint32 character_id) bool Perl_Client_TeleportToPlayerByCharacterID(Client* self, uint32 character_id)
@ -2872,6 +2880,7 @@ void perl_register_client()
package.add("TeleportRaidToPlayerByCharID", &Perl_Client_TeleportRaidToPlayerByCharacterID); package.add("TeleportRaidToPlayerByCharID", &Perl_Client_TeleportRaidToPlayerByCharacterID);
package.add("TeleportRaidToPlayerByName", &Perl_Client_TeleportRaidToPlayerByName); package.add("TeleportRaidToPlayerByName", &Perl_Client_TeleportRaidToPlayerByName);
package.add("TaskSelector", &Perl_Client_TaskSelector); package.add("TaskSelector", &Perl_Client_TaskSelector);
package.add("TaskSelectorNoCooldown", &Perl_Client_TaskSelectorNoCooldown);
package.add("Thirsty", &Perl_Client_Thirsty); package.add("Thirsty", &Perl_Client_Thirsty);
package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID); package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID);
package.add("UnFreeze", &Perl_Client_UnFreeze); package.add("UnFreeze", &Perl_Client_UnFreeze);

View File

@ -2294,10 +2294,10 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level
#endif //BOTS #endif //BOTS
void QuestManager::taskselector(int taskcount, int *tasks) { void QuestManager::taskselector(const std::vector<int>& tasks, bool ignore_cooldown) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager) if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager)
initiator->TaskQuestSetSelector(owner, taskcount, tasks); initiator->TaskQuestSetSelector(owner, tasks, ignore_cooldown);
} }
void QuestManager::enabletask(int taskcount, int *tasks) { void QuestManager::enabletask(int taskcount, int *tasks) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
@ -2322,11 +2322,11 @@ bool QuestManager::istaskenabled(int taskid) {
return false; return false;
} }
void QuestManager::tasksetselector(int tasksetid) { void QuestManager::tasksetselector(int tasksetid, bool ignore_cooldown) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid); Log(Logs::General, Logs::Tasks, "[UPDATE] TaskSetSelector called for task set %i", tasksetid);
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager) if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner && task_manager)
initiator->TaskSetSelector(owner, tasksetid); initiator->TaskSetSelector(owner, tasksetid, ignore_cooldown);
} }
bool QuestManager::istaskactive(int task) { bool QuestManager::istaskactive(int task) {

View File

@ -210,8 +210,8 @@ public:
void playerfeature(char *feature, int setting); void playerfeature(char *feature, int setting);
void npcfeature(char *feature, int setting); void npcfeature(char *feature, int setting);
void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration); void popup(const char *title, const char *text, uint32 popupid, uint32 buttons, uint32 Duration);
void taskselector(int taskcount, int *tasks); void taskselector(const std::vector<int>& tasks, bool ignore_cooldown = false);
void tasksetselector(int tasksettid); void tasksetselector(int tasksettid, bool ignore_cooldown = false);
void enabletask(int taskcount, int *tasks); void enabletask(int taskcount, int *tasks);
void disabletask(int taskcount, int *tasks); void disabletask(int taskcount, int *tasks);
bool istaskenabled(int taskid); bool istaskenabled(int taskid);

View File

@ -558,11 +558,10 @@ TaskType TaskManager::GetTaskType(uint32 task_id)
return TaskType::Task; return TaskType::Task;
} }
void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id) void TaskManager::TaskSetSelector(Client* client, Mob* mob, int task_set_id, bool ignore_cooldown)
{ {
int task_list[MAXCHOOSERENTRIES];
int task_list_index = 0;
int player_level = client->GetLevel(); int player_level = client->GetLevel();
ClientTaskState* client_task_state = client->GetTaskState();
LogTasks( LogTasks(
"TaskSetSelector called for task_set_id [{}] EnableTaskSize is [{}]", "TaskSetSelector called for task_set_id [{}] EnableTaskSize is [{}]",
@ -579,12 +578,12 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s
{ {
const auto task_data = GetTaskData(task_id); const auto task_data = GetTaskData(task_id);
if (task_data && task_data->type == TaskType::Shared) { if (task_data && task_data->type == TaskType::Shared) {
SharedTaskSelector(client, mob, m_task_sets[task_set_id].size(), m_task_sets[task_set_id].data()); SharedTaskSelector(client, mob, m_task_sets[task_set_id], ignore_cooldown);
return; return;
} }
} }
if (client->HasTaskRequestCooldownTimer()) { if (!ignore_cooldown && client->HasTaskRequestCooldownTimer()) {
client->SendTaskRequestCooldownTimerMessage(); client->SendTaskRequestCooldownTimerMessage();
return; return;
} }
@ -607,7 +606,8 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s
++iterator; ++iterator;
} // skip first when all enabled since it's useless data } // skip first when all enabled since it's useless data
while (iterator != m_task_sets[task_set_id].end() && task_list_index < MAXCHOOSERENTRIES) { std::vector<int> task_list;
while (iterator != m_task_sets[task_set_id].end() && task_list.size() < MAXCHOOSERENTRIES) {
auto task = *iterator; auto task = *iterator;
const auto task_data = GetTaskData(task); const auto task_data = GetTaskData(task);
@ -617,14 +617,14 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s
!client_task_state->IsTaskActive(task) && client_task_state->HasSlotForTask(task_data) && !client_task_state->IsTaskActive(task) && client_task_state->HasSlotForTask(task_data) &&
// this slot checking is a bit silly, but we allow mixing of task types ... // this slot checking is a bit silly, but we allow mixing of task types ...
(IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) { (IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) {
task_list[task_list_index++] = task; task_list.push_back(task);
} }
++iterator; ++iterator;
} }
if (task_list_index > 0) { if (!task_list.empty()) {
SendTaskSelector(client, mob, task_list_index, task_list); SendTaskSelector(client, mob, task_list);
} }
else { else {
client->MessageString(Chat::Yellow, NO_TASK_OFFERS, ".", ".", client->GetName()); client->MessageString(Chat::Yellow, NO_TASK_OFFERS, ".", ".", client->GetName());
@ -633,42 +633,36 @@ void TaskManager::TaskSetSelector(Client *client, ClientTaskState *client_task_s
// unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle // unlike the non-Quest version of this function, it does not check enabled, that is assumed the responsibility of the quest to handle
// we do however still want it to check the other stuff like level, active, room, etc // we do however still want it to check the other stuff like level, active, room, etc
void TaskManager::TaskQuestSetSelector( void TaskManager::TaskQuestSetSelector(Client* client, Mob* mob, const std::vector<int>& tasks, bool ignore_cooldown)
Client *client,
ClientTaskState *client_task_state,
Mob *mob,
int count,
int *tasks
)
{ {
int task_list[MAXCHOOSERENTRIES]; std::vector<int> task_list;
int task_list_index = 0;
int player_level = client->GetLevel(); int player_level = client->GetLevel();
ClientTaskState* client_task_state = client->GetTaskState();
LogTasks("[UPDATE] TaskQuestSetSelector called for array size [{}]", count); LogTasks("[UPDATE] TaskQuestSetSelector called with size [{}]", tasks.size());
if (count <= 0) { if (tasks.empty()) {
return; return;
} }
// live prevents mixing selection types (also uses diff opcodes for solo vs shared tasks) // live prevents mixing selection types (also uses diff opcodes for solo vs shared tasks)
// to keep shared task validation live-like (and simple), any shared task will // to keep shared task validation live-like (and simple), any shared task will
// forward this to shared task validation and non-shared tasks will be dropped // forward this to shared task validation and non-shared tasks will be dropped
for (int i = 0; i < count; ++i) { for (int i = 0; i < tasks.size(); ++i) {
auto task = tasks[i]; auto task = tasks[i];
const auto task_data = GetTaskData(task); const auto task_data = GetTaskData(task);
if (task_data && task_data->type == TaskType::Shared) { if (task_data && task_data->type == TaskType::Shared) {
SharedTaskSelector(client, mob, count, tasks); SharedTaskSelector(client, mob, tasks, ignore_cooldown);
return; return;
} }
} }
if (client->HasTaskRequestCooldownTimer()) { if (!ignore_cooldown && client->HasTaskRequestCooldownTimer()) {
client->SendTaskRequestCooldownTimerMessage(); client->SendTaskRequestCooldownTimerMessage();
return; return;
} }
for (int i = 0; i < count; ++i) { for (int i = 0; i < tasks.size() && task_list.size() < MAXCHOOSERENTRIES; ++i) {
auto task = tasks[i]; auto task = tasks[i];
const auto task_data = GetTaskData(task); const auto task_data = GetTaskData(task);
// verify level, we're not currently on it, repeatable status, if it's a (shared) task // verify level, we're not currently on it, repeatable status, if it's a (shared) task
@ -677,23 +671,27 @@ void TaskManager::TaskQuestSetSelector(
client_task_state->HasSlotForTask(task_data) && client_task_state->HasSlotForTask(task_data) &&
// this slot checking is a bit silly, but we allow mixing of task types ... // this slot checking is a bit silly, but we allow mixing of task types ...
(IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) { (IsTaskRepeatable(task) || !client_task_state->IsTaskCompleted(task))) {
task_list[task_list_index++] = task; task_list.push_back(task);
} }
} }
if (task_list_index > 0) { if (!task_list.empty()) {
SendTaskSelector(client, mob, task_list_index, task_list); SendTaskSelector(client, mob, task_list);
} }
else { else {
client->MessageString(Chat::Yellow, NO_TASK_OFFERS, ".", ".", client->GetName()); client->MessageString(Chat::Yellow, NO_TASK_OFFERS, ".", ".", client->GetName());
} }
} }
void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const int *tasks) void TaskManager::SharedTaskSelector(Client* client, Mob* mob, const std::vector<int>& tasks, bool ignore_cooldown)
{ {
LogTasks("[UPDATE] SharedTaskSelector called for array size [{}]", count); LogTasks("[UPDATE] SharedTaskSelector called with size [{}]", tasks.size());
if (count <= 0 || client->HasTaskRequestCooldownTimer()) { if (tasks.empty()) {
return;
}
if (!ignore_cooldown && client->HasTaskRequestCooldownTimer()) {
client->SendTaskRequestCooldownTimerMessage(); client->SendTaskRequestCooldownTimerMessage();
return; return;
} }
@ -736,10 +734,9 @@ void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const
if (!validation_failed) { if (!validation_failed) {
// run type and level filters on task selections // run type and level filters on task selections
int task_list[MAXCHOOSERENTRIES] = {0}; std::vector<int> task_list;
int task_list_index = 0;
for (int i = 0; i < count && task_list_index < MAXCHOOSERENTRIES; ++i) { for (int i = 0; i < tasks.size() && task_list.size() < MAXCHOOSERENTRIES; ++i) {
// todo: are there non repeatable shared tasks? (would need to check all group/raid members) // todo: are there non repeatable shared tasks? (would need to check all group/raid members)
auto task = tasks[i]; auto task = tasks[i];
const auto task_data = GetTaskData(task); const auto task_data = GetTaskData(task);
@ -748,13 +745,13 @@ void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const
request.lowest_level >= task_data->min_level && request.lowest_level >= task_data->min_level &&
(task_data->max_level == 0 || request.highest_level <= task_data->max_level)) (task_data->max_level == 0 || request.highest_level <= task_data->max_level))
{ {
task_list[task_list_index++] = task; task_list.push_back(task);
} }
} }
// check if any tasks are left to offer after filtering // check if any tasks are left to offer after filtering
if (task_list_index > 0) { if (!task_list.empty()) {
SendSharedTaskSelector(client, mob, task_list_index, task_list); SendSharedTaskSelector(client, mob, task_list);
} }
else { else {
client->MessageString(Chat::Red, TaskStr::NOT_MEET_REQ); client->MessageString(Chat::Red, TaskStr::NOT_MEET_REQ);
@ -763,14 +760,14 @@ void TaskManager::SharedTaskSelector(Client *client, Mob *mob, int count, const
} }
// sends task selector to client // sends task selector to client
void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int *task_list) void TaskManager::SendTaskSelector(Client* client, Mob* mob, const std::vector<int>& task_list)
{ {
LogTasks("TaskSelector for [{}] Tasks", task_count); LogTasks("TaskSelector for [{}] Tasks", task_list.size());
int player_level = client->GetLevel(); int player_level = client->GetLevel();
client->GetTaskState()->ClearLastOffers(); client->GetTaskState()->ClearLastOffers();
int valid_tasks_count = 0; int valid_tasks_count = 0;
for (int task_index = 0; task_index < task_count; task_index++) { for (int task_index = 0; task_index < task_list.size(); task_index++) {
if (!ValidateLevel(task_list[task_index], player_level)) { if (!ValidateLevel(task_list[task_index], player_level)) {
continue; continue;
} }
@ -796,7 +793,7 @@ void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int
// this is also sent in OP_TaskDescription // this is also sent in OP_TaskDescription
buf.WriteUInt32(mob->GetID()); // TaskGiver buf.WriteUInt32(mob->GetID()); // TaskGiver
for (int i = 0; i < task_count; i++) { // max 40 for (int i = 0; i < task_list.size(); i++) { // max 40
if (!ValidateLevel(task_list[i], player_level)) { if (!ValidateLevel(task_list[i], player_level)) {
continue; continue;
} }
@ -816,9 +813,9 @@ void TaskManager::SendTaskSelector(Client *client, Mob *mob, int task_count, int
client->QueuePacket(outapp.get()); client->QueuePacket(outapp.get());
} }
void TaskManager::SendSharedTaskSelector(Client *client, Mob *mob, int task_count, int *task_list) void TaskManager::SendSharedTaskSelector(Client* client, Mob* mob, const std::vector<int>& task_list)
{ {
LogTasks("SendSharedTaskSelector for [{}] Tasks", task_count); LogTasks("SendSharedTaskSelector for [{}] Tasks", task_list.size());
// request timer is only set when shared task selection shown (not for failed validations) // request timer is only set when shared task selection shown (not for failed validations)
client->StartTaskRequestCooldownTimer(); client->StartTaskRequestCooldownTimer();
@ -826,12 +823,12 @@ void TaskManager::SendSharedTaskSelector(Client *client, Mob *mob, int task_coun
SerializeBuffer buf; SerializeBuffer buf;
buf.WriteUInt32(task_count); // number of tasks buf.WriteUInt32(static_cast<uint32_t>(task_list.size())); // number of tasks
// shared task selection (live doesn't mix types) makes client send shared task specific opcode for accepts // shared task selection (live doesn't mix types) makes client send shared task specific opcode for accepts
buf.WriteUInt32(static_cast<uint32_t>(TaskType::Shared)); buf.WriteUInt32(static_cast<uint32_t>(TaskType::Shared));
buf.WriteUInt32(mob->GetID()); // task giver entity id buf.WriteUInt32(mob->GetID()); // task giver entity id
for (int i = 0; i < task_count; ++i) { for (int i = 0; i < task_list.size(); ++i) {
int task_id = task_list[i]; int task_id = task_list[i];
buf.WriteUInt32(task_id); buf.WriteUInt32(task_id);
m_task_data[task_id].SerializeSelector(buf, client->ClientVersion()); m_task_data[task_id].SerializeSelector(buf, client->ClientVersion());

View File

@ -24,20 +24,14 @@ public:
bool LoadTaskSets(); bool LoadTaskSets();
bool LoadClientState(Client *client, ClientTaskState *client_task_state); bool LoadClientState(Client *client, ClientTaskState *client_task_state);
bool SaveClientState(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); void SendTaskSelector(Client* client, Mob* mob, const std::vector<int>& tasks);
bool ValidateLevel(int task_id, int player_level); bool ValidateLevel(int task_id, int player_level);
std::string GetTaskName(uint32 task_id); std::string GetTaskName(uint32 task_id);
TaskType GetTaskType(uint32 task_id); TaskType GetTaskType(uint32 task_id);
void TaskSetSelector(Client *client, ClientTaskState *client_task_state, Mob *mob, int task_set_id); void TaskSetSelector(Client* client, Mob* mob, int task_set_id, bool ignore_cooldown);
// task list provided by QuestManager (perl/lua) // task list provided by QuestManager (perl/lua)
void TaskQuestSetSelector( void TaskQuestSetSelector(Client* client, Mob* mob, const std::vector<int>& tasks, bool ignore_cooldown);
Client *client, void SharedTaskSelector(Client* client, Mob* mob, const std::vector<int>& tasks, bool ignore_cooldown);
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 SendActiveTasksToClient(Client *client, bool task_complete = false);
void SendSingleActiveTaskToClient( void SendSingleActiveTaskToClient(
Client *client, Client *client,
@ -92,7 +86,7 @@ private:
// shared tasks // shared tasks
void SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskState *cts); void SyncClientSharedTaskWithPersistedState(Client *c, ClientTaskState *cts);
void SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTaskState *cts); void SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTaskState *cts);
void SendSharedTaskSelector(Client* client, Mob* mob, int task_count, int* task_list); void SendSharedTaskSelector(Client* client, Mob* mob, const std::vector<int>& tasks);
void SyncClientSharedTaskStateToLocal(Client *c); void SyncClientSharedTaskStateToLocal(Client *c);
}; };