Adding Spell scaling into base class

This commit is contained in:
2024-09-29 02:04:02 -04:00
parent ff5eb09faa
commit c4be5d44be
5 changed files with 218 additions and 73 deletions

View File

@@ -31,9 +31,8 @@ MythicPlus.EnableDeathLimits = 1
# Enabled difficulty settings
#
##########################################################
# MythicPlus.EnabledDifficulties = 3,4,5
# MythicPlus.DisabledDungeons =
MythicPlus.EnabledDifficulties = mythic,legendary,ascendant
MythicPlus.DisabledDungeons =
##########################################################
#
@@ -48,7 +47,7 @@ MythicPlus.Mythic.DungeonHealth = 1.25
MythicPlus.Mythic.DungeonMelee = 1.25
MythicPlus.Mythic.DungeonBaseDamage = 1.50
MythicPlus.Mythic.DungeonSpell = 1.15
MythicPlus.Mythic.DungeonArmor = 1.25
MythicPlus.Mythic.DungeonArmor = 1.95
MythicPlus.Mythic.DungeonAvgLevel = 83
MythicPlus.Mythic.DungeonBossHealth = 1.50

View File

@@ -23,9 +23,9 @@ public:
{
{"", HandleHelp, SEC_PLAYER, Console::No},
{"status", HandleStatus, SEC_PLAYER, Console::No},
{"mythic",HandleMythic, SEC_PLAYER, Console::No},
{"legendary",HandleLegendary, SEC_PLAYER, Console::No},
{"ascendant",HandleAscendant, SEC_PLAYER, Console::No},
// {"mythic",HandleMythic, SEC_PLAYER, Console::No},
// {"legendary",HandleLegendary, SEC_PLAYER, Console::No},
// {"ascendant",HandleAscendant, SEC_PLAYER, Console::No},
{"set", HandleSetDifficulty, SEC_PLAYER, Console::No},
{"disable", HandleDisable, SEC_ADMINISTRATOR, Console::Yes},
{"enable", HandleEnable, SEC_ADMINISTRATOR, Console::Yes}
@@ -44,8 +44,7 @@ public:
{
std::string helpText = "Mythic+ Commands:\n"
" .mp status - show current global settings of Mythic+ mod\n"
" .mp [mythic,legendary,ascendant] - Shortcode to set Mythic+ difficulty to level for your group. \n"
" .mp set [mythic,legendary,ascendant] - Set Mythic+ difficulty\n"
" .mp set [mythic,legendary,ascendant] - Set Mythic+ difficulty in current beta only supports mythic.\n"
" .mp [enable,disable] - enable or disable this mod\n"
" .mp - Show this help message\n";
handler->PSendSysMessage(helpText);
@@ -71,8 +70,19 @@ public:
}
std::string difficulty = args[0];
if(sMythicPlus->IsDifficultyEnabled(difficulty)) {
handler->PSendSysMessage("|cFFFF0000 The difficulty level you have selected is not enabled.");
// if(!sMythicPlus->IsDifficultyEnabled(difficulty)) {
// handler->PSendSysMessage("|cFFFF0000 The difficulty level you have selected is not enabled.");
// return true;
// }
if (!group->IsLeader(player->GetGUID())) {
handler->PSendSysMessage("|cFFFF0000 You must be the group leader to set a Mythic+ difficulty.");
return true;
}
if (player->GetMap()->IsDungeon()) {
player->ResetInstances(player->GetGUID(), INSTANCE_RESET_CHANGE_DIFFICULTY, false);
player->SendResetInstanceSuccess(player->GetMap()->GetId());
return true;
}

View File

@@ -4,6 +4,12 @@
#include "ObjectMgr.h"
#include "MapMgr.h"
#include "ScriptMgr.h"
#include "Player.h"
#include "Group.h"
#include "Map.h"
#include "Unit.h"
#include "Creature.h"
#include "SpellInfo.h"
bool MythicPlus::IsMapEligible(Map* map)
{
@@ -49,22 +55,25 @@ bool MythicPlus::EligibleHealTarget(Unit* target)
return false;
}
if(sMythicPlus->EligibleDamageTarget(target)) {
if (target->GetTypeId() == TYPEID_CORPSE || target->GetTypeId() == TYPEID_GAMEOBJECT) {
return false;
}
#if defined(MOD_PRESENT_NPCBOTS)
if (target->IsNPCBot()) {
return false;
}
if ((target->IsPet() || target->IsSummon() || target->IsHunterPet()) && target->GetOwner()->IsNPCBot()) {
return false;
}
#endif
if(sMythicPlus->IsCreatureEligible(target->ToCreature())) {
return true;
}
if (target->GetTypeId() == TYPEID_CORPSE || target->GetTypeId() == TYPEID_GAMEOBJECT) {
return false;
}
return true;
return false;
}
bool MythicPlus::EligibleDamageTarget(Unit* target)
@@ -74,12 +83,12 @@ bool MythicPlus::EligibleDamageTarget(Unit* target)
}
if (target->GetTypeId() == TYPEID_PLAYER) {
MpLogger::debug("Target {} is a player", target->GetName());
return true;
}
#if defined(MOD_PRESENT_NPCBOTS)
if (target->IsNPCBot()) {
MpLogger::debug("Target {} is an NPC eligible to be smacked hard", target->GetName());
return true;
}
@@ -98,6 +107,10 @@ bool MythicPlus::EligibleDamageTarget(Unit* target)
bool MythicPlus::IsCreatureEligible(Creature* creature)
{
if(!creature) {
return false;
}
if (creature->IsDungeonBoss()) {
return true;
}
@@ -229,7 +242,7 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m
// Normalize the damage from earlier expansions
float cTemplateDmgMult = cInfo->DamageModifier;
if (origLevel <= 60 && cTemplateDmgMult < 3.0f) {
cTemplateDmgMult = 3.0f;
cTemplateDmgMult = 4.0f;
}
if (origLevel <= 70 && origLevel > 60 && cTemplateDmgMult < 4.0f) {
cTemplateDmgMult = 4.0f;
@@ -247,10 +260,13 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m
creature->SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
creature->SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
creature->ApplyAttackTimePercentMod(BASE_ATTACK, 0.75, true);
creature->ApplyAttackTimePercentMod(OFF_ATTACK, 0.95, true);
creature->ApplyCastTimePercentMod(0.80, true);
creature->UpdateAllStats();
// Scale up the armor with some variance also to make some tougher enemies in the mix
uint32 armor = uint32(std::ceil(stats->BaseArmor * multipliers->armor));
uint32 armor = uint32(std::ceil(stats->BaseArmor * multipliers->armor * cInfo->ModArmor));
creature->SetArmor(armor);
/**
@@ -258,10 +274,82 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m
*/
// creature->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower * multipliers->melee);
// creature->SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower * multipliers->melee);
}
int32 ScaleDamageSpell(SpellInfo const * spellInfo, MpCreatureData* creatureData, Creature* creature, float damageMultiplier)
{
if (!spellInfo) {
MpLogger::error("Invalid spell info ScaleDamageSpell()");
return;
}
MpLogger::debug("Scaled creature reported base damage from {} to {}", creature->GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE), creature->GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE));
MpLogger::debug("Scaled creature {} armor to {}", creature->GetName(), creature->GetArmor());
if(!creatureData) {
MpLogger::error("Invalid creature data ScaleDamageSpell()");
return;
}
if(!creature) {
MpLogger::error("Invalid creature ScaleDamageSpell()");
return;
}
int32 originalLevel = creatureData->originalLevel;
int32 currentLevel = creature->GetLevel();
int32 totalDamage = 0;
// Calculate the scaling factor using the 1.8 exponent
float scalingFactor = pow(float(originalLevel / originalLevel), 1.8f);
auto effects = spellInfo->GetEffects();
// Loop through all spell effects to scale their base damage
for (uint8 i = 0; i < effects.size(); ++i)
{
SpellEffectInfo effect = effects[i];
totalDamage += effect.CalcValue(creature, nullptr,nullptr);
}
// Apply scaling factor and the set multiplier from the instance data
totalDamage = int32(totalDamage * scalingFactor * damageMultiplier);
return totalDamage;
}
int32 ScaleHealSpell(SpellInfo const * spellInfo, MpCreatureData* creatureData, Creature* creature, Creature* target, float healMultiplier)
{
if (!spellInfo) {
MpLogger::error("Invalid spell info ScaleHealSpell()");
return;
}
if(!creatureData) {
MpLogger::error("Invalid creature data ScaleHealSpell()");
return;
}
if(!creature) {
MpLogger::error("Invalid creature ScaleHealSpell()");
return;
}
if(!target) {
MpLogger::error("Invalid target ScaleHealSpell()");
return;
}
int32 originalHp = creatureData->originalStats->BaseHealth[EXPANSION_WRATH_OF_THE_LICH_KING];
int32 currentHealth = creature->GetHealth();
int32 totalHeal = 0;
auto effects = spellInfo->GetEffects();
// Loop through all spell effects to scale their base healing
for (uint8 i = 0; i < effects.size(); ++i)
{
SpellEffectInfo effect = effects[i];
totalHeal += effect.CalcValue(creature, nullptr, target);
}
// Apply scaling factor and the set multiplier from the instance data
return pow((totalHeal / originalHp) * currentHealth, 0.8f) * healMultiplier;
return totalHeal;
}
/**

View File

@@ -54,7 +54,8 @@ public:
UNIT_EVENT_MELEE,
UNIT_EVENT_HEAL,
UNIT_EVENT_DOT,
UNIT_EVENT_SPELL
UNIT_EVENT_SPELL,
UNIT_EVENT_HOT
};
// Map is eligible for mythic+ scaling
@@ -98,6 +99,12 @@ public:
// Scales the creature based on the level and the creature base stats
void ScaleCreature(uint8 level, Creature* creature, MpMultipliers* multipliers);
// Scales a damage spell up based on the level increase
int32 ScaleDamageSpell(SpellInfo const * spellInfo, MpCreatureData* creatureData, Creature* creature, float damageMultiplier);
// This scales a heal spell up based on the how much % the original heal spell was
int32 ScaleHealSpell(SpellInfo const * spellInfo, MpCreatureData* creatureData, Creature* creature, Creature* target, float healMultiplier);
private:
MythicPlus() { }
~MythicPlus() { }

View File

@@ -8,7 +8,7 @@ class MythicPlus_UnitScript : public UnitScript
public:
MythicPlus_UnitScript() : UnitScript("MythicPlus_UnitScript", true) { }
void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* /*spellInfo*/) override {
void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage, SpellInfo const* spellInfo) override {
if (!target && !attacker) {
return;
}
@@ -18,7 +18,19 @@ public:
return;
}
damage = modifyIncomingDmgHeal(MythicPlus::UNIT_EVENT_DOT, target, attacker, damage);
bool haspositiveeffect = false;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) {
if (spellInfo->_IsPositiveEffect(i, true)) {
haspositiveeffect = true;
break;
}
}
if(haspositiveeffect) {
damage = modifyIncomingDmgHeal(MythicPlus::UNIT_EVENT_HOT, target, attacker, damage);
} else {
damage = modifyIncomingDmgHeal(MythicPlus::UNIT_EVENT_DOT, target, attacker, damage);
}
}
void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage, SpellInfo const* /*spellInfo*/) override {
@@ -65,64 +77,93 @@ public:
healing = modifyIncomingDmgHeal(MythicPlus::UNIT_EVENT_HEAL, target, healer, healing);
}
// void OnAuraApply(Unit* unit, Aura* aura) override {}
};
uint32 modifyIncomingDmgHeal(MythicPlus::MP_UNIT_EVENT_TYPE eventType,Unit* target, Unit* attacker, uint32 damageOrHeal) {
if (!target && !attacker) {
return damageOrHeal;
}
uint32 modifyIncomingDmgHeal(MythicPlus::MP_UNIT_EVENT_TYPE eventType,Unit* target, Unit* attacker, uint32 damageOrHeal) {
if (!target && !attacker) {
return damageOrHeal;
}
int32 alteredDmgHeal = 0;
Map *map = target->GetMap();
if(!sMythicPlus->IsMapEligible(map)) {
return damageOrHeal;
}
Map *map = target->GetMap();
if(!sMythicPlus->IsMapEligible(map)) {
return damageOrHeal;
}
Creature* creature = attacker ? attacker->ToCreature() : nullptr;
if (!creature) {
MpLogger::debug("Attacker was considered not a creature");
return damageOrHeal;
}
Creature* creature = attacker->ToCreature();
MpInstanceData* instanceData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId());
if(!instanceData) {
return damageOrHeal;
}
MpInstanceData* instanceData = sMpDataStore->GetInstanceData(map->GetId(), map->GetInstanceId());
if(!instanceData) {
return damageOrHeal;
}
// If the target is the enemy then increase the amount of healing by the instance data modifier for spell output.
if(sMythicPlus->EligibleDamageTarget(target)) {
/**
* @TODO: Allow more granular control over the scaling of DOT, HOT, and other spell effects
* in the future if needed
*/
std::string eventName = "";
switch (eventType) {
case MythicPlus::UNIT_EVENT_MELEE:
if(creature->IsDungeonBoss()) {
return damageOrHeal * instanceData->boss.melee;
} else {
return damageOrHeal * instanceData->creature.melee;
}
eventName = "Melee";
break;
case MythicPlus::UNIT_EVENT_HEAL:
eventName = "Heal";
break;
case MythicPlus::UNIT_EVENT_DOT:
case MythicPlus::UNIT_EVENT_SPELL:
if(creature->IsDungeonBoss()) {
return damageOrHeal * instanceData->boss.spell;
} else {
return damageOrHeal * instanceData->creature.spell;
}
eventName = "DOT";
break;
case MythicPlus::UNIT_EVENT_SPELL:
eventName = "Spell";
break;
}
}
/**
* @TODO: Add more granular control over the scaling of healing spells
*/
if(sMythicPlus->EligibleHealTarget(target)) {
if(creature->IsDungeonBoss()) {
return damageOrHeal * instanceData->boss.spell;
} else {
return damageOrHeal * instanceData->creature.spell;
}
}
return damageOrHeal;
}
MpLogger::debug("Incoming Event Type ({}): {} hits {} before mod: {}", eventName, attacker->GetName(), target->GetName(), damageOrHeal);
bool isHeal = false;
// If the target is the enemy then increase the amount of healing by the instance data modifier for spell output.
if(sMythicPlus->EligibleDamageTarget(target)) {
/**
* @TODO: Allow more granular control over the scaling of DOT, HOT, and other spell effects
* in the future if needed
*/
switch (eventType) {
case MythicPlus::UNIT_EVENT_MELEE:
if(creature->IsDungeonBoss()) {
alteredDmgHeal = damageOrHeal * instanceData->boss.melee;
} else {
alteredDmgHeal = damageOrHeal * instanceData->creature.melee;
}
MpLogger::debug("Incoming Melee New Damage: {}({}) {} hits {}", alteredDmgHeal, damageOrHeal, attacker->GetName(), target->GetName());
break;
case MythicPlus::UNIT_EVENT_DOT:
case MythicPlus::UNIT_EVENT_SPELL:
if(creature->IsDungeonBoss()) {
alteredDmgHeal = damageOrHeal * instanceData->boss.spell;
} else {
alteredDmgHeal = damageOrHeal * instanceData->creature.spell;
}
MpLogger::debug("Incoming spell or dot New Damage: {}({}) {} hits {}", alteredDmgHeal, damageOrHeal, attacker->GetName(), target->GetName());
break;
}
}
/**
* @TODO: Add more granular control over the scaling of healing spells
*/
if(sMythicPlus->EligibleHealTarget(target) && (eventType == MythicPlus::UNIT_EVENT_HEAL || eventType == MythicPlus::UNIT_EVENT_HOT)) {
isHeal = true;
if(creature->IsDungeonBoss()) {
alteredDmgHeal = damageOrHeal * instanceData->boss.spell;
} else {
alteredDmgHeal = damageOrHeal * instanceData->creature.spell;
}
MpLogger::debug("Incoming heal: {}({}) {} hits {}", alteredDmgHeal, damageOrHeal, attacker->GetName(), target->GetName());
}
return alteredDmgHeal > 0 ? alteredDmgHeal : damageOrHeal;
}
// void OnAuraApply(Unit* unit, Aura* aura) override {}
};
void Add_MP_UnitScripts()
{