mirror of
https://github.com/araxiaonline/mod-mythic-plus.git
synced 2026-06-13 03:02:24 -04:00
Adding Spell scaling into base class
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() { }
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user