fix(scripts/Ulduar): Improve Hodir (#4703)
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1614870494129873100');
|
||||||
|
|
||||||
|
DELETE FROM `spell_target_position` WHERE `ID`=62501 AND `EffectIndex`=0;
|
||||||
|
INSERT INTO `spell_target_position` (`ID`, `EffectIndex`, `MapID`, `PositionX`, `PositionY`, `PositionZ`, `Orientation`, `VerifiedBuild`) VALUES (62501, 0, 603, 2035.95, -202.085, 432.687, 3.16408, 0);
|
||||||
|
|
||||||
|
DELETE FROM `spell_script_names` WHERE `spell_id` = 62502;
|
||||||
|
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (62501, 'spell_hodir_shatter_chest');
|
||||||
@@ -5246,6 +5246,12 @@ void SpellMgr::LoadDbcDataCorrections()
|
|||||||
spellInfo->EffectRadiusIndex[0] = 16; // 1yd
|
spellInfo->EffectRadiusIndex[0] = 16; // 1yd
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Hodir Shatter Cache
|
||||||
|
ApplySpellFix({ 62502 }, [](SpellEntry* spellInfo)
|
||||||
|
{
|
||||||
|
spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_SRC_AREA_ENTRY;
|
||||||
|
});
|
||||||
|
|
||||||
// Ulduar, General Vezax, Mark of the Faceless
|
// Ulduar, General Vezax, Mark of the Faceless
|
||||||
ApplySpellFix({ 63278 }, [](SpellEntry* spellInfo)
|
ApplySpellFix({ 63278 }, [](SpellEntry* spellInfo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ enum HodirSpellData
|
|||||||
SPELL_FLASH_FREEZE_VISUAL = 62148,
|
SPELL_FLASH_FREEZE_VISUAL = 62148,
|
||||||
SPELL_SAFE_AREA = 65705,
|
SPELL_SAFE_AREA = 65705,
|
||||||
SPELL_SAFE_AREA_TRIGGERED = 62464,
|
SPELL_SAFE_AREA_TRIGGERED = 62464,
|
||||||
|
SPELL_SHATTER_CHEST = 62501,
|
||||||
|
|
||||||
SPELL_ICICLE_BOSS_AURA = 62227,
|
SPELL_ICICLE_BOSS_AURA = 62227,
|
||||||
SPELL_ICICLE_TBBA = 63545,
|
SPELL_ICICLE_TBBA = 63545,
|
||||||
@@ -95,13 +96,7 @@ enum HodirNPCs
|
|||||||
NPC_ICICLE_UNPACKED = 33169,
|
NPC_ICICLE_UNPACKED = 33169,
|
||||||
NPC_ICICLE_PACKED = 33173,
|
NPC_ICICLE_PACKED = 33173,
|
||||||
NPC_TOASTY_FIRE = 33342,
|
NPC_TOASTY_FIRE = 33342,
|
||||||
};
|
NPC_RARE_WINTER_CACHE_TRIGGER = 88101,
|
||||||
|
|
||||||
enum HodirGOs
|
|
||||||
{
|
|
||||||
GO_HODIR_SNOWDRIFT = 194173,
|
|
||||||
// GO_HODIR_FROZEN_DOOR = 194441,
|
|
||||||
// GO_HODIR_DOOR = 194634,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HodirEvents
|
enum HodirEvents
|
||||||
@@ -113,6 +108,8 @@ enum HodirEvents
|
|||||||
EVENT_FREEZE = 4,
|
EVENT_FREEZE = 4,
|
||||||
EVENT_SMALL_ICICLES_ENABLE = 5,
|
EVENT_SMALL_ICICLES_ENABLE = 5,
|
||||||
EVENT_HARD_MODE_MISSED = 6,
|
EVENT_HARD_MODE_MISSED = 6,
|
||||||
|
EVENT_DESPAWN_CHEST = 7,
|
||||||
|
EVENT_FAIL_HM = 8,
|
||||||
|
|
||||||
EVENT_TRY_FREE_HELPER = 10,
|
EVENT_TRY_FREE_HELPER = 10,
|
||||||
EVENT_PRIEST_DISPELL_MAGIC = 11,
|
EVENT_PRIEST_DISPELL_MAGIC = 11,
|
||||||
@@ -127,18 +124,22 @@ enum HodirEvents
|
|||||||
EVENT_MAGE_MELT_ICE = 20,
|
EVENT_MAGE_MELT_ICE = 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum HodirText
|
||||||
|
{
|
||||||
|
TEXT_AGGRO = 0,
|
||||||
|
TEXT_SLAY = 1,
|
||||||
|
TEXT_FLASH_FREEZE = 2,
|
||||||
|
TEXT_STALACTITE = 3,
|
||||||
|
TEXT_DEATH = 4,
|
||||||
|
TEXT_BERSERK = 5,
|
||||||
|
TEXT_HM_MISS = 6,
|
||||||
|
TEXT_EMOTE_FREEZE = 7,
|
||||||
|
TEXT_EMOTE_BLOW = 8,
|
||||||
|
};
|
||||||
|
|
||||||
#define SPELL_FROZEN_BLOWS RAID_MODE(SPELL_FROZEN_BLOWS_10, SPELL_FROZEN_BLOWS_25)
|
#define SPELL_FROZEN_BLOWS RAID_MODE(SPELL_FROZEN_BLOWS_10, SPELL_FROZEN_BLOWS_25)
|
||||||
#define SPELL_SHAMAN_STORM_CLOUD RAID_MODE(SPELL_SHAMAN_STORM_CLOUD_10, SPELL_SHAMAN_STORM_CLOUD_25)
|
#define SPELL_SHAMAN_STORM_CLOUD RAID_MODE(SPELL_SHAMAN_STORM_CLOUD_10, SPELL_SHAMAN_STORM_CLOUD_25)
|
||||||
|
|
||||||
#define TEXT_HODIR_AGGRO "You will suffer for this trespass!"
|
|
||||||
#define TEXTEMOTE_HODIR_FROZEN_BLOWS "Hodir roars furious."
|
|
||||||
#define TEXT_HODIR_FLASH_FREEZE "Winds of the north consume you!"
|
|
||||||
#define TEXTEMOTE_HODIR_HARD_MODE_MISSED "Hodir shatters the Rare Cache of Hodir!"
|
|
||||||
#define TEXT_HODIR_SLAIN_1 "Tragic. To come so far, only to fail."
|
|
||||||
#define TEXT_HODIR_SLAIN_2 "Welcome to the endless winter."
|
|
||||||
#define TEXT_HODIR_BERSERK "Enough! This ends now!"
|
|
||||||
#define TEXT_HODIR_DEFEATED "I... I am released from his grasp... at last."
|
|
||||||
|
|
||||||
enum HodirSounds
|
enum HodirSounds
|
||||||
{
|
{
|
||||||
SOUND_HODIR_AGGRO = 15552,
|
SOUND_HODIR_AGGRO = 15552,
|
||||||
@@ -208,24 +209,26 @@ public:
|
|||||||
InstanceScript* pInstance;
|
InstanceScript* pInstance;
|
||||||
EventMap events;
|
EventMap events;
|
||||||
SummonList summons;
|
SummonList summons;
|
||||||
uint64 Helpers[8];
|
uint64 Helpers[8]{ };
|
||||||
bool berserk;
|
bool berserk{ false };
|
||||||
bool hardmode;
|
bool bAchievCheese{ true };
|
||||||
bool bAchievCheese;
|
bool bAchievGettingCold{ true };
|
||||||
bool bAchievGettingCold;
|
bool bAchievCoolestFriends{ true };
|
||||||
bool bAchievCoolestFriends;
|
uint16 addSpawnTimer{ 0 };
|
||||||
uint16 addSpawnTimer;
|
|
||||||
|
|
||||||
void Reset() override
|
void Reset() override
|
||||||
{
|
{
|
||||||
events.Reset();
|
events.Reset();
|
||||||
summons.DespawnAll();
|
summons.DespawnAll();
|
||||||
berserk = false;
|
berserk = false;
|
||||||
hardmode = true;
|
|
||||||
bAchievCheese = true;
|
bAchievCheese = true;
|
||||||
bAchievGettingCold = true;
|
bAchievGettingCold = true;
|
||||||
bAchievCoolestFriends = true;
|
bAchievCoolestFriends = true;
|
||||||
addSpawnTimer = 5000;
|
me->SetSheath(SHEATH_STATE_MELEE);
|
||||||
|
|
||||||
|
// Reset the spells cast after wipe
|
||||||
|
me->RemoveAllAuras();
|
||||||
|
pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_BITING_COLD_PLAYER_AURA);
|
||||||
|
|
||||||
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
|
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
|
||||||
{
|
{
|
||||||
@@ -236,26 +239,27 @@ public:
|
|||||||
{
|
{
|
||||||
go->SetGoState(GO_STATE_ACTIVE);
|
go->SetGoState(GO_STATE_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
|
||||||
|
{
|
||||||
|
pInstance->SetData(TYPE_SPAWN_HODIR_CACHE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset helpers
|
||||||
|
if (!summons.size())
|
||||||
|
SpawnHelpers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EnterCombat(Unit* /*pWho*/) override
|
void EnterCombat(Unit* /*pWho*/) override
|
||||||
{
|
{
|
||||||
if (summons.size() != uint32(RAID_MODE(8, 16)))
|
|
||||||
{
|
|
||||||
EnterEvadeMode();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
me->setActive(true);
|
|
||||||
me->CastSpell(me, SPELL_BITING_COLD_BOSS_AURA, true);
|
me->CastSpell(me, SPELL_BITING_COLD_BOSS_AURA, true);
|
||||||
SmallIcicles(true);
|
SmallIcicles(true);
|
||||||
events.Reset();
|
events.Reset();
|
||||||
events.RescheduleEvent(EVENT_FLASH_FREEZE, 60000);
|
events.ScheduleEvent(EVENT_FLASH_FREEZE, urand(48000, 49000));
|
||||||
events.RescheduleEvent(EVENT_FREEZE, 15000);
|
events.ScheduleEvent(EVENT_FREEZE, urand(17000,20000));
|
||||||
events.RescheduleEvent(EVENT_BERSERK, 480000);
|
events.ScheduleEvent(EVENT_BERSERK, 480000);
|
||||||
events.RescheduleEvent(EVENT_HARD_MODE_MISSED, 180000);
|
events.ScheduleEvent(EVENT_HARD_MODE_MISSED, 180000);
|
||||||
|
Talk(TEXT_AGGRO);
|
||||||
me->MonsterYell(TEXT_HODIR_AGGRO, LANG_UNIVERSAL, 0);
|
|
||||||
me->PlayDirectSound(SOUND_HODIR_AGGRO, 0);
|
|
||||||
|
|
||||||
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
|
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
|
||||||
{
|
{
|
||||||
@@ -268,7 +272,22 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustReachedHome() override { me->setActive(false); }
|
void DoAction(int action) override
|
||||||
|
{
|
||||||
|
if (action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case EVENT_FAIL_HM:
|
||||||
|
if (GameObject* go = me->FindNearestGameObject(GO_HODIR_CHEST_HARD, 500.0f))
|
||||||
|
{
|
||||||
|
go->SetGoState(GO_STATE_ACTIVE);
|
||||||
|
events.ScheduleEvent(EVENT_DESPAWN_CHEST, 3000);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SmallIcicles(bool enable)
|
void SmallIcicles(bool enable)
|
||||||
{
|
{
|
||||||
@@ -344,36 +363,28 @@ public:
|
|||||||
go->SetGoState(GO_STATE_ACTIVE);
|
go->SetGoState(GO_STATE_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
me->MonsterYell(TEXT_HODIR_DEFEATED, LANG_UNIVERSAL, 0);
|
Talk(TEXT_DEATH);
|
||||||
me->PlayDirectSound(SOUND_HODIR_DEFEATED, 0);
|
|
||||||
me->DespawnOrUnsummon(10000);
|
me->DespawnOrUnsummon(10000);
|
||||||
|
|
||||||
// spawn appropriate chests
|
|
||||||
uint32 chestId = me->GetMap()->Is25ManRaid() ? GO_HODIR_CHEST_NORMAL_HERO : GO_HODIR_CHEST_NORMAL;
|
|
||||||
if( GameObject* go = me->SummonGameObject(chestId, 1969.115f, -212.94f, 432.687f, 3 * M_PI / 2, 0, 0, 0, 0, 0) )
|
|
||||||
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
|
|
||||||
|
|
||||||
if( hardmode )
|
|
||||||
{
|
|
||||||
uint32 chestId2 = me->GetMap()->Is25ManRaid() ? GO_HODIR_CHEST_HARD_HERO : GO_HODIR_CHEST_HARD;
|
|
||||||
if( GameObject* go = me->SummonGameObject(chestId2, 2031.207f, -213.236f, 432.687f, 3 * M_PI / 2, 0, 0, 0, 0, 0) )
|
|
||||||
go->SetUInt32Value(GAMEOBJECT_FLAGS, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsInRoom()
|
||||||
|
{
|
||||||
|
// Calculate the distance between his home position to the gate
|
||||||
|
if (me->GetExactDist(me->GetHomePosition().GetPositionX(),
|
||||||
|
me->GetHomePosition().GetPositionY(),
|
||||||
|
me->GetHomePosition().GetPositionZ()) > 80.0f)
|
||||||
|
{
|
||||||
|
EnterEvadeMode();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateAI(uint32 diff) override
|
void UpdateAI(uint32 diff) override
|
||||||
{
|
{
|
||||||
if (addSpawnTimer <= diff)
|
if (!IsInRoom()) { return; }
|
||||||
{
|
|
||||||
addSpawnTimer = 5000;
|
|
||||||
if (!me->IsInCombat() && !summons.size() && !me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
|
||||||
if (SelectTargetFromPlayerList(135.0f))
|
|
||||||
SpawnHelpers();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
addSpawnTimer -= diff;
|
|
||||||
|
|
||||||
if (!UpdateVictim())
|
if (!UpdateVictim())
|
||||||
{
|
{
|
||||||
@@ -403,16 +414,19 @@ public:
|
|||||||
{
|
{
|
||||||
berserk = true;
|
berserk = true;
|
||||||
me->CastSpell(me, SPELL_BERSERK, true);
|
me->CastSpell(me, SPELL_BERSERK, true);
|
||||||
me->MonsterYell(TEXT_HODIR_BERSERK, LANG_UNIVERSAL, 0);
|
Talk(TEXT_BERSERK);
|
||||||
me->PlayDirectSound(SOUND_HODIR_BERSERK, 0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_HARD_MODE_MISSED:
|
case EVENT_HARD_MODE_MISSED:
|
||||||
{
|
{
|
||||||
hardmode = false;
|
Talk(TEXT_HM_MISS);
|
||||||
me->MonsterTextEmote(TEXTEMOTE_HODIR_HARD_MODE_MISSED, 0);
|
me->CastSpell(me->FindNearestGameObject(GO_HODIR_CHEST_HARD, 400.0f), SPELL_SHATTER_CHEST, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EVENT_DESPAWN_CHEST:
|
||||||
|
if (pInstance && pInstance->GetData(TYPE_HODIR) != DONE)
|
||||||
|
pInstance->SetData(TYPE_HODIR_HM_FAIL, 0);
|
||||||
|
break;
|
||||||
case EVENT_FLASH_FREEZE:
|
case EVENT_FLASH_FREEZE:
|
||||||
{
|
{
|
||||||
std::list<Unit*> targets;
|
std::list<Unit*> targets;
|
||||||
@@ -431,14 +445,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
me->CastSpell((Unit*)nullptr, SPELL_FLASH_FREEZE_CAST, false);
|
me->CastSpell((Unit*)nullptr, SPELL_FLASH_FREEZE_CAST, false);
|
||||||
me->MonsterTextEmote("Hodir begins to cast Flash Freeze!", 0, true);
|
|
||||||
me->MonsterYell(TEXT_HODIR_FLASH_FREEZE, LANG_UNIVERSAL, 0);
|
|
||||||
me->PlayDirectSound(SOUND_HODIR_FLASH_FREEZE, 0);
|
me->PlayDirectSound(SOUND_HODIR_FLASH_FREEZE, 0);
|
||||||
|
Talk(TEXT_FLASH_FREEZE);
|
||||||
|
Talk(TEXT_EMOTE_FREEZE);
|
||||||
SmallIcicles(false);
|
SmallIcicles(false);
|
||||||
events.RepeatEvent(55000 + urand(0, 10000));
|
events.ScheduleEvent(EVENT_FLASH_FREEZE, urand(48000, 49000));
|
||||||
events.ScheduleEvent(EVENT_SMALL_ICICLES_ENABLE, Is25ManRaid() ? 12000 : 24000);
|
events.ScheduleEvent(EVENT_SMALL_ICICLES_ENABLE, Is25ManRaid() ? 12000 : 24000);
|
||||||
events.ScheduleEvent(EVENT_FROZEN_BLOWS, 15000);
|
events.ScheduleEvent(EVENT_FROZEN_BLOWS, 15000);
|
||||||
events.RescheduleEvent(EVENT_FREEZE, 20000);
|
events.RescheduleEvent(EVENT_FREEZE, urand(17000, 20000));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_SMALL_ICICLES_ENABLE:
|
case EVENT_SMALL_ICICLES_ENABLE:
|
||||||
@@ -448,10 +462,9 @@ public:
|
|||||||
break;
|
break;
|
||||||
case EVENT_FROZEN_BLOWS:
|
case EVENT_FROZEN_BLOWS:
|
||||||
{
|
{
|
||||||
me->MonsterTextEmote("Hodir gains Frozen Blows!", 0, true);
|
Talk(TEXT_EMOTE_BLOW);
|
||||||
me->MonsterTextEmote(TEXTEMOTE_HODIR_FROZEN_BLOWS, 0);
|
Talk(TEXT_STALACTITE);
|
||||||
me->PlayDirectSound(SOUND_HODIR_FROZEN_BLOWS, 0);
|
me->CastSpell(me, Is25ManRaid()? SPELL_FROZEN_BLOWS_25 : SPELL_FROZEN_BLOWS_10, true);
|
||||||
me->CastSpell(me, SPELL_FROZEN_BLOWS, true);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EVENT_FREEZE:
|
case EVENT_FREEZE:
|
||||||
@@ -459,7 +472,7 @@ public:
|
|||||||
me->CastSpell(plr, SPELL_FREEZE, false);
|
me->CastSpell(plr, SPELL_FREEZE, false);
|
||||||
else if (Unit* plr = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
|
else if (Unit* plr = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true))
|
||||||
me->CastSpell(plr, SPELL_FREEZE, false);
|
me->CastSpell(plr, SPELL_FREEZE, false);
|
||||||
events.RepeatEvent(15000);
|
events.RescheduleEvent(EVENT_FREEZE, urand(17000, 20000));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,19 +529,8 @@ public:
|
|||||||
|
|
||||||
void KilledUnit(Unit* who) override
|
void KilledUnit(Unit* who) override
|
||||||
{
|
{
|
||||||
if( who->GetTypeId() == TYPEID_PLAYER )
|
if (who->GetTypeId() == TYPEID_PLAYER)
|
||||||
{
|
Talk(TEXT_SLAY);
|
||||||
if( urand(0, 1) )
|
|
||||||
{
|
|
||||||
me->MonsterYell(TEXT_HODIR_SLAIN_1, LANG_UNIVERSAL, 0);
|
|
||||||
me->PlayDirectSound(SOUND_HODIR_SLAIN_1, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
me->MonsterYell(TEXT_HODIR_SLAIN_2, LANG_UNIVERSAL, 0);
|
|
||||||
me->PlayDirectSound(SOUND_HODIR_SLAIN_2, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JustSummoned(Creature* s) override
|
void JustSummoned(Creature* s) override
|
||||||
@@ -576,8 +578,6 @@ public:
|
|||||||
return (bAchievCheese ? 1 : 0);
|
return (bAchievCheese ? 1 : 0);
|
||||||
case 2:
|
case 2:
|
||||||
return (bAchievGettingCold ? 1 : 0);
|
return (bAchievGettingCold ? 1 : 0);
|
||||||
case 3:
|
|
||||||
return (hardmode ? 1 : 0);
|
|
||||||
case 4:
|
case 4:
|
||||||
return (bAchievCoolestFriends ? 1 : 0);
|
return (bAchievCoolestFriends ? 1 : 0);
|
||||||
}
|
}
|
||||||
@@ -1143,6 +1143,33 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class spell_hodir_shatter_chest : public SpellScriptLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
spell_hodir_shatter_chest() : SpellScriptLoader("spell_hodir_shatter_chest") { }
|
||||||
|
|
||||||
|
class spell_hodir_shatter_chestSpellScript : public SpellScript
|
||||||
|
{
|
||||||
|
PrepareSpellScript(spell_hodir_shatter_chestSpellScript)
|
||||||
|
|
||||||
|
void destroyWinterCache()
|
||||||
|
{
|
||||||
|
if (Unit* hodir = GetCaster())
|
||||||
|
hodir->GetAI()->DoAction(EVENT_FAIL_HM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Register() override
|
||||||
|
{
|
||||||
|
AfterHit += SpellHitFn(spell_hodir_shatter_chestSpellScript::destroyWinterCache);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
SpellScript* GetSpellScript() const override
|
||||||
|
{
|
||||||
|
return new spell_hodir_shatter_chestSpellScript();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class spell_hodir_biting_cold_main_aura : public SpellScriptLoader
|
class spell_hodir_biting_cold_main_aura : public SpellScriptLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -1156,7 +1183,10 @@ public:
|
|||||||
{
|
{
|
||||||
if ((aurEff->GetTickNumber() % 4) == 0)
|
if ((aurEff->GetTickNumber() % 4) == 0)
|
||||||
if (Unit* target = GetTarget())
|
if (Unit* target = GetTarget())
|
||||||
if (target->GetTypeId() == TYPEID_PLAYER && !target->isMoving() && !target->HasAura(SPELL_BITING_COLD_PLAYER_AURA))
|
if (target->GetTypeId() == TYPEID_PLAYER
|
||||||
|
&& !target->isMoving()
|
||||||
|
&& !target->HasAura(SPELL_BITING_COLD_PLAYER_AURA)
|
||||||
|
&& !target->HasAura(SPELL_MAGE_TOASTY_FIRE_AURA))
|
||||||
target->CastSpell(target, SPELL_BITING_COLD_PLAYER_AURA, true);
|
target->CastSpell(target, SPELL_BITING_COLD_PLAYER_AURA, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1181,15 +1211,8 @@ public:
|
|||||||
{
|
{
|
||||||
PrepareAuraScript(spell_hodir_biting_cold_player_aura_AuraScript)
|
PrepareAuraScript(spell_hodir_biting_cold_player_aura_AuraScript)
|
||||||
|
|
||||||
uint8 counter;
|
uint8 counter {0};
|
||||||
bool prev;
|
bool prev {false};
|
||||||
|
|
||||||
bool Load() override
|
|
||||||
{
|
|
||||||
counter = 0;
|
|
||||||
prev = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
|
||||||
{
|
{
|
||||||
@@ -1570,6 +1593,7 @@ void AddSC_boss_hodir()
|
|||||||
new spell_hodir_flash_freeze();
|
new spell_hodir_flash_freeze();
|
||||||
new spell_hodir_storm_power();
|
new spell_hodir_storm_power();
|
||||||
new spell_hodir_storm_cloud();
|
new spell_hodir_storm_cloud();
|
||||||
|
new spell_hodir_shatter_chest();
|
||||||
|
|
||||||
new achievement_cheese_the_freeze();
|
new achievement_cheese_the_freeze();
|
||||||
new achievement_getting_cold_in_here();
|
new achievement_getting_cold_in_here();
|
||||||
|
|||||||
@@ -23,11 +23,19 @@ public:
|
|||||||
|
|
||||||
struct instance_ulduar_InstanceMapScript : public InstanceScript
|
struct instance_ulduar_InstanceMapScript : public InstanceScript
|
||||||
{
|
{
|
||||||
instance_ulduar_InstanceMapScript(Map* pMap) : InstanceScript(pMap) {Initialize();};
|
instance_ulduar_InstanceMapScript(Map* pMap) : InstanceScript(pMap)
|
||||||
|
{
|
||||||
|
Initialize();
|
||||||
|
// 0: 10 man difficulty
|
||||||
|
// 1: 25 man difficulty
|
||||||
|
m_difficulty = (pMap->Is25ManRaid() ? 0 : 1);
|
||||||
|
};
|
||||||
|
|
||||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||||
uint32 C_of_Ulduar_MASK;
|
uint32 C_of_Ulduar_MASK;
|
||||||
|
|
||||||
|
int m_difficulty;
|
||||||
|
|
||||||
// Bosses
|
// Bosses
|
||||||
uint64 m_uiLeviathanGUID;
|
uint64 m_uiLeviathanGUID;
|
||||||
uint64 m_uiIgnisGUID;
|
uint64 m_uiIgnisGUID;
|
||||||
@@ -70,6 +78,13 @@ public:
|
|||||||
// Thorim
|
// Thorim
|
||||||
uint64 m_thorimGameobjectsGUID[5];
|
uint64 m_thorimGameobjectsGUID[5];
|
||||||
|
|
||||||
|
// Hodir's chests
|
||||||
|
bool hmHodir;
|
||||||
|
uint64 m_hodirNormalChest;
|
||||||
|
uint64 m_hodirHardmodeChest;
|
||||||
|
Position normalChestPosition = { 1967.152588f, -204.188461f, 432.686951f, 5.50957f };
|
||||||
|
Position hardChestPosition = { 2035.94600f, -202.084885f, 432.686859f, 3.164077f };
|
||||||
|
|
||||||
// Mimiron
|
// Mimiron
|
||||||
uint64 m_MimironDoor[3];
|
uint64 m_MimironDoor[3];
|
||||||
uint64 m_MimironLeviathanMKIIguid;
|
uint64 m_MimironLeviathanMKIIguid;
|
||||||
@@ -146,6 +161,11 @@ public:
|
|||||||
// Thorim
|
// Thorim
|
||||||
memset(&m_thorimGameobjectsGUID, 0, sizeof(m_thorimGameobjectsGUID));
|
memset(&m_thorimGameobjectsGUID, 0, sizeof(m_thorimGameobjectsGUID));
|
||||||
|
|
||||||
|
// Hodir
|
||||||
|
m_hodirNormalChest = 0;
|
||||||
|
m_hodirHardmodeChest = 0;
|
||||||
|
hmHodir = true; // If players fail the Hardmode then becomes false
|
||||||
|
|
||||||
// Mimiron
|
// Mimiron
|
||||||
memset(&m_MimironDoor, 0, sizeof(m_MimironDoor));
|
memset(&m_MimironDoor, 0, sizeof(m_MimironDoor));
|
||||||
m_MimironLeviathanMKIIguid = 0;
|
m_MimironLeviathanMKIIguid = 0;
|
||||||
@@ -233,6 +253,78 @@ public:
|
|||||||
SetData(eventId, 0);
|
SetData(eventId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SpawnHodirChests(int rd)
|
||||||
|
{
|
||||||
|
if (Creature* cr = instance->GetCreature(m_uiHodirGUID))
|
||||||
|
{
|
||||||
|
switch (rd)
|
||||||
|
{
|
||||||
|
case 0: // 10 man chest
|
||||||
|
{
|
||||||
|
if (!m_hodirNormalChest)
|
||||||
|
{
|
||||||
|
if (GameObject* go = cr->SummonGameObject(
|
||||||
|
GO_HODIR_CHEST_NORMAL,
|
||||||
|
normalChestPosition.GetPositionX(),
|
||||||
|
normalChestPosition.GetPositionY(),
|
||||||
|
normalChestPosition.GetPositionZ(),
|
||||||
|
normalChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
m_hodirNormalChest = go->GetGUID();
|
||||||
|
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m_hodirHardmodeChest)
|
||||||
|
{
|
||||||
|
if (GameObject* go = cr->SummonGameObject(
|
||||||
|
GO_HODIR_CHEST_HARD,
|
||||||
|
hardChestPosition.GetPositionX(),
|
||||||
|
hardChestPosition.GetPositionY(),
|
||||||
|
hardChestPosition.GetPositionZ(),
|
||||||
|
hardChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
m_hodirHardmodeChest = go->GetGUID();
|
||||||
|
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||||
|
hmHodir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: // 25 man chest
|
||||||
|
{
|
||||||
|
if (!m_hodirNormalChest)
|
||||||
|
{
|
||||||
|
if (GameObject* go = cr->SummonGameObject(
|
||||||
|
GO_HODIR_CHEST_NORMAL_HERO,
|
||||||
|
normalChestPosition.GetPositionX(),
|
||||||
|
normalChestPosition.GetPositionY(),
|
||||||
|
normalChestPosition.GetPositionZ(),
|
||||||
|
normalChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
m_hodirNormalChest = go->GetGUID();
|
||||||
|
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m_hodirHardmodeChest)
|
||||||
|
{
|
||||||
|
if (GameObject* go = cr->SummonGameObject(
|
||||||
|
GO_HODIR_CHEST_HARD_HERO,
|
||||||
|
hardChestPosition.GetPositionX(),
|
||||||
|
hardChestPosition.GetPositionY(),
|
||||||
|
hardChestPosition.GetPositionZ(),
|
||||||
|
hardChestPosition.GetOrientation(), 0, 0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
m_hodirHardmodeChest = go->GetGUID();
|
||||||
|
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||||
|
hmHodir = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OnCreatureCreate(Creature* creature) override
|
void OnCreatureCreate(Creature* creature) override
|
||||||
{
|
{
|
||||||
switch(creature->GetEntry())
|
switch(creature->GetEntry())
|
||||||
@@ -573,6 +665,23 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setChestsLootable(uint32 boss)
|
||||||
|
{
|
||||||
|
if (boss)
|
||||||
|
{
|
||||||
|
switch (boss)
|
||||||
|
{
|
||||||
|
case TYPE_HODIR:
|
||||||
|
if (hmHodir)
|
||||||
|
if (GameObject* go = instance->GetGameObject(m_hodirHardmodeChest))
|
||||||
|
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||||
|
if (GameObject* go = instance->GetGameObject(m_hodirNormalChest))
|
||||||
|
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetData(uint32 type, uint32 data) override
|
void SetData(uint32 type, uint32 data) override
|
||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
@@ -617,8 +726,22 @@ public:
|
|||||||
}
|
}
|
||||||
if (type == TYPE_MIMIRON && data == IN_PROGRESS) // after reaching him without tram and starting the fight
|
if (type == TYPE_MIMIRON && data == IN_PROGRESS) // after reaching him without tram and starting the fight
|
||||||
m_mimironTramUsed = true;
|
m_mimironTramUsed = true;
|
||||||
|
if (GetData(TYPE_HODIR) == DONE)
|
||||||
|
setChestsLootable(TYPE_HODIR);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TYPE_SPAWN_HODIR_CACHE:
|
||||||
|
// Is the difficulty 10 man(0) ? return 10 man : return 25 man;
|
||||||
|
SpawnHodirChests(m_difficulty == 0 ? 0 : 1);
|
||||||
|
break;
|
||||||
|
case TYPE_HODIR_HM_FAIL:
|
||||||
|
if (GameObject* go = instance->GetGameObject(m_hodirHardmodeChest))
|
||||||
|
{
|
||||||
|
hmHodir = false;
|
||||||
|
go->Delete();
|
||||||
|
m_hodirHardmodeChest = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case TYPE_WATCHERS:
|
case TYPE_WATCHERS:
|
||||||
m_auiEncounter[type] |= 1 << data;
|
m_auiEncounter[type] |= 1 << data;
|
||||||
break;
|
break;
|
||||||
@@ -822,6 +945,14 @@ public:
|
|||||||
return m_thorimGameobjectsGUID[data - DATA_THORIM_LEVER_GATE];
|
return m_thorimGameobjectsGUID[data - DATA_THORIM_LEVER_GATE];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Hodir chests
|
||||||
|
case GO_HODIR_CHEST_HARD:
|
||||||
|
case GO_HODIR_CHEST_HARD_HERO:
|
||||||
|
return m_hodirHardmodeChest;
|
||||||
|
case GO_HODIR_CHEST_NORMAL:
|
||||||
|
case GO_HODIR_CHEST_NORMAL_HERO:
|
||||||
|
return m_hodirNormalChest;
|
||||||
|
|
||||||
// Freya Elders
|
// Freya Elders
|
||||||
case NPC_ELDER_IRONBRANCH:
|
case NPC_ELDER_IRONBRANCH:
|
||||||
case NPC_ELDER_STONEBARK:
|
case NPC_ELDER_STONEBARK:
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ enum UlduarEncounters
|
|||||||
TYPE_YOGGSARON = 12,
|
TYPE_YOGGSARON = 12,
|
||||||
TYPE_ALGALON = 13,
|
TYPE_ALGALON = 13,
|
||||||
TYPE_WATCHERS = 14,
|
TYPE_WATCHERS = 14,
|
||||||
|
TYPE_SPAWN_HODIR_CACHE = 15,
|
||||||
|
TYPE_HODIR_HM_FAIL = 16,
|
||||||
|
TYPE_WINTER_CACHE = 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum UlduarData
|
enum UlduarData
|
||||||
|
|||||||
Reference in New Issue
Block a user