aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/Models/WorldModel.h6
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/PetAI.h1
-rw-r--r--src/server/game/AI/CreatureAIRegistry.cpp2
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAI.cpp1327
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAI.h630
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAIMgr.cpp680
-rw-r--r--src/server/game/AI/EventAI/CreatureEventAIMgr.h46
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp19
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h3
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp2
-rw-r--r--src/server/game/Accounts/RBAC.h6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp6
-rw-r--r--src/server/game/CMakeLists.txt1
-rw-r--r--src/server/game/Chat/ChatLink.h10
-rw-r--r--src/server/game/Combat/UnitEvents.h8
-rw-r--r--src/server/game/DataStores/DBCEnums.h58
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp1
-rw-r--r--src/server/game/Entities/Object/Object.h5
-rw-r--r--src/server/game/Entities/Player/Player.cpp36
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp3
-rw-r--r--src/server/game/Entities/Transport/Transport.h1
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp16
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp8
-rw-r--r--src/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Handlers/PetHandler.cpp6
-rw-r--r--src/server/game/Maps/TransportMgr.cpp6
-rw-r--r--src/server/game/Maps/TransportMgr.h4
-rw-r--r--src/server/game/Movement/PathGenerator.cpp2
-rw-r--r--src/server/game/Scripting/MapScripts.cpp4
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp10
-rw-r--r--src/server/game/Spells/SpellMgr.cpp3
-rw-r--r--src/server/game/World/World.cpp17
-rw-r--r--src/server/game/World/World.h6
-rw-r--r--src/server/scripts/CMakeLists.txt1
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp29
-rw-r--r--src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp39
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp1
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp32
-rw-r--r--src/server/scripts/EasternKingdoms/zone_hinterlands.cpp6
-rw-r--r--src/server/scripts/Kalimdor/CMakeLists.txt5
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp1
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp1
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp2
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp115
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp103
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp136
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp107
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp270
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp344
-rw-r--r--src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h51
-rw-r--r--src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp1
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp4
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp3
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp44
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp17
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp4
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp1
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp2
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp2
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp203
-rw-r--r--src/server/scripts/Northrend/zone_grizzly_hills.cpp40
-rw-r--r--src/server/scripts/Northrend/zone_howling_fjord.cpp112
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp86
-rw-r--r--src/server/scripts/Northrend/zone_sholazar_basin.cpp52
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp193
-rw-r--r--src/server/scripts/Northrend/zone_zuldrak.cpp14
-rw-r--r--src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp1
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp18
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp44
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp44
-rw-r--r--src/server/scripts/Outland/zone_blades_edge_mountains.cpp101
-rw-r--r--src/server/shared/Cryptography/HMACSHA1.cpp1
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.cpp2
-rw-r--r--src/server/worldserver/CMakeLists.txt1
-rw-r--r--src/server/worldserver/Master.cpp7
85 files changed, 1874 insertions, 3322 deletions
diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h
index 23fb1cdb7b6..309b6d8051c 100644
--- a/src/server/collision/Models/WorldModel.h
+++ b/src/server/collision/Models/WorldModel.h
@@ -36,7 +36,7 @@ namespace VMAP
class MeshTriangle
{
public:
- MeshTriangle(){ }
+ MeshTriangle() : idx0(0), idx1(0), idx2(0) { }
MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { }
uint32 idx0;
@@ -59,7 +59,7 @@ namespace VMAP
bool writeToFile(FILE* wf);
static bool readFromFile(FILE* rf, WmoLiquid* &liquid);
private:
- WmoLiquid(): iHeight(0), iFlags(0) { }
+ WmoLiquid(): iTilesX(0), iTilesY(0), iType(0), iHeight(0), iFlags(0) { }
uint32 iTilesX; //!< number of tiles in x direction, each
uint32 iTilesY;
G3D::Vector3 iCorner; //!< the lower corner
@@ -74,7 +74,7 @@ namespace VMAP
class GroupModel
{
public:
- GroupModel(): iLiquid(0) { }
+ GroupModel(): iMogpFlags(0), iGroupWMOID(0), iLiquid(0) { }
GroupModel(const GroupModel &other);
GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound):
iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) { }
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp
index 723f8262181..4f015e3f016 100644
--- a/src/server/game/AI/CoreAI/CombatAI.cpp
+++ b/src/server/game/AI/CoreAI/CombatAI.cpp
@@ -330,7 +330,7 @@ void VehicleAI::CheckConditions(const uint32 diff)
{
if (!conditions.empty())
{
- if( Vehicle* vehicleKit = me->GetVehicleKit())
+ if (Vehicle* vehicleKit = me->GetVehicleKit())
for (SeatMap::iterator itr = vehicleKit->Seats.begin(); itr != vehicleKit->Seats.end(); ++itr)
if (Unit* passenger = ObjectAccessor::GetUnit(*me, itr->second.Passenger.Guid))
{
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 9cce00440e1..6e24a079f9f 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -57,7 +57,6 @@ class PetAI : public CreatureAI
void UpdateAllies();
TimeTracker i_tracker;
- bool inCombat;
std::set<uint64> m_AllySet;
uint32 m_updateAlliesTimer;
diff --git a/src/server/game/AI/CreatureAIRegistry.cpp b/src/server/game/AI/CreatureAIRegistry.cpp
index 8f035667a34..8b74db24a42 100644
--- a/src/server/game/AI/CreatureAIRegistry.cpp
+++ b/src/server/game/AI/CreatureAIRegistry.cpp
@@ -22,7 +22,6 @@
#include "GuardAI.h"
#include "PetAI.h"
#include "TotemAI.h"
-#include "CreatureEventAI.h"
#include "RandomMovementGenerator.h"
#include "MovementGeneratorImpl.h"
#include "CreatureAIRegistry.h"
@@ -46,7 +45,6 @@ namespace AIRegistry
(new CreatureAIFactory<CombatAI>("CombatAI"))->RegisterSelf();
(new CreatureAIFactory<ArcherAI>("ArcherAI"))->RegisterSelf();
(new CreatureAIFactory<TurretAI>("TurretAI"))->RegisterSelf();
- (new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
(new CreatureAIFactory<VehicleAI>("VehicleAI"))->RegisterSelf();
(new CreatureAIFactory<SmartAI>("SmartAI"))->RegisterSelf();
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp
deleted file mode 100644
index 8e2e4e8dc2e..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAI.cpp
+++ /dev/null
@@ -1,1327 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "Common.h"
-#include "CreatureEventAI.h"
-#include "CreatureEventAIMgr.h"
-#include "ObjectMgr.h"
-#include "Spell.h"
-#include "World.h"
-#include "Cell.h"
-#include "CellImpl.h"
-#include "GameEventMgr.h"
-#include "GridNotifiers.h"
-#include "GridNotifiersImpl.h"
-#include "InstanceScript.h"
-#include "SpellMgr.h"
-#include "CreatureAIImpl.h"
-#include "ConditionMgr.h"
-
-bool CreatureEventAIHolder::UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax)
-{
- if (repeatMin == repeatMax)
- Time = repeatMin;
- else if (repeatMax > repeatMin)
- Time = urand(repeatMin, repeatMax);
- else
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using Event %u (Type = %u) has RandomMax < RandomMin. Event repeating disabled.", creature->GetEntry(), Event.event_id, Event.event_type);
- Enabled = false;
- return false;
- }
-
- return true;
-}
-
-int CreatureEventAI::Permissible(const Creature* creature)
-{
- if (creature->GetAIName() == "EventAI")
- return PERMIT_BASE_SPECIAL;
- return PERMIT_BASE_NO;
-}
-
-CreatureEventAI::CreatureEventAI(Creature* c) : CreatureAI(c)
-{
- // Need make copy for filter unneeded steps and safe in case table reload
- CreatureEventAI_Event_Map::const_iterator CreatureEvents = sEventAIMgr->GetCreatureEventAIMap().find(me->GetEntry());
- if (CreatureEvents != sEventAIMgr->GetCreatureEventAIMap().end())
- {
- std::vector<CreatureEventAI_Event>::const_iterator i;
- for (i = (*CreatureEvents).second.begin(); i != (*CreatureEvents).second.end(); ++i)
- {
- //Debug check
- #ifndef TRINITY_DEBUG
- if ((*i).event_flags & EFLAG_DEBUG_ONLY)
- continue;
- #endif
- if (me->GetMap()->IsDungeon())
- {
- if ((1 << (me->GetMap()->GetSpawnMode()+1)) & (*i).event_flags)
- {
- //event flagged for instance mode
- m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
- }
- continue;
- }
- m_CreatureEventAIList.push_back(CreatureEventAIHolder(*i));
- }
- //EventMap had events but they were not added because they must be for instance
- if (m_CreatureEventAIList.empty())
- TC_LOG_ERROR("misc", "CreatureEventAI: Creature %u has events but no events added to list because of instance flags.", me->GetEntry());
- }
- else
- TC_LOG_ERROR("misc", "CreatureEventAI: EventMap for Creature %u is empty but creature is using CreatureEventAI.", me->GetEntry());
-
- m_bEmptyList = m_CreatureEventAIList.empty();
- m_Phase = 0;
- m_CombatMovementEnabled = true;
- m_MeleeEnabled = true;
- m_AttackDistance = 0.0f;
- m_AttackAngle = 0.0f;
-
- m_InvincibilityHpLevel = 0;
-
- //Handle Spawned Events
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- if (SpawnedEventConditionsCheck((*i).Event))
- ProcessEvent(*i);
- }
-}
-
-bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker /*=NULL*/)
-{
- if (!holder.Enabled || holder.Time)
- return false;
-
- //Check the inverse phase mask (event doesn't trigger if current phase bit is set in mask)
- if (holder.Event.event_inverse_phase_mask & (1 << m_Phase))
- return false;
-
- CreatureEventAI_Event const& event = holder.Event;
-
- //Check event conditions based on the event type, also reset events
- switch (event.event_type)
- {
- case EVENT_T_TIMER:
- if (!me->IsInCombat())
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax);
- break;
- case EVENT_T_TIMER_OOC:
- if (me->IsInCombat())
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.timer.repeatMin, event.timer.repeatMax);
- break;
- case EVENT_T_HP:
- {
- if (!me->IsInCombat() || !me->GetMaxHealth())
- return false;
-
- uint32 perc = uint32(me->GetHealthPct());
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_MANA:
- {
- if (!me->IsInCombat() || !me->GetMaxPower(POWER_MANA))
- return false;
-
- uint32 perc = (me->GetPower(POWER_MANA)*100) / me->GetMaxPower(POWER_MANA);
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_AGGRO:
- break;
- case EVENT_T_KILL:
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.kill.repeatMin, event.kill.repeatMax);
- break;
- case EVENT_T_DEATH:
- case EVENT_T_EVADE:
- break;
- case EVENT_T_SPELLHIT:
- //Spell hit is special case, param1 and param2 handled within CreatureEventAI::SpellHit
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.spell_hit.repeatMin, event.spell_hit.repeatMax);
- break;
- case EVENT_T_RANGE:
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.range.repeatMin, event.range.repeatMax);
- break;
- case EVENT_T_OOC_LOS:
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.ooc_los.repeatMin, event.ooc_los.repeatMax);
- break;
- case EVENT_T_RESET:
- case EVENT_T_SPAWNED:
- break;
- case EVENT_T_TARGET_HP:
- {
- if (!me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxHealth())
- return false;
-
- uint32 perc = uint32(me->GetVictim()->GetHealthPct());
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_TARGET_CASTING:
- if (!me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->IsNonMeleeSpellCasted(false, false, true))
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.target_casting.repeatMin, event.target_casting.repeatMax);
- break;
- case EVENT_T_FRIENDLY_HP:
- {
- if (!me->IsInCombat())
- return false;
-
- Unit* unit = DoSelectLowestHpFriendly((float)event.friendly_hp.radius, event.friendly_hp.hpDeficit);
- if (!unit)
- return false;
-
- actionInvoker = unit;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.friendly_hp.repeatMin, event.friendly_hp.repeatMax);
- break;
- }
- case EVENT_T_FRIENDLY_IS_CC:
- {
- if (!me->IsInCombat())
- return false;
-
- std::list<Creature*> pList;
- DoFindFriendlyCC(pList, (float)event.friendly_is_cc.radius);
-
- //List is empty
- if (pList.empty())
- return false;
-
- //We don't really care about the whole list, just return first available
- actionInvoker = *(pList.begin());
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.friendly_is_cc.repeatMin, event.friendly_is_cc.repeatMax);
- break;
- }
- case EVENT_T_FRIENDLY_MISSING_BUFF:
- {
- std::list<Creature*> pList;
- DoFindFriendlyMissingBuff(pList, (float)event.friendly_buff.radius, event.friendly_buff.spellId);
-
- //List is empty
- if (pList.empty())
- return false;
-
- //We don't really care about the whole list, just return first available
- actionInvoker = *(pList.begin());
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.friendly_buff.repeatMin, event.friendly_buff.repeatMax);
- break;
- }
- case EVENT_T_SUMMONED_UNIT:
- {
- //Prevent event from occuring on no unit or non creatures
- if (!actionInvoker || actionInvoker->GetTypeId() != TYPEID_UNIT)
- return false;
-
- //Creature id doesn't match up
- if (actionInvoker->ToCreature()->GetEntry() != event.summon_unit.creatureId)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.summon_unit.repeatMin, event.summon_unit.repeatMax);
- break;
- }
- case EVENT_T_TARGET_MANA:
- {
- if (!me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->GetMaxPower(POWER_MANA))
- return false;
-
- uint32 perc = (me->GetVictim()->GetPower(POWER_MANA)*100) / me->GetVictim()->GetMaxPower(POWER_MANA);
-
- if (perc > event.percent_range.percentMax || perc < event.percent_range.percentMin)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.percent_range.repeatMin, event.percent_range.repeatMax);
- break;
- }
- case EVENT_T_REACHED_HOME:
- case EVENT_T_RECEIVE_EMOTE:
- break;
- case EVENT_T_BUFFED:
- {
- //Note: checked only aura for effect 0, if need check aura for effect 1/2 then
- // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
- Aura const* aura = me->GetAura(event.buffed.spellId);
- if (!aura || aura->GetStackAmount() < event.buffed.amount)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax);
- break;
- }
- case EVENT_T_TARGET_BUFFED:
- {
- //Prevent event from occuring on no unit
- if (!actionInvoker)
- return false;
-
- //Note: checked only aura for effect 0, if need check aura for effect 1/2 then
- // possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
- Aura const* aura = actionInvoker->GetAura(event.buffed.spellId);
- if (!aura || aura->GetStackAmount() < event.buffed.amount)
- return false;
-
- //Repeat Timers
- holder.UpdateRepeatTimer(me, event.buffed.repeatMin, event.buffed.repeatMax);
- break;
- }
- default:
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", me->GetEntry(), holder.Event.event_id, holder.Event.event_type);
- break;
- }
-
- //Disable non-repeatable events
- if (!(holder.Event.event_flags & EFLAG_REPEATABLE))
- holder.Enabled = false;
-
- //Store random here so that all random actions match up
- uint32 rnd = rand();
-
- //Return if chance for event is not met
- if (holder.Event.event_chance <= rnd % 100)
- return false;
-
- //Process actions
- for (uint8 j = 0; j < MAX_ACTIONS; ++j)
- ProcessAction(holder.Event.action[j], rnd, holder.Event.event_id, actionInvoker);
-
- return true;
-}
-
-void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker)
-{
- switch (action.type)
- {
- case ACTION_T_TEXT:
- {
- if (!action.text.TextId1)
- return;
-
- int32 temp = action.text.TextId1;
-
- if (action.text.TextId2 && action.text.TextId3)
- temp = RAND(action.text.TextId1, action.text.TextId2, action.text.TextId3);
- else if (action.text.TextId2 && urand(0, 1))
- temp = action.text.TextId2;
-
- if (temp)
- {
- Unit* target = NULL;
-
- if (actionInvoker)
- {
- if (actionInvoker->GetTypeId() == TYPEID_PLAYER)
- target = actionInvoker;
- else if (Unit* owner = actionInvoker->GetOwner())
- {
- if (owner->GetTypeId() == TYPEID_PLAYER)
- target = owner;
- }
- }
- else
- {
- target = me->GetVictim();
- if (target && target->GetTypeId() != TYPEID_PLAYER)
- if (Unit* owner = target->GetOwner())
- if (owner->GetTypeId() == TYPEID_PLAYER)
- target = owner;
- }
-
- DoScriptText(temp, me, target);
- }
- break;
- }
- case ACTION_T_SET_FACTION:
- {
- if (action.set_faction.factionId)
- me->setFaction(action.set_faction.factionId);
- else
- {
- if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(me->GetEntry()))
- {
- //if no id provided, assume reset and then use default
- if (me->getFaction() != ci->faction_A)
- me->setFaction(ci->faction_A);
- }
- }
- break;
- }
- case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- {
- if (action.morph.creatureId || action.morph.modelId)
- {
- //set model based on entry from creature_template
- if (action.morph.creatureId)
- {
- if (CreatureTemplate const* ci = sObjectMgr->GetCreatureTemplate(action.morph.creatureId))
- me->SetDisplayId(ObjectMgr::ChooseDisplayId(ci));
- }
- //if no param1, then use value from param2 (modelId)
- else
- me->SetDisplayId(action.morph.modelId);
- }
- else
- me->DeMorph();
- break;
- }
- case ACTION_T_SOUND:
- me->PlayDirectSound(action.sound.soundId);
- break;
- case ACTION_T_EMOTE:
- me->HandleEmoteCommand(action.emote.emoteId);
- break;
- case ACTION_T_RANDOM_SOUND:
- {
- int32 temp = GetRandActionParam(rnd, action.random_sound.soundId1, action.random_sound.soundId2, action.random_sound.soundId3);
- if (temp >= 0)
- me->PlayDirectSound(temp);
- break;
- }
- case ACTION_T_RANDOM_EMOTE:
- {
- int32 temp = GetRandActionParam(rnd, action.random_emote.emoteId1, action.random_emote.emoteId2, action.random_emote.emoteId3);
- if (temp >= 0)
- me->HandleEmoteCommand(temp);
- break;
- }
- case ACTION_T_CAST:
- {
- Unit* target = GetTargetByType(action.cast.target, actionInvoker);
- Unit* caster = me;
-
- if (!target)
- return;
-
- if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
- caster = target;
-
- //Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
- bool canCast = !caster->IsNonMeleeSpellCasted(false) || (action.cast.castFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS));
-
- // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them
- if (action.cast.castFlags & CAST_AURA_NOT_PRESENT)
- {
- if (target->HasAura(action.cast.spellId))
- return;
- }
-
- if (canCast)
- {
- const SpellInfo* tSpell = sSpellMgr->GetSpellInfo(action.cast.spellId);
-
- //Verify that spell exists
- if (tSpell)
- {
- //Check if cannot cast spell
- if (!(action.cast.castFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)) &&
- !CanCast(target, tSpell, (action.cast.castFlags & CAST_TRIGGERED)))
- {
- //Melee current victim if flag not set
- if (!(action.cast.castFlags & CAST_NO_MELEE_IF_OOM))
- {
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
- {
- m_AttackDistance = 0.0f;
- m_AttackAngle = 0.0f;
-
- me->GetMotionMaster()->MoveChase(me->GetVictim(), m_AttackDistance, m_AttackAngle);
- }
- }
- }
- else
- {
- //Interrupt any previous spell
- if (caster->IsNonMeleeSpellCasted(false) && action.cast.castFlags & CAST_INTERRUPT_PREVIOUS)
- caster->InterruptNonMeleeSpells(false);
-
- caster->CastSpell(target, action.cast.spellId, (action.cast.castFlags & CAST_TRIGGERED));
- }
- }
- else
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: event %d creature %d attempt to cast spell that doesn't exist %d", eventId, me->GetEntry(), action.cast.spellId);
- }
- break;
- }
- case ACTION_T_THREAT_SINGLE_PCT:
- if (Unit* target = GetTargetByType(action.threat_single_pct.target, actionInvoker))
- me->getThreatManager().modifyThreatPercent(target, action.threat_single_pct.percent);
- break;
- case ACTION_T_THREAT_ALL_PCT:
- {
- ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList();
- for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
- if (Unit* unit = Unit::GetUnit(*me, (*i)->getUnitGuid()))
- me->getThreatManager().modifyThreatPercent(unit, action.threat_all_pct.percent);
- break;
- }
- case ACTION_T_QUEST_EVENT:
- if (Unit* target = GetTargetByType(action.quest_event.target, actionInvoker))
- if (target->GetTypeId() == TYPEID_PLAYER)
- target->ToPlayer()->AreaExploredOrEventHappens(action.quest_event.questId);
- break;
- case ACTION_T_SET_UNIT_FIELD:
- {
- Unit* target = GetTargetByType(action.set_unit_field.target, actionInvoker);
-
- // not allow modify important for integrity object fields
- if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
- return;
-
- if (target)
- target->SetUInt32Value(action.set_unit_field.field, action.set_unit_field.value);
-
- break;
- }
- case ACTION_T_SET_UNIT_FLAG:
- if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
- target->SetFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
- break;
- case ACTION_T_REMOVE_UNIT_FLAG:
- if (Unit* target = GetTargetByType(action.unit_flag.target, actionInvoker))
- target->RemoveFlag(UNIT_FIELD_FLAGS, action.unit_flag.value);
- break;
- case ACTION_T_AUTO_ATTACK:
- m_MeleeEnabled = action.auto_attack.state != 0;
- break;
- case ACTION_T_COMBAT_MOVEMENT:
- // ignore no affect case
- if (m_CombatMovementEnabled == (action.combat_movement.state != 0))
- return;
-
- m_CombatMovementEnabled = action.combat_movement.state != 0;
-
- //Allow movement (create new targeted movement gen only if idle)
- if (m_CombatMovementEnabled)
- {
- Unit* victim = me->GetVictim();
- if (me->IsInCombat() && victim)
- {
- if (action.combat_movement.melee)
- {
- me->AddUnitState(UNIT_STATE_MELEE_ATTACKING);
- me->SendMeleeAttackStart(victim);
- }
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
- me->GetMotionMaster()->MoveChase(victim, m_AttackDistance, m_AttackAngle); // Targeted movement generator will start melee automatically, no need to send it explicitly
- }
- }
- else
- {
- if (me->IsInCombat())
- {
- Unit* victim = me->GetVictim();
- if (action.combat_movement.melee && victim)
- {
- me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
- me->SendMeleeAttackStop(victim);
- }
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
- me->GetMotionMaster()->MoveIdle();
- }
- }
- break;
- case ACTION_T_SET_PHASE:
- m_Phase = action.set_phase.phase;
- break;
- case ACTION_T_INC_PHASE:
- {
- int32 new_phase = int32(m_Phase)+action.set_inc_phase.step;
- if (new_phase < 0)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d decrease m_Phase under 0. CreatureEntry = %d", eventId, me->GetEntry());
- m_Phase = 0;
- }
- else if (new_phase >= MAX_PHASE)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d incremented m_Phase above %u. m_Phase mask cannot be used with phases past %u. CreatureEntry = %d", eventId, MAX_PHASE-1, MAX_PHASE-1, me->GetEntry());
- m_Phase = MAX_PHASE-1;
- }
- else
- m_Phase = new_phase;
-
- break;
- }
- case ACTION_T_EVADE:
- EnterEvadeMode();
- break;
- case ACTION_T_FLEE_FOR_ASSIST:
- me->DoFleeToGetAssistance();
- break;
- case ACTION_T_QUEST_EVENT_ALL:
- if (actionInvoker && actionInvoker->GetTypeId() == TYPEID_PLAYER)
- {
- if (Unit* Temp = Unit::GetUnit(*me, actionInvoker->GetGUID()))
- if (Temp->GetTypeId() == TYPEID_PLAYER)
- Temp->ToPlayer()->GroupEventHappens(action.quest_event_all.questId, me);
- }
- break;
- case ACTION_T_REMOVEAURASFROMSPELL:
- if (Unit* target = GetTargetByType(action.remove_aura.target, actionInvoker))
- target->RemoveAurasDueToSpell(action.remove_aura.spellId);
- break;
- case ACTION_T_RANGED_MOVEMENT:
- m_AttackDistance = (float)action.ranged_movement.distance;
- m_AttackAngle = action.ranged_movement.angle/180.0f*M_PI;
-
- if (m_CombatMovementEnabled)
- {
- me->GetMotionMaster()->MoveChase(me->GetVictim(), m_AttackDistance, m_AttackAngle);
- }
- break;
- case ACTION_T_RANDOM_PHASE:
- m_Phase = GetRandActionParam(rnd, action.random_phase.phase1, action.random_phase.phase2, action.random_phase.phase3);
- break;
- case ACTION_T_RANDOM_PHASE_RANGE:
- if (action.random_phase_range.phaseMin <= action.random_phase_range.phaseMax)
- m_Phase = urand(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax);
- else
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: ACTION_T_RANDOM_PHASE_RANGE cannot have Param2 < Param1. Event = %d. CreatureEntry = %d", eventId, me->GetEntry());
- break;
- case ACTION_T_KILLED_MONSTER:
- //first attempt player who tapped creature
- if (Player* player = me->GetLootRecipient())
- player->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player); // player as param is a hacky solution not to use GUID
- else
- {
- //if not available, use actionInvoker
- if (Unit* target = GetTargetByType(action.killed_monster.target, actionInvoker))
- if (Player* player2 = target->GetCharmerOrOwnerPlayerOrPlayerItself())
- player2->RewardPlayerAndGroupAtEvent(action.killed_monster.creatureId, player2);
- }
- break;
- case ACTION_T_SET_INST_DATA:
- {
- InstanceScript* instance = me->GetInstanceScript();
- if (!instance)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d attempt to set instance data without instance script. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- instance->SetData(action.set_inst_data.field, action.set_inst_data.value);
- break;
- }
- case ACTION_T_SET_INST_DATA64:
- {
- Unit* target = GetTargetByType(action.set_inst_data64.target, actionInvoker);
- if (!target)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d attempt to set instance data64 but Target == NULL. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- InstanceScript* instance = me->GetInstanceScript();
- if (!instance)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d attempt to set instance data64 without instance script. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- instance->SetData64(action.set_inst_data64.field, target->GetGUID());
- break;
- }
- case ACTION_T_UPDATE_TEMPLATE:
- if (me->GetEntry() == action.update_template.creatureId)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d ACTION_T_UPDATE_TEMPLATE call with param1 == current entry. Creature %d", eventId, me->GetEntry());
- return;
- }
-
- me->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE);
- break;
- case ACTION_T_DIE:
- if (me->isDead())
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %d ACTION_T_DIE on dead creature. Creature %d", eventId, me->GetEntry());
- return;
- }
- me->Kill(me);
- break;
- case ACTION_T_ZONE_COMBAT_PULSE:
- {
- me->SetInCombatWithZone();
- break;
- }
- case ACTION_T_CALL_FOR_HELP:
- {
- me->CallForHelp((float)action.call_for_help.radius);
- break;
- }
- break;
-
- // TRINITY ONLY
- case ACTION_T_MOVE_RANDOM_POINT: //dosen't work in combat
- {
- float x, y, z;
- me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, (float)action.raw.param1);
- me->GetMotionMaster()->MovePoint(0, x, y, z);
- break;
- }
- case ACTION_T_SET_STAND_STATE:
- me->SetStandState(UnitStandStateType(action.raw.param1));
- break;
- case ACTION_T_SET_PHASE_MASK:
- me->SetPhaseMask(action.raw.param1, true);
- break;
- case ACTION_T_SET_VISIBILITY:
- me->SetVisible(bool(action.raw.param1));
- break;
- case ACTION_T_SET_ACTIVE:
- me->setActive(action.raw.param1 ? true : false);
- break;
- case ACTION_T_SET_AGGRESSIVE:
- me->SetReactState(ReactStates(action.raw.param1));
- break;
- case ACTION_T_ATTACK_START_PULSE:
- AttackStart(me->SelectNearestTarget((float)action.raw.param1));
- break;
- case ACTION_T_SUMMON_GO:
- {
- float x, y, z;
- me->GetPosition(x, y, z);
- GameObject* object = me->SummonGameObject(action.raw.param1, x, y, z, 0, 0, 0, 0, 0, action.raw.param2);
- if (!object)
- TC_LOG_ERROR("scripts", "EventAI failed to spawn object %u. Spawn event %d is on creature %d", action.raw.param1, eventId, me->GetEntry());
-
- break;
- }
- case ACTION_T_SET_SHEATH:
- {
- me->SetSheath(SheathState(action.set_sheath.sheath));
- break;
- }
- case ACTION_T_FORCE_DESPAWN:
- {
- me->DespawnOrUnsummon(action.forced_despawn.msDelay);
- break;
- }
- case ACTION_T_SET_INVINCIBILITY_HP_LEVEL:
- {
- if (action.invincibility_hp_level.is_percent)
- m_InvincibilityHpLevel = me->CountPctFromMaxHealth(action.invincibility_hp_level.hp_level);
- else
- m_InvincibilityHpLevel = action.invincibility_hp_level.hp_level;
- break;
- }
- case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL:
- {
- if (action.mount.creatureId || action.mount.modelId)
- {
- // set model based on entry from creature_template
- if (action.mount.creatureId)
- {
- if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(action.mount.creatureId))
- me->Mount(ObjectMgr::ChooseDisplayId(cInfo));
- }
- //if no param1, then use value from param2 (modelId)
- else
- me->Mount(action.mount.modelId);
- }
- else
- me->Dismount();
-
- break;
- }
- default:
- break;
- }
-}
-
-void CreatureEventAI::JustRespawned()
-{
- Reset();
-
- if (m_bEmptyList)
- return;
-
- //Handle Spawned Events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- if (SpawnedEventConditionsCheck((*i).Event))
- ProcessEvent(*i);
-}
-
-void CreatureEventAI::Reset()
-{
- m_EventUpdateTime = EVENT_UPDATE_TIME;
- m_EventDiff = 0;
-
- if (m_bEmptyList)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_RESET)
- ProcessEvent(*i);
- }
-
- //Reset all events to enabled
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- CreatureEventAI_Event const& event = (*i).Event;
- switch (event.event_type)
- {
- //Reset all out of combat timers
- case EVENT_T_TIMER_OOC:
- {
- if ((*i).UpdateRepeatTimer(me, event.timer.initialMin, event.timer.initialMax))
- (*i).Enabled = true;
- break;
- }
- default:
- /// @todo enable below code line / verify this is correct to enable events previously disabled (ex. aggro yell), instead of enable this in void EnterCombat()
- //(*i).Enabled = true;
- //(*i).Time = 0;
- break;
- }
- }
-}
-
-void CreatureEventAI::JustReachedHome()
-{
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_REACHED_HOME)
- ProcessEvent(*i);
- }
- }
-
- Reset();
-}
-
-void CreatureEventAI::EnterEvadeMode()
-{
- CreatureAI::EnterEvadeMode();
-
- if (m_bEmptyList)
- return;
-
- //Handle Evade events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_EVADE)
- ProcessEvent(*i);
- }
-}
-
-void CreatureEventAI::JustDied(Unit* killer)
-{
- Reset();
-
- if (m_bEmptyList)
- return;
-
- //Handle Evade events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_DEATH)
- ProcessEvent(*i, killer);
- }
-
- // reset phase after any death state events
- m_Phase = 0;
-}
-
-void CreatureEventAI::KilledUnit(Unit* victim)
-{
- if (m_bEmptyList || victim->GetTypeId() != TYPEID_PLAYER)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_KILL)
- ProcessEvent(*i, victim);
- }
-}
-
-void CreatureEventAI::JustSummoned(Creature* unit)
-{
- if (m_bEmptyList || !unit)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- if ((*i).Event.event_type == EVENT_T_SUMMONED_UNIT)
- ProcessEvent(*i, unit);
- }
-}
-
-void CreatureEventAI::EnterCombat(Unit* enemy)
-{
- //Check for on combat start events
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- CreatureEventAI_Event const& event = (*i).Event;
- switch (event.event_type)
- {
- case EVENT_T_AGGRO:
- (*i).Enabled = true;
- ProcessEvent(*i, enemy);
- break;
- //Reset all in combat timers
- case EVENT_T_TIMER:
- if ((*i).UpdateRepeatTimer(me, event.timer.initialMin, event.timer.initialMax))
- (*i).Enabled = true;
- break;
- //All normal events need to be re-enabled and their time set to 0
- default:
- (*i).Enabled = true;
- (*i).Time = 0;
- break;
- }
- }
- }
-
- m_EventUpdateTime = EVENT_UPDATE_TIME;
- m_EventDiff = 0;
-}
-
-void CreatureEventAI::AttackStart(Unit* who)
-{
- if (!who)
- return;
-
- if (me->Attack(who, m_MeleeEnabled))
- {
- if (m_CombatMovementEnabled)
- {
- me->GetMotionMaster()->MoveChase(who, m_AttackDistance, m_AttackAngle);
- }
- else
- {
- me->GetMotionMaster()->MoveIdle();
- }
- }
-}
-
-void CreatureEventAI::MoveInLineOfSight(Unit* who)
-{
- if (me->GetVictim())
- return;
-
- //Check for OOC LOS Event
- if (!m_bEmptyList)
- {
- for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
- {
- if ((*itr).Event.event_type == EVENT_T_OOC_LOS)
- {
- //can trigger if closer than fMaxAllowedRange
- float fMaxAllowedRange = (float)((*itr).Event.ooc_los.maxRange);
-
- //if range is ok and we are actually in LOS
- if (me->IsWithinDistInMap(who, fMaxAllowedRange) && me->IsWithinLOSInMap(who))
- {
- //if friendly event&&who is not hostile OR hostile event&&who is hostile
- if (((*itr).Event.ooc_los.noHostile && !me->IsHostileTo(who)) ||
- ((!(*itr).Event.ooc_los.noHostile) && me->IsHostileTo(who)))
- ProcessEvent(*itr, who);
- }
- }
- }
- }
-
- CreatureAI::MoveInLineOfSight(who);
-}
-
-void CreatureEventAI::SpellHit(Unit* unit, const SpellInfo* spell)
-{
- if (m_bEmptyList)
- return;
-
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- if ((*i).Event.event_type == EVENT_T_SPELLHIT)
- //If spell id matches (or no spell id) & if spell school matches (or no spell school)
- if (!(*i).Event.spell_hit.spellId || spell->Id == (*i).Event.spell_hit.spellId)
- if (spell->SchoolMask & (*i).Event.spell_hit.schoolMask)
- ProcessEvent(*i, unit);
-}
-
-void CreatureEventAI::UpdateAI(uint32 diff)
-{
- //Check if we are in combat (also updates calls threat update code)
- bool Combat = UpdateVictim();
-
- if (!m_bEmptyList)
- {
- //Events are only updated once every EVENT_UPDATE_TIME ms to prevent lag with large amount of events
- if (m_EventUpdateTime <= diff)
- {
- m_EventDiff += diff;
-
- //Check for time based events
- for (CreatureEventAIList::iterator i = m_CreatureEventAIList.begin(); i != m_CreatureEventAIList.end(); ++i)
- {
- //Decrement Timers
- if ((*i).Time)
- {
- if (m_EventDiff <= (*i).Time)
- {
- //Do not decrement timers if event cannot trigger in this phase
- if (!((*i).Event.event_inverse_phase_mask & (1 << m_Phase)))
- (*i).Time -= m_EventDiff;
-
- //Skip processing of events that have time remaining
- continue;
- }
- else (*i).Time = 0;
- }
-
- //Events that are updated every EVENT_UPDATE_TIME
- switch ((*i).Event.event_type)
- {
- case EVENT_T_TIMER_OOC:
- ProcessEvent(*i);
- break;
- case EVENT_T_TIMER:
- case EVENT_T_MANA:
- case EVENT_T_HP:
- case EVENT_T_TARGET_HP:
- case EVENT_T_TARGET_CASTING:
- case EVENT_T_FRIENDLY_HP:
- if (me->GetVictim())
- ProcessEvent(*i);
- break;
- case EVENT_T_RANGE:
- if (me->GetVictim())
- if (me->IsInMap(me->GetVictim()) && me->InSamePhase(me->GetVictim()))
- if (me->IsInRange(me->GetVictim(), (float)(*i).Event.range.minDist, (float)(*i).Event.range.maxDist))
- ProcessEvent(*i);
- break;
- default:
- break;
- }
- }
-
- m_EventDiff = 0;
- m_EventUpdateTime = EVENT_UPDATE_TIME;
- }
- else
- {
- m_EventDiff += diff;
- m_EventUpdateTime -= diff;
- }
- }
-
- //Melee Auto-Attack
- if (Combat && m_MeleeEnabled)
- DoMeleeAttackIfReady();
-}
-
-inline uint32 CreatureEventAI::GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3)
-{
- switch (rnd % 3)
- {
- case 0: return param1;
- case 1: return param2;
- case 2: break;
- }
-
- return param3;
-}
-
-inline int32 CreatureEventAI::GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3)
-{
- switch (rnd % 3)
- {
- case 0: return param1;
- case 1: return param2;
- case 2: break;
- }
-
- return param3;
-}
-
-inline Unit* CreatureEventAI::GetTargetByType(uint32 target, Unit* actionInvoker)
-{
- switch (target)
- {
- case TARGET_T_SELF:
- return me;
- case TARGET_T_HOSTILE:
- return me->GetVictim();
- case TARGET_T_HOSTILE_SECOND_AGGRO:
- return SelectTarget(SELECT_TARGET_TOPAGGRO, 1);
- case TARGET_T_HOSTILE_LAST_AGGRO:
- return SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0);
- case TARGET_T_HOSTILE_RANDOM:
- return SelectTarget(SELECT_TARGET_RANDOM, 0);
- case TARGET_T_HOSTILE_RANDOM_NOT_TOP:
- return SelectTarget(SELECT_TARGET_RANDOM, 1);
- case TARGET_T_ACTION_INVOKER:
- return actionInvoker;
- default:
- return NULL;
- };
-}
-
-Unit* CreatureEventAI::DoSelectLowestHpFriendly(float range, uint32 minHPDiff)
-{
- CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
- Unit* unit = NULL;
-
- Trinity::MostHPMissingInRange u_check(me, range, minHPDiff);
- Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(me, unit, u_check);
-
- /*
- typedef TYPELIST_4(GameObject, Creature*except pets*, DynamicObject, Corpse*Bones*) AllGridObjectTypes;
- This means that if we only search grid then we cannot possibly return pets or players so this is safe
- */
- TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange>, GridTypeMapContainer > grid_unit_searcher(searcher);
-
- cell.Visit(p, grid_unit_searcher, *me->GetMap(), *me, range);
- return unit;
-}
-
-void CreatureEventAI::DoFindFriendlyCC(std::list<Creature*>& _list, float range)
-{
- CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
- Trinity::FriendlyCCedInRange u_check(me, range);
- Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(me, _list, u_check);
-
- TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
-
- cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
-}
-
-void CreatureEventAI::DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid)
-{
- CellCoord p(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
- Trinity::FriendlyMissingBuffInRange u_check(me, range, spellid);
- Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(me, _list, u_check);
-
- TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange>, GridTypeMapContainer > grid_creature_searcher(searcher);
-
- cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
-}
-
-// *********************************
-// *** Functions used globally ***
-
-void CreatureEventAI::DoScriptText(int32 textEntry, WorldObject* source, Unit* target)
-{
- if (!source)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText entry %i, invalid Source pointer.", textEntry);
- return;
- }
-
- if (textEntry >= 0)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.", source->GetEntry(), source->GetTypeId(), source->GetGUIDLow(), textEntry);
- return;
- }
-
- CreatureEventAI_TextMap::const_iterator i = sEventAIMgr->GetCreatureEventAITextMap().find(textEntry);
-
- if (i == sEventAIMgr->GetCreatureEventAITextMap().end())
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.", source->GetEntry(), source->GetTypeId(), source->GetGUIDLow(), textEntry);
- return;
- }
-
- TC_LOG_DEBUG("scripts.ai", "CreatureEventAI: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u", textEntry, (*i).second.SoundId, (*i).second.Type, (*i).second.Language, (*i).second.Emote);
-
- if ((*i).second.SoundId)
- {
- if (sSoundEntriesStore.LookupEntry((*i).second.SoundId))
- source->PlayDirectSound((*i).second.SoundId);
- else
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText entry %i tried to process invalid sound id %u.", textEntry, (*i).second.SoundId);
- }
-
- if ((*i).second.Emote)
- {
- if (source->GetTypeId() == TYPEID_UNIT || source->GetTypeId() == TYPEID_PLAYER)
- {
- ((Unit*)source)->HandleEmoteCommand((*i).second.Emote);
- }
- else
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", textEntry, source->GetTypeId());
- }
-
- switch ((*i).second.Type)
- {
- case CHAT_TYPE_SAY:
- source->MonsterSay(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
- break;
- case CHAT_TYPE_YELL:
- source->MonsterYell(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
- break;
- case CHAT_TYPE_TEXT_EMOTE:
- source->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0);
- break;
- case CHAT_TYPE_BOSS_EMOTE:
- source->MonsterTextEmote(textEntry, target ? target->GetGUID() : 0, true);
- break;
- case CHAT_TYPE_WHISPER:
- {
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- source->MonsterWhisper(textEntry, target->GetGUID());
- else TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry);
- }break;
- case CHAT_TYPE_BOSS_WHISPER:
- {
- if (target && target->GetTypeId() == TYPEID_PLAYER)
- source->MonsterWhisper(textEntry, target->GetGUID(), true);
- else TC_LOG_ERROR("sql.sql", "CreatureEventAI: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", textEntry);
- }break;
- case CHAT_TYPE_ZONE_YELL:
- source->MonsterYellToZone(textEntry, (*i).second.Language, target ? target->GetGUID() : 0);
- break;
- }
-}
-
-bool CreatureEventAI::CanCast(Unit* target, SpellInfo const* spell, bool triggered)
-{
- //No target so we can't cast
- if (!target || !spell)
- return false;
-
- //Silenced so we can't cast
- if (!triggered && me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
- return false;
-
- //Check for power
- if (!triggered && me->GetPower((Powers)spell->PowerType) < uint32(spell->CalcPowerCost(me, spell->GetSchoolMask())))
- return false;
-
- //Unit is out of range of this spell
- if (!me->IsInRange(target, spell->GetMinRange(false), spell->GetMaxRange(false)))
- return false;
-
- //Spell is on cooldown
- if (me->HasSpellCooldown(spell->Id))
- return false;
-
- return true;
-}
-
-void CreatureEventAI::ReceiveEmote(Player* player, uint32 textEmote)
-{
- if (m_bEmptyList)
- return;
-
- for (CreatureEventAIList::iterator itr = m_CreatureEventAIList.begin(); itr != m_CreatureEventAIList.end(); ++itr)
- {
- if ((*itr).Event.event_type == EVENT_T_RECEIVE_EMOTE)
- {
- if ((*itr).Event.receive_emote.emoteId != textEmote)
- return;
-
- Condition cond;
- cond.ConditionType = ConditionTypes((*itr).Event.receive_emote.condition);
- cond.ConditionValue1 = (*itr).Event.receive_emote.conditionValue1;
- cond.ConditionValue2 = (*itr).Event.receive_emote.conditionValue2;
-
- ConditionSourceInfo srcInfo = ConditionSourceInfo(player);
- if (cond.Meets(srcInfo))
- {
- TC_LOG_DEBUG("scripts.ai", "CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing");
- ProcessEvent(*itr, player);
- }
- }
- }
-}
-
-void CreatureEventAI::DamageTaken(Unit* /*done_by*/, uint32& damage)
-{
- if (m_InvincibilityHpLevel > 0 && me->GetHealth() < m_InvincibilityHpLevel+damage)
- {
- if (me->GetHealth() <= m_InvincibilityHpLevel)
- damage = 0;
- else
- damage = me->GetHealth() - m_InvincibilityHpLevel;
- }
-}
-
-bool CreatureEventAI::SpawnedEventConditionsCheck(CreatureEventAI_Event const& event)
-{
- if (event.event_type != EVENT_T_SPAWNED)
- return false;
-
- switch (event.spawned.condition)
- {
- case SPAWNED_EVENT_ALWAY:
- // always
- return true;
- case SPAWNED_EVENT_MAP:
- // map ID check
- return me->GetMapId() == event.spawned.conditionValue1;
- case SPAWNED_EVENT_ZONE:
- {
- // zone ID check
- uint32 zone, area;
- me->GetZoneAndAreaId(zone, area);
- return zone == event.spawned.conditionValue1 || area == event.spawned.conditionValue1;
- }
- default:
- break;
- }
-
- return false;
-}
diff --git a/src/server/game/AI/EventAI/CreatureEventAI.h b/src/server/game/AI/EventAI/CreatureEventAI.h
deleted file mode 100644
index c16f0901b05..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAI.h
+++ /dev/null
@@ -1,630 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_CREATURE_EAI_H
-#define TRINITY_CREATURE_EAI_H
-
-#include "Common.h"
-#include "Creature.h"
-#include "CreatureAI.h"
-#include "Unit.h"
-
-class Player;
-class WorldObject;
-
-#define EVENT_UPDATE_TIME 500
-#define MAX_ACTIONS 3
-#define MAX_PHASE 32
-
-enum EventAI_Type
-{
- EVENT_T_TIMER = 0, // InitialMin, InitialMax, RepeatMin, RepeatMax
- EVENT_T_TIMER_OOC = 1, // InitialMin, InitialMax, RepeatMin, RepeatMax
- EVENT_T_HP = 2, // HPMax%, HPMin%, RepeatMin, RepeatMax
- EVENT_T_MANA = 3, // ManaMax%, ManaMin% RepeatMin, RepeatMax
- EVENT_T_AGGRO = 4, // NONE
- EVENT_T_KILL = 5, // RepeatMin, RepeatMax
- EVENT_T_DEATH = 6, // NONE
- EVENT_T_EVADE = 7, // NONE
- EVENT_T_SPELLHIT = 8, // SpellID, School, RepeatMin, RepeatMax
- EVENT_T_RANGE = 9, // MinDist, MaxDist, RepeatMin, RepeatMax
- EVENT_T_OOC_LOS = 10, // NoHostile, MaxRnage, RepeatMin, RepeatMax
- EVENT_T_SPAWNED = 11, // Condition, CondValue1
- EVENT_T_TARGET_HP = 12, // HPMax%, HPMin%, RepeatMin, RepeatMax
- EVENT_T_TARGET_CASTING = 13, // RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_HP = 14, // HPDeficit, Radius, RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_IS_CC = 15, // DispelType, Radius, RepeatMin, RepeatMax
- EVENT_T_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax
- EVENT_T_SUMMONED_UNIT = 17, // CreatureId, RepeatMin, RepeatMax
- EVENT_T_TARGET_MANA = 18, // ManaMax%, ManaMin%, RepeatMin, RepeatMax
- EVENT_T_QUEST_ACCEPT = 19, // QuestID
- EVENT_T_QUEST_COMPLETE = 20, //
- EVENT_T_REACHED_HOME = 21, // NONE
- EVENT_T_RECEIVE_EMOTE = 22, // EmoteId, Condition, CondValue1, CondValue2
- EVENT_T_BUFFED = 23, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 Repeat Min/Max
- EVENT_T_TARGET_BUFFED = 24, // Param1 = SpellID, Param2 = Number of Time STacked, Param3/4 Repeat Min/Max
- EVENT_T_RESET = 35, // Is it called after combat, when the creature respawn and spawn. -- TRINITY ONLY
-
- EVENT_T_END
-};
-
-enum EventAI_ActionType
-{
- ACTION_T_NONE = 0, // No action
- ACTION_T_TEXT = 1, // TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
- ACTION_T_SET_FACTION = 2, // FactionId (or 0 for default)
- ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
- ACTION_T_SOUND = 4, // SoundId
- ACTION_T_EMOTE = 5, // EmoteId
- ACTION_T_RANDOM_SAY = 6, // UNUSED
- ACTION_T_RANDOM_YELL = 7, // UNUSED
- ACTION_T_RANDOM_TEXTEMOTE = 8, // UNUSED
- ACTION_T_RANDOM_SOUND = 9, // SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
- ACTION_T_RANDOM_EMOTE = 10, // EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
- ACTION_T_CAST = 11, // SpellId, Target, CastFlags
- ACTION_T_SUMMON = 12, // CreatureID, Target, Duration in ms
- ACTION_T_THREAT_SINGLE_PCT = 13, // Threat%, Target
- ACTION_T_THREAT_ALL_PCT = 14, // Threat%
- ACTION_T_QUEST_EVENT = 15, // QuestID, Target
- // none = 16,
- ACTION_T_SET_UNIT_FIELD = 17, // Field_Number, Value, Target
- ACTION_T_SET_UNIT_FLAG = 18, // Flags (may be more than one field OR'd together), Target
- ACTION_T_REMOVE_UNIT_FLAG = 19, // Flags (may be more than one field OR'd together), Target
- ACTION_T_AUTO_ATTACK = 20, // AllowAttackState (0 = stop attack, anything else means continue attacking)
- ACTION_T_COMBAT_MOVEMENT = 21, // AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
- ACTION_T_SET_PHASE = 22, // Phase
- ACTION_T_INC_PHASE = 23, // Value (may be negative to decrement phase, should not be 0)
- ACTION_T_EVADE = 24, // No Params
- ACTION_T_FLEE_FOR_ASSIST = 25, // No Params
- ACTION_T_QUEST_EVENT_ALL = 26, // QuestID
- // none = 27,
- ACTION_T_REMOVEAURASFROMSPELL = 28, // Target, Spellid
- ACTION_T_RANGED_MOVEMENT = 29, // Distance, Angle
- ACTION_T_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3
- ACTION_T_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax
- ACTION_T_SUMMON_ID = 32, // CreatureId, Target, SpawnId
- ACTION_T_KILLED_MONSTER = 33, // CreatureId, Target
- ACTION_T_SET_INST_DATA = 34, // Field, Data
- ACTION_T_SET_INST_DATA64 = 35, // Field, Target
- ACTION_T_UPDATE_TEMPLATE = 36, // Entry, Team
- ACTION_T_DIE = 37, // No Params
- ACTION_T_ZONE_COMBAT_PULSE = 38, // No Params
- ACTION_T_CALL_FOR_HELP = 39, // Radius
- ACTION_T_SET_SHEATH = 40, // Sheath (0-passive, 1-melee, 2-ranged)
- ACTION_T_FORCE_DESPAWN = 41, // No Params
- ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42, // MinHpValue, format(0-flat, 1-percent from max health)
- ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to dismount)
-
- ACTION_T_SET_PHASE_MASK = 97,
- ACTION_T_SET_STAND_STATE = 98,
- ACTION_T_MOVE_RANDOM_POINT = 99,
- ACTION_T_SET_VISIBILITY = 100,
- ACTION_T_SET_ACTIVE = 101, //Apply
- ACTION_T_SET_AGGRESSIVE = 102, //Apply
- ACTION_T_ATTACK_START_PULSE = 103, //Distance
- ACTION_T_SUMMON_GO = 104, //GameObjectID, DespawnTime in ms
-
- ACTION_T_END = 105
-};
-
-enum Target
-{
- //Self (me)
- TARGET_T_SELF = 0, //Self cast
-
- //Hostile targets (if pet then returns pet owner)
- TARGET_T_HOSTILE, //Our current target (ie: highest aggro)
- TARGET_T_HOSTILE_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
- TARGET_T_HOSTILE_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
- TARGET_T_HOSTILE_RANDOM, //Just any random target on our threat list
- TARGET_T_HOSTILE_RANDOM_NOT_TOP, //Any random target except top threat
-
- //Invoker targets (if pet then returns pet owner)
- TARGET_T_ACTION_INVOKER, //Unit who caused this Event to occur (only works for EVENT_T_AGGRO, EVENT_T_KILL, EVENT_T_DEATH, EVENT_T_SPELLHIT, EVENT_T_OOC_LOS, EVENT_T_FRIENDLY_HP, EVENT_T_FRIENDLY_IS_CC, EVENT_T_FRIENDLY_MISSING_BUFF)
-
- //Hostile targets (including pets)
- TARGET_T_HOSTILE_WPET, //Current target (can be a pet)
- TARGET_T_HOSTILE_WPET_SECOND_AGGRO, //Second highest aggro (generaly used for cleaves and some special attacks)
- TARGET_T_HOSTILE_WPET_LAST_AGGRO, //Dead last on aggro (no idea what this could be used for)
- TARGET_T_HOSTILE_WPET_RANDOM, //Just any random target on our threat list
- TARGET_T_HOSTILE_WPET_RANDOM_NOT_TOP, //Any random target except top threat
-
- TARGET_T_ACTION_INVOKER_WPET,
-
- TARGET_T_END
-};
-
-enum CastFlags
-{
- CAST_INTERRUPT_PREVIOUS = 0x01, //Interrupt any spell casting
- CAST_TRIGGERED = 0x02, //Triggered (this makes spell cost zero mana and have no cast time)
- CAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
- CAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
- CAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
- CAST_AURA_NOT_PRESENT = 0x20 //Only casts the spell if the target does not have an aura from the spell
-};
-
-enum EventFlags
-{
- EFLAG_REPEATABLE = 0x01, //Event repeats
- EFLAG_DIFFICULTY_0 = 0x02, //Event only occurs in instance difficulty 0
- EFLAG_DIFFICULTY_1 = 0x04, //Event only occurs in instance difficulty 1
- EFLAG_DIFFICULTY_2 = 0x08, //Event only occurs in instance difficulty 2
- EFLAG_DIFFICULTY_3 = 0x10, //Event only occurs in instance difficulty 3
- EFLAG_RESERVED_5 = 0x20,
- EFLAG_RESERVED_6 = 0x40,
- EFLAG_DEBUG_ONLY = 0x80, //Event only occurs in debug build
-
- EFLAG_DIFFICULTY_ALL = (EFLAG_DIFFICULTY_0|EFLAG_DIFFICULTY_1|EFLAG_DIFFICULTY_2|EFLAG_DIFFICULTY_3)
-};
-
-enum SpawnedEventMode
-{
- SPAWNED_EVENT_ALWAY = 0,
- SPAWNED_EVENT_MAP = 1,
- SPAWNED_EVENT_ZONE = 2
-};
-
-// String text additional data, used in (CreatureEventAI)
-struct StringTextData
-{
- uint32 SoundId;
- uint8 Type;
- uint32 Language;
- uint32 Emote;
-};
-// Text Maps
-typedef UNORDERED_MAP<int32, StringTextData> CreatureEventAI_TextMap;
-
-struct CreatureEventAI_Action
-{
- EventAI_ActionType type: 16;
- union
- {
- // ACTION_T_TEXT = 1
- struct
- {
- int32 TextId1;
- int32 TextId2;
- int32 TextId3;
- } text;
- // ACTION_T_SET_FACTION = 2
- struct
- {
- uint32 factionId; // faction or 0 for default)
- } set_faction;
- // ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3
- struct
- {
- uint32 creatureId; // set one from fields (or 0 for both to demorph)
- uint32 modelId;
- } morph;
- // ACTION_T_SOUND = 4
- struct
- {
- uint32 soundId;
- } sound;
- // ACTION_T_EMOTE = 5
- struct
- {
- uint32 emoteId;
- } emote;
- // ACTION_T_RANDOM_SOUND = 9
- struct
- {
- int32 soundId1; // (-1 in any field means no output if randomed that field)
- int32 soundId2;
- int32 soundId3;
- } random_sound;
- // ACTION_T_RANDOM_EMOTE = 10
- struct
- {
- int32 emoteId1; // (-1 in any field means no output if randomed that field)
- int32 emoteId2;
- int32 emoteId3;
- } random_emote;
- // ACTION_T_CAST = 11
- struct
- {
- uint32 spellId;
- uint32 target;
- uint32 castFlags;
- } cast;
- // ACTION_T_SUMMON = 12
- struct
- {
- uint32 creatureId;
- uint32 target;
- uint32 duration;
- } summon;
- // ACTION_T_THREAT_SINGLE_PCT = 13
- struct
- {
- int32 percent;
- uint32 target;
- } threat_single_pct;
- // ACTION_T_THREAT_ALL_PCT = 14
- struct
- {
- int32 percent;
- } threat_all_pct;
- // ACTION_T_QUEST_EVENT = 15
- struct
- {
- uint32 questId;
- uint32 target;
- } quest_event;
- // ACTION_T_SET_UNIT_FIELD = 17
- struct
- {
- uint32 field;
- uint32 value;
- uint32 target;
- } set_unit_field;
- // ACTION_T_SET_UNIT_FLAG = 18, // value provided mask bits that will be set
- // ACTION_T_REMOVE_UNIT_FLAG = 19, // value provided mask bits that will be clear
- struct
- {
- uint32 value;
- uint32 target;
- } unit_flag;
- // ACTION_T_AUTO_ATTACK = 20
- struct
- {
- uint32 state; // 0 = stop attack, anything else means continue attacking
- } auto_attack;
- // ACTION_T_COMBAT_MOVEMENT = 21
- struct
- {
- uint32 state; // 0 = stop combat based movement, anything else continue attacking
- uint32 melee; // if set: at stop send melee combat stop if in combat, use for terminate melee fighting state for switch to ranged
- } combat_movement;
- // ACTION_T_SET_PHASE = 22
- struct
- {
- uint32 phase;
- } set_phase;
- // ACTION_T_INC_PHASE = 23
- struct
- {
- int32 step;
- } set_inc_phase;
- // ACTION_T_QUEST_EVENT_ALL = 26
- struct
- {
- uint32 questId;
- } quest_event_all;
- // ACTION_T_REMOVEAURASFROMSPELL = 28
- struct
- {
- uint32 target;
- uint32 spellId;
- } remove_aura;
- // ACTION_T_RANGED_MOVEMENT = 29
- struct
- {
- uint32 distance;
- int32 angle;
- } ranged_movement;
- // ACTION_T_RANDOM_PHASE = 30
- struct
- {
- uint32 phase1;
- uint32 phase2;
- uint32 phase3;
- } random_phase;
- // ACTION_T_RANDOM_PHASE_RANGE = 31
- struct
- {
- uint32 phaseMin;
- uint32 phaseMax;
- } random_phase_range;
- // ACTION_T_SUMMON_ID = 32
- struct
- {
- uint32 creatureId;
- uint32 target;
- uint32 spawnId;
- } summon_id;
- // ACTION_T_KILLED_MONSTER = 33
- struct
- {
- uint32 creatureId;
- uint32 target;
- } killed_monster;
- // ACTION_T_SET_INST_DATA = 34
- struct
- {
- uint32 field;
- uint32 value;
- } set_inst_data;
- // ACTION_T_SET_INST_DATA64 = 35
- struct
- {
- uint32 field;
- uint32 target;
- } set_inst_data64;
- // ACTION_T_UPDATE_TEMPLATE = 36
- struct
- {
- uint32 creatureId;
- uint32 team;
- } update_template;
- // ACTION_T_CALL_FOR_HELP = 39
- struct
- {
- uint32 radius;
- } call_for_help;
- // ACTION_T_SET_SHEATH = 40
- struct
- {
- uint32 sheath;
- } set_sheath;
- // ACTION_T_FORCE_DESPAWN = 41
- struct
- {
- uint32 msDelay;
- } forced_despawn;
- // ACTION_T_SET_INVINCIBILITY_HP_LEVEL = 42
- struct
- {
- uint32 hp_level;
- uint32 is_percent;
- } invincibility_hp_level;
- // ACTION_T_MOUNT_TO_ENTRY_OR_MODEL = 43
- struct
- {
- uint32 creatureId; // set one from fields (or 0 for both to dismount)
- uint32 modelId;
- } mount;
- // RAW
- struct
- {
- uint32 param1;
- uint32 param2;
- uint32 param3;
- } raw;
- };
-};
-
-struct CreatureEventAI_Event
-{
- uint32 event_id;
-
- uint32 creature_id;
-
- uint32 event_inverse_phase_mask;
-
- EventAI_Type event_type : 16;
- uint8 event_chance : 8;
- uint8 event_flags : 8;
-
- union
- {
- // EVENT_T_TIMER = 0
- // EVENT_T_TIMER_OOC = 1
- struct
- {
- uint32 initialMin;
- uint32 initialMax;
- uint32 repeatMin;
- uint32 repeatMax;
- } timer;
- // EVENT_T_HP = 2
- // EVENT_T_MANA = 3
- // EVENT_T_TARGET_HP = 12
- // EVENT_T_TARGET_MANA = 18
- struct
- {
- uint32 percentMax;
- uint32 percentMin;
- uint32 repeatMin;
- uint32 repeatMax;
- } percent_range;
- // EVENT_T_KILL = 5
- struct
- {
- uint32 repeatMin;
- uint32 repeatMax;
- } kill;
- // EVENT_T_SPELLHIT = 8
- struct
- {
- uint32 spellId;
- uint32 schoolMask; // -1 ( == 0xffffffff) is ok value for full mask, or must be more limited mask like (0 < 1) = 1 for normal/physical school
- uint32 repeatMin;
- uint32 repeatMax;
- } spell_hit;
- // EVENT_T_RANGE = 9
- struct
- {
- uint32 minDist;
- uint32 maxDist;
- uint32 repeatMin;
- uint32 repeatMax;
- } range;
- // EVENT_T_OOC_LOS = 10
- struct
- {
- uint32 noHostile;
- uint32 maxRange;
- uint32 repeatMin;
- uint32 repeatMax;
- } ooc_los;
- // EVENT_T_SPAWNED = 11
- struct
- {
- uint32 condition;
- uint32 conditionValue1;
- } spawned;
- // EVENT_T_TARGET_CASTING = 13
- struct
- {
- uint32 repeatMin;
- uint32 repeatMax;
- } target_casting;
- // EVENT_T_FRIENDLY_HP = 14
- struct
- {
- uint32 hpDeficit;
- uint32 radius;
- uint32 repeatMin;
- uint32 repeatMax;
- } friendly_hp;
- // EVENT_T_FRIENDLY_IS_CC = 15
- struct
- {
- uint32 dispelType; // unused ?
- uint32 radius;
- uint32 repeatMin;
- uint32 repeatMax;
- } friendly_is_cc;
- // EVENT_T_FRIENDLY_MISSING_BUFF = 16
- struct
- {
- uint32 spellId;
- uint32 radius;
- uint32 repeatMin;
- uint32 repeatMax;
- } friendly_buff;
- // EVENT_T_SUMMONED_UNIT = 17
- struct
- {
- uint32 creatureId;
- uint32 repeatMin;
- uint32 repeatMax;
- } summon_unit;
- // EVENT_T_QUEST_ACCEPT = 19
- // EVENT_T_QUEST_COMPLETE = 20
- struct
- {
- uint32 questId;
- } quest;
- // EVENT_T_RECEIVE_EMOTE = 22
- struct
- {
- uint32 emoteId;
- uint32 condition;
- uint32 conditionValue1;
- uint32 conditionValue2;
- } receive_emote;
- // EVENT_T_BUFFED = 23
- // EVENT_T_TARGET_BUFFED = 24
- struct
- {
- uint32 spellId;
- uint32 amount;
- uint32 repeatMin;
- uint32 repeatMax;
- } buffed;
-
- // RAW
- struct
- {
- uint32 param1;
- uint32 param2;
- uint32 param3;
- uint32 param4;
- } raw;
- };
-
- CreatureEventAI_Action action[MAX_ACTIONS];
-};
-//Event_Map
-typedef UNORDERED_MAP<uint32, std::vector<CreatureEventAI_Event> > CreatureEventAI_Event_Map;
-
-struct CreatureEventAI_Summon
-{
- //uint32 id;
-
- float position_x;
- float position_y;
- float position_z;
- float orientation;
- uint32 SpawnTimeSecs;
-};
-
-//EventSummon_Map
-typedef UNORDERED_MAP<uint32, CreatureEventAI_Summon> CreatureEventAI_Summon_Map;
-
-struct CreatureEventAIHolder
-{
- CreatureEventAIHolder(CreatureEventAI_Event const& p) : Event(p), Time(0), Enabled(true){ }
-
- CreatureEventAI_Event Event;
- uint32 Time;
- bool Enabled;
-
- // helper
- bool UpdateRepeatTimer(Creature* creature, uint32 repeatMin, uint32 repeatMax);
-};
-
-class CreatureEventAI : public CreatureAI
-{
- public:
- explicit CreatureEventAI(Creature* c);
- ~CreatureEventAI() { }
-
- void JustRespawned();
- void Reset();
- void JustReachedHome();
- void EnterCombat(Unit* enemy);
- void EnterEvadeMode();
- void JustDied(Unit* /*killer*/);
- void KilledUnit(Unit* victim);
- void JustSummoned(Creature* unit);
- void AttackStart(Unit* who);
- void MoveInLineOfSight(Unit* who);
- void SpellHit(Unit* unit, const SpellInfo* spell);
- void DamageTaken(Unit* done_by, uint32& damage);
- void HealReceived(Unit* /*done_by*/, uint32& /*addhealth*/) { }
- void UpdateAI(uint32 diff);
- void ReceiveEmote(Player* player, uint32 textEmote);
- static int Permissible(const Creature*);
-
- bool ProcessEvent(CreatureEventAIHolder& holder, Unit* actionInvoker = NULL);
- void ProcessAction(CreatureEventAI_Action const& action, uint32 rnd, uint32 eventId, Unit* actionInvoker);
- inline uint32 GetRandActionParam(uint32 rnd, uint32 param1, uint32 param2, uint32 param3);
- inline int32 GetRandActionParam(uint32 rnd, int32 param1, int32 param2, int32 param3);
- inline Unit* GetTargetByType(uint32 target, Unit* actionInvoker);
-
- void DoScriptText(int32 textEntry, WorldObject* source, Unit* target);
- bool CanCast(Unit* target, SpellInfo const* spell, bool triggered);
-
- bool SpawnedEventConditionsCheck(CreatureEventAI_Event const& event);
-
- Unit* DoSelectLowestHpFriendly(float range, uint32 minHPDiff);
- void DoFindFriendlyMissingBuff(std::list<Creature*>& _list, float range, uint32 spellid);
- void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
-
- protected:
- uint32 m_EventUpdateTime; // Time between event updates
- uint32 m_EventDiff; // Time between the last event call
- bool m_bEmptyList;
-
- typedef std::vector<CreatureEventAIHolder> CreatureEventAIList;
- CreatureEventAIList m_CreatureEventAIList; // Holder for events (stores enabled, time, and eventid)
- // Variables used by Events themselves
- uint8 m_Phase; // Current phase, max 32 phases
- bool m_CombatMovementEnabled; // If we allow targeted movment gen (movement twoards top threat)
- bool m_MeleeEnabled; // If we allow melee auto attack
- float m_AttackDistance; // Distance to attack from
- float m_AttackAngle; // Angle of attack
- uint32 m_InvincibilityHpLevel; // Minimal health level allowed at damage apply
-};
-#endif
diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp b/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp
deleted file mode 100644
index daaf531dbda..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAIMgr.cpp
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "Common.h"
-#include "DatabaseEnv.h"
-#include "CreatureEventAI.h"
-#include "CreatureEventAIMgr.h"
-#include "ObjectMgr.h"
-#include "ObjectDefines.h"
-#include "GridDefines.h"
-#include "ConditionMgr.h"
-#include "SpellMgr.h"
-#include "SpellInfo.h"
-#include "Player.h"
-
-// -------------------
-void CreatureEventAIMgr::LoadCreatureEventAI_Texts()
-{
- uint32 oldMSTime = getMSTime();
-
- // Drop Existing Text Map, only done once and we are ready to add data from multiple sources.
- m_CreatureEventAI_TextMap.clear();
-
- // Load EventAI Text
- sObjectMgr->LoadTrinityStrings("creature_ai_texts", MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID);
-
- // Gather Additional data from EventAI Texts 0 1 2 3 4
- QueryResult result = WorldDatabase.Query("SELECT entry, sound, type, language, emote FROM creature_ai_texts");
-
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 additional CreatureEventAI Texts data. DB table `creature_ai_texts` is empty.");
- return;
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
- StringTextData temp;
-
- int32 i = fields[0].GetInt32();
- temp.SoundId = fields[1].GetUInt32();
- temp.Type = fields[2].GetUInt8();
- temp.Language = fields[3].GetUInt8();
- temp.Emote = fields[4].GetUInt16();
-
- // range negative
- if (i > MIN_CREATURE_AI_TEXT_STRING_ID || i <= MAX_CREATURE_AI_TEXT_STRING_ID)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Entry %i in table `creature_ai_texts` is not in valid range(%d-%d)", i, MIN_CREATURE_AI_TEXT_STRING_ID, MAX_CREATURE_AI_TEXT_STRING_ID);
- continue;
- }
-
- // range negative (must not happen, loaded from same table)
- if (!sObjectMgr->GetTrinityStringLocale(i))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Entry %i in table `creature_ai_texts` not found", i);
- continue;
- }
-
- if (temp.SoundId)
- {
- if (!sSoundEntriesStore.LookupEntry(temp.SoundId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Entry %i in table `creature_ai_texts` has Sound %u but sound does not exist.", i, temp.SoundId);
- }
-
- if (!GetLanguageDescByID(temp.Language))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Entry %i in table `creature_ai_texts` using Language %u but Language does not exist.", i, temp.Language);
-
- if (temp.Type > CHAT_TYPE_ZONE_YELL)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Entry %i in table `creature_ai_texts` has Type %u but this Chat Type does not exist.", i, temp.Type);
-
- if (temp.Emote)
- {
- if (!sEmotesStore.LookupEntry(temp.Emote))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Entry %i in table `creature_ai_texts` has Emote %u but emote does not exist.", i, temp.Emote);
- }
-
- m_CreatureEventAI_TextMap[i] = temp;
- ++count;
- }
- while (result->NextRow());
-
- TC_LOG_INFO("server.loading", ">> Loaded %u additional CreatureEventAI Texts data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
-
-void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
-{
- uint32 oldMSTime = getMSTime();
-
- //Drop Existing EventAI List
- m_CreatureEventAI_Event_Map.clear();
-
- // Gather event data
- QueryResult result = WorldDatabase.Query("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, "
- "event_param1, event_param2, event_param3, event_param4, "
- "action1_type, action1_param1, action1_param2, action1_param3, "
- "action2_type, action2_param1, action2_param2, action2_param3, "
- "action3_type, action3_param1, action3_param2, action3_param3 "
- "FROM creature_ai_scripts");
-
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 CreatureEventAI scripts. DB table `creature_ai_scripts` is empty.");
- return;
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
-
- CreatureEventAI_Event temp;
- temp.event_id = EventAI_Type(fields[0].GetUInt32());
- uint32 i = temp.event_id;
-
- temp.creature_id = fields[1].GetUInt32();
- uint32 creature_id = temp.creature_id;
-
- uint32 e_type = fields[2].GetUInt8();
- //Report any errors in event
- if (e_type >= EVENT_T_END)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u have wrong type (%u), skipping.", i, e_type);
- continue;
- }
- temp.event_type = EventAI_Type(e_type);
-
- temp.event_inverse_phase_mask = fields[3].GetInt32();
- temp.event_chance = fields[4].GetUInt32();
- temp.event_flags = fields[5].GetUInt32();
- temp.raw.param1 = fields[6].GetInt32();
- temp.raw.param2 = fields[7].GetInt32();
- temp.raw.param3 = fields[8].GetInt32();
- temp.raw.param4 = fields[9].GetInt32();
-
- CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature_id);
- //Creature does not exist in database
- if (!cInfo)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u has script for non-existing creature entry (%u), skipping.", i, creature_id);
- continue;
- }
-
- // Only on the first script
- if (cInfo->AIName != "EventAI" && m_CreatureEventAI_Event_Map[creature_id].empty())
- TC_LOG_ERROR("sql.sql", "Creature entry %u has EventAI scripts, but its AIName is not 'EventAI' - possible AI-mismatch?", temp.creature_id);
-
- //No chance of this event occuring
- if (temp.event_chance == 0)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u has 0 percent chance. Event will never trigger!", i);
- //Chance above 100, force it to be 100
- else if (temp.event_chance > 100)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i);
- temp.event_chance = 100;
- }
-
- //Individual event checks
- switch (temp.event_type)
- {
- case EVENT_T_TIMER:
- case EVENT_T_TIMER_OOC:
- if (temp.timer.initialMax < temp.timer.initialMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i);
- if (temp.timer.repeatMax < temp.timer.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_HP:
- case EVENT_T_MANA:
- case EVENT_T_TARGET_HP:
- case EVENT_T_TARGET_MANA:
- if (temp.percent_range.percentMax > 100)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i);
-
- if (temp.percent_range.percentMax <= temp.percent_range.percentMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i);
-
- if (temp.event_flags & EFLAG_REPEATABLE && !temp.percent_range.repeatMin && !temp.percent_range.repeatMax)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
- break;
- case EVENT_T_SPELLHIT:
- if (temp.spell_hit.spellId)
- {
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId);
- if (!spell)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i);
- continue;
- }
-
- if ((temp.spell_hit.schoolMask & spell->SchoolMask) != spell->SchoolMask)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.",
- temp.creature_id, temp.spell_hit.schoolMask, i);
- }
- }
-
- if (!temp.spell_hit.schoolMask)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.spell_hit.schoolMask, i);
-
- if (temp.spell_hit.repeatMax < temp.spell_hit.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_RANGE:
- if (temp.range.maxDist < temp.range.minDist)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (MaxDist < MinDist). Event will never repeat.", temp.creature_id, i);
- if (temp.range.repeatMax < temp.range.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_OOC_LOS:
- if (temp.ooc_los.repeatMax < temp.ooc_los.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_SPAWNED:
- switch (temp.spawned.condition)
- {
- case SPAWNED_EVENT_ALWAY:
- break;
- case SPAWNED_EVENT_MAP:
- if (!sMapStore.LookupEntry(temp.spawned.conditionValue1))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'map specific' but with not existed map (%u) in param2. Event will never repeat.",
- temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1);
- }
- break;
- case SPAWNED_EVENT_ZONE:
- if (!GetAreaEntryByAreaID(temp.spawned.conditionValue1))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using spawned event(%u) with param1 = %u 'area specific' but with not existed area (%u) in param2. Event will never repeat.",
- temp.creature_id, i, temp.spawned.condition, temp.spawned.conditionValue1);
- }
- break;
- default:
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using invalid spawned event %u mode (%u) in param1", temp.creature_id, i, temp.spawned.condition);
- break;
- }
- break;
- case EVENT_T_FRIENDLY_HP:
- if (temp.friendly_hp.repeatMax < temp.friendly_hp.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_FRIENDLY_IS_CC:
- if (temp.friendly_is_cc.repeatMax < temp.friendly_is_cc.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_FRIENDLY_MISSING_BUFF:
- {
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.spell_hit.spellId);
- if (!spell)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i);
- continue;
- }
- if (temp.friendly_buff.repeatMax < temp.friendly_buff.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- }
- case EVENT_T_KILL:
- if (temp.kill.repeatMax < temp.kill.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_TARGET_CASTING:
- if (temp.target_casting.repeatMax < temp.target_casting.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_SUMMONED_UNIT:
- if (!sObjectMgr->GetCreatureTemplate(temp.summon_unit.creatureId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event(%u) with not existed creature template id (%u) in param1, skipped.", temp.creature_id, i, temp.summon_unit.creatureId);
- if (temp.summon_unit.repeatMax < temp.summon_unit.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- case EVENT_T_QUEST_ACCEPT:
- case EVENT_T_QUEST_COMPLETE:
- if (!sObjectMgr->GetQuestTemplate(temp.quest.questId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using event(%u) with not existed qyest id (%u) in param1, skipped.", temp.creature_id, i, temp.quest.questId);
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using not implemented event (%u) in event %u.", temp.creature_id, temp.event_id, i);
- continue;
-
- case EVENT_T_AGGRO:
- case EVENT_T_DEATH:
- case EVENT_T_EVADE:
- case EVENT_T_REACHED_HOME:
- {
- if (temp.event_flags & EFLAG_REPEATABLE)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i);
- temp.event_flags &= ~EFLAG_REPEATABLE;
- }
-
- break;
- }
-
- case EVENT_T_RECEIVE_EMOTE:
- {
- if (!sEmotesTextStore.LookupEntry(temp.receive_emote.emoteId))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using event %u: param1 (EmoteTextId: %u) are not valid.", temp.creature_id, i, temp.receive_emote.emoteId);
- continue;
- }
- if (temp.receive_emote.condition)
- {
- Condition cond;
- cond.ConditionType = ConditionTypes(temp.receive_emote.condition);
- cond.ConditionValue1 = temp.receive_emote.conditionValue1;
- cond.ConditionValue2 = temp.receive_emote.conditionValue2;
- if (!sConditionMgr->isConditionTypeValid(&cond))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using event %u: param2 (Condition: %u) are not valid.", temp.creature_id, i, temp.receive_emote.condition);
- continue;
- }
- }
-
- if (!(temp.event_flags & EFLAG_REPEATABLE))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using event %u: EFLAG_REPEATABLE not set. Event must always be repeatable. Flag applied.", temp.creature_id, i);
- temp.event_flags |= EFLAG_REPEATABLE;
- }
-
- break;
- }
-
- case EVENT_T_BUFFED:
- case EVENT_T_TARGET_BUFFED:
- {
- SpellInfo const* spell = sSpellMgr->GetSpellInfo(temp.buffed.spellId);
- if (!spell)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.spell_hit.spellId, i);
- continue;
- }
- if (temp.buffed.repeatMax < temp.buffed.repeatMin)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i);
- break;
- }
-
- default:
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Creature %u using not checked at load event (%u) in event %u. Need check code update?", temp.creature_id, temp.event_id, i);
- break;
- }
-
- for (uint32 j = 0; j < MAX_ACTIONS; j++)
- {
- uint16 action_type = fields[10+(j*4)].GetUInt8();
- if (action_type >= ACTION_T_END)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u has incorrect action type (%u), replace by ACTION_T_NONE.", i, j+1, action_type);
- temp.action[j].type = ACTION_T_NONE;
- continue;
- }
-
- CreatureEventAI_Action& action = temp.action[j];
-
- action.type = EventAI_ActionType(action_type);
- action.raw.param1 = fields[11+(j*4)].GetInt32();
- action.raw.param2 = fields[12+(j*4)].GetInt32();
- action.raw.param3 = fields[13+(j*4)].GetInt32();
-
- //Report any errors in actions
- switch (action.type)
- {
- case ACTION_T_NONE:
- break;
- case ACTION_T_TEXT:
- {
- if (action.text.TextId1 < 0)
- {
- if (m_CreatureEventAI_TextMap.find(action.text.TextId1) == m_CreatureEventAI_TextMap.end())
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param1 refrences non-existing entry in texts table.", i, j+1);
- }
- if (action.text.TextId2 < 0)
- {
- if (m_CreatureEventAI_TextMap.find(action.text.TextId2) == m_CreatureEventAI_TextMap.end())
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param2 refrences non-existing entry in texts table.", i, j+1);
-
- if (!action.text.TextId1)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u has param2, but param1 is not set. Required for randomized text.", i, j+1);
- }
- if (action.text.TextId3 < 0)
- {
- if (m_CreatureEventAI_TextMap.find(action.text.TextId3) == m_CreatureEventAI_TextMap.end())
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param3 refrences non-existing entry in texts table.", i, j+1);
-
- if (!action.text.TextId1 || !action.text.TextId2)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u has param3, but param1 and/or param2 is not set. Required for randomized text.", i, j+1);
- }
- break;
- }
- case ACTION_T_SET_FACTION:
- if (action.set_faction.factionId !=0 && !sFactionStore.LookupEntry(action.set_faction.factionId))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existent FactionId %u.", i, j+1, action.set_faction.factionId);
- action.set_faction.factionId = 0;
- }
- break;
- case ACTION_T_MORPH_TO_ENTRY_OR_MODEL:
- if (action.morph.creatureId !=0 || action.morph.modelId !=0)
- {
- if (action.morph.creatureId && !sObjectMgr->GetCreatureTemplate(action.morph.creatureId))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existant Creature entry %u.", i, j+1, action.morph.creatureId);
- action.morph.creatureId = 0;
- }
-
- if (action.morph.modelId)
- {
- if (action.morph.creatureId)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.morph.modelId, action.morph.creatureId);
- action.morph.modelId = 0;
- }
- else if (!sCreatureDisplayInfoStore.LookupEntry(action.morph.modelId))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existant ModelId %u.", i, j+1, action.morph.modelId);
- action.morph.modelId = 0;
- }
- }
- }
- break;
- case ACTION_T_SOUND:
- if (!sSoundEntriesStore.LookupEntry(action.sound.soundId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existant SoundID %u.", i, j+1, action.sound.soundId);
- break;
- case ACTION_T_EMOTE:
- if (!sEmotesStore.LookupEntry(action.emote.emoteId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.emote.emoteId);
- break;
- case ACTION_T_RANDOM_SOUND:
- if (!sSoundEntriesStore.LookupEntry(action.random_sound.soundId1))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param1 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId1);
- if (action.random_sound.soundId2 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId2))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param2 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId2);
- if (action.random_sound.soundId3 >= 0 && !sSoundEntriesStore.LookupEntry(action.random_sound.soundId3))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param3 uses non-existant SoundID %u.", i, j+1, action.random_sound.soundId3);
- break;
- case ACTION_T_RANDOM_EMOTE:
- if (!sEmotesStore.LookupEntry(action.random_emote.emoteId1))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param1 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId1);
- if (action.random_emote.emoteId2 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId2))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param2 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId2);
- if (action.random_emote.emoteId3 >= 0 && !sEmotesStore.LookupEntry(action.random_emote.emoteId3))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param3 (EmoteId: %u) are not valid.", i, j+1, action.random_emote.emoteId3);
- break;
- case ACTION_T_CAST:
- {
- const SpellInfo* spell = sSpellMgr->GetSpellInfo(action.cast.spellId);
- if (!spell)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.cast.spellId);
- /* FIXME: temp.raw.param3 not have event tipes with recovery time in it....
- else
- {
- if (spell->RecoveryTime > 0 && temp.event_flags & EFLAG_REPEATABLE)
- {
- //output as debug for now, also because there's no general rule all spells have RecoveryTime
- if (temp.event_param3 < spell->RecoveryTime)
- TC_LOG_DEBUG("CreatureEventAI: Event %u Action %u uses SpellID %u but cooldown is longer(%u) than minumum defined in event param3(%u).", i, j+1, action.cast.spellId, spell->RecoveryTime, temp.event_param3);
- }
- }
- */
-
- //Cast is always triggered if target is forced to cast on self
- if (action.cast.castFlags & CAST_FORCE_TARGET_SELF)
- action.cast.castFlags |= CAST_TRIGGERED;
-
- if (action.cast.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- }
- case ACTION_T_SUMMON:
- if (!sObjectMgr->GetCreatureTemplate(action.summon.creatureId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existent creature entry %u.", i, j+1, action.summon.creatureId);
-
- if (action.summon.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_THREAT_SINGLE_PCT:
- if (std::abs(action.threat_single_pct.percent) > 100)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_single_pct.percent);
- if (action.threat_single_pct.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_THREAT_ALL_PCT:
- if (std::abs(action.threat_all_pct.percent) > 100)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses invalid percent value %u.", i, j+1, action.threat_all_pct.percent);
- break;
- case ACTION_T_QUEST_EVENT:
- if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event.questId))
- {
- if (!qid->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event.questId);
- }
- else
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event.questId);
-
- if (action.quest_event.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
-
- break;
- case ACTION_T_SET_UNIT_FIELD:
- if (action.set_unit_field.field < OBJECT_END || action.set_unit_field.field >= UNIT_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u param1 (UNIT_FIELD*). Index out of range for intended use.", i, j+1);
- if (action.set_unit_field.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_UNIT_FLAG:
- case ACTION_T_REMOVE_UNIT_FLAG:
- if (action.unit_flag.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_PHASE:
- if (action.set_phase.phase >= MAX_PHASE)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phase >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- break;
- case ACTION_T_INC_PHASE:
- if (action.set_inc_phase.step == 0)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1);
- else if (std::abs(action.set_inc_phase.step) > MAX_PHASE-1)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u is change phase by too large for any use %i.", i, j+1, action.set_inc_phase.step);
- break;
- case ACTION_T_QUEST_EVENT_ALL:
- if (Quest const* qid = sObjectMgr->GetQuestTemplate(action.quest_event_all.questId))
- {
- if (!qid->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u. SpecialFlags for quest entry %u does not include |2, Action will not have any effect.", i, j+1, action.quest_event_all.questId);
- }
- else
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existent Quest entry %u.", i, j+1, action.quest_event_all.questId);
- break;
- case ACTION_T_REMOVEAURASFROMSPELL:
- if (!sSpellMgr->GetSpellInfo(action.remove_aura.spellId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existent SpellID %u.", i, j+1, action.remove_aura.spellId);
- if (action.remove_aura.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_RANDOM_PHASE: //PhaseId1, PhaseId2, PhaseId3
- if (action.random_phase.phase1 >= MAX_PHASE)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phase1 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase.phase2 >= MAX_PHASE)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phase2 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase.phase3 >= MAX_PHASE)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phase3 >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- break;
- case ACTION_T_RANDOM_PHASE_RANGE: //PhaseMin, PhaseMax
- if (action.random_phase_range.phaseMin >= MAX_PHASE)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phaseMin >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase_range.phaseMin >= MAX_PHASE)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phaseMax >= %u. Phase mask cannot be used past phase %u.", i, j+1, MAX_PHASE, MAX_PHASE-1);
- if (action.random_phase_range.phaseMin >= action.random_phase_range.phaseMax)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set phaseMax <= phaseMin.", i, j+1);
- std::swap(action.random_phase_range.phaseMin, action.random_phase_range.phaseMax);
- // equal case processed at call
- }
- break;
- case ACTION_T_KILLED_MONSTER:
- if (!sObjectMgr->GetCreatureTemplate(action.killed_monster.creatureId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.killed_monster.creatureId);
- if (action.killed_monster.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_SET_INST_DATA:
- if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1);
- if (action.set_inst_data.value > 4/*SPECIAL*/)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u attempts to set instance data above encounter state 4. Custom case?", i, j+1);
- break;
- case ACTION_T_SET_INST_DATA64:
- if (!(temp.event_flags & EFLAG_DIFFICULTY_ALL))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u. Cannot set instance data without difficulty event flags.", i, j+1);
- if (action.set_inst_data64.target >= TARGET_T_END)
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses incorrect Target type", i, j+1);
- break;
- case ACTION_T_UPDATE_TEMPLATE:
- if (!sObjectMgr->GetCreatureTemplate(action.update_template.creatureId))
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses non-existant creature entry %u.", i, j+1, action.update_template.creatureId);
- break;
- case ACTION_T_SET_SHEATH:
- if (action.set_sheath.sheath >= MAX_SHEATH_STATE)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses wrong sheath state %u.", i, j+1, action.set_sheath.sheath);
- action.set_sheath.sheath = SHEATH_STATE_UNARMED;
- }
- break;
- case ACTION_T_SET_INVINCIBILITY_HP_LEVEL:
- if (action.invincibility_hp_level.is_percent)
- {
- if (action.invincibility_hp_level.hp_level > 100)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses wrong percent value %u.", i, j+1, action.invincibility_hp_level.hp_level);
- action.invincibility_hp_level.hp_level = 100;
- }
- }
- break;
- case ACTION_T_MOUNT_TO_ENTRY_OR_MODEL:
- if (action.mount.creatureId != 0 || action.mount.modelId != 0)
- {
- if (action.mount.creatureId && !sObjectMgr->GetCreatureTemplate(action.mount.creatureId))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses nonexistent Creature entry %u.", i, j+1, action.mount.creatureId);
- action.morph.creatureId = 0;
- }
-
- if (action.mount.modelId)
- {
- if (action.mount.creatureId)
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u have unused ModelId %u with also set creature id %u.", i, j+1, action.mount.modelId, action.mount.creatureId);
- action.mount.modelId = 0;
- }
- else if (!sCreatureDisplayInfoStore.LookupEntry(action.mount.modelId))
- {
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u uses nonexistent ModelId %u.", i, j+1, action.mount.modelId);
- action.mount.modelId = 0;
- }
- }
- }
- break;
- case ACTION_T_EVADE: //No Params
- case ACTION_T_FLEE_FOR_ASSIST: //No Params
- case ACTION_T_DIE: //No Params
- case ACTION_T_ZONE_COMBAT_PULSE: //No Params
- case ACTION_T_FORCE_DESPAWN: //No Params
- case ACTION_T_AUTO_ATTACK: //AllowAttackState (0 = stop attack, anything else means continue attacking)
- case ACTION_T_COMBAT_MOVEMENT: //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
- case ACTION_T_RANGED_MOVEMENT: //Distance, Angle
- case ACTION_T_CALL_FOR_HELP: //Distance
- break;
-
- case ACTION_T_RANDOM_SAY:
- case ACTION_T_RANDOM_YELL:
- case ACTION_T_RANDOM_TEXTEMOTE:
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u currently unused ACTION type. Did you forget to update database?", i, j+1);
- break;
-
- case ACTION_T_MOVE_RANDOM_POINT:
- case ACTION_T_SET_STAND_STATE:
- case ACTION_T_SET_PHASE_MASK:
- case ACTION_T_SET_VISIBILITY:
- case ACTION_T_SET_ACTIVE:
- case ACTION_T_SET_AGGRESSIVE:
- case ACTION_T_ATTACK_START_PULSE:
- case ACTION_T_SUMMON_GO:
- break;
-
- default:
- TC_LOG_ERROR("sql.sql", "CreatureEventAI: Event %u Action %u have currently not checked at load action type (%u). Need check code update?", i, j+1, action.type);
- break;
- }
- }
-
- //Add to list
- m_CreatureEventAI_Event_Map[creature_id].push_back(temp);
- ++count;
-
- }
- while (result->NextRow());
-
- TC_LOG_INFO("server.loading", ">> Loaded %u CreatureEventAI scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
diff --git a/src/server/game/AI/EventAI/CreatureEventAIMgr.h b/src/server/game/AI/EventAI/CreatureEventAIMgr.h
deleted file mode 100644
index 577958b6f5b..00000000000
--- a/src/server/game/AI/EventAI/CreatureEventAIMgr.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TRINITY_CREATURE_EAI_MGR_H
-#define TRINITY_CREATURE_EAI_MGR_H
-
-#include "Common.h"
-#include "CreatureEventAI.h"
-
-class CreatureEventAIMgr
-{
- friend class ACE_Singleton<CreatureEventAIMgr, ACE_Null_Mutex>;
-
- private:
- CreatureEventAIMgr(){ }
- ~CreatureEventAIMgr(){ }
-
- public:
- void LoadCreatureEventAI_Texts();
- void LoadCreatureEventAI_Scripts();
-
- CreatureEventAI_Event_Map const& GetCreatureEventAIMap() const { return m_CreatureEventAI_Event_Map; }
- CreatureEventAI_TextMap const& GetCreatureEventAITextMap() const { return m_CreatureEventAI_TextMap; }
-
- private:
- CreatureEventAI_Event_Map m_CreatureEventAI_Event_Map;
- CreatureEventAI_TextMap m_CreatureEventAI_TextMap;
-};
-
-#define sEventAIMgr ACE_Singleton<CreatureEventAIMgr, ACE_Null_Mutex>::instance()
-#endif
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index ae3f7078f5c..c367ba0a5ed 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -460,7 +460,6 @@ void SmartAI::EnterEvadeMode()
me->LoadCreaturesAddon();
me->SetLootRecipient(NULL);
me->ResetPlayerDamageReq();
-
GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);//must be after aura clear so we can cast spells from db
SetRun(mRun);
@@ -588,6 +587,9 @@ int SmartAI::Permissible(const Creature* creature)
void SmartAI::JustReachedHome()
{
GetScript()->ProcessEventsFor(SMART_EVENT_REACHED_HOME);
+
+ if (!UpdateVictim() && me->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE && me->GetWaypointPath())
+ me->ToCreature()->GetMotionMaster()->MovePath(me->GetWaypointPath(), true);
}
void SmartAI::EnterCombat(Unit* enemy)
@@ -787,6 +789,8 @@ void SmartAI::SetCombatMove(bool on)
}
else
{
+ me->GetMotionMaster()->MovementExpired();
+ me->GetMotionMaster()->Clear(true);
me->StopMoving();
me->GetMotionMaster()->MoveIdle();
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index d2d5027ce7d..7555471e091 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -516,7 +516,26 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)
me->InterruptNonMeleeSpells(false);
+ if (e.action.cast.flags & SMARTCAST_COMBAT_MOVE)
+ {
+ // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed
+ // unless target is outside spell range, out of mana, or LOS.
+
+ bool _allowMove = false;
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell);
+ int32 mana = me->GetPower(POWER_MANA);
+
+ if (me->GetDistance((*itr)->ToUnit()) > spellInfo->GetMaxRange(true) ||
+ me->GetDistance((*itr)->ToUnit()) < spellInfo->GetMinRange(true) ||
+ !me->ToUnit()->IsWithinLOSInMap((*itr)->ToUnit()) ||
+ mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask()))
+ _allowMove = true;
+
+ CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove);
+ }
+
me->CastSpell((*itr)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED));
+
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_CAST:: Creature %u casts spell %u on target %u with castflags %u",
me->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 35abdcc47f0..d6bf318b8ac 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1283,7 +1283,8 @@ enum SmartCastFlags
//SMARTCAST_FORCE_CAST = 0x04, //Forces cast even if creature is out of mana or out of range
//SMARTCAST_NO_MELEE_IF_OOM = 0x08, //Prevents creature from entering melee if out of mana or out of range
//SMARTCAST_FORCE_TARGET_SELF = 0x10, //Forces the target to cast this spell on itself
- SMARTCAST_AURA_NOT_PRESENT = 0x20 //Only casts the spell if the target does not have an aura from the spell
+ SMARTCAST_AURA_NOT_PRESENT = 0x20, //Only casts the spell if the target does not have an aura from the spell
+ SMARTCAST_COMBAT_MOVE = 0x40 //Prevents combat movement if cast successful. Allows movement on range, OOM, LOS
};
// one line in DB is one event
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index b80df5018e4..4c71a044488 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -459,7 +459,7 @@ void AccountMgr::LoadRBAC()
{
Field* field = result->Fetch();
uint32 newId = field[0].GetUInt32();
- if (secId != newId)
+ if (secId != newId || permissions == NULL)
{
secId = newId;
permissions = &_defaultPermissions[secId];
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 1bc135bc8e0..b18996f2af0 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -517,7 +517,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_RELOAD_ALL = 611,
RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT = 612,
RBAC_PERM_COMMAND_RELOAD_ALL_AREA = 613,
- RBAC_PERM_COMMAND_RELOAD_ALL_EVENTAI = 614,
+ RBAC_PERM_UNUSED_614 = 614, // unused
RBAC_PERM_COMMAND_RELOAD_ALL_GOSSIP = 615,
RBAC_PERM_COMMAND_RELOAD_ALL_ITEM = 616,
RBAC_PERM_COMMAND_RELOAD_ALL_LOCALES = 617,
@@ -534,8 +534,8 @@ enum RBACPermissions
RBAC_PERM_COMMAND_RELOAD_COMMAND = 628,
RBAC_PERM_COMMAND_RELOAD_CONDITIONS = 629,
RBAC_PERM_COMMAND_RELOAD_CONFIG = 630,
- RBAC_PERM_COMMAND_RELOAD_CREATURE_AI_SCRIPTS = 631,
- RBAC_PERM_COMMAND_RELOAD_CREATURE_AI_TEXTS = 632,
+ RBAC_PERM_UNUSED_631 = 631, // unused
+ RBAC_PERM_UNUSED_632 = 632, // unused
RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN = 633,
RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE = 634,
RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION = 635,
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index c4e8ba49ba9..aa3568a62d5 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -558,8 +558,12 @@ void BattlegroundIC::UpdateNodeWorldState(ICNodePoint* nodePoint)
uint32 worldstate = nodePoint->worldStates[nodePoint->nodeState];
// with this we are sure we dont bug the client
- for (uint8 i = 0; i < 4; ++i)
+ for (uint8 i = 0; i < 5; ++i)
+ {
+ if (nodePoint->worldStates[i] == worldstate)
+ continue;
UpdateWorldState(nodePoint->worldStates[i], 0);
+ }
UpdateWorldState(worldstate, 1);
}
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index f455610666e..be3997243e4 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -130,7 +130,6 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Addons
${CMAKE_CURRENT_SOURCE_DIR}/AI
${CMAKE_CURRENT_SOURCE_DIR}/AI/CoreAI
- ${CMAKE_CURRENT_SOURCE_DIR}/AI/EventAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/ScriptedAI
${CMAKE_CURRENT_SOURCE_DIR}/AI/SmartScripts
${CMAKE_CURRENT_SOURCE_DIR}/AuctionHouse
diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h
index 57785fbe1a0..c77fcf7ad76 100644
--- a/src/server/game/Chat/ChatLink.h
+++ b/src/server/game/Chat/ChatLink.h
@@ -56,7 +56,10 @@ protected:
class ItemChatLink : public ChatLink
{
public:
- ItemChatLink() : ChatLink(), _item(NULL), _suffix(NULL), _property(NULL) { }
+ ItemChatLink() : ChatLink(), _item(NULL), _suffix(NULL), _property(NULL)
+ {
+ memset(_data, 0, sizeof(_data));
+ }
virtual bool Initialize(std::istringstream& iss);
virtual bool ValidateName(char* buffer, const char* context);
@@ -98,7 +101,10 @@ protected:
class AchievementChatLink : public ChatLink
{
public:
- AchievementChatLink() : ChatLink(), _guid(0), _achievement(NULL) { }
+ AchievementChatLink() : ChatLink(), _guid(0), _achievement(NULL)
+ {
+ memset(_data, 0, sizeof(_data));
+ }
virtual bool Initialize(std::istringstream& iss);
virtual bool ValidateName(char* buffer, const char* context);
diff --git a/src/server/game/Combat/UnitEvents.h b/src/server/game/Combat/UnitEvents.h
index 0e568d139a8..8bb7d95a384 100644
--- a/src/server/game/Combat/UnitEvents.h
+++ b/src/server/game/Combat/UnitEvents.h
@@ -93,13 +93,13 @@ class ThreatRefStatusChangeEvent : public UnitBaseEvent
};
ThreatManager* iThreatManager;
public:
- ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType) { iHostileReference = NULL; }
+ ThreatRefStatusChangeEvent(uint32 pType) : UnitBaseEvent(pType), iThreatManager(NULL) { iHostileReference = NULL; }
- ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; }
+ ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference) : UnitBaseEvent(pType), iThreatManager(NULL) { iHostileReference = pHostileReference; }
- ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, float pValue) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; iFValue = pValue; }
+ ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, float pValue) : UnitBaseEvent(pType), iThreatManager(NULL) { iHostileReference = pHostileReference; iFValue = pValue; }
- ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, bool pValue) : UnitBaseEvent(pType) { iHostileReference = pHostileReference; iBValue = pValue; }
+ ThreatRefStatusChangeEvent(uint32 pType, HostileReference* pHostileReference, bool pValue) : UnitBaseEvent(pType), iThreatManager(NULL) { iHostileReference = pHostileReference; iBValue = pValue; }
int32 getIValue() const { return iIValue; }
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 171d0fe8cc2..e976704c215 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -224,35 +224,35 @@ enum AchievementCategory
enum AreaFlags
{
- AREA_FLAG_UNK0 = 0x00000001, // Unknown
- AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
- AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
- AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
- AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
- AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
- AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
- AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
- AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
- AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
- AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
- AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
- AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
- AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
- AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
- AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
- AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
- AREA_FLAG_UNUSED2 = 0x00020000, // Unused in 3.3.5a
- AREA_FLAG_CONTESTED_AREA = 0x00040000, // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
- AREA_FLAG_UNK6 = 0x00080000, // Valgarde and Acherus: The Ebon Hold
- AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <= 15
- AREA_FLAG_TOWN = 0x00200000, // small towns with Inn
- AREA_FLAG_UNK7 = 0x00400000, // Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion (Something to do with team?)
- AREA_FLAG_UNK8 = 0x00800000, // Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion (Something to do with team?)
- AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
- AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
- AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
- AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
- AREA_FLAG_NO_FLY_ZONE = 0x20000000 // Marks zones where you cannot fly
+ AREA_FLAG_UNK0 = 0x00000001, // Unknown
+ AREA_FLAG_UNK1 = 0x00000002, // Razorfen Downs, Naxxramas and Acherus: The Ebon Hold (3.3.5a)
+ AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before)
+ AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones
+ AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning
+ AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
+ AREA_FLAG_ALLOW_DUELS = 0x00000040, // allow to duel here
+ AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
+ AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
+ AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
+ AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
+ AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
+ AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
+ AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
+ AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
+ AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
+ AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
+ AREA_FLAG_UNUSED2 = 0x00020000, // Unused in 3.3.5a
+ AREA_FLAG_CONTESTED_AREA = 0x00040000, // On PvP servers these areas are considered contested, even though the zone it is contained in is a Horde/Alliance territory.
+ AREA_FLAG_UNK4 = 0x00080000, // Valgarde and Acherus: The Ebon Hold
+ AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <= 15
+ AREA_FLAG_TOWN = 0x00200000, // small towns with Inn
+ AREA_FLAG_REST_ZONE_HORDE = 0x00400000, // Instead of using areatriggers, the zone will act as one for Horde players (Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn, Sunreaver Pavilion, etc)
+ AREA_FLAG_REST_ZONE_ALLIANCE = 0x00800000, // Instead of using areatriggers, the zone will act as one for Alliance players (Valgarde, Acherus: The Ebon Hold, Westguard Inn, Silver Covenant Pavilion, etc)
+ AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
+ AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
+ AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
+ AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
+ AREA_FLAG_NO_FLY_ZONE = 0x20000000 // Marks zones where you cannot fly
};
enum Difficulty
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 64e9d4a1c26..3c44c8e6035 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -64,6 +64,7 @@ GameObject::GameObject() : WorldObject(false), MapObject(),
lootingGroupLowGUID = 0;
ResetLootMode(); // restore default loot mode
+ m_stationaryPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
}
GameObject::~GameObject()
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index f03b95d0cc7..aeeb1d691f0 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -536,7 +536,10 @@ class MapObject
friend class ObjectGridLoader; //grid loader for loading creatures
protected:
- MapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE) { }
+ MapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE)
+ {
+ _newPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
+ }
private:
Cell _currentCell;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index c61621f3a91..91e2e9f1834 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -15312,7 +15312,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
// cast spells after mark quest complete (some spells have quest completed state requirements in spell_area data)
if (quest->GetRewSpellCast() > 0)
{
- if (questGiver->isType(TYPEMASK_UNIT))
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpellCast());
+ if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL))
{
if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID()))
creature->CastSpell(this, quest->GetRewSpellCast(), true);
@@ -15322,7 +15323,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
}
else if (quest->GetRewSpell() > 0)
{
- if (questGiver->isType(TYPEMASK_UNIT))
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(quest->GetRewSpell());
+ if (questGiver->isType(TYPEMASK_UNIT) && !spellInfo->HasEffect(SPELL_EFFECT_LEARN_SPELL))
{
if (Creature* creature = GetMap()->GetCreature(questGiver->GetGUID()))
creature->CastSpell(this, quest->GetRewSpell(), true);
@@ -19890,7 +19892,7 @@ void Player::UpdateSpeakTime()
}
}
else
- m_speakCount = 0;
+ m_speakCount = 1;
m_speakTime = current + sWorld->getIntConfig(CONFIG_CHATFLOOD_MESSAGE_DELAY);
}
@@ -20707,13 +20709,15 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
if (!spell || spell->m_appliedMods.empty())
return;
+ std::list<Aura*> aurasQueue;
+
for (uint8 i=0; i<MAX_SPELLMOD; ++i)
{
for (SpellModList::iterator itr = m_spellMods[i].begin(); itr != m_spellMods[i].end(); ++itr)
{
SpellModifier* mod = *itr;
- // spellmods without aura set cannot be charged
+ // Spellmods without aura set cannot be charged
if (!mod->ownerAura || !mod->ownerAura->IsUsingCharges())
continue;
@@ -20724,17 +20728,20 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
if (aura && mod->ownerAura != aura)
continue;
- // check if mod affected this spell
- // first, check if the mod aura applied at least one spellmod to this spell
+ // Check if mod affected this spell
+ // First, check if the mod aura applied at least one spellmod to this spell
Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(mod->ownerAura);
if (iterMod == spell->m_appliedMods.end())
continue;
- // secondly, check if the current mod is one of the spellmods applied by the mod aura
+ // Second, check if the current mod is one of those applied by the mod aura
if (!(mod->mask & spell->m_spellInfo->SpellFamilyFlags))
continue;
- // remove from list
- spell->m_appliedMods.erase(iterMod);
+ // remove from list - This will be done after all mods have been gone through
+ // to ensure we iterate over all mods of an aura before removing said aura
+ // from applied mods (Else, an aura with two mods on the current spell would
+ // only see the first of its modifier restored)
+ aurasQueue.push_back(mod->ownerAura);
// add mod charges back to mod
if (mod->charges == -1)
@@ -20742,15 +20749,22 @@ void Player::RestoreSpellMods(Spell* spell, uint32 ownerAuraId, Aura* aura)
else
mod->charges++;
- // Do not set more spellmods than avalible
+ // Do not set more spellmods than available
if (mod->ownerAura->GetCharges() < mod->charges)
mod->charges = mod->ownerAura->GetCharges();
// Skip this check for now - aura charges may change due to various reason
- /// @todo trac these changes correctly
+ /// @todo track these changes correctly
//ASSERT (mod->ownerAura->GetCharges() <= mod->charges);
}
}
+
+ for (std::list<Aura*>::iterator itr = aurasQueue.begin(); itr != aurasQueue.end(); ++itr)
+ {
+ Spell::UsedSpellMods::iterator iterMod = spell->m_appliedMods.find(*itr);
+ if (iterMod != spell->m_appliedMods.end())
+ spell->m_appliedMods.erase(iterMod);
+ }
}
void Player::RestoreAllSpellMods(uint32 ownerAuraId, Aura* aura)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 35a3f5f10d4..6aa19b5395a 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -251,7 +251,7 @@ typedef std::list<PlayerCreateInfoAction> PlayerCreateInfoActions;
struct PlayerInfo
{
// existence checked by displayId != 0
- PlayerInfo() : displayId_m(0), displayId_f(0), levelInfo(NULL) { }
+ PlayerInfo() : mapId(0), areaId(0), positionX(0.0f), positionY(0.0f), positionZ(0.0f), orientation(0.0f), displayId_m(0), displayId_f(0), levelInfo(NULL) { }
uint32 mapId;
uint32 areaId;
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index ddb0775dc01..386a36ae1f0 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -33,7 +33,8 @@
#include "CellImpl.h"
Transport::Transport() : GameObject(),
- _transportInfo(NULL), _isMoving(true), _pendingStop(false)
+ _transportInfo(NULL), _isMoving(true), _pendingStop(false),
+ _triggeredArrivalEvent(false), _triggeredDepartureEvent(false)
{
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
}
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index 0145ec608ae..e290a5d5e00 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -90,7 +90,6 @@ class Transport : public GameObject, public TransportBase
KeyFrameVec::const_iterator _currentFrame;
KeyFrameVec::const_iterator _nextFrame;
- uint32 _moveTimer;
TimeTrackerSmall _positionChangeTimer;
bool _isMoving;
bool _pendingStop;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 54db2da73df..38785018768 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -957,6 +957,8 @@ void Unit::CastSpell(GameObject* go, uint32 spellId, bool triggered, Item* castI
uint32 Unit::SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
+ if (!spellInfo)
+ return 0;
SpellNonMeleeDamage damageInfo(this, victim, spellInfo->Id, spellInfo->SchoolMask);
damage = SpellDamageBonusDone(victim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
damage = victim->SpellDamageBonusTaken(this, spellInfo, damage, SPELL_DIRECT_DAMAGE);
@@ -13607,9 +13609,19 @@ void CharmInfo::InitEmptyActionBar(bool withAttack)
void CharmInfo::InitPossessCreateSpells()
{
- InitEmptyActionBar();
if (_unit->GetTypeId() == TYPEID_UNIT)
{
+ // Adding switch until better way is found. Malcrom
+ // Adding entrys to this switch will prevent COMMAND_ATTACK being added to pet bar.
+ switch (_unit->GetEntry())
+ {
+ case 23575: // Mindless Abomination
+ break;
+ default:
+ InitEmptyActionBar();
+ break;
+ }
+
for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
{
uint32 spellId = _unit->ToCreature()->m_spells[i];
@@ -13623,6 +13635,8 @@ void CharmInfo::InitPossessCreateSpells()
}
}
}
+ else
+ InitEmptyActionBar();
}
void CharmInfo::InitCharmCreateSpells()
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index e1d6a2f3d9e..d5ab2057d81 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -102,7 +102,7 @@ void Vehicle::Install()
if (!spellInfo)
continue;
- if (spellInfo->PowerType == POWER_ENERGY)
+ if (spellInfo->PowerType == POWER_ENERGY && spellInfo->CalcPowerCost(_me, spellInfo->GetSchoolMask()) > 0)
{
_me->setPowerType(POWER_ENERGY);
_me->SetMaxPower(POWER_ENERGY, 100);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 8ebcc17df16..3d56225bc00 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -234,7 +234,8 @@ ObjectMgr::ObjectMgr():
_hiGoGuid(1),
_hiDoGuid(1),
_hiCorpseGuid(1),
- _hiMoTransGuid(1)
+ _hiMoTransGuid(1),
+ DBCLocaleIndex(LOCALE_enUS)
{
for (uint8 i = 0; i < MAX_CLASSES; ++i)
{
@@ -1411,6 +1412,11 @@ bool ObjectMgr::SetCreatureLinkedRespawn(uint32 guidLow, uint32 linkedGuidLow)
}
const CreatureData* slave = GetCreatureData(linkedGuidLow);
+ if (!slave)
+ {
+ TC_LOG_ERROR("sql.sql", "Creature '%u' linking to non-existent creature '%u'.", guidLow, linkedGuidLow);
+ return false;
+ }
const MapEntry* const map = sMapStore.LookupEntry(master->mapid);
if (!map || !map->Instanceable() || (master->mapid != slave->mapid))
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index fa0f0e76e46..bf835ed6c4e 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -457,7 +457,7 @@ typedef std::pair<QuestRelations::const_iterator, QuestRelations::const_iterator
struct PetLevelInfo
{
- PetLevelInfo() : health(0), mana(0) { for (uint8 i=0; i < MAX_STATS; ++i) stats[i] = 0; }
+ PetLevelInfo() : health(0), mana(0), armor(0) { for (uint8 i=0; i < MAX_STATS; ++i) stats[i] = 0; }
uint16 stats[MAX_STATS];
uint16 health;
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index ad8cacbd3c0..d57308d359a 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -718,6 +718,12 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket)
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
+ if (!spellInfo)
+ {
+ TC_LOG_ERROR("network", "WORLD: unknown PET spell id %u", spellid);
+ return;
+ }
+
// do not add not learned spells/ passive spells
if (!pet->HasSpell(spellid) || !spellInfo->IsAutocastable())
return;
diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp
index b84a8ddb217..11798201397 100644
--- a/src/server/game/Maps/TransportMgr.cpp
+++ b/src/server/game/Maps/TransportMgr.cpp
@@ -60,6 +60,12 @@ void TransportMgr::LoadTransportTemplates()
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
GameObjectTemplate const* goInfo = sObjectMgr->GetGameObjectTemplate(entry);
+ if (goInfo == NULL)
+ {
+ TC_LOG_ERROR("sql.sql", "Transport %u has no associated GameObjectTemplate from `gameobject_template` , skipped.", entry);
+ continue;
+ }
+
if (goInfo->moTransport.taxiPathId >= sTaxiPathNodesByPath.size())
{
TC_LOG_ERROR("sql.sql", "Transport %u (name: %s) has an invalid path specified in `gameobject_template`.`data0` (%u) field, skipped.", entry, goInfo->name.c_str(), goInfo->moTransport.taxiPathId);
diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h
index 250a2c50bb1..205a614eabb 100644
--- a/src/server/game/Maps/TransportMgr.h
+++ b/src/server/game/Maps/TransportMgr.h
@@ -38,7 +38,7 @@ typedef UNORDERED_MAP<uint32, std::set<uint32> > TransportInstanceMap;
struct KeyFrame
{
- explicit KeyFrame(TaxiPathNodeEntry const& _node) : Node(&_node),
+ explicit KeyFrame(TaxiPathNodeEntry const& _node) : Index(0), Node(&_node),
DistSinceStop(-1.0f), DistUntilStop(-1.0f), DistFromPrev(-1.0f), TimeFrom(0.0f), TimeTo(0.0f),
Teleport(false), ArriveTime(0), DepartureTime(0), Spline(NULL), NextDistFromPrev(0.0f), NextArriveTime(0)
{
@@ -66,7 +66,7 @@ struct KeyFrame
struct TransportTemplate
{
- TransportTemplate() : pathTime(0), accelTime(0.0f), accelDist(0.0f) { }
+ TransportTemplate() : inInstance(false), pathTime(0), accelTime(0.0f), accelDist(0.0f), entry(0) { }
~TransportTemplate();
std::set<uint32> mapsUsed;
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index 85a08e49fd3..91ad6d2b676 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -33,6 +33,8 @@ PathGenerator::PathGenerator(const Unit* owner) :
_endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(NULL),
_navMeshQuery(NULL)
{
+ memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs));
+
TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow());
uint32 mapId = _sourceUnit->GetMapId();
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index e70c88d2181..41c18b850a1 100644
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -499,7 +499,7 @@ void Map::ScriptsProcess()
if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount())
TC_LOG_ERROR("scripts", "%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID,
- source->GetValuesCount(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
+ cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUIDLow());
else
cSource->SetFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue);
}
@@ -513,7 +513,7 @@ void Map::ScriptsProcess()
if (step.script->FlagToggle.FieldID <= OBJECT_FIELD_ENTRY || step.script->FlagToggle.FieldID >= cSource->GetValuesCount())
TC_LOG_ERROR("scripts", "%s wrong field %u (max count: %u) in object (TypeId: %u, Entry: %u, GUID: %u) specified, skipping.",
step.script->GetDebugInfo().c_str(), step.script->FlagToggle.FieldID,
- source->GetValuesCount(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow());
+ cSource->GetValuesCount(), cSource->GetTypeId(), cSource->GetEntry(), cSource->GetGUIDLow());
else
cSource->RemoveFlag(step.script->FlagToggle.FieldID, step.script->FlagToggle.FieldValue);
}
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 28fe883feb9..b486eb45915 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -321,7 +321,10 @@ void AddSC_boss_ptheradras();
void AddSC_instance_maraudon();
void AddSC_boss_onyxia(); //Onyxia's Lair
void AddSC_instance_onyxias_lair();
-void AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs
+void AddSC_boss_tuten_kash(); //Razorfen Downs
+void AddSC_boss_mordresh_fire_eye();
+void AddSC_boss_glutton();
+void AddSC_boss_amnennar_the_coldbringer();
void AddSC_razorfen_downs();
void AddSC_instance_razorfen_downs();
void AddSC_razorfen_kraul(); //Razorfen Kraul
@@ -1032,7 +1035,10 @@ void AddKalimdorScripts()
AddSC_instance_maraudon();
AddSC_boss_onyxia(); //Onyxia's Lair
AddSC_instance_onyxias_lair();
- AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs
+ AddSC_boss_tuten_kash(); //Razorfen Downs
+ AddSC_boss_mordresh_fire_eye();
+ AddSC_boss_glutton();
+ AddSC_boss_amnennar_the_coldbringer();
AddSC_razorfen_downs();
AddSC_instance_razorfen_downs();
AddSC_razorfen_kraul(); //Razorfen Kraul
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 994050b2374..241df021a6c 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3221,6 +3221,9 @@ void SpellMgr::LoadSpellInfoCorrections()
case 28200: // Ascendance (Talisman of Ascendance trinket)
spellInfo->ProcCharges = 6;
break;
+ case 37408: // Oscillation Field
+ spellInfo->AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS;
+ break;
case 47201: // Everlasting Affliction
case 47202:
case 47203:
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 83083778e32..d8dc19c5dcd 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -41,7 +41,6 @@
#include "ArenaTeamMgr.h"
#include "GuildMgr.h"
#include "TicketMgr.h"
-#include "CreatureEventAIMgr.h"
#include "SpellMgr.h"
#include "GroupMgr.h"
#include "Chat.h"
@@ -1692,12 +1691,6 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Scripts text locales..."); // must be after Load*Scripts calls
sObjectMgr->LoadDbScriptStrings();
- TC_LOG_INFO("server.loading", "Loading CreatureEventAI Texts...");
- sEventAIMgr->LoadCreatureEventAI_Texts();
-
- TC_LOG_INFO("server.loading", "Loading CreatureEventAI Scripts...");
- sEventAIMgr->LoadCreatureEventAI_Scripts();
-
TC_LOG_INFO("server.loading", "Loading spell script names...");
sObjectMgr->LoadSpellScriptNames();
@@ -3018,16 +3011,6 @@ void World::LoadDBVersion()
m_DBVersion = "Unknown world database.";
}
-void World::ProcessStartEvent()
-{
- isEventKillStart = true;
-}
-
-void World::ProcessStopEvent()
-{
- isEventKillStart = false;
-}
-
void World::UpdateAreaDependentAuras()
{
SessionMap::const_iterator itr;
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 9435fa8aa94..9422566b707 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -731,12 +731,6 @@ class World
void UpdateAreaDependentAuras();
- void ProcessStartEvent();
- void ProcessStopEvent();
- bool GetEventKill() const { return isEventKillStart; }
-
- bool isEventKillStart;
-
CharacterNameData const* GetCharacterNameData(uint32 guid) const;
void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level);
void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index 5be634d2060..20e4c4c7fdd 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -73,7 +73,6 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Addons
${CMAKE_SOURCE_DIR}/src/server/game/AI
${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI
- ${CMAKE_SOURCE_DIR}/src/server/game/AI/EventAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 039766177c1..59477c6684f 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -26,7 +26,6 @@ EndScriptData */
#include "AchievementMgr.h"
#include "AuctionHouseMgr.h"
#include "Chat.h"
-#include "CreatureEventAIMgr.h"
#include "CreatureTextMgr.h"
#include "DisableMgr.h"
#include "Language.h"
@@ -53,7 +52,6 @@ public:
{
{ "achievement", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT, true, &HandleReloadAllAchievementCommand, "", NULL },
{ "area", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_AREA, true, &HandleReloadAllAreaCommand, "", NULL },
- { "eventai", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_EVENTAI, true, &HandleReloadAllEventAICommand, "", NULL },
{ "gossips", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_GOSSIP, true, &HandleReloadAllGossipsCommand, "", NULL },
{ "item", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_ITEM, true, &HandleReloadAllItemCommand, "", NULL },
{ "locales", rbac::RBAC_PERM_COMMAND_RELOAD_ALL_LOCALES, true, &HandleReloadAllLocalesCommand, "", NULL },
@@ -80,8 +78,6 @@ public:
{ "conditions", rbac::RBAC_PERM_COMMAND_RELOAD_CONDITIONS, true, &HandleReloadConditions, "", NULL },
{ "config", rbac::RBAC_PERM_COMMAND_RELOAD_CONFIG, true, &HandleReloadConfigCommand, "", NULL },
{ "creature_text", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEXT, true, &HandleReloadCreatureText, "", NULL },
- { "creature_ai_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_AI_SCRIPTS, true, &HandleReloadEventAIScriptsCommand, "", NULL },
- { "creature_ai_texts", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_AI_TEXTS, true, &HandleReloadEventAITextsCommand, "", NULL },
{ "creature_questender", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER, true, &HandleReloadCreatureQuestEnderCommand, "", NULL },
{ "creature_linked_respawn", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN, true, &HandleReloadLinkedRespawnCommand, "", NULL },
{ "creature_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesCreatureCommand, "", NULL },
@@ -182,7 +178,6 @@ public:
HandleReloadAllAchievementCommand(handler, "");
HandleReloadAllAreaCommand(handler, "");
- HandleReloadAllEventAICommand(handler, "");
HandleReloadAllLootCommand(handler, "");
HandleReloadAllNpcCommand(handler, "");
HandleReloadAllQuestCommand(handler, "");
@@ -273,13 +268,6 @@ public:
return true;
}
- static bool HandleReloadAllEventAICommand(ChatHandler* handler, const char* /*args*/)
- {
- HandleReloadEventAITextsCommand(handler, "a");
- HandleReloadEventAIScriptsCommand(handler, "a");
- return true;
- }
-
static bool HandleReloadAllSpellCommand(ChatHandler* handler, const char* /*args*/)
{
HandleReloadSkillDiscoveryTemplateCommand(handler, "a");
@@ -1014,23 +1002,6 @@ public:
return true;
}
- static bool HandleReloadEventAITextsCommand(ChatHandler* handler, const char* /*args*/)
- {
-
- TC_LOG_INFO("misc", "Re-Loading Texts from `creature_ai_texts`...");
- sEventAIMgr->LoadCreatureEventAI_Texts();
- handler->SendGlobalGMSysMessage("DB table `creature_ai_texts` reloaded.");
- return true;
- }
-
- static bool HandleReloadEventAIScriptsCommand(ChatHandler* handler, const char* /*args*/)
- {
- TC_LOG_INFO("misc", "Re-Loading Scripts from `creature_ai_scripts`...");
- sEventAIMgr->LoadCreatureEventAI_Scripts();
- handler->SendGlobalGMSysMessage("DB table `creature_ai_scripts` reloaded.");
- return true;
- }
-
static bool HandleReloadSpellScriptsCommand(ChatHandler* handler, const char* args)
{
if (sScriptMgr->IsScriptScheduled())
diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
index 6dbcdffca72..2b1b04cb654 100644
--- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
+++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp
@@ -60,6 +60,7 @@ public:
{
waterBoltTimer = 3 * IN_MILLISECONDS;
resetTimer = 5 * IN_MILLISECONDS;
+ balindaGUID = 0;
}
void UpdateAI(uint32 diff) OVERRIDE
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp
index 275b3802764..ff839e3cacb 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/boss_rend_blackhand.cpp
@@ -171,6 +171,7 @@ public:
_Reset();
gythEvent = false;
victorGUID = 0;
+ portcullisGUID = 0;
}
void EnterCombat(Unit* /*who*/) OVERRIDE
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
index 9b250cc169a..a1bbad7ee1c 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp
@@ -73,6 +73,8 @@ public:
go_blackrockaltar = 0;
go_portcullis_active = 0;
go_portcullis_tobossrooms = 0;
+ memset(go_roomrunes, 0, sizeof(go_roomrunes));
+ memset(go_emberseerrunes, 0, sizeof(go_emberseerrunes));
}
void OnCreatureCreate(Creature* creature) OVERRIDE
@@ -270,7 +272,7 @@ public:
return true;
}
- void ProcessEvent(WorldObject* /*gameObject*/, uint32 eventId) OVERRIDE
+ void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) OVERRIDE
{
switch (eventId)
{
@@ -313,102 +315,71 @@ public:
{
case DATA_HIGHLORD_OMOKK:
return HighlordOmokk;
- break;
case DATA_SHADOW_HUNTER_VOSHGAJIN:
return ShadowHunterVoshgajin;
- break;
case DATA_WARMASTER_VOONE:
return WarMasterVoone;
- break;
case DATA_MOTHER_SMOLDERWEB:
return MotherSmolderweb;
- break;
case DATA_UROK_DOOMHOWL:
return UrokDoomhowl;
- break;
case DATA_QUARTERMASTER_ZIGRIS:
return QuartermasterZigris;
- break;
case DATA_GIZRUL_THE_SLAVENER:
return GizrultheSlavener;
- break;
case DATA_HALYCON:
return Halycon;
- break;
case DATA_OVERLORD_WYRMTHALAK:
return OverlordWyrmthalak;
- break;
case DATA_PYROGAURD_EMBERSEER:
return PyroguardEmberseer;
- break;
case DATA_WARCHIEF_REND_BLACKHAND:
return WarchiefRendBlackhand;
- break;
case DATA_GYTH:
return Gyth;
- break;
case DATA_THE_BEAST:
return TheBeast;
- break;
case DATA_GENERAL_DRAKKISATH:
return GeneralDrakkisath;
- break;
case GO_EMBERSEER_IN:
return go_emberseerin;
- break;
case GO_DOORS:
return go_doors;
- break;
case GO_EMBERSEER_OUT:
return go_emberseerout;
- break;
case GO_HALL_RUNE_1:
return go_roomrunes[0];
- break;
case GO_HALL_RUNE_2:
return go_roomrunes[1];
- break;
case GO_HALL_RUNE_3:
return go_roomrunes[2];
- break;
case GO_HALL_RUNE_4:
return go_roomrunes[3];
- break;
case GO_HALL_RUNE_5:
return go_roomrunes[4];
- break;
case GO_HALL_RUNE_6:
return go_roomrunes[5];
- break;
case GO_HALL_RUNE_7:
return go_roomrunes[6];
- break;
case GO_EMBERSEER_RUNE_1:
return go_emberseerrunes[0];
- break;
case GO_EMBERSEER_RUNE_2:
return go_emberseerrunes[1];
- break;
case GO_EMBERSEER_RUNE_3:
return go_emberseerrunes[2];
- break;
case GO_EMBERSEER_RUNE_4:
return go_emberseerrunes[3];
- break;
case GO_EMBERSEER_RUNE_5:
return go_emberseerrunes[4];
- break;
case GO_EMBERSEER_RUNE_6:
return go_emberseerrunes[5];
- break;
case GO_EMBERSEER_RUNE_7:
return go_emberseerrunes[6];
- break;
case GO_PORTCULLIS_ACTIVE:
return go_portcullis_active;
- break;
case GO_PORTCULLIS_TOBOSSROOMS:
return go_portcullis_tobossrooms;
+ default:
break;
}
return 0;
@@ -577,8 +548,6 @@ public:
protected:
EventMap Events;
- uint32 encounter[EncounterCount];
- std::string m_strInstData;
uint64 HighlordOmokk;
uint64 ShadowHunterVoshgajin;
uint64 WarMasterVoone;
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
index f3a788918f2..4e0c79509fc 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp
@@ -264,7 +264,6 @@ public:
if (Unit* player = me->SelectNearestPlayer(60.0f))
{
me->SetInFront(player);
- me->SendMovementFlagUpdate();
Talk(SAY_SUCCESS);
if (GameObject* portcullis1 = me->FindNearestGameObject(GO_PORTCULLIS_ACTIVE, 65.0f))
portcullis1->SetGoState(GO_STATE_ACTIVE);
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
index 622c34d3358..0c85e89ec4a 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp
@@ -63,6 +63,7 @@ public:
{
// Razorgore
EggCount = 0;
+ EggEvent = 0;
RazorgoreTheUntamedGUID = 0;
RazorgoreDoorGUID = 0;
EggList.clear();
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
index 8efcbf29d30..91127f2db0d 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
@@ -614,7 +614,8 @@ public:
}
return 50000;
case 15:
- arca->DealDamage(arca, arca->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ if (arca)
+ arca->DealDamage(arca, arca->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
return 5000;
default : return 9999999;
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
index 463e88b670b..0810d5ca2b8 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
@@ -807,6 +807,7 @@ public:
me->GetPosition(x, y, z); //this visual aura some under ground
me->SetPosition(x, y, z + 0.35f, 0.0f);
Despawn();
+ debuffGUID = 0;
Creature* debuff = DoSpawnCreature(HELPER, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 14500);
if (debuff)
{
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp
index 280b4c27770..e68d834b20d 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp
@@ -200,16 +200,13 @@ public:
{
if (!SisterDeath)
{
- if (instance)
+ Unit* Temp = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_ALYTHESS));
+ if (Temp && Temp->isDead())
{
- Unit* Temp = Unit::GetUnit(*me, instance->GetData64(DATA_ALYTHESS));
- if (Temp && Temp->isDead())
- {
- Talk(YELL_SISTER_ALYTHESS_DEAD);
- DoCast(me, SPELL_EMPOWER);
- me->InterruptSpell(CURRENT_GENERIC_SPELL);
- SisterDeath = true;
- }
+ Talk(YELL_SISTER_ALYTHESS_DEAD);
+ DoCast(me, SPELL_EMPOWER);
+ me->InterruptSpell(CURRENT_GENERIC_SPELL);
+ SisterDeath = true;
}
}
@@ -347,15 +344,12 @@ public:
{
Enraged = false;
- if (instance)
+ if (Creature* temp = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SACROLASH)))
{
- if (Creature* temp = ObjectAccessor::GetCreature((*me), instance->GetData64(DATA_SACROLASH)))
- {
- if (temp->isDead())
- temp->Respawn();
- else if (temp->GetVictim())
- me->getThreatManager().addThreat(temp->GetVictim(), 0.0f);
- }
+ if (temp->isDead())
+ temp->Respawn();
+ else if (temp->GetVictim())
+ me->getThreatManager().addThreat(temp->GetVictim(), 0.0f);
}
if (!me->IsInCombat())
@@ -527,7 +521,7 @@ public:
if (!SisterDeath)
{
- Unit* Temp = Unit::GetUnit(*me, instance->GetData64(DATA_SACROLASH));
+ Unit* Temp = ObjectAccessor::GetUnit(*me, instance->GetData64(DATA_SACROLASH));
if (Temp && Temp->isDead())
{
Talk(YELL_SISTER_SACROLASH_DEAD);
@@ -538,7 +532,7 @@ public:
}
if (!me->GetVictim())
{
- Creature* sisiter = ObjectAccessor::GetCreature((*me), instance->GetData64(DATA_SACROLASH));
+ Creature* sisiter = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SACROLASH));
if (sisiter && !sisiter->isDead() && sisiter->GetVictim())
{
me->AddThreat(sisiter->GetVictim(), 0.0f);
diff --git a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
index ebec0170d23..257e3c21688 100644
--- a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
@@ -41,9 +41,9 @@ enum OOX
{
SAY_OOX_START = 0,
SAY_OOX_AGGRO = 1,
- SAY_OOX_AMBUSH = 3,
- SAY_OOX_AMBUSH_REPLY = 4,
- SAY_OOX_END = 5,
+ SAY_OOX_AMBUSH = 2,
+ SAY_OOX_AMBUSH_REPLY = 3,
+ SAY_OOX_END = 4,
QUEST_RESQUE_OOX_09 = 836,
diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt
index 17c360a54b2..c02e896a87d 100644
--- a/src/server/scripts/Kalimdor/CMakeLists.txt
+++ b/src/server/scripts/Kalimdor/CMakeLists.txt
@@ -15,12 +15,15 @@ set(scripts_STAT_SRCS
Kalimdor/zone_moonglade.cpp
Kalimdor/RazorfenDowns/razorfen_downs.cpp
Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp
+ Kalimdor/RazorfenDowns/boss_tuten_kash.cpp
+ Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp
+ Kalimdor/RazorfenDowns/boss_glutton.cpp
Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp
Kalimdor/RazorfenDowns/razorfen_downs.h
- Kalimdor/ZulFarrak/zulfarrak.h
Kalimdor/ZulFarrak/zulfarrak.cpp
Kalimdor/ZulFarrak/instance_zulfarrak.cpp
Kalimdor/ZulFarrak/boss_zum_rah.cpp
+ Kalimdor/ZulFarrak/zulfarrak.h
Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp
Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h
Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
index 164de89b017..52f706d5626 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp
@@ -186,6 +186,7 @@ public:
{
npc_towering_infernalAI(Creature* creature) : ScriptedAI(creature)
{
+ AnetheronGUID = 0;
instance = creature->GetInstanceScript();
if (instance)
AnetheronGUID = instance->GetData64(DATA_ANETHERON);
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
index aaf2bb65ba0..dd486df16ed 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp
@@ -193,6 +193,7 @@ public:
{
npc_lesser_doomguardAI(Creature* creature) : hyjal_trashAI(creature)
{
+ AzgalorGUID = 0;
instance = creature->GetInstanceScript();
if (instance)
AzgalorGUID = instance->GetData64(DATA_AZGALOR);
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp
index 43d75fad876..9245a0c648f 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp
@@ -186,6 +186,7 @@ hyjal_trashAI::hyjal_trashAI(Creature* creature) : npc_escortAI(creature)
faction = 0;
useFlyPath = false;
damageTaken = 0;
+ memset(DummyTarget, 0, sizeof(DummyTarget));
Reset();
}
@@ -430,7 +431,6 @@ public:
bool meteor;
bool CanMove;
- bool WpEnabled;
bool go;
uint32 spawnTimer;
uint32 FlameBuffetTimer;
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp
index 4a4d7fe4b07..323fd92a8f6 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_amnennar_the_coldbringer.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -16,63 +15,57 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/* ScriptData
-SDName: Boss_Amnennar_the_coldbringer
-SD%Complete: 100
-SDComment:
-SDCategory: Razorfen Downs
-EndScriptData */
-
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "razorfen_downs.h"
-enum AmnennarTheColdbringer
+enum Say
{
SAY_AGGRO = 0,
SAY_SUMMON60 = 1,
SAY_SUMMON30 = 2,
SAY_HP = 3,
- SAY_KILL = 4,
+ SAY_KILL = 4
+};
+enum Spells
+{
SPELL_AMNENNARSWRATH = 13009,
SPELL_FROSTBOLT = 15530,
SPELL_FROST_NOVA = 15531,
SPELL_FROST_SPECTRES = 12642
};
+enum Events
+{
+ EVENT_AMNENNARSWRATH = 1,
+ EVENT_FROSTBOLT = 2,
+ EVENT_FROST_NOVA = 3
+};
+
class boss_amnennar_the_coldbringer : public CreatureScript
{
public:
boss_amnennar_the_coldbringer() : CreatureScript("boss_amnennar_the_coldbringer") { }
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new boss_amnennar_the_coldbringerAI(creature);
- }
-
- struct boss_amnennar_the_coldbringerAI : public ScriptedAI
+ struct boss_amnennar_the_coldbringerAI : public BossAI
{
- boss_amnennar_the_coldbringerAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 AmnenarsWrath_Timer;
- uint32 FrostBolt_Timer;
- uint32 FrostNova_Timer;
- bool Spectrals60;
- bool Spectrals30;
- bool Hp;
+ boss_amnennar_the_coldbringerAI(Creature* creature) : BossAI(creature, DATA_AMNENNAR_THE_COLD_BRINGER) { }
void Reset() OVERRIDE
{
- AmnenarsWrath_Timer = 8000;
- FrostBolt_Timer = 1000;
- FrostNova_Timer = urand(10000, 15000);
- Spectrals30 = false;
- Spectrals60 = false;
- Hp = false;
+ _Reset();
+ hp60Spectrals = false;
+ hp30Spectrals = false;
+ hp50 = false;
}
void EnterCombat(Unit* /*who*/) OVERRIDE
{
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_AMNENNARSWRATH, 8000);
+ events.ScheduleEvent(EVENT_FROSTBOLT, 1000);
+ events.ScheduleEvent(EVENT_FROST_NOVA, urand(10000, 15000));
Talk(SAY_AGGRO);
}
@@ -81,55 +74,73 @@ public:
Talk(SAY_KILL);
}
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ _JustDied();
+ }
+
void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
- //AmnenarsWrath_Timer
- if (AmnenarsWrath_Timer <= diff)
- {
- DoCastVictim(SPELL_AMNENNARSWRATH);
- AmnenarsWrath_Timer = 12000;
- } else AmnenarsWrath_Timer -= diff;
+ events.Update(diff);
- //FrostBolt_Timer
- if (FrostBolt_Timer <= diff)
- {
- DoCastVictim(SPELL_FROSTBOLT);
- FrostBolt_Timer = 8000;
- } else FrostBolt_Timer -= diff;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (FrostNova_Timer <= diff)
+ while (uint32 eventId = events.ExecuteEvent())
{
- DoCast(me, SPELL_FROST_NOVA);
- FrostNova_Timer = 15000;
- } else FrostNova_Timer -= diff;
+ switch (eventId)
+ {
+ case EVENT_AMNENNARSWRATH:
+ DoCastVictim(SPELL_AMNENNARSWRATH);
+ events.ScheduleEvent(EVENT_AMNENNARSWRATH, 12000);
+ break;
+ case EVENT_FROSTBOLT:
+ DoCastVictim(SPELL_FROSTBOLT);
+ events.ScheduleEvent(EVENT_FROSTBOLT, 8000);
+ break;
+ case EVENT_FROST_NOVA:
+ DoCast(me, SPELL_FROST_NOVA);
+ events.ScheduleEvent(EVENT_FROST_NOVA, 15000);
+ break;
+ }
+ }
- if (!Spectrals60 && HealthBelowPct(60))
+ if (!hp60Spectrals && HealthBelowPct(60))
{
Talk(SAY_SUMMON60);
DoCastVictim(SPELL_FROST_SPECTRES);
- Spectrals60 = true;
+ hp60Spectrals = true;
}
- if (!Hp && HealthBelowPct(50))
+ if (!hp50 && HealthBelowPct(50))
{
Talk(SAY_HP);
- Hp = true;
+ hp50 = true;
}
- if (!Spectrals30 && HealthBelowPct(30))
+ if (!hp30Spectrals && HealthBelowPct(30))
{
Talk(SAY_SUMMON30);
DoCastVictim(SPELL_FROST_SPECTRES);
- Spectrals30 = true;
+ hp30Spectrals = true;
}
DoMeleeAttackIfReady();
}
+
+ private:
+ bool hp60Spectrals;
+ bool hp30Spectrals;
+ bool hp50;
};
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new boss_amnennar_the_coldbringerAI(creature);
+ }
};
void AddSC_boss_amnennar_the_coldbringer()
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp
new file mode 100644
index 00000000000..b75fcad64a5
--- /dev/null
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_glutton.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "razorfen_downs.h"
+
+enum Say
+{
+ SAY_AGGRO = 0,
+ SAY_SLAY = 1,
+ SAY_HP50 = 2,
+ SAY_HP15 = 3
+};
+
+enum Spells
+{
+ SPELL_DISEASE_CLOUD = 12627,
+ SPELL_FRENZY = 12795
+};
+
+class boss_glutton : public CreatureScript
+{
+public:
+ boss_glutton() : CreatureScript("boss_glutton") { }
+
+ struct boss_gluttonAI : public BossAI
+ {
+ boss_gluttonAI(Creature* creature) : BossAI(creature, DATA_GLUTTON) { }
+
+ void Reset() OVERRIDE
+ {
+ _Reset();
+ hp50 = false;
+ hp15 = false;
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ }
+
+ void KilledUnit(Unit* /*victim*/) OVERRIDE
+ {
+ Talk(SAY_SLAY);
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ _JustDied();
+ }
+
+ void UpdateAI(uint32 /*diff*/) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (!hp50 && HealthBelowPct(50))
+ {
+ Talk(SAY_HP50);
+ hp50 = true;
+ }
+
+ if (!hp15 && HealthBelowPct(15))
+ {
+ Talk(SAY_HP15);
+ DoCast(me, SPELL_FRENZY);
+ hp15 = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ bool hp50;
+ bool hp15;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new boss_gluttonAI(creature);
+ }
+};
+
+void AddSC_boss_glutton()
+{
+ new boss_glutton();
+}
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp
new file mode 100644
index 00000000000..1f45de3c4c6
--- /dev/null
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_mordresh_fire_eye.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "razorfen_downs.h"
+
+enum Say
+{
+ SAY_OOC_1 = 0,
+ SAY_OOC_2 = 1,
+ SAY_OOC_3 = 2,
+ SAY_AGGRO = 3
+};
+
+enum Spells
+{
+ SPELL_FIREBALL = 12466,
+ SPELL_FIRE_NOVA = 12470
+};
+
+enum Events
+{
+ EVENT_OOC_1 = 1,
+ EVENT_OOC_2 = 2,
+ EVENT_OOC_3 = 3,
+ EVENT_OOC_4 = 4,
+ EVENT_FIREBALL = 5,
+ EVENT_FIRE_NOVA = 6
+};
+
+class boss_mordresh_fire_eye : public CreatureScript
+{
+public:
+ boss_mordresh_fire_eye() : CreatureScript("boss_mordresh_fire_eye") { }
+
+ struct boss_mordresh_fire_eyeAI : public BossAI
+ {
+ boss_mordresh_fire_eyeAI(Creature* creature) : BossAI(creature, DATA_MORDRESH_FIRE_EYE) { }
+
+ void Reset() OVERRIDE
+ {
+ _Reset();
+ events.ScheduleEvent(EVENT_OOC_1, 10000);
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ _EnterCombat();
+ events.Reset();
+ Talk(SAY_AGGRO);
+ events.ScheduleEvent(EVENT_FIREBALL, 100);
+ events.ScheduleEvent(EVENT_FIRE_NOVA, urand(8000, 12000));
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ _JustDied();
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ if (!UpdateVictim())
+ {
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_OOC_1:
+ Talk(SAY_OOC_1);
+ events.ScheduleEvent(EVENT_OOC_2, 8000);
+ break;
+ case EVENT_OOC_2:
+ Talk(SAY_OOC_2);
+ events.ScheduleEvent(EVENT_OOC_3, 3000);
+ break;
+ case EVENT_OOC_3:
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ events.ScheduleEvent(EVENT_OOC_4, 6000);
+ break;
+ case EVENT_OOC_4:
+ Talk(SAY_OOC_3);
+ events.ScheduleEvent(EVENT_OOC_1, 14000);
+ break;
+ }
+ }
+ return;
+ }
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FIREBALL:
+ DoCastVictim(SPELL_FIREBALL);
+ events.ScheduleEvent(EVENT_FIREBALL, urand(2400, 3800));
+ break;
+ case EVENT_FIRE_NOVA:
+ DoCast(me, SPELL_FIRE_NOVA);
+ events.ScheduleEvent(EVENT_FIRE_NOVA, urand(11000, 16000));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new boss_mordresh_fire_eyeAI(creature);
+ }
+};
+
+void AddSC_boss_mordresh_fire_eye()
+{
+ new boss_mordresh_fire_eye();
+}
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp
new file mode 100644
index 00000000000..5cf8a2992a3
--- /dev/null
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/boss_tuten_kash.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "razorfen_downs.h"
+
+enum Spells
+{
+ SPELL_THRASH = 8876,
+ SPELL_WEB_SPRAY = 12252,
+ SPELL_VIRULENT_POISON = 12254,
+ SPELL_CURSE_OF_TUTENKASH = 12255
+};
+
+enum Events
+{
+ EVENT_WEB_SPRAY = 1,
+ EVENT_CURSE_OF_TUTENKASH = 2
+};
+
+class boss_tuten_kash : public CreatureScript
+{
+public:
+ boss_tuten_kash() : CreatureScript("boss_tuten_kash") { }
+
+ struct boss_tuten_kashAI : public BossAI
+ {
+ boss_tuten_kashAI(Creature* creature) : BossAI(creature, DATA_TUTEN_KASH) { }
+
+ void Reset() OVERRIDE
+ {
+ _Reset();
+ if (!me->HasAura(SPELL_THRASH))
+ DoCast(me, SPELL_THRASH);
+ if (!me->HasAura(SPELL_VIRULENT_POISON))
+ DoCast(me, SPELL_VIRULENT_POISON);
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
+ {
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_WEB_SPRAY, urand(3000, 5000));
+ events.ScheduleEvent(EVENT_CURSE_OF_TUTENKASH, urand(9000, 14000));
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ _JustDied();
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WEB_SPRAY:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, false))
+ {
+ if (!target->HasAura(SPELL_WEB_SPRAY))
+ DoCast(target, SPELL_WEB_SPRAY);
+ }
+ events.ScheduleEvent(EVENT_WEB_SPRAY, urand(6000, 8000));
+ break;
+ case EVENT_CURSE_OF_TUTENKASH:
+ DoCast(me, SPELL_CURSE_OF_TUTENKASH);
+ events.ScheduleEvent(EVENT_CURSE_OF_TUTENKASH, urand(15000, 25000));
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new boss_tuten_kashAI(creature);
+ }
+};
+
+void AddSC_boss_tuten_kash()
+{
+ new boss_tuten_kash();
+}
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp
index 091c7e46585..097f340891a 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/instance_razorfen_downs.cpp
@@ -16,199 +16,219 @@
*/
#include "ScriptMgr.h"
+#include "ObjectMgr.h"
#include "InstanceScript.h"
#include "razorfen_downs.h"
#include "Player.h"
#include "TemporarySummon.h"
-#define MAX_ENCOUNTER 1
+Position const PosSummonTutenkash[15] =
+{
+ // 7349 Tomb Fiend
+ { 2487.339f, 805.9111f, 43.08361f, 2.844887f },
+ { 2485.405f, 804.1145f, 43.68511f, 3.054326f },
+ { 2488.431f, 801.2809f, 42.70374f, 4.29351f },
+ { 2489.914f, 804.7949f, 43.25175f, 1.658063f },
+ { 2541.246f, 907.0941f, 46.64201f, 2.024582f },
+ { 2544.701f, 907.6331f, 46.38007f, 1.605703f },
+ { 2541.49f, 911.1756f, 46.26493f, 4.817109f },
+ { 2544.693f, 912.8887f, 46.39912f, 2.129302f },
+ { 2524.036f, 834.4852f, 48.37031f, 0.8028514f },
+ { 2527.017f, 829.9793f, 48.06498f, 0.6981317f },
+ // 7351 Tomb Reaver
+ { 2542.818f, 904.9359f, 46.80911f, 4.642576f },
+ { 2543.287f, 911.2448f, 46.32785f, 0.6806784f },
+ { 2489.083f, 806.5914f, 43.21102f, 3.682645f },
+ { 2486.828f, 802.8737f, 43.19883f, 2.9147f },
+ // 7355 Tuten'kash
+ { 2487.939f, 804.2224f, 43.10735f, 1.692969f }
+};
class instance_razorfen_downs : public InstanceMapScript
{
public:
- instance_razorfen_downs() : InstanceMapScript("instance_razorfen_downs", 129) { }
-
- InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE
- {
- return new instance_razorfen_downs_InstanceMapScript(map);
- }
+ instance_razorfen_downs() : InstanceMapScript(RFDScriptName, 129) { }
struct instance_razorfen_downs_InstanceMapScript : public InstanceScript
{
instance_razorfen_downs_InstanceMapScript(Map* map) : InstanceScript(map)
{
+ SetBossNumber(EncounterCount);
}
- uint64 uiGongGUID;
-
- uint32 m_auiEncounter[MAX_ENCOUNTER];
-
- uint16 uiGongWaves;
-
- std::string str_data;
-
void Initialize() OVERRIDE
{
- uiGongGUID = 0;
-
- uiGongWaves = 0;
-
- memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
- }
-
- std::string GetSaveData() OVERRIDE
- {
- OUT_SAVE_INST_DATA;
-
- std::ostringstream saveStream;
-
- saveStream << "T C " << m_auiEncounter[0]
- << ' ' << uiGongWaves;
-
- str_data = saveStream.str();
-
- OUT_SAVE_INST_DATA_COMPLETE;
- return str_data;
+ goGongGUID = 0;
+ gongWave = 0;
+ fiendsKilled = 0;
+ reaversKilled = 0;
+ summonLowRange = 0;
+ summonHighRange = 0;
+ summonCreature = 0;
}
- void Load(const char* in) OVERRIDE
+ void OnGameObjectCreate(GameObject* gameObject) OVERRIDE
{
- if (!in)
+ switch (gameObject->GetEntry())
{
- OUT_LOAD_INST_DATA_FAIL;
- return;
+ case GO_GONG:
+ goGongGUID = gameObject->GetGUID();
+ if (GetBossState(DATA_TUTEN_KASH) == DONE)
+ gameObject->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ break;
+ case GO_IDOL_OVEN_FIRE:
+ case GO_IDOL_CUP_FIRE:
+ case GO_IDOL_MOUTH_FIRE:
+ if (GetBossState(DATA_EXTINGUISHING_THE_IDOL) == DONE)
+ gameObject->Delete();
+ break;
+ default:
+ break;
}
-
- OUT_LOAD_INST_DATA(in);
-
- char dataHead1, dataHead2;
- uint16 data0, data1;
-
- std::istringstream loadStream(in);
- loadStream >> dataHead1 >> dataHead2 >> data0 >> data1;
-
- if (dataHead1 == 'T' && dataHead2 == 'C')
- {
- m_auiEncounter[0] = data0;
-
- for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
- if (m_auiEncounter[i] == IN_PROGRESS)
- m_auiEncounter[i] = NOT_STARTED;
-
- uiGongWaves = data1;
- } else OUT_LOAD_INST_DATA_FAIL;
-
- OUT_LOAD_INST_DATA_COMPLETE;
}
- void OnGameObjectCreate(GameObject* go) OVERRIDE
+ bool SetBossState(uint32 type, EncounterState state) OVERRIDE
{
- switch (go->GetEntry())
+ if (!InstanceScript::SetBossState(type, state))
+ return false;
+
+ switch (type)
{
- case GO_GONG:
- uiGongGUID = go->GetGUID();
- if (m_auiEncounter[0] == DONE)
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ case DATA_TUTEN_KASH:
+ case DATA_MORDRESH_FIRE_EYE:
+ case DATA_GLUTTON:
+ case DATA_AMNENNAR_THE_COLD_BRINGER:
+ case DATA_GONG:
+ case DATA_WAVE:
+ case DATA_EXTINGUISHING_THE_IDOL:
break;
default:
break;
}
+ return true;
}
- void SetData(uint32 uiType, uint32 uiData) OVERRIDE
+ void SetData(uint32 type, uint32 data) OVERRIDE
{
- if (uiType == DATA_GONG_WAVES)
+ if (type == DATA_WAVE)
{
- uiGongWaves = uiData;
-
- switch (uiGongWaves)
+ switch (data)
{
- case 9:
- case 14:
- if (GameObject* go = instance->GetGameObject(uiGongGUID))
- go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- break;
- case 1:
- case 10:
- case 16:
+ case IN_PROGRESS:
{
- GameObject* go = instance->GetGameObject(uiGongGUID);
-
- if (!go)
- return;
-
- go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
-
- uint32 uiCreature = 0;
- uint8 uiSummonTimes = 0;
+ if (GameObject* go = instance->GetGameObject(goGongGUID))
+ go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- switch (uiGongWaves)
+ switch (gongWave)
{
- case 1:
- uiCreature = NPC_TOMB_FIEND;
- uiSummonTimes = 7;
- break;
- case 10:
- uiCreature = NPC_TOMB_REAVER;
- uiSummonTimes = 3;
+ case 0:
+ summonLowRange = 0;
+ summonHighRange = 10;
+ summonCreature = NPC_TOMB_FIEND;
break;
- case 16:
- uiCreature = NPC_TUTEN_KASH;
+ case 1:
+ summonLowRange = 10;
+ summonHighRange = 14;
+ summonCreature = NPC_TOMB_REAVER;
break;
- default:
+ case 2:
+ summonLowRange = 14;
+ summonHighRange = 15;
+ summonCreature = NPC_TUTEN_KASH;
break;
}
- if (Creature* creature = go->SummonCreature(uiCreature, 2502.635f, 844.140f, 46.896f, 0.633f))
+ if (GameObject* go = instance->GetGameObject(goGongGUID))
{
- if (uiGongWaves == 10 || uiGongWaves == 1)
+ for (uint8 i = summonLowRange; i < summonHighRange; ++i)
{
- for (uint8 i = 0; i < uiSummonTimes; ++i)
- {
- if (Creature* summon = go->SummonCreature(uiCreature, 2502.635f + float(irand(-5, 5)), 844.140f + float(irand(-5, 5)), 46.896f, 0.633f))
- summon->GetMotionMaster()->MovePoint(0, 2533.479f + float(irand(-5, 5)), 870.020f + float(irand(-5, 5)), 47.678f);
- }
+ Creature* creature = go->SummonCreature(summonCreature, PosSummonTutenkash[i]);
+ creature->GetMotionMaster()->MovePoint(0, 2533.479f + float(irand(-5, 5)), 870.020f + float(irand(-5, 5)), 47.678f);
}
- creature->GetMotionMaster()->MovePoint(0, 2533.479f + float(irand(-5, 5)), 870.020f + float(irand(-5, 5)), 47.678f);
}
+
+ ++gongWave;
break;
}
- default:
+ case NPC_TOMB_FIEND:
+ if (++fiendsKilled == 10)
+ {
+ fiendsKilled = 0;
+ if (GameObject* go = instance->GetGameObject(goGongGUID))
+ go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ }
+ break;
+ case NPC_TOMB_REAVER:
+ if (++reaversKilled == 4)
+ {
+ reaversKilled = 0;
+ if (GameObject* go = instance->GetGameObject(goGongGUID))
+ go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
+ }
break;
}
+
}
- if (uiType == BOSS_TUTEN_KASH)
- {
- m_auiEncounter[0] = uiData;
+ }
- if (uiData == DONE)
- SaveToDB();
- }
+ std::string GetSaveData() OVERRIDE
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << "R D " << GetBossSaveData();
+
+ OUT_SAVE_INST_DATA_COMPLETE;
+ return saveStream.str();
}
- uint32 GetData(uint32 uiType) const OVERRIDE
+ void Load(const char* str) OVERRIDE
{
- switch (uiType)
+ if (!str)
{
- case DATA_GONG_WAVES:
- return uiGongWaves;
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
}
- return 0;
- }
+ OUT_LOAD_INST_DATA(str);
- uint64 GetData64(uint32 uiType) const OVERRIDE
- {
- switch (uiType)
+ char dataHead1, dataHead2;
+
+ std::istringstream loadStream(str);
+ loadStream >> dataHead1 >> dataHead2;
+
+ if (dataHead1 == 'R' && dataHead2 == 'D')
{
- case DATA_GONG: return uiGongGUID;
+ for (uint32 i = 0; i < EncounterCount; ++i)
+ {
+ uint32 tmpState;
+ loadStream >> tmpState;
+ if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
+ tmpState = NOT_STARTED;
+ SetBossState(i, EncounterState(tmpState));
+ }
}
+ else
+ OUT_LOAD_INST_DATA_FAIL;
- return 0;
+ OUT_LOAD_INST_DATA_COMPLETE;
}
+
+ protected:
+ uint64 goGongGUID;
+ uint16 gongWave;
+ uint8 fiendsKilled;
+ uint8 reaversKilled;
+ uint8 summonLowRange;
+ uint8 summonHighRange;
+ uint32 summonCreature;
};
+ InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE
+ {
+ return new instance_razorfen_downs_InstanceMapScript(map);
+ }
};
void AddSC_instance_razorfen_downs()
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
index 320c9970077..3300f0d811b 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp
@@ -32,6 +32,10 @@ EndContentData */
#include "ScriptedGossip.h"
#include "razorfen_downs.h"
#include "Player.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "Cell.h"
+#include "CellImpl.h"
/*###
# npc_henry_stern
@@ -101,32 +105,272 @@ public:
};
/*######
-## go_gong
+## npc_belnistrasz for Quest 3525 "Extinguishing the Idol"
######*/
-class go_gong : public GameObjectScript
+Position const PosSummonSpawner[3] =
+{
+ { 2582.789f, 954.3925f, 52.48214f, 3.787364f },
+ { 2569.42f, 956.3801f, 52.27323f, 5.427974f },
+ { 2570.62f, 942.3934f, 53.7433f, 0.715585f }
+};
+
+enum Belnistrasz
+{
+ EVENT_CHANNEL = 1,
+ EVENT_IDOL_ROOM_SPAWNER = 2,
+ EVENT_PROGRESS = 3,
+ EVENT_COMPLETE = 4,
+ EVENT_FIREBALL = 5,
+ EVENT_FROST_NOVA = 6,
+
+ FACTION_ESCORT = 250,
+
+ PATH_ESCORT = 871710,
+ POINT_REACH_IDOL = 17,
+
+ QUEST_EXTINGUISHING_THE_IDOL = 3525,
+
+ SAY_QUEST_ACCEPTED = 0,
+ SAY_EVENT_START = 1,
+ SAY_EVENT_THREE_MIN_LEFT = 2,
+ SAY_EVENT_TWO_MIN_LEFT = 3,
+ SAY_EVENT_ONE_MIN_LEFT = 4,
+ SAY_EVENT_END = 5,
+ SAY_AGGRO = 6, // Combat
+ SAY_WATCH_OUT = 7, // 25% chance to target random creature and say on wave spawn
+
+ SPELL_ARCANE_INTELLECT = 13326,
+ SPELL_FIREBALL = 9053,
+ SPELL_FROST_NOVA = 11831,
+ SPELL_IDOL_SHUTDOWN_VISUAL = 12774, // Hits Unit Entry: 8662
+ SPELL_IDOM_ROOM_CAMERA_SHAKE = 12816 // Dummy needs scripting
+};
+
+class npc_belnistrasz : public CreatureScript
{
public:
- go_gong() : GameObjectScript("go_gong") { }
+ npc_belnistrasz() : CreatureScript("npc_belnistrasz") { }
- bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE
+ struct npc_belnistraszAI : public ScriptedAI
{
- //basic support, not blizzlike data is missing...
- InstanceScript* instance = go->GetInstanceScript();
+ npc_belnistraszAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ eventInProgress = false;
+ }
- if (instance)
+ void Reset() OVERRIDE
{
- instance->SetData(DATA_GONG_WAVES, instance->GetData(DATA_GONG_WAVES)+1);
- return true;
+ if (!eventInProgress)
+ {
+ if (!me->HasAura(SPELL_ARCANE_INTELLECT))
+ DoCast(me, SPELL_ARCANE_INTELLECT);
+
+ channeling = false;
+ eventProgress = 0;
+ spawnerCount = 0;
+ me->SetFlag(UNIT_NPC_FLAGS, GOSSIP_OPTION_QUESTGIVER);
+ }
}
- return false;
+ void EnterCombat(Unit* who) OVERRIDE
+ {
+ if (channeling)
+ {
+ Talk(SAY_WATCH_OUT, who->GetGUID());
+ }
+ else
+ {
+ events.ScheduleEvent(EVENT_FIREBALL, 1000);
+ events.ScheduleEvent(EVENT_FROST_NOVA, urand(8000, 12000));
+ if (urand(0, 100) > 40)
+ Talk(SAY_AGGRO, who->GetGUID());
+ }
+ }
+
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ instance->SetBossState(DATA_EXTINGUISHING_THE_IDOL, DONE);
+ me->DespawnOrUnsummon(5000);
+ }
+
+ void sQuestAccept(Player* /*player*/, Quest const* quest) OVERRIDE
+ {
+ if (quest->GetQuestId() == QUEST_EXTINGUISHING_THE_IDOL)
+ {
+ eventInProgress = true;
+ Talk(SAY_QUEST_ACCEPTED);
+ me->RemoveFlag(UNIT_NPC_FLAGS, GOSSIP_OPTION_QUESTGIVER);
+ me->setFaction(FACTION_ESCORT);
+ me->GetMotionMaster()->MovePath(PATH_ESCORT, false);
+ }
+ }
+
+ void MovementInform(uint32 type, uint32 id) OVERRIDE
+ {
+ if (type == WAYPOINT_MOTION_TYPE && id == POINT_REACH_IDOL)
+ {
+ channeling = true;
+ events.ScheduleEvent(EVENT_CHANNEL, 2000);
+ }
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (!eventInProgress)
+ return;
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CHANNEL:
+ Talk(SAY_EVENT_START);
+ DoCast(me, SPELL_IDOL_SHUTDOWN_VISUAL);
+ events.ScheduleEvent(EVENT_IDOL_ROOM_SPAWNER, 100);
+ events.ScheduleEvent(EVENT_PROGRESS, 120000);
+ break;
+ case EVENT_IDOL_ROOM_SPAWNER:
+ if (Creature* creature = me->SummonCreature(NPC_IDOL_ROOM_SPAWNER, PosSummonSpawner[urand(0,2)], TEMPSUMMON_TIMED_DESPAWN, 4000))
+ creature->AI()->SetData(0,spawnerCount);
+ if (++spawnerCount < 8)
+ events.ScheduleEvent(EVENT_IDOL_ROOM_SPAWNER, 35000);
+ break;
+ case EVENT_PROGRESS:
+ {
+ switch (eventProgress)
+ {
+ case 0:
+ Talk(SAY_EVENT_THREE_MIN_LEFT);
+ ++eventProgress;
+ events.ScheduleEvent(EVENT_PROGRESS, 60000);
+ break;
+ case 1:
+ Talk(SAY_EVENT_TWO_MIN_LEFT);
+ ++eventProgress;
+ events.ScheduleEvent(EVENT_PROGRESS, 60000);
+ break;
+ case 2:
+ Talk(SAY_EVENT_ONE_MIN_LEFT);
+ ++eventProgress;
+ events.ScheduleEvent(EVENT_PROGRESS, 60000);
+ break;
+ case 3:
+ events.CancelEvent(EVENT_IDOL_ROOM_SPAWNER);
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ Talk(SAY_EVENT_END);
+ events.ScheduleEvent(EVENT_COMPLETE, 3000);
+ break;
+ }
+ break;
+ }
+ case EVENT_COMPLETE:
+ {
+ DoCast(me, SPELL_IDOM_ROOM_CAMERA_SHAKE);
+ me->SummonGameObject(GO_BELNISTRASZS_BRAZIER, 2577.196f, 947.0781f, 53.16757f, 2.356195f, 0, 0, 0.9238796f, 0.3826832f, 3600000);
+ std::list<WorldObject*> ClusterList;
+ Trinity::AllWorldObjectsInRange objects(me, 50.0f);
+ Trinity::WorldObjectListSearcher<Trinity::AllWorldObjectsInRange> searcher(me, ClusterList, objects);
+ me->VisitNearbyObject(50.0f, searcher);
+ for (std::list<WorldObject*>::const_iterator itr = ClusterList.begin(); itr != ClusterList.end(); ++itr)
+ {
+ if (Player* player = (*itr)->ToPlayer())
+ {
+ if (player->GetQuestStatus(QUEST_EXTINGUISHING_THE_IDOL) == QUEST_STATUS_INCOMPLETE)
+ player->CompleteQuest(QUEST_EXTINGUISHING_THE_IDOL);
+ }
+ else if (GameObject* go = (*itr)->ToGameObject())
+ {
+ if (go->GetEntry() == GO_IDOL_OVEN_FIRE || go->GetEntry() == GO_IDOL_CUP_FIRE || go->GetEntry() == GO_IDOL_MOUTH_FIRE)
+ go->Delete();
+ }
+ }
+ instance->SetBossState(DATA_EXTINGUISHING_THE_IDOL, DONE);
+ me->DespawnOrUnsummon();
+ break;
+ }
+ case EVENT_FIREBALL:
+ if (me->HasUnitState(UNIT_STATE_CASTING) || !UpdateVictim())
+ return;
+ DoCastVictim(SPELL_FIREBALL);
+ events.ScheduleEvent(EVENT_FIREBALL, 8000);
+ break;
+ case EVENT_FROST_NOVA:
+ if (me->HasUnitState(UNIT_STATE_CASTING) || !UpdateVictim())
+ return;
+ DoCast(me, SPELL_FROST_NOVA);
+ events.ScheduleEvent(EVENT_FROST_NOVA, 15000);
+ break;
+ }
+ }
+ if (!channeling)
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ bool eventInProgress;
+ bool channeling;
+ uint8 eventProgress;
+ uint8 spawnerCount;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_belnistraszAI(creature);
}
+};
+
+class npc_idol_room_spawner : public CreatureScript
+{
+public:
+ npc_idol_room_spawner() : CreatureScript("npc_idol_room_spawner") { }
+
+ struct npc_idol_room_spawnerAI : public ScriptedAI
+ {
+ npc_idol_room_spawnerAI(Creature* creature) : ScriptedAI(creature)
+ {
+ instance = creature->GetInstanceScript();
+ }
+
+ void Reset() OVERRIDE { }
+ void SetData(uint32 /*type*/, uint32 data) OVERRIDE
+ {
+ if (!instance)
+ return;
+
+ if (data < 7)
+ {
+ me->SummonCreature(NPC_WITHERED_BATTLE_BOAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
+ if (data > 0 && me->GetOrientation() < 4.0f)
+ me->SummonCreature(NPC_WITHERED_BATTLE_BOAR, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
+ me->SummonCreature(NPC_DEATHS_HEAD_GEOMANCER, me->GetPositionX() + (cos(me->GetOrientation() - (M_PI/2)) * 2), me->GetPositionY() + (sin(me->GetOrientation() - (M_PI/2)) * 2), me->GetPositionZ(), me->GetOrientation());
+ me->SummonCreature(NPC_WITHERED_QUILGUARD, me->GetPositionX() + (cos(me->GetOrientation() + (M_PI/2)) * 2), me->GetPositionY() + (sin(me->GetOrientation() + (M_PI/2)) * 2), me->GetPositionZ(), me->GetOrientation());
+ }
+ else if (data == 7)
+ me->SummonCreature(NPC_PLAGUEMAW_THE_ROTTING, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
+ }
+
+ private:
+ InstanceScript* instance;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_idol_room_spawnerAI(creature);
+ }
};
enum TombCreature
{
+ EVENT_WEB = 7,
+ SPELL_POISON_PROC = 3616,
+ SPELL_VIRULENT_POISON_PROC = 12254,
SPELL_WEB = 745
};
@@ -135,11 +379,6 @@ class npc_tomb_creature : public CreatureScript
public:
npc_tomb_creature() : CreatureScript("npc_tomb_creature") { }
- CreatureAI* GetAI(Creature* creature) const OVERRIDE
- {
- return new npc_tomb_creatureAI(creature);
- }
-
struct npc_tomb_creatureAI : public ScriptedAI
{
npc_tomb_creatureAI(Creature* creature) : ScriptedAI(creature)
@@ -147,45 +386,86 @@ public:
instance = creature->GetInstanceScript();
}
- InstanceScript* instance;
+ void Reset() OVERRIDE
+ {
+ if (!me->HasAura(SPELL_POISON_PROC) && me->GetEntry() == NPC_TOMB_FIEND)
+ DoCast(me, SPELL_POISON_PROC);
- uint32 uiWebTimer;
+ if (!me->HasAura(SPELL_VIRULENT_POISON_PROC) && me->GetEntry() == NPC_TOMB_REAVER)
+ DoCast(me, SPELL_VIRULENT_POISON_PROC);
+ }
- void Reset() OVERRIDE
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (instance)
+ instance->SetData(DATA_WAVE, me->GetEntry());
+ }
+
+ void EnterCombat(Unit* /*who*/) OVERRIDE
{
- uiWebTimer = urand(5000, 8000);
+ events.ScheduleEvent(EVENT_WEB, urand(5000, 8000));
}
- void UpdateAI(uint32 uiDiff) OVERRIDE
+ void UpdateAI(uint32 diff) OVERRIDE
{
if (!UpdateVictim())
return;
- //from acid
- if (me->GetEntry() == NPC_TOMB_REAVER)
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (uiWebTimer <= uiDiff)
+ switch (eventId)
{
- DoCastVictim(SPELL_WEB);
- uiWebTimer = urand(7000, 16000);
- } else uiWebTimer -= uiDiff;
+ case EVENT_WEB:
+ DoCastVictim(SPELL_WEB);
+ events.ScheduleEvent(EVENT_WEB, urand(7000, 16000));
+ break;
+ }
}
-
DoMeleeAttackIfReady();
}
- void JustDied(Unit* /*killer*/) OVERRIDE
+ private:
+ InstanceScript* instance;
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_tomb_creatureAI(creature);
+ }
+};
+
+/*######
+## go_gong
+######*/
+
+class go_gong : public GameObjectScript
+{
+public:
+ go_gong() : GameObjectScript("go_gong") { }
+
+ bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE
+ {
+ InstanceScript* instance = go->GetInstanceScript();
+
+ if (instance)
{
- if (instance)
- instance->SetData(DATA_GONG_WAVES, instance->GetData(DATA_GONG_WAVES)+1);
+ go->SendCustomAnim(0);
+ instance->SetData(DATA_WAVE, IN_PROGRESS);
+ return true;
}
- };
+ return false;
+ }
};
void AddSC_razorfen_downs()
{
new npc_henry_stern();
- new go_gong();
+ new npc_belnistrasz();
+ new npc_idol_room_spawner();
new npc_tomb_creature();
+ new go_gong();
}
diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h
index c0f63474f23..9fe5314fda0 100644
--- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h
+++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.h
@@ -18,27 +18,56 @@
#ifndef DEF_RAZORFEN_DOWNS_H
#define DEF_RAZORFEN_DOWNS_H
-enum Data
+#define RFDScriptName "instance_razorfen_downs"
+
+uint32 const EncounterCount = 5;
+
+enum DataTypes
{
- BOSS_TUTEN_KASH,
- DATA_GONG_WAVES
+ // Main Bosses
+ DATA_TUTEN_KASH = 0,
+ DATA_MORDRESH_FIRE_EYE = 1,
+ DATA_GLUTTON = 2,
+ DATA_AMNENNAR_THE_COLD_BRINGER = 3,
+ // Events
+ DATA_GONG = 4,
+ DATA_WAVE = 5,
+ DATA_EXTINGUISHING_THE_IDOL = 6
};
-enum Data64
+enum CreatureIds
{
- DATA_GONG
+ // Used in Tuten Kash summon event
+ NPC_TOMB_FIEND = 7349,
+ NPC_TOMB_REAVER = 7351,
+ NPC_TUTEN_KASH = 7355,
+ // Used for quest 3525 "Extinguishing the Idol"
+ NPC_IDOL_ROOM_SPAWNER = 8611,
+ NPC_WITHERED_BATTLE_BOAR = 7333,
+ NPC_DEATHS_HEAD_GEOMANCER = 7335,
+ NPC_WITHERED_QUILGUARD = 7329,
+ NPC_PLAGUEMAW_THE_ROTTING = 7356
};
enum GameObjectIds
{
- GO_GONG = 148917
+ // Used for Tuten Kash summon event
+ GO_GONG = 148917,
+ // Used for quest 3525 "Extinguishing the Idol"
+ GO_IDOL_OVEN_FIRE = 151951,
+ GO_IDOL_CUP_FIRE = 151952,
+ GO_IDOL_MOUTH_FIRE = 151973,
+ GO_BELNISTRASZS_BRAZIER = 152097
};
-enum CreatureId
+template<class AI>
+CreatureAI* GetRazorfenDownsAI(Creature* creature)
{
- NPC_TOMB_FIEND = 7349,
- NPC_TOMB_REAVER = 7351,
- NPC_TUTEN_KASH = 7355
-};
+ if (InstanceMap* instance = creature->GetMap()->ToInstanceMap())
+ if (instance->GetInstanceScript())
+ if (instance->GetScriptId() == sObjectMgr->GetScriptId(RFDScriptName))
+ return new AI(creature);
+ return NULL;
+}
#endif
diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
index ee8618eacc9..35fea896a10 100644
--- a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
@@ -176,6 +176,7 @@ public:
void Reset() OVERRIDE
{
IsMovementActive = false;
+ TargetTubberGUID = 0;
}
void MovementInform(uint32 type, uint32 id) OVERRIDE
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
index d1f0bb10ecd..d2b5b5eaf8c 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
@@ -922,6 +922,7 @@ public:
{
eye_tentacleAI(Creature* creature) : ScriptedAI(creature)
{
+ Portal = 0;
if (Creature* pPortal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
pPortal->SetReactState(REACT_PASSIVE);
@@ -999,6 +1000,7 @@ public:
{
SetCombatMovement(false);
+ Portal = 0;
if (Creature* pPortal = me->SummonCreature(NPC_SMALL_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
pPortal->SetReactState(REACT_PASSIVE);
@@ -1109,6 +1111,7 @@ public:
{
SetCombatMovement(false);
+ Portal = 0;
if (Creature* pPortal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
pPortal->SetReactState(REACT_PASSIVE);
@@ -1228,6 +1231,7 @@ public:
{
SetCombatMovement(false);
+ Portal = 0;
if (Creature* pPortal = me->SummonCreature(NPC_GIANT_PORTAL, *me, TEMPSUMMON_CORPSE_DESPAWN))
{
pPortal->SetReactState(REACT_PASSIVE);
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index 8f6b951d524..3fdfc0c8ae3 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -310,8 +310,6 @@ class npc_snobold_vassal : public CreatureScript
_targetGUID = 0;
_targetDied = false;
- if (_instance)
- _bossGUID = _instance->GetData64(NPC_GORMOK);
//Workaround for Snobold
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
}
@@ -450,7 +448,6 @@ class npc_snobold_vassal : public CreatureScript
private:
EventMap _events;
InstanceScript* _instance;
- uint64 _bossGUID;
uint64 _targetGUID;
bool _targetDied;
};
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 6b746222a72..96b772df5a9 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -1121,6 +1121,7 @@ enum TrashSpells
SPELL_FROSTBOLT = 72166,
SPELL_CHAINS_OF_ICE = 72121,
SPELL_HALLUCINATION = 72342,
+ AURA_HALLUCINATION = 72343,
// Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies)
SPELL_HALLUCINATION_2 = 72344,
@@ -1180,13 +1181,11 @@ enum TrashEvents
struct npc_gauntlet_trash : public ScriptedAI
{
- npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature),
- _instance(creature->GetInstanceScript())
- {
- }
+ npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()) { }
void Reset() OVERRIDE
{
+ InternalWaveId = 0;
me->CastSpell(me, SPELL_WELL_OF_SOULS, true);
_events.Reset();
}
@@ -1226,9 +1225,7 @@ public:
struct npc_ghostly_priestAI : public npc_gauntlet_trash
{
- npc_ghostly_priestAI(Creature* creature) : npc_gauntlet_trash(creature)
- {
- }
+ npc_ghostly_priestAI(Creature* creature) : npc_gauntlet_trash(creature) { }
void EnterCombat(Unit* /*who*/) OVERRIDE
{
@@ -1297,8 +1294,12 @@ public:
struct npc_phantom_mageAI : public npc_gauntlet_trash
{
- npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature)
+ npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature) { }
+
+ void EnterEvadeMode() OVERRIDE
{
+ if (!me->HasAura(AURA_HALLUCINATION))
+ npc_gauntlet_trash::EnterEvadeMode();
}
void EnterCombat(Unit* /*who*/) OVERRIDE
@@ -1342,6 +1343,8 @@ public:
_events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000);
break;
case EVENT_HALLUCINATION:
+ // removing any dots on mage or else the invisibility spell will break duration
+ me->RemoveAllAuras();
DoCast(SPELL_HALLUCINATION);
break;
}
@@ -1365,6 +1368,19 @@ public:
{
npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature) { }
+ void Reset() OVERRIDE
+ {
+ if (Unit* unit = me->SelectNearestTarget())
+ AttackStart(unit);
+ DoZoneInCombat();
+ }
+
+ void EnterEvadeMode() OVERRIDE
+ {
+ if (!me->GetOwner()->HasAura(AURA_HALLUCINATION))
+ npc_phantom_mage::npc_phantom_mageAI::EnterEvadeMode();
+ }
+
void JustDied(Unit* /*killer*/) OVERRIDE
{
DoCast(SPELL_HALLUCINATION_2);
@@ -1384,9 +1400,7 @@ public:
struct npc_shadowy_mercenaryAI : public npc_gauntlet_trash
{
- npc_shadowy_mercenaryAI(Creature* creature) : npc_gauntlet_trash(creature)
- {
- }
+ npc_shadowy_mercenaryAI(Creature* creature) : npc_gauntlet_trash(creature) { }
void EnterCombat(Unit* /*who*/) OVERRIDE
{
@@ -1444,9 +1458,7 @@ public:
struct npc_spectral_footmanAI : public npc_gauntlet_trash
{
- npc_spectral_footmanAI(Creature* creature) : npc_gauntlet_trash(creature)
- {
- }
+ npc_spectral_footmanAI(Creature* creature) : npc_gauntlet_trash(creature) { }
void EnterCombat(Unit* /*who*/) OVERRIDE
{
@@ -1498,9 +1510,7 @@ public:
struct npc_tortured_riflemanAI : public npc_gauntlet_trash
{
- npc_tortured_riflemanAI(Creature* creature) : npc_gauntlet_trash(creature)
- {
- }
+ npc_tortured_riflemanAI(Creature* creature) : npc_gauntlet_trash(creature) { }
void EnterCombat(Unit* /*who*/) OVERRIDE
{
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
index 0599596fc0a..955f4fb1568 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
@@ -110,10 +110,13 @@ public:
void OnCreatureCreate(Creature* creature) OVERRIDE
{
- Map::PlayerList const& players = instance->GetPlayers();
- if (!players.isEmpty())
- if (Player* player = players.begin()->GetSource())
- _teamInInstance = player->GetTeam();
+ if (!_teamInInstance)
+ {
+ Map::PlayerList const& players = instance->GetPlayers();
+ if (!players.isEmpty())
+ if (Player* player = players.begin()->GetSource())
+ _teamInInstance = player->GetTeam();
+ }
switch (creature->GetEntry())
{
@@ -184,7 +187,7 @@ public:
case GO_ARTHAS_DOOR:
_arthasDoorGUID = go->GetGUID();
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- if (GetBossState(DATA_FROSWORN_EVENT) == DONE)
+ if (GetData(DATA_FROSWORN_EVENT) == DONE)
HandleGameObject(0, true, go);
else
HandleGameObject(0, false, go);
@@ -511,13 +514,13 @@ public:
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
- saveStream << "H R " << GetBossSaveData() << _introEvent << ' ' << _frostwornGeneral << _escapeevent;
+ saveStream << "H R " << GetBossSaveData() << _introEvent << ' ' << _frostwornGeneral << ' ' << _escapeevent;
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
- void Load(char const* in) OVERRIDE OVERRIDE
+ void Load(char const* in) OVERRIDE
{
if (!in)
{
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp
index 20b7d39815f..4a9a41f6f8e 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp
@@ -187,7 +187,7 @@ class boss_garfrost : public CreatureScript
switch (eventId)
{
case EVENT_THROW_SARONITE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
Talk(SAY_THROW_SARONITE, target->GetGUID());
DoCast(target, SPELL_THROW_SARONITE);
@@ -199,7 +199,7 @@ class boss_garfrost : public CreatureScript
events.ScheduleEvent(EVENT_CHILLING_WAVE, 40000, 0, PHASE_TWO);
break;
case EVENT_DEEP_FREEZE:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true))
{
Talk(SAY_CAST_DEEP_FREEZE, target->GetGUID());
DoCast(target, SPELL_DEEP_FREEZE);
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp
index 7aa8b123f98..d61fc69a0ae 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp
@@ -63,7 +63,7 @@ class instance_pit_of_saron : public InstanceMapScript
{
if (!_teamInInstance)
{
- Map::PlayerList const &players = instance->GetPlayers();
+ Map::PlayerList const& players = instance->GetPlayers();
if (!players.isEmpty())
if (Player* player = players.begin()->GetSource())
_teamInInstance = player->GetTeam();
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
index 68387279c1d..f76c46d96ff 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp
@@ -514,6 +514,7 @@ class npc_gothik_minion : public CreatureScript
npc_gothik_minionAI(Creature* creature) : CombatAI(creature)
{
liveSide = IN_LIVE_SIDE(me);
+ gateClose = false;
}
bool liveSide;
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp
index a1511fb3dd8..4777b451e4e 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp
@@ -165,7 +165,7 @@ public:
unit->SetControlled(true, UNIT_STATE_ROOT);
}
- void ProcessEvent(WorldObject* /*obj*/, uint32 eventId)
+ void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) OVERRIDE
{
if (eventId == EVENT_FOCUSING_IRIS)
{
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp
index 96fadc7002b..b108378910e 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp
@@ -179,7 +179,7 @@ class instance_oculus : public InstanceMapScript
}
}
- void ProcessEvent(WorldObject* /*unit*/, uint32 eventId)
+ void ProcessEvent(WorldObject* /*unit*/, uint32 eventId) OVERRIDE
{
if (eventId != EVENT_CALL_DRAGON)
return;
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
index 4b24e5a81fb..1230868c020 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
@@ -38,44 +38,45 @@ enum GossipNPCs
enum Drakes
{
-/*Ruby Drake,
-(npc 27756) (item 37860)
-(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756)
-*/
- SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464
- SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy
- SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets
- SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells.
- SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted.
- //you do not have acces to until you kill Mage-Lord Urom
- SPELL_RUBY_MARTYR = 50253, //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec.
-
-/*Amber Drake,
-(npc 27755) (item 37859)
-(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755)
-*/
- SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460
- SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy
- SPELL_AMBER_SHOCK_CHARGE = 49836,
- SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated.
- // SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target.
- //you do not have access to until you kill the Mage-Lord Urom.
- SPELL_AMBER_TEMPORAL_RIFT = 49592, //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15, 000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated.
-
-/*Emerald Drake,
-(npc 27692) (item 37815),
- (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692)
-*/
- SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346
- SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy
- SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times.
- SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25, 000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec.
+/*
+ * Ruby Drake (27756)
+ * (summoned by spell Ruby Essence (37860) --> Call Amber Drake (49462) --> Summon 27756)
+ */
+ SPELL_RIDE_RUBY_DRAKE_QUE = 49463, // Apply Aura: Periodic Trigger, Interval: 3 seconds --> 49464
+ SPELL_RUBY_DRAKE_SADDLE = 49464, // Allows you to ride on the back of an Amber Drake. --> Dummy
+ SPELL_RUBY_SEARING_WRATH = 50232, // (60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets
+ SPELL_RUBY_EVASIVE_AURA = 50248, // Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells.
+ SPELL_RUBY_EVASIVE_CHARGES = 50241,
+ SPELL_RUBY_EVASIVE_MANEUVERS = 50240, // Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted.
+ // you do not have acces to until you kill Mage-Lord Urom
+ SPELL_RUBY_MARTYR = 50253, // Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec.
+
+/*
+ * Amber Drake (27755)
+ * (summoned by spell Amber Essence (37859) --> Call Amber Drake (49461) --> Summon 27755)
+ */
+ SPELL_RIDE_AMBER_DRAKE_QUE = 49459, // Apply Aura: Periodic Trigger, Interval: 3 seconds --> 49460
+ SPELL_AMBER_DRAKE_SADDLE = 49460, // Allows you to ride on the back of an Amber Drake. --> Dummy
+ SPELL_AMBER_SHOCK_CHARGE = 49836,
+ SPELL_AMBER_SHOCK_LANCE = 49840, // (60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated.
+ SPELL_AMBER_STOP_TIME = 49838, // Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target.
+ // you do not have access to until you kill the Mage-Lord Urom.
+ SPELL_AMBER_TEMPORAL_RIFT = 49592, // (60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15, 000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated.
+
+/*
+ * Emerald Drake (27692)
+ * (summoned by spell Emerald Essence (37815) --> Call Emerald Drake (49345) --> Summon 27692)
+ */
+ SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, // Apply Aura: Periodic Trigger, Interval: 3 seconds --> 49346
+ SPELL_EMERALD_DRAKE_SADDLE = 49346, // Allows you to ride on the back of an Amber Drake. --> Dummy
+ SPELL_EMERALD_LEECHING_POISON = 50328, // (60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times.
+ SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, // (60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25, 000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec.
// you do not have access to until you kill the Mage-Lord Urom
- SPELL_EMERALD_DREAM_FUNNEL = 50344, //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels.
+ SPELL_EMERALD_DREAM_FUNNEL = 50344, // (60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels.
// Misc
- POINT_LAND = 2,
- POINT_TAKE_OFF = 3
+ POINT_LAND = 2,
+ POINT_TAKE_OFF = 3
};
enum DrakeEvents
@@ -432,6 +433,85 @@ class spell_oculus_ride_ruby_emerald_amber_drake_que : public SpellScriptLoader
}
};
+// 50240 - Evasive Maneuvers
+class spell_oculus_evasive_maneuvers : public SpellScriptLoader
+{
+ public:
+ spell_oculus_evasive_maneuvers() : SpellScriptLoader("spell_oculus_evasive_maneuvers") { }
+
+ class spell_oculus_evasive_maneuvers_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_oculus_evasive_maneuvers_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_RUBY_EVASIVE_CHARGES))
+ return false;
+ return true;
+ }
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
+ {
+ PreventDefaultAction();
+ GetTarget()->RemoveAuraFromStack(SPELL_RUBY_EVASIVE_CHARGES);
+ if (!GetTarget()->HasAura(SPELL_RUBY_EVASIVE_CHARGES))
+ Remove();
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectProc += AuraEffectProcFn(spell_oculus_evasive_maneuvers_AuraScript::HandleProc, EFFECT_2, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_oculus_evasive_maneuvers_AuraScript();
+ }
+};
+
+// 49840 - Shock Lance
+class spell_oculus_shock_lance : public SpellScriptLoader
+{
+ public:
+ spell_oculus_shock_lance() : SpellScriptLoader("spell_oculus_shock_lance") { }
+
+ class spell_oculus_shock_lance_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_oculus_shock_lance_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_AMBER_SHOCK_CHARGE))
+ return false;
+ return true;
+ }
+
+ void CalcDamage()
+ {
+ int32 damage = GetHitDamage();
+ if (Unit* target = GetHitUnit())
+ if (AuraEffect const* shockCharges = target->GetAuraEffect(SPELL_AMBER_SHOCK_CHARGE, EFFECT_0, GetCaster()->GetGUID()))
+ {
+ damage += shockCharges->GetAmount();
+ shockCharges->GetBase()->Remove();
+ }
+
+ SetHitDamage(damage);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnHit += SpellHitFn(spell_oculus_shock_lance_SpellScript::CalcDamage);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_oculus_shock_lance_SpellScript();
+ }
+};
+
// 49838 - Stop Time
class spell_oculus_stop_time : public SpellScriptLoader
{
@@ -457,7 +537,7 @@ class spell_oculus_stop_time : public SpellScriptLoader
Unit* target = GetTarget();
for (uint32 i = 0; i < 5; ++i)
- caster->CastSpell(target, SPELL_AMBER_SHOCK_CHARGE, false);
+ caster->CastSpell(target, SPELL_AMBER_SHOCK_CHARGE, true);
}
void Register() OVERRIDE
@@ -472,6 +552,51 @@ class spell_oculus_stop_time : public SpellScriptLoader
}
};
+// 49592 - Temporal Rift
+class spell_oculus_temporal_rift : public SpellScriptLoader
+{
+ public:
+ spell_oculus_temporal_rift() : SpellScriptLoader("spell_oculus_temporal_rift") { }
+
+ class spell_oculus_temporal_rift_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_oculus_temporal_rift_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_AMBER_SHOCK_CHARGE))
+ return false;
+ return true;
+ }
+
+ void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ int32 amount = aurEff->GetAmount() + eventInfo.GetDamageInfo()->GetDamage();
+
+ if (amount >= 15000)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(GetTarget(), SPELL_AMBER_SHOCK_CHARGE, true);
+ amount -= 15000;
+ }
+
+ const_cast<AuraEffect*>(aurEff)->SetAmount(amount);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectProc += AuraEffectProcFn(spell_oculus_temporal_rift_AuraScript::HandleProc, EFFECT_2, SPELL_AURA_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const OVERRIDE
+ {
+ return new spell_oculus_temporal_rift_AuraScript();
+ }
+};
+
+// 50341 - Touch the Nightmare
class spell_oculus_touch_the_nightmare : public SpellScriptLoader
{
public:
@@ -498,7 +623,8 @@ class spell_oculus_touch_the_nightmare : public SpellScriptLoader
}
};
-class spell_oculus_dream_funnel: public SpellScriptLoader
+// 50344 - Dream Funnel
+class spell_oculus_dream_funnel : public SpellScriptLoader
{
public:
spell_oculus_dream_funnel() : SpellScriptLoader("spell_oculus_dream_funnel") { }
@@ -535,7 +661,10 @@ void AddSC_oculus()
new npc_ruby_emerald_amber_drake();
new spell_oculus_call_ruby_emerald_amber_drake();
new spell_oculus_ride_ruby_emerald_amber_drake_que();
+ new spell_oculus_evasive_maneuvers();
+ new spell_oculus_shock_lance();
new spell_oculus_stop_time();
+ new spell_oculus_temporal_rift();
new spell_oculus_touch_the_nightmare();
new spell_oculus_dream_funnel();
}
diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
index 9ea3023de01..6587f0536b3 100644
--- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp
+++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
@@ -20,7 +20,9 @@
#include "ScriptedCreature.h"
#include "ScriptedEscortAI.h"
#include "Player.h"
+#include "Spell.h"
#include "SpellInfo.h"
+#include "SpellScript.h"
#include "CreatureTextMgr.h"
/*######
@@ -749,6 +751,43 @@ public:
}
};
+enum ShredderDelivery
+{
+ NPC_BROKEN_DOWN_SHREDDER = 27354
+};
+
+class spell_shredder_delivery : public SpellScriptLoader
+{
+ public:
+ spell_shredder_delivery() : SpellScriptLoader("spell_shredder_delivery") { }
+
+ class spell_shredder_delivery_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_shredder_delivery_SpellScript);
+
+ bool Load() OVERRIDE
+ {
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (GetCaster()->ToCreature()->GetEntry() == NPC_BROKEN_DOWN_SHREDDER)
+ GetCaster()->ToCreature()->DespawnOrUnsummon();
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_shredder_delivery_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_shredder_delivery_SpellScript();
+ }
+};
+
void AddSC_grizzly_hills()
{
new npc_emily();
@@ -759,4 +798,5 @@ void AddSC_grizzly_hills()
new npc_wounded_skirmisher();
new npc_venture_co_straggler();
new npc_lake_frog();
+ new spell_shredder_delivery();
}
diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp
index 671628e4cbc..fd5b0a5ca1c 100644
--- a/src/server/scripts/Northrend/zone_howling_fjord.cpp
+++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp
@@ -32,6 +32,8 @@ EndContentData */
#include "ScriptedGossip.h"
#include "ScriptedEscortAI.h"
#include "Player.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
/*######
## npc_apothecary_hanes
@@ -43,7 +45,8 @@ enum Entries
FACTION_ESCORTEE_H = 775,
NPC_HANES_FIRE_TRIGGER = 23968,
QUEST_TRAIL_OF_FIRE = 11241,
- SPELL_COSMETIC_LOW_POLY_FIRE = 56274
+ SPELL_COSMETIC_LOW_POLY_FIRE = 56274,
+ SPELL_HEALING_POTION = 17534
};
class npc_apothecary_hanes : public CreatureScript
@@ -92,7 +95,7 @@ public:
{
if (PotTimer <= diff)
{
- DoCast(me, 17534, true);
+ DoCast(me, SPELL_HEALING_POTION, true);
PotTimer = 10000;
} else PotTimer -= diff;
}
@@ -380,10 +383,107 @@ public:
}
};
+enum MindlessAbomination
+{
+ EVENT_CHECK_CHARMED = 1
+};
+
+class npc_mindless_abomination : public CreatureScript
+{
+public:
+ npc_mindless_abomination() : CreatureScript("npc_mindless_abomination") { }
+
+ struct npc_mindless_abominationAI : public ScriptedAI
+ {
+ npc_mindless_abominationAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() OVERRIDE
+ {
+ events.ScheduleEvent(EVENT_CHECK_CHARMED, 1000);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_CHECK_CHARMED:
+ if (!me->IsCharmedOwnedByPlayerOrPlayer())
+ me->DespawnOrUnsummon();
+ else
+ events.ScheduleEvent(EVENT_CHECK_CHARMED, 1000);
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_mindless_abominationAI(creature);
+ }
+};
+
+class spell_mindless_abomination_explosion_fx_master : public SpellScriptLoader
+{
+ enum Spells
+ {
+ SPELL_RANDOM_CIRCUMFERENCE_POINT_POISON = 42266,
+ SPELL_COSMETIC_BLOOD_EXPLOSION_GREEN_LARGE = 43401
+ };
+
+ public:
+ spell_mindless_abomination_explosion_fx_master() : SpellScriptLoader("spell_mindless_abomination_explosion_fx_master") { }
+
+ class spell_mindless_abomination_explosion_fx_master_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_mindless_abomination_explosion_fx_master_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_RANDOM_CIRCUMFERENCE_POINT_POISON) || !sSpellMgr->GetSpellInfo(SPELL_COSMETIC_BLOOD_EXPLOSION_GREEN_LARGE))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*eff*/)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ if (!caster)
+ return;
+
+ caster->AI()->DoCast(caster, SPELL_COSMETIC_BLOOD_EXPLOSION_GREEN_LARGE);
+
+ for (uint8 i = 0; i < 10; ++i)
+ caster->AI()->DoCast(caster, SPELL_RANDOM_CIRCUMFERENCE_POINT_POISON);
+
+ caster->DespawnOrUnsummon(4000);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_mindless_abomination_explosion_fx_master_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_mindless_abomination_explosion_fx_master_SpellScript();
+ }
+};
+
void AddSC_howling_fjord()
{
- new npc_apothecary_hanes;
- new npc_plaguehound_tracker;
- new npc_razael_and_lyana;
- new npc_daegarn;
+ new npc_apothecary_hanes();
+ new npc_plaguehound_tracker();
+ new npc_razael_and_lyana();
+ new npc_daegarn();
+ new npc_mindless_abomination();
+ new spell_mindless_abomination_explosion_fx_master();
}
diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index b20efa1c5a5..5c65be982e0 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -25,91 +25,6 @@
#include "CombatAI.h"
/*######
-## npc_arete
-######*/
-
-#define GOSSIP_ARETE_ITEM1 "Lord-Commander, I would hear your tale."
-#define GOSSIP_ARETE_ITEM2 "<You nod slightly but do not complete the motion as the Lord-Commander narrows his eyes before he continues.>"
-#define GOSSIP_ARETE_ITEM3 "I thought that they now called themselves the Scarlet Onslaught?"
-#define GOSSIP_ARETE_ITEM4 "Where did the grand admiral go?"
-#define GOSSIP_ARETE_ITEM5 "That's fine. When do I start?"
-#define GOSSIP_ARETE_ITEM6 "Let's finish this!"
-#define GOSSIP_ARETE_ITEM7 "That's quite a tale, Lord-Commander."
-
-enum Arete
-{
- GOSSIP_TEXTID_ARETE1 = 13525,
- GOSSIP_TEXTID_ARETE2 = 13526,
- GOSSIP_TEXTID_ARETE3 = 13527,
- GOSSIP_TEXTID_ARETE4 = 13528,
- GOSSIP_TEXTID_ARETE5 = 13529,
- GOSSIP_TEXTID_ARETE6 = 13530,
- GOSSIP_TEXTID_ARETE7 = 13531,
-
- QUEST_THE_STORY_THUS_FAR = 12807
-};
-
-class npc_arete : public CreatureScript
-{
-public:
- npc_arete() : CreatureScript("npc_arete") { }
-
- bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(QUEST_THE_STORY_THUS_FAR) == QUEST_STATUS_INCOMPLETE)
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE1, creature->GetGUID());
- return true;
- }
-
- 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();
- switch (action)
- {
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE2, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE3, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+3:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE4, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+4:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE5, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+5:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE6, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+6:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ARETE_ITEM7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
- player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ARETE7, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+7:
- player->CLOSE_GOSSIP_MENU();
- player->AreaExploredOrEventHappens(QUEST_THE_STORY_THUS_FAR);
- break;
- }
-
- return true;
- }
-};
-
-/*######
## npc_squire_david
######*/
@@ -1149,7 +1064,6 @@ class npc_morbidus : public CreatureScript
void AddSC_icecrown()
{
- new npc_arete;
new npc_squire_david;
new npc_argent_valiant;
new npc_guardian_pavilion;
diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp
index 77b85037a01..a0b6524bd89 100644
--- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp
+++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp
@@ -1082,6 +1082,57 @@ public:
}
};
+/*######
+## Quest Dreadsaber Mastery: Stalking the Prey (12550)
+######*/
+
+enum ShangoTracks
+{
+ SPELL_CORRECT_TRACKS = 52160,
+ SPELL_INCORRECT_TRACKS = 52163,
+ SAY_CORRECT_TRACKS = 28634,
+ SAY_INCORRECT_TRACKS = 28635
+};
+
+class spell_shango_tracks : public SpellScriptLoader
+{
+public:
+ spell_shango_tracks() : SpellScriptLoader("spell_shango_tracks") { }
+
+ class spell_shango_tracks_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_shango_tracks_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Player* player = GetHitUnit()->ToPlayer())
+ {
+ switch (GetSpellInfo()->Id)
+ {
+ case SPELL_CORRECT_TRACKS:
+ player->MonsterSay(sObjectMgr->GetTrinityStringForDBCLocale(SAY_CORRECT_TRACKS), LANG_UNIVERSAL, player->GetGUID());
+ break;
+ case SPELL_INCORRECT_TRACKS:
+ player->MonsterSay(sObjectMgr->GetTrinityStringForDBCLocale(SAY_INCORRECT_TRACKS), LANG_UNIVERSAL, player->GetGUID());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_shango_tracks_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_shango_tracks_SpellScript();
+ }
+};
+
void AddSC_sholazar_basin()
{
new npc_injured_rainspeaker_oracle();
@@ -1095,4 +1146,5 @@ void AddSC_sholazar_basin()
new spell_q12589_shoot_rjr();
new npc_haiphoon();
new npc_vics_flying_machine();
+ new spell_shango_tracks();
}
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 825981ba5c5..d08c60d373d 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -413,6 +413,181 @@ class npc_hyldsmeet_protodrake : public CreatureScript
}
};
+
+/*#####
+# npc_brann_bronzebeard for Quest 13285 "Forging the Keystone"
+#####*/
+
+enum BrannBronzebeard
+{
+ NPC_BRANN_BRONZEBEARD = 31810,
+ NPC_A_DISTANT_VOICE = 31814,
+ OBJECT_TOL_SIGNAL_1 = 193590,
+ OBJECT_TOL_SIGNAL_2 = 193591,
+ OBJECT_TOL_SIGNAL_3 = 193592,
+ OBJECT_TOL_SIGNAL_4 = 193593,
+ OBJECT_TOL_SIGNAL_5 = 193594,
+ SPELL_RESURRECTION = 58854,
+ SAY_BRANN_1 = 0,
+ SAY_BRANN_2 = 1,
+ SAY_BRANN_3 = 2,
+ SAY_VOICE_1 = 0,
+ SAY_VOICE_2 = 1,
+ SAY_VOICE_3 = 2,
+ SAY_VOICE_4 = 3,
+ SAY_VOICE_5 = 4,
+
+ EVENT_SCRIPT_1 = 1,
+ EVENT_SCRIPT_2 = 2,
+ EVENT_SCRIPT_3 = 3,
+ EVENT_SCRIPT_4 = 4,
+ EVENT_SCRIPT_5 = 5,
+ EVENT_SCRIPT_6 = 6,
+ EVENT_SCRIPT_7 = 7,
+ EVENT_SCRIPT_8 = 8,
+ EVENT_SCRIPT_9 = 9,
+ EVENT_SCRIPT_10 = 10,
+ EVENT_SCRIPT_11 = 11,
+ EVENT_SCRIPT_12 = 12,
+ EVENT_SCRIPT_13 = 13
+};
+
+class npc_brann_bronzebeard_keystone : public CreatureScript
+{
+public:
+ npc_brann_bronzebeard_keystone() : CreatureScript("npc_brann_bronzebeard_keystone") { }
+
+ struct npc_brann_bronzebeard_keystoneAI : public ScriptedAI
+ {
+ npc_brann_bronzebeard_keystoneAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() OVERRIDE
+ {
+ memset(&objectGUID, 0, sizeof(objectGUID));
+ playerGUID = 0;
+ voiceGUID = 0;
+ objectCounter = 0;
+ }
+
+ void sGossipSelect(Player* player, uint32 /*sender*/, uint32 /*action*/) OVERRIDE
+ {
+ player->CLOSE_GOSSIP_MENU();
+ playerGUID = player->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_1, 100);
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SCRIPT_1:
+ Talk(SAY_BRANN_1, playerGUID);
+ me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
+ if (Creature* voice = me->SummonCreature(NPC_A_DISTANT_VOICE, 7863.43f, -1396.585f, 1538.076f, 2.949606f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 49000))
+ voiceGUID = voice->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_2, 4000);
+ break;
+ case EVENT_SCRIPT_2:
+ me->SetWalk(true);
+ me->GetMotionMaster()->MovePoint(0, 7861.488f, -1396.376f, 1534.059f, false);
+ events.ScheduleEvent(EVENT_SCRIPT_3, 6000);
+ break;
+ case EVENT_SCRIPT_3:
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_WORK_MINING);
+ events.ScheduleEvent(EVENT_SCRIPT_4, 6000);
+ break;
+ case EVENT_SCRIPT_4:
+ me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID))
+ {
+ voice->AI()->DoCast(voice, SPELL_RESURRECTION);
+ voice->AI()->Talk(SAY_VOICE_1, playerGUID);
+ }
+ if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_1, 7860.273f, -1383.622f, 1538.302f, -1.658062f, 0, 0, -0.737277f, 0.6755905f, 0))
+ objectGUID[objectCounter++] = go->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_5, 6000);
+ break;
+ case EVENT_SCRIPT_5:
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID))
+ voice->AI()->Talk(SAY_VOICE_2, playerGUID);
+ if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_2, 7875.67f, -1387.266f, 1538.323f, -2.373644f, 0, 0, -0.9271832f, 0.3746083f, 0))
+ objectGUID[objectCounter++] = go->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_6, 6000);
+ break;
+ case EVENT_SCRIPT_6:
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID))
+ voice->AI()->Talk(SAY_VOICE_3, playerGUID);
+ if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_3, 7879.212f, -1401.175f, 1538.279f, 2.967041f, 0, 0, 0.9961939f, 0.08716504f, 0))
+ objectGUID[objectCounter++] = go->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_7, 6000);
+ break;
+ case EVENT_SCRIPT_7:
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID))
+ voice->AI()->Talk(SAY_VOICE_4, playerGUID);
+ if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_4, 7868.944f, -1411.18f, 1538.213f, 2.111848f, 0, 0, 0.8703556f, 0.4924237f, 0))
+ objectGUID[objectCounter++] = go->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_8, 6000);
+ break;
+ case EVENT_SCRIPT_8:
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID))
+ voice->AI()->Talk(SAY_VOICE_5, playerGUID);
+ if (GameObject* go = me->SummonGameObject(OBJECT_TOL_SIGNAL_5, 7855.11f, -1406.839f, 1538.42f, 1.151916f, 0, 0, 0.5446386f, 0.8386708f, 0))
+ objectGUID[objectCounter] = go->GetGUID();
+ events.ScheduleEvent(EVENT_SCRIPT_9, 6000);
+ break;
+ case EVENT_SCRIPT_9:
+ if (Creature* voice = ObjectAccessor::GetCreature(*me, voiceGUID))
+ voice->AI()->DoCast(voice, SPELL_RESURRECTION);
+ events.ScheduleEvent(EVENT_SCRIPT_10, 6000);
+ break;
+ case EVENT_SCRIPT_10:
+ Talk(SAY_BRANN_2, playerGUID);
+ if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID))
+ player->KilledMonsterCredit(me->GetEntry());
+ events.ScheduleEvent(EVENT_SCRIPT_11, 6000);
+ break;
+ case EVENT_SCRIPT_11:
+ me->SetOrientation(2.932153f);
+ me->SendMovementFlagUpdate(true);
+ Talk(SAY_BRANN_3, playerGUID);
+ for (uint8 i = 0; i < 5; ++i)
+ {
+ if (GameObject* go = ObjectAccessor::GetGameObject(*me, objectGUID[i]))
+ go->Delete();
+ }
+ events.ScheduleEvent(EVENT_SCRIPT_12, 6000);
+ break;
+ case EVENT_SCRIPT_12:
+ me->GetMotionMaster()->Clear();
+ me->SetWalk(false);
+ me->GetMotionMaster()->MovePoint(0, 7799.908f, -1413.561f, 1534.829f, false);
+ events.ScheduleEvent(EVENT_SCRIPT_13, 10000);
+ break;
+ case EVENT_SCRIPT_13:
+ me->DisappearAndDie();
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ uint64 playerGUID;
+ uint64 objectGUID[5];
+ uint64 voiceGUID;
+ uint8 objectCounter;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_brann_bronzebeard_keystoneAI(creature);
+ }
+};
+
enum CloseRift
{
SPELL_DESPAWN_RIFT = 61665
@@ -467,7 +642,11 @@ class spell_close_rift : public SpellScriptLoader
enum JokkumScriptcast
{
SPELL_JOKKUM_KILL_CREDIT = 56545,
- SPELL_JOKKUM_SUMMON = 56541
+ SPELL_JOKKUM_SUMMON = 56541,
+ SPELL_RIDE_JOKKUM = 56606,
+ NPC_KINGJOKKUM = 30331,
+ SAY_HOLD_ON = 0,
+ PATH_JOKKUM = 2072200
};
class spell_jokkum_scriptcast : public SpellScriptLoader
@@ -491,6 +670,17 @@ class spell_jokkum_scriptcast : public SpellScriptLoader
{
player->CastSpell(player, SPELL_JOKKUM_KILL_CREDIT, true);
player->CastSpell(player, SPELL_JOKKUM_SUMMON, true);
+
+ if (Creature* kingjokkum = GetClosestCreatureWithEntry(player, NPC_KINGJOKKUM, 10.0f))
+ {
+ kingjokkum->setFaction(player->getFaction());
+ player->CastSpell(kingjokkum, SPELL_RIDE_JOKKUM, true);
+ player->SetUInt64Value(PLAYER_FARSIGHT, player->GetGUID());
+ kingjokkum->AI()->Talk(0, player->GetGUID());
+ kingjokkum->ToPlayer()->SetClientControl(kingjokkum, 1);
+ kingjokkum->GetMotionMaster()->MovePath(PATH_JOKKUM, false);
+ kingjokkum->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
+ }
}
}
@@ -514,6 +704,7 @@ void AddSC_storm_peaks()
new npc_freed_protodrake();
new npc_icefang();
new npc_hyldsmeet_protodrake();
+ new npc_brann_bronzebeard_keystone();
new spell_close_rift();
new spell_jokkum_scriptcast();
}
diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp
index 29d7c017748..1137c86f287 100644
--- a/src/server/scripts/Northrend/zone_zuldrak.cpp
+++ b/src/server/scripts/Northrend/zone_zuldrak.cpp
@@ -57,16 +57,15 @@ public:
float x, y, z;
me->GetClosePoint(x, y, z, me->GetObjectSize() / 3, 0.1f);
- if (Unit* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000))
+ if (Creature* summon = me->SummonCreature(NPC_RAGECLAW, x, y, z, 0, TEMPSUMMON_DEAD_DESPAWN, 1000))
{
_rageclawGUID = summon->GetGUID();
- LockRageclaw();
+ LockRageclaw(summon);
}
}
- void LockRageclaw()
+ void LockRageclaw(Creature* rageclaw)
{
- Unit* rageclaw = Unit::GetCreature(*me, _rageclawGUID);
// pointer check not needed
me->SetInFront(rageclaw);
rageclaw->SetInFront(me);
@@ -75,12 +74,11 @@ public:
DoCast(rageclaw, SPELL_RIGHT_CHAIN, true);
}
- void UnlockRageclaw(Unit* who)
+ void UnlockRageclaw(Unit* who, Creature* rageclaw)
{
if (!who)
return;
- Creature* rageclaw = Unit::GetCreature(*me, _rageclawGUID);
// pointer check not needed
DoCast(rageclaw, SPELL_FREE_RAGECLAW, true);
@@ -95,7 +93,7 @@ public:
{
if (Creature* rageclaw = Unit::GetCreature(*me, _rageclawGUID))
{
- UnlockRageclaw(caster);
+ UnlockRageclaw(caster, rageclaw);
caster->ToPlayer()->KilledMonster(rageclaw->GetCreatureTemplate(), _rageclawGUID);
me->DespawnOrUnsummon();
}
@@ -459,6 +457,8 @@ public:
void Reset() OVERRIDE
{
+ _playerGUID = 0;
+ _getingredienttry = 0;
_events.ScheduleEvent(EVENT_TURN_TO_POT, urand(15000, 26000));
}
diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
index 4f7ac113547..783e7b9f09b 100644
--- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
+++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp
@@ -68,6 +68,7 @@ public:
void Reset() OVERRIDE
{
+ myClass = CLASS_NONE;
Class_Timer = 1000;
}
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp
index b5947e93216..36377b4d715 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_dalliah_the_doomsayer.cpp
@@ -72,7 +72,7 @@ class boss_dalliah_the_doomsayer : public CreatureScript
_JustDied();
Talk(SAY_DEATH);
- if (Creature* soccothrates = ObjectAccessor::GetCreature(*me, soccothratesGUID))
+ if (Creature* soccothrates = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SOCCOTHRATES)))
if (soccothrates->IsAlive() && !soccothrates->IsInCombat())
soccothrates->AI()->SetData(1, 1);
}
@@ -86,9 +86,6 @@ class boss_dalliah_the_doomsayer : public CreatureScript
events.ScheduleEvent(EVENT_SHADOW_WAVE, urand(11000, 16000));
events.ScheduleEvent(EVENT_ME_FIRST, 6000);
Talk(SAY_AGGRO);
-
- if (Creature* soccothrates = me->FindNearestCreature(NPC_SOCCOTHRATES, 100.0f, true))
- soccothratesGUID = soccothrates->GetGUID();
}
void KilledUnit(Unit* /*victim*/) OVERRIDE
@@ -161,7 +158,7 @@ class boss_dalliah_the_doomsayer : public CreatureScript
events.ScheduleEvent(EVENT_SHADOW_WAVE, urand(11000, 16000));
break;
case EVENT_ME_FIRST:
- if (Creature* soccothrates = ObjectAccessor::GetCreature(*me, soccothratesGUID))
+ if (Creature* soccothrates = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SOCCOTHRATES)))
if (soccothrates->IsAlive() && !soccothrates->IsInCombat())
soccothrates->AI()->Talk(SAY_AGGRO_DALLIAH_FIRST);
break;
@@ -172,7 +169,7 @@ class boss_dalliah_the_doomsayer : public CreatureScript
if (HealthBelowPct(25) && !soccothratesTaunt)
{
- if (Creature* soccothrates = ObjectAccessor::GetCreature(*me, soccothratesGUID))
+ if (Creature* soccothrates = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SOCCOTHRATES)))
soccothrates->AI()->Talk(SAY_DALLIAH_25_PERCENT);
soccothratesTaunt = true;
}
@@ -180,15 +177,14 @@ class boss_dalliah_the_doomsayer : public CreatureScript
DoMeleeAttackIfReady();
}
- private:
- bool soccothratesTaunt;
- bool soccothratesDeath;
- uint64 soccothratesGUID;
+ private:
+ bool soccothratesTaunt;
+ bool soccothratesDeath;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- return new boss_dalliah_the_doomsayerAI(creature);
+ return GetArcatrazAI<boss_dalliah_the_doomsayerAI>(creature);
}
};
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp
index 046ef93bf10..2d9bfc92583 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_wrath_scryer_soccothrates.cpp
@@ -98,7 +98,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
_JustDied();
Talk(SAY_DEATH);
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
if (dalliah->IsAlive() && !dalliah->IsInCombat())
dalliah->AI()->SetData(1, 1);
}
@@ -120,20 +120,13 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
void MoveInLineOfSight(Unit* who) OVERRIDE
{
- if (instance)
+ if (instance->GetData(DATA_CONVERSATION) == NOT_STARTED && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 70.0f))
{
- if (instance->GetData(DATA_CONVERSATION) == NOT_STARTED && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 70.0f))
- {
- Talk(SAY_SOCCOTHRATES_CONVO_1);
- instance->SetData(DATA_CONVERSATION, DONE);
+ Talk(SAY_SOCCOTHRATES_CONVO_1);
+ instance->SetData(DATA_CONVERSATION, DONE);
- if (Creature* dalliah = me->FindNearestCreature(NPC_DALLIAH, 50.0f, true))
- {
- dalliahGUID = dalliah->GetGUID();
- preFight = true;
- events.ScheduleEvent(EVENT_PREFIGHT_1, 2000);
- }
- }
+ preFight = true;
+ events.ScheduleEvent(EVENT_PREFIGHT_1, 2000);
}
}
@@ -163,7 +156,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
switch (eventId)
{
case EVENT_PREFIGHT_1:
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
dalliah->AI()->Talk(SAY_DALLIAH_CONVO_1);
events.ScheduleEvent(EVENT_PREFIGHT_2, 3000);
break;
@@ -172,7 +165,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
events.ScheduleEvent(EVENT_PREFIGHT_3, 3000);
break;
case EVENT_PREFIGHT_3:
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
dalliah->AI()->Talk(SAY_DALLIAH_CONVO_2);
events.ScheduleEvent(EVENT_PREFIGHT_4, 6000);
break;
@@ -181,7 +174,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
events.ScheduleEvent(EVENT_PREFIGHT_5, 2000);
break;
case EVENT_PREFIGHT_5:
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
dalliah->AI()->Talk(SAY_DALLIAH_CONVO_3);
events.ScheduleEvent(EVENT_PREFIGHT_6, 3000);
break;
@@ -190,7 +183,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
events.ScheduleEvent(EVENT_PREFIGHT_7, 2000);
break;
case EVENT_PREFIGHT_7:
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
dalliah->GetMotionMaster()->MovePoint(0, 118.6048f, 96.84852f, 22.44115f);
events.ScheduleEvent(EVENT_PREFIGHT_8, 4000);
break;
@@ -199,7 +192,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
events.ScheduleEvent(EVENT_PREFIGHT_9, 4000);
break;
case EVENT_PREFIGHT_9:
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
{
dalliah->SetFacingToObject(me);
me->SetFacingToObject(dalliah);
@@ -253,7 +246,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
events.ScheduleEvent(EVENT_KNOCK_AWAY, urand(11000, 12000));
break;
case EVENT_ME_FIRST:
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
if (dalliah->IsAlive() && !dalliah->IsInCombat())
dalliah->AI()->Talk(SAY_AGGRO_SOCCOTHRATES_FIRST);
break;
@@ -264,7 +257,7 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
if (HealthBelowPct(25) && !dalliahTaunt)
{
- if (Creature* dalliah = ObjectAccessor::GetCreature(*me, dalliahGUID))
+ if (Creature* dalliah = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALLIAH)))
dalliah->AI()->Talk(SAY_SOCCOTHRATES_25_PERCENT);
dalliahTaunt = true;
}
@@ -272,16 +265,15 @@ class boss_wrath_scryer_soccothrates : public CreatureScript
DoMeleeAttackIfReady();
}
- private:
- bool preFight;
- bool dalliahTaunt;
- bool dalliahDeath;
- uint64 dalliahGUID;
+ private:
+ bool preFight;
+ bool dalliahTaunt;
+ bool dalliahDeath;
};
CreatureAI* GetAI(Creature* creature) const OVERRIDE
{
- return new boss_wrath_scryer_soccothratesAI(creature);
+ return GetArcatrazAI<boss_wrath_scryer_soccothratesAI>(creature);
}
};
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp
index 0145636f9d2..cb7cd3828e2 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/instance_arcatraz.cpp
@@ -38,6 +38,8 @@ class instance_arcatraz : public InstanceMapScript
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
+ DalliahGUID = 0;
+ SoccothratesGUID = 0;
MellicharGUID = 0;
WardensShieldGUID = 0;
@@ -49,8 +51,20 @@ class instance_arcatraz : public InstanceMapScript
void OnCreatureCreate(Creature* creature) OVERRIDE
{
- if (creature->GetEntry() == NPC_MELLICHAR)
- MellicharGUID = creature->GetGUID();
+ switch (creature->GetEntry())
+ {
+ case NPC_DALLIAH:
+ DalliahGUID = creature->GetGUID();
+ break;
+ case NPC_SOCCOTHRATES:
+ SoccothratesGUID = creature->GetGUID();
+ break;
+ case NPC_MELLICHAR:
+ MellicharGUID = creature->GetGUID();
+ break;
+ default:
+ break;
+ }
}
void OnGameObjectCreate(GameObject* go) OVERRIDE
@@ -102,29 +116,13 @@ class instance_arcatraz : public InstanceMapScript
switch (type)
{
case DATA_WARDEN_1:
- if (data == IN_PROGRESS)
- HandleGameObject(StasisPodGUIDs[0], true);
- StasisPodStates[0] = uint8(data);
- break;
case DATA_WARDEN_2:
- if (data == IN_PROGRESS)
- HandleGameObject(StasisPodGUIDs[1], true);
- StasisPodStates[1] = uint8(data);
- break;
case DATA_WARDEN_3:
- if (data == IN_PROGRESS)
- HandleGameObject(StasisPodGUIDs[2], true);
- StasisPodStates[2] = uint8(data);
- break;
case DATA_WARDEN_4:
- if (data == IN_PROGRESS)
- HandleGameObject(StasisPodGUIDs[3], true);
- StasisPodStates[3] = uint8(data);
- break;
case DATA_WARDEN_5:
if (data == IN_PROGRESS)
- HandleGameObject(StasisPodGUIDs[4], true);
- StasisPodStates[4] = uint8(data);
+ HandleGameObject(StasisPodGUIDs[type - DATA_WARDEN_1], true);
+ StasisPodStates[type - DATA_WARDEN_1] = uint8(data);
break;
case DATA_CONVERSATION:
ConversationState = uint8(data);
@@ -156,6 +154,10 @@ class instance_arcatraz : public InstanceMapScript
{
switch (data)
{
+ case DATA_DALLIAH:
+ return DalliahGUID;
+ case DATA_SOCCOTHRATES:
+ return SoccothratesGUID;
case DATA_MELLICHAR:
return MellicharGUID;
case DATA_WARDENS_SHIELD:
@@ -233,6 +235,8 @@ class instance_arcatraz : public InstanceMapScript
}
protected:
+ uint64 DalliahGUID;
+ uint64 SoccothratesGUID;
uint64 StasisPodGUIDs[5];
uint64 MellicharGUID;
uint64 WardensShieldGUID;
diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
index a005153a4fc..167fd7f2074 100644
--- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
+++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp
@@ -19,7 +19,7 @@
/* ScriptData
SDName: Blades_Edge_Mountains
SD%Complete: 90
-SDComment: Quest support: 10503, 10504, 10556, 10609, 10682, 10821, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete)
+SDComment: Quest support: 10503, 10504, 10556, 10594, 10609, 10682, 10821, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete)
SDCategory: Blade's Edge Mountains
EndScriptData */
@@ -40,6 +40,10 @@ EndContentData */
#include "GridNotifiersImpl.h"
#include "Cell.h"
#include "CellImpl.h"
+#include "SpellInfo.h"
+#include "SpellScript.h"
+#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
//Support for quest: You're Fired! (10821)
bool obelisk_one, obelisk_two, obelisk_three, obelisk_four, obelisk_five;
@@ -1143,6 +1147,99 @@ class go_apexis_relic : public GameObjectScript
}
};
+/*######
+## npc_oscillating_frequency_scanner_master_bunny used for quest 10594 "Gauging the Resonant Frequency"
+######*/
+
+enum ScannerMasterBunny
+{
+ NPC_OSCILLATING_FREQUENCY_SCANNER_TOP_BUNNY = 21759,
+ SPELL_OSCILLATION_FIELD = 37408,
+ QUEST_GAUGING_THE_RESONANT_FREQUENCY = 10594
+};
+
+class npc_oscillating_frequency_scanner_master_bunny : public CreatureScript
+{
+public:
+ npc_oscillating_frequency_scanner_master_bunny() : CreatureScript("npc_oscillating_frequency_scanner_master_bunny") { }
+
+ struct npc_oscillating_frequency_scanner_master_bunnyAI : public ScriptedAI
+ {
+ npc_oscillating_frequency_scanner_master_bunnyAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() OVERRIDE
+ {
+ if (GetClosestCreatureWithEntry(me, NPC_OSCILLATING_FREQUENCY_SCANNER_TOP_BUNNY, 25.0f))
+ me->DespawnOrUnsummon();
+ else
+ {
+ // Spell 37392 does not exist in dbc, manually spawning
+ me->SummonCreature(21759, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 0.5f, me->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 50000);
+ me->SummonGameObject(184926, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), 0, 0, 0, 0, 50000);
+ me->DespawnOrUnsummon(50000);
+ }
+
+ timer = 500;
+ }
+
+ void IsSummonedBy(Unit* summoner) OVERRIDE
+ {
+ if (summoner->isType(TYPEMASK_PLAYER))
+ playerGuid = summoner->GetGUID();
+ }
+
+ void UpdateAI(uint32 diff) OVERRIDE
+ {
+ if (timer <= diff)
+ {
+ if (Player* player = ObjectAccessor::GetPlayer(*me, playerGuid))
+ DoCast(player, SPELL_OSCILLATION_FIELD);
+
+ timer = 3000;
+ }
+ else
+ timer -= diff;
+ }
+
+ private:
+ uint64 playerGuid;
+ uint32 timer;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const OVERRIDE
+ {
+ return new npc_oscillating_frequency_scanner_master_bunnyAI(creature);
+ }
+};
+
+class spell_oscillating_field : public SpellScriptLoader
+{
+ public:
+ spell_oscillating_field() : SpellScriptLoader("spell_oscillating_field") { }
+
+ class spell_oscillating_field_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_oscillating_field_SpellScript);
+
+ void HandleEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (Player* player = GetHitPlayer())
+ if (player->GetAuraCount(SPELL_OSCILLATION_FIELD) == 5 && player->GetQuestStatus(QUEST_GAUGING_THE_RESONANT_FREQUENCY) == QUEST_STATUS_INCOMPLETE)
+ player->CompleteQuest(QUEST_GAUGING_THE_RESONANT_FREQUENCY);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_oscillating_field_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_oscillating_field_SpellScript();
+ }
+};
+
void AddSC_blades_edge_mountains()
{
new npc_bladespire_ogre();
@@ -1157,4 +1254,6 @@ void AddSC_blades_edge_mountains()
new npc_simon_bunny();
new go_simon_cluster();
new go_apexis_relic();
+ new npc_oscillating_frequency_scanner_master_bunny();
+ new spell_oscillating_field();
}
diff --git a/src/server/shared/Cryptography/HMACSHA1.cpp b/src/server/shared/Cryptography/HMACSHA1.cpp
index c6c49f14a8e..2585fa64ea1 100644
--- a/src/server/shared/Cryptography/HMACSHA1.cpp
+++ b/src/server/shared/Cryptography/HMACSHA1.cpp
@@ -24,6 +24,7 @@ HmacHash::HmacHash(uint32 len, uint8 *seed)
{
HMAC_CTX_init(&m_ctx);
HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL);
+ memset(m_digest, 0, sizeof(m_digest));
}
HmacHash::~HmacHash()
diff --git a/src/server/shared/DataStores/DBCFileLoader.cpp b/src/server/shared/DataStores/DBCFileLoader.cpp
index 0aa94f1d14a..3c02d5f533d 100644
--- a/src/server/shared/DataStores/DBCFileLoader.cpp
+++ b/src/server/shared/DataStores/DBCFileLoader.cpp
@@ -23,7 +23,7 @@
#include "DBCFileLoader.h"
#include "Errors.h"
-DBCFileLoader::DBCFileLoader() : fieldsOffset(NULL), data(NULL), stringTable(NULL) { }
+DBCFileLoader::DBCFileLoader() : recordSize(0), recordCount(0), fieldCount(0), stringSize(0), fieldsOffset(NULL), data(NULL), stringTable(NULL) { }
bool DBCFileLoader::Load(const char* filename, const char* fmt)
{
diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt
index e48197aeb2c..99ea60ba76f 100644
--- a/src/server/worldserver/CMakeLists.txt
+++ b/src/server/worldserver/CMakeLists.txt
@@ -70,7 +70,6 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/game/Addons
${CMAKE_SOURCE_DIR}/src/server/game/AI
${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI
- ${CMAKE_SOURCE_DIR}/src/server/game/AI/EventAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI
${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts
${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse
diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp
index ffeeafc8951..3fcd4c28f0f 100644
--- a/src/server/worldserver/Master.cpp
+++ b/src/server/worldserver/Master.cpp
@@ -86,7 +86,12 @@ private:
uint32 _lastChange;
uint32 _delaytime;
public:
- FreezeDetectorRunnable() { _delaytime = 0; }
+ FreezeDetectorRunnable()
+ {
+ _loops = 0;
+ _lastChange = 0;
+ _delaytime = 0;
+ }
void SetDelayTime(uint32 t) { _delaytime = t; }