aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRat <none@none>2009-08-24 00:24:22 +0200
committerRat <none@none>2009-08-24 00:24:22 +0200
commit0c515c3119180b7c66bf93d32b94883e6ab9a6bc (patch)
treee446d146e10448a68681879e233f446f1d4795a3 /src
parent6ce460e04db03bbe7fd5f50b7d4d025ab0fb5baf (diff)
*rewrite The Lurker Below boss script (again)
--HG-- branch : trunk
Diffstat (limited to 'src')
-rw-r--r--src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp430
1 files changed, 181 insertions, 249 deletions
diff --git a/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp b/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp
index 30911809240..7758e0fcedb 100644
--- a/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp
+++ b/src/bindings/scripts/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp
@@ -37,7 +37,7 @@ EndScriptData */
#define SPELL_EMERGE 20568
#define SPELL_SCALDINGWATER 37284
-#define EMOTE_SPOUT "takes a deep breath."
+#define EMOTE_SPOUT "The Lurker Below takes a deep breath."
#define SPOUT_DIST 100
@@ -65,13 +65,6 @@ float AddPos[9][3] =
{42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z
};
-enum RotationType
-{
- NOROTATE = 0,
- CLOCKWISE = 1,
- COUNTERCLOCKWISE = 2,
-};
-
struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI
{
boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(m_creature)
@@ -91,38 +84,35 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI
bool Spawned;
bool Submerged;
-
- double SpoutAngle;
-
- uint8 RotType;
-
+ bool InRange;
uint32 RotTimer;
uint32 SpoutAnimTimer;
uint32 WaterboltTimer;
uint32 SpoutTimer;
- uint32 WhirlTimer;//after avery spout
+ uint32 WhirlTimer;
uint32 PhaseTimer;
uint32 GeyserTimer;
+ uint32 CheckTimer;
void Reset()
{
m_creature->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING + MOVEMENTFLAG_LEVITATING);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->SetCorpseDelay(1000*60*60);
-
- RotType = NOROTATE;
+ m_creature->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
- SpoutAngle = 0;
SpoutAnimTimer = 1000;
- RotTimer = 20000;
- WaterboltTimer = 3000;
- SpoutTimer = 15000;
+ RotTimer = 0;
+ WaterboltTimer = 15000;//give time to get in range when fight starts
+ SpoutTimer = 45000;
WhirlTimer = 18000;//after avery spout
PhaseTimer = 120000;
GeyserTimer = rand()%5000 + 15000;
+ CheckTimer = 15000;//give time to get in range when fight starts
Submerged = false;
Spawned = false;
+ InRange = false;
Summons.DespawnAll();
@@ -139,245 +129,187 @@ struct TRINITY_DLL_DECL boss_the_lurker_belowAI : public Scripted_NoMovementAI
}*/
}
- void MoveInLineOfSight(Unit *who)
- {
- if (!who || m_creature->getVictim())
- return;
+ void JustDied(Unit* Killer)
+ {
+ if (pInstance)
+ pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE);
- if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who))
- {
- float attackRadius = m_creature->GetAttackDistance(who);
- if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who))
- AttackStart(who);
- }
+ Summons.DespawnAll();
}
- void EnterCombat(Unit *who)
- {
- if (pInstance)
- pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS);
-
- if (!who || m_creature->getVictim())
- return;
-
- if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who))
- {
- float attackRadius = m_creature->GetAttackDistance(who);
- if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who))
- AttackStart(who);
- }
- }
+ void UpdateAI(const uint32 diff)
+ {
+ //MAP 548
+ //Check if players in water and if in water cast spell
+ /*Map* pMap = m_creature->GetMap();
+ if (pMap->IsDungeon() && pInstance && pInstance->GetData(DATA_THELURKERBELOWEVENT) == IN_PROGRESS)
+ {
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
- void JustDied(Unit* Killer)
- {
- if (pInstance)
- pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE);
+ if (PlayerList.isEmpty())
+ return;
- Summons.DespawnAll();
- }
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (i->getSource()->isAlive() && i->getSource()->IsInWater() && !i->getSource()->HasAura(SPELL_SCALDINGWATER))
+ i->getSource()->CastSpell(i->getSource(), SPELL_SCALDINGWATER, true);
+ else if (!i->getSource()->IsInWater())
+ i->getSource()->RemoveAurasDueToSpell(SPELL_SCALDINGWATER);
+ }
+ }*/
- void Rotate(const uint32 diff)
- {
- bool Spout = false;
- switch (RotType)
- {
- case NOROTATE:
- return;
- case CLOCKWISE://20secs for 360turn
- //no target if rotating!
- m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
- SpoutAngle += (double)diff/20000*(double)M_PI*2;
- if (SpoutAngle >= M_PI*2)SpoutAngle = 0;
- m_creature->SetOrientation(SpoutAngle);
- m_creature->StopMoving();
- Spout = true;
- break;
- case COUNTERCLOCKWISE://20secs for 360turn
- //no target if rotating!
- m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
- SpoutAngle -= (double)diff/20000*(double)M_PI*2;
- if (SpoutAngle <= 0)SpoutAngle = M_PI*2;
- m_creature->SetOrientation(SpoutAngle);
- m_creature->StopMoving();
- Spout = true;
- break;
- }
-
- if (!Spout)
- return;
-
- if (RotTimer<diff)//end rotate
- {
- RotType = NOROTATE;//set norotate state
- RotTimer=20000;
- m_creature->InterruptNonMeleeSpells(false);
- WhirlTimer = 4000; //whirl directly after spout ends
- return;
- }else RotTimer-=diff;
-
- if (SpoutAnimTimer<diff)
- {
- DoCast(m_creature,SPELL_SPOUT_ANIM,true);
- SpoutAnimTimer = 1000;
- }else SpoutAnimTimer-=diff;
-
- Map* pMap = m_creature->GetMap();
- if (pMap->IsDungeon() && pInstance && pInstance->GetData(DATA_THELURKERBELOWEVENT) == IN_PROGRESS)
- {
- Map::PlayerList const &PlayerList = pMap->GetPlayers();
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- Player *target = i->getSource();
- if (target && target->isAlive() && m_creature->HasInArc((double)diff/20000*(double)M_PI*2,target) && m_creature->IsWithinDist(target, SPOUT_DIST) && !target->IsInWater())
- DoCast(target,SPELL_SPOUT,true);//only knock back palyers in arc, in 100yards, not in water
- }
- }
- }
+ //Rotate(diff);//always check rotate things
- void StartRotate(Unit* victim)
- {
- switch (rand()%2)
- {
- case 0: RotType = CLOCKWISE; break;
- case 1: RotType = COUNTERCLOCKWISE; break;
- }
- RotTimer=20000;
+ //Return since we have no target
- if (victim)
- SpoutAngle = m_creature->GetAngle(victim);
+ if(m_creature->getThreatManager().getThreatList().empty())//check if should evade
+ {
+ if(m_creature->isInCombat())
+ EnterEvadeMode();
+ return;
+ }
+ if (!Submerged)
+ {
+ if (PhaseTimer < diff)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCast(m_creature,SPELL_SUBMERGE);
+ PhaseTimer = 60000;//60secs submerged
+ Submerged = true;
+ }else PhaseTimer-=diff;
+
+ if (SpoutTimer < diff)
+ {
+ m_creature->MonsterTextEmote(EMOTE_SPOUT,0,true);
+ if(rand()%2)
+ m_creature->StartAutoRotate(CREATURE_ROTATE_LEFT,20000);
+ else
+ m_creature->StartAutoRotate(CREATURE_ROTATE_RIGHT,20000);
+ SpoutTimer = 45000;
+ WhirlTimer = 20000;//whirl directly after spout
+ RotTimer = 20000;
+ return;
+ }else SpoutTimer -= diff;
+
+ //Whirl directly after a Spout and at random times
+ if (WhirlTimer < diff)
+ {
+ WhirlTimer = 18000;
+ DoCast(m_creature,SPELL_WHIRL);
+ }else WhirlTimer -= diff;
+
+ if(CheckTimer < diff)//check if there are players in melee range
+ {
+ InRange = false;
+ Map* pMap = m_creature->GetMap();
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+ if (!PlayerList.isEmpty())
+ {
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if(m_creature->IsWithinMeleeRange(i->getSource()))
+ InRange = true;
+ }
+ }
+ CheckTimer = 2000;
+ }else CheckTimer -= diff;
+
+ if(RotTimer)
+ {
+ Map* pMap = m_creature->GetMap();
+ if (pMap->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (i->getSource() && i->getSource()->isAlive() && m_creature->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && m_creature->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater())
+ DoCast(i->getSource(),SPELL_SPOUT,true);//only knock back palyers in arc, in 100yards, not in water
+ }
+ }
+
+ if(SpoutAnimTimer < diff)
+ {
+ DoCast(m_creature,SPELL_SPOUT_ANIM,true);
+ SpoutAnimTimer = 1000;
+ }else SpoutAnimTimer -= diff;
+
+ if(RotTimer < diff)
+ {
+ RotTimer = 0;
+ }else RotTimer -= diff;
+ return;
+ }
+
+ if (GeyserTimer < diff)
+ {
+ Unit* target = SelectUnit(SELECT_TARGET_RANDOM,1);
+ if (!target && m_creature->getVictim())
+ target = m_creature->getVictim();
+ if (target)
+ DoCast(target,SPELL_GEYSER,true);
+ GeyserTimer = rand()%5000 + 15000;
+ }else GeyserTimer -= diff;
+
+ if(!InRange)//if on players in melee range cast Waterbolt
+ {
+ if (WaterboltTimer < diff)
+ {
+ Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0);
+ if (!target && m_creature->getVictim())
+ target = m_creature->getVictim();
+ if (target)
+ DoCast(target,SPELL_WATERBOLT,true);
+ WaterboltTimer = 3000;
+ }else WaterboltTimer -= diff;
+ }
+
+ if (!UpdateVictim())
+ return;
- m_creature->MonsterTextEmote(EMOTE_SPOUT,0,true);
- //DoCast(m_creature,SPELL_SPOUT_BREATH);//take breath anim
- }
+ DoMeleeAttackIfReady();
- void UpdateAI(const uint32 diff)
- {
- //Return since we have no target
- if (!UpdateVictim() /*|| !m_creature->getVictim()*/)//rotate resets target
- return;
-
- //Check if players in water and if in water cast spell
- Map* pMap = m_creature->GetMap();
- if (pMap->IsDungeon() && pInstance && pInstance->GetData(DATA_THELURKERBELOWEVENT) == IN_PROGRESS)
- {
- Map::PlayerList const &PlayerList = pMap->GetPlayers();
-
- if (PlayerList.isEmpty())
- return;
-
- for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
- {
- if (i->getSource()->isAlive() && i->getSource()->IsInWater() && !i->getSource()->HasAura(SPELL_SCALDINGWATER))
- i->getSource()->CastSpell(i->getSource(), SPELL_SCALDINGWATER, true);
- else if (!i->getSource()->IsInWater())
- i->getSource()->RemoveAurasDueToSpell(SPELL_SCALDINGWATER);
- }
- }
-
- Rotate(diff);//always check rotate things
- if (!Submerged)
- {
- if (PhaseTimer < diff)
- {
- m_creature->InterruptNonMeleeSpells(false);
- DoCast(m_creature,SPELL_SUBMERGE);
- PhaseTimer = 60000;//60secs submerged
- Submerged = true;
- }else PhaseTimer-=diff;
- }
-
- if (!Submerged && RotType == NOROTATE)//is not spouting and not submerged
- {
- if (SpoutTimer < diff)
- {
- if (m_creature->getVictim() && RotType == NOROTATE)
- StartRotate(m_creature->getVictim());//start spout and random rotate
-
- SpoutTimer= 35000;
- return;
- }else SpoutTimer -= diff;
-
- //Whirl directly after a Spout and at random times
- if (WhirlTimer < diff)
- {
- WhirlTimer = rand()%5000 + 15000;
- DoCast(m_creature,SPELL_WHIRL);
- WaterboltTimer += 5000;//add 5secs to waterbolt timer, to add some time to run back to boss
- }else WhirlTimer -= diff;
-
- if (GeyserTimer < diff)
- {
- Unit* target = NULL;
- target = SelectUnit(SELECT_TARGET_RANDOM,1);
-
- if (target)
- DoCast(target,SPELL_GEYSER,true);
- else
- target = SelectUnit(SELECT_TARGET_RANDOM,0);
- if (target)
- DoCast(target,SPELL_GEYSER,true);
-
- GeyserTimer = rand()%5000 + 15000;
- }else GeyserTimer -= diff;
-
- if (WaterboltTimer < diff)
- {
- Unit* target = SelectTarget(SELECT_TARGET_NEAREST,0,14,true);
- if (!target)
- {
- target = SelectUnit(SELECT_TARGET_RANDOM,0);
- if (target)
- DoCast(target,SPELL_WATERBOLT);
- }
- WaterboltTimer = 3000;
- }else WaterboltTimer -= diff;
-
- if (!UpdateVictim())
+ }else//submerged
+ {
+ if (PhaseTimer < diff)
+ {
+ Submerged = false;
+ m_creature->InterruptNonMeleeSpells(false);//shouldn't be any
+ m_creature->RemoveAllAuras();
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ m_creature->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED);
+ DoCast(m_creature,SPELL_EMERGE,true);
+ Spawned = false;
+ SpoutTimer = 3000; // directly cast Spout after emerging!
+ PhaseTimer = 120000;
return;
+ }else PhaseTimer-=diff;
- DoMeleeAttackIfReady();
-
- }else if (!Submerged)
- return;
- else if (Submerged)//phase 2, submerged
- {
- if (PhaseTimer < diff)
- {
- Submerged = false;
- m_creature->InterruptNonMeleeSpells(false);//shouldn't be any
- m_creature->RemoveAllAuras();
- m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- m_creature->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED);
- m_creature->RemoveFlag(UNIT_FIELD_BYTES_1,9);
- DoCast(m_creature,SPELL_EMERGE);
- Spawned = false;
- SpoutTimer = 4000; // directly cast Spout after emerging!
- WhirlTimer = 26000;
- PhaseTimer = 120000;
- return;
- }else PhaseTimer-=diff;
-
- if (!m_creature->isInCombat())
- DoZoneInCombat();
-
- if (!Spawned)
- {
- m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- //spawn adds
- for (uint8 i = 0; i < 9; ++i)
- {
- Creature* Summoned;
- if (i < 7)
- Summoned = m_creature->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
- else Summoned = m_creature->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
-
- if (Summoned)
- Summons.Summon(Summoned);
- Spawned = true;
- }
- }
- }
- }
+ if(m_creature->getThreatManager().getThreatList().empty())//check if should evade
+ {
+ EnterEvadeMode();
+ return;
+ }
+ if (!m_creature->isInCombat())
+ DoZoneInCombat();
+
+ if (!Spawned)
+ {
+ m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2);
+ //spawn adds
+ for (uint8 i = 0; i < 9; ++i)
+ {
+ Creature* Summoned;
+ if (i < 6)
+ Summoned = m_creature->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ else Summoned = m_creature->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ if (Summoned)
+ Summons.Summon(Summoned);
+ }
+ Spawned = true;
+ }
+ }
+ }
};
CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature)
@@ -427,7 +359,7 @@ struct TRINITY_DLL_DECL mob_coilfang_ambusherAI : public Scripted_NoMovementAI
{
if (!who || m_creature->getVictim()) return;
- if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who))
+ if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(m_creature) && m_creature->IsHostileTo(who) && m_creature->IsWithinDistInMap(who, 45))
{
AttackStart(who);
}