From 7b3141bfde021f09d9d28eda2467262026a30ba1 Mon Sep 17 00:00:00 2001 From: joschiwald Date: Sun, 15 Jun 2014 17:41:42 +0200 Subject: Scripts/Gurtogg: * fixed bloodboil targeting * fel rage should only hit players Closes #12193 --- .../scripts/Outland/BlackTemple/boss_bloodboil.cpp | 333 --------------------- .../Outland/BlackTemple/boss_gurtogg_bloodboil.cpp | 318 ++++++++++++++++++++ src/server/scripts/Outland/CMakeLists.txt | 2 +- 3 files changed, 319 insertions(+), 334 deletions(-) delete mode 100644 src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp create mode 100644 src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp (limited to 'src/server/scripts/Outland') diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp deleted file mode 100644 index 0004df68016..00000000000 --- a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore - * Copyright (C) 2006-2009 ScriptDev2 - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -/* ScriptData -SDName: Boss_Bloodboil -SD%Complete: 80 -SDComment: Bloodboil not working correctly, missing enrage -SDCategory: Black Temple -EndScriptData */ - -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "black_temple.h" - -enum Bloodboil -{ - //Speech'n'Sound - SAY_AGGRO = 0, - SAY_SLAY = 1, - SAY_SPECIAL = 2, - SAY_ENRAGE = 3, - SAY_DEATH = 4, - - //Spells - SPELL_ACID_GEYSER = 40630, - SPELL_ACIDIC_WOUND = 40481, - SPELL_ARCING_SMASH = 40599, - SPELL_BLOODBOIL = 42005, // This spell is AoE whereas it shouldn't be - SPELL_FEL_ACID = 40508, - SPELL_FEL_RAGE_SELF = 40594, - SPELL_FEL_RAGE_TARGET = 40604, - SPELL_FEL_RAGE_2 = 40616, - SPELL_FEL_RAGE_3 = 41625, - SPELL_BEWILDERING_STRIKE = 40491, - SPELL_EJECT1 = 40486, // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) - SPELL_EJECT2 = 40597, // 1000 Physical damage + Stun (used in phase 2?) - SPELL_TAUNT_GURTOGG = 40603, - SPELL_INSIGNIFIGANCE = 40618, - SPELL_BERSERK = 45078 -}; - - -//This is used to sort the players by distance in preparation for the Bloodboil cast. - -class boss_gurtogg_bloodboil : public CreatureScript -{ -public: - boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct boss_gurtogg_bloodboilAI : public ScriptedAI - { - boss_gurtogg_bloodboilAI(Creature* creature) : ScriptedAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; - - uint64 TargetGUID; - - float TargetThreat; - - uint32 BloodboilTimer; - uint32 BloodboilCount; - uint32 AcidGeyserTimer; - uint32 AcidicWoundTimer; - uint32 ArcingSmashTimer; - uint32 EnrageTimer; - uint32 FelAcidTimer; - uint32 EjectTimer; - uint32 BewilderingStrikeTimer; - uint32 PhaseChangeTimer; - - bool Phase1; - - void Reset() override - { - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, NOT_STARTED); - - TargetGUID = 0; - - TargetThreat = 0; - - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidGeyserTimer = 1000; - AcidicWoundTimer = 6000; - ArcingSmashTimer = 19000; - EnrageTimer = 600000; - FelAcidTimer = 25000; - EjectTimer = 10000; - BewilderingStrikeTimer = 15000; - PhaseChangeTimer = 60000; - - Phase1 = true; - - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); - } - - void EnterCombat(Unit* /*who*/) override - { - DoZoneInCombat(); - Talk(SAY_AGGRO); - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) override - { - Talk(SAY_SLAY); - } - - void JustDied(Unit* /*killer*/) override - { - instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE); - - Talk(SAY_DEATH); - } - - // Note: This seems like a very complicated fix. The fix needs to be handled by the core, as implementation of limited-target AoE spells are still not limited. - void CastBloodboil() - { - // Get the Threat List - std::list m_threatlist = me->getThreatManager().getThreatList(); - - if (m_threatlist.empty()) // He doesn't have anyone in his threatlist, useless to continue - return; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr!= m_threatlist.end(); ++itr) //store the threat list in a different container - { - Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (target && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER) - targets.push_back(target); - } - - //Sort the list of players - targets.sort(Trinity::ObjectDistanceOrderPred(me, false)); - //Resize so we only get top 5 - targets.resize(5); - - //Aura each player in the targets list with Bloodboil. Aura code copied+pasted from Aura command in Level3.cpp - /*SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_BLOODBOIL); - if (spellInfo) - { - for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) - { - Unit* target = *itr; - if (!target) return; - for (uint32 i = 0; i<3; ++i) - { - uint8 eff = spellInfo->Effect[i]; - if (eff >= TOTAL_SPELL_EFFECTS) - continue; - - Aura* Aur = new Aura(spellInfo, i, target, target, target); - target->AddAura(Aur); - } - } - }*/ - } - - void RevertThreatOnTarget(uint64 guid) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, guid)) - { - if (DoGetThreat(unit)) - DoModifyThreatPercent(unit, -100); - if (TargetThreat) - me->AddThreat(unit, TargetThreat); - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (ArcingSmashTimer <= diff) - { - DoCastVictim(SPELL_ARCING_SMASH); - ArcingSmashTimer = 10000; - } else ArcingSmashTimer -= diff; - - if (FelAcidTimer <= diff) - { - DoCastVictim(SPELL_FEL_ACID); - FelAcidTimer = 25000; - } else FelAcidTimer -= diff; - - if (!me->HasAura(SPELL_BERSERK)) - { - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_BERSERK); - Talk(SAY_ENRAGE); - } else EnrageTimer -= diff; - } - - if (Phase1) - { - if (BewilderingStrikeTimer <= diff) - { - DoCastVictim(SPELL_BEWILDERING_STRIKE); - float mt_threat = DoGetThreat(me->GetVictim()); - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) - me->AddThreat(target, mt_threat); - BewilderingStrikeTimer = 20000; - } else BewilderingStrikeTimer -= diff; - - if (EjectTimer <= diff) - { - DoCastVictim(SPELL_EJECT1); - DoModifyThreatPercent(me->GetVictim(), -40); - EjectTimer = 15000; - } else EjectTimer -= diff; - - if (AcidicWoundTimer <= diff) - { - DoCastVictim(SPELL_ACIDIC_WOUND); - AcidicWoundTimer = 10000; - } else AcidicWoundTimer -= diff; - - if (BloodboilTimer <= diff) - { - if (BloodboilCount < 5) // Only cast it five times. - { - //CastBloodboil(); // Causes issues on windows, so is commented out. - DoCastVictim(SPELL_BLOODBOIL); - ++BloodboilCount; - BloodboilTimer = 10000*BloodboilCount; - } - } else BloodboilTimer -= diff; - } - - if (!Phase1) - { - if (AcidGeyserTimer <= diff) - { - DoCastVictim(SPELL_ACID_GEYSER); - AcidGeyserTimer = 30000; - } else AcidGeyserTimer -= diff; - - if (EjectTimer <= diff) - { - DoCastVictim(SPELL_EJECT2); - EjectTimer = 15000; - } else EjectTimer -= diff; - } - - if (PhaseChangeTimer <= diff) - { - if (Phase1) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - Phase1 = false; - - TargetThreat = DoGetThreat(target); - TargetGUID = target->GetGUID(); - target->CastSpell(me, SPELL_TAUNT_GURTOGG, true); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -100); - me->AddThreat(target, 50000000.0f); - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); - // If VMaps are disabled, this spell can call the whole instance - DoCast(me, SPELL_INSIGNIFIGANCE, true); - DoCast(target, SPELL_FEL_RAGE_TARGET, true); - DoCast(target, SPELL_FEL_RAGE_2, true); - /* These spells do not work, comment them out for now. - DoCast(target, SPELL_FEL_RAGE_2, true); - DoCast(target, SPELL_FEL_RAGE_3, true);*/ - - //Cast this without triggered so that it appears in combat logs and shows visual. - DoCast(me, SPELL_FEL_RAGE_SELF); - - Talk(SAY_SPECIAL); - - AcidGeyserTimer = 1000; - PhaseChangeTimer = 30000; - } - } - else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage - { - if (TargetGUID) - RevertThreatOnTarget(TargetGUID); - TargetGUID = 0; - Phase1 = true; - BloodboilTimer = 10000; - BloodboilCount = 0; - AcidicWoundTimer += 2000; - ArcingSmashTimer += 2000; - FelAcidTimer += 2000; - EjectTimer += 2000; - PhaseChangeTimer = 60000; - me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); - } - } else PhaseChangeTimer -= diff; - - DoMeleeAttackIfReady(); - } - }; - -}; - -void AddSC_boss_gurtogg_bloodboil() -{ - new boss_gurtogg_bloodboil(); -} diff --git a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp new file mode 100644 index 00000000000..f03caa37cb2 --- /dev/null +++ b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2008-2014 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +/* ScriptData +Name: Boss_Bloodboil +Complete: 80 +Category: Black Temple +EndScriptData */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "black_temple.h" + +enum Bloodboil +{ + //Speech'n'Sound + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_SPECIAL = 2, + SAY_ENRAGE = 3, + SAY_DEATH = 4, + + //Spells + SPELL_ACID_GEYSER = 40630, + SPELL_ACIDIC_WOUND = 40481, + SPELL_ARCING_SMASH = 40599, + SPELL_BLOODBOIL = 42005, // This spell is AoE whereas it shouldn't be + SPELL_FEL_ACID = 40508, + SPELL_FEL_RAGE_SELF = 40594, + SPELL_FEL_RAGE_TARGET = 40604, + SPELL_FEL_RAGE_2 = 40616, + SPELL_FEL_RAGE_3 = 41625, + SPELL_BEWILDERING_STRIKE = 40491, + SPELL_EJECT1 = 40486, // 1000 Physical damage + knockback + script effect (should handle threat reduction I think) + SPELL_EJECT2 = 40597, // 1000 Physical damage + Stun (used in phase 2?) + SPELL_TAUNT_GURTOGG = 40603, + SPELL_INSIGNIFIGANCE = 40618, + SPELL_BERSERK = 45078 +}; + +class boss_gurtogg_bloodboil : public CreatureScript +{ +public: + boss_gurtogg_bloodboil() : CreatureScript("boss_gurtogg_bloodboil") { } + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } + + struct boss_gurtogg_bloodboilAI : public ScriptedAI + { + boss_gurtogg_bloodboilAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + } + + InstanceScript* instance; + + uint64 TargetGUID; + + float TargetThreat; + + uint32 BloodboilTimer; + uint32 BloodboilCount; + uint32 AcidGeyserTimer; + uint32 AcidicWoundTimer; + uint32 ArcingSmashTimer; + uint32 EnrageTimer; + uint32 FelAcidTimer; + uint32 EjectTimer; + uint32 BewilderingStrikeTimer; + uint32 PhaseChangeTimer; + + bool Phase1; + + void Reset() override + { + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, NOT_STARTED); + + TargetGUID = 0; + + TargetThreat = 0; + + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidGeyserTimer = 1000; + AcidicWoundTimer = 6000; + ArcingSmashTimer = 19000; + EnrageTimer = 600000; + FelAcidTimer = 25000; + EjectTimer = 10000; + BewilderingStrikeTimer = 15000; + PhaseChangeTimer = 60000; + + Phase1 = true; + + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + Talk(SAY_AGGRO); + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) override + { + Talk(SAY_SLAY); + } + + void JustDied(Unit* /*killer*/) override + { + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE); + + Talk(SAY_DEATH); + } + + void RevertThreatOnTarget(uint64 guid) + { + if (Unit* unit = ObjectAccessor::GetUnit(*me, guid)) + { + if (DoGetThreat(unit)) + DoModifyThreatPercent(unit, -100); + if (TargetThreat) + me->AddThreat(unit, TargetThreat); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (ArcingSmashTimer <= diff) + { + DoCastVictim(SPELL_ARCING_SMASH); + ArcingSmashTimer = 10000; + } else ArcingSmashTimer -= diff; + + if (FelAcidTimer <= diff) + { + DoCastVictim(SPELL_FEL_ACID); + FelAcidTimer = 25000; + } else FelAcidTimer -= diff; + + if (!me->HasAura(SPELL_BERSERK)) + { + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_BERSERK); + Talk(SAY_ENRAGE); + } else EnrageTimer -= diff; + } + + if (Phase1) + { + if (BewilderingStrikeTimer <= diff) + { + DoCastVictim(SPELL_BEWILDERING_STRIKE); + float mt_threat = DoGetThreat(me->GetVictim()); + if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) + me->AddThreat(target, mt_threat); + BewilderingStrikeTimer = 20000; + } else BewilderingStrikeTimer -= diff; + + if (EjectTimer <= diff) + { + DoCastVictim(SPELL_EJECT1); + DoModifyThreatPercent(me->GetVictim(), -40); + EjectTimer = 15000; + } else EjectTimer -= diff; + + if (AcidicWoundTimer <= diff) + { + DoCastVictim(SPELL_ACIDIC_WOUND); + AcidicWoundTimer = 10000; + } else AcidicWoundTimer -= diff; + + if (BloodboilTimer <= diff) + { + if (BloodboilCount < 5) // Only cast it five times. + { + DoCastAOE(SPELL_BLOODBOIL); + ++BloodboilCount; + BloodboilTimer = 10000*BloodboilCount; + } + } else BloodboilTimer -= diff; + } + + if (!Phase1) + { + if (AcidGeyserTimer <= diff) + { + DoCastVictim(SPELL_ACID_GEYSER); + AcidGeyserTimer = 30000; + } else AcidGeyserTimer -= diff; + + if (EjectTimer <= diff) + { + DoCastVictim(SPELL_EJECT2); + EjectTimer = 15000; + } else EjectTimer -= diff; + } + + if (PhaseChangeTimer <= diff) + { + if (Phase1) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + { + Phase1 = false; + + TargetThreat = DoGetThreat(target); + TargetGUID = target->GetGUID(); + target->CastSpell(me, SPELL_TAUNT_GURTOGG, true); + if (DoGetThreat(target)) + DoModifyThreatPercent(target, -100); + me->AddThreat(target, 50000000.0f); + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); + // If VMaps are disabled, this spell can call the whole instance + DoCast(me, SPELL_INSIGNIFIGANCE, true); + DoCast(target, SPELL_FEL_RAGE_TARGET, true); + DoCast(target, SPELL_FEL_RAGE_2, true); + /* These spells do not work, comment them out for now. + DoCast(target, SPELL_FEL_RAGE_2, true); + DoCast(target, SPELL_FEL_RAGE_3, true);*/ + + //Cast this without triggered so that it appears in combat logs and shows visual. + DoCast(me, SPELL_FEL_RAGE_SELF); + + Talk(SAY_SPECIAL); + + AcidGeyserTimer = 1000; + PhaseChangeTimer = 30000; + } + } + else // Encounter is a loop pretty much. Phase 1 -> Phase 2 -> Phase 1 -> Phase 2 till death or enrage + { + if (TargetGUID) + RevertThreatOnTarget(TargetGUID); + TargetGUID = 0; + Phase1 = true; + BloodboilTimer = 10000; + BloodboilCount = 0; + AcidicWoundTimer += 2000; + ArcingSmashTimer += 2000; + FelAcidTimer += 2000; + EjectTimer += 2000; + PhaseChangeTimer = 60000; + me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false); + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false); + } + } else PhaseChangeTimer -= diff; + + DoMeleeAttackIfReady(); + } + }; + +}; + +// 42005 - Bloodboil +class spell_gurtogg_bloodboil_bloodboil : public SpellScriptLoader +{ + public: + spell_gurtogg_bloodboil_bloodboil() : SpellScriptLoader("spell_gurtogg_bloodboil_bloodboil") { } + + class spell_gurtogg_bloodboil_bloodboil_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gurtogg_bloodboil_bloodboil_SpellScript); + + void FilterTargets(std::list& targets) + { + if (targets.size() <= 5) + return; + + // Sort the list of players + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster(), false)); + // Resize so we only get top 5 + targets.resize(5); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gurtogg_bloodboil_bloodboil_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gurtogg_bloodboil_bloodboil_SpellScript(); + } +}; + +void AddSC_boss_gurtogg_bloodboil() +{ + new boss_gurtogg_bloodboil(); + new spell_gurtogg_bloodboil_bloodboil(); +} diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index 414a3bce14a..0c69a236ef8 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -112,7 +112,7 @@ set(scripts_STAT_SRCS Outland/BlackTemple/instance_black_temple.cpp Outland/BlackTemple/boss_reliquary_of_souls.cpp Outland/BlackTemple/boss_warlord_najentus.cpp - Outland/BlackTemple/boss_bloodboil.cpp + Outland/BlackTemple/boss_gurtogg_bloodboil.cpp Outland/BlackTemple/boss_illidan.cpp Outland/zone_shadowmoon_valley.cpp Outland/zone_blades_edge_mountains.cpp -- cgit v1.2.3