Combine task_activity item and npc fields

This will make tooling easier.

While denormalizing goallists may not be ideal, it decouples tasks from
rewards which share the table and removes a redundant column in favor
of a using the delimited string which better matches live packet data.
This commit is contained in:
hg 2022-09-25 17:14:57 -04:00 committed by Akkadius
parent d22fca7593
commit 64c5292c69
7 changed files with 102 additions and 136 deletions

View File

@ -28,11 +28,7 @@ public:
uint32_t goalmethod;
int32_t goalcount;
std::string description_override;
uint32_t npc_id;
uint32_t npc_goal_id;
std::string npc_match_list;
uint32_t item_id;
uint32_t item_goal_id;
std::string item_id_list;
std::string item_list;
int32_t dz_switch_id;
@ -66,11 +62,7 @@ public:
"goalmethod",
"goalcount",
"description_override",
"npc_id",
"npc_goal_id",
"npc_match_list",
"item_id",
"item_goal_id",
"item_id_list",
"item_list",
"dz_switch_id",
@ -100,11 +92,7 @@ public:
"goalmethod",
"goalcount",
"description_override",
"npc_id",
"npc_goal_id",
"npc_match_list",
"item_id",
"item_goal_id",
"item_id_list",
"item_list",
"dz_switch_id",
@ -168,11 +156,7 @@ public:
e.goalmethod = 0;
e.goalcount = 1;
e.description_override = "";
e.npc_id = 0;
e.npc_goal_id = 0;
e.npc_match_list = "";
e.item_id = 0;
e.item_goal_id = 0;
e.item_id_list = "";
e.item_list = "";
e.dz_switch_id = 0;
@ -231,25 +215,21 @@ public:
e.goalmethod = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.goalcount = static_cast<int32_t>(atoi(row[7]));
e.description_override = row[8] ? row[8] : "";
e.npc_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.npc_goal_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.npc_match_list = row[11] ? row[11] : "";
e.item_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.item_goal_id = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.item_id_list = row[14] ? row[14] : "";
e.item_list = row[15] ? row[15] : "";
e.dz_switch_id = static_cast<int32_t>(atoi(row[16]));
e.min_x = strtof(row[17], nullptr);
e.min_y = strtof(row[18], nullptr);
e.min_z = strtof(row[19], nullptr);
e.max_x = strtof(row[20], nullptr);
e.max_y = strtof(row[21], nullptr);
e.max_z = strtof(row[22], nullptr);
e.skill_list = row[23] ? row[23] : "";
e.spell_list = row[24] ? row[24] : "";
e.zones = row[25] ? row[25] : "";
e.zone_version = static_cast<int32_t>(atoi(row[26]));
e.optional = static_cast<int8_t>(atoi(row[27]));
e.npc_match_list = row[9] ? row[9] : "";
e.item_id_list = row[10] ? row[10] : "";
e.item_list = row[11] ? row[11] : "";
e.dz_switch_id = static_cast<int32_t>(atoi(row[12]));
e.min_x = strtof(row[13], nullptr);
e.min_y = strtof(row[14], nullptr);
e.min_z = strtof(row[15], nullptr);
e.max_x = strtof(row[16], nullptr);
e.max_y = strtof(row[17], nullptr);
e.max_z = strtof(row[18], nullptr);
e.skill_list = row[19] ? row[19] : "";
e.spell_list = row[20] ? row[20] : "";
e.zones = row[21] ? row[21] : "";
e.zone_version = static_cast<int32_t>(atoi(row[22]));
e.optional = static_cast<int8_t>(atoi(row[23]));
return e;
}
@ -292,25 +272,21 @@ public:
v.push_back(columns[6] + " = " + std::to_string(e.goalmethod));
v.push_back(columns[7] + " = " + std::to_string(e.goalcount));
v.push_back(columns[8] + " = '" + Strings::Escape(e.description_override) + "'");
v.push_back(columns[9] + " = " + std::to_string(e.npc_id));
v.push_back(columns[10] + " = " + std::to_string(e.npc_goal_id));
v.push_back(columns[11] + " = '" + Strings::Escape(e.npc_match_list) + "'");
v.push_back(columns[12] + " = " + std::to_string(e.item_id));
v.push_back(columns[13] + " = " + std::to_string(e.item_goal_id));
v.push_back(columns[14] + " = '" + Strings::Escape(e.item_id_list) + "'");
v.push_back(columns[15] + " = '" + Strings::Escape(e.item_list) + "'");
v.push_back(columns[16] + " = " + std::to_string(e.dz_switch_id));
v.push_back(columns[17] + " = " + std::to_string(e.min_x));
v.push_back(columns[18] + " = " + std::to_string(e.min_y));
v.push_back(columns[19] + " = " + std::to_string(e.min_z));
v.push_back(columns[20] + " = " + std::to_string(e.max_x));
v.push_back(columns[21] + " = " + std::to_string(e.max_y));
v.push_back(columns[22] + " = " + std::to_string(e.max_z));
v.push_back(columns[23] + " = '" + Strings::Escape(e.skill_list) + "'");
v.push_back(columns[24] + " = '" + Strings::Escape(e.spell_list) + "'");
v.push_back(columns[25] + " = '" + Strings::Escape(e.zones) + "'");
v.push_back(columns[26] + " = " + std::to_string(e.zone_version));
v.push_back(columns[27] + " = " + std::to_string(e.optional));
v.push_back(columns[9] + " = '" + Strings::Escape(e.npc_match_list) + "'");
v.push_back(columns[10] + " = '" + Strings::Escape(e.item_id_list) + "'");
v.push_back(columns[11] + " = '" + Strings::Escape(e.item_list) + "'");
v.push_back(columns[12] + " = " + std::to_string(e.dz_switch_id));
v.push_back(columns[13] + " = " + std::to_string(e.min_x));
v.push_back(columns[14] + " = " + std::to_string(e.min_y));
v.push_back(columns[15] + " = " + std::to_string(e.min_z));
v.push_back(columns[16] + " = " + std::to_string(e.max_x));
v.push_back(columns[17] + " = " + std::to_string(e.max_y));
v.push_back(columns[18] + " = " + std::to_string(e.max_z));
v.push_back(columns[19] + " = '" + Strings::Escape(e.skill_list) + "'");
v.push_back(columns[20] + " = '" + Strings::Escape(e.spell_list) + "'");
v.push_back(columns[21] + " = '" + Strings::Escape(e.zones) + "'");
v.push_back(columns[22] + " = " + std::to_string(e.zone_version));
v.push_back(columns[23] + " = " + std::to_string(e.optional));
auto results = db.QueryDatabase(
fmt::format(
@ -341,11 +317,7 @@ public:
v.push_back(std::to_string(e.goalmethod));
v.push_back(std::to_string(e.goalcount));
v.push_back("'" + Strings::Escape(e.description_override) + "'");
v.push_back(std::to_string(e.npc_id));
v.push_back(std::to_string(e.npc_goal_id));
v.push_back("'" + Strings::Escape(e.npc_match_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_goal_id));
v.push_back("'" + Strings::Escape(e.item_id_list) + "'");
v.push_back("'" + Strings::Escape(e.item_list) + "'");
v.push_back(std::to_string(e.dz_switch_id));
@ -398,11 +370,7 @@ public:
v.push_back(std::to_string(e.goalmethod));
v.push_back(std::to_string(e.goalcount));
v.push_back("'" + Strings::Escape(e.description_override) + "'");
v.push_back(std::to_string(e.npc_id));
v.push_back(std::to_string(e.npc_goal_id));
v.push_back("'" + Strings::Escape(e.npc_match_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_goal_id));
v.push_back("'" + Strings::Escape(e.item_id_list) + "'");
v.push_back("'" + Strings::Escape(e.item_list) + "'");
v.push_back(std::to_string(e.dz_switch_id));
@ -459,25 +427,21 @@ public:
e.goalmethod = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.goalcount = static_cast<int32_t>(atoi(row[7]));
e.description_override = row[8] ? row[8] : "";
e.npc_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.npc_goal_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.npc_match_list = row[11] ? row[11] : "";
e.item_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.item_goal_id = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.item_id_list = row[14] ? row[14] : "";
e.item_list = row[15] ? row[15] : "";
e.dz_switch_id = static_cast<int32_t>(atoi(row[16]));
e.min_x = strtof(row[17], nullptr);
e.min_y = strtof(row[18], nullptr);
e.min_z = strtof(row[19], nullptr);
e.max_x = strtof(row[20], nullptr);
e.max_y = strtof(row[21], nullptr);
e.max_z = strtof(row[22], nullptr);
e.skill_list = row[23] ? row[23] : "";
e.spell_list = row[24] ? row[24] : "";
e.zones = row[25] ? row[25] : "";
e.zone_version = static_cast<int32_t>(atoi(row[26]));
e.optional = static_cast<int8_t>(atoi(row[27]));
e.npc_match_list = row[9] ? row[9] : "";
e.item_id_list = row[10] ? row[10] : "";
e.item_list = row[11] ? row[11] : "";
e.dz_switch_id = static_cast<int32_t>(atoi(row[12]));
e.min_x = strtof(row[13], nullptr);
e.min_y = strtof(row[14], nullptr);
e.min_z = strtof(row[15], nullptr);
e.max_x = strtof(row[16], nullptr);
e.max_y = strtof(row[17], nullptr);
e.max_z = strtof(row[18], nullptr);
e.skill_list = row[19] ? row[19] : "";
e.spell_list = row[20] ? row[20] : "";
e.zones = row[21] ? row[21] : "";
e.zone_version = static_cast<int32_t>(atoi(row[22]));
e.optional = static_cast<int8_t>(atoi(row[23]));
all_entries.push_back(e);
}
@ -511,25 +475,21 @@ public:
e.goalmethod = static_cast<uint32_t>(strtoul(row[6], nullptr, 10));
e.goalcount = static_cast<int32_t>(atoi(row[7]));
e.description_override = row[8] ? row[8] : "";
e.npc_id = static_cast<uint32_t>(strtoul(row[9], nullptr, 10));
e.npc_goal_id = static_cast<uint32_t>(strtoul(row[10], nullptr, 10));
e.npc_match_list = row[11] ? row[11] : "";
e.item_id = static_cast<uint32_t>(strtoul(row[12], nullptr, 10));
e.item_goal_id = static_cast<uint32_t>(strtoul(row[13], nullptr, 10));
e.item_id_list = row[14] ? row[14] : "";
e.item_list = row[15] ? row[15] : "";
e.dz_switch_id = static_cast<int32_t>(atoi(row[16]));
e.min_x = strtof(row[17], nullptr);
e.min_y = strtof(row[18], nullptr);
e.min_z = strtof(row[19], nullptr);
e.max_x = strtof(row[20], nullptr);
e.max_y = strtof(row[21], nullptr);
e.max_z = strtof(row[22], nullptr);
e.skill_list = row[23] ? row[23] : "";
e.spell_list = row[24] ? row[24] : "";
e.zones = row[25] ? row[25] : "";
e.zone_version = static_cast<int32_t>(atoi(row[26]));
e.optional = static_cast<int8_t>(atoi(row[27]));
e.npc_match_list = row[9] ? row[9] : "";
e.item_id_list = row[10] ? row[10] : "";
e.item_list = row[11] ? row[11] : "";
e.dz_switch_id = static_cast<int32_t>(atoi(row[12]));
e.min_x = strtof(row[13], nullptr);
e.min_y = strtof(row[14], nullptr);
e.min_z = strtof(row[15], nullptr);
e.max_x = strtof(row[16], nullptr);
e.max_y = strtof(row[17], nullptr);
e.max_z = strtof(row[18], nullptr);
e.skill_list = row[19] ? row[19] : "";
e.spell_list = row[20] ? row[20] : "";
e.zones = row[21] ? row[21] : "";
e.zone_version = static_cast<int32_t>(atoi(row[22]));
e.optional = static_cast<int8_t>(atoi(row[23]));
all_entries.push_back(e);
}

View File

@ -77,11 +77,7 @@ struct ActivityInformation {
int spell_id; // older clients, first id from above
TaskMethodType goal_method;
int goal_count;
uint32_t npc_id;
uint32_t npc_goal_id;
std::string npc_match_list; // delimited by '|' for partial name matches but also supports ids
uint32_t item_id;
uint32_t item_goal_id;
std::string item_id_list; // delimited by '|' to support multiple item ids
int dz_switch_id;
float min_x;

View File

@ -34,7 +34,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9207
#define CURRENT_BINARY_DATABASE_VERSION 9208
#ifdef BOTS
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9029

View File

@ -461,6 +461,7 @@
9205|2022_09_03_fix_starting_point_heading.sql|SELECT * FROM db_version WHERE version >= 9205|empty|
9206|2022_09_03_fix_door_destination_headings.sql|SELECT * FROM db_version WHERE version >= 9206|empty|
9207|2022_09_03_fix_zone_point_heading_data.sql|SELECT * FROM db_version WHERE version >= 9207|empty|
9208|2022_09_25_task_concat_matchlists.sql|SHOW COLUMNS FROM `task_activities` LIKE 'npc_id'|not_empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not

View File

@ -0,0 +1,39 @@
-- npc id
UPDATE `task_activities`
SET `task_activities`.`npc_match_list` = CONCAT_WS('|', `npc_match_list`, `npc_id`)
WHERE npc_id != 0;
-- npc_goal_id goallists
UPDATE `task_activities`
INNER JOIN
(
SELECT `goallists`.`listid`, GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids`
FROM `goallists`
GROUP BY `goallists`.`listid`
) AS `goallist_group`
ON `task_activities`.`npc_goal_id` = `goallist_group`.`listid`
SET `task_activities`.`npc_match_list` = CONCAT_WS('|', `npc_match_list`, `goallist_ids`)
WHERE npc_goal_id != 0;
-- item id
UPDATE `task_activities`
SET `task_activities`.`item_id_list` = CONCAT_WS('|', `item_id_list`, `item_id`)
WHERE item_id != 0;
-- item_goal_id goallists
UPDATE `task_activities`
INNER JOIN
(
SELECT `goallists`.`listid`, GROUP_CONCAT(`goallists`.`entry` ORDER BY `goallists`.`entry` SEPARATOR '|') AS `goallist_ids`
FROM `goallists`
GROUP BY `goallists`.`listid`
) AS `goallist_group`
ON `task_activities`.`item_goal_id` = `goallist_group`.`listid`
SET `task_activities`.`item_id_list` = CONCAT_WS('|', `item_id_list`, `goallist_ids`)
WHERE item_goal_id != 0;
ALTER TABLE `task_activities`
DROP COLUMN `npc_id`,
DROP COLUMN `npc_goal_id`,
DROP COLUMN `item_id`,
DROP COLUMN `item_goal_id`;

View File

@ -492,19 +492,6 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter,
return false;
}
// item is only checked for updates that provide an item (unlike npc which may be null for non-npcs)
if (activity.item_id != 0 && filter.item_id != 0 && activity.item_id != filter.item_id)
{
LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed item id filter", client->GetName(), task_id, client_activity.activity_id);
return false;
}
if (activity.npc_id != 0 && (!filter.npc || activity.npc_id != filter.npc->GetNPCTypeID()))
{
LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed npc id filter", client->GetName(), task_id, client_activity.activity_id);
return false;
}
if (!activity.CheckZone(zone->GetZoneID(), zone->GetInstanceVersion()))
{
LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed zone filter", client->GetName(), task_id, client_activity.activity_id);
@ -523,13 +510,7 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter,
}
}
if (activity.item_goal_id != 0 && filter.item_id != 0 &&
!task_manager->m_goal_list_manager.IsInList(activity.item_goal_id, filter.item_id))
{
LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed item goallist filter", client->GetName(), task_id, client_activity.activity_id);
return false;
}
// item is only checked for updates that provide an item to check (unlike npc which may be null for non-npcs)
if (!activity.item_id_list.empty() && filter.item_id != 0 &&
!TaskGoalListManager::IsInMatchList(activity.item_id_list, std::to_string(filter.item_id)))
{
@ -537,13 +518,6 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter,
return false;
}
if (activity.npc_goal_id != 0 && (!filter.npc ||
!task_manager->m_goal_list_manager.IsInList(activity.npc_goal_id, filter.npc->GetNPCTypeID())))
{
LogTasks("[CanUpdate] client [{}] task [{}]-[{}] failed npc goallist filter", client->GetName(), task_id, client_activity.activity_id);
return false;
}
// npc filter supports both npc names and ids in match lists
if (!activity.npc_match_list.empty() && (!filter.npc ||
(!TaskGoalListManager::IsInMatchListPartial(activity.npc_match_list, filter.npc->GetName()) &&

View File

@ -212,11 +212,7 @@ bool TaskManager::LoadTasks(int single_task)
activity_data->spell_list = task_activity.spell_list;
activity_data->spell_id = Strings::IsNumber(task_activity.spell_list) ? std::stoi(task_activity.spell_list) : 0; // for older clients
activity_data->description_override = task_activity.description_override;
activity_data->npc_id = task_activity.npc_id;
activity_data->npc_goal_id = task_activity.npc_goal_id;
activity_data->npc_match_list = task_activity.npc_match_list;
activity_data->item_id = task_activity.item_id;
activity_data->item_goal_id = task_activity.item_goal_id;
activity_data->item_id_list = task_activity.item_id_list;
activity_data->dz_switch_id = task_activity.dz_switch_id;
activity_data->goal_method = (TaskMethodType) task_activity.goalmethod;