diff --git a/common/repositories/base/base_task_activities_repository.h b/common/repositories/base/base_task_activities_repository.h index 2da4db0b4..70a092e27 100644 --- a/common/repositories/base/base_task_activities_repository.h +++ b/common/repositories/base/base_task_activities_repository.h @@ -34,6 +34,7 @@ public: int goalcount; int delivertonpc; std::string zones; + int zone_version; int optional; }; @@ -60,6 +61,7 @@ public: "goalcount", "delivertonpc", "zones", + "zone_version", "optional", }; } @@ -82,6 +84,7 @@ public: "goalcount", "delivertonpc", "zones", + "zone_version", "optional", }; } @@ -138,6 +141,7 @@ public: entry.goalcount = 1; entry.delivertonpc = 0; entry.zones = ""; + entry.zone_version = -1; entry.optional = 0; return entry; @@ -189,7 +193,8 @@ public: entry.goalcount = atoi(row[12]); entry.delivertonpc = atoi(row[13]); entry.zones = row[14] ? row[14] : ""; - entry.optional = atoi(row[15]); + entry.zone_version = atoi(row[15]); + entry.optional = atoi(row[16]); return entry; } @@ -238,7 +243,8 @@ public: update_values.push_back(columns[12] + " = " + std::to_string(task_activities_entry.goalcount)); update_values.push_back(columns[13] + " = " + std::to_string(task_activities_entry.delivertonpc)); update_values.push_back(columns[14] + " = '" + Strings::Escape(task_activities_entry.zones) + "'"); - update_values.push_back(columns[15] + " = " + std::to_string(task_activities_entry.optional)); + update_values.push_back(columns[15] + " = " + std::to_string(task_activities_entry.zone_version)); + update_values.push_back(columns[16] + " = " + std::to_string(task_activities_entry.optional)); auto results = db.QueryDatabase( fmt::format( @@ -275,6 +281,7 @@ public: insert_values.push_back(std::to_string(task_activities_entry.goalcount)); insert_values.push_back(std::to_string(task_activities_entry.delivertonpc)); insert_values.push_back("'" + Strings::Escape(task_activities_entry.zones) + "'"); + insert_values.push_back(std::to_string(task_activities_entry.zone_version)); insert_values.push_back(std::to_string(task_activities_entry.optional)); auto results = db.QueryDatabase( @@ -320,6 +327,7 @@ public: insert_values.push_back(std::to_string(task_activities_entry.goalcount)); insert_values.push_back(std::to_string(task_activities_entry.delivertonpc)); insert_values.push_back("'" + Strings::Escape(task_activities_entry.zones) + "'"); + insert_values.push_back(std::to_string(task_activities_entry.zone_version)); insert_values.push_back(std::to_string(task_activities_entry.optional)); insert_chunks.push_back("(" + Strings::Implode(",", insert_values) + ")"); @@ -369,7 +377,8 @@ public: entry.goalcount = atoi(row[12]); entry.delivertonpc = atoi(row[13]); entry.zones = row[14] ? row[14] : ""; - entry.optional = atoi(row[15]); + entry.zone_version = atoi(row[15]); + entry.optional = atoi(row[16]); all_entries.push_back(entry); } @@ -409,7 +418,8 @@ public: entry.goalcount = atoi(row[12]); entry.delivertonpc = atoi(row[13]); entry.zones = row[14] ? row[14] : ""; - entry.optional = atoi(row[15]); + entry.zone_version = atoi(row[15]); + entry.optional = atoi(row[16]); all_entries.push_back(entry); } diff --git a/common/tasks.h b/common/tasks.h index 680297a7a..d2777e151 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -67,14 +67,17 @@ struct ActivityInformation { int deliver_to_npc; std::vector zone_ids; std::string zones; // IDs ; separated, ZoneID is the first in this list for older clients -- default empty string, max length 64 + int zone_version; bool optional; - inline bool CheckZone(int zone_id) + inline bool CheckZone(int zone_id, int version) { if (zone_ids.empty()) { return true; } - return std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end(); + bool found_zone = std::find(zone_ids.begin(), zone_ids.end(), zone_id) != zone_ids.end(); + + return found_zone && (zone_version == version || zone_version == -1); } void SerializeSelector(SerializeBuffer& out, EQ::versions::ClientVersion client_version) const diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index cae450b80..a0a01e410 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -440,6 +440,7 @@ 9184|2022_05_21_schema_consistency.sql|SELECT * FROM db_version WHERE version >= 9184|empty| 9185|2022_05_07_discord_webhooks.sql|SHOW TABLES LIKE 'discord_webhooks'|empty| 9186|2022_07_09_zone_expansion_deprecate.sql|SHOW COLUMNS FROM 'zone' LIKE 'expansion'|notempty| +9187|2022_07_09_task_zone_version_matching.sql|SHOW COLUMNS FROM `task_activities` LIKE 'zone_version'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2022_07_09_task_zone_version_matching.sql b/utils/sql/git/required/2022_07_09_task_zone_version_matching.sql new file mode 100644 index 000000000..8421ab418 --- /dev/null +++ b/utils/sql/git/required/2022_07_09_task_zone_version_matching.sql @@ -0,0 +1 @@ +ALTER TABLE `task_activities` ADD COLUMN `zone_version` int(11) default -1 AFTER zones; diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index dda42b80d..78c041794 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -621,7 +621,7 @@ bool ClientTaskState::UpdateTasksByNPC(Client *client, TaskActivityType activity continue; } // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { LogTasks( "[UPDATE] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", client->GetName(), @@ -699,7 +699,7 @@ int ClientTaskState::ActiveSpeakTask(int npc_type_id) continue; } // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { continue; } // Is the activity_information to speak with this type of NPC ? @@ -748,7 +748,7 @@ int ClientTaskState::ActiveSpeakActivity(int npc_type_id, int task_id) continue; } // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { continue; } @@ -809,7 +809,7 @@ void ClientTaskState::UpdateTasksForItem(Client *client, TaskActivityType activi continue; } // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { LogTasks( "[UpdateTasksForItem] Error: Character [{}] activity_information type [{}] for Item [{}] failed zone check", client->GetName(), @@ -881,7 +881,7 @@ void ClientTaskState::UpdateTasksOnExplore(Client *client, int explore_id) if (activity_info->activity_type != TaskActivityType::Explore) { continue; } - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { LogTasks( "[UpdateTasksOnExplore] character [{}] explore_id [{}] failed zone check", client->GetName(), @@ -977,7 +977,7 @@ bool ClientTaskState::UpdateTasksOnDeliver( continue; } // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { Log( Logs::General, Logs::Tasks, "[UPDATE] Char: %s Deliver activity_information failed zone check (current zone %i, need zone " @@ -1039,7 +1039,7 @@ bool ClientTaskState::UpdateTasksOnDeliver( return is_updated; } -void ClientTaskState::UpdateTasksOnTouch(Client *client, int zone_id) +void ClientTaskState::UpdateTasksOnTouch(Client *client, int zone_id, uint16 version) { // If the client has no tasks, there is nothing further to check. @@ -1077,7 +1077,7 @@ void ClientTaskState::UpdateTasksOnTouch(Client *client, int zone_id) if (activity_info->goal_method != METHODSINGLEID) { continue; } - if (!activity_info->CheckZone(zone_id)) { + if (!activity_info->CheckZone(zone_id, version)) { LogTasks( "[UpdateTasksOnTouch] character [{}] Touch activity_information failed zone check", client->GetName() @@ -1929,7 +1929,7 @@ void ClientTaskState::TaskPeriodicChecks(Client *client) // the zone before we send the 'Task activity_information Completed' message. // if (!m_checked_touch_activities) { - UpdateTasksOnTouch(client, zone->GetZoneID()); + UpdateTasksOnTouch(client, zone->GetZoneID(), zone->GetInstanceVersion()); m_checked_touch_activities = true; } } diff --git a/zone/task_client_state.h b/zone/task_client_state.h index b8aa03667..dfbdaaab3 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -38,7 +38,7 @@ public: void UpdateTasksOnExplore(Client *client, int explore_id); bool UpdateTasksOnSpeakWith(Client *client, int npc_type_id); bool UpdateTasksOnDeliver(Client *client, std::list &items, int cash, int npc_type_id); - void UpdateTasksOnTouch(Client *client, int zone_id); + void UpdateTasksOnTouch(Client *client, int zone_id, uint16 version); void ProcessTaskProximities(Client *client, float x, float y, float z); bool TaskOutOfTime(TaskType task_type, int index); void TaskPeriodicChecks(Client *client); diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 866f5bf3e..501cb295e 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -236,6 +236,7 @@ bool TaskManager::LoadTasks(int single_task) activity_data->goal_match_list = task_activity.goal_match_list; activity_data->goal_count = task_activity.goalcount; activity_data->deliver_to_npc = task_activity.delivertonpc; + activity_data->zone_version = task_activity.zone_version; // zones activity_data->zones = task_activity.zones; @@ -1853,7 +1854,7 @@ void TaskManager::HandleUpdateTasksOnKill(Client *client, uint32 npc_type_id, st } // Is there a zone restriction on the activity_information ? - if (!activity_info->CheckZone(zone->GetZoneID())) { + if (!activity_info->CheckZone(zone->GetZoneID(), zone->GetInstanceVersion())) { LogTasks( "[HandleUpdateTasksOnKill] character [{}] task_id [{}] activity_id [{}] activity_type [{}] for NPC [{}] failed zone check", client->GetName(),