diff --git a/zone/client.h b/zone/client.h index 03d09d50c..bbe4ba575 100644 --- a/zone/client.h +++ b/zone/client.h @@ -997,7 +997,7 @@ public: inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); } inline bool IsTaskEnabled(int TaskID) { return (taskstate ? taskstate->IsTaskEnabled(TaskID) : false); } inline void ProcessTaskProximities(float X, float Y, float Z) { if(taskstate) taskstate->ProcessTaskProximities(this, X, Y, Z); } - inline void AssignTask(int TaskID, int NPCID) { if(taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID); } + inline void AssignTask(int TaskID, int NPCID, bool enforce_level_requirement = false) { if (taskstate) taskstate->AcceptNewTask(this, TaskID, NPCID, enforce_level_requirement); } inline int ActiveSpeakTask(int NPCID) { if(taskstate) return taskstate->ActiveSpeakTask(NPCID); else return 0; } inline int ActiveSpeakActivity(int NPCID, int TaskID) { if(taskstate) return taskstate->ActiveSpeakActivity(NPCID, TaskID); else return 0; } inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); } diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 871d47074..f5de73698 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -2383,11 +2383,19 @@ XS(XS__assigntask) { dXSARGS; unsigned int taskid; - if(items == 1) { + bool enforce_level_requirement = false; + if(items == 1 || items == 2) { taskid = (int)SvIV(ST(0)); - quest_manager.assigntask(taskid); + if (items == 2) + { + if ((int)SvIV(ST(1)) == 1) + { + enforce_level_requirement = true; + } + } + quest_manager.assigntask(taskid, enforce_level_requirement); } else { - Perl_croak(aTHX_ "Usage: assigntask(taskid)"); + Perl_croak(aTHX_ "Usage: assigntask(taskid, enforce_level_requirement)"); } XSRETURN_EMPTY; diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index d69924577..0e397b58e 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1077,6 +1077,11 @@ void Lua_Client::AssignTask(int task, int npc_id) { self->AssignTask(task, npc_id); } +void Lua_Client::AssignTask(int task, int npc_id, bool enforce_level_requirement) { + Lua_Safe_Call_Void(); + self->AssignTask(task, npc_id, enforce_level_requirement); +} + void Lua_Client::FailTask(int task) { Lua_Safe_Call_Void(); self->FailTask(task); @@ -1525,6 +1530,7 @@ luabind::scope lua_register_client() { .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) .def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity) .def("AssignTask", (void(Lua_Client::*)(int,int))&Lua_Client::AssignTask) + .def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask .def("FailTask", (void(Lua_Client::*)(int))&Lua_Client::FailTask) .def("IsTaskCompleted", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskCompleted) .def("IsTaskActive", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskActive) diff --git a/zone/lua_client.h b/zone/lua_client.h index dd1059a0a..f3f0e1897 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -242,6 +242,7 @@ public: int FindSpellBookSlotBySpellID(int spell_id); void UpdateTaskActivity(int task, int activity, int count); void AssignTask(int task, int npc_id); + void AssignTask(int task, int npc_id, bool enforce_level_requirement); void FailTask(int task); bool IsTaskCompleted(int task); bool IsTaskActive(int task); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index ee4ee943d..de9e8512a 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5126,13 +5126,20 @@ XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_AssignTask) { dXSARGS; - if (items != 3) - Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, TaskID, NPCID)"); + if (items != 3 && items != 4) + Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, TaskID, NPCID, enforce_level_requirement)"); { Client * THIS; int TaskID = (int)SvIV(ST(1)); int NPCID = (int)SvIV(ST(2)); - + bool enforce_level_requirement = false; + if (items == 4) + { + if ((int)SvIV(ST(3)) == 1) + { + enforce_level_requirement = true; + } + } if (sv_derived_from(ST(0), "Client")) { IV tmp = SvIV((SV*)SvRV(ST(0))); THIS = INT2PTR(Client *,tmp); @@ -5142,7 +5149,7 @@ XS(XS_Client_AssignTask) if(THIS == nullptr) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); - THIS->AssignTask(TaskID, NPCID); + THIS->AssignTask(TaskID, NPCID, enforce_level_requirement); } XSRETURN_EMPTY; } @@ -6477,7 +6484,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$"); newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$"); newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, file, "$$$$;$"); - newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$"); + newXSproto(strcpy(buf, "AssignTask"), XS_Client_AssignTask, file, "$$$;$"); newXSproto(strcpy(buf, "FailTask"), XS_Client_FailTask, file, "$$"); newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$"); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index b6243091f..a15724325 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2200,11 +2200,11 @@ void QuestManager::taskexploredarea(int exploreid) { initiator->UpdateTasksOnExplore(exploreid); } -void QuestManager::assigntask(int taskid) { +void QuestManager::assigntask(int taskid, bool enforce_level_requirement) { QuestManagerCurrentQuestVars(); - if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) - initiator->AssignTask(taskid, owner->GetID()); + if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) + initiator->AssignTask(taskid, owner->GetID(), enforce_level_requirement); } void QuestManager::failtask(int taskid) { diff --git a/zone/questmgr.h b/zone/questmgr.h index 960a8f1f4..78f4b34ed 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -188,7 +188,7 @@ public: 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); + void assigntask(int taskid, bool enforce_level_requirement = false); void failtask(int taskid); int tasktimeleft(int taskid); int istaskcompleted(int taskid); diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 4f3fe8124..537cdefed 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -895,6 +895,30 @@ bool TaskManager::AppropriateLevel(int TaskID, int PlayerLevel) { } +int TaskManager::GetTaskMinLevel(int TaskID) +{ + if (Tasks[TaskID]->MinLevel) + { + return Tasks[TaskID]->MinLevel; + } + else + { + return -1; + } +} + +int TaskManager::GetTaskMaxLevel(int TaskID) +{ + if (Tasks[TaskID]->MaxLevel) + { + return Tasks[TaskID]->MaxLevel; + } + else + { + return -1; + } +} + void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID) { unsigned int EnabledTaskIndex = 0; @@ -2948,7 +2972,7 @@ void ClientTaskState::RemoveTask(Client *c, int sequenceNumber) { } -void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID) { +void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement) { if(!taskmanager || TaskID<0 || TaskID>=MAXTASKS) { c->Message(13, "Task system not functioning, or TaskID %i out of range.", TaskID); @@ -2973,6 +2997,12 @@ void ClientTaskState::AcceptNewTask(Client *c, int TaskID, int NPCID) { } } + if (enforce_level_requirement && !taskmanager->AppropriateLevel(TaskID, c->GetLevel())) + { + c->Message(13, "You are outside the level range of this task."); + return; + } + if(!taskmanager->IsTaskRepeatable(TaskID) && IsTaskCompleted(TaskID)) return; // We do it this way, because when the Client cancels a task, it retains the sequence number of the remaining diff --git a/zone/tasks.h b/zone/tasks.h index c525bbcd8..459eacd08 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -168,7 +168,7 @@ public: int GetTaskActivityDoneCount(int index, int ActivityID); int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID); int GetTaskStartTime(int index); - void AcceptNewTask(Client *c, int TaskID, int NPCID); + void AcceptNewTask(Client *c, int TaskID, int NPCID, bool enforce_level_requirement = false); void FailTask(Client *c, int TaskID); int TaskTimeLeft(int TaskID); int IsTaskCompleted(int TaskID); @@ -230,6 +230,8 @@ public: void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList); void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList); bool AppropriateLevel(int TaskID, int PlayerLevel); + int GetTaskMinLevel(int TaskID); + int GetTaskMaxLevel(int TaskID); void TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID); void SendActiveTasksToClient(Client *c, bool TaskComplete=false); void SendSingleActiveTaskToClient(Client *c, int TaskIndex, bool TaskComplete, bool BringUpTaskJournal=false);