mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-22 18:15:31 +01:00
Merge commit 'f3e86d3e686b8f7e29f55b884f6c8cb226ee1598' into 4.3.4
Conflicts: dep/libmpq/CMakeLists.txt doc/UnixInstall.txt src/server/game/Accounts/RBAC.cpp src/server/game/Guilds/GuildMgr.cpp src/server/game/Server/WorldSocket.cpp src/server/scripts/Commands/cs_mmaps.cpp src/server/scripts/Commands/cs_rbac.cpp src/server/scripts/EasternKingdoms/Deadmines/deadmines.cpp src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp src/server/scripts/EasternKingdoms/ZulAman/zulaman.h src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_gahzranka.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp src/server/scripts/EasternKingdoms/ZulGurub/zulgurub.h src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp src/server/scripts/Kalimdor/boss_azuregos.cpp src/server/scripts/Kalimdor/zone_azshara.cpp src/server/scripts/Kalimdor/zone_darkshore.cpp src/server/scripts/Kalimdor/zone_felwood.cpp src/server/scripts/Kalimdor/zone_moonglade.cpp src/server/scripts/Kalimdor/zone_orgrimmar.cpp src/server/scripts/Kalimdor/zone_stonetalon_mountains.cpp src/server/scripts/OutdoorPvP/OutdoorPvPEP.cpp src/server/scripts/OutdoorPvP/OutdoorPvPEP.h src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp src/server/shared/Cryptography/Authentication/AuthCrypt.cpp src/server/shared/Cryptography/Authentication/AuthCrypt.h src/server/shared/Cryptography/HMACSHA1.cpp src/server/shared/Cryptography/HMACSHA1.h src/server/shared/Packets/WorldPacket.h src/tools/map_extractor/mpq_libmpq.cpp src/tools/map_extractor/mpq_libmpq04.h src/tools/mesh_extractor/ADT.cpp src/tools/mesh_extractor/ADT.h src/tools/mesh_extractor/CMakeLists.txt src/tools/mesh_extractor/Cache.h src/tools/mesh_extractor/Chunk.cpp src/tools/mesh_extractor/Chunk.h src/tools/mesh_extractor/ChunkedData.cpp src/tools/mesh_extractor/ChunkedData.h src/tools/mesh_extractor/Constants.h src/tools/mesh_extractor/ContinentBuilder.cpp src/tools/mesh_extractor/ContinentBuilder.h src/tools/mesh_extractor/DBC.cpp src/tools/mesh_extractor/DBC.h src/tools/mesh_extractor/DoodadHandler.cpp src/tools/mesh_extractor/DoodadHandler.h src/tools/mesh_extractor/Geometry.cpp src/tools/mesh_extractor/Geometry.h src/tools/mesh_extractor/LiquidHandler.cpp src/tools/mesh_extractor/LiquidHandler.h src/tools/mesh_extractor/MPQ.cpp src/tools/mesh_extractor/MPQ.h src/tools/mesh_extractor/MPQManager.cpp src/tools/mesh_extractor/MPQManager.h src/tools/mesh_extractor/MapChunk.cpp src/tools/mesh_extractor/MapChunk.h src/tools/mesh_extractor/MeshExtractor.cpp src/tools/mesh_extractor/Model.cpp src/tools/mesh_extractor/Model.h src/tools/mesh_extractor/ObjectDataHandler.cpp src/tools/mesh_extractor/ObjectDataHandler.h src/tools/mesh_extractor/TileBuilder.cpp src/tools/mesh_extractor/TileBuilder.h src/tools/mesh_extractor/Utils.cpp src/tools/mesh_extractor/Utils.h src/tools/mesh_extractor/WDT.cpp src/tools/mesh_extractor/WDT.h src/tools/mesh_extractor/WorldModelGroup.cpp src/tools/mesh_extractor/WorldModelGroup.h src/tools/mesh_extractor/WorldModelHandler.cpp src/tools/mesh_extractor/WorldModelHandler.h src/tools/mesh_extractor/WorldModelRoot.cpp src/tools/mesh_extractor/WorldModelRoot.h src/tools/vmap4_extractor/loadlib/loadlib.h src/tools/vmap4_extractor/mpq_libmpq.cpp src/tools/vmap4_extractor/mpq_libmpq04.h
This commit is contained in:
@@ -81,4 +81,4 @@ include(cmake/showoptions.cmake)
|
||||
add_subdirectory(dep)
|
||||
|
||||
# add core sources
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
# set(CMAKE_INSTALL_PREFIX
|
||||
# "" CACHE PATH "Default install path")
|
||||
# endif()
|
||||
#endif()
|
||||
#endif()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -47,17 +47,17 @@ public:
|
||||
static ChatCommand mmapCommandTable[] =
|
||||
{
|
||||
{ "loadedtiles", rbac::RBAC_PERM_COMMAND_MMAP_LOADEDTILES, false, &HandleMmapLoadedTilesCommand, "", NULL },
|
||||
{ "loc", rbac::RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "", NULL },
|
||||
{ "path", rbac::RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "", NULL },
|
||||
{ "stats", rbac::RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "", NULL },
|
||||
{ "testarea", rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
{ "loc", rbac::RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "", NULL },
|
||||
{ "path", rbac::RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "", NULL },
|
||||
{ "stats", rbac::RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "", NULL },
|
||||
{ "testarea", rbac::RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "", NULL },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
static ChatCommand commandTable[] =
|
||||
{
|
||||
{ "mmap", rbac::RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
{ "mmap", rbac::RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable },
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
return commandTable;
|
||||
}
|
||||
|
||||
@@ -15,19 +15,67 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: boss_Akilzon
|
||||
SD%Complete: 75%
|
||||
SDComment: Missing timer for Call Lightning and Sound ID's
|
||||
SQLUpdate:
|
||||
#Temporary fix for Soaring Eagles
|
||||
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "Cell.h"
|
||||
#include "CellImpl.h"
|
||||
#include "zulaman.h"
|
||||
#include "Weather.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_STATIC_DISRUPTION = 43622,
|
||||
SPELL_STATIC_VISUAL = 45265,
|
||||
SPELL_CALL_LIGHTNING = 43661, // Missing timer
|
||||
SPELL_GUST_OF_WIND = 43621,
|
||||
SPELL_ELECTRICAL_STORM = 43648,
|
||||
SPELL_BERSERK = 45078,
|
||||
SPELL_ELECTRICAL_OVERLOAD = 43658,
|
||||
SPELL_EAGLE_SWOOP = 44732,
|
||||
SPELL_ZAP = 43137,
|
||||
SPELL_SAND_STORM = 25160
|
||||
};
|
||||
|
||||
enum Says
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_PLAYER_KILL = 1,
|
||||
EMOTE_ELECTRICAL_STORM = 2,
|
||||
SAY_SUMMON_EAGLE = 3,
|
||||
SAY_SUMMON_BIRDS = 4,
|
||||
SAY_BERSERK = 5,
|
||||
SAY_DEATH = 6
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SUMMON = 1,
|
||||
SAY_INTRO = 2, // Not used in script
|
||||
SAY_ENRAGE = 3,
|
||||
SAY_KILL = 4,
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
|
||||
enum Misc
|
||||
{
|
||||
NPC_SOARING_EAGLE = 24858,
|
||||
SE_LOC_X_MAX = 400,
|
||||
SE_LOC_X_MIN = 335,
|
||||
SE_LOC_Y_MAX = 1435,
|
||||
SE_LOC_Y_MIN = 1370
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_STATIC_DISRUPTION = 1,
|
||||
EVENT_GUST_OF_WIND = 2,
|
||||
EVENT_CALL_LIGHTNING = 3,
|
||||
EVENT_ELECTRICAL_STORM = 4,
|
||||
EVENT_RAIN = 5,
|
||||
EVENT_SUMMON_EAGLES = 6,
|
||||
EVENT_STORM_SEQUENCE = 7,
|
||||
EVENT_ENRAGE = 8
|
||||
};
|
||||
|
||||
class boss_akilzon : public CreatureScript
|
||||
@@ -37,17 +85,45 @@ class boss_akilzon : public CreatureScript
|
||||
|
||||
struct boss_akilzonAI : public BossAI
|
||||
{
|
||||
boss_akilzonAI(Creature* creature) : BossAI(creature, DATA_AKILZON) { }
|
||||
boss_akilzonAI(Creature* creature) : BossAI(creature, DATA_AKILZONEVENT)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
TargetGUID.Clear();
|
||||
CloudGUID.Clear();
|
||||
CycloneGUID.Clear();
|
||||
for (ObjectGuid& guid : BirdGUIDs)
|
||||
guid.Clear();
|
||||
|
||||
StormCount = 0;
|
||||
isRaining = false;
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
|
||||
Initialize();
|
||||
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(10000, 20000)); // 10 to 20 seconds (bosskillers)
|
||||
events.ScheduleEvent(EVENT_GUST_OF_WIND, urand(20000, 30000)); // 20 to 30 seconds(bosskillers)
|
||||
events.ScheduleEvent(EVENT_CALL_LIGHTNING, urand(10000, 20000)); // totaly random timer. can't find any info on this
|
||||
events.ScheduleEvent(EVENT_ELECTRICAL_STORM, 60000); // 60 seconds(bosskillers)
|
||||
events.ScheduleEvent(EVENT_RAIN, urand(47000, 52000));
|
||||
events.ScheduleEvent(EVENT_ENRAGE, 10*MINUTE*IN_MILLISECONDS); // 10 minutes till enrage(bosskillers)
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
_EnterCombat();
|
||||
//DoZoneInCombat();
|
||||
instance->SetData(DATA_AKILZONEVENT, IN_PROGRESS);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
@@ -60,6 +136,91 @@ class boss_akilzon : public CreatureScript
|
||||
{
|
||||
if (who->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_PLAYER_KILL);
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void SetWeather(uint32 weather, float grade)
|
||||
{
|
||||
Map* map = me->GetMap();
|
||||
if (!map->IsDungeon())
|
||||
return;
|
||||
|
||||
WorldPacket data(SMSG_WEATHER, (4+4+4));
|
||||
data << uint32(weather) << float(grade) << uint8(0);
|
||||
|
||||
map->SendToPlayers(&data);
|
||||
}
|
||||
|
||||
void HandleStormSequence(Unit* Cloud) // 1: begin, 2-9: tick, 10: end
|
||||
{
|
||||
if (StormCount < 10 && StormCount > 1)
|
||||
{
|
||||
// deal damage
|
||||
int32 bp0 = 800;
|
||||
for (uint8 i = 2; i < StormCount; ++i)
|
||||
bp0 *= 2;
|
||||
|
||||
CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
|
||||
Cell cell(p);
|
||||
cell.SetNoCreate();
|
||||
|
||||
std::list<Unit*> tempUnitMap;
|
||||
|
||||
{
|
||||
Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, SIZE_OF_GRIDS);
|
||||
Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(me, tempUnitMap, u_check);
|
||||
|
||||
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
|
||||
TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
|
||||
|
||||
cell.Visit(p, world_unit_searcher, *me->GetMap(), *me, SIZE_OF_GRIDS);
|
||||
cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, SIZE_OF_GRIDS);
|
||||
}
|
||||
|
||||
// deal damage
|
||||
for (std::list<Unit*>::const_iterator i = tempUnitMap.begin(); i != tempUnitMap.end(); ++i)
|
||||
{
|
||||
if (Unit* target = (*i))
|
||||
{
|
||||
if (Cloud && !Cloud->IsWithinDist(target, 6, false))
|
||||
Cloud->CastCustomSpell(target, SPELL_ZAP, &bp0, NULL, NULL, true, 0, 0, me->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
// visual
|
||||
float x, y, z;
|
||||
z = me->GetPositionZ();
|
||||
uint8 maxCount = 5 + rand32() % 5;
|
||||
for (uint8 i = 0; i < maxCount; ++i)
|
||||
{
|
||||
x = 343.0f + rand32() % 60;
|
||||
y = 1380.0f + rand32() % 60;
|
||||
if (Unit* trigger = me->SummonTrigger(x, y, z, 0, 2000))
|
||||
{
|
||||
trigger->setFaction(35);
|
||||
trigger->SetMaxHealth(100000);
|
||||
trigger->SetHealth(100000);
|
||||
trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
if (Cloud)
|
||||
Cloud->CastCustomSpell(trigger, /*43661*/SPELL_ZAP, &bp0, NULL, NULL, true, 0, 0, Cloud->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++StormCount;
|
||||
|
||||
if (StormCount > 10)
|
||||
{
|
||||
StormCount = 0; // finish
|
||||
events.ScheduleEvent(EVENT_SUMMON_EAGLES, 5000);
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
CloudGUID.Clear();
|
||||
if (Cloud)
|
||||
Cloud->DealDamage(Cloud, Cloud->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
|
||||
SetWeather(WEATHER_STATE_FINE, 0.0f);
|
||||
isRaining = false;
|
||||
}
|
||||
events.ScheduleEvent(EVENT_STORM_SEQUENCE, 1000);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -69,21 +230,149 @@ class boss_akilzon : public CreatureScript
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
/*
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_STATIC_DISRUPTION:
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
|
||||
if (!target)
|
||||
target = me->GetVictim();
|
||||
if (target)
|
||||
{
|
||||
TargetGUID = target->GetGUID();
|
||||
DoCast(target, SPELL_STATIC_DISRUPTION, false);
|
||||
me->SetInFront(me->GetVictim());
|
||||
}
|
||||
/*if (float dist = me->IsWithinDist3d(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 5.0f) dist = 5.0f;
|
||||
SDisruptAOEVisual_Timer = 1000 + floor(dist / 30 * 1000.0f);*/
|
||||
events.ScheduleEvent(EVENT_STATIC_DISRUPTION, urand(10000, 18000));
|
||||
break;
|
||||
}
|
||||
case EVENT_GUST_OF_WIND:
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1);
|
||||
if (!target)
|
||||
target = me->GetVictim();
|
||||
if (target)
|
||||
DoCast(target, SPELL_GUST_OF_WIND);
|
||||
events.ScheduleEvent(EVENT_GUST_OF_WIND, urand(20000, 30000));
|
||||
break;
|
||||
}
|
||||
case EVENT_CALL_LIGHTNING:
|
||||
DoCastVictim(SPELL_CALL_LIGHTNING);
|
||||
events.ScheduleEvent(EVENT_CALL_LIGHTNING, urand(12000, 17000)); // totaly random timer. can't find any info on this
|
||||
break;
|
||||
case EVENT_ELECTRICAL_STORM:
|
||||
{
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true);
|
||||
if (!target)
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
target->CastSpell(target, 44007, true); // cloud visual
|
||||
DoCast(target, SPELL_ELECTRICAL_STORM, false); // storm cyclon + visual
|
||||
float x, y, z;
|
||||
target->GetPosition(x, y, z);
|
||||
/// @todo: fix it in correct way, that causes player to can fly until logout
|
||||
/*
|
||||
if (target)
|
||||
{
|
||||
target->SetDisableGravity(true);
|
||||
target->MonsterMoveWithSpeed(x, y, me->GetPositionZ()+15, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
Unit* Cloud = me->SummonTrigger(x, y, me->GetPositionZ()+16, 0, 15000);
|
||||
if (Cloud)
|
||||
{
|
||||
CloudGUID = Cloud->GetGUID();
|
||||
Cloud->SetDisableGravity(true);
|
||||
Cloud->StopMoving();
|
||||
Cloud->SetObjectScale(1.0f);
|
||||
Cloud->setFaction(35);
|
||||
Cloud->SetMaxHealth(9999999);
|
||||
Cloud->SetHealth(9999999);
|
||||
Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
StormCount = 1;
|
||||
events.ScheduleEvent(EVENT_ELECTRICAL_STORM, 60000); // 60 seconds(bosskillers)
|
||||
events.ScheduleEvent(EVENT_RAIN, urand(47000, 52000));
|
||||
break;
|
||||
}
|
||||
case EVENT_RAIN:
|
||||
if (!isRaining)
|
||||
{
|
||||
SetWeather(WEATHER_STATE_HEAVY_RAIN, 0.9999f);
|
||||
isRaining = true;
|
||||
}
|
||||
else
|
||||
events.ScheduleEvent(EVENT_RAIN, 1000);
|
||||
break;
|
||||
case EVENT_STORM_SEQUENCE:
|
||||
{
|
||||
Unit* target = ObjectAccessor::GetUnit(*me, CloudGUID);
|
||||
if (!target || !target->IsAlive())
|
||||
{
|
||||
EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
else if (Unit* Cyclone = ObjectAccessor::GetUnit(*me, CycloneGUID))
|
||||
Cyclone->CastSpell(target, SPELL_SAND_STORM, true); // keep casting or...
|
||||
HandleStormSequence(target);
|
||||
break;
|
||||
}
|
||||
case EVENT_SUMMON_EAGLES:
|
||||
Talk(SAY_SUMMON);
|
||||
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
for (uint8 i = 0; i < 8; ++i)
|
||||
{
|
||||
Unit* bird = ObjectAccessor::GetUnit(*me, BirdGUIDs[i]);
|
||||
if (!bird) //they despawned on die
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
x = target->GetPositionX() + irand(-10, 10);
|
||||
y = target->GetPositionY() + irand(-10, 10);
|
||||
z = target->GetPositionZ() + urand(16, 20);
|
||||
if (z > 95)
|
||||
z = 95.0f - urand(0, 5);
|
||||
}
|
||||
Creature* creature = me->SummonCreature(NPC_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
if (creature)
|
||||
{
|
||||
creature->AddThreat(me->GetVictim(), 1.0f);
|
||||
creature->AI()->AttackStart(me->GetVictim());
|
||||
BirdGUIDs[i] = creature->GetGUID();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVENT_ENRAGE:
|
||||
Talk(SAY_ENRAGE);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
events.ScheduleEvent(EVENT_ENRAGE, 600000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid BirdGUIDs[8];
|
||||
ObjectGuid TargetGUID;
|
||||
ObjectGuid CycloneGUID;
|
||||
ObjectGuid CloudGUID;
|
||||
uint8 StormCount;
|
||||
bool isRaining;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
@@ -92,7 +381,99 @@ class boss_akilzon : public CreatureScript
|
||||
}
|
||||
};
|
||||
|
||||
class npc_akilzon_eagle : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_akilzon_eagle() : CreatureScript("npc_akilzon_eagle") { }
|
||||
|
||||
struct npc_akilzon_eagleAI : public ScriptedAI
|
||||
{
|
||||
npc_akilzon_eagleAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
EagleSwoop_Timer = urand(5000, 10000);
|
||||
arrived = true;
|
||||
TargetGUID.Clear();
|
||||
}
|
||||
|
||||
uint32 EagleSwoop_Timer;
|
||||
bool arrived;
|
||||
ObjectGuid TargetGUID;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
me->SetDisableGravity(true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void MovementInform(uint32, uint32) override
|
||||
{
|
||||
arrived = true;
|
||||
if (TargetGUID)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, TargetGUID))
|
||||
DoCast(target, SPELL_EAGLE_SWOOP, true);
|
||||
TargetGUID.Clear();
|
||||
me->SetSpeed(MOVE_RUN, 1.2f);
|
||||
EagleSwoop_Timer = urand(5000, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (EagleSwoop_Timer <= diff)
|
||||
EagleSwoop_Timer = 0;
|
||||
else
|
||||
EagleSwoop_Timer -= diff;
|
||||
|
||||
if (arrived)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
float x, y, z;
|
||||
if (EagleSwoop_Timer)
|
||||
{
|
||||
x = target->GetPositionX() + irand(-10, 10);
|
||||
y = target->GetPositionY() + irand(-10, 10);
|
||||
z = target->GetPositionZ() + urand(10, 15);
|
||||
if (z > 95)
|
||||
z = 95.0f - urand(0, 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
target->GetContactPoint(me, x, y, z);
|
||||
z += 2;
|
||||
me->SetSpeed(MOVE_RUN, 5.0f);
|
||||
TargetGUID = target->GetGUID();
|
||||
}
|
||||
me->GetMotionMaster()->MovePoint(0, x, y, z);
|
||||
arrived = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_akilzon_eagleAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_akilzon()
|
||||
{
|
||||
new boss_akilzon();
|
||||
new npc_akilzon_eagle();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -18,56 +19,187 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "zulaman.h"
|
||||
|
||||
enum Says
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_PLAYER_KILL = 1,
|
||||
SAY_MELEE = 2,
|
||||
SAY_SPLIT = 3,
|
||||
SAY_COMBINE = 4,
|
||||
SAY_DEATH = 5
|
||||
};
|
||||
#include "SpellInfo.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_DUAL_WIELD = 29651,
|
||||
SPELL_SABER_LASH = 43267,
|
||||
SPELL_FRENZY = 43139,
|
||||
SPELL_FLAMESHOCK = 43303,
|
||||
SPELL_EARTHSHOCK = 43305,
|
||||
SPELL_TRANSFORM_SPLIT = 43142,
|
||||
SPELL_TRANSFORM_SPLIT2 = 43573,
|
||||
SPELL_TRANSFORM_MERGE = 43271,
|
||||
SPELL_SUMMON_LYNX = 43143,
|
||||
SPELL_SUMMON_TOTEM = 43302,
|
||||
SPELL_BERSERK = 45078,
|
||||
SPELL_LYNX_FRENZY = 43290, // Used by Spirit Lynx
|
||||
SPELL_SHRED_ARMOR = 43243 // Used by Spirit Lynx
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum Hal_CreatureIds
|
||||
{
|
||||
NPC_SPIRIT_LYNX = 24143,
|
||||
NPC_TOTEM = 24224
|
||||
};
|
||||
|
||||
enum PhaseHalazzi
|
||||
{
|
||||
PHASE_NONE = 0,
|
||||
PHASE_LYNX = 1,
|
||||
PHASE_SPLIT = 2,
|
||||
PHASE_HUMAN = 3,
|
||||
PHASE_MERGE = 4,
|
||||
PHASE_ENRAGE = 5
|
||||
};
|
||||
|
||||
enum Yells
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_SABER = 1,
|
||||
SAY_SPLIT = 2,
|
||||
SAY_MERGE = 3,
|
||||
SAY_KILL = 4,
|
||||
SAY_DEATH = 5,
|
||||
SAY_BERSERK = 6
|
||||
};
|
||||
|
||||
class boss_halazzi : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
boss_halazzi() : CreatureScript("boss_halazzi") { }
|
||||
|
||||
struct boss_halazziAI : public BossAI
|
||||
struct boss_halazziAI : public ScriptedAI
|
||||
{
|
||||
boss_halazziAI(Creature* creature) : BossAI(creature, DATA_HALAZZI) { }
|
||||
boss_halazziAI(Creature* creature) : ScriptedAI(creature), summons(me)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
Phase = PHASE_NONE;
|
||||
FrenzyTimer = 0;
|
||||
SaberlashTimer = 0;
|
||||
ShockTimer = 0;
|
||||
TotemTimer = 0;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
LynxGUID.Clear();
|
||||
TransformCount = 0;
|
||||
BerserkTimer = 600000;
|
||||
CheckTimer = 1000;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
SummonList summons;
|
||||
PhaseHalazzi Phase;
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 SaberlashTimer;
|
||||
uint32 ShockTimer;
|
||||
uint32 TotemTimer;
|
||||
uint32 CheckTimer;
|
||||
uint32 BerserkTimer;
|
||||
uint32 TransformCount;
|
||||
|
||||
ObjectGuid LynxGUID;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
instance->SetData(DATA_HALAZZIEVENT, NOT_STARTED);
|
||||
summons.DespawnAll();
|
||||
|
||||
Initialize();
|
||||
|
||||
DoCast(me, SPELL_DUAL_WIELD, true);
|
||||
|
||||
Phase = PHASE_NONE;
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
instance->SetData(DATA_HALAZZIEVENT, IN_PROGRESS);
|
||||
Talk(SAY_AGGRO);
|
||||
_EnterCombat();
|
||||
EnterPhase(PHASE_LYNX);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
void JustSummoned(Creature* summon) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
summon->AI()->AttackStart(me->GetVictim());
|
||||
if (summon->GetEntry() == NPC_SPIRIT_LYNX)
|
||||
LynxGUID = summon->GetGUID();
|
||||
summons.Summon(summon);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_PLAYER_KILL);
|
||||
if (damage >= me->GetHealth() && Phase != PHASE_ENRAGE)
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void SpellHit(Unit*, const SpellInfo* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_TRANSFORM_SPLIT2)
|
||||
EnterPhase(PHASE_HUMAN);
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (Phase != PHASE_MERGE)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterPhase(PhaseHalazzi NextPhase)
|
||||
{
|
||||
switch (NextPhase)
|
||||
{
|
||||
case PHASE_LYNX:
|
||||
case PHASE_ENRAGE:
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
DoCast(me, SPELL_TRANSFORM_MERGE, true);
|
||||
me->Attack(me->GetVictim(), true);
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
}
|
||||
if (Creature* Lynx = ObjectAccessor::GetCreature(*me, LynxGUID))
|
||||
Lynx->DisappearAndDie();
|
||||
me->SetMaxHealth(600000);
|
||||
me->SetHealth(600000 - 150000 * TransformCount);
|
||||
FrenzyTimer = 16000;
|
||||
SaberlashTimer = 20000;
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_SPLIT:
|
||||
Talk(SAY_SPLIT);
|
||||
DoCast(me, SPELL_TRANSFORM_SPLIT, true);
|
||||
break;
|
||||
case PHASE_HUMAN:
|
||||
//DoCast(me, SPELL_SUMMON_LYNX, true);
|
||||
DoSpawnCreature(NPC_SPIRIT_LYNX, 5, 5, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
|
||||
me->SetMaxHealth(400000);
|
||||
me->SetHealth(400000);
|
||||
ShockTimer = 10000;
|
||||
TotemTimer = 12000;
|
||||
break;
|
||||
case PHASE_MERGE:
|
||||
if (Unit* pLynx = ObjectAccessor::GetUnit(*me, LynxGUID))
|
||||
{
|
||||
Talk(SAY_MERGE);
|
||||
pLynx->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
pLynx->GetMotionMaster()->Clear();
|
||||
pLynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MoveFollow(pLynx, 0, 0);
|
||||
++TransformCount;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Phase = NextPhase;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
@@ -75,32 +207,194 @@ class boss_halazzi : public CreatureScript
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
/*
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
if (BerserkTimer <= diff)
|
||||
{
|
||||
switch (eventId)
|
||||
Talk(SAY_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
BerserkTimer = 60000;
|
||||
} else BerserkTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (SaberlashTimer <= diff)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
// A tank with more than 490 defense skills should receive no critical hit
|
||||
//DoCast(me, 41296, true);
|
||||
DoCastVictim(SPELL_SABER_LASH, true);
|
||||
//me->RemoveAurasDueToSpell(41296);
|
||||
SaberlashTimer = 30000;
|
||||
} else SaberlashTimer -= diff;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_FRENZY);
|
||||
FrenzyTimer = urand(10000, 15000);
|
||||
} else FrenzyTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_LYNX)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (HealthBelowPct(25 * (3 - TransformCount)))
|
||||
EnterPhase(PHASE_SPLIT);
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (Phase == PHASE_HUMAN || Phase == PHASE_ENRAGE)
|
||||
{
|
||||
if (TotemTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_SUMMON_TOTEM);
|
||||
TotemTimer = 20000;
|
||||
} else TotemTimer -= diff;
|
||||
|
||||
if (ShockTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
if (target->IsNonMeleeSpellCast(false))
|
||||
DoCast(target, SPELL_EARTHSHOCK);
|
||||
else
|
||||
DoCast(target, SPELL_FLAMESHOCK);
|
||||
ShockTimer = urand(10000, 15000);
|
||||
}
|
||||
} else ShockTimer -= diff;
|
||||
|
||||
if (Phase == PHASE_HUMAN)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
if (!HealthAbovePct(20) /*HealthBelowPct(10)*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
else
|
||||
{
|
||||
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
|
||||
if (Lynx && !Lynx->HealthAbovePct(20) /*Lynx->HealthBelowPct(10)*/)
|
||||
EnterPhase(PHASE_MERGE);
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
if (Phase == PHASE_MERGE)
|
||||
{
|
||||
if (CheckTimer <= diff)
|
||||
{
|
||||
Unit* Lynx = ObjectAccessor::GetUnit(*me, LynxGUID);
|
||||
if (Lynx)
|
||||
{
|
||||
Lynx->GetMotionMaster()->MoveFollow(me, 0, 0);
|
||||
me->GetMotionMaster()->MoveFollow(Lynx, 0, 0);
|
||||
if (me->IsWithinDistInMap(Lynx, 6.0f))
|
||||
{
|
||||
if (TransformCount < 3)
|
||||
EnterPhase(PHASE_LYNX);
|
||||
else
|
||||
EnterPhase(PHASE_ENRAGE);
|
||||
}
|
||||
}
|
||||
CheckTimer = 1000;
|
||||
} else CheckTimer -= diff;
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
instance->SetData(DATA_HALAZZIEVENT, DONE);
|
||||
Talk(SAY_DEATH);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetZulAmanAI<boss_halazziAI>(creature);
|
||||
return GetInstanceAI<boss_halazziAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
// Spirits Lynx AI
|
||||
class npc_halazzi_lynx : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_halazzi_lynx() : CreatureScript("npc_halazzi_lynx") { }
|
||||
|
||||
struct npc_halazzi_lynxAI : public ScriptedAI
|
||||
{
|
||||
npc_halazzi_lynxAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
|
||||
shredder_timer = 4000;
|
||||
}
|
||||
|
||||
uint32 FrenzyTimer;
|
||||
uint32 shredder_timer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*done_by*/, uint32 &damage) override
|
||||
{
|
||||
if (damage >= me->GetHealth())
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override {/*DoZoneInCombat();*/ }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (FrenzyTimer <= diff)
|
||||
{
|
||||
DoCast(me, SPELL_LYNX_FRENZY);
|
||||
FrenzyTimer = urand(30000, 50000); //frenzy every 30-50 seconds
|
||||
} else FrenzyTimer -= diff;
|
||||
|
||||
if (shredder_timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_SHRED_ARMOR);
|
||||
shredder_timer = 4000;
|
||||
} else shredder_timer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_halazzi_lynxAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_halazzi()
|
||||
{
|
||||
new boss_halazzi();
|
||||
new npc_halazzi_lynx();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -15,83 +16,430 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Janalai
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Zul'Aman
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "zulaman.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "CellImpl.h"
|
||||
|
||||
enum Says
|
||||
enum Yells
|
||||
{
|
||||
SAY_AGGRO = 0,
|
||||
SAY_PLAYER_KILL = 1,
|
||||
SAY_SUMMON_HATCHER = 2,
|
||||
SAY_FIRE_BOMB = 3,
|
||||
SAY_HATCH_ALL_EGGS = 4,
|
||||
EMOTE_FRENZY = 5,
|
||||
SAY_DEATH = 6
|
||||
SAY_AGGRO = 0,
|
||||
SAY_FIRE_BOMBS = 1,
|
||||
SAY_SUMMON_HATCHER = 2,
|
||||
SAY_ALL_EGGS = 3,
|
||||
SAY_BERSERK = 4,
|
||||
SAY_SLAY = 5,
|
||||
SAY_DEATH = 6,
|
||||
SAY_EVENT_STRANGERS = 7,
|
||||
SAY_EVENT_FRIENDS = 8
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Jan'alai
|
||||
SPELL_FLAME_BREATH = 43140,
|
||||
SPELL_FIRE_WALL = 43113,
|
||||
SPELL_ENRAGE = 44779,
|
||||
SPELL_SUMMON_PLAYERS = 43097,
|
||||
SPELL_TELE_TO_CENTER = 43098, // coord
|
||||
SPELL_HATCH_ALL = 43144,
|
||||
SPELL_BERSERK = 45078,
|
||||
|
||||
// Fire Bob Spells
|
||||
SPELL_FIRE_BOMB_CHANNEL = 42621, // last forever
|
||||
SPELL_FIRE_BOMB_THROW = 42628, // throw visual
|
||||
SPELL_FIRE_BOMB_DUMMY = 42629, // bomb visual
|
||||
SPELL_FIRE_BOMB_DAMAGE = 42630,
|
||||
|
||||
// Hatcher Spells
|
||||
SPELL_HATCH_EGG = 42471, // 43734
|
||||
SPELL_SUMMON_HATCHLING = 42493,
|
||||
|
||||
// Hatchling Spells
|
||||
SPELL_FLAMEBUFFET = 43299
|
||||
};
|
||||
|
||||
enum Events
|
||||
enum Creatures
|
||||
{
|
||||
NPC_AMANI_HATCHER = 23818,
|
||||
NPC_HATCHLING = 23598, // 42493
|
||||
NPC_EGG = 23817,
|
||||
NPC_FIRE_BOMB = 23920
|
||||
};
|
||||
|
||||
const int area_dx = 44;
|
||||
const int area_dy = 51;
|
||||
|
||||
float JanalainPos[1][3] =
|
||||
{
|
||||
{-33.93f, 1149.27f, 19}
|
||||
};
|
||||
|
||||
float FireWallCoords[4][4] =
|
||||
{
|
||||
{-10.13f, 1149.27f, 19, 3.1415f},
|
||||
{-33.93f, 1123.90f, 19, 0.5f*3.1415f},
|
||||
{-54.80f, 1150.08f, 19, 0},
|
||||
{-33.93f, 1175.68f, 19, 1.5f*3.1415f}
|
||||
};
|
||||
|
||||
float hatcherway[2][5][3] =
|
||||
{
|
||||
{
|
||||
{-87.46f, 1170.09f, 6},
|
||||
{-74.41f, 1154.75f, 6},
|
||||
{-52.74f, 1153.32f, 19},
|
||||
{-33.37f, 1172.46f, 19},
|
||||
{-33.09f, 1203.87f, 19}
|
||||
},
|
||||
{
|
||||
{-86.57f, 1132.85f, 6},
|
||||
{-73.94f, 1146.00f, 6},
|
||||
{-52.29f, 1146.51f, 19},
|
||||
{-33.57f, 1125.72f, 19},
|
||||
{-34.29f, 1095.22f, 19}
|
||||
}
|
||||
};
|
||||
class boss_janalai : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
boss_janalai() : CreatureScript("boss_janalai") { }
|
||||
|
||||
struct boss_janalaiAI : public BossAI
|
||||
boss_janalai()
|
||||
: CreatureScript("boss_janalai")
|
||||
{
|
||||
boss_janalaiAI(Creature* creature) : BossAI(creature, DATA_JANALAI) { }
|
||||
}
|
||||
|
||||
struct boss_janalaiAI : public ScriptedAI
|
||||
{
|
||||
boss_janalaiAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
FireBreathTimer = 8000;
|
||||
BombTimer = 30000;
|
||||
BombSequenceTimer = 1000;
|
||||
BombCount = 0;
|
||||
HatcherTimer = 10000;
|
||||
EnrageTimer = MINUTE * 5 * IN_MILLISECONDS;
|
||||
|
||||
noeggs = false;
|
||||
isBombing = false;
|
||||
enraged = false;
|
||||
|
||||
isFlameBreathing = false;
|
||||
|
||||
for (uint8 i = 0; i < 40; ++i)
|
||||
FireBombGUIDs[i].Clear();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 FireBreathTimer;
|
||||
uint32 BombTimer;
|
||||
uint32 BombSequenceTimer;
|
||||
uint32 BombCount;
|
||||
uint32 HatcherTimer;
|
||||
uint32 EnrageTimer;
|
||||
|
||||
bool noeggs;
|
||||
bool enraged;
|
||||
bool isBombing;
|
||||
|
||||
bool isFlameBreathing;
|
||||
|
||||
ObjectGuid FireBombGUIDs[40];
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
}
|
||||
instance->SetData(DATA_JANALAIEVENT, NOT_STARTED);
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_EnterCombat();
|
||||
Initialize();
|
||||
|
||||
HatchAllEggs(1);
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
|
||||
instance->SetData(DATA_JANALAIEVENT, DONE);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_PLAYER_KILL);
|
||||
Talk(SAY_SLAY);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
instance->SetData(DATA_JANALAIEVENT, IN_PROGRESS);
|
||||
|
||||
Talk(SAY_AGGRO);
|
||||
// DoZoneInCombat();
|
||||
}
|
||||
|
||||
void DamageDealt(Unit* target, uint32 &damage, DamageEffectType /*damagetype*/) override
|
||||
{
|
||||
if (isFlameBreathing)
|
||||
{
|
||||
if (!me->HasInArc(float(M_PI) / 6, target))
|
||||
damage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FireWall()
|
||||
{
|
||||
uint8 WallNum;
|
||||
Creature* wall = NULL;
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
if (i == 0 || i == 2)
|
||||
WallNum = 3;
|
||||
else
|
||||
WallNum = 2;
|
||||
|
||||
for (uint8 j = 0; j < WallNum; j++)
|
||||
{
|
||||
if (WallNum == 3)
|
||||
wall = me->SummonCreature(NPC_FIRE_BOMB, FireWallCoords[i][0], FireWallCoords[i][1]+5*(j-1), FireWallCoords[i][2], FireWallCoords[i][3], TEMPSUMMON_TIMED_DESPAWN, 15000);
|
||||
else
|
||||
wall = me->SummonCreature(NPC_FIRE_BOMB, FireWallCoords[i][0]-2+4*j, FireWallCoords[i][1], FireWallCoords[i][2], FireWallCoords[i][3], TEMPSUMMON_TIMED_DESPAWN, 15000);
|
||||
if (wall) wall->CastSpell(wall, SPELL_FIRE_WALL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnBombs()
|
||||
{
|
||||
float dx, dy;
|
||||
for (int i(0); i < 40; ++i)
|
||||
{
|
||||
dx = float(irand(-area_dx/2, area_dx/2));
|
||||
dy = float(irand(-area_dy/2, area_dy/2));
|
||||
|
||||
Creature* bomb = DoSpawnCreature(NPC_FIRE_BOMB, dx, dy, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
|
||||
if (bomb)
|
||||
FireBombGUIDs[i] = bomb->GetGUID();
|
||||
}
|
||||
BombCount = 0;
|
||||
}
|
||||
|
||||
bool HatchAllEggs(uint32 action) //1: reset, 2: isHatching all
|
||||
{
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
{
|
||||
CellCoord pair(Trinity::ComputeCellCoord(x, y));
|
||||
Cell cell(pair);
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::AllCreaturesOfEntryInRange check(me, NPC_EGG, 100);
|
||||
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher);
|
||||
|
||||
cell.Visit(pair, cSearcher, *me->GetMap(), *me, me->GetGridActivationRange());
|
||||
}
|
||||
|
||||
//TC_LOG_ERROR("scripts", "Eggs %d at middle", templist.size());
|
||||
if (templist.empty())
|
||||
return false;
|
||||
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
|
||||
{
|
||||
if (action == 1)
|
||||
(*i)->SetDisplayId(10056);
|
||||
else if (action == 2 &&(*i)->GetDisplayId() != 11686)
|
||||
(*i)->CastSpell(*i, SPELL_HATCH_EGG, false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Boom()
|
||||
{
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
{
|
||||
CellCoord pair(Trinity::ComputeCellCoord(x, y));
|
||||
Cell cell(pair);
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::AllCreaturesOfEntryInRange check(me, NPC_FIRE_BOMB, 100);
|
||||
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher);
|
||||
|
||||
cell.Visit(pair, cSearcher, *me->GetMap(), *me, me->GetGridActivationRange());
|
||||
}
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
|
||||
{
|
||||
(*i)->CastSpell(*i, SPELL_FIRE_BOMB_DAMAGE, true);
|
||||
(*i)->RemoveAllAuras();
|
||||
}
|
||||
}
|
||||
|
||||
void HandleBombSequence()
|
||||
{
|
||||
if (BombCount < 40)
|
||||
{
|
||||
if (Unit* FireBomb = ObjectAccessor::GetUnit(*me, FireBombGUIDs[BombCount]))
|
||||
{
|
||||
FireBomb->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoCast(FireBomb, SPELL_FIRE_BOMB_THROW, true);
|
||||
FireBomb->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
}
|
||||
++BombCount;
|
||||
if (BombCount == 40)
|
||||
{
|
||||
BombSequenceTimer = 5000;
|
||||
} else BombSequenceTimer = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
Boom();
|
||||
isBombing = false;
|
||||
BombTimer = urand(20000, 40000);
|
||||
me->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL);
|
||||
if (EnrageTimer <= 10000)
|
||||
EnrageTimer = 0;
|
||||
else
|
||||
EnrageTimer -= 10000;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (isFlameBreathing)
|
||||
{
|
||||
if (!me->IsNonMeleeSpellCast(false))
|
||||
isFlameBreathing = false;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBombing)
|
||||
{
|
||||
if (BombSequenceTimer <= diff)
|
||||
HandleBombSequence();
|
||||
else
|
||||
BombSequenceTimer -= diff;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
//enrage if under 25% hp before 5 min.
|
||||
if (!enraged && HealthBelowPct(25))
|
||||
EnrageTimer = 0;
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
/*
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
if (EnrageTimer <= diff)
|
||||
{
|
||||
switch (eventId)
|
||||
if (!enraged)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
DoCast(me, SPELL_ENRAGE, true);
|
||||
enraged = true;
|
||||
EnrageTimer = 300000;
|
||||
}
|
||||
else
|
||||
{
|
||||
Talk(SAY_BERSERK);
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
EnrageTimer = 300000;
|
||||
}
|
||||
} else EnrageTimer -= diff;
|
||||
|
||||
if (BombTimer <= diff)
|
||||
{
|
||||
Talk(SAY_FIRE_BOMBS);
|
||||
|
||||
me->AttackStop();
|
||||
me->GetMotionMaster()->Clear();
|
||||
DoTeleportTo(JanalainPos[0][0], JanalainPos[0][1], JanalainPos[0][2]);
|
||||
me->StopMoving();
|
||||
DoCast(me, SPELL_FIRE_BOMB_CHANNEL, false);
|
||||
//DoTeleportPlayer(me, JanalainPos[0][0], JanalainPos[0][1], JanalainPos[0][2], 0);
|
||||
//DoCast(me, SPELL_TELE_TO_CENTER, true);
|
||||
|
||||
FireWall();
|
||||
SpawnBombs();
|
||||
isBombing = true;
|
||||
BombSequenceTimer = 100;
|
||||
|
||||
//Teleport every Player into the middle
|
||||
Map* map = me->GetMap();
|
||||
if (!map->IsDungeon())
|
||||
return;
|
||||
|
||||
Map::PlayerList const &PlayerList = map->GetPlayers();
|
||||
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
|
||||
if (Player* i_pl = i->GetSource())
|
||||
if (i_pl->IsAlive())
|
||||
DoTeleportPlayer(i_pl, JanalainPos[0][0] - 5 + rand32() % 10, JanalainPos[0][1] - 5 + rand32() % 10, JanalainPos[0][2], 0);
|
||||
//DoCast(Temp, SPELL_SUMMON_PLAYERS, true) // core bug, spell does not work if too far
|
||||
return;
|
||||
} else BombTimer -= diff;
|
||||
|
||||
if (!noeggs)
|
||||
{
|
||||
if (HealthBelowPct(35))
|
||||
{
|
||||
Talk(SAY_ALL_EGGS);
|
||||
|
||||
me->AttackStop();
|
||||
me->GetMotionMaster()->Clear();
|
||||
DoTeleportTo(JanalainPos[0][0], JanalainPos[0][1], JanalainPos[0][2]);
|
||||
me->StopMoving();
|
||||
DoCast(me, SPELL_HATCH_ALL, false);
|
||||
HatchAllEggs(2);
|
||||
noeggs = true;
|
||||
}
|
||||
else if (HatcherTimer <= diff)
|
||||
{
|
||||
if (HatchAllEggs(0))
|
||||
{
|
||||
Talk(SAY_SUMMON_HATCHER);
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[0][0][0], hatcherway[0][0][1], hatcherway[0][0][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
me->SummonCreature(NPC_AMANI_HATCHER, hatcherway[1][0][0], hatcherway[1][0][1], hatcherway[1][0][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
|
||||
HatcherTimer = 90000;
|
||||
}
|
||||
else
|
||||
noeggs = true;
|
||||
} else HatcherTimer -= diff;
|
||||
}
|
||||
*/
|
||||
|
||||
EnterEvadeIfOutOfCombatArea(diff);
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
|
||||
if (FireBreathTimer <= diff)
|
||||
{
|
||||
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
|
||||
{
|
||||
me->AttackStop();
|
||||
me->GetMotionMaster()->Clear();
|
||||
DoCast(target, SPELL_FLAME_BREATH, false);
|
||||
me->StopMoving();
|
||||
isFlameBreathing = true;
|
||||
}
|
||||
FireBreathTimer = 8000;
|
||||
} else FireBreathTimer -= diff;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,7 +449,283 @@ class boss_janalai : public CreatureScript
|
||||
}
|
||||
};
|
||||
|
||||
class npc_janalai_firebomb : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
npc_janalai_firebomb()
|
||||
: CreatureScript("npc_janalai_firebomb")
|
||||
{
|
||||
}
|
||||
|
||||
struct npc_janalai_firebombAI : public ScriptedAI
|
||||
{
|
||||
npc_janalai_firebombAI(Creature* creature) : ScriptedAI(creature){ }
|
||||
|
||||
void Reset() override { }
|
||||
|
||||
void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_FIRE_BOMB_THROW)
|
||||
DoCast(me, SPELL_FIRE_BOMB_DUMMY, true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override { }
|
||||
|
||||
void AttackStart(Unit* /*who*/) override { }
|
||||
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override { }
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_janalai_firebombAI(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_janalai_hatcher : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
npc_janalai_hatcher()
|
||||
: CreatureScript("npc_janalai_hatcher")
|
||||
{
|
||||
}
|
||||
|
||||
struct npc_janalai_hatcherAI : public ScriptedAI
|
||||
{
|
||||
npc_janalai_hatcherAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
waypoint = 0;
|
||||
isHatching = false;
|
||||
hasChangedSide = false;
|
||||
WaitTimer = 1;
|
||||
HatchNum = 0;
|
||||
side = false;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 waypoint;
|
||||
uint32 HatchNum;
|
||||
uint32 WaitTimer;
|
||||
|
||||
bool side;
|
||||
bool hasChangedSide;
|
||||
bool isHatching;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
me->SetWalk(true);
|
||||
Initialize();
|
||||
side =(me->GetPositionY() < 1150);
|
||||
}
|
||||
|
||||
bool HatchEggs(uint32 num)
|
||||
{
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
{
|
||||
CellCoord pair(Trinity::ComputeCellCoord(x, y));
|
||||
Cell cell(pair);
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::AllCreaturesOfEntryInRange check(me, 23817, 50);
|
||||
Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, templist, check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher);
|
||||
|
||||
cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange());
|
||||
}
|
||||
|
||||
//TC_LOG_ERROR("scripts", "Eggs %d at %d", templist.size(), side);
|
||||
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end() && num > 0; ++i)
|
||||
if ((*i)->GetDisplayId() != 11686)
|
||||
{
|
||||
(*i)->CastSpell(*i, SPELL_HATCH_EGG, false);
|
||||
num--;
|
||||
}
|
||||
|
||||
return num == 0; // if num == 0, no more templist
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override { }
|
||||
void AttackStart(Unit* /*who*/) override { }
|
||||
void MoveInLineOfSight(Unit* /*who*/) override { }
|
||||
|
||||
void MovementInform(uint32, uint32) override
|
||||
{
|
||||
if (waypoint == 5)
|
||||
{
|
||||
isHatching = true;
|
||||
HatchNum = 1;
|
||||
WaitTimer = 5000;
|
||||
}
|
||||
else
|
||||
WaitTimer = 1;
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!instance || !(instance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS))
|
||||
{
|
||||
me->DisappearAndDie();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isHatching)
|
||||
{
|
||||
if (WaitTimer)
|
||||
{
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->GetMotionMaster()->MovePoint(0, hatcherway[side][waypoint][0], hatcherway[side][waypoint][1], hatcherway[side][waypoint][2]);
|
||||
++waypoint;
|
||||
WaitTimer = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (WaitTimer <= diff)
|
||||
{
|
||||
if (HatchEggs(HatchNum))
|
||||
{
|
||||
++HatchNum;
|
||||
WaitTimer = 10000;
|
||||
}
|
||||
else if (!hasChangedSide)
|
||||
{
|
||||
side = side ? 0 : 1;
|
||||
isHatching = false;
|
||||
waypoint = 3;
|
||||
WaitTimer = 1;
|
||||
hasChangedSide = true;
|
||||
}
|
||||
else
|
||||
me->DisappearAndDie();
|
||||
|
||||
} else WaitTimer -= diff;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_janalai_hatcherAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_janalai_hatchling : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
npc_janalai_hatchling()
|
||||
: CreatureScript("npc_janalai_hatchling")
|
||||
{
|
||||
}
|
||||
|
||||
struct npc_janalai_hatchlingAI : public ScriptedAI
|
||||
{
|
||||
npc_janalai_hatchlingAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
BuffetTimer = 7000;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
uint32 BuffetTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
Initialize();
|
||||
if (me->GetPositionY() > 1150)
|
||||
me->GetMotionMaster()->MovePoint(0, hatcherway[0][3][0] + rand32() % 4 - 2, 1150.0f + rand32() % 4 - 2, hatcherway[0][3][2]);
|
||||
else
|
||||
me->GetMotionMaster()->MovePoint(0, hatcherway[1][3][0] + rand32() % 4 - 2, 1150.0f + rand32() % 4 - 2, hatcherway[1][3][2]);
|
||||
|
||||
me->SetDisableGravity(true);
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override {/*DoZoneInCombat();*/ }
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!instance || !(instance->GetData(DATA_JANALAIEVENT) == IN_PROGRESS))
|
||||
{
|
||||
me->DisappearAndDie();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (BuffetTimer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_FLAMEBUFFET, false);
|
||||
BuffetTimer = 10000;
|
||||
} else BuffetTimer -= diff;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_janalai_hatchlingAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_janalai_egg : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_janalai_egg(): CreatureScript("npc_janalai_egg") { }
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return new npc_janalai_eggAI(creature);
|
||||
}
|
||||
|
||||
struct npc_janalai_eggAI : public ScriptedAI
|
||||
{
|
||||
npc_janalai_eggAI(Creature* creature) : ScriptedAI(creature){ }
|
||||
|
||||
void Reset() override { }
|
||||
|
||||
void UpdateAI(uint32 /*diff*/) override { }
|
||||
|
||||
void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_HATCH_EGG)
|
||||
{
|
||||
DoCast(SPELL_SUMMON_HATCHLING);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
void AddSC_boss_janalai()
|
||||
{
|
||||
new boss_janalai();
|
||||
new npc_janalai_firebomb();
|
||||
new npc_janalai_hatcher();
|
||||
new npc_janalai_hatchling();
|
||||
new npc_janalai_egg();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -15,86 +16,444 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Boss_Nalorakk
|
||||
SD%Complete: 100
|
||||
SDComment:
|
||||
SDCategory: Zul'Aman
|
||||
EndScriptData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "zulaman.h"
|
||||
|
||||
enum Says
|
||||
{
|
||||
SAY_WAVE_1 = 0,
|
||||
SAY_WAVE_2 = 1,
|
||||
SAY_WAVE_3 = 2,
|
||||
SAY_WAVE_4 = 3,
|
||||
SAY_AGGRO = 4,
|
||||
SAY_PLAYER_KILL = 5,
|
||||
SAY_SURGE = 6,
|
||||
EMOTE_SURGE = 7,
|
||||
EMOTE_BEAR = 8,
|
||||
SAY_BEAR = 9,
|
||||
SAY_TROLL = 10,
|
||||
SAY_DEATH = 11
|
||||
};
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
#include "CellImpl.h"
|
||||
|
||||
enum Spells
|
||||
{
|
||||
SPELL_BERSERK = 45078,
|
||||
|
||||
// Troll form
|
||||
SPELL_BRUTALSWIPE = 42384,
|
||||
SPELL_MANGLE = 42389,
|
||||
SPELL_MANGLEEFFECT = 44955,
|
||||
SPELL_SURGE = 42402,
|
||||
SPELL_BEARFORM = 42377,
|
||||
|
||||
// Bear form
|
||||
SPELL_LACERATINGSLASH = 42395,
|
||||
SPELL_RENDFLESH = 42397,
|
||||
SPELL_DEAFENINGROAR = 42398
|
||||
};
|
||||
|
||||
enum Events
|
||||
// Trash Waves
|
||||
float NalorakkWay[8][3] =
|
||||
{
|
||||
{ 18.569f, 1414.512f, 11.42f}, // waypoint 1
|
||||
{-17.264f, 1419.551f, 12.62f},
|
||||
{-52.642f, 1419.357f, 27.31f}, // waypoint 2
|
||||
{-69.908f, 1419.721f, 27.31f},
|
||||
{-79.929f, 1395.958f, 27.31f},
|
||||
{-80.072f, 1374.555f, 40.87f}, // waypoint 3
|
||||
{-80.072f, 1314.398f, 40.87f},
|
||||
{-80.072f, 1295.775f, 48.60f} // waypoint 4
|
||||
};
|
||||
|
||||
#define YELL_NALORAKK_WAVE1 "Get da move on, guards! It be killin' time!"
|
||||
#define SOUND_NALORAKK_WAVE1 12066
|
||||
#define YELL_NALORAKK_WAVE2 "Guards, go already! Who you more afraid of, dem... or me?"
|
||||
#define SOUND_NALORAKK_WAVE2 12067
|
||||
#define YELL_NALORAKK_WAVE3 "Ride now! Ride out dere and bring me back some heads!"
|
||||
#define SOUND_NALORAKK_WAVE3 12068
|
||||
#define YELL_NALORAKK_WAVE4 "I be losin' me patience! Go on: make dem wish dey was never born!"
|
||||
#define SOUND_NALORAKK_WAVE4 12069
|
||||
|
||||
//Unimplemented SoundIDs
|
||||
/*
|
||||
#define SOUND_NALORAKK_EVENT1 12078
|
||||
#define SOUND_NALORAKK_EVENT2 12079
|
||||
*/
|
||||
|
||||
//General defines
|
||||
#define YELL_AGGRO "You be dead soon enough!"
|
||||
#define SOUND_YELL_AGGRO 12070
|
||||
#define YELL_KILL_ONE "Mua-ha-ha! Now whatchoo got to say?"
|
||||
#define SOUND_YELL_KILL_ONE 12075
|
||||
#define YELL_KILL_TWO "Da Amani gonna rule again!"
|
||||
#define SOUND_YELL_KILL_TWO 12076
|
||||
#define YELL_DEATH "I... be waitin' on da udda side...."
|
||||
#define SOUND_YELL_DEATH 12077
|
||||
#define YELL_BERSERK "You had your chance, now it be too late!" //Never seen this being used, so just guessing from what I hear.
|
||||
#define SOUND_YELL_BERSERK 12074
|
||||
#define YELL_SURGE "I bring da pain!"
|
||||
#define SOUND_YELL_SURGE 12071
|
||||
|
||||
#define YELL_SHIFTEDTOTROLL "Make way for Nalorakk!"
|
||||
#define SOUND_YELL_TOTROLL 12073
|
||||
|
||||
|
||||
#define YELL_SHIFTEDTOBEAR "You call on da beast, you gonna get more dan you bargain for!"
|
||||
#define SOUND_YELL_TOBEAR 12072
|
||||
|
||||
class boss_nalorakk : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
boss_nalorakk() : CreatureScript("boss_nalorakk") { }
|
||||
|
||||
struct boss_nalorakkAI : public BossAI
|
||||
boss_nalorakk()
|
||||
: CreatureScript("boss_nalorakk")
|
||||
{
|
||||
boss_nalorakkAI(Creature* creature) : BossAI(creature, DATA_NALORAKK) { }
|
||||
}
|
||||
|
||||
struct boss_nalorakkAI : public ScriptedAI
|
||||
{
|
||||
boss_nalorakkAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
Initialize();
|
||||
inMove = false;
|
||||
MoveEvent = true;
|
||||
MovePhase = 0;
|
||||
waitTimer = 0;
|
||||
LaceratingSlash_Timer = 0;
|
||||
RendFlesh_Timer = 0;
|
||||
DeafeningRoar_Timer = 0;
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Surge_Timer = urand(15000, 20000);
|
||||
BrutalSwipe_Timer = urand(7000, 12000);
|
||||
Mangle_Timer = urand(10000, 15000);
|
||||
ShapeShift_Timer = urand(45000, 50000);
|
||||
Berserk_Timer = 600000;
|
||||
|
||||
inBearForm = false;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint32 BrutalSwipe_Timer;
|
||||
uint32 Mangle_Timer;
|
||||
uint32 Surge_Timer;
|
||||
|
||||
uint32 LaceratingSlash_Timer;
|
||||
uint32 RendFlesh_Timer;
|
||||
uint32 DeafeningRoar_Timer;
|
||||
|
||||
uint32 ShapeShift_Timer;
|
||||
uint32 Berserk_Timer;
|
||||
|
||||
bool inBearForm;
|
||||
bool MoveEvent;
|
||||
bool inMove;
|
||||
uint32 MovePhase;
|
||||
uint32 waitTimer;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
if (MoveEvent)
|
||||
{
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
inMove = false;
|
||||
waitTimer = 0;
|
||||
me->SetSpeed(MOVE_RUN, 2);
|
||||
me->SetWalk(false);
|
||||
}else
|
||||
{
|
||||
(*me).GetMotionMaster()->MovePoint(0, NalorakkWay[7][0], NalorakkWay[7][1], NalorakkWay[7][2]);
|
||||
}
|
||||
|
||||
instance->SetData(DATA_NALORAKKEVENT, NOT_STARTED);
|
||||
|
||||
Initialize();
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); /// @todo find the correct equipment id
|
||||
}
|
||||
|
||||
void SendAttacker(Unit* target)
|
||||
{
|
||||
std::list<Creature*> templist;
|
||||
float x, y, z;
|
||||
me->GetPosition(x, y, z);
|
||||
|
||||
{
|
||||
CellCoord pair(Trinity::ComputeCellCoord(x, y));
|
||||
Cell cell(pair);
|
||||
cell.SetNoCreate();
|
||||
|
||||
Trinity::AllFriendlyCreaturesInGrid check(me);
|
||||
Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(me, templist, check);
|
||||
|
||||
TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> cSearcher(searcher);
|
||||
|
||||
cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange());
|
||||
}
|
||||
|
||||
if (templist.empty())
|
||||
return;
|
||||
|
||||
for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i)
|
||||
{
|
||||
if ((*i) && me->IsWithinDistInMap((*i), 25))
|
||||
{
|
||||
(*i)->SetNoCallAssistance(true);
|
||||
(*i)->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AttackStart(Unit* who) override
|
||||
{
|
||||
if (!MoveEvent)
|
||||
ScriptedAI::AttackStart(who);
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
|
||||
{
|
||||
if (!MoveEvent)
|
||||
{
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (me->IsHostileTo(who))
|
||||
{
|
||||
if (!inMove)
|
||||
{
|
||||
switch (MovePhase)
|
||||
{
|
||||
case 0:
|
||||
if (me->IsWithinDistInMap(who, 50))
|
||||
{
|
||||
me->Yell(YELL_NALORAKK_WAVE1, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE1);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(1, NalorakkWay[1][0], NalorakkWay[1][1], NalorakkWay[1][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (me->IsWithinDistInMap(who, 40))
|
||||
{
|
||||
me->Yell(YELL_NALORAKK_WAVE2, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE2);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(3, NalorakkWay[3][0], NalorakkWay[3][1], NalorakkWay[3][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (me->IsWithinDistInMap(who, 40))
|
||||
{
|
||||
me->Yell(YELL_NALORAKK_WAVE3, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE3);
|
||||
|
||||
(*me).GetMotionMaster()->MovePoint(6, NalorakkWay[6][0], NalorakkWay[6][1], NalorakkWay[6][2]);
|
||||
MovePhase ++;
|
||||
inMove = true;
|
||||
|
||||
SendAttacker(who);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
if (me->IsWithinDistInMap(who, 50))
|
||||
{
|
||||
SendAttacker(who);
|
||||
|
||||
me->Yell(YELL_NALORAKK_WAVE4, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_NALORAKK_WAVE4);
|
||||
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
MoveEvent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_EnterCombat();
|
||||
instance->SetData(DATA_NALORAKKEVENT, IN_PROGRESS);
|
||||
|
||||
me->Yell(YELL_AGGRO, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_AGGRO);
|
||||
DoZoneInCombat();
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DEATH);
|
||||
_JustDied();
|
||||
instance->SetData(DATA_NALORAKKEVENT, DONE);
|
||||
|
||||
me->Yell(YELL_DEATH, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_DEATH);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* victim) override
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER)
|
||||
Talk(SAY_PLAYER_KILL);
|
||||
switch (urand(0, 1))
|
||||
{
|
||||
case 0:
|
||||
me->Yell(YELL_KILL_ONE, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_KILL_ONE);
|
||||
break;
|
||||
case 1:
|
||||
me->Yell(YELL_KILL_TWO, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_KILL_TWO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 type, uint32 id) override
|
||||
{
|
||||
if (MoveEvent)
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (!inMove)
|
||||
return;
|
||||
|
||||
if (MovePhase != id)
|
||||
return;
|
||||
|
||||
switch (MovePhase)
|
||||
{
|
||||
case 2:
|
||||
me->SetOrientation(3.1415f*2);
|
||||
inMove = false;
|
||||
return;
|
||||
case 1:
|
||||
case 3:
|
||||
case 4:
|
||||
case 6:
|
||||
MovePhase ++;
|
||||
waitTimer = 1;
|
||||
inMove = true;
|
||||
return;
|
||||
case 5:
|
||||
me->SetOrientation(3.1415f*0.5f);
|
||||
inMove = false;
|
||||
return;
|
||||
case 7:
|
||||
me->SetOrientation(3.1415f*0.5f);
|
||||
inMove = false;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (waitTimer && inMove)
|
||||
{
|
||||
if (waitTimer <= diff)
|
||||
{
|
||||
(*me).GetMotionMaster()->MovementExpired();
|
||||
(*me).GetMotionMaster()->MovePoint(MovePhase, NalorakkWay[MovePhase][0], NalorakkWay[MovePhase][1], NalorakkWay[MovePhase][2]);
|
||||
waitTimer = 0;
|
||||
} else waitTimer -= diff;
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
/*
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
if (Berserk_Timer <= diff)
|
||||
{
|
||||
switch (eventId)
|
||||
DoCast(me, SPELL_BERSERK, true);
|
||||
me->Yell(YELL_BERSERK, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_BERSERK);
|
||||
Berserk_Timer = 600000;
|
||||
} else Berserk_Timer -= diff;
|
||||
|
||||
if (ShapeShift_Timer <= diff)
|
||||
{
|
||||
if (inBearForm)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122);
|
||||
me->Yell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_TOTROLL);
|
||||
me->RemoveAurasDueToSpell(SPELL_BEARFORM);
|
||||
Surge_Timer = urand(15000, 20000);
|
||||
BrutalSwipe_Timer = urand(7000, 12000);
|
||||
Mangle_Timer = urand(10000, 15000);
|
||||
ShapeShift_Timer = urand(45000, 50000);
|
||||
inBearForm = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0);
|
||||
me->Yell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_TOBEAR);
|
||||
DoCast(me, SPELL_BEARFORM, true);
|
||||
LaceratingSlash_Timer = 2000; // dur 18s
|
||||
RendFlesh_Timer = 3000; // dur 5s
|
||||
DeafeningRoar_Timer = urand(5000, 10000); // dur 2s
|
||||
ShapeShift_Timer = urand(20000, 25000); // dur 30s
|
||||
inBearForm = true;
|
||||
}
|
||||
} else ShapeShift_Timer -= diff;
|
||||
|
||||
if (!inBearForm)
|
||||
{
|
||||
if (BrutalSwipe_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_BRUTALSWIPE);
|
||||
BrutalSwipe_Timer = urand(7000, 12000);
|
||||
} else BrutalSwipe_Timer -= diff;
|
||||
|
||||
if (Mangle_Timer <= diff)
|
||||
{
|
||||
if (me->GetVictim() && !me->EnsureVictim()->HasAura(SPELL_MANGLEEFFECT))
|
||||
{
|
||||
DoCastVictim(SPELL_MANGLE);
|
||||
Mangle_Timer = 1000;
|
||||
}
|
||||
else Mangle_Timer = urand(10000, 15000);
|
||||
} else Mangle_Timer -= diff;
|
||||
|
||||
if (Surge_Timer <= diff)
|
||||
{
|
||||
me->Yell(YELL_SURGE, LANG_UNIVERSAL);
|
||||
DoPlaySoundToSet(me, SOUND_YELL_SURGE);
|
||||
Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 45, true);
|
||||
if (target)
|
||||
DoCast(target, SPELL_SURGE);
|
||||
Surge_Timer = urand(15000, 20000);
|
||||
} else Surge_Timer -= diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LaceratingSlash_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_LACERATINGSLASH);
|
||||
LaceratingSlash_Timer = urand(18000, 23000);
|
||||
} else LaceratingSlash_Timer -= diff;
|
||||
|
||||
if (RendFlesh_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_RENDFLESH);
|
||||
RendFlesh_Timer = urand(5000, 10000);
|
||||
} else RendFlesh_Timer -= diff;
|
||||
|
||||
if (DeafeningRoar_Timer <= diff)
|
||||
{
|
||||
DoCastVictim(SPELL_DEAFENINGROAR);
|
||||
DeafeningRoar_Timer = urand(15000, 20000);
|
||||
} else DeafeningRoar_Timer -= diff;
|
||||
}
|
||||
*/
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
@@ -110,3 +469,4 @@ void AddSC_boss_nalorakk()
|
||||
{
|
||||
new boss_nalorakk();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -15,209 +16,421 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* ScriptData
|
||||
SDName: Zulaman
|
||||
SD%Complete: 90
|
||||
SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script
|
||||
SDCategory: Zul'Aman
|
||||
EndScriptData */
|
||||
|
||||
/* ContentData
|
||||
npc_forest_frog
|
||||
EndContentData */
|
||||
|
||||
#include "ScriptMgr.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "Player.h"
|
||||
#include "CreatureTextMgr.h"
|
||||
#include "SpellScript.h"
|
||||
#include "zulaman.h"
|
||||
#include "Player.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
|
||||
/*######
|
||||
## npc_forest_frog
|
||||
######*/
|
||||
|
||||
enum ForestFrog
|
||||
{
|
||||
// Spells
|
||||
SPELL_REMOVE_AMANI_CURSE = 43732,
|
||||
SPELL_PUSH_MOJO = 43923,
|
||||
|
||||
// Creatures
|
||||
NPC_FOREST_FROG = 24396
|
||||
|
||||
};
|
||||
|
||||
class npc_forest_frog : public CreatureScript
|
||||
{
|
||||
public:
|
||||
|
||||
npc_forest_frog()
|
||||
: CreatureScript("npc_forest_frog")
|
||||
{
|
||||
}
|
||||
|
||||
struct npc_forest_frogAI : public ScriptedAI
|
||||
{
|
||||
npc_forest_frogAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
void Reset() override { }
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override { }
|
||||
|
||||
void DoSpawnRandom()
|
||||
{
|
||||
uint32 cEntry = 0;
|
||||
switch (rand32() % 10)
|
||||
{
|
||||
case 0: cEntry = 24397; break; //Mannuth
|
||||
case 1: cEntry = 24403; break; //Deez
|
||||
case 2: cEntry = 24404; break; //Galathryn
|
||||
case 3: cEntry = 24405; break; //Adarrah
|
||||
case 4: cEntry = 24406; break; //Fudgerick
|
||||
case 5: cEntry = 24407; break; //Darwen
|
||||
case 6: cEntry = 24445; break; //Mitzi
|
||||
case 7: cEntry = 24448; break; //Christian
|
||||
case 8: cEntry = 24453; break; //Brennan
|
||||
case 9: cEntry = 24455; break; //Hollee
|
||||
}
|
||||
|
||||
if (!instance->GetData(TYPE_RAND_VENDOR_1))
|
||||
if (rand32() % 10 == 1) cEntry = 24408; //Gunter
|
||||
if (!instance->GetData(TYPE_RAND_VENDOR_2))
|
||||
if (rand32() % 10 == 1) cEntry = 24409; //Kyren
|
||||
|
||||
if (cEntry) me->UpdateEntry(cEntry);
|
||||
|
||||
if (cEntry == 24408) instance->SetData(TYPE_RAND_VENDOR_1, DONE);
|
||||
if (cEntry == 24409) instance->SetData(TYPE_RAND_VENDOR_2, DONE);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* caster, const SpellInfo* spell) override
|
||||
{
|
||||
if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && me->GetEntry() == NPC_FOREST_FROG)
|
||||
{
|
||||
//increase or decrease chance of mojo?
|
||||
if (rand32() % 99 == 50) DoCast(caster, SPELL_PUSH_MOJO, true);
|
||||
else DoSpawnRandom();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_forest_frogAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_zulaman_hostage
|
||||
######*/
|
||||
|
||||
#define GOSSIP_HOSTAGE1 "I am glad to help you."
|
||||
|
||||
static uint32 HostageEntry[] = {23790, 23999, 24024, 24001};
|
||||
static uint32 ChestEntry[] = {186648, 187021, 186672, 186667};
|
||||
|
||||
class npc_zulaman_hostage : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_zulaman_hostage() : CreatureScript("npc_zulaman_hostage") { }
|
||||
|
||||
bool OnGossipHello(Player* player, Creature* creature) override
|
||||
{
|
||||
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HOSTAGE1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
|
||||
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
|
||||
{
|
||||
player->PlayerTalkClass->ClearMenus();
|
||||
|
||||
if (action == GOSSIP_ACTION_INFO_DEF + 1)
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
|
||||
if (!creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
|
||||
return true;
|
||||
|
||||
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
InstanceScript* instance = creature->GetInstanceScript();
|
||||
if (instance)
|
||||
{
|
||||
//uint8 progress = instance->GetData(DATA_CHESTLOOTED);
|
||||
instance->SetData(DATA_CHESTLOOTED, 0);
|
||||
float x, y, z;
|
||||
creature->GetPosition(x, y, z);
|
||||
uint32 entry = creature->GetEntry();
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
{
|
||||
if (HostageEntry[i] == entry)
|
||||
{
|
||||
creature->SummonGameObject(ChestEntry[i], x-2, y, z, 0, 0, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/*######
|
||||
## npc_harrison_jones
|
||||
######*/
|
||||
|
||||
enum Says
|
||||
{
|
||||
// Vol'jin
|
||||
SAY_INTRO_1 = 0,
|
||||
SAY_INTRO_2 = 1,
|
||||
SAY_INTRO_3 = 2,
|
||||
SAY_INTRO_4 = 3,
|
||||
SAY_INTRO_FAIL = 4,
|
||||
|
||||
// Hex Lord Malacrass
|
||||
SAY_HEXLOR_INTRO = 0
|
||||
SAY_HARRISON_0 = 0,
|
||||
SAY_HARRISON_1 = 1,
|
||||
SAY_HARRISON_2 = 0,
|
||||
SAY_HARRISON_3 = 1
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
// Vol'jin
|
||||
SPELL_BANGING_THE_GONG = 45225
|
||||
SPELL_BANGING_THE_GONG = 45225,
|
||||
SPELL_STEALTH = 34189,
|
||||
SPELL_COSMETIC_SPEAR_THROW = 43647
|
||||
};
|
||||
|
||||
enum Events
|
||||
{
|
||||
EVENT_INTRO_MOVEPOINT_1 = 1,
|
||||
EVENT_INTRO_MOVEPOINT_2 = 2,
|
||||
EVENT_INTRO_MOVEPOINT_3 = 3,
|
||||
EVENT_BANGING_THE_GONG = 4,
|
||||
EVENT_START_DOOR_OPENING_1 = 5,
|
||||
EVENT_START_DOOR_OPENING_2 = 6,
|
||||
EVENT_START_DOOR_OPENING_3 = 7,
|
||||
EVENT_START_DOOR_OPENING_4 = 8,
|
||||
EVENT_START_DOOR_OPENING_5 = 9,
|
||||
EVENT_START_DOOR_OPENING_6 = 10,
|
||||
EVENT_START_DOOR_OPENING_7 = 11
|
||||
GONG_EVENT_1 = 1,
|
||||
GONG_EVENT_2 = 2,
|
||||
GONG_EVENT_3 = 3,
|
||||
GONG_EVENT_4 = 4,
|
||||
GONG_EVENT_5 = 5,
|
||||
GONG_EVENT_6 = 6,
|
||||
GONG_EVENT_7 = 7,
|
||||
GONG_EVENT_8 = 8,
|
||||
GONG_EVENT_9 = 9,
|
||||
GONG_EVENT_10 = 10,
|
||||
GONG_EVENT_11 = 11
|
||||
};
|
||||
|
||||
enum Points
|
||||
enum Waypoints
|
||||
{
|
||||
POINT_INTRO = 1,
|
||||
POINT_STRANGE_GONG = 2,
|
||||
POINT_START_DOOR_OPENING_1 = 3,
|
||||
POINT_START_DOOR_OPENING_2 = 4
|
||||
HARRISON_MOVE_1 = 860440,
|
||||
HARRISON_MOVE_2 = 860441,
|
||||
HARRISON_MOVE_3 = 860442
|
||||
};
|
||||
|
||||
enum Misc
|
||||
enum DisplayIds
|
||||
{
|
||||
ITEM_VIRTUAL_ITEM = 5301
|
||||
MODEL_HARRISON_JONES_0 = 22340,
|
||||
MODEL_HARRISON_JONES_1 = 22354,
|
||||
MODEL_HARRISON_JONES_2 = 22347
|
||||
};
|
||||
|
||||
Position const VoljinIntroWaypoint[4] =
|
||||
enum EntryIds
|
||||
{
|
||||
{ 117.7349f, 1662.77f, 42.02156f, 0.0f },
|
||||
{ 132.14f, 1645.143f, 42.02158f, 0.0f },
|
||||
{ 121.8901f, 1639.118f, 42.23253f, 0.0f },
|
||||
{ 122.618f, 1639.546f, 42.11659f, 0.0f },
|
||||
NPC_HARRISON_JONES_1 = 24375,
|
||||
NPC_HARRISON_JONES_2 = 24365,
|
||||
NPC_AMANISHI_GUARDIAN = 23597,
|
||||
};
|
||||
|
||||
class npc_voljin_zulaman : public CreatureScript
|
||||
enum Weapons
|
||||
{
|
||||
WEAPON_MACE = 5301,
|
||||
WEAPON_SPEAR = 13631
|
||||
};
|
||||
|
||||
class npc_harrison_jones : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_voljin_zulaman() : CreatureScript("npc_voljin_zulaman") { }
|
||||
|
||||
struct npc_voljin_zulamanAI : public ScriptedAI
|
||||
npc_harrison_jones() : CreatureScript("npc_harrison_jones")
|
||||
{
|
||||
npc_voljin_zulamanAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript())
|
||||
}
|
||||
|
||||
struct npc_harrison_jonesAI : public ScriptedAI
|
||||
{
|
||||
npc_harrison_jonesAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
|
||||
if (_instance->GetData(DATA_ZULAMAN_STATE) == NOT_STARTED)
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
Initialize();
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
_gongEvent = 0;
|
||||
_gongTimer = 0;
|
||||
uiTargetGUID = 0;
|
||||
}
|
||||
|
||||
InstanceScript* instance;
|
||||
|
||||
uint8 _gongEvent;
|
||||
uint32 _gongTimer;
|
||||
uint64 uiTargetGUID;
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_gongCount = 0;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void EnterCombat(Unit* /*who*/) override { }
|
||||
|
||||
void sGossipSelect(Player* player, uint32 sender, uint32 action) override
|
||||
{
|
||||
if (_instance->GetData(DATA_ZULAMAN_STATE) != NOT_STARTED)
|
||||
return;
|
||||
|
||||
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
|
||||
{
|
||||
_events.Reset();
|
||||
me->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
|
||||
if (me->GetCreatureTemplate()->GossipMenuId == sender && !action)
|
||||
{
|
||||
player->CLOSE_GOSSIP_MENU();
|
||||
me->SetFacingToObject(player);
|
||||
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
me->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
|
||||
_events.ScheduleEvent(EVENT_INTRO_MOVEPOINT_1, 1000);
|
||||
Talk(SAY_INTRO_1, player);
|
||||
me->SetWalk(true);
|
||||
}
|
||||
Talk(SAY_HARRISON_0);
|
||||
_gongEvent = GONG_EVENT_1;
|
||||
_gongTimer = 4000;
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
void SpellHit(Unit*, const SpellInfo* spell) override
|
||||
{
|
||||
if (action == ACTION_START_ZULAMAN)
|
||||
if (spell->Id == SPELL_COSMETIC_SPEAR_THROW)
|
||||
{
|
||||
if (++_gongCount == 10)
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_1, 500);
|
||||
me->RemoveAllAuras();
|
||||
me->SetEntry(NPC_HARRISON_JONES_2);
|
||||
me->SetDisplayId(MODEL_HARRISON_JONES_2);
|
||||
me->SetTarget(ObjectGuid::Empty);
|
||||
me->SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_DEAD);
|
||||
me->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
|
||||
instance->SetData(DATA_GONGEVENT, DONE);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
_events.Update(diff);
|
||||
while (uint32 eventId = _events.ExecuteEvent())
|
||||
if (_gongEvent)
|
||||
{
|
||||
switch (eventId)
|
||||
if (_gongTimer <= diff)
|
||||
{
|
||||
case EVENT_INTRO_MOVEPOINT_1:
|
||||
me->GetMotionMaster()->MovePoint(POINT_INTRO, VoljinIntroWaypoint[0]);
|
||||
_events.ScheduleEvent(EVENT_INTRO_MOVEPOINT_2, 1000);
|
||||
break;
|
||||
case EVENT_INTRO_MOVEPOINT_2:
|
||||
me->GetMotionMaster()->MovePoint(POINT_STRANGE_GONG, VoljinIntroWaypoint[1]);
|
||||
_events.ScheduleEvent(EVENT_INTRO_MOVEPOINT_3, 4000);
|
||||
break;
|
||||
case EVENT_INTRO_MOVEPOINT_3:
|
||||
Talk(SAY_INTRO_2);
|
||||
_events.ScheduleEvent(EVENT_BANGING_THE_GONG, 3000);
|
||||
case EVENT_BANGING_THE_GONG:
|
||||
DoCast(me, SPELL_BANGING_THE_GONG);
|
||||
if (GameObject* strangeGong = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(DATA_STRANGE_GONG)))
|
||||
strangeGong->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, uint32(ITEM_VIRTUAL_ITEM));
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_1:
|
||||
me->RemoveAura(SPELL_BANGING_THE_GONG);
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_2, 500);
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_2:
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, uint32(0));
|
||||
if (GameObject* strangeGong = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(DATA_STRANGE_GONG)))
|
||||
strangeGong->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_3, 500);
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_3:
|
||||
me->GetMotionMaster()->MovePoint(POINT_START_DOOR_OPENING_1, VoljinIntroWaypoint[2]);
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_4:
|
||||
_instance->SetData(DATA_ZULAMAN_STATE, IN_PROGRESS);
|
||||
if (GameObject* masiveGate = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(DATA_MASSIVE_GATE)))
|
||||
masiveGate->SetGoState(GO_STATE_ACTIVE);
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_5, 3000);
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_5:
|
||||
Talk(SAY_INTRO_4);
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_6, 6000);
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_6:
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_7, 6000);
|
||||
break;
|
||||
case EVENT_START_DOOR_OPENING_7:
|
||||
if (Creature* hexLordTrigger = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_HEXLORD_TRIGGER)))
|
||||
sCreatureTextMgr->SendChat(hexLordTrigger, SAY_HEXLOR_INTRO, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
switch (_gongEvent)
|
||||
{
|
||||
case GONG_EVENT_1:
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_1, false);
|
||||
_gongEvent = GONG_EVENT_2;
|
||||
_gongTimer = 12000;
|
||||
break;
|
||||
case GONG_EVENT_2:
|
||||
me->SetFacingTo(6.235659f);
|
||||
Talk(SAY_HARRISON_1);
|
||||
DoCast(me, SPELL_BANGING_THE_GONG);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_MACE));
|
||||
me->SetSheath(SHEATH_STATE_MELEE);
|
||||
_gongEvent = GONG_EVENT_3;
|
||||
_gongTimer = 4000;
|
||||
break;
|
||||
case GONG_EVENT_3:
|
||||
if (GameObject* gong = me->GetMap()->GetGameObject(instance->GetGuidData(GO_STRANGE_GONG)))
|
||||
gong->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
_gongEvent = GONG_EVENT_4;
|
||||
_gongTimer = 105000;
|
||||
break;
|
||||
case GONG_EVENT_4:
|
||||
me->RemoveAura(SPELL_BANGING_THE_GONG);
|
||||
if (GameObject* gong = me->GetMap()->GetGameObject(instance->GetGuidData(GO_STRANGE_GONG)))
|
||||
gong->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
|
||||
|
||||
// trigger or gong will need to be scripted to set IN_PROGRESS after enough hits.
|
||||
// This is temp workaround.
|
||||
instance->SetData(DATA_GONGEVENT, IN_PROGRESS); // to be removed.
|
||||
|
||||
if (instance->GetData(DATA_GONGEVENT) == IN_PROGRESS)
|
||||
{
|
||||
// Players are Now Saved to instance at SPECIAL (Player should be notified?)
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_2, false);
|
||||
_gongEvent = GONG_EVENT_5;
|
||||
_gongTimer = 5000;
|
||||
}
|
||||
else
|
||||
{
|
||||
_gongTimer = 1000;
|
||||
_gongEvent = GONG_EVENT_9;
|
||||
}
|
||||
break;
|
||||
case GONG_EVENT_5:
|
||||
me->SetEntry(NPC_HARRISON_JONES_1);
|
||||
me->SetDisplayId(MODEL_HARRISON_JONES_1);
|
||||
Talk(SAY_HARRISON_2);
|
||||
_gongTimer = 12000;
|
||||
_gongEvent = GONG_EVENT_6;
|
||||
break;
|
||||
case GONG_EVENT_6:
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
|
||||
Talk(SAY_HARRISON_3);
|
||||
_gongTimer = 7000;
|
||||
_gongEvent = GONG_EVENT_7;
|
||||
break;
|
||||
case GONG_EVENT_7:
|
||||
if (!uiTargetGUID)
|
||||
{
|
||||
std::list<Creature*> targetList;
|
||||
GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f);
|
||||
if (!targetList.empty())
|
||||
{
|
||||
for (std::list<Creature*>::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
{
|
||||
if (Creature* ptarget = *itr)
|
||||
{
|
||||
if (ptarget->GetPositionX() > 120)
|
||||
{
|
||||
ptarget->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(WEAPON_SPEAR));
|
||||
ptarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
|
||||
ptarget->SetReactState(REACT_PASSIVE);
|
||||
ptarget->AI()->SetData(0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ptarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
|
||||
ptarget->SetReactState(REACT_PASSIVE);
|
||||
ptarget->AI()->SetData(0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GameObject* gate = me->GetMap()->GetGameObject(instance->GetGuidData(GO_MASSIVE_GATE)))
|
||||
gate->SetGoState(GO_STATE_ACTIVE);
|
||||
_gongTimer = 2000;
|
||||
_gongEvent = GONG_EVENT_8;
|
||||
break;
|
||||
case GONG_EVENT_8:
|
||||
DoCast(me, SPELL_STEALTH);
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(0));
|
||||
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
me->GetMotionMaster()->MovePath(HARRISON_MOVE_3, false);
|
||||
_gongTimer = 1000;
|
||||
_gongEvent = 0;
|
||||
break;
|
||||
case GONG_EVENT_9:
|
||||
me->GetMotionMaster()->MovePoint(0, 120.687f, 1674.0f, 42.0217f);
|
||||
_gongTimer = 12000;
|
||||
_gongEvent = GONG_EVENT_10;
|
||||
break;
|
||||
case GONG_EVENT_10:
|
||||
me->SetFacingTo(1.59044f);
|
||||
_gongEvent = 11;
|
||||
_gongTimer = 6000;
|
||||
break;
|
||||
case GONG_EVENT_11:
|
||||
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
|
||||
|
||||
instance->SetData(DATA_GONGEVENT, NOT_STARTED);
|
||||
_gongEvent = 0;
|
||||
_gongTimer = 1000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
_gongTimer -= diff;
|
||||
}
|
||||
}
|
||||
|
||||
void MovementInform(uint32 movementType, uint32 pointId) override
|
||||
{
|
||||
if (movementType != POINT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
switch (pointId)
|
||||
{
|
||||
case POINT_STRANGE_GONG:
|
||||
if (GameObject* strangeGong = ObjectAccessor::GetGameObject(*me, _instance->GetGuidData(DATA_STRANGE_GONG)))
|
||||
me->SetFacingToObject(strangeGong); // setInFront
|
||||
break;
|
||||
case POINT_START_DOOR_OPENING_1:
|
||||
me->SetFacingTo(4.747295f);
|
||||
me->GetMotionMaster()->MovePoint(POINT_START_DOOR_OPENING_2, VoljinIntroWaypoint[3]);
|
||||
Talk(SAY_INTRO_3);
|
||||
_events.ScheduleEvent(EVENT_START_DOOR_OPENING_4, 4500);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* _instance;
|
||||
EventMap _events;
|
||||
uint8 _gongCount;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetInstanceAI<npc_voljin_zulamanAI>(creature);
|
||||
return GetInstanceAI<npc_harrison_jonesAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
// 45226 - Banging the Gong
|
||||
class spell_banging_the_gong : public SpellScriptLoader
|
||||
{
|
||||
public:
|
||||
@@ -245,8 +458,11 @@ class spell_banging_the_gong : public SpellScriptLoader
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void AddSC_zulaman()
|
||||
{
|
||||
new npc_voljin_zulaman();
|
||||
new npc_forest_frog();
|
||||
new npc_zulaman_hostage();
|
||||
new npc_harrison_jones();
|
||||
new spell_banging_the_gong();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@@ -18,74 +19,45 @@
|
||||
#ifndef DEF_ZULAMAN_H
|
||||
#define DEF_ZULAMAN_H
|
||||
|
||||
uint32 const EncounterCount = 6;
|
||||
#define ZulAmanScriptName "instance_zulaman"
|
||||
#define DataHeader "ZA"
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
// BossState
|
||||
DATA_AKILZON = 0,
|
||||
DATA_NALORAKK = 1,
|
||||
DATA_JANALAI = 2,
|
||||
DATA_HALAZZI = 3,
|
||||
DATA_HEXLORD = 4,
|
||||
DATA_DAAKARA = 5,
|
||||
|
||||
// Data64
|
||||
DATA_HEXLORD_TRIGGER,
|
||||
|
||||
DATA_STRANGE_GONG,
|
||||
DATA_MASSIVE_GATE,
|
||||
|
||||
// SetData
|
||||
DATA_ZULAMAN_STATE
|
||||
DATA_GONGEVENT = 0,
|
||||
DATA_NALORAKKEVENT = 1,
|
||||
DATA_AKILZONEVENT = 2,
|
||||
DATA_JANALAIEVENT = 3,
|
||||
DATA_HALAZZIEVENT = 4,
|
||||
DATA_HEXLORDEVENT = 5,
|
||||
DATA_ZULJINEVENT = 6,
|
||||
DATA_CHESTLOOTED = 7,
|
||||
TYPE_RAND_VENDOR_1 = 8,
|
||||
TYPE_RAND_VENDOR_2 = 9
|
||||
};
|
||||
|
||||
enum CreatureIds
|
||||
{
|
||||
NPC_AKILZON = 23574,
|
||||
NPC_NALORAKK = 23576,
|
||||
NPC_JANALAI = 23578,
|
||||
NPC_HALAZZI = 23577,
|
||||
NPC_HEXLORD = 24239,
|
||||
NPC_DAAKARA = 23863,
|
||||
|
||||
NPC_VOLJIN = 52924,
|
||||
NPC_HEXLORD_TRIGGER = 24363
|
||||
NPC_HARRISON_JONES = 24358,
|
||||
NPC_JANALAI = 23578,
|
||||
NPC_ZULJIN = 23863,
|
||||
NPC_HEXLORD = 24239,
|
||||
NPC_HALAZZI = 23577,
|
||||
NPC_NALORAKK = 23576
|
||||
};
|
||||
|
||||
enum GameObjectIds
|
||||
enum GameobjectIds
|
||||
{
|
||||
GO_STRANGE_GONG = 187359,
|
||||
GO_MASSIVE_GATE = 186728,
|
||||
GO_DOOR_HALAZZI = 186303,
|
||||
GO_GATE_ZULJIN = 186304,
|
||||
GO_GATE_HEXLORD = 186305,
|
||||
GO_MASSIVE_GATE = 186728,
|
||||
GO_DOOR_AKILZON = 186858,
|
||||
GO_DOOR_ZULJIN = 186859,
|
||||
GO_HARKORS_SATCHEL = 187021,
|
||||
GO_TANZARS_TRUNK = 186648,
|
||||
GO_ASHLIS_BAG = 186672,
|
||||
GO_KRAZS_PACKAGE = 186667,
|
||||
GO_STRANGE_GONG = 187359
|
||||
};
|
||||
|
||||
enum ZulAmanEvents
|
||||
{
|
||||
EVENT_START_ZULAMAN = 15897,
|
||||
EVENT_UPDATE_ZULAMAN_TIMER = 1,
|
||||
};
|
||||
|
||||
enum ZulAmanAction
|
||||
{
|
||||
ACTION_START_ZULAMAN = 1
|
||||
};
|
||||
|
||||
enum ZulAmanWorldStates
|
||||
{
|
||||
WORLD_STATE_ZULAMAN_TIMER_ENABLED = 3104,
|
||||
WORLD_STATE_ZULAMAN_TIMER = 3106,
|
||||
};
|
||||
|
||||
template<class AI>
|
||||
CreatureAI* GetZulAmanAI(Creature* creature)
|
||||
{
|
||||
if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
|
||||
if (instance->GetInstanceScript())
|
||||
if (instance->GetScriptId() == sObjectMgr->GetScriptId(ZulAmanScriptName))
|
||||
return new AI(creature);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
||||
@@ -87,4 +87,4 @@ public:
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user