From 93749bc509bb38539389aa09d2a85f1cba8ae5a9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 1 Aug 2018 13:50:09 -0400 Subject: [PATCH] Add actual support for multi-zone task activities --- zone/tasks.cpp | 28 +++++++++++++++------------- zone/tasks.h | 9 ++++++++- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/zone/tasks.cpp b/zone/tasks.cpp index 5a3ba7914..56297bf3b 100644 --- a/zone/tasks.cpp +++ b/zone/tasks.cpp @@ -249,7 +249,9 @@ bool TaskManager::LoadTasks(int singleTask) Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].GoalCount = atoi(row[11]); Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].DeliverToNPC = atoi(row[12]); Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones = row[13]; - Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].ZoneID = atoi(row[13]); // for older clients + auto zones = SplitString(Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].zones, ';'); + for (auto && e : zones) + Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].ZoneIDs.push_back(std::stoi(e)); Tasks[taskID]->Activity[Tasks[taskID]->ActivityCount].Optional = atoi(row[14]); Log(Logs::General, Logs::Tasks, @@ -1144,7 +1146,7 @@ void TaskManager::SendTaskSelector(Client *c, Mob *mob, int TaskCount, int *Task buf.WriteInt32(activity.skill_id); buf.WriteInt32(activity.spell_id); - buf.WriteInt32(activity.ZoneID); + buf.WriteInt32(activity.ZoneIDs.empty() ? 0 : activity.ZoneIDs.front()); buf.WriteString(activity.desc_override); } } @@ -1534,7 +1536,7 @@ bool ClientTaskState::UpdateTasksByNPC(Client *c, int ActivityType, int NPCTypeI if (Task->Activity[j].Type != ActivityType) continue; // Is there a zone restriction on the activity ? - if ((Task->Activity[j].ZoneID > 0) && (Task->Activity[j].ZoneID != (int)zone->GetZoneID())) { + if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Task: %i, Activity %i, Activity type %i for NPC %i failed zone " "check", @@ -1594,7 +1596,7 @@ int ClientTaskState::ActiveSpeakTask(int NPCTypeID) { if (Task->Activity[j].Type != ActivitySpeakWith) continue; // Is there a zone restriction on the activity ? - if (Task->Activity[j].ZoneID > 0 && Task->Activity[j].ZoneID != (int)zone->GetZoneID()) + if (!Task->Activity[j].CheckZone(zone->GetZoneID())) continue; // Is the activity to speak with this type of NPC ? if (Task->Activity[j].GoalMethod == METHODQUEST && Task->Activity[j].GoalID == NPCTypeID) @@ -1632,7 +1634,7 @@ int ClientTaskState::ActiveSpeakActivity(int NPCTypeID, int TaskID) { if (Task->Activity[j].Type != ActivitySpeakWith) continue; // Is there a zone restriction on the activity ? - if (Task->Activity[j].ZoneID > 0 && Task->Activity[j].ZoneID != (int)zone->GetZoneID()) + if (!Task->Activity[j].CheckZone(zone->GetZoneID())) continue; // Is the activity to speak with this type of NPC ? if (Task->Activity[j].GoalMethod == METHODQUEST && Task->Activity[j].GoalID == NPCTypeID) @@ -1678,7 +1680,7 @@ void ClientTaskState::UpdateTasksForItem(Client *c, ActivityType Type, int ItemI if (Task->Activity[j].Type != (int)Type) continue; // Is there a zone restriction on the activity ? - if (Task->Activity[j].ZoneID > 0 && Task->Activity[j].ZoneID != (int)zone->GetZoneID()) { + if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Activity type %i for Item %i failed zone check", c->GetName(), Type, ItemID); continue; @@ -1737,7 +1739,7 @@ void ClientTaskState::UpdateTasksOnExplore(Client *c, int ExploreID) // We are only interested in explore activities if (Task->Activity[j].Type != ActivityExplore) continue; - if (Task->Activity[j].ZoneID > 0 && Task->Activity[j].ZoneID != (int)zone->GetZoneID()) { + if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Explore exploreid %i failed zone check", c->GetName(), ExploreID); @@ -1801,11 +1803,11 @@ bool ClientTaskState::UpdateTasksOnDeliver(Client *c, std::listActivity[j].Type != ActivityDeliver && Task->Activity[j].Type != ActivityGiveCash) continue; // Is there a zone restriction on the activity ? - if (Task->Activity[j].ZoneID > 0 && Task->Activity[j].ZoneID != (int)zone->GetZoneID()) { + if (!Task->Activity[j].CheckZone(zone->GetZoneID())) { Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Deliver activity failed zone check (current zone %i, need zone " - "%i", - c->GetName(), zone->GetZoneID(), Task->Activity[j].ZoneID); + "%s", + c->GetName(), zone->GetZoneID(), Task->Activity[j].zones.c_str()); continue; } // Is the activity to deliver to this NPCTypeID ? @@ -1878,7 +1880,7 @@ void ClientTaskState::UpdateTasksOnTouch(Client *c, int ZoneID) continue; if (Task->Activity[j].GoalMethod != METHODSINGLEID) continue; - if (Task->Activity[j].ZoneID != ZoneID) { + if (!Task->Activity[j].CheckZone(ZoneID)) { Log(Logs::General, Logs::Tasks, "[UPDATE] Char: %s Touch activity failed zone check", c->GetName()); continue; @@ -2568,7 +2570,7 @@ void ClientTaskState::SendTaskHistory(Client *c, int TaskIndex) { thd2->GoalCount = Task->Activity[i].GoalCount; thd2->unknown04 = 0xffffffff; thd2->unknown08 = 0xffffffff; - thd2->ZoneID = Task->Activity[i].ZoneID; + thd2->ZoneID = Task->Activity[i].ZoneIDs.empty() ? 0 : Task->Activity[i].ZoneIDs.front(); thd2->unknown16 = 0x00000000; Ptr = (char *)thd2 + sizeof(TaskHistoryReplyData2_Struct); VARSTRUCT_ENCODE_STRING(Ptr, Task->Activity[i].desc_override.c_str()); @@ -2772,7 +2774,7 @@ void TaskManager::SendTaskActivityLong(Client *c, int TaskID, int ActivityID, in buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].skill_id); buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].spell_id); - buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].ZoneID); + buf.WriteUInt32(Tasks[TaskID]->Activity[ActivityID].ZoneIDs.empty() ? 0 : Tasks[TaskID]->Activity[ActivityID].ZoneIDs.front()); buf.WriteUInt32(0); buf.WriteString(Tasks[TaskID]->Activity[ActivityID].desc_override); diff --git a/zone/tasks.h b/zone/tasks.h index 1505a50a1..0bc45c146 100644 --- a/zone/tasks.h +++ b/zone/tasks.h @@ -25,6 +25,7 @@ Copyright (C) 2001-2004 EQEMu Development Team (http://eqemulator.net) #include #include #include +#include #define MAXTASKS 10000 #define MAXTASKSETS 1000 @@ -113,9 +114,15 @@ struct ActivityInformation { TaskMethodType GoalMethod; int GoalCount; int DeliverToNPC; - int ZoneID; + std::vector ZoneIDs; std::string zones; // IDs ; searated, ZoneID is the first in this list for older clients -- default empty string bool Optional; + + inline bool CheckZone(int zone_id) { + if (ZoneIDs.empty()) + return true; + return std::find(ZoneIDs.begin(), ZoneIDs.end(), zone_id) != ZoneIDs.end(); + } }; typedef enum { ActivitiesSequential = 0, ActivitiesStepped = 1 } SequenceType;