diff --git a/CMakeLists.txt b/CMakeLists.txt index 7dfe6de007a..56ea65e5d7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,4 +81,4 @@ include(cmake/showoptions.cmake) add_subdirectory(dep) # add core sources -add_subdirectory(src) \ No newline at end of file +add_subdirectory(src) diff --git a/PreLoad.cmake b/PreLoad.cmake index e624104dab9..f7cf5a1ebe6 100644 --- a/PreLoad.cmake +++ b/PreLoad.cmake @@ -20,4 +20,4 @@ # set(CMAKE_INSTALL_PREFIX # "" CACHE PATH "Default install path") # endif() -#endif() \ No newline at end of file +#endif() diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 62e2c6220ac..9c2fa9861d0 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2015 TrinityCore +* Copyright (C) 2008-2015 TrinityCore * Copyright (C) 2005-2009 MaNGOS * * This program is free software; you can redistribute it and/or modify it diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 166afec6b39..e36196c742a 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2008-2015 TrinityCore * * 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; } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index b4ef9f34c64..4dcb41f533b 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -15,19 +15,67 @@ * with this program. If not, see . */ +/* 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 tempUnitMap; + + { + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(me, me, SIZE_OF_GRIDS); + Trinity::UnitListSearcher searcher(me, tempUnitMap, u_check); + + TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor, 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::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(); } + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp index dcef6dc6166..2317582af99 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 * * 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(creature); + return GetInstanceAI(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(); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index 9040edf1e12..01ac3920082 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2006-2007 ScriptDev2 * * 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,63 +16,375 @@ * with this program. If not, see . */ +/* ScriptData +SDName: Boss_Hex_Lord_Malacrass +SD%Complete: +SDComment: +SDCategory: Zul'Aman +EndScriptData */ + #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellScript.h" #include "SpellAuraEffects.h" #include "zulaman.h" -enum Says +#define YELL_AGGRO "Da shadow gonna fall on you... " +#define SOUND_YELL_AGGRO 12041 +#define YELL_SPIRIT_BOLTS "Your soul gonna bleed!" +#define SOUND_YELL_SPIRIT_BOLTS 12047 +#define YELL_DRAIN_POWER "Darkness comin\' for you" +#define SOUND_YELL_DRAIN_POWER 12046 +#define YELL_KILL_ONE "Dis a nightmare ya don\' wake up from!" +#define SOUND_YELL_KILL_ONE 12043 +#define YELL_KILL_TWO "Azzaga choogo zinn!" +#define SOUND_YELL_KILL_TWO 12044 +#define YELL_DEATH "Dis not... da end of me..." +#define SOUND_YELL_DEATH 12051 + + +enum Creatures { - SAY_AGGRO = 0, - SAY_PLAYER_KILL = 1, - SAY_SPIRIT_BOLTS = 2, - SAY_SIPHON_SOUL = 3, - SAY_PET_DEATH = 4, - SAY_DEATH = 5 + NPC_TEMP_TRIGGER = 23920 }; enum Spells { + SPELL_SPIRIT_BOLTS = 43383, + SPELL_DRAIN_POWER = 44131, + SPELL_SIPHON_SOUL = 43501, + + // Druid + SPELL_DR_THORNS = 43420, + SPELL_DR_LIFEBLOOM = 43421, + SPELL_DR_MOONFIRE = 43545, + + // Hunter + SPELL_HU_EXPLOSIVE_TRAP = 43444, + SPELL_HU_FREEZING_TRAP = 43447, + SPELL_HU_SNAKE_TRAP = 43449, + + // Mage + SPELL_MG_FIREBALL = 41383, + SPELL_MG_FROST_NOVA = 43426, + SPELL_MG_ICE_LANCE = 43427, + SPELL_MG_FROSTBOLT = 43428, + + // Paladin + SPELL_PA_CONSECRATION = 43429, + SPELL_PA_AVENGING_WRATH = 43430, + SPELL_PA_HOLY_LIGHT = 43451, + + // Priest + SPELL_PR_HEAL = 41372, + SPELL_PR_MIND_BLAST = 41374, + SPELL_PR_SW_DEATH = 41375, + SPELL_PR_PSYCHIC_SCREAM = 43432, + SPELL_PR_MIND_CONTROL = 43550, + SPELL_PR_PAIN_SUPP = 44416, + + // Rogue + SPELL_RO_BLIND = 43433, + SPELL_RO_SLICE_DICE = 43457, + SPELL_RO_WOUND_POISON = 43461, + + // Shaman + SPELL_SH_CHAIN_LIGHT = 43435, + SPELL_SH_FIRE_NOVA = 43436, + SPELL_SH_HEALING_WAVE = 43548, + + // Warlock + SPELL_WL_CURSE_OF_DOOM = 43439, + SPELL_WL_RAIN_OF_FIRE = 43440, SPELL_WL_UNSTABLE_AFFL = 43522, SPELL_WL_UNSTABLE_AFFL_DISPEL = 43523, + + // Warrior + SPELL_WR_MORTAL_STRIKE = 43441, + SPELL_WR_WHIRLWIND = 43442, + SPELL_WR_SPELL_REFLECT = 43443, + + // Thurg + SPELL_BLOODLUST = 43578, + SPELL_CLEAVE = 15496, + + // Gazakroth + SPELL_FIREBOLT = 43584, + + // Alyson Antille + SPELL_FLASH_HEAL = 43575, + SPELL_DISPEL_MAGIC = 43577, + + // Lord Raadan + SPELL_FLAME_BREATH = 43582, + SPELL_THUNDERCLAP = 43583, + + // Darkheart + SPELL_PSYCHIC_WAIL = 43590, + + // Slither + SPELL_VENOM_SPIT = 43579, + + // Fenstalker + SPELL_VOLATILE_INFECTION = 43586, + + // Koragg + SPELL_COLD_STARE = 43593, + SPELL_MIGHTY_BLOW = 43592 + }; -enum Events +#define ORIENT 1.5696f +#define POS_Y 921.2795f +#define POS_Z 33.8883f + +static float Pos_X[4] = {112.8827f, 107.8827f, 122.8827f, 127.8827f}; + +static uint32 AddEntryList[8]= { + 24240, //Alyson Antille + 24241, //Thurg + 24242, //Slither + 24243, //Lord Raadan + 24244, //Gazakroth + 24245, //Fenstalker + 24246, //Darkheart + 24247 //Koragg +}; + +enum AbilityTarget +{ + ABILITY_TARGET_SELF = 0, + ABILITY_TARGET_VICTIM = 1, + ABILITY_TARGET_ENEMY = 2, + ABILITY_TARGET_HEAL = 3, + ABILITY_TARGET_BUFF = 4, + ABILITY_TARGET_SPECIAL = 5 +}; + +struct PlayerAbilityStruct +{ + uint32 spell; + AbilityTarget target; + uint32 cooldown; //FIXME - it's never used +}; + +static PlayerAbilityStruct PlayerAbility[][3] = +{ + // 1 warrior + {{SPELL_WR_SPELL_REFLECT, ABILITY_TARGET_SELF, 10000}, + {SPELL_WR_WHIRLWIND, ABILITY_TARGET_SELF, 10000}, + {SPELL_WR_MORTAL_STRIKE, ABILITY_TARGET_VICTIM, 6000}}, + // 2 paladin + {{SPELL_PA_CONSECRATION, ABILITY_TARGET_SELF, 10000}, + {SPELL_PA_HOLY_LIGHT, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PA_AVENGING_WRATH, ABILITY_TARGET_SELF, 10000}}, + // 3 hunter + {{SPELL_HU_EXPLOSIVE_TRAP, ABILITY_TARGET_SELF, 10000}, + {SPELL_HU_FREEZING_TRAP, ABILITY_TARGET_SELF, 10000}, + {SPELL_HU_SNAKE_TRAP, ABILITY_TARGET_SELF, 10000}}, + // 4 rogue + {{SPELL_RO_WOUND_POISON, ABILITY_TARGET_VICTIM, 3000}, + {SPELL_RO_SLICE_DICE, ABILITY_TARGET_SELF, 10000}, + {SPELL_RO_BLIND, ABILITY_TARGET_ENEMY, 10000}}, + // 5 priest + {{SPELL_PR_PAIN_SUPP, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PR_HEAL, ABILITY_TARGET_HEAL, 10000}, + {SPELL_PR_PSYCHIC_SCREAM, ABILITY_TARGET_SELF, 10000}}, + // 5* shadow priest + {{SPELL_PR_MIND_CONTROL, ABILITY_TARGET_ENEMY, 15000}, + {SPELL_PR_MIND_BLAST, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_PR_SW_DEATH, ABILITY_TARGET_ENEMY, 10000}}, + // 7 shaman + {{SPELL_SH_FIRE_NOVA, ABILITY_TARGET_SELF, 10000}, + {SPELL_SH_HEALING_WAVE, ABILITY_TARGET_HEAL, 10000}, + {SPELL_SH_CHAIN_LIGHT, ABILITY_TARGET_ENEMY, 8000}}, + // 8 mage + {{SPELL_MG_FIREBALL, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_MG_FROSTBOLT, ABILITY_TARGET_ENEMY, 5000}, + {SPELL_MG_ICE_LANCE, ABILITY_TARGET_SPECIAL, 2000}}, + // 9 warlock + {{SPELL_WL_CURSE_OF_DOOM, ABILITY_TARGET_ENEMY, 10000}, + {SPELL_WL_RAIN_OF_FIRE, ABILITY_TARGET_ENEMY, 10000}, + {SPELL_WL_UNSTABLE_AFFL, ABILITY_TARGET_ENEMY, 10000}}, + // 11 druid + {{SPELL_DR_LIFEBLOOM, ABILITY_TARGET_HEAL, 10000}, + {SPELL_DR_THORNS, ABILITY_TARGET_SELF, 10000}, + {SPELL_DR_MOONFIRE, ABILITY_TARGET_ENEMY, 8000}} +}; + +struct boss_hexlord_addAI : public ScriptedAI +{ + InstanceScript* instance; + + boss_hexlord_addAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + } + + void Reset() override { } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + } + + void UpdateAI(uint32 /*diff*/) override + { + if (instance->GetData(DATA_HEXLORDEVENT) != IN_PROGRESS) + { + EnterEvadeMode(); + return; + } + + DoMeleeAttackIfReady(); + } }; class boss_hexlord_malacrass : public CreatureScript { public: - boss_hexlord_malacrass() : CreatureScript("boss_hexlord_malacrass") { } - - struct boss_hex_lord_malacrassAI : public BossAI + boss_hexlord_malacrass() + : CreatureScript("boss_hexlord_malacrass") { - boss_hex_lord_malacrassAI(Creature* creature) : BossAI(creature, DATA_HEXLORD) { } + } + + struct boss_hex_lord_malacrassAI : public ScriptedAI + { + boss_hex_lord_malacrassAI(Creature* creature) : ScriptedAI(creature) + { + Initialize(); + instance = creature->GetInstanceScript(); + SelectAddEntry(); + for (uint8 i = 0; i < 4; ++i) + AddGUID[i].Clear(); + PlayerGUID.Clear(); + PlayerClass = CLASS_NONE; + } + + void Initialize() + { + SpiritBolts_Timer = 20000; + DrainPower_Timer = 60000; + SiphonSoul_Timer = 100000; + PlayerAbility_Timer = 99999; + CheckAddState_Timer = 5000; + ResetTimer = 5000; + } + + InstanceScript* instance; + + ObjectGuid AddGUID[4]; + uint32 AddEntry[4]; + + ObjectGuid PlayerGUID; + + uint32 SpiritBolts_Timer; + uint32 DrainPower_Timer; + uint32 SiphonSoul_Timer; + uint32 PlayerAbility_Timer; + uint32 CheckAddState_Timer; + uint32 ResetTimer; + + uint32 PlayerClass; void Reset() override { - _Reset(); + instance->SetData(DATA_HEXLORDEVENT, NOT_STARTED); + + Initialize(); + + SpawnAdds(); + + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); } void EnterCombat(Unit* /*who*/) override { - Talk(SAY_AGGRO); - _EnterCombat(); + instance->SetData(DATA_HEXLORDEVENT, IN_PROGRESS); + + DoZoneInCombat(); + me->Yell(YELL_AGGRO, LANG_UNIVERSAL); + DoPlaySoundToSet(me, SOUND_YELL_AGGRO); + + for (uint8 i = 0; i < 4; ++i) + { + Creature* creature = ObjectAccessor::GetCreature(*me, AddGUID[i]); + if (creature && creature->IsAlive()) + creature->AI()->AttackStart(me->GetVictim()); + else + { + EnterEvadeMode(); + break; + } + } + } + + void KilledUnit(Unit* /*victim*/) override + { + 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 JustDied(Unit* /*killer*/) override { - Talk(SAY_DEATH); - _JustDied(); + instance->SetData(DATA_HEXLORDEVENT, DONE); + + me->Yell(YELL_DEATH, LANG_UNIVERSAL); + DoPlaySoundToSet(me, SOUND_YELL_DEATH); + + for (uint8 i = 0; i < 4; ++i) + { + Unit* Temp = ObjectAccessor::GetUnit(*me, AddGUID[i]); + if (Temp && Temp->IsAlive()) + Temp->DealDamage(Temp, Temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } } - void KilledUnit(Unit* victim) override + void SelectAddEntry() { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_PLAYER_KILL); + std::vector AddList; + + for (uint8 i = 0; i < 8; ++i) + AddList.push_back(AddEntryList[i]); + + while (AddList.size() > 4) + AddList.erase(AddList.begin() + rand32() % AddList.size()); + + uint8 i = 0; + for (std::vector::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr, ++i) + AddEntry[i] = *itr; + } + + void SpawnAdds() + { + for (uint8 i = 0; i < 4; ++i) + { + Creature* creature = (ObjectAccessor::GetCreature((*me), AddGUID[i])); + if (!creature || !creature->IsAlive()) + { + if (creature) creature->setDeathState(DEAD); + creature = me->SummonCreature(AddEntry[i], Pos_X[i], POS_Y, POS_Z, ORIENT, TEMPSUMMON_DEAD_DESPAWN, 0); + if (creature) AddGUID[i] = creature->GetGUID(); + } + else + { + creature->AI()->EnterEvadeMode(); + creature->SetPosition(Pos_X[i], POS_Y, POS_Z, ORIENT); + creature->StopMoving(); + } + } } void UpdateAI(uint32 diff) override @@ -79,23 +392,125 @@ class boss_hexlord_malacrass : public CreatureScript if (!UpdateVictim()) return; - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - /* - while (uint32 eventId = events.ExecuteEvent()) + if (ResetTimer <= diff) { - switch (eventId) + if (me->IsWithinDist3d(119.223f, 1035.45f, 29.4481f, 10)) { - default: - break; + EnterEvadeMode(); + return; } - } - */ + ResetTimer = 5000; + } else ResetTimer -= diff; + + if (CheckAddState_Timer <= diff) + { + for (uint8 i = 0; i < 4; ++i) + if (Creature* temp = ObjectAccessor::GetCreature(*me, AddGUID[i])) + if (temp->IsAlive() && !temp->GetVictim()) + temp->AI()->AttackStart(me->GetVictim()); + + CheckAddState_Timer = 5000; + } else CheckAddState_Timer -= diff; + + if (DrainPower_Timer <= diff) + { + DoCast(me, SPELL_DRAIN_POWER, true); + me->Yell(YELL_DRAIN_POWER, LANG_UNIVERSAL); + DoPlaySoundToSet(me, SOUND_YELL_DRAIN_POWER); + DrainPower_Timer = urand(40000, 55000); // must cast in 60 sec, or buff/debuff will disappear + } else DrainPower_Timer -= diff; + + if (SpiritBolts_Timer <= diff) + { + if (DrainPower_Timer < 12000) // channel 10 sec + SpiritBolts_Timer = 13000; // cast drain power first + else + { + DoCast(me, SPELL_SPIRIT_BOLTS, false); + me->Yell(YELL_SPIRIT_BOLTS, LANG_UNIVERSAL); + DoPlaySoundToSet(me, SOUND_YELL_SPIRIT_BOLTS); + SpiritBolts_Timer = 40000; + SiphonSoul_Timer = 10000; // ready to drain + PlayerAbility_Timer = 99999; + } + } else SpiritBolts_Timer -= diff; + + if (SiphonSoul_Timer <= diff) + { + Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 70, true); + Unit* trigger = DoSpawnCreature(NPC_TEMP_TRIGGER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 30000); + if (!target || !trigger) + { + EnterEvadeMode(); + return; + } + else + { + trigger->SetDisplayId(11686); + trigger->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + trigger->CastSpell(target, SPELL_SIPHON_SOUL, true); + trigger->GetMotionMaster()->MoveChase(me); + + //DoCast(target, SPELL_SIPHON_SOUL, true); + //me->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, target->GetGUID()); + //me->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SIPHON_SOUL); + + PlayerGUID = target->GetGUID(); + PlayerAbility_Timer = urand(8000, 10000); + PlayerClass = target->getClass() - 1; + + if (PlayerClass == CLASS_DRUID-1) + PlayerClass = CLASS_DRUID; + else if (PlayerClass == CLASS_PRIEST-1 && target->HasSpell(15473)) + PlayerClass = CLASS_PRIEST; // shadow priest + + SiphonSoul_Timer = 99999; // buff lasts 30 sec + } + } else SiphonSoul_Timer -= diff; + + if (PlayerAbility_Timer <= diff) + { + //Unit* target = ObjectAccessor::GetUnit(*me, PlayerGUID); + //if (target && target->IsAlive()) + //{ + UseAbility(); + PlayerAbility_Timer = urand(8000, 10000); + //} + } else PlayerAbility_Timer -= diff; DoMeleeAttackIfReady(); } + + void UseAbility() + { + uint8 random = urand(0, 2); + Unit* target = NULL; + switch (PlayerAbility[PlayerClass][random].target) + { + case ABILITY_TARGET_SELF: + target = me; + break; + case ABILITY_TARGET_VICTIM: + target = me->GetVictim(); + break; + case ABILITY_TARGET_ENEMY: + default: + target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + break; + case ABILITY_TARGET_HEAL: + target = DoSelectLowestHpFriendly(50, 0); + break; + case ABILITY_TARGET_BUFF: + { + std::list templist = DoFindFriendlyMissingBuff(50, PlayerAbility[PlayerClass][random].spell); + if (!templist.empty()) + target = *(templist.begin()); + } + break; + } + if (target) + DoCast(target, PlayerAbility[PlayerClass][random].spell, false); + } }; CreatureAI* GetAI(Creature* creature) const override @@ -104,6 +519,511 @@ class boss_hexlord_malacrass : public CreatureScript } }; +class boss_thurg : public CreatureScript +{ + public: + + boss_thurg() + : CreatureScript("boss_thurg") + { + } + + struct boss_thurgAI : public boss_hexlord_addAI + { + + boss_thurgAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + bloodlust_timer = 15000; + cleave_timer = 10000; + } + + uint32 bloodlust_timer; + uint32 cleave_timer; + + void Reset() override + { + Initialize(); + + boss_hexlord_addAI::Reset(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (bloodlust_timer <= diff) + { + std::list templist = DoFindFriendlyMissingBuff(50, SPELL_BLOODLUST); + if (!templist.empty()) + { + if (Unit* target = *(templist.begin())) + DoCast(target, SPELL_BLOODLUST, false); + } + bloodlust_timer = 12000; + } else bloodlust_timer -= diff; + + if (cleave_timer <= diff) + { + DoCastVictim(SPELL_CLEAVE, false); + cleave_timer = 12000; //3 sec cast + } else cleave_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + +class boss_alyson_antille : public CreatureScript +{ + public: + + boss_alyson_antille() + : CreatureScript("boss_alyson_antille") + { + } + + struct boss_alyson_antilleAI : public boss_hexlord_addAI + { + //Holy Priest + boss_alyson_antilleAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + flashheal_timer = 2500; + dispelmagic_timer = 10000; + } + + uint32 flashheal_timer; + uint32 dispelmagic_timer; + + void Reset() override + { + Initialize(); + + //AcquireGUID(); + + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) override + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (flashheal_timer <= diff) + { + Unit* target = DoSelectLowestHpFriendly(99, 30000); + if (target) + { + if (target->IsWithinDistInMap(me, 50)) + DoCast(target, SPELL_FLASH_HEAL, false); + else + { + // bugged + //me->GetMotionMaster()->Clear(); + //me->GetMotionMaster()->MoveChase(target, 20); + } + } + else + { + if (urand(0, 1)) + target = DoSelectLowestHpFriendly(50, 0); + else + target = SelectTarget(SELECT_TARGET_RANDOM, 0); + if (target) + DoCast(target, SPELL_DISPEL_MAGIC, false); + } + flashheal_timer = 2500; + } else flashheal_timer -= diff; + + /*if (dispelmagic_timer <= diff) + { + if (urand(0, 1)) + { + Unit* target = SelectTarget(); + + DoCast(target, SPELL_DISPEL_MAGIC, false); + } + else + me->CastSpell(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DISPEL_MAGIC, false); + + dispelmagic_timer = 12000; + } else dispelmagic_timer -= diff;*/ + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + +struct boss_gazakrothAI : public boss_hexlord_addAI +{ + boss_gazakrothAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + firebolt_timer = 2000; + } + + uint32 firebolt_timer; + + void Reset() override + { + Initialize(); + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) override + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (firebolt_timer <= diff) + { + DoCastVictim(SPELL_FIREBOLT, false); + firebolt_timer = 700; + } else firebolt_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } +}; + +class boss_lord_raadan : public CreatureScript +{ + public: + + boss_lord_raadan() + : CreatureScript("boss_lord_raadan") + { + } + + struct boss_lord_raadanAI : public boss_hexlord_addAI + { + boss_lord_raadanAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + flamebreath_timer = 8000; + thunderclap_timer = 13000; + } + + uint32 flamebreath_timer; + uint32 thunderclap_timer; + + void Reset() override + { + Initialize(); + + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (thunderclap_timer <= diff) + { + DoCastVictim(SPELL_THUNDERCLAP, false); + thunderclap_timer = 12000; + } else thunderclap_timer -= diff; + + if (flamebreath_timer <= diff) + { + DoCastVictim(SPELL_FLAME_BREATH, false); + flamebreath_timer = 12000; + } else flamebreath_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + +class boss_darkheart : public CreatureScript +{ + public: + + boss_darkheart() + : CreatureScript("boss_darkheart") + { + } + + struct boss_darkheartAI : public boss_hexlord_addAI + { + boss_darkheartAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + psychicwail_timer = 8000; + } + + uint32 psychicwail_timer; + + void Reset() override + { + Initialize(); + boss_hexlord_addAI::Reset(); + } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (psychicwail_timer <= diff) + { + DoCastVictim(SPELL_PSYCHIC_WAIL, false); + psychicwail_timer = 12000; + } else psychicwail_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + + +class boss_slither : public CreatureScript +{ + public: + + boss_slither() + : CreatureScript("boss_slither") + { + } + + struct boss_slitherAI : public boss_hexlord_addAI + { + boss_slitherAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + venomspit_timer = 5000; + } + + uint32 venomspit_timer; + + void Reset() override + { + Initialize(); + boss_hexlord_addAI::Reset(); + } + + void AttackStart(Unit* who) override + { + if (!who) + return; + + if (who->isTargetableForAttack()) + { + if (me->Attack(who, false)) + { + me->GetMotionMaster()->MoveChase(who, 20); + me->AddThreat(who, 0.0f); + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (venomspit_timer <= diff) + { + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(victim, SPELL_VENOM_SPIT, false); + venomspit_timer = 2500; + } else venomspit_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + +class boss_fenstalker : public CreatureScript +{ + public: + + boss_fenstalker() + : CreatureScript("boss_fenstalker") + { + } + + struct boss_fenstalkerAI : public boss_hexlord_addAI + { + boss_fenstalkerAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + volatileinf_timer = 15000; + } + + uint32 volatileinf_timer; + + void Reset() override + { + Initialize(); + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (volatileinf_timer <= diff) + { + // core bug + if (me->GetVictim()) + me->EnsureVictim()->CastSpell(me->GetVictim(), SPELL_VOLATILE_INFECTION, false); + volatileinf_timer = 12000; + } else volatileinf_timer -= diff; + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + +class boss_koragg : public CreatureScript +{ + public: + + boss_koragg() + : CreatureScript("boss_koragg") + { + } + + struct boss_koraggAI : public boss_hexlord_addAI + { + boss_koraggAI(Creature* creature) : boss_hexlord_addAI(creature) + { + Initialize(); + } + + void Initialize() + { + coldstare_timer = 15000; + mightyblow_timer = 10000; + } + + uint32 coldstare_timer; + uint32 mightyblow_timer; + + void Reset() override + { + Initialize(); + boss_hexlord_addAI::Reset(); + + } + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (mightyblow_timer <= diff) + { + DoCastVictim(SPELL_MIGHTY_BLOW, false); + mightyblow_timer = 12000; + } + if (coldstare_timer <= diff) + { + if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(victim, SPELL_COLD_STARE, false); + coldstare_timer = 12000; + } + + boss_hexlord_addAI::UpdateAI(diff); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI(creature); + } +}; + class spell_hexlord_unstable_affliction : public SpellScriptLoader { public: @@ -141,5 +1061,14 @@ class spell_hexlord_unstable_affliction : public SpellScriptLoader void AddSC_boss_hex_lord_malacrass() { new boss_hexlord_malacrass(); + new boss_thurg(); + // new boss_gazakroth(); + new boss_lord_raadan(); + new boss_darkheart(); + new boss_slither(); + new boss_fenstalker(); + new boss_koragg(); + new boss_alyson_antille(); new spell_hexlord_unstable_affliction(); } + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp index b4e20641a85..3228fbfde1b 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 * * 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 . */ +/* 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 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 searcher(me, templist, check); + + TypeContainerVisitor, 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::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 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 searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *me->GetMap(), *me, me->GetGridActivationRange()); + } + for (std::list::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 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 searcher(me, templist, check); + + TypeContainerVisitor, 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::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(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(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(); } + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index dcc6f02473e..a0e4d037f8a 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 * * 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 . */ +/* 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 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 searcher(me, templist, check); + + TypeContainerVisitor, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange()); + } + + if (templist.empty()) + return; + + for (std::list::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(); } + diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp index 153040fdcfe..3b52e6775b2 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 * * 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 . */ +/* 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(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 targetList; + GetCreatureListWithEntryInGrid(targetList, me, NPC_AMANISHI_GUARDIAN, 26.0f); + if (!targetList.empty()) + { + for (std::list::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(creature); + return GetInstanceAI(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(); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h index 42b23016fde..74162f0859d 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h +++ b/src/server/scripts/EasternKingdoms/ZulAman/zulaman.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2006-2009 ScriptDev2 * * 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 -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 diff --git a/src/server/scripts/Kalimdor/zone_felwood.cpp b/src/server/scripts/Kalimdor/zone_felwood.cpp index 97891e0338f..f0d172db7fa 100644 --- a/src/server/scripts/Kalimdor/zone_felwood.cpp +++ b/src/server/scripts/Kalimdor/zone_felwood.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2008-2015 TrinityCore + * Copyright (C) 2008-2015 TrinityCore * * 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 diff --git a/src/tools/map_extractor/wdt.h b/src/tools/map_extractor/wdt.h index fbec55353a3..8eed0bc6093 100644 --- a/src/tools/map_extractor/wdt.h +++ b/src/tools/map_extractor/wdt.h @@ -87,4 +87,4 @@ public: #pragma pack(pop) -#endif \ No newline at end of file +#endif