From c21d47f450f18775350a8f193e2216e24abff36c Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sat, 4 Mar 2023 18:24:16 -0500 Subject: [PATCH] [Scaling] Add support for pipe-separated zone IDs and versions (#3015) * [Scaling] Add support for pipe-separated zone IDs and versions # Notes - Allows `|` separated zone IDs and instance versions within the scaling data. - Loads scaling data on zone bootup as well, without needing to repop for it to initialize. * Cleanup --- .../base_npc_scale_global_base_repository.h | 264 +++++++++--------- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + ..._28_npc_scaling_zone_list_version_list.sql | 5 + zone/npc_scale_manager.cpp | 102 ++++++- zone/zone.cpp | 2 + 6 files changed, 230 insertions(+), 146 deletions(-) create mode 100644 utils/sql/git/required/2023_02_28_npc_scaling_zone_list_version_list.sql diff --git a/common/repositories/base/base_npc_scale_global_base_repository.h b/common/repositories/base/base_npc_scale_global_base_repository.h index d09165c5c..838034792 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -22,8 +22,8 @@ public: struct NpcScaleGlobalBase { int32_t type; int32_t level; - uint32_t zone_id; - int32_t instance_version; + std::string zone_id_list; + std::string instance_version_list; int32_t ac; int32_t hp; int32_t accuracy; @@ -62,8 +62,8 @@ public: return { "type", "level", - "zone_id", - "instance_version", + "zone_id_list", + "instance_version_list", "ac", "hp", "accuracy", @@ -98,8 +98,8 @@ public: return { "type", "level", - "zone_id", - "instance_version", + "zone_id_list", + "instance_version_list", "ac", "hp", "accuracy", @@ -166,36 +166,36 @@ public: { NpcScaleGlobalBase e{}; - e.type = 0; - e.level = 0; - e.zone_id = 0; - e.instance_version = -1; - e.ac = 0; - e.hp = 0; - e.accuracy = 0; - e.slow_mitigation = 0; - e.attack = 0; - e.strength = 0; - e.stamina = 0; - e.dexterity = 0; - e.agility = 0; - e.intelligence = 0; - e.wisdom = 0; - e.charisma = 0; - e.magic_resist = 0; - e.cold_resist = 0; - e.fire_resist = 0; - e.poison_resist = 0; - e.disease_resist = 0; - e.corruption_resist = 0; - e.physical_resist = 0; - e.min_dmg = 0; - e.max_dmg = 0; - e.hp_regen_rate = 0; - e.attack_delay = 0; - e.spell_scale = 100; - e.heal_scale = 100; - e.special_abilities = ""; + e.type = 0; + e.level = 0; + e.zone_id_list = ""; + e.instance_version_list = ""; + e.ac = 0; + e.hp = 0; + e.accuracy = 0; + e.slow_mitigation = 0; + e.attack = 0; + e.strength = 0; + e.stamina = 0; + e.dexterity = 0; + e.agility = 0; + e.intelligence = 0; + e.wisdom = 0; + e.charisma = 0; + e.magic_resist = 0; + e.cold_resist = 0; + e.fire_resist = 0; + e.poison_resist = 0; + e.disease_resist = 0; + e.corruption_resist = 0; + e.physical_resist = 0; + e.min_dmg = 0; + e.max_dmg = 0; + e.hp_regen_rate = 0; + e.attack_delay = 0; + e.spell_scale = 100; + e.heal_scale = 100; + e.special_abilities = ""; return e; } @@ -232,36 +232,36 @@ public: if (results.RowCount() == 1) { NpcScaleGlobalBase e{}; - e.type = static_cast(atoi(row[0])); - e.level = static_cast(atoi(row[1])); - e.zone_id = static_cast(strtoul(row[2], nullptr, 10)); - e.instance_version = static_cast(atoi(row[3])); - e.ac = static_cast(atoi(row[4])); - e.hp = static_cast(atoi(row[5])); - e.accuracy = static_cast(atoi(row[6])); - e.slow_mitigation = static_cast(atoi(row[7])); - e.attack = static_cast(atoi(row[8])); - e.strength = static_cast(atoi(row[9])); - e.stamina = static_cast(atoi(row[10])); - e.dexterity = static_cast(atoi(row[11])); - e.agility = static_cast(atoi(row[12])); - e.intelligence = static_cast(atoi(row[13])); - e.wisdom = static_cast(atoi(row[14])); - e.charisma = static_cast(atoi(row[15])); - e.magic_resist = static_cast(atoi(row[16])); - e.cold_resist = static_cast(atoi(row[17])); - e.fire_resist = static_cast(atoi(row[18])); - e.poison_resist = static_cast(atoi(row[19])); - e.disease_resist = static_cast(atoi(row[20])); - e.corruption_resist = static_cast(atoi(row[21])); - e.physical_resist = static_cast(atoi(row[22])); - e.min_dmg = static_cast(atoi(row[23])); - e.max_dmg = static_cast(atoi(row[24])); - e.hp_regen_rate = static_cast(atoi(row[25])); - e.attack_delay = static_cast(atoi(row[26])); - e.spell_scale = static_cast(atoi(row[27])); - e.heal_scale = static_cast(atoi(row[28])); - e.special_abilities = row[29] ? row[29] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.zone_id_list = row[2] ? row[2] : ""; + e.instance_version_list = row[3] ? row[3] : ""; + e.ac = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + e.accuracy = static_cast(atoi(row[6])); + e.slow_mitigation = static_cast(atoi(row[7])); + e.attack = static_cast(atoi(row[8])); + e.strength = static_cast(atoi(row[9])); + e.stamina = static_cast(atoi(row[10])); + e.dexterity = static_cast(atoi(row[11])); + e.agility = static_cast(atoi(row[12])); + e.intelligence = static_cast(atoi(row[13])); + e.wisdom = static_cast(atoi(row[14])); + e.charisma = static_cast(atoi(row[15])); + e.magic_resist = static_cast(atoi(row[16])); + e.cold_resist = static_cast(atoi(row[17])); + e.fire_resist = static_cast(atoi(row[18])); + e.poison_resist = static_cast(atoi(row[19])); + e.disease_resist = static_cast(atoi(row[20])); + e.corruption_resist = static_cast(atoi(row[21])); + e.physical_resist = static_cast(atoi(row[22])); + e.min_dmg = static_cast(atoi(row[23])); + e.max_dmg = static_cast(atoi(row[24])); + e.hp_regen_rate = static_cast(atoi(row[25])); + e.attack_delay = static_cast(atoi(row[26])); + e.spell_scale = static_cast(atoi(row[27])); + e.heal_scale = static_cast(atoi(row[28])); + e.special_abilities = row[29] ? row[29] : ""; return e; } @@ -297,8 +297,8 @@ public: v.push_back(columns[0] + " = " + std::to_string(e.type)); v.push_back(columns[1] + " = " + std::to_string(e.level)); - v.push_back(columns[2] + " = " + std::to_string(e.zone_id)); - v.push_back(columns[3] + " = " + std::to_string(e.instance_version)); + v.push_back(columns[2] + " = '" + Strings::Escape(e.zone_id_list) + "'"); + v.push_back(columns[3] + " = '" + Strings::Escape(e.instance_version_list) + "'"); v.push_back(columns[4] + " = " + std::to_string(e.ac)); v.push_back(columns[5] + " = " + std::to_string(e.hp)); v.push_back(columns[6] + " = " + std::to_string(e.accuracy)); @@ -348,8 +348,8 @@ public: v.push_back(std::to_string(e.type)); v.push_back(std::to_string(e.level)); - v.push_back(std::to_string(e.zone_id)); - v.push_back(std::to_string(e.instance_version)); + v.push_back("'" + Strings::Escape(e.zone_id_list) + "'"); + v.push_back("'" + Strings::Escape(e.instance_version_list) + "'"); v.push_back(std::to_string(e.ac)); v.push_back(std::to_string(e.hp)); v.push_back(std::to_string(e.accuracy)); @@ -407,8 +407,8 @@ public: v.push_back(std::to_string(e.type)); v.push_back(std::to_string(e.level)); - v.push_back(std::to_string(e.zone_id)); - v.push_back(std::to_string(e.instance_version)); + v.push_back("'" + Strings::Escape(e.zone_id_list) + "'"); + v.push_back("'" + Strings::Escape(e.instance_version_list) + "'"); v.push_back(std::to_string(e.ac)); v.push_back(std::to_string(e.hp)); v.push_back(std::to_string(e.accuracy)); @@ -468,36 +468,36 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { NpcScaleGlobalBase e{}; - e.type = static_cast(atoi(row[0])); - e.level = static_cast(atoi(row[1])); - e.zone_id = static_cast(strtoul(row[2], nullptr, 10)); - e.instance_version = static_cast(atoi(row[3])); - e.ac = static_cast(atoi(row[4])); - e.hp = static_cast(atoi(row[5])); - e.accuracy = static_cast(atoi(row[6])); - e.slow_mitigation = static_cast(atoi(row[7])); - e.attack = static_cast(atoi(row[8])); - e.strength = static_cast(atoi(row[9])); - e.stamina = static_cast(atoi(row[10])); - e.dexterity = static_cast(atoi(row[11])); - e.agility = static_cast(atoi(row[12])); - e.intelligence = static_cast(atoi(row[13])); - e.wisdom = static_cast(atoi(row[14])); - e.charisma = static_cast(atoi(row[15])); - e.magic_resist = static_cast(atoi(row[16])); - e.cold_resist = static_cast(atoi(row[17])); - e.fire_resist = static_cast(atoi(row[18])); - e.poison_resist = static_cast(atoi(row[19])); - e.disease_resist = static_cast(atoi(row[20])); - e.corruption_resist = static_cast(atoi(row[21])); - e.physical_resist = static_cast(atoi(row[22])); - e.min_dmg = static_cast(atoi(row[23])); - e.max_dmg = static_cast(atoi(row[24])); - e.hp_regen_rate = static_cast(atoi(row[25])); - e.attack_delay = static_cast(atoi(row[26])); - e.spell_scale = static_cast(atoi(row[27])); - e.heal_scale = static_cast(atoi(row[28])); - e.special_abilities = row[29] ? row[29] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.zone_id_list = row[2] ? row[2] : ""; + e.instance_version_list = row[3] ? row[3] : ""; + e.ac = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + e.accuracy = static_cast(atoi(row[6])); + e.slow_mitigation = static_cast(atoi(row[7])); + e.attack = static_cast(atoi(row[8])); + e.strength = static_cast(atoi(row[9])); + e.stamina = static_cast(atoi(row[10])); + e.dexterity = static_cast(atoi(row[11])); + e.agility = static_cast(atoi(row[12])); + e.intelligence = static_cast(atoi(row[13])); + e.wisdom = static_cast(atoi(row[14])); + e.charisma = static_cast(atoi(row[15])); + e.magic_resist = static_cast(atoi(row[16])); + e.cold_resist = static_cast(atoi(row[17])); + e.fire_resist = static_cast(atoi(row[18])); + e.poison_resist = static_cast(atoi(row[19])); + e.disease_resist = static_cast(atoi(row[20])); + e.corruption_resist = static_cast(atoi(row[21])); + e.physical_resist = static_cast(atoi(row[22])); + e.min_dmg = static_cast(atoi(row[23])); + e.max_dmg = static_cast(atoi(row[24])); + e.hp_regen_rate = static_cast(atoi(row[25])); + e.attack_delay = static_cast(atoi(row[26])); + e.spell_scale = static_cast(atoi(row[27])); + e.heal_scale = static_cast(atoi(row[28])); + e.special_abilities = row[29] ? row[29] : ""; all_entries.push_back(e); } @@ -522,36 +522,36 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { NpcScaleGlobalBase e{}; - e.type = static_cast(atoi(row[0])); - e.level = static_cast(atoi(row[1])); - e.zone_id = static_cast(strtoul(row[2], nullptr, 10)); - e.instance_version = static_cast(atoi(row[3])); - e.ac = static_cast(atoi(row[4])); - e.hp = static_cast(atoi(row[5])); - e.accuracy = static_cast(atoi(row[6])); - e.slow_mitigation = static_cast(atoi(row[7])); - e.attack = static_cast(atoi(row[8])); - e.strength = static_cast(atoi(row[9])); - e.stamina = static_cast(atoi(row[10])); - e.dexterity = static_cast(atoi(row[11])); - e.agility = static_cast(atoi(row[12])); - e.intelligence = static_cast(atoi(row[13])); - e.wisdom = static_cast(atoi(row[14])); - e.charisma = static_cast(atoi(row[15])); - e.magic_resist = static_cast(atoi(row[16])); - e.cold_resist = static_cast(atoi(row[17])); - e.fire_resist = static_cast(atoi(row[18])); - e.poison_resist = static_cast(atoi(row[19])); - e.disease_resist = static_cast(atoi(row[20])); - e.corruption_resist = static_cast(atoi(row[21])); - e.physical_resist = static_cast(atoi(row[22])); - e.min_dmg = static_cast(atoi(row[23])); - e.max_dmg = static_cast(atoi(row[24])); - e.hp_regen_rate = static_cast(atoi(row[25])); - e.attack_delay = static_cast(atoi(row[26])); - e.spell_scale = static_cast(atoi(row[27])); - e.heal_scale = static_cast(atoi(row[28])); - e.special_abilities = row[29] ? row[29] : ""; + e.type = static_cast(atoi(row[0])); + e.level = static_cast(atoi(row[1])); + e.zone_id_list = row[2] ? row[2] : ""; + e.instance_version_list = row[3] ? row[3] : ""; + e.ac = static_cast(atoi(row[4])); + e.hp = static_cast(atoi(row[5])); + e.accuracy = static_cast(atoi(row[6])); + e.slow_mitigation = static_cast(atoi(row[7])); + e.attack = static_cast(atoi(row[8])); + e.strength = static_cast(atoi(row[9])); + e.stamina = static_cast(atoi(row[10])); + e.dexterity = static_cast(atoi(row[11])); + e.agility = static_cast(atoi(row[12])); + e.intelligence = static_cast(atoi(row[13])); + e.wisdom = static_cast(atoi(row[14])); + e.charisma = static_cast(atoi(row[15])); + e.magic_resist = static_cast(atoi(row[16])); + e.cold_resist = static_cast(atoi(row[17])); + e.fire_resist = static_cast(atoi(row[18])); + e.poison_resist = static_cast(atoi(row[19])); + e.disease_resist = static_cast(atoi(row[20])); + e.corruption_resist = static_cast(atoi(row[21])); + e.physical_resist = static_cast(atoi(row[22])); + e.min_dmg = static_cast(atoi(row[23])); + e.max_dmg = static_cast(atoi(row[24])); + e.hp_regen_rate = static_cast(atoi(row[25])); + e.attack_delay = static_cast(atoi(row[26])); + e.spell_scale = static_cast(atoi(row[27])); + e.heal_scale = static_cast(atoi(row[28])); + e.special_abilities = row[29] ? row[29] : ""; all_entries.push_back(e); } diff --git a/common/version.h b/common/version.h index 3b491950a..513869017 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9221 +#define CURRENT_BINARY_DATABASE_VERSION 9222 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9038 #endif diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index d67f0e821..73a19d52b 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -475,6 +475,7 @@ 9219|2023_01_29_merchant_status_requirements.sql|SHOW COLUMNS FROM merchantlist LIKE 'min_status'|empty| 9220|2022_12_19_player_events_tables.sql|SHOW TABLES LIKE 'player_event_logs'|empty| 9221|2023_02_24_npc_scaling_zone_id_instance_version.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'zone_id'|empty| +9222|2023_02_28_npc_scaling_zone_list_version_list.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'zone_id_list'|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/2023_02_28_npc_scaling_zone_list_version_list.sql b/utils/sql/git/required/2023_02_28_npc_scaling_zone_list_version_list.sql new file mode 100644 index 000000000..f97140973 --- /dev/null +++ b/utils/sql/git/required/2023_02_28_npc_scaling_zone_list_version_list.sql @@ -0,0 +1,5 @@ +ALTER TABLE `npc_scale_global_base` + CHANGE COLUMN `zone_id` `zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 0 AFTER `level`, + CHANGE COLUMN `instance_version` `instance_version_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT 0 AFTER `zone_id_list`, + DROP PRIMARY KEY, + ADD PRIMARY KEY (`type`, `level`, `zone_id_list`(255), `instance_version_list`(255)) USING BTREE; diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index 512876f8c..494187aa2 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -216,12 +216,17 @@ bool NpcScaleManager::LoadScaleData() { auto rows = NpcScaleGlobalBaseRepository::All(content_db); for (const auto &s : rows) { + if ( + s.zone_id_list.empty() || + s.instance_version_list.empty() + ) { + continue; + } + global_npc_scale scale_data; scale_data.type = s.type; scale_data.level = s.level; - scale_data.zone_id = s.zone_id; - scale_data.instance_version = s.instance_version; scale_data.ac = s.ac; scale_data.hp = s.hp; scale_data.accuracy = s.accuracy; @@ -252,17 +257,88 @@ bool NpcScaleManager::LoadScaleData() scale_data.special_abilities = s.special_abilities; } - npc_global_base_scaling_data.insert( - std::make_pair( - std::make_tuple( - scale_data.type, - scale_data.level, - scale_data.zone_id, - scale_data.instance_version - ), - scale_data - ) - ); + const auto has_multiple_zones = Strings::Contains(s.zone_id_list, "|"); + const auto has_multiple_versions = Strings::Contains(s.instance_version_list, "|"); + + if (!has_multiple_zones && !has_multiple_versions) { + scale_data.zone_id = std::stoul(s.zone_id_list); + scale_data.instance_version = static_cast(std::stoul(s.instance_version_list)); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } else if (has_multiple_zones && !has_multiple_versions) { + scale_data.instance_version = static_cast(std::stoul(s.instance_version_list)); + + const auto zones = Strings::Split(s.zone_id_list, "|"); + + for (const auto &z : zones) { + scale_data.zone_id = std::stoul(z); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } + } else if (!has_multiple_zones && has_multiple_versions) { + scale_data.zone_id = std::stoul(s.zone_id_list); + + const auto versions = Strings::Split(s.instance_version_list, "|"); + + for (const auto &v : versions) { + scale_data.instance_version = static_cast(std::stoul(v)); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } + } else if (has_multiple_zones && has_multiple_versions) { + const auto zones = Strings::Split(s.zone_id_list, "|"); + const auto versions = Strings::Split(s.instance_version_list, "|"); + + for (const auto &z : zones) { + scale_data.zone_id = std::stoul(z); + + for (const auto &v : versions) { + scale_data.instance_version = static_cast(std::stoul(v)); + + npc_global_base_scaling_data.insert( + std::make_pair( + std::make_tuple( + scale_data.type, + scale_data.level, + scale_data.zone_id, + scale_data.instance_version + ), + scale_data + ) + ); + } + } + } } LogInfo("Loaded [{}] global scaling data entries", Strings::Commify(rows.size())); diff --git a/zone/zone.cpp b/zone/zone.cpp index 97e5b74c9..287856f82 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1218,6 +1218,8 @@ bool Zone::Init(bool is_static) { LoadGrids(); LoadTickItems(); + npc_scale_manager->LoadScaleData(); + // logging origination information LogSys.origination_info.zone_short_name = zone->short_name; LogSys.origination_info.zone_long_name = zone->long_name;