Add Optional Enforce Task Level Requirement

Affected:
quest::assigntask
$client->AssignTask

This is to allow those task level requirements in DB to be used,
optionally. It defaults to do not enforce (translated: no change for
current servers), but can be set with an additional flag to both
commands (see below). The LUA bit was added thanks to help from demonstar55.

quest::assigntask(703); # works
quest::assigntask(703, 1); # denies user
$client->AssignTask(701, $npc->GetID()); # works
$client->AssignTask(701, $npc->GetID(), 1); # denies user
This commit is contained in:
hateborne 2015-07-15 19:16:51 -04:00
parent 3cd474e960
commit d64f79cb2a
9 changed files with 69 additions and 15 deletions

View File

@ -997,7 +997,7 @@ public:
inline void DisableTask(int TaskCount, int *TaskList) { if(taskstate) taskstate->DisableTask(CharacterID(), TaskCount, TaskList); } 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 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 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 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 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); } inline void FailTask(int TaskID) { if(taskstate) taskstate->FailTask(this, TaskID); }

View File

@ -2383,11 +2383,19 @@ XS(XS__assigntask)
{ {
dXSARGS; dXSARGS;
unsigned int taskid; unsigned int taskid;
if(items == 1) { bool enforce_level_requirement = false;
if(items == 1 || items == 2) {
taskid = (int)SvIV(ST(0)); 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 { } else {
Perl_croak(aTHX_ "Usage: assigntask(taskid)"); Perl_croak(aTHX_ "Usage: assigntask(taskid, enforce_level_requirement)");
} }
XSRETURN_EMPTY; XSRETURN_EMPTY;

View File

@ -1077,6 +1077,11 @@ void Lua_Client::AssignTask(int task, int npc_id) {
self->AssignTask(task, 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) { void Lua_Client::FailTask(int task) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->FailTask(task); self->FailTask(task);
@ -1525,6 +1530,7 @@ luabind::scope lua_register_client() {
.def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID) .def("FindSpellBookSlotBySpellID", (int(Lua_Client::*)(int))&Lua_Client::FindSpellBookSlotBySpellID)
.def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity) .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))&Lua_Client::AssignTask)
.def("AssignTask", (void(Lua_Client::*)(int,int,bool))&Lua_Client::AssignTask
.def("FailTask", (void(Lua_Client::*)(int))&Lua_Client::FailTask) .def("FailTask", (void(Lua_Client::*)(int))&Lua_Client::FailTask)
.def("IsTaskCompleted", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskCompleted) .def("IsTaskCompleted", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskCompleted)
.def("IsTaskActive", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskActive) .def("IsTaskActive", (bool(Lua_Client::*)(int))&Lua_Client::IsTaskActive)

View File

@ -242,6 +242,7 @@ public:
int FindSpellBookSlotBySpellID(int spell_id); int FindSpellBookSlotBySpellID(int spell_id);
void UpdateTaskActivity(int task, int activity, int count); void UpdateTaskActivity(int task, int activity, int count);
void AssignTask(int task, int npc_id); void AssignTask(int task, int npc_id);
void AssignTask(int task, int npc_id, bool enforce_level_requirement);
void FailTask(int task); void FailTask(int task);
bool IsTaskCompleted(int task); bool IsTaskCompleted(int task);
bool IsTaskActive(int task); bool IsTaskActive(int task);

View File

@ -5126,13 +5126,20 @@ XS(XS_Client_AssignTask); /* prototype to pass -Wmissing-prototypes */
XS(XS_Client_AssignTask) XS(XS_Client_AssignTask)
{ {
dXSARGS; dXSARGS;
if (items != 3) if (items != 3 && items != 4)
Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, TaskID, NPCID)"); Perl_croak(aTHX_ "Usage: Client::AssignTask(THIS, TaskID, NPCID, enforce_level_requirement)");
{ {
Client * THIS; Client * THIS;
int TaskID = (int)SvIV(ST(1)); int TaskID = (int)SvIV(ST(1));
int NPCID = (int)SvIV(ST(2)); 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")) { if (sv_derived_from(ST(0), "Client")) {
IV tmp = SvIV((SV*)SvRV(ST(0))); IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Client *,tmp); THIS = INT2PTR(Client *,tmp);
@ -5142,7 +5149,7 @@ XS(XS_Client_AssignTask)
if(THIS == nullptr) if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
THIS->AssignTask(TaskID, NPCID); THIS->AssignTask(TaskID, NPCID, enforce_level_requirement);
} }
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }
@ -6477,7 +6484,7 @@ XS(boot_Client)
newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$"); newXSproto(strcpy(buf, "GetFreeSpellBookSlot"), XS_Client_GetFreeSpellBookSlot, file, "$;$");
newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$"); newXSproto(strcpy(buf, "GetSpellBookSlotBySpellID"), XS_Client_GetSpellBookSlotBySpellID, file, "$$");
newXSproto(strcpy(buf, "UpdateTaskActivity"), XS_Client_UpdateTaskActivity, 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, "FailTask"), XS_Client_FailTask, file, "$$");
newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$"); newXSproto(strcpy(buf, "IsTaskCompleted"), XS_Client_IsTaskCompleted, file, "$$");
newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$"); newXSproto(strcpy(buf, "IsTaskActive"), XS_Client_IsTaskActive, file, "$$");

View File

@ -2200,11 +2200,11 @@ void QuestManager::taskexploredarea(int exploreid) {
initiator->UpdateTasksOnExplore(exploreid); initiator->UpdateTasksOnExplore(exploreid);
} }
void QuestManager::assigntask(int taskid) { void QuestManager::assigntask(int taskid, bool enforce_level_requirement) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();
if(RuleB(TaskSystem, EnableTaskSystem) && initiator && owner) if (RuleB(TaskSystem, EnableTaskSystem) && initiator && owner)
initiator->AssignTask(taskid, owner->GetID()); initiator->AssignTask(taskid, owner->GetID(), enforce_level_requirement);
} }
void QuestManager::failtask(int taskid) { void QuestManager::failtask(int taskid) {

View File

@ -188,7 +188,7 @@ public:
void updatetaskactivity(int task, int activity, int count, bool ignore_quest_update = false); void updatetaskactivity(int task, int activity, int count, bool ignore_quest_update = false);
void resettaskactivity(int task, int activity); void resettaskactivity(int task, int activity);
void taskexploredarea(int exploreid); void taskexploredarea(int exploreid);
void assigntask(int taskid); void assigntask(int taskid, bool enforce_level_requirement = false);
void failtask(int taskid); void failtask(int taskid);
int tasktimeleft(int taskid); int tasktimeleft(int taskid);
int istaskcompleted(int taskid); int istaskcompleted(int taskid);

View File

@ -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) { void TaskManager::TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID) {
unsigned int EnabledTaskIndex = 0; 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) { if(!taskmanager || TaskID<0 || TaskID>=MAXTASKS) {
c->Message(13, "Task system not functioning, or TaskID %i out of range.", TaskID); 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; 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 // We do it this way, because when the Client cancels a task, it retains the sequence number of the remaining

View File

@ -168,7 +168,7 @@ public:
int GetTaskActivityDoneCount(int index, int ActivityID); int GetTaskActivityDoneCount(int index, int ActivityID);
int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID); int GetTaskActivityDoneCountFromTaskID(int TaskID, int ActivityID);
int GetTaskStartTime(int index); 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); void FailTask(Client *c, int TaskID);
int TaskTimeLeft(int TaskID); int TaskTimeLeft(int TaskID);
int IsTaskCompleted(int TaskID); int IsTaskCompleted(int TaskID);
@ -230,6 +230,8 @@ public:
void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList); void SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *TaskList);
void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList); void SendTaskSelectorNew(Client *c, Mob *mob, int TaskCount, int *TaskList);
bool AppropriateLevel(int TaskID, int PlayerLevel); 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 TaskSetSelector(Client *c, ClientTaskState *state, Mob *mob, int TaskSetID);
void SendActiveTasksToClient(Client *c, bool TaskComplete=false); void SendActiveTasksToClient(Client *c, bool TaskComplete=false);
void SendSingleActiveTaskToClient(Client *c, int TaskIndex, bool TaskComplete, bool BringUpTaskJournal=false); void SendSingleActiveTaskToClient(Client *c, int TaskIndex, bool TaskComplete, bool BringUpTaskJournal=false);