aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/scripts/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp262
1 files changed, 166 insertions, 96 deletions
diff --git a/src/bindings/scripts/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp b/src/bindings/scripts/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp
index 34fa7820208..0ee5b099420 100644
--- a/src/bindings/scripts/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp
+++ b/src/bindings/scripts/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp
@@ -18,77 +18,73 @@
/* ScriptData
SDName: razorscale
+SDAuthor: MaXiMiUS
SD%Complete: 65
EndScriptData */
#include "precompiled.h"
#include "ulduar.h"
-//wrong text ids. correct are between -1000000 AND -1999999
-//between -2000000 and -2999999 are custom texts so wtf?
+//not in db
#define SAY_AGGRO -2000000
#define SAY_KILL -2000001
#define SAY_PHASE_2_TRANS -2000002
#define SAY_PHASE_3_TRANS -2000003
#define EMOTE_BREATH -2000004
-#define SPELL_FLAMEBUFFET 64016
-#define SPELL_FIREBALL 62796
-
-#define SPELL_WINGBUFFET 62666
-#define SPELL_FLAMEBREATH 63317
-#define SPELL_FUSEARMOR 64771
-#define SPELL_DEVOURINGFLAME 63014
-
-#define SPELL_SUMMONADDS 17646
-
-#define CREATURE_ADDS 33846
-
-static float MovementLocations[4][3] =
+enum Spells
{
- {607.7, -281.9, 408.6},
- {602.0, -245.5, 424.7},
- {612.3, -230.8, 409.1},
- {624.1, -251.8, 426.1}
+ SPELL_FLAMEBUFFET = 64016,
+ SPELL_FIREBALL = 62796,
+
+ SPELL_WINGBUFFET = 62666,
+ SPELL_FLAMEBREATH = 63317,
+ SPELL_FUSEARMOR = 64771,
+ SPELL_DEVOURINGFLAME = 63014
};
-static float SpawnLocations[4][3] =
+enum Mobs
{
- {602.0, -248.1, 391.2},
- {624.4, -232-4, 391.1},
- {643.3, -256.4, 391.4},
- {626.6, -271.5, 391.4},
+ NPC_DARK_RUNE_SENTINEL = 33846
};
struct TRINITY_DLL_DECL boss_razorscaleAI : public BossAI
{
boss_razorscaleAI(Creature *pCreature) : BossAI(pCreature, TYPE_RAZORSCALE) {}
- uint32 Phase;
+ uint8 Phase;
uint32 FlameBreathTimer;
- uint32 FUSEARMORTimer;
- uint32 DEVOURINGFLAMETimer;
- uint32 MovementTimer;
+ uint32 FuseArmorTimer;
+ uint32 DevouringFlameTimer;
+ uint32 FlameBuffetTimer;
uint32 SummonAddsTimer;
uint32 WingBuffetTimer;
uint32 FireballTimer;
+ //uint32 StunTimer;
+ //uint32 CastSpellsTimer;
bool InitialSpawn;
+ bool IsFlying;
void Reset()
{
Phase = 1;
+ FlyPhase(Phase, 0);
+
FlameBreathTimer = 20000;
- DEVOURINGFLAMETimer = 2000;
- FUSEARMORTimer = 15000;
- MovementTimer = 3000;
+ DevouringFlameTimer = 2000;
+ FuseArmorTimer = 15000;
+ FlameBuffetTimer = 3000;
SummonAddsTimer = 45000;
WingBuffetTimer = 17000;
FireballTimer = 18000;
+ //StunTimer = 30000;
+ //CastSpellsTimer = 0;
InitialSpawn = true;
+ IsFlying = true;
m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
m_creature->ApplySpellImmune(1, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true);
@@ -122,55 +118,40 @@ struct TRINITY_DLL_DECL boss_razorscaleAI : public BossAI
m_creature->GetMotionMaster()->MoveTargetedHome();
}
- if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 99 && Phase == 1)
+ if(!m_creature->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()) // Victim is not controlled by a player (should never happen)
+ m_creature->getVictim()->CombatStop(); // Forcibly stop combat with this victim
+
+ if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 99 && Phase == 1) // TODO: Only land (exit Phase 1) if brought down with harpoon guns! This is important!
{
Phase = 2;
- m_creature->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- m_creature->SetHover(true);
- m_creature->GetMotionMaster()->Clear(false);
- m_creature->GetMotionMaster()->MoveIdle();
- DoScriptText(SAY_PHASE_2_TRANS, m_creature);
+ DoScriptText(SAY_PHASE_2_TRANS, m_creature); // Audio: "Move quickly! She won't remain grounded for long!"
}
- if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 50 && Phase == 2)
+ if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 33 && Phase == 2) // Health under 33%, Razorscale can't fly anymore.
{
Phase = 3;
- m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING);
- m_creature->SetHover(false);
- m_creature->GetMotionMaster()->MovePoint(0, 619.6, -261.1, 391.471832);
- DoStartMovement(m_creature->getVictim());
- m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
- DoScriptText(SAY_PHASE_3_TRANS, m_creature);
- m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ DoScriptText(SAY_PHASE_3_TRANS, m_creature); // "Razorscale lands permanently!"
+ // TODO: Cast Devouring Flame on all harpoon guns simultaneously, briefly after Phase 3 starts (lasts until the harpoon guns are destroyed)
}
- if (Phase == 1 || Phase == 3)
+ /*
+ if (Phase == 2 && CastSpellsTimer > 0) // 5 seconds of spell casting, after stun breaks, during Phase 2
{
- if (FlameBreathTimer <= diff)
- {
- DoCastVictim(SPELL_FLAMEBREATH);
- FlameBreathTimer = 15000;
- } else FlameBreathTimer -= diff;
-
- if (DEVOURINGFLAMETimer <= diff)
- {
- std::list<Unit*> pTargets;
- SelectTargetList(pTargets, 10, SELECT_TARGET_RANDOM, 100, true);
- for (std::list<Unit*>::iterator i = pTargets.begin(); i != pTargets.end(); ++i)
- if (!m_creature->HasInArc(M_PI, *i))
- {
- DoCast(*i, SPELL_DEVOURINGFLAME);
- break;
- }
+ if (CastSpellsTimer <= diff) // 5 seconds are up
+ Phase = 1; // Return to phase 1
+ else
+ CastSpellsTimer -= diff;
+ }*/
- DEVOURINGFLAMETimer = 10000;
- } else DEVOURINGFLAMETimer -= diff;
+ FlyPhase(Phase, diff);
- if (FUSEARMORTimer <= diff)
+ if (Phase >= 2) // Ground Phase (Phase 3 = permanent ground phase)
+ {
+ if (FuseArmorTimer <= diff)
{
DoCastVictim(SPELL_FUSEARMOR);
- FUSEARMORTimer = 10000;
- } else FUSEARMORTimer -= diff;
+ FuseArmorTimer = 10000;
+ } else FuseArmorTimer -= diff;
if (WingBuffetTimer <= diff)
{
@@ -178,10 +159,53 @@ struct TRINITY_DLL_DECL boss_razorscaleAI : public BossAI
WingBuffetTimer = urand(7000,14000);
} else WingBuffetTimer -= diff;
+ if (FireballTimer <= diff)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
+ {
+ m_creature->SetInFront(pTarget);
+ DoCast(pTarget, SPELL_FIREBALL);
+ }
+
+ FireballTimer = 18000;
+ } else FireballTimer -= diff;
+
+ if (FlameBreathTimer <= diff)
+ {
+ DoScriptText(EMOTE_BREATH, m_creature); // TODO: "Razorscale takes a deep breath..."
+ DoCastVictim(SPELL_FLAMEBREATH);
+ FlameBreathTimer = 15000;
+ WingBuffetTimer = 0;
+ } else FlameBreathTimer -= diff;
+
+ if (Phase == 3)
+ {
+ if (FlameBuffetTimer <= diff)
+ {
+ DoScriptText(EMOTE_BREATH, m_creature);
+ std::list<Unit*> pTargets;
+ SelectTargetList(pTargets, HEROIC(3,9), SELECT_TARGET_RANDOM, 100, true);
+ uint8 i = 0;
+ for (std::list<Unit*>::iterator itr = pTargets.begin(); itr != pTargets.end();)
+ {
+ if (m_creature->HasInArc(M_PI, *itr))
+ {
+ DoCast(*itr, SPELL_FLAMEBUFFET, true);
+ ++i;
+ }
+ if (++itr == pTargets.end() || i == HEROIC(3,9))
+ {
+ AttackStart(*--itr); // seems to attack targets randomly during perma-ground phase..
+ break;
+ }
+ }
+ FlameBuffetTimer = 25000;
+ } else FlameBuffetTimer -= diff;
+ }
+
DoMeleeAttackIfReady();
}
-
- if (Phase == 2)
+ else if (Phase == 1) //Flying Phase
{
if (InitialSpawn)
SummonAdds();
@@ -190,30 +214,25 @@ struct TRINITY_DLL_DECL boss_razorscaleAI : public BossAI
if (FireballTimer <= diff)
{
- std::list<Unit*> pTargets;
- SelectTargetList(pTargets, 10, SELECT_TARGET_RANDOM, 100, true);
- for (std::list<Unit*>::iterator i = pTargets.begin(); i != pTargets.end(); ++i)
- if (!m_creature->HasInArc(M_PI, *i))
- {
- DoCast(*i, SPELL_FIREBALL);
- break;
- }
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
+ {
+ m_creature->SetInFront(pTarget);
+ DoCast(pTarget, SPELL_FIREBALL);
+ }
FireballTimer = 18000;
} else FireballTimer -= diff;
- if (MovementTimer <= diff)
+ if (DevouringFlameTimer <= diff)
{
- if (urand(0,99) < 30)
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
{
- DoScriptText(EMOTE_BREATH, m_creature);
- if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(pTarget, SPELL_FLAMEBUFFET);
+ m_creature->SetInFront(pTarget);
+ DoCast(pTarget, SPELL_DEVOURINGFLAME);
}
- else ChangePosition();
- MovementTimer = 25000;
- } else MovementTimer -= diff;
+ DevouringFlameTimer = 10000;
+ } else DevouringFlameTimer -= diff;
if (SummonAddsTimer <= diff)
SummonAdds();
@@ -221,23 +240,74 @@ struct TRINITY_DLL_DECL boss_razorscaleAI : public BossAI
}
}
- void ChangePosition()
+ void SummonAdds()
{
- /* Malfunctioning, Razorscale is flying around randomly, attacking players from hundreds of yards away.
- uint8 random = urand(0,3);
- m_creature->GetMotionMaster()->MovePoint(0, MovementLocations[random][0], MovementLocations[random][1], MovementLocations[random][2]); */
+ // TODO: Adds will come in waves from mole machines. One mole can spawn a Dark Rune Watcher
+ // with 1-2 Guardians, or a lone Sentinel. Up to 4 mole machines can spawn adds at any given time.
+ uint8 random = urand(1,4);
+ for (uint8 i = 0; i < random; ++i)
+ {
+ Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true);
+ float x = std::max(500.0f, std::min(650.0f, pTarget->GetPositionX() + irand(-20,20))); // Safe range is between 500 and 650
+ float y = std::max(-235.0f, std::min(-145.0f, pTarget->GetPositionY() + irand(-20,20))); // Safe range is between -235 and -145
+ float z = m_creature->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT); // Ground level
+ // TODO: Spawn drillers, then spawn adds 5 seconds later
+ if (Creature *pAdd = m_creature->SummonCreature(NPC_DARK_RUNE_SENTINEL, x, y, z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
+ pAdd->AI()->AttackStart(pTarget);
+ }
+ SummonAddsTimer = 45000;
}
- void SummonAdds()
+ void FlyPhase(uint8 Phase, const uint32 diff)
{
- for (uint32 i = 0; i < 4; ++i)
+ const float x = 587.54;
+ const float y = -174.92;
+ const float GroundLevel = m_creature->GetBaseMap()->GetHeight(x, y, MAX_HEIGHT);
+ const float FlightHeight = GroundLevel + 4.0f; // TODO: Fly out of range of attacks (442 is sufficient height for this), minus ~(10*number of harpoon gun chains attached to Razorscale)
+
+ if (Phase == 1) // Always flying during Phase 1
+ IsFlying = true;
+
+ m_creature->SetFlying(IsFlying);
+ m_creature->SendMovementFlagUpdate();
+
+ if (Phase == 1) // Flying Phase
{
- uint8 random = urand(0,3);
- if (Creature *pAdd = m_creature->SummonCreature(CREATURE_ADDS, SpawnLocations[random][0], SpawnLocations[random][1], SpawnLocations[random][2], 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
- if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true))
- pAdd->AI()->AttackStart(pTarget);
+ if (m_creature->GetPositionZ() == FlightHeight) // Correct height, stop moving
+ m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+ else // Incorrect height
+ {
+ m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+ m_creature->GetMotionMaster()->MovePoint(0, x, y, FlightHeight);
+ }
+ }
+ else // Ground Phases
+ {
+ const float CurrentGroundLevel = m_creature->GetBaseMap()->GetHeight(m_creature->GetPositionX(), m_creature->GetPositionY(), MAX_HEIGHT);
+ //if (StunTimer == 30000) // Only fly around if not stunned.
+ //{
+ m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+ if (IsFlying && m_creature->GetPositionZ() > CurrentGroundLevel) // Fly towards the ground
+ m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), CurrentGroundLevel);
+ else
+ IsFlying = false; // Landed, no longer flying
+ //}
+
+ //if (!IsFlying &&Phase == 2 && CastSpellsTimer == 0 && StunTimer >= diff) // No longer flying, non-permanent ground phase, and not casting spells
+ //{
+ // TODO: Add stun here. 30 second stun after Razorscale is grounded by harpoon guns
+ //StunTimer -= diff;
+ //}
+ //else if (StunTimer != 30000 && (StunTimer < 0 || Phase == 3)) // Stun is active, and needs to end. Note: Stun breaks instantly if Phase 3 starts
+ //{
+ // TODO: Remove stun here.
+ //DoCast(SPELL_WINGBUFFET); // "Used in the beginning of the phase."
+ //WingBuffetTimer = urand(7000,14000);
+ //StunTimer = 30000; // Reinitialize the stun timer
+ //if (Phase == 2) // Non-permanent ground phase
+ // CastSpellsTimer = 5000; // Five seconds of casting before returning to Phase 1
+ //}
}
- SummonAddsTimer = 45000;
}
};