From f030461bc7c45ab743ca6498e35c7f5f88d7f97b Mon Sep 17 00:00:00 2001 From: Alex King <89047260+Kinglykrab@users.noreply.github.com> Date: Sun, 5 Mar 2023 22:36:53 -0500 Subject: [PATCH] [Feature] Add Heroic Strikethrough to NPC Scaling (#3028) * [Feature] Add Heroic Strikethrough to NPC Scaling # Notes - Adds Heroic Strikethrough support to NPC scaling. - Cleans up `std::stoul` to use `Strings::ToUnsignedInt` since recent changes. - Sets default values to sane values and removes support for `NULL` values. * Update 2023_03_04_npc_scale_global_base_heroic_strikethrough.sql --- .../base_npc_scale_global_base_repository.h | 10 + common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + ...scale_global_base_heroic_strikethrough.sql | 55 ++++++ zone/npc_scale_manager.cpp | 181 +++++++++--------- zone/npc_scale_manager.h | 1 + 6 files changed, 162 insertions(+), 88 deletions(-) create mode 100644 utils/sql/git/required/2023_03_04_npc_scale_global_base_heroic_strikethrough.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 838034792..0a90d5300 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -50,6 +50,7 @@ public: int32_t spell_scale; int32_t heal_scale; std::string special_abilities; + int32_t heroic_strikethrough; }; static std::string PrimaryKey() @@ -90,6 +91,7 @@ public: "spell_scale", "heal_scale", "special_abilities", + "heroic_strikethrough", }; } @@ -126,6 +128,7 @@ public: "spell_scale", "heal_scale", "special_abilities", + "heroic_strikethrough", }; } @@ -196,6 +199,7 @@ public: e.spell_scale = 100; e.heal_scale = 100; e.special_abilities = ""; + e.heroic_strikethrough = 0; return e; } @@ -262,6 +266,7 @@ public: e.spell_scale = static_cast(atoi(row[27])); e.heal_scale = static_cast(atoi(row[28])); e.special_abilities = row[29] ? row[29] : ""; + e.heroic_strikethrough = static_cast(atoi(row[30])); return e; } @@ -325,6 +330,7 @@ public: v.push_back(columns[27] + " = " + std::to_string(e.spell_scale)); v.push_back(columns[28] + " = " + std::to_string(e.heal_scale)); v.push_back(columns[29] + " = '" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(columns[30] + " = " + std::to_string(e.heroic_strikethrough)); auto results = db.QueryDatabase( fmt::format( @@ -376,6 +382,7 @@ public: v.push_back(std::to_string(e.spell_scale)); v.push_back(std::to_string(e.heal_scale)); v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(std::to_string(e.heroic_strikethrough)); auto results = db.QueryDatabase( fmt::format( @@ -435,6 +442,7 @@ public: v.push_back(std::to_string(e.spell_scale)); v.push_back(std::to_string(e.heal_scale)); v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); + v.push_back(std::to_string(e.heroic_strikethrough)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -498,6 +506,7 @@ public: e.spell_scale = static_cast(atoi(row[27])); e.heal_scale = static_cast(atoi(row[28])); e.special_abilities = row[29] ? row[29] : ""; + e.heroic_strikethrough = static_cast(atoi(row[30])); all_entries.push_back(e); } @@ -552,6 +561,7 @@ public: e.spell_scale = static_cast(atoi(row[27])); e.heal_scale = static_cast(atoi(row[28])); e.special_abilities = row[29] ? row[29] : ""; + e.heroic_strikethrough = static_cast(atoi(row[30])); all_entries.push_back(e); } diff --git a/common/version.h b/common/version.h index 513869017..261c8f6f4 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 9222 +#define CURRENT_BINARY_DATABASE_VERSION 9223 #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 73a19d52b..a1a1a366d 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -476,6 +476,7 @@ 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| +9223|2023_03_04_npc_scale_global_base_heroic_strikethrough.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'heroic_strikethrough'|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_03_04_npc_scale_global_base_heroic_strikethrough.sql b/utils/sql/git/required/2023_03_04_npc_scale_global_base_heroic_strikethrough.sql new file mode 100644 index 000000000..6559cb0a0 --- /dev/null +++ b/utils/sql/git/required/2023_03_04_npc_scale_global_base_heroic_strikethrough.sql @@ -0,0 +1,55 @@ +UPDATE `npc_scale_global_base` SET ac = 0 WHERE ac IS NULL; +UPDATE `npc_scale_global_base` SET hp = 0 WHERE hp IS NULL; +UPDATE `npc_scale_global_base` SET accuracy = 0 WHERE accuracy IS NULL; +UPDATE `npc_scale_global_base` SET slow_mitigation = 0 WHERE slow_mitigation IS NULL; +UPDATE `npc_scale_global_base` SET attack = 0 WHERE attack IS NULL; +UPDATE `npc_scale_global_base` SET strength = 0 WHERE strength IS NULL; +UPDATE `npc_scale_global_base` SET stamina = 0 WHERE stamina IS NULL; +UPDATE `npc_scale_global_base` SET dexterity = 0 WHERE dexterity IS NULL; +UPDATE `npc_scale_global_base` SET agility = 0 WHERE agility IS NULL; +UPDATE `npc_scale_global_base` SET intelligence = 0 WHERE intelligence IS NULL; +UPDATE `npc_scale_global_base` SET wisdom = 0 WHERE wisdom IS NULL; +UPDATE `npc_scale_global_base` SET charisma = 0 WHERE charisma IS NULL; +UPDATE `npc_scale_global_base` SET magic_resist = 0 WHERE magic_resist IS NULL; +UPDATE `npc_scale_global_base` SET cold_resist = 0 WHERE cold_resist IS NULL; +UPDATE `npc_scale_global_base` SET fire_resist = 0 WHERE fire_resist IS NULL; +UPDATE `npc_scale_global_base` SET poison_resist = 0 WHERE poison_resist IS NULL; +UPDATE `npc_scale_global_base` SET disease_resist = 0 WHERE disease_resist IS NULL; +UPDATE `npc_scale_global_base` SET corruption_resist = 0 WHERE corruption_resist IS NULL; +UPDATE `npc_scale_global_base` SET physical_resist = 0 WHERE physical_resist IS NULL; +UPDATE `npc_scale_global_base` SET min_dmg = 0 WHERE min_dmg IS NULL; +UPDATE `npc_scale_global_base` SET max_dmg = 0 WHERE max_dmg IS NULL; +UPDATE `npc_scale_global_base` SET hp_regen_rate = 0 WHERE hp_regen_rate IS NULL; +UPDATE `npc_scale_global_base` SET attack_delay = 0 WHERE attack_delay IS NULL; +UPDATE `npc_scale_global_base` SET physical_resist = 0 WHERE physical_resist IS NULL; +UPDATE `npc_scale_global_base` SET spell_scale = 100 WHERE spell_scale IS NULL; +UPDATE `npc_scale_global_base` SET heal_scale = 100 WHERE heal_scale IS NULL; +UPDATE `npc_scale_global_base` SET special_abilities = '' WHERE special_abilities IS NULL; +ALTER TABLE `npc_scale_global_base` + MODIFY COLUMN `ac` int(11) NOT NULL DEFAULT 0 AFTER `instance_version_list`, + MODIFY COLUMN `hp` int(11) NOT NULL DEFAULT 0 AFTER `ac`, + MODIFY COLUMN `accuracy` int(11) NOT NULL DEFAULT 0 AFTER `hp`, + MODIFY COLUMN `slow_mitigation` int(11) NOT NULL DEFAULT 0 AFTER `accuracy`, + MODIFY COLUMN `attack` int(11) NOT NULL DEFAULT 0 AFTER `slow_mitigation`, + MODIFY COLUMN `strength` int(11) NOT NULL DEFAULT 0 AFTER `attack`, + MODIFY COLUMN `stamina` int(11) NOT NULL DEFAULT 0 AFTER `strength`, + MODIFY COLUMN `dexterity` int(11) NOT NULL DEFAULT 0 AFTER `stamina`, + MODIFY COLUMN `agility` int(11) NOT NULL DEFAULT 0 AFTER `dexterity`, + MODIFY COLUMN `intelligence` int(11) NOT NULL DEFAULT 0 AFTER `agility`, + MODIFY COLUMN `wisdom` int(11) NOT NULL DEFAULT 0 AFTER `intelligence`, + MODIFY COLUMN `charisma` int(11) NOT NULL DEFAULT 0 AFTER `wisdom`, + MODIFY COLUMN `magic_resist` int(11) NOT NULL DEFAULT 0 AFTER `charisma`, + MODIFY COLUMN `cold_resist` int(11) NOT NULL DEFAULT 0 AFTER `magic_resist`, + MODIFY COLUMN `fire_resist` int(11) NOT NULL DEFAULT 0 AFTER `cold_resist`, + MODIFY COLUMN `poison_resist` int(11) NOT NULL DEFAULT 0 AFTER `fire_resist`, + MODIFY COLUMN `disease_resist` int(11) NOT NULL DEFAULT 0 AFTER `poison_resist`, + MODIFY COLUMN `corruption_resist` int(11) NOT NULL DEFAULT 0 AFTER `disease_resist`, + MODIFY COLUMN `physical_resist` int(11) NOT NULL DEFAULT 0 AFTER `corruption_resist`, + MODIFY COLUMN `min_dmg` int(11) NOT NULL DEFAULT 0 AFTER `physical_resist`, + MODIFY COLUMN `max_dmg` int(11) NOT NULL DEFAULT 0 AFTER `min_dmg`, + MODIFY COLUMN `hp_regen_rate` int(11) NOT NULL DEFAULT 0 AFTER `max_dmg`, + MODIFY COLUMN `attack_delay` int(11) NOT NULL DEFAULT 0 AFTER `hp_regen_rate`, + MODIFY COLUMN `spell_scale` int(11) NOT NULL DEFAULT 100 AFTER `attack_delay`, + MODIFY COLUMN `heal_scale` int(11) NOT NULL DEFAULT 100 AFTER `spell_scale`, + MODIFY COLUMN `special_abilities` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `heal_scale`, + ADD COLUMN `heroic_strikethrough` int(11) NOT NULL DEFAULT 0 AFTER `heal_scale`; diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index 494187aa2..d1d076c7b 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -176,6 +176,10 @@ void NpcScaleManager::ScaleNPC( npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale)); } + if (always_scale || npc->GetHeroicStrikethrough() == 0) { + npc->ModifyNPCStat("heroic_strikethrough", std::to_string(scale_data.heroic_strikethrough)); + } + if (override_special_abilities || (!npc->HasSpecialAbilities() && is_auto_scaled)) { npc->ModifyNPCStat("special_abilities", scale_data.special_abilities); } @@ -225,33 +229,34 @@ bool NpcScaleManager::LoadScaleData() global_npc_scale scale_data; - scale_data.type = s.type; - scale_data.level = s.level; - scale_data.ac = s.ac; - scale_data.hp = s.hp; - scale_data.accuracy = s.accuracy; - scale_data.slow_mitigation = s.slow_mitigation; - scale_data.attack = s.attack; - scale_data.strength = s.strength; - scale_data.stamina = s.stamina; - scale_data.dexterity = s.dexterity; - scale_data.agility = s.agility; - scale_data.intelligence = s.intelligence; - scale_data.wisdom = s.wisdom; - scale_data.charisma = s.charisma; - scale_data.magic_resist = s.magic_resist; - scale_data.cold_resist = s.cold_resist; - scale_data.fire_resist = s.fire_resist; - scale_data.poison_resist = s.poison_resist; - scale_data.disease_resist = s.disease_resist; - scale_data.corruption_resist = s.corruption_resist; - scale_data.physical_resist = s.physical_resist; - scale_data.min_dmg = s.min_dmg; - scale_data.max_dmg = s.max_dmg; - scale_data.hp_regen_rate = s.hp_regen_rate; - scale_data.attack_delay = s.attack_delay; - scale_data.spell_scale = s.spell_scale; - scale_data.heal_scale = s.heal_scale; + scale_data.type = s.type; + scale_data.level = s.level; + scale_data.ac = s.ac; + scale_data.hp = s.hp; + scale_data.accuracy = s.accuracy; + scale_data.slow_mitigation = s.slow_mitigation; + scale_data.attack = s.attack; + scale_data.strength = s.strength; + scale_data.stamina = s.stamina; + scale_data.dexterity = s.dexterity; + scale_data.agility = s.agility; + scale_data.intelligence = s.intelligence; + scale_data.wisdom = s.wisdom; + scale_data.charisma = s.charisma; + scale_data.magic_resist = s.magic_resist; + scale_data.cold_resist = s.cold_resist; + scale_data.fire_resist = s.fire_resist; + scale_data.poison_resist = s.poison_resist; + scale_data.disease_resist = s.disease_resist; + scale_data.corruption_resist = s.corruption_resist; + scale_data.physical_resist = s.physical_resist; + scale_data.min_dmg = s.min_dmg; + scale_data.max_dmg = s.max_dmg; + scale_data.hp_regen_rate = s.hp_regen_rate; + scale_data.attack_delay = s.attack_delay; + scale_data.spell_scale = s.spell_scale; + scale_data.heal_scale = s.heal_scale; + scale_data.heroic_strikethrough = s.heroic_strikethrough; if (!s.special_abilities.empty()) { scale_data.special_abilities = s.special_abilities; @@ -261,8 +266,8 @@ bool NpcScaleManager::LoadScaleData() 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)); + scale_data.zone_id = Strings::ToUnsignedInt(s.zone_id_list); + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(s.instance_version_list)); npc_global_base_scaling_data.insert( std::make_pair( @@ -276,12 +281,12 @@ bool NpcScaleManager::LoadScaleData() ) ); } else if (has_multiple_zones && !has_multiple_versions) { - scale_data.instance_version = static_cast(std::stoul(s.instance_version_list)); + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(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); + scale_data.zone_id = Strings::ToUnsignedInt(z); npc_global_base_scaling_data.insert( std::make_pair( @@ -296,12 +301,12 @@ bool NpcScaleManager::LoadScaleData() ); } } else if (!has_multiple_zones && has_multiple_versions) { - scale_data.zone_id = std::stoul(s.zone_id_list); + scale_data.zone_id = Strings::ToUnsignedInt(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)); + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(v)); npc_global_base_scaling_data.insert( std::make_pair( @@ -320,10 +325,10 @@ bool NpcScaleManager::LoadScaleData() const auto versions = Strings::Split(s.instance_version_list, "|"); for (const auto &z : zones) { - scale_data.zone_id = std::stoul(z); + scale_data.zone_id = Strings::ToUnsignedInt(z); for (const auto &v : versions) { - scale_data.instance_version = static_cast(std::stoul(v)); + scale_data.instance_version = static_cast(Strings::ToUnsignedInt(v)); npc_global_base_scaling_data.insert( std::make_pair( @@ -637,32 +642,33 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc) auto n = NpcTypesRepository::FindOne(content_db, static_cast(npc->GetNPCTypeID())); if (n.id > 0) { - n.AC = g.ac; - n.hp = g.hp; - n.Accuracy = g.accuracy; - n.slow_mitigation = g.slow_mitigation; - n.ATK = g.attack; - n.STR = g.strength; - n.STA = g.stamina; - n.DEX = g.dexterity; - n.AGI = g.agility; - n._INT = g.intelligence; - n.WIS = g.wisdom; - n.CHA = g.charisma; - n.MR = g.magic_resist; - n.CR = g.cold_resist; - n.FR = g.fire_resist; - n.PR = g.poison_resist; - n.DR = g.disease_resist; - n.Corrup = g.corruption_resist; - n.PhR = g.physical_resist; - n.mindmg = g.min_dmg; - n.maxdmg = g.max_dmg; - n.hp_regen_rate = g.hp_regen_rate; - n.attack_delay = g.attack_delay; - n.spellscale = static_cast(g.spell_scale); - n.healscale = static_cast(g.heal_scale); - n.special_abilities = g.special_abilities; + n.AC = g.ac; + n.hp = g.hp; + n.Accuracy = g.accuracy; + n.slow_mitigation = g.slow_mitigation; + n.ATK = g.attack; + n.STR = g.strength; + n.STA = g.stamina; + n.DEX = g.dexterity; + n.AGI = g.agility; + n._INT = g.intelligence; + n.WIS = g.wisdom; + n.CHA = g.charisma; + n.MR = g.magic_resist; + n.CR = g.cold_resist; + n.FR = g.fire_resist; + n.PR = g.poison_resist; + n.DR = g.disease_resist; + n.Corrup = g.corruption_resist; + n.PhR = g.physical_resist; + n.mindmg = g.min_dmg; + n.maxdmg = g.max_dmg; + n.hp_regen_rate = g.hp_regen_rate; + n.attack_delay = g.attack_delay; + n.spellscale = static_cast(g.spell_scale); + n.healscale = static_cast(g.heal_scale); + n.heroic_strikethrough = g.heroic_strikethrough; + n.special_abilities = g.special_abilities; return NpcTypesRepository::UpdateOne(content_db, n); } @@ -702,32 +708,33 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc) auto n = NpcTypesRepository::FindOne(content_db, static_cast(npc->GetNPCTypeID())); if (n.id > 0) { - n.AC = 0; - n.hp = 0; - n.Accuracy = 0; - n.slow_mitigation = 0; - n.ATK = 0; - n.STR = 0; - n.STA = 0; - n.DEX = 0; - n.AGI = 0; - n._INT = 0; - n.WIS = 0; - n.CHA = 0; - n.MR = 0; - n.CR = 0; - n.FR = 0; - n.PR = 0; - n.DR = 0; - n.Corrup = 0; - n.PhR = 0; - n.mindmg = 0; - n.maxdmg = 0; - n.hp_regen_rate = 0; - n.attack_delay = 0; - n.spellscale = 0; - n.healscale = 0; - n.special_abilities = ""; + n.AC = 0; + n.hp = 0; + n.Accuracy = 0; + n.slow_mitigation = 0; + n.ATK = 0; + n.STR = 0; + n.STA = 0; + n.DEX = 0; + n.AGI = 0; + n._INT = 0; + n.WIS = 0; + n.CHA = 0; + n.MR = 0; + n.CR = 0; + n.FR = 0; + n.PR = 0; + n.DR = 0; + n.Corrup = 0; + n.PhR = 0; + n.mindmg = 0; + n.maxdmg = 0; + n.hp_regen_rate = 0; + n.attack_delay = 0; + n.spellscale = 0; + n.healscale = 0; + n.heroic_strikethrough = 0; + n.special_abilities = ""; return NpcTypesRepository::UpdateOne(content_db, n); } diff --git a/zone/npc_scale_manager.h b/zone/npc_scale_manager.h index 46a0020b9..e49137248 100644 --- a/zone/npc_scale_manager.h +++ b/zone/npc_scale_manager.h @@ -57,6 +57,7 @@ public: int attack_delay; int spell_scale; int heal_scale; + int heroic_strikethrough; std::string special_abilities; };