diff options
Diffstat (limited to 'src')
24 files changed, 429 insertions, 748 deletions
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 143cb1f0ec1..de263fafdea 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -32,6 +32,7 @@ #include "SmartAI.h" #include "Group.h" #include "Vehicle.h" +#include "ScriptedGossip.h" SmartScript::SmartScript() { @@ -1323,7 +1324,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (IsCreature(*itr)) (*itr)->ToCreature()->Respawn(); else if (IsGameObject(*itr)) - (*itr)->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.GoRespawnTime); + (*itr)->ToGameObject()->SetRespawnTime(e.action.RespawnTarget.goRespawnTime); } delete targets; @@ -1784,6 +1785,29 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); break; } + case SMART_ACTION_SEND_GOSSIP_MENU: + { + sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SEND_GOSSIP_MENU: gossipMenuId %d, gossip_option_id %d", + e.action.sendGossipMenu.gossipMenuId, e.action.sendGossipMenu.gossipOptionId); + + ObjectList* targets = GetTargets(e, unit); + if (!targets) + return; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if(Player* player = (*itr)->ToPlayer()) + { + if (e.action.sendGossipMenu.gossipMenuId) + player->PrepareGossipMenu(GetBaseObject(), e.action.sendGossipMenu.gossipMenuId, true); + else + player->PlayerTalkClass->ClearMenus(); + + player->SEND_GOSSIP_MENU(e.action.sendGossipMenu.gossipOptionId, GetBaseObject()->GetGUID()); + } + + delete targets; + break; + } default: sLog->outErrorDb("SmartScript::ProcessAction: Unhandled Action type %u", e.GetActionType()); break; @@ -2608,6 +2632,19 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff) if (e.timer < diff) { + // delay spell cast event if another spell is being casted + if (e.GetActionType() == SMART_ACTION_CAST) + { + if (!(e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)) + { + if (me && me->HasUnitState(UNIT_STAT_CASTING)) + { + e.timer = 1; + return; + } + } + } + e.active = true;//activate events with cooldown switch (e.GetEventType())//process ONLY timed events { diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 03d04f4b3df..7ebe8ca500f 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -222,7 +222,7 @@ class SmartScript } void DecPhase(int32 p = 1) { mEventPhase -= (mEventPhase < (uint32)p ? (uint32)p - mEventPhase : (uint32)p); } - bool IsInPhase(uint32 p) const { return mEventPhase & p; } + bool IsInPhase(uint32 p) const { return (1 << (mEventPhase - 1)) & p; } void SetPhase(uint32 p = 0) { mEventPhase = p; } SmartAIEventList mEvents; diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index fab2a6b7722..b1516916760 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -775,6 +775,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_ADD_DYNAMIC_FLAG: case SMART_ACTION_REMOVE_DYNAMIC_FLAG: case SMART_ACTION_JUMP_TO_POS: + case SMART_ACTION_SEND_GOSSIP_MENU: break; default: sLog->outErrorDb("SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 327d03d31ff..a37b95fd035 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -450,20 +450,17 @@ enum SMART_ACTION SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST = 87, // script9 ids 1-9 SMART_ACTION_CALL_RANDOM_RANGE_TIMED_ACTIONLIST = 88, // script9 id min, max SMART_ACTION_RANDOM_MOVE = 89, // maxDist - SMART_ACTION_SET_UNIT_FIELD_BYTES_1 = 90, // bytes, target SMART_ACTION_REMOVE_UNIT_FIELD_BYTES_1 = 91, // bytes, target - SMART_ACTION_INTERRUPT_SPELL = 92, - SMART_ACTION_SEND_GO_CUSTOM_ANIM = 93, // anim id - SMART_ACTION_SET_DYNAMIC_FLAG = 94, // Flags SMART_ACTION_ADD_DYNAMIC_FLAG = 95, // Flags SMART_ACTION_REMOVE_DYNAMIC_FLAG = 96, // Flags SMART_ACTION_JUMP_TO_POS = 97, // speedXY, speedZ, targetX, targetY, targetZ + SMART_ACTION_SEND_GOSSIP_MENU = 98, // menuId, optionId - SMART_ACTION_END = 98, + SMART_ACTION_END = 99, }; struct SmartAction @@ -859,8 +856,14 @@ struct SmartAction struct { - uint32 GoRespawnTime; + uint32 goRespawnTime; } RespawnTarget; + + struct + { + uint32 gossipMenuId; + uint32 gossipOptionId; + } sendGossipMenu; struct { diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 8dd5e17f550..9dda89a6972 100755 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -1859,6 +1859,12 @@ bool ChatHandler::HandleDamageCommand(const char * args) return false; } + if (target->GetTypeId() == TYPEID_PLAYER) + { + if (HasLowerSecurity((Player*)target, 0, false)) + return false; + } + if (!target->isAlive()) return true; @@ -2671,7 +2677,7 @@ bool ChatHandler::HandleResetAllCommand(const char * args) CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'", atLogin, atLogin); - ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, *HashMapHolder<Player>::GetLock(), true); + ACE_READ_GUARD_RETURN(HashMapHolder<Player>::LockType, guard, *HashMapHolder<Player>::GetLock(), true); HashMapHolder<Player>::MapType const& plist = sObjectAccessor->GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) itr->second->SetAtLoginFlag(atLogin); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index e7d4e69a247..dc70781a0f3 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1595,7 +1595,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe static uint32 const BOSS_LEVEL = 83; static float const BOSS_RESISTANCE_CONSTANT = 510.0f; - uint32 level = getLevel(); + uint32 level = victim->getLevel(); float resistanceConstant = 0.0f; if (level == BOSS_LEVEL) diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index 306d19d2001..84d27efc8d9 100755 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -165,9 +165,9 @@ Unit* ObjectAccessor::FindUnit(uint64 guid) Player* ObjectAccessor::FindPlayerByName(const char* name) { - ACE_GUARD_RETURN(LockType, g, *HashMapHolder<Player>::GetLock(), NULL); - HashMapHolder<Player>::MapType& m = HashMapHolder<Player>::GetContainer(); - for (HashMapHolder<Player>::MapType::iterator iter = m.begin(); iter != m.end(); ++iter) + ACE_READ_GUARD_RETURN(HashMapHolder<Player>::LockType, g, *HashMapHolder<Player>::GetLock(), NULL); + HashMapHolder<Player>::MapType const& m = GetPlayers(); + for (HashMapHolder<Player>::MapType::const_iterator iter = m.begin(); iter != m.end(); ++iter) if (iter->second->IsInWorld() && strcmp(name, iter->second->GetName()) == 0) return iter->second; @@ -176,9 +176,9 @@ Player* ObjectAccessor::FindPlayerByName(const char* name) void ObjectAccessor::SaveAllPlayers() { - ACE_GUARD(LockType, g, *HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType& m = HashMapHolder<Player>::GetContainer(); - for (HashMapHolder<Player>::MapType::iterator itr = m.begin(); itr != m.end(); ++itr) + ACE_READ_GUARD(HashMapHolder<Player>::LockType, g, *HashMapHolder<Player>::GetLock()); + HashMapHolder<Player>::MapType const& m = GetPlayers(); + for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) itr->second->SaveToDB(); } @@ -380,7 +380,7 @@ void ObjectAccessor::UnloadAll() /// Define the static members of HashMapHolder template <class T> UNORDERED_MAP< uint64, T* > HashMapHolder<T>::m_objectMap; -template <class T> ACE_Thread_Mutex HashMapHolder<T>::i_lock; +template <class T> typename HashMapHolder<T>::LockType HashMapHolder<T>::i_lock; /// Global definitions for the hashmap storage diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index 4ffe27b19d8..ae88ae3673f 100755 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -48,23 +48,23 @@ class HashMapHolder public: typedef UNORDERED_MAP<uint64, T*> MapType; - typedef ACE_Thread_Mutex LockType; + typedef ACE_RW_Thread_Mutex LockType; static void Insert(T* o) { - ACE_GUARD(LockType, Guard, i_lock); + ACE_WRITE_GUARD(LockType, Guard, i_lock); m_objectMap[o->GetGUID()] = o; } static void Remove(T* o) { - ACE_GUARD(LockType, Guard, i_lock); + ACE_WRITE_GUARD(LockType, Guard, i_lock); m_objectMap.erase(o->GetGUID()); } static T* Find(uint64 guid) { - ACE_GUARD_RETURN(LockType, Guard, i_lock, NULL); + ACE_READ_GUARD_RETURN(LockType, Guard, i_lock, NULL); typename MapType::iterator itr = m_objectMap.find(guid); return (itr != m_objectMap.end()) ? itr->second : NULL; } @@ -198,22 +198,22 @@ class ObjectAccessor Player* FindPlayerByName(const char* name); // when using this, you must use the hashmapholder's lock - HashMapHolder<Player>::MapType& GetPlayers() + HashMapHolder<Player>::MapType const& GetPlayers() const { return HashMapHolder<Player>::GetContainer(); } // when using this, you must use the hashmapholder's lock - HashMapHolder<Creature>::MapType& GetCreatures() - { - return HashMapHolder<Creature>::GetContainer(); - } - - // when using this, you must use the hashmapholder's lock - HashMapHolder<GameObject>::MapType& GetGameObjects() - { - return HashMapHolder<GameObject>::GetContainer(); - } + //HashMapHolder<Creature>::MapType& GetCreatures() + //{ + // return HashMapHolder<Creature>::GetContainer(); + //} + + //// when using this, you must use the hashmapholder's lock + //HashMapHolder<GameObject>::MapType& GetGameObjects() + //{ + // return HashMapHolder<GameObject>::GetContainer(); + //} template<class T> void AddObject(T* object) { diff --git a/src/server/game/Grids/GridStates.cpp b/src/server/game/Grids/GridStates.cpp index dcf7c3bf1ad..fd5e3c68a51 100755 --- a/src/server/game/Grids/GridStates.cpp +++ b/src/server/game/Grids/GridStates.cpp @@ -22,24 +22,24 @@ #include "Log.h" void -InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32 /*x*/, const uint32 /*y*/, const uint32) const +InvalidState::Update(Map &, NGridType &, GridInfo &, const uint32) const { } void -ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 x, const uint32 y, const uint32 t_diff) const +ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 t_diff) const { // Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle info.UpdateTimeTracker(t_diff); if (info.getTimeTracker().Passed()) { - if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(x, y)) + if (grid.ActiveObjectsInGrid() == 0 && !m.ActiveObjectsNearGrid(grid)) { ObjectGridStoper worker; TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer> visitor(worker); grid.VisitAllGrids(visitor); grid.SetGridState(GRID_STATE_IDLE); - sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] on map %u moved to IDLE state", x, y, m.GetId()); + sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] on map %u moved to IDLE state", grid.getX(), grid.getY(), m.GetId()); } else { @@ -49,24 +49,24 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 x, co } void -IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32 x, const uint32 y, const uint32) const +IdleState::Update(Map &m, NGridType &grid, GridInfo &, const uint32) const { m.ResetGridExpiry(grid); grid.SetGridState(GRID_STATE_REMOVAL); - sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] on map %u moved to REMOVAL state", x, y, m.GetId()); + sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] on map %u moved to REMOVAL state", grid.getX(), grid.getY(), m.GetId()); } void -RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 x, const uint32 y, const uint32 t_diff) const +RemovalState::Update(Map &m, NGridType &grid, GridInfo &info, const uint32 t_diff) const { if (!info.getUnloadLock()) { info.UpdateTimeTracker(t_diff); if (info.getTimeTracker().Passed()) { - if (!m.UnloadGrid(x, y, false)) + if (!m.UnloadGrid(grid, false)) { - sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] for map %u differed unloading due to players or active objects nearby", x, y, m.GetId()); + sLog->outDebug(LOG_FILTER_MAPS, "Grid[%u, %u] for map %u differed unloading due to players or active objects nearby", grid.getX(), grid.getY(), m.GetId()); m.ResetGridExpiry(grid); } } diff --git a/src/server/game/Grids/GridStates.h b/src/server/game/Grids/GridStates.h index 81bf749b63f..78f70356608 100755 --- a/src/server/game/Grids/GridStates.h +++ b/src/server/game/Grids/GridStates.h @@ -40,35 +40,31 @@ class GridState void setMagic() { i_Magic = MAGIC_TESTVAL; } unsigned int i_Magic; #endif - virtual void Update(Map &, NGridType&, GridInfo &, const uint32 x, const uint32 y, const uint32 t_diff) const = 0; + virtual void Update(Map &, NGridType&, GridInfo &, const uint32 t_diff) const = 0; }; class InvalidState : public GridState { public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 x, const uint32 y, const uint32 t_diff) const; + void Update(Map &, NGridType &, GridInfo &, const uint32 t_diff) const; }; class ActiveState : public GridState { public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 x, const uint32 y, const uint32 t_diff) const; + void Update(Map &, NGridType &, GridInfo &, const uint32 t_diff) const; }; class IdleState : public GridState { public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 x, const uint32 y, const uint32 t_diff) const; + void Update(Map &, NGridType &, GridInfo &, const uint32 t_diff) const; }; class RemovalState : public GridState { public: - - void Update(Map &, NGridType &, GridInfo &, const uint32 x, const uint32 y, const uint32 t_diff) const; + void Update(Map &, NGridType &, GridInfo &, const uint32 t_diff) const; }; #endif diff --git a/src/server/game/Grids/NGrid.h b/src/server/game/Grids/NGrid.h index bcd03edb2b8..b814fd386a5 100755 --- a/src/server/game/Grids/NGrid.h +++ b/src/server/game/Grids/NGrid.h @@ -77,7 +77,6 @@ class GRID_OBJECT_TYPES class NGrid { public: - typedef Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> GridType; NGrid(uint32 id, int32 x, int32 y, time_t expiry, bool unload = true) : i_gridId(id), i_x(x), i_y(y), i_cellstate(GRID_STATE_INVALID), i_GridObjectDataLoaded(false) @@ -85,13 +84,13 @@ class NGrid i_GridInfo = GridInfo(expiry, unload); } - const GridType& operator()(unsigned short x, unsigned short y) const + GridType& GetGridType(const uint32 x, const uint32 y) { ASSERT(x < N && y < N); return i_cells[x][y]; } - GridType& operator()(unsigned short x, unsigned short y) + GridType const& GetGridType(const uint32 x, const uint32 y) const { ASSERT(x < N && y < N); return i_cells[x][y]; @@ -123,12 +122,22 @@ class NGrid template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) { - getGridType(x, y).AddWorldObject(obj); + GetGridType(x, y).AddWorldObject(obj); } template<class SPECIFIC_OBJECT> void RemoveWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) { - getGridType(x, y).RemoveWorldObject(obj); + GetGridType(x, y).RemoveWorldObject(obj); + } + + template<class SPECIFIC_OBJECT> void AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) + { + GetGridType(x, y).AddGridObject(obj); + } + + template<class SPECIFIC_OBJECT> void RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) + { + GetGridType(x, y).RemoveGridObject(obj); } // Visit all Grids (cells) in NGrid (grid) @@ -137,14 +146,14 @@ class NGrid { for (uint32 x = 0; x < N; ++x) for (uint32 y = 0; y < N; ++y) - getGridType(x, y).Visit(visitor); + GetGridType(x, y).Visit(visitor); } // Visit a single Grid (cell) in NGrid (grid) template<class T, class TT> void VisitGrid(const uint32 x, const uint32 y, TypeContainerVisitor<T, TypeMapContainer<TT> > &visitor) { - getGridType(x, y).Visit(visitor); + GetGridType(x, y).Visit(visitor); } unsigned int ActiveObjectsInGrid(void) const @@ -156,24 +165,7 @@ class NGrid return count; } - template<class SPECIFIC_OBJECT> bool AddGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - return getGridType(x, y).AddGridObject(obj); - } - - template<class SPECIFIC_OBJECT> bool RemoveGridObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) - { - return getGridType(x, y).RemoveGridObject(obj); - } - private: - - GridType& getGridType(const uint32 x, const uint32 y) - { - ASSERT(x < N && y < N); - return i_cells[x][y]; - } - uint32 i_gridId; GridInfo i_GridInfo; GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> > i_Reference; diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 425a31fc38a..ebeac025f1d 100755 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -238,9 +238,9 @@ void Map::AddToGrid(T* obj, Cell const& cell) { NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); if (obj->m_isWorldObject) - (*grid)(cell.CellX(), cell.CellY()).template AddWorldObject<T>(obj); + grid->GetGridType(cell.CellX(), cell.CellY()).template AddWorldObject<T>(obj); else - (*grid)(cell.CellX(), cell.CellY()).template AddGridObject<T>(obj); + grid->GetGridType(cell.CellX(), cell.CellY()).template AddGridObject<T>(obj); } template<> @@ -248,9 +248,9 @@ void Map::AddToGrid(Creature* obj, Cell const& cell) { NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); if (obj->m_isWorldObject) - (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj); + grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj); else - (*grid)(cell.CellX(), cell.CellY()).AddGridObject(obj); + grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj); obj->SetCurrentCell(cell); } @@ -260,9 +260,9 @@ void Map::RemoveFromGrid(T* obj, Cell const& cell) { NGridType* grid = getNGrid(cell.GridX(), cell.GridY()); if (obj->m_isWorldObject) - (*grid)(cell.CellX(), cell.CellY()).template RemoveWorldObject<T>(obj); + grid->GetGridType(cell.CellX(), cell.CellY()).template RemoveWorldObject<T>(obj); else - (*grid)(cell.CellX(), cell.CellY()).template RemoveGridObject<T>(obj); + grid->GetGridType(cell.CellX(), cell.CellY()).template RemoveGridObject<T>(obj); } template<class T> @@ -283,27 +283,17 @@ void Map::SwitchGridContainers(T* obj, bool on) NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY()); ASSERT(ngrid != NULL); - GridType &grid = (*ngrid)(cell.CellX(), cell.CellY()); + GridType &grid = ngrid->GetGridType(cell.CellX(), cell.CellY()); if (on) { grid.RemoveGridObject<T>(obj); grid.AddWorldObject<T>(obj); - /*if (!grid.RemoveGridObject<T>(obj, obj->GetGUID()) - || !grid.AddWorldObject<T>(obj, obj->GetGUID())) - { - ASSERT(false); - }*/ } else { grid.RemoveWorldObject<T>(obj); grid.AddGridObject<T>(obj); - /*if (!grid.RemoveWorldObject<T>(obj, obj->GetGUID()) - || !grid.AddGridObject<T>(obj, obj->GetGUID())) - { - ASSERT(false); - }*/ } obj->m_isWorldObject = on; } @@ -387,7 +377,7 @@ bool Map::EnsureGridLoaded(const Cell &cell) loader.LoadN(); // Add resurrectable corpses to world object list in grid - sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), (*grid)(cell.CellX(), cell.CellY()), this); + sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this); return true; } @@ -944,13 +934,13 @@ bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly) return false; } -bool Map::UnloadGrid(const uint32 x, const uint32 y, bool unloadAll) +bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) { - NGridType *grid = getNGrid(x, y); - ASSERT(grid != NULL); + const uint32 x = ngrid.getX(); + const uint32 y = ngrid.getY(); { - if (!unloadAll && ActiveObjectsNearGrid(x, y)) + if (!unloadAll && ActiveObjectsNearGrid(ngrid)) return false; sLog->outDebug(LOG_FILTER_MAPS, "Unloading grid[%u, %u] for map %u", x, y, GetId()); @@ -964,7 +954,7 @@ bool Map::UnloadGrid(const uint32 x, const uint32 y, bool unloadAll) // move creatures to respawn grids if this is diff.grid or to remove list ObjectGridEvacuator worker; TypeContainerVisitor<ObjectGridEvacuator, GridTypeMapContainer> visitor(worker); - grid->VisitAllGrids(visitor); + ngrid.VisitAllGrids(visitor); // Finish creature moves, remove and delete all creatures with delayed remove before unload MoveAllCreaturesInMoveList(); @@ -973,7 +963,7 @@ bool Map::UnloadGrid(const uint32 x, const uint32 y, bool unloadAll) { ObjectGridCleaner worker; TypeContainerVisitor<ObjectGridCleaner, GridTypeMapContainer> visitor(worker); - grid->VisitAllGrids(visitor); + ngrid.VisitAllGrids(visitor); } RemoveAllObjectsInRemoveList(); @@ -981,12 +971,12 @@ bool Map::UnloadGrid(const uint32 x, const uint32 y, bool unloadAll) { ObjectGridUnloader worker; TypeContainerVisitor<ObjectGridUnloader, GridTypeMapContainer> visitor(worker); - grid->VisitAllGrids(visitor); + ngrid.VisitAllGrids(visitor); } ASSERT(i_objectsToRemove.empty()); - delete grid; + delete &ngrid; setNGrid(NULL, x, y); } int gx = (MAX_NUMBER_OF_GRIDS - 1) - x; @@ -1040,7 +1030,7 @@ void Map::UnloadAll() { NGridType &grid(*i->getSource()); ++i; - UnloadGrid(grid.getX(), grid.getY(), true); // deletes the grid and removes it from the GridRefManager + UnloadGrid(grid, true); // deletes the grid and removes it from the GridRefManager } } @@ -1999,7 +1989,7 @@ void Map::DelayedUpdate(const uint32 t_diff) GridInfo* info = i->getSource()->getGridInfoRef(); ++i; // The update might delete the map and we need the next map before the iterator gets invalid ASSERT(grid->GetGridState() >= 0 && grid->GetGridState() < MAX_GRID_STATE); - si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, grid->getX(), grid->getY(), t_diff); + si_GridStates[grid->GetGridState()]->Update(*this, *grid, *info, t_diff); } } } @@ -2102,11 +2092,9 @@ void Map::SendToPlayers(WorldPacket const* data) const itr->getSource()->GetSession()->SendPacket(data); } -bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const +bool Map::ActiveObjectsNearGrid(NGridType const& ngrid) const { - ASSERT(x < MAX_NUMBER_OF_GRIDS && y < MAX_NUMBER_OF_GRIDS); - - CellCoord cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS); + CellCoord cell_min(ngrid.getX() * MAX_NUMBER_OF_CELLS, ngrid.getY() * MAX_NUMBER_OF_CELLS); CellCoord cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS); //we must find visible range in cells so we unload only non-visible cells... diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index a8386360ae2..053759a3ab3 100755 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -275,7 +275,7 @@ class Map : public GridRefManager<NGridType> bool GetUnloadLock(const GridCoord &p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); } void SetUnloadLock(const GridCoord &p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); } void LoadGrid(float x, float y); - bool UnloadGrid(const uint32 x, const uint32 y, bool pForce); + bool UnloadGrid(NGridType& ngrid, bool pForce); virtual void UnloadAll(); void ResetGridExpiry(NGridType &grid, float factor = 1) const @@ -379,7 +379,7 @@ class Map : public GridRefManager<NGridType> bool HavePlayers() const { return !m_mapRefManager.isEmpty(); } uint32 GetPlayersCountExceptGMs() const; - bool ActiveObjectsNearGrid(uint32 x, uint32 y) const; + bool ActiveObjectsNearGrid(NGridType const& ngrid) const; void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); } void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); } diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index 293933c8bb9..bbef60aa5e7 100755 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -260,7 +260,7 @@ void PoolGroup<Quest>::Despawn1Object(uint32 quest_id) QuestRelations::iterator lastElement = questMap->upper_bound(itr->second); for (; qitr != lastElement; ++qitr) { - if (qitr->first == itr->second) + if (qitr->first == itr->second && qitr->second == itr->first) { questMap->erase(qitr); // iterator is now no more valid break; // but we can exit loop since the element is found @@ -279,7 +279,7 @@ void PoolGroup<Quest>::Despawn1Object(uint32 quest_id) QuestRelations::iterator lastElement = questMap->upper_bound(itr->second); for (; qitr != lastElement; ++qitr) { - if (qitr->first == itr->second) + if (qitr->first == itr->second && qitr->second == itr->first) { questMap->erase(qitr); // iterator is now no more valid break; // but we can exit loop since the element is found diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index a1a1f5d5cac..9650afb60e2 100755 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -205,6 +205,11 @@ int32 Quest::GetRewOrReqMoney() const return int32(RewOrReqMoney * sWorld->getRate(RATE_DROP_MONEY)); } +bool Quest::IsAutoComplete() const +{ + return QuestMethod == 0 || HasFlag(QUEST_FLAGS_AUTOCOMPLETE); +} + bool Quest::IsAllowedInRaid() const { if (IsRaidQuest()) diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 61d492ce88c..90e52660160 100755 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -246,7 +246,7 @@ class Quest uint32 GetQuestStartScript() const { return QuestStartScript; } uint32 GetQuestCompleteScript() const { return QuestCompleteScript; } bool IsRepeatable() const { return QuestFlags & QUEST_TRINITY_FLAGS_REPEATABLE; } - bool IsAutoComplete() const { return QuestMethod ? false : true; } + bool IsAutoComplete() const; uint32 GetFlags() const { return QuestFlags; } bool IsDaily() const { return QuestFlags & QUEST_FLAGS_DAILY; } bool IsWeekly() const { return QuestFlags & QUEST_FLAGS_WEEKLY; } diff --git a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp index 1b0cef69c04..971e0b89c0f 100755 --- a/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/MiscHandler.cpp @@ -239,8 +239,8 @@ void WorldSession::HandleWhoOpcode(WorldPacket & recv_data) data << uint32(matchcount); // placeholder, count of players matching criteria data << uint32(displaycount); // placeholder, count of players displayed - ACE_GUARD(ACE_Thread_Mutex, g, *HashMapHolder<Player>::GetLock()); - HashMapHolder<Player>::MapType& m = sObjectAccessor->GetPlayers(); + ACE_READ_GUARD(HashMapHolder<Player>::LockType, g, *HashMapHolder<Player>::GetLock()); + HashMapHolder<Player>::MapType const& m = sObjectAccessor->GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { if (AccountMgr::IsPlayerAccount(security)) diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 2a352e92d01..68ccf96bb87 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -117,8 +117,8 @@ public: bool first = true; bool footer = false; - ACE_GUARD_RETURN(ACE_Thread_Mutex, guard, *HashMapHolder<Player>::GetLock(), true); - HashMapHolder<Player>::MapType& m = sObjectAccessor->GetPlayers(); + ACE_READ_GUARD_RETURN(HashMapHolder<Player>::LockType, guard, *HashMapHolder<Player>::GetLock(), true); + HashMapHolder<Player>::MapType const& m = sObjectAccessor->GetPlayers(); for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr) { AccountTypes itrSec = itr->second->GetSession()->GetSecurity(); diff --git a/src/server/scripts/EasternKingdoms/eversong_woods.cpp b/src/server/scripts/EasternKingdoms/eversong_woods.cpp index 10b7066068b..d02cce3f17c 100644 --- a/src/server/scripts/EasternKingdoms/eversong_woods.cpp +++ b/src/server/scripts/EasternKingdoms/eversong_woods.cpp @@ -35,91 +35,6 @@ EndContentData */ #include "ScriptedEscortAI.h" /*###### -## npc_prospector_anvilward -######*/ - -#define GOSSIP_HELLO "I need a moment of your time, sir." -#define GOSSIP_SELECT "Why... yes, of course. I've something to show you right inside this building, Mr. Anvilward." - -enum eProspectorAnvilward -{ - SAY_ANVIL1 = -1000209, - SAY_ANVIL2 = -1000210, - QUEST_THE_DWARVEN_SPY = 8483, -}; - -class npc_prospector_anvilward : public CreatureScript -{ -public: - npc_prospector_anvilward() : CreatureScript("npc_prospector_anvilward") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->SEND_GOSSIP_MENU(8240, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->CLOSE_GOSSIP_MENU(); - if (npc_escortAI* pEscortAI = CAST_AI(npc_prospector_anvilward::npc_prospector_anvilwardAI, creature->AI())) - pEscortAI->Start(true, false, player->GetGUID()); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (player->GetQuestStatus(QUEST_THE_DWARVEN_SPY) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(8239, creature->GetGUID()); - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_prospector_anvilwardAI(creature); - } - - struct npc_prospector_anvilwardAI : public npc_escortAI - { - // CreatureAI functions - npc_prospector_anvilwardAI(Creature* c) : npc_escortAI(c) {} - - // Pure Virtual Functions - void WaypointReached(uint32 i) - { - Player* player = GetPlayerForEscort(); - - if (!player) - return; - - switch (i) - { - case 0: DoScriptText(SAY_ANVIL1, me, player); break; - case 5: DoScriptText(SAY_ANVIL2, me, player); break; - case 6: me->setFaction(24); break; - } - } - - void Reset() - { - me->RestoreFaction(); - } - - void JustDied(Unit* /*killer*/) - { - me->RestoreFaction(); - } - }; - -}; - -/*###### ## Quest 9686 Second Trial ######*/ @@ -711,7 +626,6 @@ public: void AddSC_eversong_woods() { - new npc_prospector_anvilward(); new npc_second_trial_controller(); new npc_second_trial_paladin(); new go_second_trial(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index e4749fd2ffe..be83c4d326a 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -284,7 +284,7 @@ public: if (m_uiPenetratingColdTimer <= uiDiff) { - me->CastCustomSpell(SPELL_PENETRATING_COLD, SPELLVALUE_MAX_TARGETS, RAID_MODE(2, 5)); + me->CastCustomSpell(SPELL_PENETRATING_COLD, SPELLVALUE_MAX_TARGETS, RAID_MODE(2, 5, 2, 5)); m_uiPenetratingColdTimer = 20*IN_MILLISECONDS; } else m_uiPenetratingColdTimer -= uiDiff; diff --git a/src/server/scripts/Northrend/dalaran.cpp b/src/server/scripts/Northrend/dalaran.cpp index be9e9308f4f..8ff5a314dcc 100644 --- a/src/server/scripts/Northrend/dalaran.cpp +++ b/src/server/scripts/Northrend/dalaran.cpp @@ -70,8 +70,9 @@ public: return; Player* player = who->GetCharmerOrOwnerPlayerOrPlayerItself(); - - if (!player || player->isGameMaster() || player->IsBeingTeleported()) + + // If player has Disguise aura for quest A Meeting With The Magister or An Audience With The Arcanist, do not teleport it away but let it pass + if (!player || player->isGameMaster() || player->IsBeingTeleported() || player->HasAura(70973) || player->HasAura(70971)) return; switch (me->GetEntry()) diff --git a/src/server/scripts/Outland/nagrand.cpp b/src/server/scripts/Outland/nagrand.cpp index b639050320c..726edb5efb2 100644 --- a/src/server/scripts/Outland/nagrand.cpp +++ b/src/server/scripts/Outland/nagrand.cpp @@ -19,330 +19,20 @@ /* ScriptData SDName: Nagrand SD%Complete: 90 -SDComment: Quest support: 9849, 9868, 9918, 9874, 9991, 10107, 10108, 10044, 10172, 10646, 10085, 10987. TextId's unknown for altruis_the_sufferer and greatmother_geyah (npc_text) +SDComment: Quest support: 9868, 9874, 10044, 10172, 10085. TextId's unknown for altruis_the_sufferer and greatmother_geyah (npc_text) SDCategory: Nagrand EndScriptData */ /* ContentData -mob_shattered_rumbler -mob_lump -npc_altruis_the_sufferer npc_greatmother_geyah -npc_lantresor_of_the_blade npc_maghar_captive npc_creditmarker_visit_with_ancestors -mob_sparrowhawk EndContentData */ #include "ScriptPCH.h" #include "ScriptedEscortAI.h" /*###### -## mob_shattered_rumbler - this should be done with ACID -######*/ - -class mob_shattered_rumbler : public CreatureScript -{ -public: - mob_shattered_rumbler() : CreatureScript("mob_shattered_rumbler") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_shattered_rumblerAI (creature); - } - - struct mob_shattered_rumblerAI : public ScriptedAI - { - bool Spawn; - - mob_shattered_rumblerAI(Creature* c) : ScriptedAI(c) {} - - void Reset() - { - Spawn = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void SpellHit(Unit* Hitter, const SpellInfo* Spellkind) - { - if (Spellkind->Id == 32001 && !Spawn) - { - float x = me->GetPositionX(); - float y = me->GetPositionY(); - float z = me->GetPositionZ(); - - Hitter->SummonCreature(18181, x+(0.7f * (rand()%30)), y+(rand()%5), z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); - Hitter->SummonCreature(18181, x+(rand()%5), y-(rand()%5), z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); - Hitter->SummonCreature(18181, x-(rand()%5), y+(0.5f *(rand()%60)), z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60000); - me->setDeathState(CORPSE); - Spawn = true; - } - return; - } - }; - -}; - -/*###### -## mob_lump -######*/ - -#define SPELL_VISUAL_SLEEP 16093 -#define SPELL_SPEAR_THROW 32248 - -#define LUMP_SAY0 -1000190 -#define LUMP_SAY1 -1000191 - -#define LUMP_DEFEAT -1000192 - -#define GOSSIP_HL "I need answers, ogre!" -#define GOSSIP_SL1 "Why are Boulderfist out this far? You know that this is Kurenai territory." -#define GOSSIP_SL2 "And you think you can just eat anything you want? You're obviously trying to eat the Broken of Telaar." -#define GOSSIP_SL3 "This means war, Lump! War I say!" - -class mob_lump : public CreatureScript -{ -public: - mob_lump() : CreatureScript("mob_lump") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(9353, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(9354, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SL3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(9355, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->SEND_GOSSIP_MENU(9356, creature->GetGUID()); - player->TalkedToCreature(18354, creature->GetGUID()); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (player->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(9352, creature->GetGUID()); - - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_lumpAI(creature); - } - - struct mob_lumpAI : public ScriptedAI - { - mob_lumpAI(Creature* c) : ScriptedAI(c) - { - bReset = false; - } - - uint32 Reset_Timer; - uint32 Spear_Throw_Timer; - bool bReset; - - void Reset() - { - Reset_Timer = 60000; - Spear_Throw_Timer = 2000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void AttackedBy(Unit* pAttacker) - { - if (me->getVictim()) - return; - - if (me->IsFriendlyTo(pAttacker)) - return; - - AttackStart(pAttacker); - } - - void DamageTaken(Unit* done_by, uint32 & damage) - { - if (done_by->GetTypeId() == TYPEID_PLAYER && me->HealthBelowPctDamaged(30, damage)) - { - if (!bReset && CAST_PLR(done_by)->GetQuestStatus(9918) == QUEST_STATUS_INCOMPLETE) - { - //Take 0 damage - damage = 0; - - CAST_PLR(done_by)->AttackStop(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->setFaction(1080); //friendly - me->SetStandState(UNIT_STAND_STATE_SIT); - DoScriptText(LUMP_DEFEAT, me); - - bReset = true; - } - } - } - - void EnterCombat(Unit* /*who*/) - { - if (me->HasAura(SPELL_VISUAL_SLEEP)) - me->RemoveAura(SPELL_VISUAL_SLEEP); - - if (!me->IsStandState()) - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoScriptText(RAND(LUMP_SAY0, LUMP_SAY1), me); - } - - void UpdateAI(const uint32 diff) - { - //check if we waiting for a reset - if (bReset) - { - if (Reset_Timer <= diff) - { - EnterEvadeMode(); - bReset = false; - me->setFaction(1711); //hostile - return; - } - else Reset_Timer -= diff; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Spear_Throw_Timer - if (Spear_Throw_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SPEAR_THROW); - Spear_Throw_Timer = 20000; - } else Spear_Throw_Timer -= diff; - - DoMeleeAttackIfReady(); - } - }; - -}; - -/*###### -## npc_altruis_the_sufferer -######*/ - -#define GOSSIP_HATS1 "I see twisted steel and smell sundered earth." -#define GOSSIP_HATS2 "Well...?" -#define GOSSIP_HATS3 "[PH] Story about Illidan's Pupil" - -#define GOSSIP_SATS1 "Legion?" -#define GOSSIP_SATS2 "And now?" -#define GOSSIP_SATS3 "How do you see them now?" -#define GOSSIP_SATS4 "Forge camps?" -#define GOSSIP_SATS5 "Ok." -#define GOSSIP_SATS6 "[PH] Story done" - -class npc_altruis_the_sufferer : public CreatureScript -{ -public: - npc_altruis_the_sufferer() : CreatureScript("npc_altruis_the_sufferer") { } - - bool OnQuestAccept(Player* player, Creature* /*creature*/, Quest const* /*quest*/) - { - if (!player->GetQuestRewardStatus(9991)) //Survey the Land, q-id 9991 - { - player->CLOSE_GOSSIP_MENU(); - player->ActivateTaxiPathTo(532); //TaxiPath 532 - } - return true; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+10: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11); - player->SEND_GOSSIP_MENU(9420, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+11: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12); - player->SEND_GOSSIP_MENU(9421, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+12: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13); - player->SEND_GOSSIP_MENU(9422, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+13: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14); - player->SEND_GOSSIP_MENU(9423, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+14: - player->SEND_GOSSIP_MENU(9424, creature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+20: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21); - player->SEND_GOSSIP_MENU(9427, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+21: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(9991); - break; - - case GOSSIP_ACTION_INFO_DEF+30: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SATS6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 31); - player->SEND_GOSSIP_MENU(384, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+31: - player->CLOSE_GOSSIP_MENU(); - player->AreaExploredOrEventHappens(10646); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - //gossip before obtaining Survey the Land - if (player->GetQuestStatus(9991) == QUEST_STATUS_NONE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10); - - //gossip when Survey the Land is incomplete (technically, after the flight) - if (player->GetQuestStatus(9991) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); - - //wowwiki.com/Varedis - if (player->GetQuestStatus(10646) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HATS3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+30); - - player->SEND_GOSSIP_MENU(9419, creature->GetGUID()); - - return true; - } - -}; - -/*###### ## npc_greatmother_geyah ######*/ @@ -453,83 +143,6 @@ public: }; -/*###### -## npc_lantresor_of_the_blade -######*/ - -#define GOSSIP_HLB "I have killed many of your ogres, Lantresor. I have no fear." -#define GOSSIP_SLB1 "Should I know? You look like an orc to me." -#define GOSSIP_SLB2 "And the other half?" -#define GOSSIP_SLB3 "I have heard of your kind, but I never thought to see the day when I would meet a half-breed." -#define GOSSIP_SLB4 "My apologies. I did not mean to offend. I am here on behalf of my people." -#define GOSSIP_SLB5 "My people ask that you pull back your Boulderfist ogres and cease all attacks on our territories. In return, we will also pull back our forces." -#define GOSSIP_SLB6 "We will fight you until the end, then, Lantresor. We will not stand idly by as you pillage our towns and kill our people." -#define GOSSIP_SLB7 "What do I need to do?" - -class npc_lantresor_of_the_blade : public CreatureScript -{ -public: - npc_lantresor_of_the_blade() : CreatureScript("npc_lantresor_of_the_blade") { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*uiSender*/, uint32 uiAction) - { - player->PlayerTalkClass->ClearMenus(); - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(9362, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+1: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - player->SEND_GOSSIP_MENU(9363, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - player->SEND_GOSSIP_MENU(9364, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); - player->SEND_GOSSIP_MENU(9365, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+4: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5); - player->SEND_GOSSIP_MENU(9366, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+5: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6); - player->SEND_GOSSIP_MENU(9367, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+6: - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SLB7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7); - player->SEND_GOSSIP_MENU(9368, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+7: - player->SEND_GOSSIP_MENU(9369, creature->GetGUID()); - if (player->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE) - player->AreaExploredOrEventHappens(10107); - if (player->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) - player->AreaExploredOrEventHappens(10108); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestStatus(10107) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(10108) == QUEST_STATUS_INCOMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HLB, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - player->SEND_GOSSIP_MENU(9361, creature->GetGUID()); - - return true; - } - -}; - /*##### ## npc_maghar_captive #####*/ @@ -747,113 +360,9 @@ public: }; /*###### -## mob_sparrowhawk +## go_corkis_prison and npc_corki ######*/ -#define SPELL_SPARROWHAWK_NET 39810 -#define SPELL_ITEM_CAPTIVE_SPARROWHAWK 39812 - -class mob_sparrowhawk : public CreatureScript -{ -public: - mob_sparrowhawk() : CreatureScript("mob_sparrowhawk") { } - - CreatureAI* GetAI(Creature* creature) const - { - return new mob_sparrowhawkAI (creature); - } - - struct mob_sparrowhawkAI : public ScriptedAI - { - - mob_sparrowhawkAI(Creature* c) : ScriptedAI(c) {} - - uint32 Check_Timer; - uint64 PlayerGUID; - bool fleeing; - - void Reset() - { - me->RemoveAurasDueToSpell(SPELL_SPARROWHAWK_NET); - Check_Timer = 1000; - PlayerGUID = 0; - fleeing = false; - } - void AttackStart(Unit* who) - { - if (PlayerGUID) - return; - - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit* /*who*/) {} - - void MoveInLineOfSight(Unit* who) - { - if (!who || PlayerGUID) - return; - - if (!PlayerGUID && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 30) && CAST_PLR(who)->GetQuestStatus(10987) == QUEST_STATUS_INCOMPLETE) - { - PlayerGUID = who->GetGUID(); - return; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - if (Check_Timer <= diff) - { - if (PlayerGUID) - { - if (fleeing && me->GetMotionMaster()->GetCurrentMovementGeneratorType() != FLEEING_MOTION_TYPE) - fleeing = false; - - Player* player = Unit::GetPlayer(*me, PlayerGUID); - if (player && me->IsWithinDistInMap(player, 30)) - { - if (!fleeing) - { - me->DeleteThreatList(); - me->GetMotionMaster()->MoveFleeing(player); - fleeing = true; - } - } - else if (fleeing) - { - me->GetMotionMaster()->MovementExpired(false); - PlayerGUID = 0; - fleeing = false; - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (PlayerGUID) - return; - - ScriptedAI::UpdateAI(diff); - } - - void SpellHit(Unit* caster, const SpellInfo* spell) - { - if (caster->GetTypeId() == TYPEID_PLAYER) - { - if (spell->Id == SPELL_SPARROWHAWK_NET && CAST_PLR(caster)->GetQuestStatus(10987) == QUEST_STATUS_INCOMPLETE) - { - DoCast(caster, SPELL_ITEM_CAPTIVE_SPARROWHAWK, true); - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - } - } - return; - } - }; -}; - enum CorkiData { // first quest @@ -916,10 +425,6 @@ public: } }; -/*###### -## npc_corki -######*/ - class npc_corki : public CreatureScript { public: @@ -970,16 +475,241 @@ public: }; }; +/*##### +## npc_kurenai_captive +#####*/ + +enum KurenaiCaptive +{ + SAY_KUR_START = 0, + SAY_KUR_NO_ESCAPE = 1, + SAY_KUR_MORE = 2, + SAY_KUR_MORE_TWO = 3, + SAY_KUR_LIGHTNING = 4, + SAY_KUR_SHOCK = 5, + SAY_KUR_COMPLETE = 6, + + SPELL_KUR_CHAIN_LIGHTNING = 16006, + SPELL_KUR_EARTHBIND_TOTEM = 15786, + SPELL_KUR_FROST_SHOCK = 12548, + SPELL_KUR_HEALING_WAVE = 12491, + + QUEST_TOTEM_KARDASH_A = 9879, + + NPC_KUR_MURK_RAIDER = 18203, + NPC_KUR_MURK_BRUTE = 18211, + NPC_KUR_MURK_SCAVENGER = 18207, + NPC_KUR_MURK_PUTRIFIER = 18202, +}; + +static float kurenaiAmbushA[]= {-1568.805786f, 8533.873047f, 1.958f}; +static float kurenaiAmbushB[]= {-1491.554321f, 8506.483398f, 1.248f}; + +class npc_kurenai_captive : public CreatureScript +{ +public: + npc_kurenai_captive() : CreatureScript("npc_kurenai_captive") { } + + bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest) + { + if (quest->GetQuestId() == QUEST_TOTEM_KARDASH_A) + { + if (npc_kurenai_captiveAI* EscortAI = dynamic_cast<npc_kurenai_captiveAI*>(creature->AI())) + { + creature->SetStandState(UNIT_STAND_STATE_STAND); + EscortAI->Start(true, false, player->GetGUID(), quest); + DoScriptText(SAY_KUR_START, creature); + + creature->SummonCreature(NPC_KUR_MURK_RAIDER, kurenaiAmbushA[0]+2.5f, kurenaiAmbushA[1]-2.5f, kurenaiAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + creature->SummonCreature(NPC_KUR_MURK_BRUTE, kurenaiAmbushA[0]-2.5f, kurenaiAmbushA[1]+2.5f, kurenaiAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + creature->SummonCreature(NPC_KUR_MURK_SCAVENGER, kurenaiAmbushA[0], kurenaiAmbushA[1], kurenaiAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + } + } + return true; + } + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_kurenai_captiveAI(creature); + } + + struct npc_kurenai_captiveAI : public npc_escortAI + { + npc_kurenai_captiveAI(Creature* creature) : npc_escortAI(creature) { } + + uint32 ChainLightningTimer; + uint32 HealTimer; + uint32 FrostShockTimer; + + void Reset() + { + ChainLightningTimer = 1000; + HealTimer = 0; + FrostShockTimer = 6000; + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_KUR_EARTHBIND_TOTEM, false); + } + + void JustDied(Unit* /*killer*/) + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + return; + + if (Player* player = GetPlayerForEscort()) + { + if (player->GetQuestStatus(QUEST_TOTEM_KARDASH_A) != QUEST_STATUS_COMPLETE) + player->FailQuest(QUEST_TOTEM_KARDASH_A); + } + } + + void WaypointReached(uint32 PointId) + { + switch(PointId) + { + case 3: + { + Talk(SAY_KUR_MORE); + + if (Creature* temp = me->SummonCreature(NPC_KUR_MURK_PUTRIFIER, kurenaiAmbushB[0], kurenaiAmbushB[1], kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000)) + Talk(SAY_KUR_MORE_TWO); + + me->SummonCreature(NPC_KUR_MURK_PUTRIFIER, kurenaiAmbushB[0]-2.5f, kurenaiAmbushB[1]-2.5f, kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(NPC_KUR_MURK_SCAVENGER, kurenaiAmbushB[0]+2.5f, kurenaiAmbushB[1]+2.5f, kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + me->SummonCreature(NPC_KUR_MURK_SCAVENGER, kurenaiAmbushB[0]+2.5f, kurenaiAmbushB[1]-2.5f, kurenaiAmbushB[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + break; + } + case 7: + { + Talk(SAY_KUR_COMPLETE); + + if (Player* player = GetPlayerForEscort()) + player->GroupEventHappens(QUEST_TOTEM_KARDASH_A, me); + + SetRun(); + break; + } + } + } + + void JustSummoned(Creature* summoned) + { + if (summoned->GetEntry() == NPC_KUR_MURK_BRUTE) + Talk(SAY_KUR_NO_ESCAPE); + + // This function is for when we summoned enemies to fight - so that does NOT mean we should make our totem count in this! + if (summoned->isTotem()) + return; + + summoned->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + summoned->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()); + summoned->AI()->AttackStart(me); + } + + void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell) + { + if (spell->Id == SPELL_KUR_CHAIN_LIGHTNING) + { + if (rand()%30) + return; + + Talk(SAY_KUR_LIGHTNING); + } + + if (spell->Id == SPELL_KUR_FROST_SHOCK) + { + if (rand()%30) + return; + + Talk(SAY_KUR_SHOCK); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STAT_CASTING)) + return; + + if (ChainLightningTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KUR_CHAIN_LIGHTNING); + ChainLightningTimer = urand(7000,14000); + } else ChainLightningTimer -= diff; + + if (HealthBelowPct(30)) + { + if (HealTimer <= diff) + { + DoCast(me, SPELL_KUR_HEALING_WAVE); + HealTimer = 5000; + } else HealTimer -= diff; + } + + if (FrostShockTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KUR_FROST_SHOCK); + FrostShockTimer = urand(7500,15000); + } else FrostShockTimer -= diff; + + DoMeleeAttackIfReady(); + } + }; +}; + +/*###### +## go_warmaul_prison +######*/ + +enum FindingTheSurvivorsData +{ + QUEST_FINDING_THE_SURVIVORS = 9948, + NPC_MAGHAR_PRISONER = 18428, + + SAY_FREE_0 = 0, + SAY_FREE_1 = 1, + SAY_FREE_2 = 2, + SAY_FREE_3 = 3, + SAY_FREE_4 = 4, +}; + +class go_warmaul_prison : public GameObjectScript +{ +public: + go_warmaul_prison() : GameObjectScript("go_warmaul_prison") { } + + bool OnGossipHello(Player* player, GameObject* go) + { + if (player->GetQuestStatus(QUEST_FINDING_THE_SURVIVORS) != QUEST_STATUS_INCOMPLETE) + return false; + + if (Creature* prisoner = go->FindNearestCreature(NPC_MAGHAR_PRISONER, 1.0f)) + { + if (prisoner) + { + go->UseDoorOrButton(); + if (player) + player->KilledMonsterCredit(NPC_MAGHAR_PRISONER, 0); + + prisoner->AI()->Talk(RAND(SAY_FREE_0, SAY_FREE_1, SAY_FREE_2, SAY_FREE_3, SAY_FREE_4), player->GetGUID()); + prisoner->ForcedDespawn(6000); + } + } + return true; + } +}; + void AddSC_nagrand() { - new mob_shattered_rumbler(); - new mob_lump(); - new npc_altruis_the_sufferer(); new npc_greatmother_geyah(); - new npc_lantresor_of_the_blade(); new npc_maghar_captive(); new npc_creditmarker_visit_with_ancestors(); - new mob_sparrowhawk(); new npc_corki(); new go_corkis_prison(); + new npc_kurenai_captive(); + new go_warmaul_prison(); } diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index ef2e4c92190..07b8a79691a 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -33,8 +33,6 @@ enum PriestSpells PRIEST_SPELL_PENANCE_R1_HEAL = 47757, PRIEST_SPELL_REFLECTIVE_SHIELD_TRIGGERED = 33619, PRIEST_SPELL_REFLECTIVE_SHIELD_R1 = 33201, - PRIEST_SPELL_SHADOWFIEND = 34433, - PRIEST_SPELL_SHADOWFIEND_TRIGGERED = 28305, }; // Guardian Spirit @@ -275,44 +273,6 @@ class spell_pri_reflective_shield_trigger : public SpellScriptLoader } }; -class spell_pri_shadowfiend : public SpellScriptLoader -{ - public: - spell_pri_shadowfiend() : SpellScriptLoader("spell_pri_shadowfiend") { } - - class spell_pri_shadowfiend_SpellScript : public SpellScript - { - PrepareSpellScript(spell_pri_shadowfiend_SpellScript); - - bool Validate(SpellInfo const* spellEntry) - { - return sSpellMgr->GetSpellInfo(PRIEST_SPELL_SHADOWFIEND) && sSpellMgr->GetSpellInfo(PRIEST_SPELL_SHADOWFIEND_TRIGGERED); - } - - void HandleTriggerSpell(SpellEffIndex /*effIndex*/) - { - Unit* unitTarget = GetHitUnit(); - if (!unitTarget) - return; - - if (Unit* pet = unitTarget->GetGuardianPet()) - { - pet->CastSpell(pet, PRIEST_SPELL_SHADOWFIEND_TRIGGERED, true); - } - } - - void Register() - { - OnEffectHitTarget += SpellEffectFn(spell_pri_shadowfiend_SpellScript::HandleTriggerSpell, EFFECT_1, SPELL_EFFECT_TRIGGER_SPELL); - } - }; - - SpellScript* GetSpellScript() const - { - return new spell_pri_shadowfiend_SpellScript; - } -}; - void AddSC_priest_spell_scripts() { new spell_pri_guardian_spirit(); @@ -321,5 +281,4 @@ void AddSC_priest_spell_scripts() new spell_pri_penance; new spell_pri_reflective_shield_trigger(); new spell_pri_mind_sear(); - new spell_pri_shadowfiend(); } diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 6ae9577070e..3b2cc5f5e00 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -899,7 +899,6 @@ class spell_q9874_liquid_fire : public SpellScriptLoader }; }; - enum SalvagingLifesStength { NPC_SHARD_KILL_CREDIT = 29303, @@ -950,6 +949,7 @@ enum eBattleStandard { NPC_KING_OF_THE_MOUNTAINT_KC = 31766, }; + class spell_q13280_13283_plant_battle_standard: public SpellScriptLoader { public: @@ -978,6 +978,54 @@ public: } }; +enum ChumTheWaterSummons +{ + SUMMON_ANGRY_KVALDIR = 66737, + SUMMON_NORTH_SEA_MAKO = 66738, + SUMMON_NORTH_SEA_THRESHER = 66739, + SUMMON_NORTH_SEA_BLUE_SHARK = 66740 +}; + +class spell_q14112_14145_chum_the_water: public SpellScriptLoader +{ +public: + spell_q14112_14145_chum_the_water() : SpellScriptLoader("spell_q14112_14145_chum_the_water") { } + + class spell_q14112_14145_chum_the_water_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q14112_14145_chum_the_water_SpellScript); + + bool Validate(SpellInfo const* /*spellEntry*/) + { + if (!sSpellMgr->GetSpellInfo(SUMMON_ANGRY_KVALDIR)) + return false; + if (!sSpellMgr->GetSpellInfo(SUMMON_NORTH_SEA_MAKO)) + return false; + if (!sSpellMgr->GetSpellInfo(SUMMON_NORTH_SEA_THRESHER)) + return false; + if (!sSpellMgr->GetSpellInfo(SUMMON_NORTH_SEA_BLUE_SHARK)) + return false; + return true; + } + + void HandleScriptEffect(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + caster->CastSpell(caster, RAND(SUMMON_ANGRY_KVALDIR, SUMMON_NORTH_SEA_MAKO, SUMMON_NORTH_SEA_THRESHER, SUMMON_NORTH_SEA_BLUE_SHARK)); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_q14112_14145_chum_the_water_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_q14112_14145_chum_the_water_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -1001,4 +1049,5 @@ void AddSC_quest_spell_scripts() new spell_q9874_liquid_fire(); new spell_q12805_lifeblood_dummy(); new spell_q13280_13283_plant_battle_standard(); + new spell_q14112_14145_chum_the_water(); } |