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 0a90d5300..4920ed708 100644 --- a/common/repositories/base/base_npc_scale_global_base_repository.h +++ b/common/repositories/base/base_npc_scale_global_base_repository.h @@ -25,7 +25,7 @@ public: std::string zone_id_list; std::string instance_version_list; int32_t ac; - int32_t hp; + int64_t hp; int32_t accuracy; int32_t slow_mitigation; int32_t attack; @@ -45,12 +45,14 @@ public: int32_t physical_resist; int32_t min_dmg; int32_t max_dmg; - int32_t hp_regen_rate; + int64_t hp_regen_rate; + int64_t hp_regen_per_second; int32_t attack_delay; int32_t spell_scale; int32_t heal_scale; - std::string special_abilities; + uint32_t avoidance; int32_t heroic_strikethrough; + std::string special_abilities; }; static std::string PrimaryKey() @@ -87,11 +89,13 @@ public: "min_dmg", "max_dmg", "hp_regen_rate", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", - "special_abilities", + "avoidance", "heroic_strikethrough", + "special_abilities", }; } @@ -124,11 +128,13 @@ public: "min_dmg", "max_dmg", "hp_regen_rate", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", - "special_abilities", + "avoidance", "heroic_strikethrough", + "special_abilities", }; } @@ -195,11 +201,13 @@ public: e.min_dmg = 0; e.max_dmg = 0; e.hp_regen_rate = 0; + e.hp_regen_per_second = 0; e.attack_delay = 0; e.spell_scale = 100; e.heal_scale = 100; - e.special_abilities = ""; + e.avoidance = 0; e.heroic_strikethrough = 0; + e.special_abilities = ""; return e; } @@ -241,7 +249,7 @@ public: 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.hp = strtoll(row[5], nullptr, 10); e.accuracy = static_cast(atoi(row[6])); e.slow_mitigation = static_cast(atoi(row[7])); e.attack = static_cast(atoi(row[8])); @@ -261,12 +269,14 @@ public: 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.heroic_strikethrough = static_cast(atoi(row[30])); + e.hp_regen_rate = strtoll(row[25], nullptr, 10); + e.hp_regen_per_second = strtoll(row[26], nullptr, 10); + e.attack_delay = static_cast(atoi(row[27])); + e.spell_scale = static_cast(atoi(row[28])); + e.heal_scale = static_cast(atoi(row[29])); + e.avoidance = static_cast(strtoul(row[30], nullptr, 10)); + e.heroic_strikethrough = static_cast(atoi(row[31])); + e.special_abilities = row[32] ? row[32] : ""; return e; } @@ -326,11 +336,13 @@ public: v.push_back(columns[23] + " = " + std::to_string(e.min_dmg)); v.push_back(columns[24] + " = " + std::to_string(e.max_dmg)); v.push_back(columns[25] + " = " + std::to_string(e.hp_regen_rate)); - v.push_back(columns[26] + " = " + std::to_string(e.attack_delay)); - 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)); + v.push_back(columns[26] + " = " + std::to_string(e.hp_regen_per_second)); + v.push_back(columns[27] + " = " + std::to_string(e.attack_delay)); + v.push_back(columns[28] + " = " + std::to_string(e.spell_scale)); + v.push_back(columns[29] + " = " + std::to_string(e.heal_scale)); + v.push_back(columns[30] + " = " + std::to_string(e.avoidance)); + v.push_back(columns[31] + " = " + std::to_string(e.heroic_strikethrough)); + v.push_back(columns[32] + " = '" + Strings::Escape(e.special_abilities) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -378,11 +390,13 @@ public: v.push_back(std::to_string(e.min_dmg)); v.push_back(std::to_string(e.max_dmg)); v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.hp_regen_per_second)); v.push_back(std::to_string(e.attack_delay)); 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.avoidance)); v.push_back(std::to_string(e.heroic_strikethrough)); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); auto results = db.QueryDatabase( fmt::format( @@ -438,11 +452,13 @@ public: v.push_back(std::to_string(e.min_dmg)); v.push_back(std::to_string(e.max_dmg)); v.push_back(std::to_string(e.hp_regen_rate)); + v.push_back(std::to_string(e.hp_regen_per_second)); v.push_back(std::to_string(e.attack_delay)); 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.avoidance)); v.push_back(std::to_string(e.heroic_strikethrough)); + v.push_back("'" + Strings::Escape(e.special_abilities) + "'"); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -481,7 +497,7 @@ public: 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.hp = strtoll(row[5], nullptr, 10); e.accuracy = static_cast(atoi(row[6])); e.slow_mitigation = static_cast(atoi(row[7])); e.attack = static_cast(atoi(row[8])); @@ -501,12 +517,14 @@ public: 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.heroic_strikethrough = static_cast(atoi(row[30])); + e.hp_regen_rate = strtoll(row[25], nullptr, 10); + e.hp_regen_per_second = strtoll(row[26], nullptr, 10); + e.attack_delay = static_cast(atoi(row[27])); + e.spell_scale = static_cast(atoi(row[28])); + e.heal_scale = static_cast(atoi(row[29])); + e.avoidance = static_cast(strtoul(row[30], nullptr, 10)); + e.heroic_strikethrough = static_cast(atoi(row[31])); + e.special_abilities = row[32] ? row[32] : ""; all_entries.push_back(e); } @@ -536,7 +554,7 @@ public: 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.hp = strtoll(row[5], nullptr, 10); e.accuracy = static_cast(atoi(row[6])); e.slow_mitigation = static_cast(atoi(row[7])); e.attack = static_cast(atoi(row[8])); @@ -556,12 +574,14 @@ public: 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.heroic_strikethrough = static_cast(atoi(row[30])); + e.hp_regen_rate = strtoll(row[25], nullptr, 10); + e.hp_regen_per_second = strtoll(row[26], nullptr, 10); + e.attack_delay = static_cast(atoi(row[27])); + e.spell_scale = static_cast(atoi(row[28])); + e.heal_scale = static_cast(atoi(row[29])); + e.avoidance = static_cast(strtoul(row[30], nullptr, 10)); + e.heroic_strikethrough = static_cast(atoi(row[31])); + e.special_abilities = row[32] ? row[32] : ""; all_entries.push_back(e); } diff --git a/common/version.h b/common/version.h index 261c8f6f4..10a96ef1b 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 9223 +#define CURRENT_BINARY_DATABASE_VERSION 9224 #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 a1a1a366d..ace611714 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -477,6 +477,7 @@ 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| +9224|2023_03_08_npc_scale_global_base_avoidance.sql|SHOW COLUMNS FROM `npc_scale_global_base` LIKE 'hp_regen_per_second'|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 index f97140973..a25d123fd 100644 --- 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 @@ -1,5 +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`, + CHANGE COLUMN `zone_id` `zone_id_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL AFTER `level`, + CHANGE COLUMN `instance_version` `instance_version_list` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL 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/utils/sql/git/required/2023_03_08_npc_scale_global_base_avoidance.sql b/utils/sql/git/required/2023_03_08_npc_scale_global_base_avoidance.sql new file mode 100644 index 000000000..64755da49 --- /dev/null +++ b/utils/sql/git/required/2023_03_08_npc_scale_global_base_avoidance.sql @@ -0,0 +1,5 @@ +ALTER TABLE `npc_scale_global_base` +MODIFY COLUMN `hp` bigint(20) NOT NULL DEFAULT 0 AFTER `ac`, +MODIFY COLUMN `hp_regen_rate` bigint(20) NOT NULL DEFAULT 0 AFTER `max_dmg`, +ADD COLUMN `hp_regen_per_second` bigint(20) NOT NULL DEFAULT 0 AFTER `hp_regen_rate`, +ADD COLUMN `avoidance` int(11) unsigned NOT NULL DEFAULT 0 AFTER `heal_scale`; diff --git a/zone/attack.cpp b/zone/attack.cpp index 4ed5897f2..94c775fdd 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -6407,6 +6407,11 @@ int64 Mob::GetHPRegen() const return hp_regen; } +int64 Mob::GetHPRegenPerSecond() const +{ + return hp_regen_per_second; +} + int64 Mob::GetManaRegen() const { return mana_regen; diff --git a/zone/mob.h b/zone/mob.h index 0dc2efe8e..e83cc0170 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1382,6 +1382,7 @@ public: int64 DoDamageCaps(int64 base_damage); int64 GetHPRegen() const; + int64 GetHPRegenPerSecond() const; int64 GetManaRegen() const; bool CanOpenDoors() const; diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index d1d076c7b..5a98375d3 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -164,6 +164,10 @@ void NpcScaleManager::ScaleNPC( npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate)); } + if (always_scale || (npc->GetHPRegenPerSecond() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("hp_regen_per_second", std::to_string(scale_data.hp_regen_per_second)); + } + if (always_scale || npc->GetAttackDelay() == 0) { npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay)); } @@ -176,6 +180,10 @@ void NpcScaleManager::ScaleNPC( npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale)); } + if (always_scale || npc->GetAvoidanceRating() == 0) { + npc->ModifyNPCStat("avoidance", std::to_string(scale_data.avoidance)); + } + if (always_scale || npc->GetHeroicStrikethrough() == 0) { npc->ModifyNPCStat("heroic_strikethrough", std::to_string(scale_data.heroic_strikethrough)); } @@ -253,9 +261,11 @@ bool NpcScaleManager::LoadScaleData() 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.hp_regen_per_second = s.hp_regen_per_second; scale_data.attack_delay = s.attack_delay; scale_data.spell_scale = s.spell_scale; scale_data.heal_scale = s.heal_scale; + scale_data.avoidance = s.avoidance; scale_data.heroic_strikethrough = s.heroic_strikethrough; if (!s.special_abilities.empty()) { @@ -664,9 +674,11 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc) n.mindmg = g.min_dmg; n.maxdmg = g.max_dmg; n.hp_regen_rate = g.hp_regen_rate; + n.hp_regen_per_second = g.hp_regen_per_second; n.attack_delay = g.attack_delay; n.spellscale = static_cast(g.spell_scale); n.healscale = static_cast(g.heal_scale); + n.Avoidance = g.avoidance; n.heroic_strikethrough = g.heroic_strikethrough; n.special_abilities = g.special_abilities; @@ -730,9 +742,11 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc) n.mindmg = 0; n.maxdmg = 0; n.hp_regen_rate = 0; + n.hp_regen_per_second = 0; n.attack_delay = 0; n.spellscale = 0; n.healscale = 0; + n.Avoidance = 0; n.heroic_strikethrough = 0; n.special_abilities = ""; diff --git a/zone/npc_scale_manager.h b/zone/npc_scale_manager.h index e49137248..2c37b3d7b 100644 --- a/zone/npc_scale_manager.h +++ b/zone/npc_scale_manager.h @@ -54,9 +54,11 @@ public: int min_dmg; int max_dmg; int64 hp_regen_rate; + int64 hp_regen_per_second; int attack_delay; int spell_scale; int heal_scale; + uint32 avoidance; int heroic_strikethrough; std::string special_abilities; @@ -85,9 +87,12 @@ public: "min_hit", "max_hit", "hp_regen", + "hp_regen_per_second", "attack_delay", "spell_scale", "heal_scale", + "avoidance", + "heroic_strikethrough", "special_abilities" };