diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index fed54e0dd..7baec86a5 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -573,12 +573,6 @@ void Lua_NPC::RecalculateSkills() self->RecalculateSkills(); } -void Lua_NPC::ScaleNPC(uint8 npc_level) -{ - Lua_Safe_Call_Void(); - self->ScaleNPC(npc_level); -} - bool Lua_NPC::IsRaidTarget() { Lua_Safe_Call_Bool(); @@ -761,6 +755,24 @@ void Lua_NPC::SetLDoNTrapDetected(bool is_detected) { self->SetLDoNTrapDetected(is_detected); } +void Lua_NPC::ScaleNPC(uint8 npc_level) +{ + Lua_Safe_Call_Void(); + self->ScaleNPC(npc_level); +} + +void Lua_NPC::ScaleNPC(uint8 npc_level, bool always_scale_stats) +{ + Lua_Safe_Call_Void(); + self->ScaleNPC(npc_level, always_scale_stats); +} + +void Lua_NPC::ScaleNPC(uint8 npc_level, bool always_scale_stats, bool always_scale_special_abilities) +{ + Lua_Safe_Call_Void(); + self->ScaleNPC(npc_level, always_scale_stats, always_scale_special_abilities); +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -874,6 +886,8 @@ luabind::scope lua_register_npc() { .def("SaveGuardSpot", (void(Lua_NPC::*)(bool))&Lua_NPC::SaveGuardSpot) .def("SaveGuardSpot", (void(Lua_NPC::*)(float,float,float,float))&Lua_NPC::SaveGuardSpot) .def("ScaleNPC", (void(Lua_NPC::*)(uint8))&Lua_NPC::ScaleNPC) + .def("ScaleNPC", (void(Lua_NPC::*)(uint8,bool))&Lua_NPC::ScaleNPC) + .def("ScaleNPC", (void(Lua_NPC::*)(uint8,bool,bool))&Lua_NPC::ScaleNPC) .def("SendPayload", (void(Lua_NPC::*)(int))&Lua_NPC::SendPayload) .def("SendPayload", (void(Lua_NPC::*)(int,std::string))&Lua_NPC::SendPayload) .def("SetCopper", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetCopper) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index e23896aea..ca8dafb1c 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -141,7 +141,6 @@ public: void SetSimpleRoamBox(float box_size, float move_distance, int move_delay); void RecalculateSkills(); void ReloadSpells(); - void ScaleNPC(uint8 npc_level); bool IsRaidTarget(); bool IsRareSpawn(); void ChangeLastName(std::string last_name); @@ -173,6 +172,9 @@ public: void SetLDoNLockedSkill(uint16 skill_value); bool IsLDoNTrapDetected(); void SetLDoNTrapDetected(bool is_detected); + void ScaleNPC(uint8 npc_level); + void ScaleNPC(uint8 npc_level, bool always_scale_stats); + void ScaleNPC(uint8 npc_level, bool always_scale_stats, bool always_scale_special_abilities); }; #endif diff --git a/zone/npc.cpp b/zone/npc.cpp index 4136c6ed2..979c74752 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -3691,7 +3691,7 @@ void NPC::ReloadSpells() { AI_AddNPCSpellsEffects(GetNPCSpellsEffectsID()); } -void NPC::ScaleNPC(uint8 npc_level) { +void NPC::ScaleNPC(uint8 npc_level, bool always_scale_stats, bool always_scale_special_abilities) { if (GetLevel() != npc_level) { SetLevel(npc_level); RecalculateSkills(); @@ -3699,7 +3699,7 @@ void NPC::ScaleNPC(uint8 npc_level) { } npc_scale_manager->ResetNPCScaling(this); - npc_scale_manager->ScaleNPC(this); + npc_scale_manager->ScaleNPC(this, always_scale_stats, always_scale_special_abilities); } bool NPC::IsGuard() diff --git a/zone/npc.h b/zone/npc.h index 7dd230f3d..35073de55 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -531,7 +531,7 @@ public: inline bool IsSkipAutoScale() const { return skip_auto_scale; } - void ScaleNPC(uint8 npc_level); + void ScaleNPC(uint8 npc_level, bool always_scale_stats = false, bool always_scale_special_abilities = false); void RecalculateSkills(); void ReloadSpells(); diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index ac9cd3bee..7224f5fd4 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -26,7 +26,11 @@ /** * @param npc */ -void NpcScaleManager::ScaleNPC(NPC *npc) +void NpcScaleManager::ScaleNPC( + NPC *npc, + bool stats_always_scale, + bool special_abilities_always_scale +) { if (npc->IsSkipAutoScale() || npc->GetNPCTypeID() == 0) { return; @@ -49,65 +53,84 @@ void NpcScaleManager::ScaleNPC(NPC *npc) return; } - if (npc->GetAC() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("ac", std::to_string(scale_data.ac).c_str()); + if (stats_always_scale || (npc->GetAC() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("ac", std::to_string(scale_data.ac)); } - if (npc->GetMaxHP() == 0) { - npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp).c_str()); + + if (stats_always_scale || npc->GetMaxHP() == 0) { + npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp)); npc->Heal(); } - if (npc->GetAccuracyRating() == 0) { - npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy).c_str()); + + if (stats_always_scale || npc->GetAccuracyRating() == 0) { + npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy)); } - if (npc->GetSlowMitigation() == 0) { - npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation).c_str()); + + if (stats_always_scale || npc->GetSlowMitigation() == 0) { + npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation)); } - if (npc->GetATK() == 0) { - npc->ModifyNPCStat("atk", std::to_string(scale_data.attack).c_str()); + + if (stats_always_scale || npc->GetATK() == 0) { + npc->ModifyNPCStat("atk", std::to_string(scale_data.attack)); } - if (npc->GetSTR() == 0) { - npc->ModifyNPCStat("str", std::to_string(scale_data.strength).c_str()); + + if (stats_always_scale || npc->GetSTR() == 0) { + npc->ModifyNPCStat("str", std::to_string(scale_data.strength)); } - if (npc->GetSTA() == 0) { - npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina).c_str()); + + if (stats_always_scale || npc->GetSTA() == 0) { + npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina)); } - if (npc->GetDEX() == 0) { - npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity).c_str()); + + if (stats_always_scale || npc->GetDEX() == 0) { + npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity)); } - if (npc->GetAGI() == 0) { - npc->ModifyNPCStat("agi", std::to_string(scale_data.agility).c_str()); + + if (stats_always_scale || npc->GetAGI() == 0) { + npc->ModifyNPCStat("agi", std::to_string(scale_data.agility)); } - if (npc->GetINT() == 0) { - npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence).c_str()); + + if (stats_always_scale || npc->GetINT() == 0) { + npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence)); } - if (npc->GetWIS() == 0) { - npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom).c_str()); + + if (stats_always_scale || npc->GetWIS() == 0) { + npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom)); } - if (npc->GetCHA() == 0) { - npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma).c_str()); + + if (stats_always_scale || npc->GetCHA() == 0) { + npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma)); } - if (npc->GetMR() == 0) { - npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist).c_str()); + + if (stats_always_scale || npc->GetMR() == 0) { + npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist)); } - if (npc->GetCR() == 0) { - npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist).c_str()); + + if (stats_always_scale || npc->GetCR() == 0) { + npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist)); } - if (npc->GetFR() == 0) { - npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist).c_str()); + + if (stats_always_scale || npc->GetFR() == 0) { + npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist)); } - if (npc->GetPR() == 0) { - npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist).c_str()); + + if (stats_always_scale || npc->GetPR() == 0) { + npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist)); } - if (npc->GetDR() == 0) { - npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist).c_str()); + + if (stats_always_scale || npc->GetDR() == 0) { + npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist)); } - if (npc->GetCorrup() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist).c_str()); + + if (stats_always_scale || (npc->GetCorrup() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist)); } - if (npc->GetPhR() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist).c_str()); + + if (stats_always_scale || (npc->GetPhR() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist)); } - if (npc->GetMinDMG() == 0 && npc->GetMaxDMG() == 0) { + + if (stats_always_scale || npc->GetMinDMG() == 0) { int min_dmg = scale_data.min_dmg; if (RuleB(Combat, UseNPCDamageClassLevelMods)) { int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); @@ -116,9 +139,10 @@ void NpcScaleManager::ScaleNPC(NPC *npc) LogNPCScaling("ClassLevelDamageMod::min_dmg base: [{}] calc: [{}]", scale_data.min_dmg, min_dmg); } - npc->ModifyNPCStat("min_hit", std::to_string(min_dmg).c_str()); + npc->ModifyNPCStat("min_hit", std::to_string(min_dmg)); } - if (npc->GetMaxDMG() == 0) { + + if (stats_always_scale || npc->GetMaxDMG() == 0) { int max_dmg = scale_data.max_dmg; if (RuleB(Combat, UseNPCDamageClassLevelMods)) { int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass()); @@ -127,22 +151,27 @@ void NpcScaleManager::ScaleNPC(NPC *npc) LogNPCScaling("ClassLevelDamageMod::max_dmg base: [{}] calc: [{}]", scale_data.max_dmg, max_dmg); } - npc->ModifyNPCStat("max_hit", std::to_string(max_dmg).c_str()); + npc->ModifyNPCStat("max_hit", std::to_string(max_dmg)); } - if (npc->GetHPRegen() == 0 && is_auto_scaled) { - npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate).c_str()); + + if (stats_always_scale || (npc->GetHPRegen() == 0 && is_auto_scaled)) { + npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate)); } - if (npc->GetAttackDelay() == 0) { - npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay).c_str()); + + if (stats_always_scale || npc->GetAttackDelay() == 0) { + npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay)); } - if (npc->GetSpellScale() == 0) { - npc->ModifyNPCStat("spell_scale", std::to_string(scale_data.spell_scale).c_str()); + + if (stats_always_scale || npc->GetSpellScale() == 0) { + npc->ModifyNPCStat("spell_scale", std::to_string(scale_data.spell_scale)); } - if (npc->GetHealScale() == 0) { - npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale).c_str()); + + if (stats_always_scale || npc->GetHealScale() == 0) { + npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale)); } - if (!npc->HasSpecialAbilities() && is_auto_scaled) { - npc->ModifyNPCStat("special_abilities", scale_data.special_abilities.c_str()); + + if (special_abilities_always_scale || (!npc->HasSpecialAbilities() && is_auto_scaled)) { + npc->ModifyNPCStat("special_abilities", scale_data.special_abilities); } if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1) { @@ -161,18 +190,18 @@ void NpcScaleManager::ScaleNPC(NPC *npc) npc_level, npc_type, (is_auto_scaled ? "true" : "false"), - scale_log.c_str() + scale_log ); } } -void NpcScaleManager::ResetNPCScaling(NPC *npc) +void NpcScaleManager::ResetNPCScaling(NPC* npc) { for (const auto &scaling_stat : scaling_stats) { auto stat_name = fmt::format("modify_stat_{}", scaling_stat); auto reset_value = std::to_string(0); if (npc->EntityVariableExists(stat_name)) { - npc->ModifyNPCStat(scaling_stat.c_str(), reset_value.c_str()); + npc->ModifyNPCStat(scaling_stat, reset_value); } } } @@ -430,24 +459,25 @@ std::string NpcScaleManager::GetNPCScalingTypeName(NPC *&npc) * @param npc * @return */ -bool NpcScaleManager::IsAutoScaled(NPC *npc) +bool NpcScaleManager::IsAutoScaled(NPC* npc) { - return - (npc->GetHP() == 0 && - npc->GetMaxDMG() == 0 && - npc->GetMinDMG() == 0 && - npc->GetSTR() == 0 && - npc->GetSTA() == 0 && - npc->GetDEX() == 0 && - npc->GetAGI() == 0 && - npc->GetINT() == 0 && - npc->GetWIS() == 0 && - npc->GetCHA() == 0 && - npc->GetMR() == 0 && - npc->GetFR() == 0 && - npc->GetCR() == 0 && - npc->GetPR() == 0 && - npc->GetDR() == 0); + return ( + npc->GetHP() == 0 && + npc->GetMaxDMG() == 0 && + npc->GetMinDMG() == 0 && + npc->GetSTR() == 0 && + npc->GetSTA() == 0 && + npc->GetDEX() == 0 && + npc->GetAGI() == 0 && + npc->GetINT() == 0 && + npc->GetWIS() == 0 && + npc->GetCHA() == 0 && + npc->GetMR() == 0 && + npc->GetFR() == 0 && + npc->GetCR() == 0 && + npc->GetPR() == 0 && + npc->GetDR() == 0 + ); } /** diff --git a/zone/npc_scale_manager.h b/zone/npc_scale_manager.h index 2748f5a61..eae4ca881 100644 --- a/zone/npc_scale_manager.h +++ b/zone/npc_scale_manager.h @@ -86,9 +86,9 @@ public: "special_abilities" }; - void ScaleNPC(NPC * npc); - void ResetNPCScaling(NPC * npc); - bool IsAutoScaled(NPC * npc); + void ScaleNPC(NPC* npc, bool always_scale_stats = false, bool always_scale_special_abilities = false); + void ResetNPCScaling(NPC* npc); + bool IsAutoScaled(NPC* npc); bool LoadScaleData(); global_npc_scale GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level); diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 0ba74fa5b..6f098b7bf 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -594,11 +594,6 @@ void Perl_NPC_RecalculateSkills(NPC* self) // @categories Skills and Recipes self->RecalculateSkills(); } -void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level) -{ - return self->ScaleNPC(npc_level); -} - bool Perl_NPC_IsRaidTarget(NPC* self) { return self->IsRaidTarget(); @@ -750,6 +745,21 @@ void Perl_NPC_SetLDoNTrapDetected(NPC* self, bool is_detected) self->SetLDoNTrapDetected(is_detected); } +void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level) +{ + return self->ScaleNPC(npc_level); +} + +void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level, bool always_scale_stats) +{ + return self->ScaleNPC(npc_level, always_scale_stats); +} + +void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level, bool always_scale_stats, bool always_scale_special_abilities) +{ + return self->ScaleNPC(npc_level, always_scale_stats, always_scale_special_abilities); +} + void perl_register_npc() { perl::interpreter perl(PERL_GET_THX); @@ -872,7 +882,9 @@ void perl_register_npc() package.add("SaveGuardSpot", (void(*)(NPC*))&Perl_NPC_SaveGuardSpot); package.add("SaveGuardSpot", (void(*)(NPC*, bool))&Perl_NPC_SaveGuardSpot); package.add("SaveGuardSpot", (void(*)(NPC*, float, float, float, float))&Perl_NPC_SaveGuardSpot); - package.add("ScaleNPC", &Perl_NPC_ScaleNPC); + package.add("ScaleNPC", (void(*)(NPC*, uint8))&Perl_NPC_ScaleNPC); + package.add("ScaleNPC", (void(*)(NPC*, uint8, bool))&Perl_NPC_ScaleNPC); + package.add("ScaleNPC", (void(*)(NPC*, uint8, bool, bool))&Perl_NPC_ScaleNPC); package.add("SendPayload", (void(*)(NPC*, int))&Perl_NPC_SendPayload); package.add("SendPayload", (void(*)(NPC*, int, std::string))&Perl_NPC_SendPayload); package.add("SetCopper", &Perl_NPC_SetCopper);