Merge branch 'Treeston-3.3.5-heigan' into 3.3.5

This commit is contained in:
Shauren
2015-10-10 11:54:53 +02:00
3 changed files with 87 additions and 81 deletions

View File

@@ -0,0 +1,7 @@
--
UPDATE `creature_text` SET `probability`=20 WHERE `entry`=15936 AND `groupid`=1;
DELETE FROM `creature_text` WHERE `entry`=15936 AND `groupid` IN (4,5);
INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
(15936,4,0,"%s teleports and begins to channel a spell!",41,100,32332,3,"Heigan EMOTE_DANCE"),
(15936,5,0,"%s rushes to attack once more!",41,100,32333,3,"Heigan EMOTE_DANCE_END");

View File

@@ -21,36 +21,42 @@
#include "naxxramas.h"
#include "Player.h"
enum Heigan
enum Spells
{
SPELL_DECREPIT_FEVER = 29998, // 25-man: 55011
SPELL_SPELL_DISRUPTION = 29310,
SPELL_PLAGUE_CLOUD = 29350,
SPELL_DECREPIT_FEVER = 29998, // 25-man: 55011
SPELL_SPELL_DISRUPTION = 29310,
SPELL_PLAGUE_CLOUD = 29350,
SPELL_TELEPORT_SELF = 30211,
};
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_TAUNT = 2,
SAY_DEATH = 3
enum Yells
{
SAY_AGGRO = 0,
SAY_SLAY = 1,
SAY_TAUNT = 2,
SAY_DEATH = 3,
EMOTE_DANCE = 4,
EMOTE_DANCE_END = 5,
};
enum Events
{
EVENT_NONE,
EVENT_DISRUPT,
EVENT_DISRUPT = 1,
EVENT_FEVER,
EVENT_ERUPT,
EVENT_PHASE,
EVENT_DANCE,
EVENT_DANCE_END
};
enum Phases
{
PHASE_FIGHT = 1,
PHASE_DANCE,
PHASE_DANCE
};
enum Misc
{
ACTION_SAFETY_DANCE_FAIL = 1,
DATA_SAFETY_DANCE = 19962139
};
@@ -66,39 +72,25 @@ public:
struct boss_heiganAI : public BossAI
{
boss_heiganAI(Creature* creature) : BossAI(creature, BOSS_HEIGAN)
{
eruptSection = 0;
eruptDirection = false;
safetyDance = false;
phase = PHASE_FIGHT;
}
boss_heiganAI(Creature* creature) : BossAI(creature, BOSS_HEIGAN), eruptSection(0), eruptDirection(false), safetyDance(false) { }
uint32 eruptSection;
bool eruptDirection;
bool safetyDance;
Phases phase;
void Reset() override
{
me->SetReactState(REACT_AGGRESSIVE);
_Reset();
}
void KilledUnit(Unit* who) override
{
if (!(rand32() % 5))
Talk(SAY_SLAY);
Talk(SAY_SLAY);
if (who->GetTypeId() == TYPEID_PLAYER)
safetyDance = false;
}
void SetData(uint32 id, uint32 data) override
{
if (id == DATA_SAFETY_DANCE)
safetyDance = data ? true : false;
}
uint32 GetData(uint32 type) const override
{
if (type == DATA_SAFETY_DANCE)
return safetyDance ? 1 : 0;
return 0;
return (type == DATA_SAFETY_DANCE && safetyDance) ? 1u : 0u;
}
void JustDied(Unit* /*killer*/) override
@@ -111,35 +103,14 @@ public:
{
_EnterCombat();
Talk(SAY_AGGRO);
EnterPhase(PHASE_FIGHT);
safetyDance = true;
}
void EnterPhase(Phases newPhase)
{
phase = newPhase;
events.Reset();
eruptSection = 3;
if (phase == PHASE_FIGHT)
{
events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000));
events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000));
events.ScheduleEvent(EVENT_PHASE, 90000);
events.ScheduleEvent(EVENT_ERUPT, 15000);
me->GetMotionMaster()->MoveChase(me->GetVictim());
}
else
{
float x, y, z, o;
me->GetHomePosition(x, y, z, o);
me->NearTeleportTo(x, y, z, o - (float(M_PI) / 2));
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->SetTarget(ObjectGuid::Empty);
DoCastAOE(SPELL_PLAGUE_CLOUD);
events.ScheduleEvent(EVENT_PHASE, 45000);
events.ScheduleEvent(EVENT_ERUPT, 8000);
}
events.ScheduleEvent(EVENT_DISRUPT, urand(15 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_FEVER, urand(10 * IN_MILLISECONDS, 20 * IN_MILLISECONDS), 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_DANCE, 90 * IN_MILLISECONDS, 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_ERUPT, 15 * IN_MILLISECONDS, 0, PHASE_FIGHT);
safetyDance = true;
}
void UpdateAI(uint32 diff) override
@@ -155,15 +126,36 @@ public:
{
case EVENT_DISRUPT:
DoCastAOE(SPELL_SPELL_DISRUPTION);
events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000));
events.ScheduleEvent(EVENT_DISRUPT, 11 * IN_MILLISECONDS);
break;
case EVENT_FEVER:
DoCastAOE(SPELL_DECREPIT_FEVER);
events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000));
events.ScheduleEvent(EVENT_FEVER, urand(20 * IN_MILLISECONDS, 25 * IN_MILLISECONDS));
break;
case EVENT_PHASE:
/// @todo Add missing texts for both phase switches
EnterPhase(phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT);
case EVENT_DANCE:
events.SetPhase(PHASE_DANCE);
Talk(SAY_TAUNT);
Talk(EMOTE_DANCE);
eruptSection = 3;
me->SetReactState(REACT_PASSIVE);
me->AttackStop();
me->StopMoving();
DoCast(SPELL_TELEPORT_SELF);
DoCastAOE(SPELL_PLAGUE_CLOUD);
events.ScheduleEvent(EVENT_DANCE_END, 45 * IN_MILLISECONDS, 0, PHASE_DANCE);
events.ScheduleEvent(EVENT_ERUPT, 10 * IN_MILLISECONDS);
break;
case EVENT_DANCE_END:
events.SetPhase(PHASE_FIGHT);
Talk(EMOTE_DANCE_END);
eruptSection = 3;
events.ScheduleEvent(EVENT_DISRUPT, urand(10, 25) * IN_MILLISECONDS, 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_FEVER, urand(15, 20) * IN_MILLISECONDS, 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_DANCE, 90 * IN_MILLISECONDS, 0, PHASE_FIGHT);
events.ScheduleEvent(EVENT_ERUPT, 15 * IN_MILLISECONDS, 0, PHASE_FIGHT);
me->CastStop();
me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat();
break;
case EVENT_ERUPT:
instance->SetData(DATA_HEIGAN_ERUPT, eruptSection);
@@ -176,13 +168,22 @@ public:
eruptDirection ? ++eruptSection : --eruptSection;
events.ScheduleEvent(EVENT_ERUPT, phase == PHASE_FIGHT ? 10000 : 3000);
if (events.IsInPhase(PHASE_DANCE))
events.ScheduleEvent(EVENT_ERUPT, 3 * IN_MILLISECONDS, 0, PHASE_DANCE);
else
events.ScheduleEvent(EVENT_ERUPT, 10 * IN_MILLISECONDS, 0, PHASE_FIGHT);
break;
}
}
DoMeleeAttackIfReady();
}
private:
uint32 eruptSection;
bool eruptDirection;
bool safetyDance; // is achievement still possible? (= no player deaths yet)
};
};
@@ -205,7 +206,7 @@ class spell_heigan_eruption : public SpellScriptLoader
if (GetHitDamage() >= int32(GetHitPlayer()->GetHealth()))
if (InstanceScript* instance = caster->GetInstanceScript())
if (Creature* Heigan = ObjectAccessor::GetCreature(*caster, instance->GetGuidData(DATA_HEIGAN)))
Heigan->AI()->SetData(DATA_SAFETY_DANCE, 0);
Heigan->AI()->KilledUnit(GetHitPlayer());
}
void Register() override
@@ -223,9 +224,7 @@ class spell_heigan_eruption : public SpellScriptLoader
class achievement_safety_dance : public AchievementCriteriaScript
{
public:
achievement_safety_dance() : AchievementCriteriaScript("achievement_safety_dance")
{
}
achievement_safety_dance() : AchievementCriteriaScript("achievement_safety_dance") { }
bool OnCheck(Player* /*player*/, Unit* target) override
{

View File

@@ -78,12 +78,13 @@ ObjectData const objectData[] =
{ 0, 0, }
};
float const HeiganPos[2] = { 2796.0f, -3707.0f };
// from P2 teleport spell stored target
float const HeiganPos[2] = { 2793.86f, -3707.38f };
float const HeiganEruptionSlope[3] =
{
(-3685.0f - HeiganPos[1]) / (2724.0f - HeiganPos[0]),
(-3647.0f - HeiganPos[1]) / (2749.0f - HeiganPos[0]),
(-3637.0f - HeiganPos[1]) / (2771.0f - HeiganPos[0])
(-3703.303223f - HeiganPos[1]) / (2777.494141f - HeiganPos[0]), // between right center and far right
(-3696.948242f - HeiganPos[1]) / (2785.624268f - HeiganPos[0]), // between left and right halves
(-3691.880615f - HeiganPos[1]) / (2790.280029f - HeiganPos[0]) // between far left and left center
};
// 0 H x
@@ -246,7 +247,6 @@ class instance_naxxramas : public InstanceMapScript
if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287)
{
uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY());
HeiganEruptionGUID[section].erase(go->GetGUID());
return;
}
@@ -552,7 +552,7 @@ class instance_naxxramas : public InstanceMapScript
// This Function is called in CheckAchievementCriteriaMeet and CheckAchievementCriteriaMeet is called before SetBossState(bossId, DONE),
// so to check if all bosses are done the checker must exclude 1 boss, the last done, if there is at most 1 encouter in progress when is
// called this function then all bosses are done. The one boss that check is the boss that calls this function, so it is dead.
bool AreAllEncoutersDone()
bool AreAllEncountersDone()
{
uint32 numBossAlive = 0;
for (uint32 i = 0; i < EncounterCount; ++i)
@@ -589,7 +589,7 @@ class instance_naxxramas : public InstanceMapScript
case 13239: // Loatheb
case 13240: // Thaddius
case 7617: // Kel'Thuzad
if (AreAllEncoutersDone() && !playerDied)
if (AreAllEncountersDone() && !playerDied)
return true;
return false;
}