mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-02-01 06:37:12 +01:00
Scripts/Shattered Halls: Rewrite Nethekurse (#31426)
This commit is contained in:
95
sql/updates/world/3.3.5/2025_12_20_01_world.sql
Normal file
95
sql/updates/world/3.3.5/2025_12_20_01_world.sql
Normal file
@@ -0,0 +1,95 @@
|
||||
--
|
||||
UPDATE `creature_template` SET `ScriptName` = 'npc_wild_shadow_fissure' WHERE `entry` = 18370;
|
||||
UPDATE `creature_template` SET `minlevel` = 70, `maxlevel` = 70, `unit_flags` = 0x02000000 WHERE `entry` = 18370;
|
||||
UPDATE `creature_template` SET `minlevel` = 71, `maxlevel` = 71, `unit_flags` = 0x02000000 WHERE `entry` = 20598;
|
||||
|
||||
DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` = 13 AND `SourceEntry` IN (30735,30741,32251,30745);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ConditionStringValue1`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
|
||||
(13,1,30735,0,0,58,0,0,0,0,"FelOrcConvertNethekurseEvent",0,0,0,"","Group 0: Spell 'Shadow Sear' (Effect 0) targets creature 'Fel Orc Convert'"),
|
||||
(13,3,30741,0,0,58,0,0,0,0,"FelOrcConvertNethekurseEvent",0,0,0,"","Group 0: Spell 'Death Coil' (Effect 0, 1) targets creature 'Fel Orc Convert'"),
|
||||
(13,1,32251,0,0,58,0,0,0,0,"FelOrcConvertNethekurseEvent",0,0,0,"","Group 0: Spell 'Consumption' (Effect 0) targets creature 'Fel Orc Convert'"),
|
||||
(13,1,30745,0,0,58,0,0,0,0,"FelOrcConvertNethekurseEvent",0,0,0,"","Group 0: Spell 'Target Fissures' (Effect 0) targets creature 'Fel Orc Convert'");
|
||||
|
||||
UPDATE `creature` SET `StringId` = 'FelOrcConvertNethekurseEvent' WHERE `guid` IN (59478,59479,59480,59481) AND `id` = 17083;
|
||||
|
||||
UPDATE `creature` SET `position_x` = 164.71588134765625, `position_y` = 266.263031005859375, `position_z` = -13.1121978759765625, `orientation` = 1.047197580337524414, `VerifiedBuild` = 14007 WHERE `guid` = 59478 AND `id` = 17083;
|
||||
UPDATE `creature` SET `position_x` = 174.04949951171875, `position_y` = 269.132476806640625, `position_z` = -13.0549201965332031, `orientation` = 1.448623299598693847, `VerifiedBuild` = 14007 WHERE `guid` = 59479 AND `id` = 17083;
|
||||
UPDATE `creature` SET `position_x` = 184.4263458251953125, `position_y` = 269.293731689453125, `position_z` = -13.0555877685546875, `orientation` = 1.727875947952270507, `VerifiedBuild` = 14007 WHERE `guid` = 59480 AND `id` = 17083;
|
||||
UPDATE `creature` SET `position_x` = 194.48394775390625, `position_y` = 267.07208251953125, `position_z` = -13.1039943695068359, `orientation` = 2.181661605834960937, `VerifiedBuild` = 14007 WHERE `guid` = 59481 AND `id` = 17083;
|
||||
|
||||
DELETE FROM `creature_text` WHERE `CreatureID` = 17083;
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(17083,0,0,"We are the true Horde!",12,0,100,0,0,0,16697,0,"Fel Orc Convert"),
|
||||
(17083,0,1,"For Kargath! For Victory!",12,0,100,0,0,0,16698,0,"Fel Orc Convert"),
|
||||
(17083,0,2,"Gakarah ma!",12,0,100,0,0,0,16699,0,"Fel Orc Convert"),
|
||||
(17083,0,3,"The blood is our power!",12,0,100,0,0,0,16700,0,"Fel Orc Convert"),
|
||||
(17083,0,4,"Lok'tar Illadari!
|
||||
",12,0,100,0,0,0,16701,0,"Fel Orc Convert"),
|
||||
(17083,0,5,"This world is OURS!",12,0,100,0,0,0,16702,0,"Fel Orc Convert"),
|
||||
(17083,0,6,"Lok narash!",12,0,100,0,0,0,16703,0,"Fel Orc Convert"),
|
||||
-- Not sure if these are grouped correctly, based on few sniffs
|
||||
-- By the way, language is correct, verified, not a typo
|
||||
-- Text 14143 seems to be unused, not added here
|
||||
(17083,1,0,"It hurt!",14,0,100,0,0,0,14136,0,"Fel Orc Convert - Shadow Sear"),
|
||||
(17083,1,1,"Augh! No more hurt!",14,0,100,0,0,0,14137,0,"Fel Orc Convert - Shadow Sear"),
|
||||
(17083,1,2,"This not good tickle!",14,0,100,0,0,0,14138,0,"Fel Orc Convert - Shadow Sear"),
|
||||
(17083,1,3,"Skin on fire!",14,0,100,0,0,0,14139,0,"Fel Orc Convert - Shadow Sear"),
|
||||
|
||||
(17083,2,0,"It hurt!",14,1,100,0,0,0,14140,0,"Fel Orc Convert - Death Coil"),
|
||||
(17083,2,1,"Aahhh!",14,1,100,0,0,0,14141,0,"Fel Orc Convert - Death Coil"),
|
||||
(17083,2,2,"No more scary!",14,1,100,0,0,0,14142,0,"Fel Orc Convert - Death Coil"),
|
||||
(17083,2,3,"No more!",14,1,100,0,0,0,14144,0,"Fel Orc Convert - Death Coil"),
|
||||
|
||||
(17083,3,0,"Pain!",14,1,100,0,0,0,14149,0,"Fel Orc Convert - Target Fissures"),
|
||||
(17083,3,1,"It hurts!",14,1,100,0,0,0,14150,0,"Fel Orc Convert - Target Fissures"),
|
||||
(17083,3,2,"Graaagggh!!",14,1,100,0,0,0,14151,0,"Fel Orc Convert - Target Fissures"),
|
||||
(17083,3,3,"No more!!",14,1,100,0,0,0,14152,0,"Fel Orc Convert - Target Fissures");
|
||||
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_grand_warlock_nethekurse_target_fissures';
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(30745, 'spell_grand_warlock_nethekurse_target_fissures');
|
||||
|
||||
DELETE FROM `areatrigger_scripts` WHERE `entry` = 4347;
|
||||
INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES
|
||||
(4347, 'at_shattered_halls_the_sewer');
|
||||
|
||||
UPDATE `gameobject_template` SET `ScriptName` = 'go_grand_warlock_chamber_door' WHERE `entry` = 182539;
|
||||
|
||||
DELETE FROM `creature_text` WHERE `CreatureID` = 16807;
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(16807,0,0,"Beg for your pitiful life!",14,0,100,11,0,10259,14130,0,"nethekurse SAY_TAUNT_SHADOW_SEAR"),
|
||||
(16807,1,0,"Run, coward, run! ",14,0,100,11,0,10260,14132,0,"nethekurse SAY_TAUNT_DEATH_COIL"),
|
||||
(16807,2,0,"Your pain amuses me!",14,0,100,11,0,10261,14148,0,"nethekurse SAY_TAUNT_SHADOW_FISSURE"),
|
||||
|
||||
(16807,3,0,"You wish to fight us all at once? This should be amusing!
|
||||
",14,0,100,0,0,10262,15594,0,"nethekurse SAY_AGGRO_ALL_ALIVE"),
|
||||
(16807,4,0,"Come on, show me a real fight!",14,0,100,0,0,10272,15595,0,"nethekurse SAY_AGGRO_SOME_ALIVE"),
|
||||
(16807,5,0,"Thank you for saving me the trouble. Now it's my turn to have some fun!
|
||||
",14,0,100,0,0,10270,15589,0,"nethekurse SAY_AGGRO_ALL_DEAD"),
|
||||
|
||||
(16807,6,0,"You can have that one, I no longer need him!",14,0,100,11,0,10263,15569,0,"nethekurse SAY_PEON_ENGAGED_1"),
|
||||
(16807,6,1,"Yes, beat him mercilessly! His skull is as thick as an ogre's!
|
||||
",14,0,100,11,0,10264,15575,0,"nethekurse SAY_PEON_ENGAGED_2"),
|
||||
(16807,6,2,"Don't waste your time on that one, he's weak!",14,0,100,11,0,10265,15573,0,"nethekurse SAY_PEON_ENGAGED_3"),
|
||||
(16807,6,3,"You want him? Very well, take him!",14,0,100,11,0,10266,15572,0,"nethekurse SAY_PEON_ENGAGED_4"),
|
||||
|
||||
(16807,7,0,"One pitiful wretch down. Go on, take another one! ",14,0,100,0,0,10267,15579,0,"nethekurse SAY_PEON_DEFEATED_1"),
|
||||
(16807,7,1,"Ah, what a waste... next!",14,0,100,0,0,10268,15584,0,"nethekurse SAY_PEON_DEFEATED_2"),
|
||||
(16807,7,2,"I was going to kill him anyway!",14,0,100,0,0,10269,15582,0,"nethekurse SAY_PEON_DEFEATED_3"),
|
||||
|
||||
(16807,8,0,"I'm already bored!",14,0,100,0,0,10271,16864,0,"nethekurse SAY_SLAY_1"),
|
||||
(16807,8,1,"I had more fun torturing the peons!",14,0,100,0,0,10273,16863,0,"nethekurse SAY_SLAY_2"),
|
||||
(16807,8,2,"You lose.",14,0,100,0,0,10274,16865,0,"nethekurse SAY_SLAY_3"),
|
||||
(16807,8,3,"Oh, just die!",14,0,100,0,0,10275,16866,0,"nethekurse SAY_SLAY_4"),
|
||||
|
||||
(16807,9,0,"What... a shame.",14,0,100,0,0,10276,16862,0,"nethekurse SAY_DEATH");
|
||||
|
||||
UPDATE `creature` SET `MovementType` = 2 WHERE `id` = 16807;
|
||||
UPDATE `creature_template_addon` SET `path_id` = 578530, `SheathState` = 1 WHERE `entry` IN (16807,20568);
|
||||
|
||||
DELETE FROM `waypoint_data` WHERE `id` = 578530;
|
||||
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `delay`, `action`, `orientation`, `move_type`, `action_chance`) VALUES
|
||||
(578530,1,178.51125,287.97794,-8.183065,0,0,NULL,0,100),
|
||||
(578530,2,171.82281,289.97687,-8.185595,0,0,NULL,0,100),
|
||||
(578530,3,178.51125,287.97794,-8.183065,0,0,NULL,0,100),
|
||||
(578530,4,184.78966,290.36990,-8.181390,0,0,NULL,0,100);
|
||||
@@ -15,196 +15,202 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Grand_Warlock_Nethekurse
|
||||
SD%Complete: 75
|
||||
SDComment: encounter not fully completed. missing part where boss kill minions.
|
||||
SDCategory: Hellfire Citadel, Shattered Halls
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
boss_grand_warlock_nethekurse
|
||||
npc_fel_orc_convert
|
||||
npc_lesser_shadow_fissure
|
||||
EndContentData */
|
||||
/*
|
||||
* Combat timers requires to be revisited
|
||||
* Clearly seen one peon died from Shadow Fissure, doesn't work because health regenerates,
|
||||
it should regenerate in case of other spells, no sniffs with Wild Shadow Fissure
|
||||
* Dark Spin gets interrupted after first tick
|
||||
* Death Coil is a buff instead of a debuff
|
||||
*/
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "Containers.h"
|
||||
#include "GameObject.h"
|
||||
#include "GameObjectAI.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "shattered_halls.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
enum Says
|
||||
enum NethekurseTexts
|
||||
{
|
||||
SAY_INTRO = 0,
|
||||
SAY_PEON_ATTACKED = 1,
|
||||
SAY_PEON_DIES = 2,
|
||||
SAY_TAUNT = 3,
|
||||
SAY_AGGRO = 4,
|
||||
SAY_SLAY = 5,
|
||||
SAY_DIE = 6
|
||||
};
|
||||
SAY_TAUNT_SHADOW_SEAR = 0,
|
||||
SAY_TAUNT_DEATH_COIL = 1,
|
||||
SAY_TAUNT_SHADOW_FISSURE = 2,
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_DEATH_COIL = 30500, // 30741 heroic
|
||||
SPELL_DARK_SPIN = 30502, // core bug spell attack caster :D
|
||||
SPELL_SHADOW_FISSURE = 30496, // Summon the ShadowFissure NPC
|
||||
SPELL_SHADOW_CLEAVE = 30495,
|
||||
H_SPELL_SHADOW_SLAM = 35953,
|
||||
SPELL_HEMORRHAGE = 30478,
|
||||
SPELL_CONSUMPTION = 30497,
|
||||
SPELL_TEMPORARY_VISUAL = 39312, // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should
|
||||
SAY_AGGRO_ALL_ALIVE = 3,
|
||||
SAY_AGGRO_SOME_ALIVE = 4,
|
||||
SAY_AGGRO_ALL_DEAD = 5,
|
||||
|
||||
SPELL_SHADOW_SEAR = 30735 // cast on entry 17083 which then makes sound 1343
|
||||
// 30948 cast on self by 17687
|
||||
};
|
||||
SAY_PEON_ENGAGED = 6,
|
||||
SAY_PEON_DEFEATED = 7,
|
||||
|
||||
enum SetData
|
||||
{
|
||||
SETDATA_DATA = 1,
|
||||
SETDATA_PEON_AGGRO = 1,
|
||||
SETDATA_PEON_DEATH = 2
|
||||
};
|
||||
SAY_SLAY = 8,
|
||||
SAY_DEATH = 9,
|
||||
|
||||
enum Events
|
||||
{
|
||||
// Fel Orc Convert
|
||||
EVENT_HEMORRHAGE = 1
|
||||
SAY_PEON_AGGRO = 0,
|
||||
SAY_PEON_SHADOW_SEAR = 1,
|
||||
SAY_PEON_DEATH_COIL = 2,
|
||||
SAY_PEON_SHADOW_FISSURE = 3
|
||||
};
|
||||
|
||||
// ########################################################
|
||||
// Grand Warlock Nethekurse
|
||||
// ########################################################
|
||||
enum NethekurseSpells
|
||||
{
|
||||
// Combat
|
||||
SPELL_SHADOW_FISSURE = 30496,
|
||||
SPELL_DEATH_COIL = 30500,
|
||||
SPELL_SHADOW_CLEAVE = 30495,
|
||||
SPELL_SHADOW_SLAM = 35953,
|
||||
SPELL_DARK_SPIN = 30502,
|
||||
|
||||
// Intro
|
||||
SPELL_PEON_SHADOW_SEAR = 30735,
|
||||
SPELL_PEON_DEATH_COIL = 30741,
|
||||
SPELL_PEON_TARGET_FISSURES = 30745,
|
||||
|
||||
// Fel Orc Convert
|
||||
SPELL_HEMORRHAGE = 30478,
|
||||
|
||||
// Lesser Shadow Fissure
|
||||
SPELL_CONSUMPTION = 30497,
|
||||
SPELL_CONSUMPTION_H = 35952,
|
||||
|
||||
// Wild Shadow Fissure
|
||||
SPELL_CONSUMPTION_WILD = 32250,
|
||||
|
||||
// Scripts
|
||||
SPELL_SHADOW_FISSURE_2 = 30744
|
||||
};
|
||||
|
||||
enum NethekurseEvents
|
||||
{
|
||||
EVENT_TAUNT_PEONS = 1,
|
||||
EVENT_INTERNAL_COOLDOWN,
|
||||
EVENT_CLEAR_EMOTE_STATE,
|
||||
|
||||
EVENT_SHADOW_FISSURE,
|
||||
EVENT_DEATH_COIL,
|
||||
EVENT_SHADOW_CLEAVE,
|
||||
EVENT_SHADOW_SLAM,
|
||||
EVENT_DARK_SPIN
|
||||
};
|
||||
|
||||
enum NethekurseActions
|
||||
{
|
||||
ACTION_START_INTRO = 0,
|
||||
ACTION_PEON_ENGAGED = 1,
|
||||
ACTION_PEON_KILLED = 2
|
||||
};
|
||||
|
||||
enum NethekurseMisc
|
||||
{
|
||||
SOUND_ID_ROAR = 9110,
|
||||
MAX_KILLED_PEONS = 4
|
||||
};
|
||||
|
||||
// 16807 - Grand Warlock Nethekurse
|
||||
struct boss_grand_warlock_nethekurse : public BossAI
|
||||
{
|
||||
boss_grand_warlock_nethekurse(Creature* creature) : BossAI(creature, DATA_NETHEKURSE)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
IsIntroEvent = false;
|
||||
IntroOnce = false;
|
||||
IsMainEvent = false;
|
||||
//HasTaunted = false;
|
||||
SpinOnce = false;
|
||||
Phase = false;
|
||||
|
||||
PeonEngagedCount = 0;
|
||||
PeonKilledCount = 0;
|
||||
|
||||
IntroEvent_Timer = 90000; // how long before getting bored and kills his minions?
|
||||
DeathCoil_Timer = 20000;
|
||||
ShadowFissure_Timer = 8000;
|
||||
Cleave_Timer = 5000;
|
||||
}
|
||||
boss_grand_warlock_nethekurse(Creature* creature) : BossAI(creature, DATA_NETHEKURSE),
|
||||
_peonKilledCount(0), _isEventOnCooldown(false), _isDarkSpinStarted(false) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
Initialize();
|
||||
_isEventOnCooldown = false;
|
||||
_isDarkSpinStarted = false;
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustEngagedWith(Unit* who) override
|
||||
{
|
||||
_JustDied();
|
||||
Talk(SAY_DIE);
|
||||
}
|
||||
BossAI::JustEngagedWith(who);
|
||||
|
||||
void SetData(uint32 data, uint32 value) override
|
||||
{
|
||||
if (data != SETDATA_DATA)
|
||||
return;
|
||||
events.Reset();
|
||||
|
||||
switch (value)
|
||||
events.ScheduleEvent(EVENT_SHADOW_FISSURE, 8s);
|
||||
events.ScheduleEvent(EVENT_DEATH_COIL, 10s, 15s);
|
||||
|
||||
if (!IsHeroic())
|
||||
events.ScheduleEvent(EVENT_SHADOW_CLEAVE, 15s, 20s);
|
||||
else
|
||||
events.ScheduleEvent(EVENT_SHADOW_SLAM, 15s, 20s);
|
||||
|
||||
switch (_peonKilledCount)
|
||||
{
|
||||
case SETDATA_PEON_AGGRO:
|
||||
if (PeonEngagedCount >= 4)
|
||||
return;
|
||||
|
||||
Talk(SAY_PEON_ATTACKED);
|
||||
++PeonEngagedCount;
|
||||
case 0:
|
||||
Talk(SAY_AGGRO_ALL_ALIVE);
|
||||
break;
|
||||
case SETDATA_PEON_DEATH:
|
||||
if (PeonKilledCount >= 4)
|
||||
return;
|
||||
|
||||
Talk(SAY_PEON_DIES);
|
||||
++PeonKilledCount;
|
||||
|
||||
if (PeonKilledCount == 4)
|
||||
{
|
||||
IsIntroEvent = false;
|
||||
IsMainEvent = true;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
Talk(SAY_AGGRO_SOME_ALIVE);
|
||||
break;
|
||||
case 4:
|
||||
Talk(SAY_AGGRO_ALL_DEAD);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DoTauntPeons()
|
||||
void DoAction(int32 action) override
|
||||
{
|
||||
Talk(SAY_TAUNT);
|
||||
|
||||
/// @todo kill the peons first
|
||||
IsIntroEvent = false;
|
||||
PeonEngagedCount = 4;
|
||||
PeonKilledCount = 4;
|
||||
IsMainEvent = true;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (IsIntroEvent || !IsMainEvent)
|
||||
if (!me->IsAlive())
|
||||
return;
|
||||
|
||||
if (me->Attack(who, true))
|
||||
switch (action)
|
||||
{
|
||||
if (Phase)
|
||||
DoStartNoMovement(who);
|
||||
else
|
||||
DoStartMovement(who);
|
||||
case ACTION_START_INTRO:
|
||||
if (!me->IsInCombat() && _peonKilledCount != MAX_KILLED_PEONS)
|
||||
events.ScheduleEvent(EVENT_TAUNT_PEONS, 0s);
|
||||
break;
|
||||
case ACTION_PEON_ENGAGED:
|
||||
if (!me->IsInCombat() && !_isEventOnCooldown)
|
||||
{
|
||||
Talk(SAY_PEON_ENGAGED);
|
||||
me->PauseMovement(5000);
|
||||
me->SetFacingTo(4.537856101989746093f);
|
||||
_isEventOnCooldown = true;
|
||||
|
||||
events.ScheduleEvent(EVENT_INTERNAL_COOLDOWN, 5s);
|
||||
}
|
||||
break;
|
||||
case ACTION_PEON_KILLED:
|
||||
{
|
||||
++_peonKilledCount;
|
||||
|
||||
if (!me->IsInCombat() && _peonKilledCount == MAX_KILLED_PEONS)
|
||||
DoZoneInCombat();
|
||||
|
||||
if (!me->IsInCombat() && !_isEventOnCooldown && _peonKilledCount != MAX_KILLED_PEONS)
|
||||
{
|
||||
Talk(SAY_PEON_DEFEATED);
|
||||
me->PauseMovement(5000);
|
||||
me->SetFacingTo(4.572762489318847656f);
|
||||
me->SetEmoteState(EMOTE_STATE_APPLAUD);
|
||||
_isEventOnCooldown = true;
|
||||
|
||||
events.ScheduleEvent(EVENT_INTERNAL_COOLDOWN, 5s);
|
||||
events.ScheduleEvent(EVENT_CLEAR_EMOTE_STATE, 5s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
|
||||
{
|
||||
if (!IntroOnce && me->IsWithinDistInMap(who, 30.0f))
|
||||
if (!_isDarkSpinStarted && me->HealthBelowPctDamaged(25, damage))
|
||||
{
|
||||
if (who->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Talk(SAY_INTRO);
|
||||
IntroOnce = true;
|
||||
IsIntroEvent = true;
|
||||
|
||||
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
|
||||
_isDarkSpinStarted = true;
|
||||
events.ScheduleEvent(EVENT_DARK_SPIN, 0s);
|
||||
}
|
||||
|
||||
if (IsIntroEvent || !IsMainEvent)
|
||||
return;
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
//triggered spell of consumption does not properly show it's SpellVisual, wrong spellid?
|
||||
summoned->CastSpell(summoned, SPELL_TEMPORARY_VISUAL, true);
|
||||
summoned->CastSpell(summoned, SPELL_CONSUMPTION, CastSpellExtraArgs().SetOriginalCaster(me->GetGUID()));
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
@@ -212,152 +218,292 @@ struct boss_grand_warlock_nethekurse : public BossAI
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (IsIntroEvent)
|
||||
{
|
||||
if (instance->GetBossState(DATA_NETHEKURSE) == IN_PROGRESS)
|
||||
{
|
||||
if (IntroEvent_Timer <= diff)
|
||||
DoTauntPeons();
|
||||
else
|
||||
IntroEvent_Timer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (!IsMainEvent)
|
||||
return;
|
||||
|
||||
if (Phase)
|
||||
{
|
||||
if (!SpinOnce)
|
||||
{
|
||||
DoCastVictim(SPELL_DARK_SPIN);
|
||||
SpinOnce = true;
|
||||
}
|
||||
|
||||
if (Cleave_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SHADOW_CLEAVE);
|
||||
Cleave_Timer = 6000 + rand32() % 2500;
|
||||
}
|
||||
else
|
||||
Cleave_Timer -= diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ShadowFissure_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
DoCast(target, SPELL_SHADOW_FISSURE);
|
||||
ShadowFissure_Timer = urand(7500, 15000);
|
||||
}
|
||||
else
|
||||
ShadowFissure_Timer -= diff;
|
||||
|
||||
if (DeathCoil_Timer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0))
|
||||
DoCast(target, SPELL_DEATH_COIL);
|
||||
DeathCoil_Timer = urand(15000, 20000);
|
||||
}
|
||||
else
|
||||
DeathCoil_Timer -= diff;
|
||||
|
||||
if (!HealthAbovePct(20))
|
||||
Phase = true;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 PeonEngagedCount;
|
||||
uint32 PeonKilledCount;
|
||||
uint32 IntroEvent_Timer;
|
||||
uint32 DeathCoil_Timer;
|
||||
uint32 ShadowFissure_Timer;
|
||||
uint32 Cleave_Timer;
|
||||
bool IntroOnce;
|
||||
bool IsIntroEvent;
|
||||
bool IsMainEvent;
|
||||
bool SpinOnce;
|
||||
//bool HasTaunted;
|
||||
bool Phase;
|
||||
};
|
||||
|
||||
// ########################################################
|
||||
// Fel Orc Convert
|
||||
// ########################################################
|
||||
|
||||
struct npc_fel_orc_convert : public ScriptedAI
|
||||
{
|
||||
npc_fel_orc_convert(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!)
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_HEMORRHAGE, 3s);
|
||||
|
||||
if (Creature* Kurse = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GRAND_WARLOCK_NETHEKURSE)))
|
||||
if (me->IsWithinDist(Kurse, 45.0f))
|
||||
Kurse->AI()->SetData(SETDATA_DATA, SETDATA_PEON_AGGRO);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (instance->GetBossState(DATA_NETHEKURSE) != IN_PROGRESS)
|
||||
return;
|
||||
_JustDied();
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
|
||||
if (Creature* Kurse = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GRAND_WARLOCK_NETHEKURSE)))
|
||||
Kurse->AI()->SetData(SETDATA_DATA, SETDATA_PEON_DEATH);
|
||||
void UpdateOutOfCombatEvents(uint32 diff)
|
||||
{
|
||||
events.Update(diff);
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
// ... intro event starts every time player enters area trigger
|
||||
case EVENT_TAUNT_PEONS:
|
||||
{
|
||||
switch (urand(0, 2))
|
||||
{
|
||||
case 0:
|
||||
// This one targets two (?) peons
|
||||
Talk(SAY_TAUNT_SHADOW_SEAR);
|
||||
DoCastSelf(SPELL_PEON_SHADOW_SEAR, { SPELLVALUE_MAX_TARGETS, 2 });
|
||||
break;
|
||||
case 1:
|
||||
// This one targets all four peons
|
||||
Talk(SAY_TAUNT_DEATH_COIL);
|
||||
DoCastSelf(SPELL_PEON_DEATH_COIL);
|
||||
break;
|
||||
case 2:
|
||||
// This one targets one peon
|
||||
Talk(SAY_TAUNT_SHADOW_FISSURE);
|
||||
DoCastSelf(SPELL_PEON_TARGET_FISSURES);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// ... cancel copies of event every time it is scheduled, then schedule new to repeat it, only one should be active
|
||||
events.CancelEvent(EVENT_TAUNT_PEONS);
|
||||
if (_peonKilledCount != MAX_KILLED_PEONS)
|
||||
events.ScheduleEvent(EVENT_TAUNT_PEONS, 25s, 35s);
|
||||
break;
|
||||
}
|
||||
case EVENT_INTERNAL_COOLDOWN:
|
||||
_isEventOnCooldown = false;
|
||||
break;
|
||||
case EVENT_CLEAR_EMOTE_STATE:
|
||||
me->SetEmoteState(EMOTE_ONESHOT_NONE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
{
|
||||
UpdateOutOfCombatEvents(diff);
|
||||
return;
|
||||
}
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (events.ExecuteEvent() == EVENT_HEMORRHAGE)
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
DoCastVictim(SPELL_HEMORRHAGE);
|
||||
events.ScheduleEvent(EVENT_HEMORRHAGE, 15s);
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SHADOW_FISSURE:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
|
||||
DoCast(target, SPELL_SHADOW_FISSURE);
|
||||
events.Repeat(8s);
|
||||
break;
|
||||
case EVENT_DEATH_COIL:
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random))
|
||||
DoCast(target, SPELL_DEATH_COIL);
|
||||
events.Repeat(10s, 20s);
|
||||
break;
|
||||
case EVENT_SHADOW_CLEAVE:
|
||||
DoCastVictim(SPELL_SHADOW_CLEAVE);
|
||||
events.Repeat(15s, 20s);
|
||||
break;
|
||||
case EVENT_SHADOW_SLAM:
|
||||
DoCastVictim(SPELL_SHADOW_SLAM);
|
||||
events.Repeat(15s, 20s);
|
||||
break;
|
||||
case EVENT_DARK_SPIN:
|
||||
DoCastSelf(SPELL_DARK_SPIN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
EventMap events;
|
||||
private:
|
||||
uint32 _peonKilledCount;
|
||||
bool _isEventOnCooldown;
|
||||
bool _isDarkSpinStarted;
|
||||
};
|
||||
|
||||
// ########################################################
|
||||
// Lesser Shadow Fissure
|
||||
// ########################################################
|
||||
// 17083 - Fel Orc Convert
|
||||
struct npc_fel_orc_convert : public ScriptedAI
|
||||
{
|
||||
npc_fel_orc_convert(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_scheduler.CancelAll();
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
if (roll_chance_i(15))
|
||||
Talk(SAY_PEON_AGGRO);
|
||||
|
||||
_scheduler.Schedule(5s, 10s, [this](TaskContext task)
|
||||
{
|
||||
DoCastVictim(SPELL_HEMORRHAGE);
|
||||
task.Repeat(5s, 10s);
|
||||
});
|
||||
|
||||
if (!me->HasStringId("FelOrcConvertNethekurseEvent"))
|
||||
return;
|
||||
|
||||
if (Creature* nethekurse = _instance->GetCreature(DATA_NETHEKURSE))
|
||||
nethekurse->AI()->DoAction(ACTION_PEON_ENGAGED);
|
||||
}
|
||||
|
||||
void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
|
||||
{
|
||||
// Not sure if these are grouped correctly, based on few sniffs
|
||||
// By the way, language is correct, verified, not a typo
|
||||
// Text 14143 seems to be unused, not added here
|
||||
switch (spellInfo->Id)
|
||||
{
|
||||
case SPELL_PEON_SHADOW_SEAR:
|
||||
if (roll_chance_i(30))
|
||||
Talk(SAY_PEON_SHADOW_SEAR);
|
||||
break;
|
||||
case SPELL_PEON_DEATH_COIL:
|
||||
if (roll_chance_i(30))
|
||||
{
|
||||
Talk(SAY_PEON_DEATH_COIL);
|
||||
DoPlaySoundToSet(me, SOUND_ID_ROAR);
|
||||
}
|
||||
break;
|
||||
case SPELL_PEON_TARGET_FISSURES:
|
||||
if (roll_chance_i(30))
|
||||
Talk(SAY_PEON_SHADOW_FISSURE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (!me->HasStringId("FelOrcConvertNethekurseEvent"))
|
||||
return;
|
||||
|
||||
if (Creature* nethekurse = _instance->GetCreature(DATA_NETHEKURSE))
|
||||
nethekurse->AI()->DoAction(ACTION_PEON_KILLED);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
_scheduler.Update(diff, [this]
|
||||
{
|
||||
DoMeleeAttackIfReady();
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
TaskScheduler _scheduler;
|
||||
};
|
||||
|
||||
// 17471 - Lesser Shadow Fissure
|
||||
struct npc_lesser_shadow_fissure : public ScriptedAI
|
||||
{
|
||||
npc_lesser_shadow_fissure(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void Reset() override { }
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
void AttackStart(Unit* /*who*/) override { }
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
void InitializeAI() override
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCastSelf(IsHeroic() ? SPELL_CONSUMPTION_H : SPELL_CONSUMPTION);
|
||||
}
|
||||
};
|
||||
|
||||
// 18370 - Wild Shadow Fissure
|
||||
struct npc_wild_shadow_fissure : public ScriptedAI
|
||||
{
|
||||
npc_wild_shadow_fissure(Creature* creature) : ScriptedAI(creature) { }
|
||||
|
||||
void InitializeAI() override
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
}
|
||||
|
||||
void JustAppeared() override
|
||||
{
|
||||
DoCastSelf(SPELL_CONSUMPTION_WILD);
|
||||
}
|
||||
};
|
||||
|
||||
// 182539 - Grand Warlock Chamber Door
|
||||
struct go_grand_warlock_chamber_door : public GameObjectAI
|
||||
{
|
||||
go_grand_warlock_chamber_door(GameObject* go) : GameObjectAI(go), _instance(go->GetInstanceScript()) { }
|
||||
|
||||
bool OnGossipHello(Player* /*player*/) override
|
||||
{
|
||||
if (Creature* nethekurse = _instance->GetCreature(DATA_NETHEKURSE))
|
||||
nethekurse->AI()->DoAction(ACTION_START_INTRO);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
// 30745 - Target Fissures
|
||||
class spell_grand_warlock_nethekurse_target_fissures : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_grand_warlock_nethekurse_target_fissures);
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_SHADOW_FISSURE_2 });
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
return;
|
||||
|
||||
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
|
||||
targets.clear();
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
void HandleScript(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
GetCaster()->CastSpell(GetHitUnit(), SPELL_SHADOW_FISSURE_2);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_grand_warlock_nethekurse_target_fissures::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_grand_warlock_nethekurse_target_fissures::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
// 4347
|
||||
class at_shattered_halls_the_sewer : public AreaTriggerScript
|
||||
{
|
||||
public:
|
||||
at_shattered_halls_the_sewer() : AreaTriggerScript("at_shattered_halls_the_sewer") { }
|
||||
|
||||
bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
|
||||
{
|
||||
if (InstanceScript* instance = player->GetInstanceScript())
|
||||
if (Creature* nethekurse = instance->GetCreature(DATA_NETHEKURSE))
|
||||
nethekurse->AI()->DoAction(ACTION_START_INTRO);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_grand_warlock_nethekurse()
|
||||
@@ -365,4 +511,8 @@ void AddSC_boss_grand_warlock_nethekurse()
|
||||
RegisterShatteredHallsCreatureAI(boss_grand_warlock_nethekurse);
|
||||
RegisterShatteredHallsCreatureAI(npc_fel_orc_convert);
|
||||
RegisterShatteredHallsCreatureAI(npc_lesser_shadow_fissure);
|
||||
RegisterShatteredHallsCreatureAI(npc_wild_shadow_fissure);
|
||||
RegisterShatteredHallsGameObjectAI(go_grand_warlock_chamber_door);
|
||||
RegisterSpellScript(spell_grand_warlock_nethekurse_target_fissures);
|
||||
new at_shattered_halls_the_sewer();
|
||||
}
|
||||
|
||||
@@ -42,9 +42,10 @@ DoorData const doorData[] =
|
||||
|
||||
ObjectData const creatureData[] =
|
||||
{
|
||||
{ NPC_LEFT_HEAD, DATA_LEFT_HEAD },
|
||||
{ NPC_RIGHT_HEAD, DATA_RIGHT_HEAD },
|
||||
{ 0, 0 } // END
|
||||
{ NPC_GRAND_WARLOCK_NETHEKURSE, DATA_NETHEKURSE },
|
||||
{ NPC_LEFT_HEAD, DATA_LEFT_HEAD },
|
||||
{ NPC_RIGHT_HEAD, DATA_RIGHT_HEAD },
|
||||
{ 0, 0 } // END
|
||||
};
|
||||
|
||||
class instance_shattered_halls : public InstanceMapScript
|
||||
@@ -115,9 +116,6 @@ class instance_shattered_halls : public InstanceMapScript
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_GRAND_WARLOCK_NETHEKURSE:
|
||||
nethekurseGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_KARGATH_BLADEFIST:
|
||||
kargathGUID = creature->GetGUID();
|
||||
break;
|
||||
@@ -181,8 +179,6 @@ class instance_shattered_halls : public InstanceMapScript
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case NPC_GRAND_WARLOCK_NETHEKURSE:
|
||||
return nethekurseGUID;
|
||||
case NPC_KARGATH_BLADEFIST:
|
||||
return kargathGUID;
|
||||
case NPC_SHATTERED_EXECUTIONER:
|
||||
@@ -285,7 +281,6 @@ class instance_shattered_halls : public InstanceMapScript
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid nethekurseGUID;
|
||||
ObjectGuid kargathGUID;
|
||||
ObjectGuid executionerGUID;
|
||||
ObjectGuid victimsGUID[3];
|
||||
|
||||
@@ -128,5 +128,6 @@ inline AI* GetShatteredHallsAI(T* obj)
|
||||
}
|
||||
|
||||
#define RegisterShatteredHallsCreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetShatteredHallsAI)
|
||||
#define RegisterShatteredHallsGameObjectAI(ai_name) RegisterGameObjectAIWithFactory(ai_name, GetShatteredHallsAI)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user