[Scaling] Add support for zone ID and instance version to NPC Scaling (#2968)

* [Scaling] Add support for zone ID and instance version to NPC Scaling

# Notes
- Adds `zone_id` and `instance_version` to `npc_scale_global_base` table to allow for zone and version-specific scaling.
- Defaults back to `zone_id` of `0` and `instance_version` of `0` for global scaling.
- Scaling load precedence is as follows:
- `zone_id` of current zone and `instance_version` of current instance
- `zone_id` of current zone and `instance_version` of `0`
- `zone_id` of `0` and `instance_version` of `0`

* Remove debug comment.

* Use zone not NPC.

* SQL
This commit is contained in:
Alex King
2023-02-24 21:17:07 -05:00
committed by GitHub
parent de2dfc1a7e
commit 2a20c69c69
9 changed files with 273 additions and 170 deletions
+5 -1
View File
@@ -4205,7 +4205,11 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on,
}
uint32 Mob::GetZoneID() const {
return(zone->GetZoneID());
return zone->GetZoneID();
}
uint16 Mob::GetInstanceVersion() const {
return zone->GetInstanceVersion();
}
int Mob::GetHaste()
+1
View File
@@ -1239,6 +1239,7 @@ public:
bool Charmed() const { return typeofpet == petCharmed; }
static uint32 GetLevelHP(uint8 tlevel);
uint32 GetZoneID() const; //for perl
uint16 GetInstanceVersion() const; //for perl
virtual int32 CheckAggroAmount(uint16 spell_id, Mob *target, bool isproc = false);
virtual int32 CheckHealAggroAmount(uint16 spell_id, Mob *target, uint32 heal_possible = 0);
+8 -10
View File
@@ -795,21 +795,19 @@ void Mob::DisplayInfo(Mob *mob)
window_text += WriteDisplayInfoSection(mob, "Proximity", npc_proximity, 1, true);
}
int8 npc_type = npc_scale_manager->GetNPCScalingType(npc);
std::string npc_type_string = npc_scale_manager->GetNPCScalingTypeName(npc);
client->Message(
0,
"| # Target: %s Type: %i (%s)",
npc->GetCleanName(),
npc_type,
npc_type_string.c_str());
Chat::White,
fmt::format(
"| # Target: {} Type: {} ({})",
npc->GetCleanName(),
npc_scale_manager->GetNPCScalingType(npc),
npc_scale_manager->GetNPCScalingTypeName(npc)
).c_str()
);
NPCCommandsMenu(client, npc);
}
// std::cout << "Window Length: " << window_text.length() << std::endl;
if (client->GetDisplayMobInfoWindow()) {
client->SendFullPopup(
"GM: Entity Info",
+87 -24
View File
@@ -30,21 +30,27 @@ void NpcScaleManager::ScaleNPC(
NPC *npc,
bool always_scale,
bool override_special_abilities
)
{
) {
if (npc->IsSkipAutoScale() || npc->GetNPCTypeID() == 0) {
return;
}
int8 npc_type = GetNPCScalingType(npc);
int npc_level = npc->GetLevel();
bool is_auto_scaled = IsAutoScaled(npc);
auto npc_type = GetNPCScalingType(npc);
auto npc_level = npc->GetLevel();
auto is_auto_scaled = IsAutoScaled(npc);
auto zone_id = zone->GetZoneID();
auto instance_version = zone->GetInstanceVersion();
global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel(npc_type, npc_level);
global_npc_scale scale_data = GetGlobalScaleDataForTypeLevel(
npc_type,
npc_level,
zone_id,
instance_version
);
if (!scale_data.level) {
LogNPCScaling(
"NPC: [{}] - scaling data not found for type: [{}] level: [{}]",
"NPC: [{}] - scaling data not found for type [{}] level [{}]",
npc->GetCleanName(),
npc_type,
npc_level
@@ -209,11 +215,13 @@ void NpcScaleManager::ResetNPCScaling(NPC* npc)
bool NpcScaleManager::LoadScaleData()
{
auto rows = NpcScaleGlobalBaseRepository::All(content_db);
for (auto &s: rows) {
for (const auto &s : rows) {
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;
@@ -246,7 +254,12 @@ bool NpcScaleManager::LoadScaleData()
npc_global_base_scaling_data.insert(
std::make_pair(
std::make_pair(scale_data.type, scale_data.level),
std::make_tuple(
scale_data.type,
scale_data.level,
scale_data.zone_id,
scale_data.instance_version
),
scale_data
)
);
@@ -262,9 +275,45 @@ bool NpcScaleManager::LoadScaleData()
* @param npc_level
* @return NpcScaleManager::global_npc_scale
*/
NpcScaleManager::global_npc_scale NpcScaleManager::GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level)
{
auto iter = npc_global_base_scaling_data.find(std::make_pair(npc_type, npc_level));
NpcScaleManager::global_npc_scale NpcScaleManager::GetGlobalScaleDataForTypeLevel(
int8 npc_type,
uint8 npc_level,
uint32 zone_id,
uint16 instance_version
) {
auto iter = npc_global_base_scaling_data.find(
std::make_tuple(
npc_type,
npc_level,
zone_id,
instance_version
)
);
if (iter != npc_global_base_scaling_data.end()) {
return iter->second;
}
iter = npc_global_base_scaling_data.find(
std::make_tuple(
npc_type,
npc_level,
zone_id,
0
)
);
if (iter != npc_global_base_scaling_data.end()) {
return iter->second;
}
iter = npc_global_base_scaling_data.find(
std::make_tuple(
npc_type,
npc_level,
0,
0
)
);
if (iter != npc_global_base_scaling_data.end()) {
return iter->second;
}
@@ -487,14 +536,21 @@ bool NpcScaleManager::IsAutoScaled(NPC* npc)
*/
bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc)
{
int8 npc_type = GetNPCScalingType(npc);
int npc_level = npc->GetLevel();
auto npc_type = GetNPCScalingType(npc);
auto npc_level = npc->GetLevel();
auto zone_id = zone->GetZoneID();
auto instance_version = zone->GetInstanceVersion();
global_npc_scale g = GetGlobalScaleDataForTypeLevel(npc_type, npc_level);
global_npc_scale g = GetGlobalScaleDataForTypeLevel(
npc_type,
npc_level,
zone_id,
instance_version
);
if (!g.level) {
LogNPCScaling(
"NPC: [{}] - scaling data not found for type: [{}] level: [{}]",
"NPC: [{}] - scaling data not found for type [{}] level [{}]",
npc->GetCleanName(),
npc_type,
npc_level
@@ -503,7 +559,7 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc)
return false;
}
auto n = NpcTypesRepository::FindOne(content_db, (int) npc->GetNPCTypeID());
auto n = NpcTypesRepository::FindOne(content_db, static_cast<int>(npc->GetNPCTypeID()));
if (n.id > 0) {
n.AC = g.ac;
n.hp = g.hp;
@@ -528,8 +584,8 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc)
n.maxdmg = g.max_dmg;
n.hp_regen_rate = g.hp_regen_rate;
n.attack_delay = g.attack_delay;
n.spellscale = (float) g.spell_scale;
n.healscale = (float) g.heal_scale;
n.spellscale = static_cast<float>(g.spell_scale);
n.healscale = static_cast<float>(g.heal_scale);
n.special_abilities = g.special_abilities;
return NpcTypesRepository::UpdateOne(content_db, n);
@@ -545,14 +601,21 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCStatically(NPC *&npc)
*/
bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc)
{
int8 npc_type = GetNPCScalingType(npc);
int npc_level = npc->GetLevel();
auto npc_type = GetNPCScalingType(npc);
auto npc_level = npc->GetLevel();
auto zone_id = zone->GetZoneID();
auto instance_version = zone->GetInstanceVersion();
global_npc_scale d = GetGlobalScaleDataForTypeLevel(npc_type, npc_level);
global_npc_scale d = GetGlobalScaleDataForTypeLevel(
npc_type,
npc_level,
zone_id,
instance_version
);
if (!d.level) {
LogNPCScaling(
"NPC: [{}] - scaling data not found for type: [{}] level: [{}]",
"NPC: [{}] - scaling data not found for type [{}] level [{}]",
npc->GetCleanName(),
npc_type,
npc_level
@@ -561,7 +624,7 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc)
return false;
}
auto n = NpcTypesRepository::FindOne(content_db, (int) npc->GetNPCTypeID());
auto n = NpcTypesRepository::FindOne(content_db, static_cast<int>(npc->GetNPCTypeID()));
if (n.id > 0) {
n.AC = 0;
n.hp = 0;
+38 -29
View File
@@ -22,37 +22,41 @@
#define EQEMU_NPC_SCALE_MANAGER_H
#include "npc.h"
#include "zone.h"
extern Zone* zone;
class NpcScaleManager {
public:
struct global_npc_scale {
int type;
int level;
int ac;
int64 hp;
int accuracy;
int slow_mitigation;
int attack;
int strength;
int stamina;
int dexterity;
int agility;
int intelligence;
int wisdom;
int charisma;
int magic_resist;
int cold_resist;
int fire_resist;
int poison_resist;
int disease_resist;
int corruption_resist;
int physical_resist;
int min_dmg;
int max_dmg;
int64 hp_regen_rate;
int attack_delay;
int spell_scale;
int heal_scale;
int8 type;
uint8 level;
uint32 zone_id;
uint16 instance_version;
int ac;
int64 hp;
int accuracy;
int slow_mitigation;
int attack;
int strength;
int stamina;
int dexterity;
int agility;
int intelligence;
int wisdom;
int charisma;
int magic_resist;
int cold_resist;
int fire_resist;
int poison_resist;
int disease_resist;
int corruption_resist;
int physical_resist;
int min_dmg;
int max_dmg;
int64 hp_regen_rate;
int attack_delay;
int spell_scale;
int heal_scale;
std::string special_abilities;
};
@@ -91,9 +95,14 @@ public:
bool IsAutoScaled(NPC* npc);
bool LoadScaleData();
global_npc_scale GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level);
global_npc_scale GetGlobalScaleDataForTypeLevel(
int8 npc_type,
uint8 npc_level,
uint32 zone_id,
uint16 instance_version
);
std::map<std::pair<int, int>, global_npc_scale> npc_global_base_scaling_data;
std::map<std::tuple<int8, uint8, uint32, uint16>, global_npc_scale> npc_global_base_scaling_data;
int8 GetNPCScalingType(NPC * &npc);
std::string GetNPCScalingTypeName(NPC * &npc);