fix(Scripts/ShatteredHalls): Rework Nethekurse (#16265)

This commit is contained in:
Skjalf
2023-05-21 18:11:31 -03:00
committed by GitHub
parent 0637170c30
commit 6a73c38eb6
4 changed files with 169 additions and 250 deletions

View File

@@ -0,0 +1,44 @@
--
SET @NPC := 151089 * 10;
DELETE FROM `waypoint_data` WHERE `id` = @NPC;
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`) VALUES
(@NPC, 1, 184.78966, 290.3699, -8.18139, 0),
(@NPC, 2, 178.51125, 287.97794, -8.183065, 0),
(@NPC, 3, 171.82281, 289.97687, -8.185595, 0),
(@NPC, 4, 178.51125, 287.97794, -8.183065, 0);
UPDATE `creature` SET `MovementType` = 2 WHERE `ID1` IN (16807, 20568);
DELETE FROM `creature_template_addon` WHERE `entry` IN (16807, 20568);
INSERT INTO `creature_template_addon` (`entry`, `path_id`) VALUES
(16807, @NPC),
(20568, @NPC);
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 17083) AND (`source_type` = 0) AND (`id` IN (1, 2, 3));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(17083, 0, 2, 0, 4, 0, 100, 512, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 16807, 50, 0, 0, 0, 0, 0, 0, 'Fel Orc Convert - On Aggro - Set Data 1 1'),
(17083, 0, 3, 0, 6, 0, 100, 512, 0, 0, 0, 0, 0, 45, 1, 2, 0, 0, 0, 0, 19, 16807, 50, 0, 0, 0, 0, 0, 0, 'Fel Orc Convert - On Just Died - Set Data 1 2');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceGroup` = 3) AND (`SourceEntry` = 17083) AND (`SourceId` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(22, 3, 17083, 0, 0, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Only play SAI Event if Invoker is a Player');
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_tsh_shadow_sear';
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 3) AND (`SourceEntry` = 30741);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 3, 30741, 0, 0, 31, 0, 3, 17083, 151090, 0, 0, 0, '', 'Death Coil (30741) can only target Fel Orc Convert (17083) of specific guids'),
(13, 3, 30741, 0, 1, 31, 0, 3, 17083, 151091, 0, 0, 0, '', 'Death Coil (30741) can only target Fel Orc Convert (17083) of specific guids'),
(13, 3, 30741, 0, 2, 31, 0, 3, 17083, 151092, 0, 0, 0, '', 'Death Coil (30741) can only target Fel Orc Convert (17083) of specific guids'),
(13, 3, 30741, 0, 3, 31, 0, 3, 17083, 151093, 0, 0, 0, '', 'Death Coil (30741) can only target Fel Orc Convert (17083) of specific guids');
DELETE FROM `spell_script_names` WHERE `spell_id` = 30745;
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(30745, 'spell_target_fissures');
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 3) AND (`SourceEntry` = 30745);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 30745, 0, 0, 31, 0, 3, 17083, 151090, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'),
(13, 1, 30745, 0, 1, 31, 0, 3, 17083, 151091, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'),
(13, 1, 30745, 0, 2, 31, 0, 3, 17083, 151092, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids'),
(13, 1, 30745, 0, 3, 31, 0, 3, 17083, 151093, 0, 0, 0, '', 'Target Fissures (30745) can only target Fel Orc Convert (17083) of specific guids');

View File

@@ -4528,6 +4528,12 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].MiscValue = 224;
});
// Target Fissures
ApplySpellFix({ 30745 }, [](SpellInfo* spellInfo)
{
spellInfo->MaxAffectedTargets = 1;
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];

View File

@@ -20,29 +20,30 @@
#include "ScriptedCreature.h"
#include "shattered_halls.h"
enum Says
enum Texts
{
SAY_INTRO = 0,
SAY_INTRO_2 = 1,
SAY_PEON_ATTACKED = 2,
SAY_PEON_DIES = 3,
SAY_SHADOW_SEAR = 4,
SAY_SHADOW_FISSURE = 5,
SAY_DEATH_COIL = 6,
SAY_SLAY = 7,
SAY_DIE = 8
SAY_SKIP_INTRO = 0,
SAY_INTRO_2 = 1,
SAY_PEON_ATTACKED = 2,
SAY_PEON_DIES = 3,
SAY_SHADOW_SEAR = 4,
SAY_SHADOW_FISSURE = 5,
SAY_DEATH_COIL = 6,
SAY_SLAY = 7,
SAY_DIE = 8
};
enum Spells
{
SPELL_DEATH_COIL = 30500,
SPELL_DARK_SPIN = 30502,
SPELL_SHADOW_FISSURE = 30496,
SPELL_SHADOW_CLEAVE = 30495,
SPELL_DEATH_COIL = 30500,
SPELL_DARK_SPIN = 30502,
SPELL_SHADOW_FISSURE = 30496,
SPELL_SHADOW_CLEAVE = 30495,
SPELL_SHADOW_SEAR = 30735,
SPELL_DEATH_COIL_RP = 30741,
SPELL_SHADOW_FISSURE_RP = 30745
SPELL_SHADOW_SEAR = 30735,
SPELL_DEATH_COIL_RP = 30741,
SPELL_SHADOW_FISSURE_RP = 30745,
SPELL_LESSER_SHADOW_FISSURE = 30744
};
enum Events
@@ -75,12 +76,22 @@ enum Actions
ACTION_START_COMBAT = 2,
};
float NethekurseIntroPath[4][3] =
enum Creatures
{
{184.78966f, 290.3699f, -8.18139f},
{178.51125f, 278.779022f, -8.183065f},
{171.82281f, 289.97687f, -8.185595f},
{178.51125f, 287.97794f, -8.183065f}
NPC_PEON = 17083
};
struct PeonRoleplay
{
uint32 spellId;
uint8 textId;
};
PeonRoleplay PeonRoleplayData[3] =
{
{ SPELL_DEATH_COIL_RP, SAY_DEATH_COIL },
{ SPELL_SHADOW_FISSURE_RP, SAY_SHADOW_FISSURE },
{ SPELL_SHADOW_SEAR, SAY_SHADOW_SEAR }
};
struct boss_grand_warlock_nethekurse : public BossAI
@@ -93,16 +104,13 @@ struct boss_grand_warlock_nethekurse : public BossAI
});
}
EventMap events2;
void Reset() override
{
EventStage = EVENT_STAGE_NONE;
_Reset();
events2.Reset();
ScheduleHealthCheckEvent(25, [&] {
DoCastSelf(SPELL_DARK_SPIN);
});
instance->SetBossState(DATA_NETHEKURSE, NOT_STARTED);
}
void JustDied(Unit* /*killer*/) override
@@ -116,58 +124,69 @@ struct boss_grand_warlock_nethekurse : public BossAI
if (data != SETDATA_DATA)
return;
switch (value)
if (value == SETDATA_PEON_AGGRO && PeonEngagedCount <= 4)
{
case SETDATA_PEON_AGGRO:
if (PeonEngagedCount >= 4)
return;
Talk(SAY_PEON_ATTACKED);
}
else if (value == SETDATA_PEON_DEATH && PeonKilledCount <= 4)
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->SetFacingTo(4.572762489318847656f);
if (EventStage < EVENT_STAGE_TAUNT)
{
Talk(SAY_PEON_ATTACKED);
}
break;
case SETDATA_PEON_DEATH:
if (PeonKilledCount >= 4)
return;
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD);
me->GetMotionMaster()->Initialize();
Talk(SAY_PEON_DIES);
if (EventStage < EVENT_STAGE_TAUNT)
{
PeonDieRP();
}
if (++PeonKilledCount == 4)
{
Talk(SAY_INTRO_2);
DoAction(ACTION_CANCEL_INTRO);
if (Unit* target = me->SelectNearestPlayer(80.0f))
{
AttackStart(target);
}
}
break;
});
}
}
void PeonDieRP()
void IntroRP()
{
me->GetMotionMaster()->Clear();
me->SetFacingTo(4.572762489318847656f);
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext context)
{
me->HandleEmoteCommand(EMOTE_ONESHOT_APPLAUD);
Talk(SAY_PEON_DIES);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle();
me->SetFacingTo(4.572762489318847656f);
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
scheduler.Schedule(2500ms, GROUP_RP, [this](TaskContext /*context*/)
{
PeonRoleplay roleplayData = Acore::Containers::SelectRandomContainerElement(PeonRoleplayData);
DoCast(me, roleplayData.spellId);
Talk(roleplayData.textId);
me->GetMotionMaster()->Initialize();
});
});
context.Repeat(16400ms, 28500ms);
});
}
void AttackStart(Unit* who) override
void JustEngagedWith(Unit* who) override
{
if (EventStage < EVENT_STAGE_MAIN)
return;
if (me->Attack(who, true))
if (who->GetEntry() == NPC_PEON)
{
DoStartMovement(who);
CombatEventScheduler();
return;
}
}
void CombatEventScheduler()
{
_JustEngagedWith();
DoAction(ACTION_CANCEL_INTRO);
scheduler.CancelAll();
scheduler.Schedule(12150ms, 19850ms, [this](TaskContext context)
{
if (me->HealthBelowPct(90))
@@ -184,64 +203,10 @@ struct boss_grand_warlock_nethekurse : public BossAI
DoCastVictim(SPELL_SHADOW_CLEAVE);
context.Repeat(1200ms, 23900ms);
});
}
void MoveInLineOfSight(Unit* /*who*/) override
{
if (EventStage == EVENT_STAGE_NONE)
if (PeonKilledCount < 4)
{
if (me->SelectNearestPlayer(30.0f))
{
DoAction(ACTION_CANCEL_INTRO);
}
}
}
void IntroRP()
{
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext context)
{
me->GetMotionMaster()->Clear();
scheduler.Schedule(500ms, GROUP_RP, [this](TaskContext /*context*/)
{
uint32 choicelocation = urand(1, 3);
me->GetMotionMaster()->MoveIdle();
me->GetMotionMaster()->MovePoint(0, NethekurseIntroPath[choicelocation][0], NethekurseIntroPath[choicelocation][1], NethekurseIntroPath[choicelocation][2]);
scheduler.Schedule(2500ms, GROUP_RP, [this, choicelocation](TaskContext /*context*/)
{
CastRandomPeonSpell(choicelocation);
});
});
context.Repeat(16400ms, 28500ms);
});
}
void JustEngagedWith(Unit* /*who*/) override
{
_JustEngagedWith();
if (EventStage == EVENT_STAGE_NONE)
{
DoAction(ACTION_CANCEL_INTRO);
CombatEventScheduler();
}
}
void CastRandomPeonSpell(uint32 choice)
{
if (choice == 1)
{
Talk(SAY_DEATH_COIL);
me->CastSpell(me, SPELL_DEATH_COIL_RP, false);
}
else if (choice == 2)
{
Talk(SAY_SHADOW_FISSURE);
me->CastSpell(me, SPELL_SHADOW_FISSURE_RP, false);
}
else if (choice == 3)
{
Talk(SAY_SHADOW_SEAR);
me->CastSpell(me, SPELL_SHADOW_SEAR, false);
Talk(SAY_SKIP_INTRO);
}
}
@@ -254,60 +219,24 @@ struct boss_grand_warlock_nethekurse : public BossAI
{
if (action == ACTION_CANCEL_INTRO)
{
introDone = true;
scheduler.CancelGroup(GROUP_RP);
events2.ScheduleEvent(EVENT_START_ATTACK, 1000);
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
me->SetInCombatWithZone();
Talk(SAY_INTRO_2);
me->SetHomePosition(NethekurseIntroPath[3][0], NethekurseIntroPath[3][1], NethekurseIntroPath[3][2], 4.572762489318847656f);
me->RemoveUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
return;
}
if (action != ACTION_START_INTRO)
return;
if (ATreached == true)
return;
ATreached = true;
me->SetUnitFlag(UNIT_FLAG_NOT_ATTACKABLE_1);
events2.ScheduleEvent(EVENT_INTRO, 90000);
Talk(SAY_INTRO);
EventStage = EVENT_STAGE_INTRO;
instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
me->SetInCombatWithZone();
IntroRP();
else if (action == ACTION_START_INTRO)
{
IntroRP();
}
}
void UpdateAI(uint32 diff) override
{
events2.Update(diff);
scheduler.Update(diff);
uint32 eventId = events2.ExecuteEvent();
if (EventStage < EVENT_STAGE_MAIN && instance->GetBossState(DATA_NETHEKURSE) == IN_PROGRESS)
{
if (eventId == EVENT_INTRO)
{
EventStage = EVENT_STAGE_TAUNT;
}
else if (eventId == EVENT_START_ATTACK)
{
EventStage = EVENT_STAGE_MAIN;
if (Unit* target = me->SelectNearestPlayer(50.0f))
{
AttackStart(target);
}
DoAction(ACTION_CANCEL_INTRO);
return;
}
}
if (!UpdateVictim())
return;
if (EventStage < EVENT_STAGE_MAIN || me->HasUnitState(UNIT_STATE_CASTING))
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->HealthBelowPct(25))
@@ -317,24 +246,6 @@ struct boss_grand_warlock_nethekurse : public BossAI
private:
uint8 PeonEngagedCount = 0;
uint8 PeonKilledCount = 0;
uint8 EventStage;
bool introDone;
bool ATreached = false;
};
class spell_tsh_shadow_sear : public AuraScript
{
PrepareAuraScript(spell_tsh_shadow_sear);
void CalculateDamageAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
amount = 0;
}
void Register() override
{
DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_tsh_shadow_sear::CalculateDamageAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
class spell_tsh_shadow_bolt : public SpellScript
@@ -345,22 +256,9 @@ class spell_tsh_shadow_bolt : public SpellScript
{
if (Creature* caster = GetCaster()->ToCreature())
{
std::list<Player*> playerList;
Map::PlayerList const& players = caster->GetMap()->GetPlayers();
for (auto itr = players.begin(); itr != players.end(); ++itr)
if (Unit* randomTarget = caster->AI()->SelectTarget(SelectTargetMethod::Random, 0, 100.0f))
{
if (Player* player = itr->GetSource()->ToPlayer())
{
if (player->IsWithinDist(caster, 100.0f) && player->IsAlive())
{
playerList.push_back(player);
}
}
}
if (!playerList.empty())
{
target = Acore::Containers::SelectRandomContainerElement(playerList);
target = randomTarget;
}
}
}
@@ -371,17 +269,28 @@ class spell_tsh_shadow_bolt : public SpellScript
}
};
class at_rp_nethekurse : public AreaTriggerScript
class spell_target_fissures : public SpellScript
{
PrepareSpellScript(spell_target_fissures);
void HandleEffect(SpellEffIndex /*effIndex*/)
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_LESSER_SHADOW_FISSURE, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_target_fissures::HandleEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
class at_rp_nethekurse : public OnlyOnceAreaTriggerScript
{
public:
at_rp_nethekurse() : AreaTriggerScript("at_rp_nethekurse") { }
at_rp_nethekurse() : OnlyOnceAreaTriggerScript("at_rp_nethekurse") { }
bool OnTrigger(Player* player, AreaTrigger const* /*at*/) override
bool _OnTrigger(Player* player, AreaTrigger const* /*at*/) override
{
if (player->IsGameMaster())
{
return false;
}
if (InstanceScript* instance = player->GetInstanceScript())
{
if (instance->GetBossState(DATA_NETHEKURSE) != DONE && instance->GetBossState(DATA_NETHEKURSE) != IN_PROGRESS)
@@ -399,7 +308,7 @@ public:
void AddSC_boss_grand_warlock_nethekurse()
{
RegisterShatteredHallsCreatureAI(boss_grand_warlock_nethekurse);
RegisterSpellScript(spell_tsh_shadow_sear);
RegisterSpellScript(spell_tsh_shadow_bolt);
RegisterSpellScript(spell_target_fissures);
new at_rp_nethekurse();
}

View File

@@ -22,9 +22,16 @@
ObjectData const creatureData[] =
{
{ NPC_GRAND_WARLOCK_NETHEKURSE , DATA_NETHEKURSE },
{ NPC_WARCHIEF_KARGATH , DATA_KARGATH },
{ 0, 0 }
{ NPC_GRAND_WARLOCK_NETHEKURSE, DATA_NETHEKURSE },
{ NPC_WARCHIEF_KARGATH, DATA_KARGATH },
{ 0, 0 }
};
DoorData const doorData[] =
{
{ GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE },
{ GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE },
{ 0, 0, DOOR_TYPE_ROOM } // END
};
class instance_shattered_halls : public InstanceMapScript
@@ -45,6 +52,7 @@ public:
{
SetBossNumber(ENCOUNTER_COUNT);
LoadObjectData(creatureData, nullptr);
LoadDoorData(doorData);
TeamIdInInstance = TEAM_NEUTRAL;
RescueTimer = 100 * MINUTE * IN_MILLISECONDS;
@@ -56,23 +64,6 @@ public:
TeamIdInInstance = player->GetTeamId();
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_GRAND_WARLOCK_CHAMBER_DOOR_1:
nethekurseDoor1GUID = go->GetGUID();
if (GetBossState(DATA_NETHEKURSE) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_GRAND_WARLOCK_CHAMBER_DOOR_2:
nethekurseDoor2GUID = go->GetGUID();
if (GetBossState(DATA_NETHEKURSE) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
}
}
void OnCreatureCreate(Creature* creature) override
{
if (TeamIdInInstance == TEAM_NEUTRAL)
@@ -85,9 +76,6 @@ public:
switch (creature->GetEntry())
{
case NPC_WARCHIEF_KARGATH:
warchiefKargathGUID = creature->GetGUID();
break;
case NPC_SHATTERED_EXECUTIONER:
if (RescueTimer > 25 * MINUTE * IN_MILLISECONDS)
creature->AddLootMode(2);
@@ -112,29 +100,6 @@ public:
InstanceScript::OnCreatureCreate(creature);
}
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
switch (type)
{
case DATA_NETHEKURSE:
if (state == IN_PROGRESS)
{
HandleGameObject(nethekurseDoor1GUID, false);
HandleGameObject(nethekurseDoor2GUID, false);
}
else
{
HandleGameObject(nethekurseDoor1GUID, true);
HandleGameObject(nethekurseDoor2GUID, true);
}
break;
}
return true;
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_ENTERED_ROOM && data == DATA_ENTERED_ROOM && RescueTimer == 100 * MINUTE * IN_MILLISECONDS)
@@ -142,7 +107,7 @@ public:
DoCastSpellOnPlayers(SPELL_KARGATHS_EXECUTIONER_1);
instance->LoadGrid(230, -80);
if (Creature* kargath = instance->GetCreature(warchiefKargathGUID))
if (Creature* kargath = GetCreature(DATA_KARGATH))
sCreatureTextMgr->SendChat(kargath, TeamIdInInstance == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
RescueTimer = 80 * MINUTE * IN_MILLISECONDS;
@@ -206,11 +171,6 @@ public:
}
protected:
ObjectGuid warchiefKargathGUID;
ObjectGuid grandWarlockNethekurseGUID;
ObjectGuid nethekurseDoor1GUID;
ObjectGuid nethekurseDoor2GUID;
ObjectGuid executionerGUID;
ObjectGuid prisonerGUID[3];
uint32 RescueTimer;