mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-21 20:56:23 +00:00
Merge branch 'master' into Playerbot
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
|
||||
*
|
||||
* This file was based on
|
||||
* https://embeddedartistry.com/blog/2017/05/17/creating-a-circular-buffer-in-c-and-c/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Originally written by Rochet2 - Copyright (C) 2018+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Originally written by Rochet2 - Copyright (C) 2018+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: http://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
#ifndef _DATA_MAP_H_
|
||||
|
||||
@@ -2176,6 +2176,9 @@ void Player::SetInWater(bool apply)
|
||||
RemoveAurasWithInterruptFlags(apply ? AURA_INTERRUPT_FLAG_NOT_ABOVEWATER : AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
|
||||
|
||||
getHostileRefMgr().updateThreatTables();
|
||||
|
||||
if (InstanceScript* instance = GetInstanceScript())
|
||||
instance->OnPlayerInWaterStateUpdate(this, apply);
|
||||
}
|
||||
|
||||
bool Player::IsInAreaTriggerRadius(AreaTrigger const* trigger, float delta) const
|
||||
|
||||
@@ -436,31 +436,27 @@ void Player::UpdateNextMailTimeAndUnreads()
|
||||
{
|
||||
// Update the next delivery time and unread mails
|
||||
time_t cTime = GameTime::GetGameTime().count();
|
||||
// Get the next delivery time
|
||||
CharacterDatabasePreparedStatement* stmtNextDeliveryTime =
|
||||
CharacterDatabase.GetPreparedStatement(CHAR_SEL_NEXT_MAIL_DELIVERYTIME);
|
||||
stmtNextDeliveryTime->SetData(0, GetGUID().GetCounter());
|
||||
stmtNextDeliveryTime->SetData(1, uint32(cTime));
|
||||
PreparedQueryResult resultNextDeliveryTime =
|
||||
CharacterDatabase.Query(stmtNextDeliveryTime);
|
||||
if (resultNextDeliveryTime)
|
||||
{
|
||||
Field* fields = resultNextDeliveryTime->Fetch();
|
||||
m_nextMailDelivereTime = time_t(fields[0].Get<uint32>());
|
||||
}
|
||||
|
||||
// Get unread mails count
|
||||
CharacterDatabasePreparedStatement* stmtUnreadAmount =
|
||||
CharacterDatabase.GetPreparedStatement(
|
||||
CHAR_SEL_CHARACTER_MAILCOUNT_UNREAD_SYNCH);
|
||||
stmtUnreadAmount->SetData(0, GetGUID().GetCounter());
|
||||
stmtUnreadAmount->SetData(1, uint32(cTime));
|
||||
PreparedQueryResult resultUnreadAmount =
|
||||
CharacterDatabase.Query(stmtUnreadAmount);
|
||||
if (resultUnreadAmount)
|
||||
m_nextMailDelivereTime = 0;
|
||||
unReadMails = 0;
|
||||
|
||||
for (Mail const* mail : GetMails())
|
||||
{
|
||||
Field* fields = resultUnreadAmount->Fetch();
|
||||
unReadMails = uint8(fields[0].Get<uint64>());
|
||||
if (mail->deliver_time > cTime)
|
||||
{
|
||||
if (!m_nextMailDelivereTime || m_nextMailDelivereTime > mail->deliver_time)
|
||||
m_nextMailDelivereTime = mail->deliver_time;
|
||||
}
|
||||
|
||||
// must be not checked yet
|
||||
if (mail->checked & MAIL_CHECK_MASK_READ)
|
||||
continue;
|
||||
|
||||
// and already delivered or expired
|
||||
if (cTime < mail->deliver_time || cTime > mail->expire_time)
|
||||
continue;
|
||||
|
||||
unReadMails++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4223,7 +4223,7 @@ void Unit::ProcessTerrainStatusUpdate()
|
||||
// remove appropriate auras if we are swimming/not swimming respectively
|
||||
if (liquidData.Status & MAP_LIQUID_STATUS_SWIMMING)
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_ABOVEWATER);
|
||||
else
|
||||
else if (!isSwimming())
|
||||
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_UNDERWATER);
|
||||
|
||||
// liquid aura handling
|
||||
|
||||
@@ -287,10 +287,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
|
||||
case COMMAND_ABANDON: // abandon (hunter pet) or dismiss (summoned pet)
|
||||
if (pet->GetCharmerGUID() == GetPlayer()->GetGUID())
|
||||
{
|
||||
if (pet->IsSummon())
|
||||
pet->ToTempSummon()->UnSummon();
|
||||
else
|
||||
_player->StopCastingCharm();
|
||||
_player->StopCastingCharm();
|
||||
}
|
||||
else if (pet->GetOwnerGUID() == GetPlayer()->GetGUID())
|
||||
{
|
||||
|
||||
@@ -186,6 +186,9 @@ public:
|
||||
|
||||
virtual void OnPlayerAreaUpdate(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) {}
|
||||
|
||||
//Called when a player enters/leaves water bodies.
|
||||
virtual void OnPlayerInWaterStateUpdate(Player* /*player*/, bool /*inWater*/) {}
|
||||
|
||||
//Handle open / close objects
|
||||
//use HandleGameObject(ObjectGuid::Empty, boolen, GO); in OnObjectCreate in instance scripts
|
||||
//use HandleGameObject(GUID, boolen, nullptr); in any other script
|
||||
|
||||
@@ -110,3 +110,21 @@ bool BoundaryUnionBoundary::IsWithinBoundaryArea(Position const* pos) const
|
||||
{
|
||||
return (_b1->IsWithinBoundary(pos) || _b2->IsWithinBoundary(pos));
|
||||
}
|
||||
|
||||
// ---== INTERSECT OF 2 BOUNDARIES ==---
|
||||
BoundaryIntersectBoundary::BoundaryIntersectBoundary(AreaBoundary const* b1, AreaBoundary const* b2, bool isInverted) :
|
||||
AreaBoundary(isInverted), _b1(b1), _b2(b2)
|
||||
{
|
||||
ASSERT(b1 && b2);
|
||||
}
|
||||
|
||||
BoundaryIntersectBoundary::~BoundaryIntersectBoundary()
|
||||
{
|
||||
delete _b1;
|
||||
delete _b2;
|
||||
}
|
||||
|
||||
bool BoundaryIntersectBoundary::IsWithinBoundaryArea(Position const* pos) const
|
||||
{
|
||||
return (_b1->IsWithinBoundary(pos) && _b2->IsWithinBoundary(pos));
|
||||
}
|
||||
|
||||
@@ -165,4 +165,18 @@ class AC_GAME_API BoundaryUnionBoundary : public AreaBoundary
|
||||
AreaBoundary const* const _b2;
|
||||
};
|
||||
|
||||
class AC_GAME_API BoundaryIntersectBoundary : public AreaBoundary
|
||||
{
|
||||
public:
|
||||
BoundaryIntersectBoundary(AreaBoundary const* b1, AreaBoundary const* b2, bool isInverted = false);
|
||||
|
||||
protected:
|
||||
virtual ~BoundaryIntersectBoundary();
|
||||
bool IsWithinBoundaryArea(Position const* pos) const override;
|
||||
|
||||
private:
|
||||
AreaBoundary const* const _b1;
|
||||
AreaBoundary const* const _b2;
|
||||
};
|
||||
|
||||
#endif //ACORE_AREA_BOUNDARY_H
|
||||
|
||||
@@ -65,9 +65,8 @@ public:
|
||||
context.Repeat(10s, 15s);
|
||||
}).Schedule(25s, 32s, [this](TaskContext context)
|
||||
{
|
||||
if (DoCastRandomTarget(SPELL_SLEEP) == SPELL_CAST_OK)
|
||||
Talk(SAY_SLEEP);
|
||||
|
||||
Talk(SAY_SLEEP);
|
||||
DoCastRandomTarget(SPELL_SLEEP, 1, 0.0f, true, false, false);
|
||||
context.Repeat(35s, 48s);
|
||||
}).Schedule(30s, 48s, [this](TaskContext context)
|
||||
{
|
||||
@@ -137,7 +136,6 @@ public:
|
||||
|
||||
private:
|
||||
bool _recentlySpoken;
|
||||
|
||||
};
|
||||
|
||||
class spell_anetheron_sleep : public SpellScript
|
||||
|
||||
@@ -97,8 +97,9 @@ uint32 const availableChargeAurasAndSpells[3][2] = {
|
||||
|
||||
Position const nordrassilPosition = { 5503.713f, -3523.436f, 1608.781f, 0.0f };
|
||||
|
||||
float const DOOMFIRE_OFFSET = 15.0f;
|
||||
float const DOOMFIRE_OFFSET = 25.0f;
|
||||
uint8 const WISP_OFFSET = 40;
|
||||
uint8 NEAR_POINT = 0;
|
||||
|
||||
struct npc_ancient_wisp : public ScriptedAI
|
||||
{
|
||||
@@ -148,6 +149,39 @@ private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
struct npc_doomfire_spirit : public ScriptedAI
|
||||
{
|
||||
npc_doomfire_spirit(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
_instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
scheduler.CancelAll();
|
||||
ScheduleTimedEvent(0s, [&]{
|
||||
if (Creature* archimonde = _instance->GetCreature(DATA_ARCHIMONDE))
|
||||
{
|
||||
Position randomNearPosition = archimonde->GetRandomNearPosition(200.0f);
|
||||
me->GetMotionMaster()->MovePoint(NEAR_POINT, randomNearPosition);
|
||||
}
|
||||
}, 6s);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
}
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
};
|
||||
|
||||
struct boss_archimonde : public BossAI
|
||||
{
|
||||
boss_archimonde(Creature* creature) : BossAI(creature, DATA_ARCHIMONDE)
|
||||
@@ -262,10 +296,7 @@ struct boss_archimonde : public BossAI
|
||||
}, 25s, 40s);
|
||||
ScheduleTimedEvent(25s, 35s, [&]
|
||||
{
|
||||
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0.0f, true, false))
|
||||
{
|
||||
DoCastDoomFire(target);
|
||||
}
|
||||
DoCastDoomFire();
|
||||
}, 20s);
|
||||
ScheduleTimedEvent(25s, 35s, [&]
|
||||
{
|
||||
@@ -391,12 +422,12 @@ struct boss_archimonde : public BossAI
|
||||
}
|
||||
}
|
||||
|
||||
void DoCastDoomFire(Unit* target)
|
||||
void DoCastDoomFire()
|
||||
{
|
||||
// hack because spell doesn't work?
|
||||
Talk(SAY_DOOMFIRE);
|
||||
Position spiritPosition = { target->GetPositionX() + DOOMFIRE_OFFSET, target->GetPositionY() + DOOMFIRE_OFFSET, target->GetPositionZ(), 0.0f };
|
||||
Position doomfirePosition = { target->GetPositionX() - DOOMFIRE_OFFSET, target->GetPositionY() - DOOMFIRE_OFFSET, target->GetPositionZ(), 0.0f };
|
||||
Position spiritPosition = me->GetRandomNearPosition(DOOMFIRE_OFFSET);
|
||||
Position doomfirePosition = me->GetRandomNearPosition(DOOMFIRE_OFFSET);
|
||||
if (Creature* doomfireSpirit = me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, spiritPosition, TEMPSUMMON_TIMED_DESPAWN, 27000))
|
||||
{
|
||||
if (Creature* doomfire = me->SummonCreature(CREATURE_DOOMFIRE, doomfirePosition, TEMPSUMMON_TIMED_DESPAWN, 27000))
|
||||
@@ -508,5 +539,6 @@ void AddSC_boss_archimonde()
|
||||
RegisterSpellScript(spell_finger_of_death);
|
||||
RegisterHyjalAI(boss_archimonde);
|
||||
RegisterHyjalAI(npc_ancient_wisp);
|
||||
RegisterHyjalAI(npc_doomfire_spirit);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#include "CreatureScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "hyjal.h"
|
||||
|
||||
enum Spells
|
||||
@@ -60,7 +62,7 @@ public:
|
||||
context.Repeat(8s, 16s);
|
||||
}).Schedule(25s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_RAIN_OF_FIRE, 0, 40.f);
|
||||
DoCastRandomTarget(SPELL_RAIN_OF_FIRE, 0, 40.f, false);
|
||||
context.Repeat(15s);
|
||||
}).Schedule(30s, [this](TaskContext context)
|
||||
{
|
||||
@@ -68,7 +70,7 @@ public:
|
||||
context.Repeat(18s, 20s);
|
||||
}).Schedule(45s, 55s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_DOOM, 0, 100.f, true, false, false);
|
||||
DoCastRandomTarget(SPELL_DOOM, 1, 100.f, true, false, false);
|
||||
Talk(SAY_DOOM);
|
||||
context.Repeat();
|
||||
}).Schedule(10min, [this](TaskContext context)
|
||||
@@ -114,10 +116,29 @@ public:
|
||||
|
||||
private:
|
||||
bool _recentlySpoken;
|
||||
};
|
||||
|
||||
class spell_azgalor_doom : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_azgalor_doom);
|
||||
|
||||
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_DEATH && !IsExpired())
|
||||
{
|
||||
target->CastSpell(target, GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_azgalor_doom::OnRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_azgalor()
|
||||
{
|
||||
RegisterHyjalAI(boss_azgalor);
|
||||
RegisterSpellScript(spell_azgalor_doom);
|
||||
}
|
||||
|
||||
@@ -133,67 +133,51 @@ private:
|
||||
uint8 _markCounter;
|
||||
};
|
||||
|
||||
class spell_mark_of_kazrogal : public SpellScriptLoader
|
||||
class spell_mark_of_kazrogal : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_mark_of_kazrogal() : SpellScriptLoader("spell_mark_of_kazrogal") { }
|
||||
PrepareSpellScript(spell_mark_of_kazrogal);
|
||||
|
||||
class spell_mark_of_kazrogal_SpellScript : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
PrepareSpellScript(spell_mark_of_kazrogal_SpellScript);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
targets.remove_if(Acore::PowerCheck(POWER_MANA, false));
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_kazrogal_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mark_of_kazrogal_AuraScript : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_mark_of_kazrogal_AuraScript);
|
||||
|
||||
bool Validate(SpellInfo const* /*spell*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MARK_DAMAGE });
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if ((int32)target->GetPower(POWER_MANA) < aurEff->GetBaseAmount())
|
||||
{
|
||||
target->CastSpell(target, SPELL_MARK_DAMAGE, true, nullptr, aurEff);
|
||||
// Remove aura
|
||||
SetDuration(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazrogal_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_mark_of_kazrogal_SpellScript();
|
||||
targets.remove_if(Acore::PowerCheck(POWER_MANA, false));
|
||||
}
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
void Register() override
|
||||
{
|
||||
return new spell_mark_of_kazrogal_AuraScript();
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mark_of_kazrogal::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
class spell_mark_of_kazrogal_aura : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_mark_of_kazrogal_aura);
|
||||
|
||||
bool Validate(SpellInfo const* /*spell*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_MARK_DAMAGE });
|
||||
}
|
||||
|
||||
void OnPeriodic(AuraEffect const* aurEff)
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
|
||||
if ((int32)target->GetPower(POWER_MANA) < aurEff->GetBaseAmount())
|
||||
{
|
||||
target->CastSpell(target, SPELL_MARK_DAMAGE, true, nullptr, aurEff);
|
||||
// Remove aura
|
||||
SetDuration(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_kazrogal_aura::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_MANA_LEECH);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_kazrogal()
|
||||
{
|
||||
RegisterHyjalAI(boss_kazrogal);
|
||||
new spell_mark_of_kazrogal();
|
||||
RegisterSpellAndAuraScriptPair(spell_mark_of_kazrogal, spell_mark_of_kazrogal_aura);
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,11 @@ enum HyjalCreaturesIds
|
||||
NPC_KAZROGAL = 17888,
|
||||
NPC_AZGALOR = 17842,
|
||||
NPC_ARCHIMONDE = 17968,
|
||||
NPC_WORLD_TRIGGER_TINY = 21987
|
||||
NPC_WORLD_TRIGGER_TINY = 21987,
|
||||
|
||||
// Boss summons
|
||||
NPC_TOWERING_INFERNAL = 17818,
|
||||
NPC_LESSER_DOOMGUARD = 17864
|
||||
};
|
||||
|
||||
enum HyjalGameobjectIds
|
||||
@@ -144,7 +148,11 @@ enum HyjalMisc
|
||||
START_WAVE_HORDE_RETREAT = 39,
|
||||
START_WAVE_NIGHT_ELF = 42,
|
||||
|
||||
CONTEXT_GROUP_WAVES = 1
|
||||
CONTEXT_GROUP_WAVES = 1,
|
||||
|
||||
AREA_NORDRASSIL = 3710,
|
||||
|
||||
SPELL_ETERNAL_SILENCE = 42201
|
||||
};
|
||||
|
||||
enum HyjalPaths
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "InstanceMapScript.h"
|
||||
#include "InstanceScript.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "hyjal.h"
|
||||
|
||||
@@ -101,6 +102,7 @@ public:
|
||||
trash = 0;
|
||||
_currentWave = 0;
|
||||
_encounterNPCs.clear();
|
||||
_summonedNPCs.clear();
|
||||
_baseAlliance.clear();
|
||||
_baseHorde.clear();
|
||||
_infernalTargets.clear();
|
||||
@@ -199,6 +201,13 @@ public:
|
||||
_encounterNPCs.insert(creature->GetGUID()); // Used for despawning on wipe
|
||||
}
|
||||
break;
|
||||
case NPC_TOWERING_INFERNAL:
|
||||
case NPC_LESSER_DOOMGUARD:
|
||||
if (creature->IsSummon())
|
||||
{
|
||||
_summonedNPCs.insert(creature->GetGUID());
|
||||
}
|
||||
break;
|
||||
}
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
@@ -232,6 +241,10 @@ public:
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NPC_TOWERING_INFERNAL:
|
||||
case NPC_LESSER_DOOMGUARD:
|
||||
_summonedNPCs.erase(unit->ToCreature()->GetGUID());
|
||||
break;
|
||||
case NPC_WINTERCHILL:
|
||||
case NPC_ANETHERON:
|
||||
case NPC_KAZROGAL:
|
||||
@@ -401,6 +414,14 @@ public:
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
// also force despawn boss summons
|
||||
for (ObjectGuid const& guid : _summonedNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
if (_bossWave && (GetBossState(_bossWave) != DONE))
|
||||
SetBossState(_bossWave, NOT_STARTED);
|
||||
|
||||
_scheduler.Schedule(300s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseAlliance)
|
||||
@@ -419,6 +440,14 @@ public:
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
// also force despawn boss summons
|
||||
for (ObjectGuid const& guid : _summonedNPCs)
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
creature->DespawnOrUnsummon();
|
||||
|
||||
if (_bossWave && (GetBossState(_bossWave) != DONE))
|
||||
SetBossState(_bossWave, NOT_STARTED);
|
||||
|
||||
_scheduler.Schedule(300s, [this](TaskContext)
|
||||
{
|
||||
for (ObjectGuid const& guid : _baseHorde)
|
||||
@@ -454,6 +483,7 @@ public:
|
||||
case DATA_RESET_WAVES:
|
||||
_scheduler.CancelGroup(CONTEXT_GROUP_WAVES);
|
||||
_encounterNPCs.clear();
|
||||
_summonedNPCs.clear();
|
||||
_currentWave = 0;
|
||||
trash = 0;
|
||||
_bossWave = 0;
|
||||
@@ -530,6 +560,14 @@ public:
|
||||
_scheduler.Update(diff);
|
||||
}
|
||||
|
||||
void OnPlayerInWaterStateUpdate(Player* player, bool inWater) override
|
||||
{
|
||||
if (inWater && player->GetAreaId() == AREA_NORDRASSIL)
|
||||
{
|
||||
player->CastSpell(player, SPELL_ETERNAL_SILENCE, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int32 trash;
|
||||
uint8 _currentWave;
|
||||
@@ -537,6 +575,7 @@ public:
|
||||
uint8 _retreat;
|
||||
TaskScheduler _scheduler;
|
||||
GuidSet _encounterNPCs;
|
||||
GuidSet _summonedNPCs;
|
||||
GuidSet _baseAlliance;
|
||||
GuidSet _baseHorde;
|
||||
GuidVector _infernalTargets;
|
||||
|
||||
@@ -2383,20 +2383,45 @@ public:
|
||||
return GetCaster()->GetTypeId() == TYPEID_UNIT;
|
||||
}
|
||||
|
||||
void CheckEnergy()
|
||||
void CalculatePower()
|
||||
{
|
||||
if (GetCaster()->GetPower(POWER_ENERGY) >= 100)
|
||||
Unit* caster = GetCaster();
|
||||
if (!caster)
|
||||
return;
|
||||
|
||||
SpellInfo const* spellInfo = GetSpellInfo();
|
||||
if (!spellInfo)
|
||||
return;
|
||||
|
||||
// Check if the effect is energize
|
||||
if (spellInfo->Effects[EFFECT_1].Effect == SPELL_EFFECT_ENERGIZE)
|
||||
{
|
||||
GetCaster()->CastSpell(GetCaster(), SPELL_OVERHEAT, true);
|
||||
if (Vehicle* vehicle = GetCaster()->GetVehicleKit())
|
||||
if (Unit* passenger = vehicle->GetPassenger(0))
|
||||
sCreatureTextMgr->SendChat(GetCaster()->ToCreature(), SAY_OVERHEAT, passenger);
|
||||
int32 energizeAmount = spellInfo->Effects[EFFECT_1].CalcValue(caster);
|
||||
|
||||
// Apply the power gain directly to the caster
|
||||
caster->ModifyPower(POWER_ENERGY, energizeAmount);
|
||||
}
|
||||
|
||||
if (caster->GetPower(POWER_ENERGY) >= 100)
|
||||
{
|
||||
caster->CastSpell(caster, SPELL_OVERHEAT, true);
|
||||
if (Vehicle* vehicle = caster->GetVehicleKit())
|
||||
if (Unit* passenger = vehicle->GetPassenger(0))
|
||||
sCreatureTextMgr->SendChat(caster->ToCreature(), SAY_OVERHEAT, passenger);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PreventPowerGainOnHit(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
AfterHit += SpellHitFn(spell_igb_cannon_blast_SpellScript::CheckEnergy);
|
||||
OnCast += SpellCastFn(spell_igb_cannon_blast_SpellScript::CalculatePower);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_igb_cannon_blast_SpellScript::PreventPowerGainOnHit, EFFECT_1, SPELL_EFFECT_ENERGIZE);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -869,85 +869,29 @@ private:
|
||||
bool _removeHealers;
|
||||
};
|
||||
|
||||
class spell_sindragosa_unchained_magic : public SpellScriptLoader
|
||||
class spell_sindragosa_unchained_magic : public SpellScript
|
||||
{
|
||||
public:
|
||||
spell_sindragosa_unchained_magic() : SpellScriptLoader("spell_sindragosa_unchained_magic") { }
|
||||
PrepareSpellScript(spell_sindragosa_unchained_magic);
|
||||
|
||||
class spell_sindragosa_unchained_magic_SpellScript : public SpellScript
|
||||
void FilterTargets(std::list<WorldObject*>& unitList)
|
||||
{
|
||||
PrepareSpellScript(spell_sindragosa_unchained_magic_SpellScript);
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& unitList)
|
||||
{
|
||||
std::list<WorldObject*> healList = unitList;
|
||||
std::list<WorldObject*> dpsList = unitList;
|
||||
unitList.clear();
|
||||
uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1);
|
||||
healList.remove_if(UnchainedMagicTargetSelector(false));
|
||||
if (healList.size() > maxSize)
|
||||
Acore::Containers::RandomResize(healList, maxSize);
|
||||
dpsList.remove_if(UnchainedMagicTargetSelector(true));
|
||||
if (dpsList.size() > maxSize)
|
||||
Acore::Containers::RandomResize(dpsList, maxSize);
|
||||
unitList.splice(unitList.begin(), healList);
|
||||
unitList.splice(unitList.begin(), dpsList);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_unchained_magic_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
SpellScript* GetSpellScript() const override
|
||||
{
|
||||
return new spell_sindragosa_unchained_magic_SpellScript();
|
||||
std::list<WorldObject*> healList = unitList;
|
||||
std::list<WorldObject*> dpsList = unitList;
|
||||
unitList.clear();
|
||||
uint32 maxSize = uint32(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1);
|
||||
healList.remove_if(UnchainedMagicTargetSelector(false));
|
||||
if (healList.size() > maxSize)
|
||||
Acore::Containers::RandomResize(healList, maxSize);
|
||||
dpsList.remove_if(UnchainedMagicTargetSelector(true));
|
||||
if (dpsList.size() > maxSize)
|
||||
Acore::Containers::RandomResize(dpsList, maxSize);
|
||||
unitList.splice(unitList.begin(), healList);
|
||||
unitList.splice(unitList.begin(), dpsList);
|
||||
}
|
||||
|
||||
class spell_sindragosa_unchained_magic_AuraScript : public AuraScript
|
||||
void Register() override
|
||||
{
|
||||
PrepareAuraScript(spell_sindragosa_unchained_magic_AuraScript);
|
||||
|
||||
std::map<uint32, uint32> _lastMSTimeForSpell;
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
_lastMSTimeForSpell.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckProc(ProcEventInfo& eventInfo)
|
||||
{
|
||||
SpellInfo const* spellInfo = eventInfo.GetSpellInfo();
|
||||
if (!spellInfo)
|
||||
return false;
|
||||
|
||||
uint32 currMSTime = GameTime::GetGameTimeMS().count();
|
||||
std::map<uint32, uint32>::iterator itr = _lastMSTimeForSpell.find(spellInfo->Id);
|
||||
if (itr != _lastMSTimeForSpell.end())
|
||||
{
|
||||
uint32 lastMSTime = itr->second;
|
||||
itr->second = currMSTime;
|
||||
if (getMSTimeDiff(lastMSTime, currMSTime) < 600)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_lastMSTimeForSpell[spellInfo->Id] = currMSTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
DoCheckProc += AuraCheckProcFn(spell_sindragosa_unchained_magic_AuraScript::CheckProc);
|
||||
}
|
||||
};
|
||||
|
||||
AuraScript* GetAuraScript() const override
|
||||
{
|
||||
return new spell_sindragosa_unchained_magic_AuraScript();
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sindragosa_unchained_magic::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2012,7 +1956,7 @@ void AddSC_boss_sindragosa()
|
||||
new boss_sindragosa();
|
||||
new npc_ice_tomb();
|
||||
new spell_sindragosa_s_fury();
|
||||
new spell_sindragosa_unchained_magic();
|
||||
RegisterSpellScript(spell_sindragosa_unchained_magic);
|
||||
new spell_sindragosa_permeating_chill();
|
||||
new spell_sindragosa_instability();
|
||||
new spell_sindragosa_icy_grip();
|
||||
|
||||
@@ -665,6 +665,37 @@ public:
|
||||
};
|
||||
};
|
||||
|
||||
struct boss_kologarn_pit_kill_bunny : public NullCreatureAI
|
||||
{
|
||||
boss_kologarn_pit_kill_bunny(Creature* creature) : NullCreatureAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
RectangleBoundary* _boundaryXY = new RectangleBoundary(1782.0f, 1832.0f, -56.0f, 8.0f);
|
||||
ZRangeBoundary* _boundaryZ = new ZRangeBoundary(400.0f, 439.0f);
|
||||
_boundaryIntersect = new BoundaryIntersectBoundary(_boundaryXY, _boundaryZ);
|
||||
|
||||
scheduler.Schedule(0s, [this](TaskContext context)
|
||||
{
|
||||
me->GetMap()->DoForAllPlayers([&](Player* player)
|
||||
{
|
||||
if (_boundaryIntersect->IsWithinBoundary(player->GetPosition()) && !player->IsGameMaster())
|
||||
{
|
||||
player->KillSelf(false);
|
||||
}
|
||||
});
|
||||
context.Repeat(1s);
|
||||
});
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
scheduler.Update(diff);
|
||||
}
|
||||
private:
|
||||
BoundaryIntersectBoundary const* _boundaryIntersect;
|
||||
};
|
||||
|
||||
// predicate function to select non main tank target
|
||||
class StoneGripTargetSelector
|
||||
{
|
||||
@@ -894,6 +925,7 @@ void AddSC_boss_kologarn()
|
||||
new boss_kologarn();
|
||||
new boss_kologarn_arms();
|
||||
new boss_kologarn_eyebeam();
|
||||
RegisterUlduarCreatureAI(boss_kologarn_pit_kill_bunny);
|
||||
|
||||
// Spells
|
||||
new spell_ulduar_stone_grip_cast_target();
|
||||
|
||||
@@ -86,7 +86,8 @@ enum SpellData
|
||||
SPELL_HAND_PULSE_25_L = 64536,
|
||||
|
||||
SPELL_SELF_REPAIR = 64383,
|
||||
SPELL_SLEEP = 64394,
|
||||
SPELL_SLEEP_VISUAL_1 = 64393,
|
||||
SPELL_SLEEP_VISUAL_2 = 64394,
|
||||
};
|
||||
|
||||
enum NPCs
|
||||
@@ -172,10 +173,11 @@ enum EVENTS
|
||||
EVENT_JOIN_ACU = 35,
|
||||
EVENT_START_PHASE4 = 36,
|
||||
EVENT_FINISH = 50,
|
||||
EVENT_SAY_VOLTRON_DEAD = 51,
|
||||
EVENT_DISAPPEAR = 52,
|
||||
EVENT_BERSERK = 53,
|
||||
EVENT_BERSERK_2 = 54,
|
||||
EVENT_STAND_UP_FRIENDLY = 51,
|
||||
EVENT_SAY_VOLTRON_DEAD = 52,
|
||||
EVENT_DISAPPEAR = 53,
|
||||
EVENT_BERSERK = 54,
|
||||
EVENT_BERSERK_2 = 55,
|
||||
|
||||
// Leviathan:
|
||||
EVENT_SPELL_NAPALM_SHELL = 3,
|
||||
@@ -754,17 +756,20 @@ public:
|
||||
Position exitPos = me->GetPosition();
|
||||
me->_ExitVehicle(&exitPos);
|
||||
me->AttackStop();
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK);
|
||||
me->GetMotionMaster()->Clear();
|
||||
summons.DoAction(1337); // despawn summons of summons
|
||||
summons.DespawnEntry(NPC_FLAMES_INITIAL);
|
||||
summons.DespawnEntry(33576);
|
||||
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
|
||||
float angle = VX001->GetOrientation();
|
||||
float v_x = me->GetPositionX() + cos(angle) * 10.0f;
|
||||
float v_y = me->GetPositionY() + std::sin(angle) * 10.0f;
|
||||
me->GetMotionMaster()->MoveJump(v_x, v_y, 364.32f, 7.0f, 7.0f);
|
||||
|
||||
DoCastSelf(SPELL_SLEEP_VISUAL_1);
|
||||
|
||||
if( pInstance )
|
||||
for( uint16 i = 0; i < 3; ++i )
|
||||
if( ObjectGuid guid = pInstance->GetGuidData(DATA_GO_MIMIRON_DOOR_1 + i) )
|
||||
@@ -783,11 +788,20 @@ public:
|
||||
computer->AI()->Talk(TALK_COMPUTER_TERMINATED);
|
||||
|
||||
events.Reset();
|
||||
events.ScheduleEvent(EVENT_SAY_VOLTRON_DEAD, 6s);
|
||||
events.ScheduleEvent(EVENT_STAND_UP_FRIENDLY, 6s);
|
||||
}
|
||||
break;
|
||||
case EVENT_STAND_UP_FRIENDLY:
|
||||
me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1);
|
||||
DoCastSelf(SPELL_SLEEP_VISUAL_2);
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
events.ScheduleEvent(EVENT_SAY_VOLTRON_DEAD, 4s);
|
||||
break;
|
||||
case EVENT_SAY_VOLTRON_DEAD:
|
||||
Talk(SAY_V07TRON_DEATH);
|
||||
me->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
|
||||
if (pInstance)
|
||||
pInstance->SetData(TYPE_MIMIRON, DONE);
|
||||
// spawn chest
|
||||
if (uint32 chestId = (hardmode ? RAID_MODE(GO_MIMIRON_CHEST_HARD, GO_MIMIRON_CHEST_HERO_HARD) : RAID_MODE(GO_MIMIRON_CHEST, GO_MIMIRON_CHEST_HERO)))
|
||||
{
|
||||
@@ -797,11 +811,9 @@ public:
|
||||
go->SetLootRecipient(me->GetMap());
|
||||
}
|
||||
}
|
||||
events.ScheduleEvent(EVENT_DISAPPEAR, 15s);
|
||||
events.ScheduleEvent(EVENT_DISAPPEAR, 9s);
|
||||
break;
|
||||
case EVENT_DISAPPEAR:
|
||||
if( pInstance )
|
||||
pInstance->SetData(TYPE_MIMIRON, DONE);
|
||||
DoCastSelf(SPELL_TELEPORT);
|
||||
summons.DespawnAll();
|
||||
break;
|
||||
|
||||
@@ -100,6 +100,15 @@ public:
|
||||
Position normalChestPosition = { 1967.152588f, -204.188461f, 432.686951f, 5.50957f };
|
||||
Position hardChestPosition = { 2035.94600f, -202.084885f, 432.686859f, 3.164077f };
|
||||
|
||||
// Mimiron Tram
|
||||
ObjectGuid m_mimironTramGUID;
|
||||
ObjectGuid m_mimironActivateTramGUID;
|
||||
ObjectGuid m_mimironTramRocketBoosterGUID;
|
||||
ObjectGuid m_mimironTramTurnaround1GUID;
|
||||
ObjectGuid m_mimironTramTurnaround2GUID;
|
||||
ObjectGuid m_mimironCallTramCenterGUID;
|
||||
ObjectGuid m_mimironCallTramMimironGUID;
|
||||
|
||||
// Mimiron
|
||||
ObjectGuid m_MimironDoor[3];
|
||||
ObjectGuid m_MimironLeviathanMKIIguid;
|
||||
@@ -124,10 +133,12 @@ public:
|
||||
ObjectGuid m_brannBronzebeardBaseCamp;
|
||||
uint32 m_algalonTimer;
|
||||
|
||||
// Ancient Gate
|
||||
const Position triggerAncientGatePosition = { 1883.65f, 269.272f, 418.406f };
|
||||
|
||||
// Shared
|
||||
EventMap _events;
|
||||
bool m_mimironTramUsed;
|
||||
ObjectGuid m_mimironTramGUID;
|
||||
ObjectGuid m_keepersgateGUID;
|
||||
ObjectGuid m_keepersGossipGUID[4];
|
||||
|
||||
@@ -170,7 +181,18 @@ public:
|
||||
// mimiron tram:
|
||||
instance->LoadGrid(2307.0f, 284.632f);
|
||||
if (GameObject* MimironTram = instance->GetGameObject(m_mimironTramGUID))
|
||||
{
|
||||
player->UpdateVisibilityOf(MimironTram);
|
||||
if (StaticTransport* t = MimironTram->ToStaticTransport())
|
||||
{
|
||||
if (GameObject* go = instance->GetGameObject(m_mimironTramRocketBoosterGUID))
|
||||
if (!go->GetTransport())
|
||||
t->AddPassenger(go, true);
|
||||
if (GameObject* go = instance->GetGameObject(m_mimironActivateTramGUID))
|
||||
if (!go->GetTransport())
|
||||
t->AddPassenger(go, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_uiAlgalonGUID && m_algalonTimer && (m_algalonTimer <= 60 || m_algalonTimer == TIMER_ALGALON_TO_SUMMON))
|
||||
{
|
||||
@@ -553,11 +575,30 @@ public:
|
||||
case GO_SNOW_MOUND:
|
||||
gameObject->EnableCollision(false);
|
||||
break;
|
||||
// Mimiron Tram
|
||||
case GO_MIMIRON_TRAM:
|
||||
if (GetData(TYPE_MIMIRON) == DONE)
|
||||
m_mimironTramUsed = true;
|
||||
m_mimironTramGUID = gameObject->GetGUID();
|
||||
break;
|
||||
case GO_MIMIRON_TRAM_ROCKET_BOOSTER:
|
||||
m_mimironTramRocketBoosterGUID = gameObject->GetGUID();
|
||||
break;
|
||||
case GO_MIMIRON_ACTIVATE_TRAM:
|
||||
m_mimironActivateTramGUID = gameObject->GetGUID();
|
||||
break;
|
||||
case GO_MIMIRON_CALL_TRAM_CENTER:
|
||||
m_mimironCallTramCenterGUID = gameObject->GetGUID();
|
||||
break;
|
||||
case GO_MIMIRON_CALL_TRAM_MIMIRON:
|
||||
m_mimironCallTramMimironGUID = gameObject->GetGUID();
|
||||
break;
|
||||
case GO_DOODAD_UL_TRAIN_TURNAROUND01:
|
||||
m_mimironTramTurnaround1GUID = gameObject->GetGUID();
|
||||
break;
|
||||
case GO_DOODAD_UL_TRAIN_TURNAROUND02:
|
||||
m_mimironTramTurnaround2GUID = gameObject->GetGUID();
|
||||
break;
|
||||
// Algalon the Observer
|
||||
case GO_CELESTIAL_PLANETARIUM_ACCESS_10:
|
||||
case GO_CELESTIAL_PLANETARIUM_ACCESS_25:
|
||||
@@ -668,8 +709,17 @@ public:
|
||||
m_auiEncounter[type] = data;
|
||||
if (GetData(TYPE_MIMIRON) == DONE && GetData(TYPE_FREYA) == DONE && GetData(TYPE_HODIR) == DONE && GetData(TYPE_THORIM) == DONE)
|
||||
{
|
||||
if (GameObject* go = instance->GetGameObject(m_keepersgateGUID))
|
||||
go->RemoveGameObjectFlag(GO_FLAG_LOCKED);
|
||||
scheduler.Schedule(45s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (GameObject* go = instance->GetGameObject(m_keepersgateGUID))
|
||||
{
|
||||
go->RemoveGameObjectFlag(GO_FLAG_LOCKED);
|
||||
if (Creature* trigger = instance->SummonCreature(NPC_ANCIENT_GATE_WORLD_TRIGGER, triggerAncientGatePosition, nullptr, 10*IN_MILLISECONDS))
|
||||
{
|
||||
trigger->AI()->Talk(EMOTE_ANCIENT_GATE_UNLOCKED);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (type == TYPE_MIMIRON && data == IN_PROGRESS) // after reaching him without tram and starting the fight
|
||||
m_mimironTramUsed = true;
|
||||
@@ -785,9 +835,51 @@ public:
|
||||
if (StaticTransport* t = MimironTram->ToStaticTransport())
|
||||
{
|
||||
if (data == 0 && t->GetGoState() == GO_STATE_ACTIVE && t->GetPathProgress() == t->GetPauseTime())
|
||||
{
|
||||
MimironTram->SetGoState(GO_STATE_READY);
|
||||
if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID))
|
||||
rocketBooster->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID))
|
||||
activateTramButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
if (GameObject* callTramCenterButton = instance->GetGameObject(m_mimironCallTramCenterGUID))
|
||||
callTramCenterButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
scheduler.Schedule(30s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (GameObject* turnaround1 = instance->GetGameObject(m_mimironTramTurnaround1GUID))
|
||||
turnaround1->UseDoorOrButton();
|
||||
if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID))
|
||||
rocketBooster->SetGoState(GO_STATE_READY);
|
||||
}).Schedule(60s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID))
|
||||
activateTramButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
if (GameObject* callTramMimironButton = instance->GetGameObject(m_mimironCallTramMimironGUID))
|
||||
callTramMimironButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
});
|
||||
}
|
||||
if (data == 1 && t->GetGoState() == GO_STATE_READY && t->GetPathProgress() == 0)
|
||||
{
|
||||
MimironTram->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID))
|
||||
rocketBooster->SetGoState(GO_STATE_ACTIVE);
|
||||
if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID))
|
||||
activateTramButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
if (GameObject* callTramMimironButton = instance->GetGameObject(m_mimironCallTramMimironGUID))
|
||||
callTramMimironButton->SetGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
scheduler.Schedule(33s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (GameObject* turnaround2 = instance->GetGameObject(m_mimironTramTurnaround2GUID))
|
||||
turnaround2->UseDoorOrButton();
|
||||
if (GameObject* rocketBooster = instance->GetGameObject(m_mimironTramRocketBoosterGUID))
|
||||
rocketBooster->SetGoState(GO_STATE_READY);
|
||||
}).Schedule(63s, [this](TaskContext /*context*/)
|
||||
{
|
||||
if (GameObject* activateTramButton = instance->GetGameObject(m_mimironActivateTramGUID))
|
||||
activateTramButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
if (GameObject* callTramCenterButton = instance->GetGameObject(m_mimironCallTramCenterGUID))
|
||||
callTramCenterButton->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DATA_BRANN_MEMOTESAY:
|
||||
|
||||
@@ -545,33 +545,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class go_call_tram : public GameObjectScript
|
||||
{
|
||||
public:
|
||||
go_call_tram() : GameObjectScript("go_call_tram") { }
|
||||
|
||||
bool OnGossipHello(Player* /*player*/, GameObject* go) override
|
||||
{
|
||||
InstanceScript* pInstance = go->GetInstanceScript();
|
||||
|
||||
if (!pInstance)
|
||||
return false;
|
||||
|
||||
switch(go->GetEntry())
|
||||
{
|
||||
case 194914:
|
||||
case 194438:
|
||||
pInstance->SetData(DATA_CALL_TRAM, 0);
|
||||
break;
|
||||
case 194912:
|
||||
case 194437:
|
||||
pInstance->SetData(DATA_CALL_TRAM, 1);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct npc_salvaged_siege_engine : public VehicleAI
|
||||
{
|
||||
npc_salvaged_siege_engine(Creature* creature) : VehicleAI(creature) { }
|
||||
@@ -609,7 +582,5 @@ void AddSC_ulduar()
|
||||
new npc_ulduar_arachnopod_destroyer();
|
||||
new spell_ulduar_arachnopod_damaged();
|
||||
new AreaTrigger_at_celestial_planetarium_enterance();
|
||||
new go_call_tram();
|
||||
|
||||
RegisterCreatureAI(npc_salvaged_siege_engine);
|
||||
}
|
||||
|
||||
@@ -215,7 +215,15 @@ enum UlduarGameObjects
|
||||
GO_KOLOGARN_DOORS = 194553,
|
||||
GO_KEEPERS_GATE = 194255,
|
||||
GO_XT002_DOORS = 194631,
|
||||
|
||||
// Tram
|
||||
GO_MIMIRON_TRAM = 194675,
|
||||
GO_MIMIRON_ACTIVATE_TRAM = 194437,
|
||||
GO_MIMIRON_CALL_TRAM_CENTER = 194914,
|
||||
GO_MIMIRON_CALL_TRAM_MIMIRON = 194912,
|
||||
GO_MIMIRON_TRAM_ROCKET_BOOSTER = 194904,
|
||||
GO_DOODAD_UL_TRAIN_TURNAROUND01 = 194915, // center
|
||||
GO_DOODAD_UL_TRAIN_TURNAROUND02 = 194913, // mimiron
|
||||
|
||||
// Mimiron, Hodir, Vezax
|
||||
GO_MIMIRON_ELEVATOR = 194749,
|
||||
@@ -290,6 +298,10 @@ enum UlduarMisc
|
||||
// Freya, Hodir, Mimiron, Thorim
|
||||
EVENT_KEEPER_TELEPORTED = 62941,
|
||||
|
||||
// Ancient Gate
|
||||
NPC_ANCIENT_GATE_WORLD_TRIGGER = 22515,
|
||||
EMOTE_ANCIENT_GATE_UNLOCKED = 19,
|
||||
|
||||
// Yogg-Saron
|
||||
ACTION_SARA_UPDATE_SUMMON_KEEPERS = 4,
|
||||
KEEPER_FREYA = 0,
|
||||
|
||||
Reference in New Issue
Block a user