diff --git a/src/AllCreatureScript.cpp b/src/AllCreatureScript.cpp index 0445518..34a633a 100644 --- a/src/AllCreatureScript.cpp +++ b/src/AllCreatureScript.cpp @@ -1,6 +1,8 @@ +#include "CreatureAI.h" #include "MpDataStore.h" #include "MpLogger.h" #include "MythicPlus.h" +#include "MpScriptAI.h" #include "ScriptMgr.h" class MythicPlus_AllCreatureScript : public AllCreatureScript @@ -35,6 +37,22 @@ public: } else { sMythicPlus->AddCreatureForScaling(creature); } + + // // Assign random affix for now. + if (roll_chance_i(30)) { + uint32 irand = urand(0, 2); + + if(irand == 0) { + creature->AddAura(23341, creature); + creature->SetName("Infernal " + creature->GetName()); + } else if(irand == 1) { + creature->AddAura(34711, creature); + creature->SetName("Berserking " + creature->GetName()); + } else { + creature->AddAura(774, creature); + creature->SetName("Blessed " + creature->GetName()); + } + } } // Cleanup the creature from custom data used for mythic+ mod @@ -43,6 +61,19 @@ public: sMythicPlus->RemoveCreature(creature); } + // CreatureAI* GetCreatureAI(Creature* creature) const override + // { + // ASSERT(creature); + + // // Attach to creatures that are in a mythic+ map + // MpCreatureData* creatureData = sMpDataStore->GetCreatureData(creature->GetGUID()); + // if (!creatureData) { + // return nullptr; + // } + + // return new MpScriptAI(creature); + // } + }; void Add_MP_AllCreatureScripts() diff --git a/src/CommandScript.cpp b/src/CommandScript.cpp index 42fea44..43f2771 100644 --- a/src/CommandScript.cpp +++ b/src/CommandScript.cpp @@ -58,6 +58,7 @@ public: { sMpDataStore->LoadScaleFactors(); handler->PSendSysMessage("Mythic+ scale factors updated."); + return true; } diff --git a/src/Instances/Ragefire/boss_bazzalan.cpp b/src/Instances/Ragefire/boss_bazzalan.cpp index a3c7004..d2f1971 100644 --- a/src/Instances/Ragefire/boss_bazzalan.cpp +++ b/src/Instances/Ragefire/boss_bazzalan.cpp @@ -1,36 +1,19 @@ -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "CreatureAI.h" -#include "MpLogger.h" +// #include "BaseCreatureHandler.h" -class Ragefire_Bazzalan_Mythic : public CreatureScript -{ -public: - Ragefire_Bazzalan_Mythic() : CreatureScript("Ragefire_Bazzalan_Mythic") { } +// class Ragefire_Bazzalan_Mythic : public BaseCreatureHandler +// { +// public: +// Ragefire_Bazzalan_Mythic(uint32 creature) : BaseCreatureHandler(creature.GetEntry()); - struct Ragefire_Bazzalan_MythicAI : public ScriptedAI - { - Ragefire_Bazzalan_MythicAI(Creature* creature) : ScriptedAI(creature) { } +// // Implement the required methods from BaseCreatureHandler +// void OnJustDied(Creature* creature, Unit* killer) override { +// // Bazzalan-specific behavior on death +// creature->Yell("The flame... it burns out...", LANG_UNIVERSAL, nullptr); +// } - void Reset() override - { - MpLogger::debug(" >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Ragefire Bazzalan Mythic reset, restoring custom health"); - uint32 health = 1000000; // Ensure max health is reset if the boss resets - me->SetCreateHealth(health); - me->SetMaxHealth(health); - me->SetHealth(health); - me->ResetPlayerDamageReq(); - me->SetModifierValue(UNIT_MOD_HEALTH, BASE_VALUE, (float)health); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new Ragefire_Bazzalan_MythicAI(creature); - } -}; - -void AddSC_Ragefire_Bazzalan_Mythic() -{ - new Ragefire_Bazzalan_Mythic(); -} +// void OnJustSpawned(Creature* creature) override { +// // Bazzalan-specific behavior on spawn +// creature->Yell("The fire rises again!", LANG_UNIVERSAL, nullptr); +// creature->SetHealth(creature->GetMaxHealth()); // Restore health on spawn +// } +// }; diff --git a/src/MpScriptAI.h b/src/MpScriptAI.h index 9446fea..5225b94 100644 --- a/src/MpScriptAI.h +++ b/src/MpScriptAI.h @@ -6,56 +6,24 @@ #ifdef _ELUNA_CREATURE_AI_H #include "ElunaCreatureAI.h" + using BaseAI = ElunaCreatureAI; +#else + using BaseAI = ScriptedAI; #endif - -class MpScriptAI : public ScriptedAI +class MpScriptAI : public BaseAI { public: - MpScriptAI(Creature* creature) : ScriptedAI(creature) { -#ifdef _ELUNA_CREATURE_AI_H - // Check if Eluna is attached to the creature - if (ElunaCreatureAI* eluna = dynamic_cast(creature->AI())) { - elunaAI = eluna; // Store a pointer to the Eluna AI - } else { - elunaAI = nullptr; // No Eluna AI attached - } -#endif - } + MpScriptAI(Creature* creature) : BaseAI(creature) {} - // Example for JustDied event void JustDied(Unit* killer) override { sCreatureHooks->JustDied(me, killer); -#ifdef _ELUNA_CREATURE_AI_H - // If Eluna is attached, call its JustDied event - if (elunaAI){ - elunaAI->JustDied(killer); - } - else -#endif - { - // If Eluna is not installed or not attached, call the default AI handler - ScriptedAI::JustDied(killer); - } + BaseAI::JustDied(killer); } void Reset() override { -#ifdef _ELUNA_CREATURE_AI_H - // If Eluna is attached, call its Reset event - if (elunaAI){ - elunaAI->Reset(); - } - else -#endif - { - // Call the default AI handler - ScriptedAI::Reset(); - } + BaseAI::Reset(); } -private: -#ifdef ENABLE_ELUNA - ElunaCreatureAI* elunaAI; // Store a pointer to Eluna's AI if attached -#endif }; diff --git a/src/MythicPlus.cpp b/src/MythicPlus.cpp index bbe1c5c..a860d66 100644 --- a/src/MythicPlus.cpp +++ b/src/MythicPlus.cpp @@ -250,45 +250,95 @@ void MythicPlus::ScaleCreature(uint8 level, Creature* creature, MpMultipliers* m creature->SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana * 3.0f); } - float oldAp = stats->AttackPower; - float oldRangeAp = stats->RangedAttackPower; + MpInstanceData *instanceData = sMpDataStore->GetInstanceData(creature->GetMapId(), creature->GetInstanceId()); + int32 meleeDamage = sMpDataStore->GetDamageScaleFactor(creature->GetMapId(), instanceData->difficulty); + if(creature->IsDungeonBoss()) { + meleeDamage *= 1.15; + } + + // Calculate the level difference + float levelDifference = creature->GetLevel() - origLevel; + + // New formula with adjusted divisor for smoother scaling + float scalingFactor = 1 + (std::log2(levelDifference + 1) * (float(meleeDamage) / 30.0f)); + + + uint32 ap = uint32(sMythicPlus->meleeAttackPowerStart - sMythicPlus->meleeAttackPowerDampener * log(cInfo->DamageModifier)); uint32 rangeAp = irand(215, 357); - float ap; // = ((85 - origLevel) * APratio); // * 100; - int32 damageBonus = sMpDataStore->GetDamageScaleFactor(mapId, difficulty); - float dmgMod = cInfo->DamageModifier + damageBonus; - - - ap = dmgMod * 80 + oldAp; - if (creature->GetLevel() >= 60) { - ap = ap * 1.25f; - rangeAp = rangeAp * 1.25f; + if(cInfo->unit_class == UNIT_CLASS_MAGE) { + ap = ap * 0.6f; } - creature->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, ap); - creature->SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, rangeAp); - // MpLogger::debug("Creature {} base attack power {} new ap {}", - // creature->GetName(), - // oldAp, - // ap - // ); - // This works out a bonus damage to apply to the mob using the database and original mod settings. - // the thought behind this is some mobs in dungeons are intended to hit harder than others - // so applying a flat bonus keeps the ratios the same but increases the overall difficulty. - // Of course within reason. - - int32 maxBonus = sMpDataStore->GetMaxDamageScaleFactor(mapId, difficulty); - - - // Allow bosses to scale as high as they want but limit non-bosses to a max bonus - if(!creature->IsDungeonBoss() && damageBonus > maxBonus) { - dmgMod = maxBonus; + if(cInfo->unit_class == UNIT_CLASS_WARRIOR) { + ap = ap * 1.2f; } - float oldDmgModifier = creature->GetModifierValue(UNIT_MOD_DAMAGE_MAINHAND, BASE_VALUE); - creature->SetModifierValue(UNIT_MOD_DAMAGE_MAINHAND,BASE_PCT, dmgMod); - creature->SetModifierValue(UNIT_MOD_DAMAGE_OFFHAND,BASE_PCT, dmgMod*0.85f); - creature->SetModifierValue(UNIT_MOD_DAMAGE_RANGED,BASE_PCT, dmgMod); + + if(cInfo->unit_class == UNIT_CLASS_ROGUE) { + ap = ap * 1.5f; + } + + // Set scaled attack power + creature->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, ap + stats->AttackPower * scalingFactor); + creature->SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, rangeAp + stats->RangedAttackPower * scalingFactor); + + // set the base weapon damage + creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING], 0); + creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, stats->BaseDamage[EXPANSION_WRATH_OF_THE_LICH_KING], 0); + + // float oldAp = stats->AttackPower; + // float oldRangeAp = stats->RangedAttackPower; + + // float ap; // = ((85 - origLevel) * APratio); // * 100; + + // int32 damageBonus = sMpDataStore->GetDamageScaleFactor(mapId, difficulty); + // float dmgMod = cInfo->DamageModifier + damageBonus; + + + // ap = dmgMod * 80 + oldAp; + // if (creature->GetLevel() >= 60) { + // ap = ap * 1.25f; + // rangeAp = rangeAp * 1.25f; + // } + + // creature->SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, ap); + // creature->SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, rangeAp); + + // // MpLogger::debug("Creature {} base attack power {} new ap {}", + // // creature->GetName(), + // // oldAp, + // // ap + // // ); + // // This works out a bonus damage to apply to the mob using the database and original mod settings. + // // the thought behind this is some mobs in dungeons are intended to hit harder than others + // // so applying a flat bonus keeps the ratios the same but increases the overall difficulty. + // // Of course within reason. + + // int32 maxBonus = sMpDataStore->GetMaxDamageScaleFactor(mapId, difficulty); + + + // // Allow bosses to scale as high as they want but limit non-bosses to a max bonus + // if(!creature->IsDungeonBoss() && damageBonus > maxBonus) { + // dmgMod = maxBonus; + // } + // float oldDmgModifier = creature->GetModifierValue(UNIT_MOD_DAMAGE_MAINHAND, BASE_VALUE); + // creature->SetModifierValue(UNIT_MOD_DAMAGE_MAINHAND,BASE_VALUE, oldDmgModifier * dmgMod); + // creature->SetModifierValue(UNIT_MOD_DAMAGE_OFFHAND,BASE_VALUE, oldDmgModifier * dmgMod * 0.85f); + // creature->SetModifierValue(UNIT_MOD_DAMAGE_RANGED,BASE_VALUE, oldDmgModifier * dmgMod); + // creature->UpdateAllStats(); + + +// Retrieve instance data and damage scaling factors +// MpInstanceData* instanceData = sMpDataStore->GetInstanceData(creature->GetMapId(), creature->GetInstanceId()); +// int32 damageBonus = sMpDataStore->GetDamageScaleFactor(creature->GetMapId(), instanceData->difficulty); + +// // Apply a boss multiplier for scaling +// if (creature->IsDungeonBoss()) { +// damageBonus *= 1.15; +// } + + // Update all stats to apply the new damage values creature->UpdateAllStats(); // Scale up the armor with some variance also to make some tougher enemies in the mix diff --git a/src/MythicPlus.h b/src/MythicPlus.h index 2760357..08f52da 100644 --- a/src/MythicPlus.h +++ b/src/MythicPlus.h @@ -56,6 +56,10 @@ public: uint32 legendaryItemOffset; uint32 ascendantItemOffset; + uint32 meleeAttackPowerDampener; + uint32 meleeAttackPowerStart; + + enum MP_UNIT_EVENT_TYPE { UNIT_EVENT_MELEE, diff --git a/src/MythicPlus_loader.cpp b/src/MythicPlus_loader.cpp index e6bcf0a..1ceaef3 100755 --- a/src/MythicPlus_loader.cpp +++ b/src/MythicPlus_loader.cpp @@ -1,5 +1,9 @@ -// #include "ScriptMgr.h" -// #include "Instances/Ragefire/boss_bazzalan.cpp" +#include "Instances/Ragefire/boss_bazzalan.cpp" + +// Creature Overrides +enum { + RAGEFIRE_BAZZALAN = 11519 +}; void Addmod_mythic_plusScripts(); void Add_MP_AllCreatureScripts(); @@ -12,7 +16,7 @@ void Add_MP_UnitScripts(); void Add_MP_WorldScripts(); // Mythic custom encounters for mythic+ dungeons -void AddSC_Ragefire_Bazzalan_Mythic(); + void Addmod_mythic_plusScripts() { @@ -25,6 +29,7 @@ void Addmod_mythic_plusScripts() Add_MP_UnitScripts(); Add_MP_WorldScripts(); - // Boss custom changes for mythic+ dungeons - AddSC_Ragefire_Bazzalan_Mythic(); + // list of boss / creature event handlers + // new Ragefire_Bazzalan_Mythic(RAGEFIRE_BAZZALAN); + } diff --git a/src/PlayerScript.cpp b/src/PlayerScript.cpp index bfaa57b..8feefe3 100644 --- a/src/PlayerScript.cpp +++ b/src/PlayerScript.cpp @@ -16,19 +16,18 @@ public: return; } - if (!player) { - return; - } - - if (!killer) { + if (!player || !killer) { return; } MpGroupData *data = sMpDataStore->GetGroupData(player->GetGroup()); - - if (player->GetMap()->IsDungeon()) { - MpLogger::debug("Player {} just died in dungeon {} by {}", player->GetName(), player->GetMap()->GetMapName(), killer->GetName()); + if (!data) { + return; } + + data->deaths++; // + + } }; diff --git a/src/WorldScript.cpp b/src/WorldScript.cpp index 2f9ff07..c689894 100644 --- a/src/WorldScript.cpp +++ b/src/WorldScript.cpp @@ -86,6 +86,9 @@ public: sMythicPlus->mythicItemOffset = sConfigMgr->GetOption("MythicPlus.Mythic.ItemOffset", 20000000); sMythicPlus->legendaryItemOffset = sConfigMgr->GetOption("MythicPlus.Legendary.ItemOffset", 21000000); sMythicPlus->ascendantItemOffset = sConfigMgr->GetOption("MythicPlus.Ascendant.ItemOffset", 22000000); + + sMythicPlus->meleeAttackPowerDampener = sConfigMgr->GetOption("MythicPlus.MeleeAttackPowerDampener", 800); + sMythicPlus->meleeAttackPowerStart = sConfigMgr->GetOption("MythicPlus.MeleeAttackPowerStart", 3000); } void OnStartup() override