diff options
Diffstat (limited to 'src')
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) |