aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bindings/scripts/scripts/northrend/naxxramas/boss_four_horsemen.cpp235
-rw-r--r--src/bindings/scripts/scripts/northrend/naxxramas/instance_naxxramas.cpp17
-rw-r--r--src/bindings/scripts/scripts/northrend/naxxramas/naxxramas.h6
-rw-r--r--src/game/Unit.cpp6
4 files changed, 245 insertions, 19 deletions
diff --git a/src/bindings/scripts/scripts/northrend/naxxramas/boss_four_horsemen.cpp b/src/bindings/scripts/scripts/northrend/naxxramas/boss_four_horsemen.cpp
index a254bcfddb4..9ad9551adc0 100644
--- a/src/bindings/scripts/scripts/northrend/naxxramas/boss_four_horsemen.cpp
+++ b/src/bindings/scripts/scripts/northrend/naxxramas/boss_four_horsemen.cpp
@@ -33,6 +33,26 @@ enum Events
EVENT_BERSERK,
};
+const Position WaypointPositions[12] =
+{
+ // Thane waypoints
+ {2542.3, -2984.1, 241.49, 5.362},
+ {2547.6, -2999.4, 241.34, 5.049},
+ {2542.9, -3015.0, 241.35, 4.654},
+ // Lady waypoints
+ {2498.3, -2961.8, 241.28, 3.267},
+ {2487.7, -2959.2, 241.28, 2.890},
+ {2469.4, -2947.6, 241.28, 2.576},
+ // Baron waypoints
+ {2553.8, -2968.4, 241.33, 5.757},
+ {2564.3, -2972.5, 241.33, 5.890},
+ {2583.9, -2971.67, 241.35, 0.008},
+ // Sir waypoints
+ {2534.5, -2921.7, 241.53, 1.363},
+ {2523.5, -2902.8, 241.28, 2.095},
+ {2517.8, -2896.6, 241.28, 2.315},
+};
+
const uint32 MOB_HORSEMEN[] = {16064, 16065, 30549, 16063};
const uint32 SPELL_MARK[] = {28832, 28833, 28834, 28835};
#define SPELL_PRIMARY(i) HEROIC(SPELL_PRIMARY_N[i],SPELL_PRIMARY_H[i])
@@ -68,7 +88,148 @@ struct TRINITY_DLL_DECL boss_four_horsemenAI : public BossAI
}
Horsemen id;
+ Unit *eventStarter;
+ uint8 nextWP;
+ uint32 punishTimer;
bool caster;
+ bool nextMovementStarted;
+ bool movementCompleted;
+ bool movementStarted;
+ bool encounterActionAttack;
+ bool encounterActionReset;
+ bool doDelayPunish;
+
+ void Reset()
+ {
+ if (!encounterActionReset)
+ DoEncounterAction(NULL, false, true, false);
+
+ me->SetReactState(REACT_AGGRESSIVE);
+ eventStarter = NULL;
+ nextWP = 0;
+ punishTimer = 2000;
+ nextMovementStarted = false;
+ movementCompleted = false;
+ movementStarted = false;
+ encounterActionAttack = false;
+ encounterActionReset = false;
+ doDelayPunish = false;
+ _Reset();
+ }
+
+ bool DoEncounterAction(Unit *who, bool attack, bool reset, bool checkAllDead)
+ {
+ if (!instance)
+ return false;
+
+ Creature *Thane = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_THANE)));
+ Creature *Lady = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_LADY)));
+ Creature *Baron = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_BARON)));
+ Creature *Sir = CAST_CRE(Unit::GetUnit(*me, instance->GetData64(DATA_SIR)));
+
+ if (Thane && Lady && Baron && Sir)
+ {
+ if (attack && who)
+ {
+ CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionAttack = true;
+ CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionAttack = true;
+ CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionAttack = true;
+ CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionAttack = true;
+
+ CAST_AI(boss_four_horsemenAI, Thane->AI())->AttackStart(who);
+ CAST_AI(boss_four_horsemenAI, Lady->AI())->AttackStart(who);
+ CAST_AI(boss_four_horsemenAI, Baron->AI())->AttackStart(who);
+ CAST_AI(boss_four_horsemenAI, Sir->AI())->AttackStart(who);
+ }
+
+ if (reset)
+ {
+ if (instance->GetBossState(BOSS_HORSEMEN) != NOT_STARTED)
+ {
+ if (!Thane->isAlive())
+ Thane->Respawn();
+
+ if (!Lady->isAlive())
+ Lady->Respawn();
+
+ if (!Baron->isAlive())
+ Baron->Respawn();
+
+ if (!Sir->isAlive())
+ Sir->Respawn();
+
+ CAST_AI(boss_four_horsemenAI, Thane->AI())->encounterActionReset = true;
+ CAST_AI(boss_four_horsemenAI, Lady->AI())->encounterActionReset = true;
+ CAST_AI(boss_four_horsemenAI, Baron->AI())->encounterActionReset = true;
+ CAST_AI(boss_four_horsemenAI, Sir->AI())->encounterActionReset = true;
+
+ CAST_AI(boss_four_horsemenAI, Thane->AI())->EnterEvadeMode();
+ CAST_AI(boss_four_horsemenAI, Lady->AI())->EnterEvadeMode();
+ CAST_AI(boss_four_horsemenAI, Baron->AI())->EnterEvadeMode();
+ CAST_AI(boss_four_horsemenAI, Sir->AI())->EnterEvadeMode();
+ }
+ }
+
+ if (checkAllDead)
+ return !Thane->isAlive() && !Lady->isAlive() && !Baron->isAlive() && !Sir->isAlive();
+ }
+ return false;
+ }
+
+ void BeginFourHorsemenMovement()
+ {
+ movementStarted = true;
+ me->SetReactState(REACT_PASSIVE);
+ me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
+ me->SetSpeed(MOVE_RUN, me->GetSpeedRate(MOVE_RUN), true);
+
+ switch(id)
+ {
+ case HORSEMEN_THANE:
+ me->GetMotionMaster()->MovePoint(0, WaypointPositions[0]);
+ break;
+ case HORSEMEN_LADY:
+ me->GetMotionMaster()->MovePoint(3, WaypointPositions[3]);
+ break;
+ case HORSEMEN_BARON:
+ me->GetMotionMaster()->MovePoint(6, WaypointPositions[6]);
+ break;
+ case HORSEMEN_SIR:
+ me->GetMotionMaster()->MovePoint(9, WaypointPositions[9]);
+ break;
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (id == 2 || id == 5 || id == 8 || id == 11)
+ {
+ movementCompleted = true;
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ if (me->canAttack(eventStarter))
+ AttackStart(eventStarter);
+ else if (!UpdateVictim())
+ {
+ EnterEvadeMode();
+ return;
+ }
+
+ if (caster)
+ {
+ me->GetMotionMaster()->Clear();
+ me->GetMotionMaster()->MoveIdle();
+ }
+
+ return;
+ }
+
+ nextMovementStarted = false;
+ nextWP = id + 1;
+ }
void MoveInLineOfSight(Unit *who)
{
@@ -79,10 +240,21 @@ struct TRINITY_DLL_DECL boss_four_horsemenAI : public BossAI
void AttackStart(Unit *who)
{
- if (caster)
- AttackStartCaster(who, 20);
- else
- BossAI::AttackStart(who);
+ if (!movementCompleted && !movementStarted)
+ {
+ eventStarter = who;
+ BeginFourHorsemenMovement();
+
+ if (!encounterActionAttack)
+ DoEncounterAction(who, true, false, false);
+ }
+ else if (movementCompleted && movementStarted)
+ {
+ if (caster)
+ me->Attack(who, false);
+ else
+ BossAI::AttackStart(who);
+ }
}
void KilledUnit(Unit* victim)
@@ -98,25 +270,40 @@ struct TRINITY_DLL_DECL boss_four_horsemenAI : public BossAI
void JustDied(Unit* killer)
{
- _JustDied();
+ events.Reset();
+ summons.DespawnAll();
+ if(instance && DoEncounterAction(NULL, false, false, true))
+ {
+ instance->SetBossState(BOSS_HORSEMEN, DONE);
+ instance->SaveToDB();
+ }
+
DoScriptText(SAY_DEATH[id], me);
}
void EnterCombat(Unit *who)
{
_EnterCombat();
+
if (id == HORSEMEN_BARON)
DoScriptText(SAY_BARON_AGGRO, me);
else
DoScriptText(SAY_AGGRO[id], me);
- events.ScheduleEvent(EVENT_MARK, 15000);
- events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000);
- events.ScheduleEvent(EVENT_BERSERK, 15*100*1000);
+
+ events.ScheduleEvent(EVENT_MARK, 15000);
+ events.ScheduleEvent(EVENT_CAST, 20000+rand()%5000);
+ events.ScheduleEvent(EVENT_BERSERK, 15*100*1000);
}
void UpdateAI(const uint32 diff)
{
- if (!UpdateVictim() || !CheckInRoom())
+ if (nextWP && movementStarted && !movementCompleted && !nextMovementStarted)
+ {
+ nextMovementStarted = true;
+ me->GetMotionMaster()->MovePoint(nextWP, WaypointPositions[nextWP]);
+ }
+
+ if (!UpdateVictim() || !CheckInRoom() || !movementCompleted)
return;
events.Update(diff);
@@ -133,24 +320,42 @@ struct TRINITY_DLL_DECL boss_four_horsemenAI : public BossAI
DoScriptText(SAY_SPECIAL[id], me);
DoCastAOE(SPELL_MARK[id]);
events.ScheduleEvent(EVENT_MARK, 15000);
- return;
+ break;
case EVENT_CAST:
if (!(rand()%5))
DoScriptText(SAY_TAUNT[rand()%3][id], me);
- DoCast(SPELL_PRIMARY(id));
+
+ if (caster)
+ {
+ if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 45))
+ DoCast(pTarget, SPELL_PRIMARY(id));
+ }
+ else
+ DoCast(me->getVictim(), SPELL_PRIMARY(id));
+
events.ScheduleEvent(EVENT_CAST, 15000);
- return;
+ break;
case EVENT_BERSERK:
DoScriptText(SAY_SPECIAL[id], me);
DoCast(me, EVENT_BERSERK);
- return;
+ break;
}
}
+ if (punishTimer <= diff)
+ {
+ if (doDelayPunish)
+ {
+ DoCastAOE(SPELL_PUNISH[id], true);
+ doDelayPunish = false;
+ }
+ punishTimer = 2000;
+ } else punishTimer -= diff;
+
if (!caster)
DoMeleeAttackIfReady();
- else if (!DoSpellAttackIfReady(SPELL_SECONDARY(id)))
- DoCastAOE(SPELL_PUNISH[id]);
+ else if ((!DoSpellAttackIfReady(SPELL_SECONDARY(id)) || !me->IsWithinLOSInMap(me->getVictim())) && movementCompleted && !doDelayPunish)
+ doDelayPunish = true;
}
};
diff --git a/src/bindings/scripts/scripts/northrend/naxxramas/instance_naxxramas.cpp b/src/bindings/scripts/scripts/northrend/naxxramas/instance_naxxramas.cpp
index 7f13e172664..d25f03eb5ab 100644
--- a/src/bindings/scripts/scripts/northrend/naxxramas/instance_naxxramas.cpp
+++ b/src/bindings/scripts/scripts/northrend/naxxramas/instance_naxxramas.cpp
@@ -110,6 +110,11 @@ struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
Creature* Sapphiron;
uint32 HorsemenNum;
uint64 uiFaerlina;
+ uint64 uiThane;
+ uint64 uiLady;
+ uint64 uiBaron;
+ uint64 uiSir;
+
void OnCreatureCreate(Creature* pCreature, bool add)
{
@@ -117,6 +122,10 @@ struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
{
case 15989: Sapphiron = add ? pCreature : NULL; return;
case 15953: uiFaerlina = pCreature->GetGUID(); return;
+ case 16064: uiThane = pCreature->GetGUID(); return;
+ case 16065: uiLady = pCreature->GetGUID(); return;
+ case 30549: uiBaron = pCreature->GetGUID(); return;
+ case 16063: uiSir = pCreature->GetGUID(); return;
}
AddMinion(pCreature, add);
@@ -163,6 +172,14 @@ struct TRINITY_DLL_DECL instance_naxxramas : public InstanceData
{
if (id == DATA_FAERLINA)
return uiFaerlina;
+ if (id == DATA_THANE)
+ return uiThane;
+ if (id == DATA_LADY)
+ return uiLady;
+ if (id == DATA_BARON)
+ return uiBaron;
+ if (id == DATA_SIR)
+ return uiSir;
return 0;
}
diff --git a/src/bindings/scripts/scripts/northrend/naxxramas/naxxramas.h b/src/bindings/scripts/scripts/northrend/naxxramas/naxxramas.h
index 99f54da435e..6f4dcae41a7 100644
--- a/src/bindings/scripts/scripts/northrend/naxxramas/naxxramas.h
+++ b/src/bindings/scripts/scripts/northrend/naxxramas/naxxramas.h
@@ -44,7 +44,11 @@ enum Data
DATA_HEIGAN_ERUPT,
DATA_GOTHIK_GATE,
DATA_SAPPHIRON_BIRTH,
- DATA_FAERLINA
+ DATA_FAERLINA,
+ DATA_THANE,
+ DATA_LADY,
+ DATA_BARON,
+ DATA_SIR
};
#define GO_BIRTH 181356
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index f8d71b8db66..3a87804a48b 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -10991,9 +10991,9 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
if (GetTypeId() != TYPEID_PLAYER)
{
// Set home position at place of engaging combat for escorted creatures
- if (( IsAIEnabled && ((Creature*)this)->AI()->IsEscorted() ) ||
- GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE ||
- GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
+ if ((IsAIEnabled && ((Creature*)this)->AI()->IsEscorted()) &&
+ (GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE ||
+ GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE))
((Creature*)this)->SetHomePosition(GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation());
if (enemy)