Merge branch 'master' into Playerbot
This commit is contained in:
@@ -18,40 +18,49 @@
|
||||
#ifndef LOCKEDQUEUE_H
|
||||
#define LOCKEDQUEUE_H
|
||||
|
||||
#include <atomic>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
template <class T, typename StorageType = std::deque<T>>
|
||||
class LockedQueue
|
||||
{
|
||||
//! Lock access to the queue.
|
||||
std::mutex _lock;
|
||||
mutable std::mutex _lock; ///< Mutex to protect access to the queue
|
||||
|
||||
//! Storage backing the queue.
|
||||
StorageType _queue;
|
||||
std::atomic<bool> _canceled{false}; ///< Flag indicating if the queue is canceled
|
||||
|
||||
//! Cancellation flag.
|
||||
volatile bool _canceled{false};
|
||||
StorageType _queue; ///< Storage container for the queue
|
||||
|
||||
public:
|
||||
|
||||
//! Create a LockedQueue.
|
||||
/**
|
||||
* @brief Default constructor to create an empty LockedQueue.
|
||||
*/
|
||||
LockedQueue() = default;
|
||||
|
||||
//! Destroy a LockedQueue.
|
||||
/**
|
||||
* @brief Destructor for LockedQueue.
|
||||
*/
|
||||
virtual ~LockedQueue() = default;
|
||||
|
||||
//! Adds an item to the queue.
|
||||
/**
|
||||
* @brief Adds an item to the back of the queue.
|
||||
*
|
||||
* @param item The item to be added to the queue.
|
||||
*/
|
||||
void add(const T& item)
|
||||
{
|
||||
lock();
|
||||
|
||||
_queue.push_back(item);
|
||||
|
||||
unlock();
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
_queue.push_back(std::move(item));
|
||||
}
|
||||
|
||||
//! Adds items back to front of the queue
|
||||
/**
|
||||
* @brief Adds a range of items to the front of the queue.
|
||||
*
|
||||
* @param begin Iterator pointing to the beginning of the range of items to be added.
|
||||
* @param end Iterator pointing to the end of the range of items to be added.
|
||||
*/
|
||||
template<class Iterator>
|
||||
void readd(Iterator begin, Iterator end)
|
||||
{
|
||||
@@ -59,33 +68,42 @@ public:
|
||||
_queue.insert(_queue.begin(), begin, end);
|
||||
}
|
||||
|
||||
//! Gets the next result in the queue, if any.
|
||||
/**
|
||||
* @brief Gets the next item in the queue and removes it.
|
||||
*
|
||||
* @param result The variable where the next item will be stored.
|
||||
* @return true if an item was retrieved and removed, false if the queue is empty.
|
||||
*/
|
||||
bool next(T& result)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
if (_queue.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = _queue.front();
|
||||
result = std::move(_queue.front());
|
||||
_queue.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the next item from the queue if it satisfies the provided checker.
|
||||
*
|
||||
* @param result The variable where the next item will be stored.
|
||||
* @param check A checker object that will be used to validate the item.
|
||||
* @return true if an item was retrieved, checked, and removed; false otherwise.
|
||||
*/
|
||||
template<class Checker>
|
||||
bool next(T& result, Checker& check)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
if (_queue.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = _queue.front();
|
||||
result = std::move(_queue.front());
|
||||
if (!check.Process(result))
|
||||
{
|
||||
return false;
|
||||
@@ -95,60 +113,54 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
|
||||
T& peek(bool autoUnlock = false)
|
||||
/**
|
||||
* @brief Peeks at the top of the queue without removing it.
|
||||
*
|
||||
* @return A reference to the item at the front of the queue, assuming there's an item in the queue (as per previous implementation)
|
||||
*/
|
||||
T& peek()
|
||||
{
|
||||
lock();
|
||||
|
||||
T& result = _queue.front();
|
||||
|
||||
if (autoUnlock)
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
return result;
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _queue.front();
|
||||
}
|
||||
|
||||
//! Cancels the queue.
|
||||
/**
|
||||
* @brief Cancels the queue, preventing further processing of items.
|
||||
*/
|
||||
void cancel()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
|
||||
_canceled = true;
|
||||
_canceled.store(true, std::memory_order_release);
|
||||
}
|
||||
|
||||
//! Checks if the queue is cancelled.
|
||||
bool cancelled()
|
||||
/**
|
||||
* @brief Checks if the queue has been canceled.
|
||||
*
|
||||
* @return true if the queue is canceled, false otherwise.
|
||||
*/
|
||||
bool cancelled() const
|
||||
{
|
||||
return _canceled.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the queue is empty.
|
||||
*
|
||||
* @return true if the queue is empty, false otherwise.
|
||||
*/
|
||||
bool empty() const
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _canceled;
|
||||
return _queue.empty();
|
||||
}
|
||||
|
||||
//! Locks the queue for access.
|
||||
void lock()
|
||||
{
|
||||
this->_lock.lock();
|
||||
}
|
||||
|
||||
//! Unlocks the queue.
|
||||
void unlock()
|
||||
{
|
||||
this->_lock.unlock();
|
||||
}
|
||||
|
||||
///! Calls pop_front of the queue
|
||||
/**
|
||||
* @brief Removes the item at the front of the queue.
|
||||
*/
|
||||
void pop_front()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
_queue.pop_front();
|
||||
}
|
||||
|
||||
///! Checks if we're empty or not with locks held
|
||||
bool empty()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_lock);
|
||||
return _queue.empty();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,41 +19,81 @@
|
||||
#define MPSCQueue_h__
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
namespace Acore::Impl
|
||||
{
|
||||
// C++ implementation of Dmitry Vyukov's lock free MPSC queue
|
||||
// http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue
|
||||
/**
|
||||
* @brief C++ implementation of Dmitry Vyukov's lock-free MPSC queue (Non-Intrusive).
|
||||
*
|
||||
* This queue allows multiple producers to enqueue items concurrently, but only one consumer
|
||||
* can dequeue items. The queue is lock-free and non-intrusive, meaning it does not modify
|
||||
* the data types that are enqueued.
|
||||
*
|
||||
* @tparam T The type of data that is being enqueued in the queue.
|
||||
*/
|
||||
template<typename T>
|
||||
class MPSCQueueNonIntrusive
|
||||
{
|
||||
public:
|
||||
MPSCQueueNonIntrusive() : _head(new Node()), _tail(_head.load(std::memory_order_relaxed))
|
||||
/**
|
||||
* @brief Constructs a new MPSCQueueNonIntrusive object.
|
||||
*
|
||||
* Initializes the queue with a dummy node and sets up atomic pointers to the head and tail.
|
||||
*/
|
||||
MPSCQueueNonIntrusive()
|
||||
: _head(new Node(nullptr)), _tail(_head.load(std::memory_order_acquire))
|
||||
{
|
||||
Node* front = _head.load(std::memory_order_relaxed);
|
||||
front->Next.store(nullptr, std::memory_order_relaxed);
|
||||
Node* front = _head.load(std::memory_order_acquire);
|
||||
front->Next.store(nullptr, std::memory_order_release); ///< Store with release to ensure visibility
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroys the MPSCQueueNonIntrusive object.
|
||||
*
|
||||
* Dequeues all items and deletes them, followed by proper cleanup of remaining nodes in the queue.
|
||||
*/
|
||||
~MPSCQueueNonIntrusive()
|
||||
{
|
||||
T* output;
|
||||
while (Dequeue(output))
|
||||
delete output;
|
||||
|
||||
Node* front = _head.load(std::memory_order_relaxed);
|
||||
delete front;
|
||||
// Properly delete remaining nodes
|
||||
Node* front = _head.load(std::memory_order_acquire);
|
||||
while (front)
|
||||
{
|
||||
Node* next = front->Next.load(std::memory_order_acquire);
|
||||
delete front;
|
||||
front = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enqueues a new item in the queue.
|
||||
*
|
||||
* This function adds a new item at the head of the queue.
|
||||
*
|
||||
* @param input Pointer to the item to be enqueued.
|
||||
*/
|
||||
void Enqueue(T* input)
|
||||
{
|
||||
Node* node = new Node(input);
|
||||
Node* prevHead = _head.exchange(node, std::memory_order_acq_rel);
|
||||
Node* prevHead = _head.exchange(node, std::memory_order_acq_rel); ///< Exchange with acquire-release semantics
|
||||
prevHead->Next.store(node, std::memory_order_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dequeues an item from the queue.
|
||||
*
|
||||
* This function removes the item at the front of the queue and returns it.
|
||||
*
|
||||
* @param result Reference to a pointer where the dequeued item will be stored.
|
||||
* @return True if an item was successfully dequeued, false if the queue was empty.
|
||||
*/
|
||||
bool Dequeue(T*& result)
|
||||
{
|
||||
Node* tail = _tail.load(std::memory_order_relaxed);
|
||||
Node* tail = _tail.load(std::memory_order_acquire);
|
||||
Node* next = tail->Next.load(std::memory_order_acquire);
|
||||
if (!next)
|
||||
return false;
|
||||
@@ -65,39 +105,63 @@ namespace Acore::Impl
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief A structure representing a node in the queue.
|
||||
*
|
||||
* Each node holds a pointer to data and an atomic pointer to the next node in the queue.
|
||||
*/
|
||||
struct Node
|
||||
{
|
||||
Node() = default;
|
||||
explicit Node(T* data) : Data(data)
|
||||
{
|
||||
Next.store(nullptr, std::memory_order_relaxed);
|
||||
Next.store(nullptr, std::memory_order_release);
|
||||
}
|
||||
|
||||
T* Data;
|
||||
std::atomic<Node*> Next;
|
||||
T* Data; ///< Data stored in the node
|
||||
std::atomic<Node*> Next; ///< Atomic pointer to the next node
|
||||
};
|
||||
|
||||
std::atomic<Node*> _head;
|
||||
std::atomic<Node*> _tail;
|
||||
std::atomic<Node*> _head; ///< Atomic pointer to the head node of the queue
|
||||
std::atomic<Node*> _tail; ///< Atomic pointer to the tail node of the queue
|
||||
|
||||
MPSCQueueNonIntrusive(MPSCQueueNonIntrusive const&) = delete;
|
||||
MPSCQueueNonIntrusive& operator=(MPSCQueueNonIntrusive const&) = delete;
|
||||
MPSCQueueNonIntrusive(MPSCQueueNonIntrusive const&) = delete; ///< Deleted copy constructor
|
||||
MPSCQueueNonIntrusive& operator=(MPSCQueueNonIntrusive const&) = delete; ///< Deleted copy assignment operator
|
||||
};
|
||||
|
||||
// C++ implementation of Dmitry Vyukov's lock free MPSC queue
|
||||
// http://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue
|
||||
/**
|
||||
* @brief C++ implementation of Dmitry Vyukov's lock-free MPSC queue (Intrusive).
|
||||
*
|
||||
* This queue allows multiple producers to enqueue items concurrently, but only one consumer
|
||||
* can dequeue items. The queue is lock-free and intrusive, meaning that the enqueued objects
|
||||
* must have an atomic link to the next item in the queue.
|
||||
*
|
||||
* @tparam T The type of data that is being enqueued in the queue.
|
||||
* @tparam IntrusiveLink A member pointer to the atomic link used for linking the nodes.
|
||||
*/
|
||||
template<typename T, std::atomic<T*> T::* IntrusiveLink>
|
||||
class MPSCQueueIntrusive
|
||||
{
|
||||
public:
|
||||
MPSCQueueIntrusive() : _dummyPtr(reinterpret_cast<T*>(std::addressof(_dummy))), _head(_dummyPtr), _tail(_dummyPtr)
|
||||
/**
|
||||
* @brief Constructs a new MPSCQueueIntrusive object.
|
||||
*
|
||||
* Initializes the queue with a dummy node and sets up atomic pointers to the head and tail.
|
||||
* The dummy node's atomic link is initialized.
|
||||
*/
|
||||
MPSCQueueIntrusive()
|
||||
: _dummyPtr(reinterpret_cast<T*>(std::addressof(_dummy))), _head(_dummyPtr), _tail(_dummyPtr)
|
||||
{
|
||||
// _dummy is constructed from aligned_storage and is intentionally left uninitialized (it might not be default constructible)
|
||||
// so we init only its IntrusiveLink here
|
||||
// Initialize the intrusive link in the dummy node
|
||||
std::atomic<T*>* dummyNext = new (&(_dummyPtr->*IntrusiveLink)) std::atomic<T*>();
|
||||
dummyNext->store(nullptr, std::memory_order_relaxed);
|
||||
dummyNext->store(nullptr, std::memory_order_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroys the MPSCQueueIntrusive object.
|
||||
*
|
||||
* Dequeues all items and deletes them.
|
||||
*/
|
||||
~MPSCQueueIntrusive()
|
||||
{
|
||||
T* output;
|
||||
@@ -105,16 +169,32 @@ namespace Acore::Impl
|
||||
delete output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enqueues a new item in the queue.
|
||||
*
|
||||
* This function adds a new item at the head of the queue.
|
||||
*
|
||||
* @param input Pointer to the item to be enqueued.
|
||||
*/
|
||||
void Enqueue(T* input)
|
||||
{
|
||||
// Set the next link to nullptr initially
|
||||
(input->*IntrusiveLink).store(nullptr, std::memory_order_release);
|
||||
T* prevHead = _head.exchange(input, std::memory_order_acq_rel);
|
||||
T* prevHead = _head.exchange(input, std::memory_order_acq_rel); ///< Exchange with acquire-release semantics
|
||||
(prevHead->*IntrusiveLink).store(input, std::memory_order_release);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dequeues an item from the queue.
|
||||
*
|
||||
* This function removes the item at the front of the queue and returns it.
|
||||
*
|
||||
* @param result Reference to a pointer where the dequeued item will be stored.
|
||||
* @return True if an item was successfully dequeued, false if the queue was empty.
|
||||
*/
|
||||
bool Dequeue(T*& result)
|
||||
{
|
||||
T* tail = _tail.load(std::memory_order_relaxed);
|
||||
T* tail = _tail.load(std::memory_order_acquire);
|
||||
T* next = (tail->*IntrusiveLink).load(std::memory_order_acquire);
|
||||
if (tail == _dummyPtr)
|
||||
{
|
||||
@@ -149,16 +229,25 @@ namespace Acore::Impl
|
||||
}
|
||||
|
||||
private:
|
||||
std::aligned_storage_t<sizeof(T), alignof(T)> _dummy;
|
||||
T* _dummyPtr;
|
||||
std::atomic<T*> _head;
|
||||
std::atomic<T*> _tail;
|
||||
std::aligned_storage_t<sizeof(T), alignof(T)> _dummy; ///< Storage for the dummy object
|
||||
T* _dummyPtr; ///< Pointer to the dummy object
|
||||
std::atomic<T*> _head; ///< Atomic pointer to the head node of the queue
|
||||
std::atomic<T*> _tail; ///< Atomic pointer to the tail node of the queue
|
||||
|
||||
MPSCQueueIntrusive(MPSCQueueIntrusive const&) = delete;
|
||||
MPSCQueueIntrusive& operator=(MPSCQueueIntrusive const&) = delete;
|
||||
MPSCQueueIntrusive(MPSCQueueIntrusive const&) = delete; ///< Deleted copy constructor
|
||||
MPSCQueueIntrusive& operator=(MPSCQueueIntrusive const&) = delete; ///< Deleted copy assignment operator
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conditional type alias for MPSCQueue.
|
||||
*
|
||||
* This alias provides the appropriate type of MPSCQueue based on whether the queue is intrusive
|
||||
* or non-intrusive.
|
||||
*
|
||||
* @tparam T The type of data that is being enqueued in the queue.
|
||||
* @tparam IntrusiveLink If provided, the queue will be intrusive, otherwise, it will be non-intrusive.
|
||||
*/
|
||||
template<typename T, std::atomic<T*> T::* IntrusiveLink = nullptr>
|
||||
using MPSCQueue = std::conditional_t<IntrusiveLink != nullptr, Acore::Impl::MPSCQueueIntrusive<T, IntrusiveLink>, Acore::Impl::MPSCQueueNonIntrusive<T>>;
|
||||
|
||||
|
||||
@@ -27,14 +27,15 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "SpellMgr.h"
|
||||
|
||||
#define AC_SAI_IS_BOOLEAN_VALID(e, value) \
|
||||
{ \
|
||||
if (value > 1) \
|
||||
{ \
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses param {} of type Boolean with value {}, valid values are 0 or 1, skipped.", \
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), STRINGIZE(value), value); \
|
||||
return false; \
|
||||
} \
|
||||
bool SmartAIMgr::IsSAIBoolValid(SmartScriptHolder const& e, SAIBool value)
|
||||
{
|
||||
if (value != 0 && value != 1)
|
||||
{
|
||||
LOG_ERROR("sql.sql", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses param {} of type Boolean with value {}, valid values are 0 or 1, skipped.",
|
||||
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), STRINGIZE(value), value);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SmartWaypointMgr* SmartWaypointMgr::instance()
|
||||
@@ -513,23 +514,22 @@ bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e)
|
||||
case SMART_TARGET_HOSTILE_LAST_AGGRO:
|
||||
case SMART_TARGET_HOSTILE_RANDOM:
|
||||
case SMART_TARGET_HOSTILE_RANDOM_NOT_TOP:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.hostileRandom.playerOnly);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.target.hostileRandom.playerOnly);
|
||||
case SMART_TARGET_FARTHEST:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.farthest.playerOnly);
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.farthest.isInLos);
|
||||
return IsSAIBoolValid(e, e.target.farthest.playerOnly) &&
|
||||
IsSAIBoolValid(e, e.target.farthest.isInLos);
|
||||
break;
|
||||
case SMART_TARGET_CLOSEST_CREATURE:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.unitClosest.dead);
|
||||
return IsSAIBoolValid(e, e.target.unitClosest.dead);
|
||||
break;
|
||||
case SMART_TARGET_CLOSEST_ENEMY:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.closestAttackable.playerOnly);
|
||||
return IsSAIBoolValid(e, e.target.closestAttackable.playerOnly);
|
||||
break;
|
||||
case SMART_TARGET_CLOSEST_FRIENDLY:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.closestFriendly.playerOnly);
|
||||
return IsSAIBoolValid(e, e.target.closestFriendly.playerOnly);
|
||||
break;
|
||||
case SMART_TARGET_OWNER_OR_SUMMONER:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.target.owner.useCharmerOrOwner);
|
||||
return IsSAIBoolValid(e, e.target.owner.useCharmerOrOwner);
|
||||
break;
|
||||
case SMART_TARGET_STORED:
|
||||
case SMART_TARGET_PLAYER_WITH_AURA:
|
||||
@@ -1079,9 +1079,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_EVENT_OOC_LOS:
|
||||
case SMART_EVENT_IC_LOS:
|
||||
if (!IsMinMaxValid(e, e.event.los.cooldownMin, e.event.los.cooldownMax))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e.event.los.hostilityMode >= AsUnderlyingType(SmartEvent::LOSHostilityMode::End))
|
||||
{
|
||||
@@ -1090,8 +1088,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.event.los.playerOnly);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.event.los.playerOnly);
|
||||
case SMART_EVENT_RESPAWN:
|
||||
if (e.event.respawn.type == SMART_SCRIPT_RESPAWN_CONDITION_MAP && !sMapStore.LookupEntry(e.event.respawn.map))
|
||||
{
|
||||
@@ -1134,8 +1131,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
if (e.event.kill.creature && !IsCreatureValid(e, e.event.kill.creature))
|
||||
return false;
|
||||
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.event.kill.playerOnly);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.event.kill.playerOnly);
|
||||
case SMART_EVENT_VICTIM_CASTING:
|
||||
if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId))
|
||||
{
|
||||
@@ -1164,14 +1160,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_EVENT_ACCEPTED_QUEST:
|
||||
case SMART_EVENT_REWARD_QUEST:
|
||||
if (e.event.quest.quest && !IsQuestValid(e, e.event.quest.quest))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsMinMaxValid(e, e.event.quest.cooldownMin, e.event.quest.cooldownMax))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SMART_EVENT_RECEIVE_EMOTE:
|
||||
{
|
||||
@@ -1464,8 +1456,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_SOUND:
|
||||
if (!IsSoundValid(e, e.action.sound.sound))
|
||||
return false;
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.sound.onlySelf);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.sound.onlySelf);
|
||||
case SMART_ACTION_RANDOM_SOUND:
|
||||
if (e.action.randomSound.sound1 && !IsSoundValid(e, e.action.randomSound.sound1))
|
||||
return false;
|
||||
@@ -1505,8 +1496,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
if (!IsQuestValid(e, e.action.questOffer.questID))
|
||||
return false;
|
||||
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.questOffer.directAdd);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.questOffer.directAdd);
|
||||
case SMART_ACTION_FAIL_QUEST:
|
||||
if (!IsQuestValid(e, e.action.quest.quest))
|
||||
return false;
|
||||
@@ -1651,8 +1641,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.summonCreature.attackInvoker);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.summonCreature.attackInvoker);
|
||||
case SMART_ACTION_CALL_KILLEDMONSTER:
|
||||
if (!IsCreatureValid(e, e.action.killedMonster.creature))
|
||||
return false;
|
||||
@@ -1660,8 +1649,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_UPDATE_TEMPLATE:
|
||||
if (!IsCreatureValid(e, e.action.updateTemplate.creature))
|
||||
return false;
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.updateTemplate.updateLevel);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.updateTemplate.updateLevel);
|
||||
case SMART_ACTION_SET_SHEATH:
|
||||
if (e.action.setSheath.sheath && e.action.setSheath.sheath >= MAX_SHEATH_STATE)
|
||||
{
|
||||
@@ -1707,8 +1695,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
case SMART_ACTION_WP_STOP:
|
||||
if (e.action.wpStop.quest && !IsQuestValid(e, e.action.wpStop.quest))
|
||||
return false;
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.wpStop.fail);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.wpStop.fail);
|
||||
case SMART_ACTION_WP_START:
|
||||
{
|
||||
if (!sSmartWaypointMgr->GetPath(e.action.wpStart.pathID))
|
||||
@@ -1729,9 +1716,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
return false;
|
||||
}
|
||||
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.wpStart.run);
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.wpStart.repeat);
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.wpStart.run) &&
|
||||
IsSAIBoolValid(e, e.action.wpStart.repeat);
|
||||
}
|
||||
case SMART_ACTION_CREATE_TIMED_EVENT:
|
||||
{
|
||||
@@ -1872,85 +1858,42 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
|
||||
break;
|
||||
}
|
||||
case SMART_ACTION_AUTO_ATTACK:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.autoAttack.attack);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.autoAttack.attack);
|
||||
case SMART_ACTION_ALLOW_COMBAT_MOVEMENT:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.combatMove.move);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.combatMove.move);
|
||||
case SMART_ACTION_CALL_FOR_HELP:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.callHelp.withEmote);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.callHelp.withEmote);
|
||||
case SMART_ACTION_SET_VISIBILITY:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.visibility.state);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.visibility.state);
|
||||
case SMART_ACTION_SET_RUN:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setRun.run);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.setRun.run);
|
||||
case SMART_ACTION_SET_CAN_FLY:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setFly.fly);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.setFly.fly);
|
||||
case SMART_ACTION_SET_SWIM:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setSwim.swim);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.setSwim.swim);
|
||||
case SMART_ACTION_SET_COUNTER:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setCounter.reset);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.setCounter.reset);
|
||||
case SMART_ACTION_INTERRUPT_SPELL:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.interruptSpellCasting.withDelayed);
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.interruptSpellCasting.withInstant);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.interruptSpellCasting.withDelayed) &&
|
||||
IsSAIBoolValid(e, e.action.interruptSpellCasting.withInstant);
|
||||
case SMART_ACTION_SET_ROOT:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setRoot.root);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.setRoot.root);
|
||||
case SMART_ACTION_DISABLE_EVADE:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.disableEvade.disable);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.disableEvade.disable);
|
||||
case SMART_ACTION_LOAD_EQUIPMENT:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.loadEquipment.force);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.loadEquipment.force);
|
||||
case SMART_ACTION_TALK:
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.talk.useTalkTarget);
|
||||
if (!IsTextValid(e, e.action.talk.textGroupID))
|
||||
return false;
|
||||
break;
|
||||
return IsSAIBoolValid(e, e.action.talk.useTalkTarget);
|
||||
case SMART_ACTION_SIMPLE_TALK:
|
||||
if (!IsTextValid(e, e.action.simpleTalk.textGroupID))
|
||||
return false;
|
||||
break;
|
||||
case SMART_ACTION_SET_HEALTH_REGEN:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.setHealthRegen.regenHealth);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.setHealthRegen.regenHealth);
|
||||
case SMART_ACTION_CALL_TIMED_ACTIONLIST:
|
||||
{
|
||||
AC_SAI_IS_BOOLEAN_VALID(e, e.action.timedActionList.allowOverride);
|
||||
break;
|
||||
}
|
||||
return IsSAIBoolValid(e, e.action.timedActionList.allowOverride);
|
||||
case SMART_ACTION_FLEE_FOR_ASSIST:
|
||||
case SMART_ACTION_MOVE_TO_POS:
|
||||
case SMART_ACTION_EVADE:
|
||||
|
||||
@@ -2219,6 +2219,7 @@ private:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IsSAIBoolValid(SmartScriptHolder const& e, SAIBool value);
|
||||
static bool IsTextValid(SmartScriptHolder const& e, uint32 id);
|
||||
static bool CheckUnusedEventParams(SmartScriptHolder const& e);
|
||||
static bool CheckUnusedActionParams(SmartScriptHolder const& e);
|
||||
|
||||
@@ -32,7 +32,7 @@ enum AccountOpResult
|
||||
AOR_DB_INTERNAL_ERROR
|
||||
};
|
||||
|
||||
#define MAX_ACCOUNT_STR 20
|
||||
#define MAX_ACCOUNT_STR 17
|
||||
#define MAX_PASS_STR 16
|
||||
#define MAX_EMAIL_STR 255
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ bool ArenaSpectator::HandleSpectatorSpectateCommand(ChatHandler* handler, std::s
|
||||
if (player->IsInCombat())
|
||||
errors.push_back("Can't be in combat.");
|
||||
|
||||
if (player->isUsingLfg())
|
||||
if (player->IsUsingLfg())
|
||||
errors.push_back("Can't spectate while using LFG system.");
|
||||
|
||||
if (player->InBattlegroundQueue())
|
||||
|
||||
@@ -185,10 +185,7 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
|
||||
return;
|
||||
}
|
||||
|
||||
if (HasFlag(CHANNEL_FLAG_LFG) &&
|
||||
sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL) &&
|
||||
AccountMgr::IsPlayerAccount(player->GetSession()->GetSecurity()) &&
|
||||
player->GetGroup())
|
||||
if (IsLFG() && sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL) && !player->IsUsingLfg())
|
||||
{
|
||||
WorldPacket data;
|
||||
MakeNotInLfg(&data);
|
||||
|
||||
@@ -181,7 +181,7 @@ public:
|
||||
[[nodiscard]] uint32 GetChannelDBId() const { return _channelDBId; }
|
||||
[[nodiscard]] bool IsConstant() const { return _channelId != 0; }
|
||||
[[nodiscard]] bool IsAnnounce() const { return _announce; }
|
||||
[[nodiscard]] bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; }
|
||||
[[nodiscard]] bool IsLFG() const { return HasFlag(CHANNEL_FLAG_LFG); }
|
||||
[[nodiscard]] std::string const& GetPassword() const { return _password; }
|
||||
void SetPassword(std::string const& npassword) { _password = npassword; }
|
||||
[[nodiscard]] uint32 GetNumPlayers() const { return playersStore.size(); }
|
||||
|
||||
@@ -1001,43 +1001,25 @@ void GameObject::Delete()
|
||||
AddObjectToRemoveList();
|
||||
}
|
||||
|
||||
void GameObject::GetFishLoot(Loot* fishloot, Player* loot_owner)
|
||||
void GameObject::GetFishLoot(Loot* fishLoot, Player* lootOwner, bool junk /*= false*/)
|
||||
{
|
||||
fishloot->clear();
|
||||
fishLoot->clear();
|
||||
|
||||
uint32 zone, subzone;
|
||||
uint32 defaultzone = 1;
|
||||
GetZoneAndAreaId(zone, subzone);
|
||||
uint32 zone, area;
|
||||
uint32 defaultZone = 1;
|
||||
GetZoneAndAreaId(zone, area);
|
||||
|
||||
// if subzone loot exist use it
|
||||
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true);
|
||||
if (fishloot->empty()) //use this becase if zone or subzone has set LOOT_MODE_JUNK_FISH,Even if no normal drop, fishloot->FillLoot return true. it wrong.
|
||||
uint16 lootMode = junk ? LOOT_MODE_JUNK_FISH : LOOT_MODE_DEFAULT;
|
||||
// Check to fill loot in the order area - zone - defaultZone.
|
||||
// This is because area and zone is not set in some places, like Off the coast of Storm Peaks.
|
||||
uint32 lootZones[] = { area, zone, defaultZone };
|
||||
for (uint32 fillZone : lootZones)
|
||||
{
|
||||
//subzone no result,use zone loot
|
||||
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true);
|
||||
//use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks.
|
||||
if (fishloot->empty())
|
||||
fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true);
|
||||
}
|
||||
}
|
||||
fishLoot->FillLoot(fillZone, LootTemplates_Fishing, lootOwner, true, true, lootMode);
|
||||
|
||||
void GameObject::GetFishLootJunk(Loot* fishloot, Player* loot_owner)
|
||||
{
|
||||
fishloot->clear();
|
||||
|
||||
uint32 zone, subzone;
|
||||
uint32 defaultzone = 1;
|
||||
GetZoneAndAreaId(zone, subzone);
|
||||
|
||||
// if subzone loot exist use it
|
||||
fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
|
||||
if (fishloot->empty()) //use this becase if zone or subzone has normal mask drop, then fishloot->FillLoot return true.
|
||||
{
|
||||
//use zone loot
|
||||
fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
|
||||
if (fishloot->empty())
|
||||
//use zone 1 as default
|
||||
fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
|
||||
// If the loot is filled and the loot is eligible, then we break out of the loop.
|
||||
if (!fishLoot->empty() && !fishLoot->isLooted())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,8 +198,7 @@ public:
|
||||
void Refresh();
|
||||
void DespawnOrUnsummon(Milliseconds delay = 0ms, Seconds forcedRespawnTime = 0s);
|
||||
void Delete();
|
||||
void GetFishLoot(Loot* loot, Player* loot_owner);
|
||||
void GetFishLootJunk(Loot* loot, Player* loot_owner);
|
||||
void GetFishLoot(Loot* fishLoot, Player* lootOwner, bool junk = false);
|
||||
[[nodiscard]] GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); }
|
||||
void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); }
|
||||
[[nodiscard]] GOState GetGoState() const { return GOState(GetByteValue(GAMEOBJECT_BYTES_1, 0)); }
|
||||
|
||||
@@ -7896,7 +7896,7 @@ void Player::SendLoot(ObjectGuid guid, LootType loot_type)
|
||||
if (loot_type == LOOT_FISHING)
|
||||
go->GetFishLoot(loot, this);
|
||||
else if (loot_type == LOOT_FISHING_JUNK)
|
||||
go->GetFishLootJunk(loot, this);
|
||||
go->GetFishLoot(loot, this, true);
|
||||
|
||||
if (go->GetGOInfo()->type == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules)
|
||||
{
|
||||
@@ -13111,7 +13111,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid targetPlayerGUID) const
|
||||
return ERR_PARTY_RESULT_OK;
|
||||
}
|
||||
|
||||
bool Player::isUsingLfg()
|
||||
bool Player::IsUsingLfg()
|
||||
{
|
||||
return sLFGMgr->GetState(GetGUID()) != lfg::LFG_STATE_NONE;
|
||||
}
|
||||
|
||||
@@ -2062,6 +2062,7 @@ public:
|
||||
bool IsInChannel(const Channel* c);
|
||||
void CleanupChannels();
|
||||
void ClearChannelWatch();
|
||||
void UpdateLFGChannel();
|
||||
void UpdateLocalChannels(uint32 newZone);
|
||||
|
||||
void UpdateDefense();
|
||||
@@ -2397,7 +2398,7 @@ public:
|
||||
void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; }
|
||||
void RemoveAtLoginFlag(AtLoginFlags flags, bool persist = false);
|
||||
|
||||
bool isUsingLfg();
|
||||
bool IsUsingLfg();
|
||||
bool inRandomLfgDungeon();
|
||||
|
||||
typedef std::set<uint32> DFQuestsDoneList;
|
||||
|
||||
@@ -5687,7 +5687,8 @@ void Player::_LoadActions(PreparedQueryResult result)
|
||||
ab->uState = ACTIONBUTTON_UNCHANGED;
|
||||
else
|
||||
{
|
||||
LOG_ERROR("entities.player", "ActionButton loading problem, will be deleted from db...");
|
||||
|
||||
LOG_ERROR("entities.player", "ActionButton loading problem, will be deleted from db. player: {}, guid: {}, button: {}, action: {}, type: {}", GetName(), GetGUID().GetCounter(), button, action, type);
|
||||
|
||||
// Will deleted in DB at next save (it can create data until save but marked as deleted)
|
||||
m_actionButtons[button].uState = ACTIONBUTTON_DELETED;
|
||||
|
||||
@@ -462,6 +462,44 @@ void Player::UpdateNextMailTimeAndUnreads()
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdateLFGChannel()
|
||||
{
|
||||
if (!sWorld->getBoolConfig(CONFIG_RESTRICTED_LFG_CHANNEL))
|
||||
return;
|
||||
|
||||
ChannelMgr* cMgr = ChannelMgr::forTeam(GetTeamId());
|
||||
if (!cMgr)
|
||||
return;
|
||||
|
||||
ChatChannelsEntry const* cce = sChatChannelsStore.LookupEntry(26); /*LookingForGroup*/
|
||||
Channel* cLFG = cMgr->GetJoinChannel(cce->pattern[m_session->GetSessionDbcLocale()], cce->ChannelID);
|
||||
if (!cLFG)
|
||||
return;
|
||||
|
||||
Channel* cUsed = nullptr;
|
||||
for (Channel* channel : m_channels)
|
||||
if (channel && channel->GetChannelId() == cce->ChannelID)
|
||||
{
|
||||
cUsed = cLFG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsUsingLfg())
|
||||
{
|
||||
if (cUsed == cLFG)
|
||||
return;
|
||||
|
||||
cLFG->JoinChannel(this, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cLFG != cUsed)
|
||||
return;
|
||||
|
||||
cLFG->LeaveChannel(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::UpdateLocalChannels(uint32 newZone)
|
||||
{
|
||||
// pussywizard: mutex needed (tc changed opcode to THREAD UNSAFE)
|
||||
|
||||
@@ -10401,6 +10401,10 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
if (meleeAttack)
|
||||
AddUnitState(UNIT_STATE_MELEE_ATTACKING);
|
||||
|
||||
// Update leash timer when attacking creatures
|
||||
if (victim->IsCreature())
|
||||
victim->ToCreature()->UpdateLeashExtensionTime();
|
||||
|
||||
// set position before any AI calls/assistance
|
||||
//if (IsCreature())
|
||||
// ToCreature()->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ());
|
||||
@@ -10410,6 +10414,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
SetInCombatWith(victim);
|
||||
if (victim->IsPlayer())
|
||||
victim->SetInCombatWith(this);
|
||||
|
||||
AddThreat(victim, 0.0f);
|
||||
|
||||
creature->SendAIReaction(AI_REACTION_HOSTILE);
|
||||
@@ -13640,9 +13645,6 @@ void Unit::SetInCombatWith(Unit* enemy, uint32 duration)
|
||||
}
|
||||
}
|
||||
|
||||
if (Creature* pCreature = ToCreature())
|
||||
pCreature->UpdateLeashExtensionTime();
|
||||
|
||||
SetInCombatState(false, enemy, duration);
|
||||
}
|
||||
|
||||
@@ -13717,6 +13719,10 @@ void Unit::CombatStart(Unit* victim, bool initialAggro)
|
||||
SetInCombatWith(victim);
|
||||
victim->SetInCombatWith(this);
|
||||
|
||||
// Update leash timer when attacking creatures
|
||||
if (victim->IsCreature())
|
||||
victim->ToCreature()->UpdateLeashExtensionTime();
|
||||
|
||||
// Xinef: If pet started combat - put owner in combat
|
||||
if (!alreadyInCombat && IsInCombat())
|
||||
{
|
||||
@@ -13753,6 +13759,12 @@ void Unit::CombatStartOnCast(Unit* target, bool initialAggro, uint32 duration)
|
||||
// Xinef: If pet started combat - put owner in combat
|
||||
if (Unit* owner = GetOwner())
|
||||
owner->SetInCombatWith(target, duration);
|
||||
|
||||
// Update leash timer when attacking creatures
|
||||
if (target->IsCreature())
|
||||
target->ToCreature()->UpdateLeashExtensionTime();
|
||||
else if (ToCreature()) // Reset leash if it is a spell caster, else it may evade inbetween casts
|
||||
ToCreature()->UpdateLeashExtensionTime();
|
||||
}
|
||||
|
||||
Unit* who = target->GetCharmerOrOwnerOrSelf();
|
||||
|
||||
@@ -8688,7 +8688,7 @@ bool ObjectMgr::LoadModuleStringsLocale()
|
||||
std::string const* ObjectMgr::GetModuleString(std::string module, uint32 id, LocaleConstant locale) const
|
||||
{
|
||||
ModuleString const* ms = GetModuleString(module, id);
|
||||
if (ms->Content.size())
|
||||
if (ms && !ms->Content.empty())
|
||||
{
|
||||
if (ms->Content.size() > size_t(locale) && !ms->Content[locale].empty())
|
||||
return &ms->Content[locale];
|
||||
|
||||
@@ -47,15 +47,11 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket)
|
||||
return;
|
||||
|
||||
if (channelName.size() >= 100 || !DisallowHyperlinksAndMaybeKick(channelName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId()))
|
||||
{
|
||||
if (Channel* channel = cMgr->GetJoinChannel(channelName, channelId))
|
||||
channel->JoinChannel(GetPlayer(), password);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
|
||||
@@ -70,10 +66,8 @@ void WorldSession::HandleLeaveChannel(WorldPacket& recvPacket)
|
||||
return;
|
||||
|
||||
if (ChannelMgr* cMgr = ChannelMgr::forTeam(GetPlayer()->GetTeamId()))
|
||||
{
|
||||
if (Channel* channel = cMgr->GetChannel(channelName, GetPlayer()))
|
||||
channel->LeaveChannel(GetPlayer(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSession::HandleChannelList(WorldPacket& recvPacket)
|
||||
|
||||
@@ -71,6 +71,7 @@ void WorldSession::HandleLfgJoinOpcode(WorldPackets::LFG::LFGJoin& packet)
|
||||
GetPlayerInfo(), packet.Roles, newDungeons.size(), packet.Comment);
|
||||
|
||||
sLFGMgr->JoinLfg(GetPlayer(), uint8(packet.Roles), newDungeons, packet.Comment);
|
||||
GetPlayer()->UpdateLFGChannel();
|
||||
}
|
||||
|
||||
void WorldSession::HandleLfgLeaveOpcode(WorldPackets::LFG::LFGLeave& /*packet*/)
|
||||
@@ -87,6 +88,7 @@ void WorldSession::HandleLfgLeaveOpcode(WorldPackets::LFG::LFGLeave& /*packet*/)
|
||||
sLFGMgr->LeaveLfg(sLFGMgr->GetState(guid) == lfg::LFG_STATE_RAIDBROWSER ? guid : gguid);
|
||||
sLFGMgr->LeaveAllLfgQueues(guid, true, group ? group->GetGUID() : ObjectGuid::Empty);
|
||||
}
|
||||
GetPlayer()->UpdateLFGChannel();
|
||||
}
|
||||
|
||||
void WorldSession::HandleLfgProposalResultOpcode(WorldPacket& recvData)
|
||||
|
||||
@@ -55,6 +55,18 @@ void InstanceScript::SaveToDB()
|
||||
CharacterDatabase.Execute(stmt);
|
||||
}
|
||||
|
||||
void InstanceScript::OnPlayerEnter(Player* player)
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsTwoFactionInstance())
|
||||
player->SetFaction((_teamIdInInstance == TEAM_HORDE) ? 1610 /*FACTION_HORDE*/ : 1 /*FACTION_ALLIANCE*/);
|
||||
}
|
||||
|
||||
void InstanceScript::OnPlayerLeave(Player* player)
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && IsTwoFactionInstance())
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
void InstanceScript::OnCreatureCreate(Creature* creature)
|
||||
{
|
||||
AddObject(creature);
|
||||
@@ -584,6 +596,12 @@ void InstanceScript::DoRespawnGameObject(ObjectGuid uiGuid, uint32 uiTimeToDespa
|
||||
LOG_DEBUG("scripts", "InstanceScript: DoRespawnGameObject failed");
|
||||
}
|
||||
|
||||
void InstanceScript::DoRespawnGameObject(uint32 type)
|
||||
{
|
||||
if (GameObject* go = instance->GetGameObject(GetObjectGuid(type)))
|
||||
go->Respawn();
|
||||
}
|
||||
|
||||
void InstanceScript::DoRespawnCreature(ObjectGuid guid, bool force)
|
||||
{
|
||||
if (Creature* creature = instance->GetCreature(guid))
|
||||
@@ -848,3 +866,21 @@ bool InstanceHasScript(WorldObject const* obj, char const* scriptName)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InstanceScript::IsTwoFactionInstance() const
|
||||
{
|
||||
switch (instance->GetId())
|
||||
{
|
||||
case 540: // Shattered Halls
|
||||
case 576: // Nexus
|
||||
case 631: // Icecrown Citadel
|
||||
case 632: // Forge of Souls
|
||||
case 649: // Trial of the Champion
|
||||
case 650: // Trial of the Crusader
|
||||
case 658: // Pit of Saron
|
||||
case 668: // Halls of Reflection
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ typedef std::map<ObjectGuid::LowType /*spawnId*/, uint8 /*state*/> ObjectStateMa
|
||||
class InstanceScript : public ZoneScript
|
||||
{
|
||||
public:
|
||||
explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) {}
|
||||
explicit InstanceScript(Map* map) : instance(map), completedEncounters(0), _teamIdInInstance(TEAM_NEUTRAL) {}
|
||||
|
||||
~InstanceScript() override {}
|
||||
|
||||
@@ -182,10 +182,10 @@ public:
|
||||
GameObject* GetGameObject(uint32 type);
|
||||
|
||||
//Called when a player successfully enters the instance.
|
||||
virtual void OnPlayerEnter(Player* /*player*/) {}
|
||||
virtual void OnPlayerEnter(Player* /*player*/);
|
||||
|
||||
//Called when a player successfully leaves the instance.
|
||||
virtual void OnPlayerLeave(Player* /*player*/) {}
|
||||
virtual void OnPlayerLeave(Player* /*player*/);
|
||||
|
||||
virtual void OnPlayerAreaUpdate(Player* /*player*/, uint32 /*oldArea*/, uint32 /*newArea*/) {}
|
||||
|
||||
@@ -203,6 +203,9 @@ public:
|
||||
//Respawns a GO having negative spawntimesecs in gameobject-table
|
||||
void DoRespawnGameObject(ObjectGuid guid, uint32 timeToDespawn = MINUTE);
|
||||
|
||||
// Respawns a GO by instance storage index
|
||||
void DoRespawnGameObject(uint32 type);
|
||||
|
||||
// Respawns a creature.
|
||||
void DoRespawnCreature(ObjectGuid guid, bool force = false);
|
||||
|
||||
@@ -282,6 +285,10 @@ public:
|
||||
[[nodiscard]] bool AllBossesDone() const;
|
||||
[[nodiscard]] bool AllBossesDone(std::initializer_list<uint32> bossIds) const;
|
||||
|
||||
TeamId GetTeamIdInInstance() const { return _teamIdInInstance; }
|
||||
void SetTeamIdInInstance(TeamId teamId) { _teamIdInInstance = teamId; }
|
||||
bool IsTwoFactionInstance() const;
|
||||
|
||||
TaskScheduler scheduler;
|
||||
protected:
|
||||
void SetHeaders(std::string const& dataHeaders);
|
||||
@@ -336,6 +343,7 @@ private:
|
||||
ObjectGuidMap _objectGuids;
|
||||
ObjectStateMap _objectStateMap;
|
||||
uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets
|
||||
TeamId _teamIdInInstance;
|
||||
std::unordered_set<uint32> _activatedAreaTriggers;
|
||||
};
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ bool Map::ExistMap(uint32 mapid, int gx, int gy)
|
||||
{
|
||||
if (header.mapMagic != MapMagic.asUInt || header.versionMagic != MapVersionMagic)
|
||||
{
|
||||
LOG_ERROR("maps", "Map file '{}' is from an incompatible map version (%.*u v{}), %.*s v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.",
|
||||
LOG_ERROR("maps", "Map file '{}' is from an incompatible map version ({:.4u} v{}), {:.4s} v{} is expected. Please pull your source, recompile tools and recreate maps using the updated mapextractor, then replace your old map files with new files.",
|
||||
tmp, 4, header.mapMagic, header.versionMagic, 4, MapMagic.asChar, MapVersionMagic);
|
||||
}
|
||||
|
||||
@@ -3026,6 +3026,15 @@ bool InstanceMap::AddPlayerToMap(Player* player)
|
||||
m_resetAfterUnload = false;
|
||||
m_unloadWhenEmpty = false;
|
||||
|
||||
if (instance_data && instance_data->IsTwoFactionInstance()
|
||||
&& instance_data->GetTeamIdInInstance() == TEAM_NEUTRAL)
|
||||
{
|
||||
instance_data->SetTeamIdInInstance(player->GetTeamId());
|
||||
if (Group* group = player->GetGroup())
|
||||
if (Player* leader = ObjectAccessor::FindConnectedPlayer(group->GetLeaderGUID()))
|
||||
instance_data->SetTeamIdInInstance(leader->GetTeamId());
|
||||
}
|
||||
|
||||
// this will acquire the same mutex so it cannot be in the previous block
|
||||
Map::AddPlayerToMap(player);
|
||||
|
||||
|
||||
@@ -84,6 +84,21 @@ void ScriptMgr::OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex
|
||||
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_DUMMY_EFFECT_ITEM, script->OnDummyEffect(caster, spellID, effIndex, itemTarget));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf)
|
||||
{
|
||||
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_CAST_CANCEL, script->OnSpellCastCancel(spell, caster, spellInfo, bySelf));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck)
|
||||
{
|
||||
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_CAST, script->OnSpellCast(spell, caster, spellInfo, skipCheck));
|
||||
}
|
||||
|
||||
void ScriptMgr::OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo)
|
||||
{
|
||||
CALL_ENABLED_HOOKS(AllSpellScript, ALLSPELLHOOK_ON_PREPARE, script->OnSpellPrepare(spell, caster, spellInfo));
|
||||
}
|
||||
|
||||
AllSpellScript::AllSpellScript(char const* name, std::vector<uint16> enabledHooks)
|
||||
: ScriptObject(name, ALLSPELLHOOK_END)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,9 @@ enum AllSpellHook
|
||||
ALLSPELLHOOK_ON_DUMMY_EFFECT_GAMEOBJECT,
|
||||
ALLSPELLHOOK_ON_DUMMY_EFFECT_CREATURE,
|
||||
ALLSPELLHOOK_ON_DUMMY_EFFECT_ITEM,
|
||||
ALLSPELLHOOK_ON_CAST_CANCEL,
|
||||
ALLSPELLHOOK_ON_CAST,
|
||||
ALLSPELLHOOK_ON_PREPARE,
|
||||
ALLSPELLHOOK_END
|
||||
};
|
||||
|
||||
@@ -100,6 +103,12 @@ public:
|
||||
* @param itemTarget Contains information about the Item
|
||||
*/
|
||||
virtual void OnDummyEffect(WorldObject* /*caster*/, uint32 /*spellID*/, SpellEffIndex /*effIndex*/, Item* /*itemTarget*/) { }
|
||||
|
||||
virtual void OnSpellCastCancel(Spell* /*spell*/, Unit* /*caster*/, SpellInfo const* /*spellInfo*/, bool /*bySelf*/) { }
|
||||
|
||||
virtual void OnSpellCast(Spell* /*spell*/, Unit* /*caster*/, SpellInfo const* /*spellInfo*/, bool /*skipCheck*/) { }
|
||||
|
||||
virtual void OnSpellPrepare(Spell* /*spell*/, Unit* /*caster*/, SpellInfo const* /*spellInfo*/) { }
|
||||
};
|
||||
|
||||
// Compatibility for old scripts
|
||||
|
||||
@@ -648,6 +648,9 @@ public: /* SpellSC */
|
||||
void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, GameObject* gameObjTarget);
|
||||
void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Creature* creatureTarget);
|
||||
void OnDummyEffect(WorldObject* caster, uint32 spellID, SpellEffIndex effIndex, Item* itemTarget);
|
||||
void OnSpellCastCancel(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool bySelf);
|
||||
void OnSpellCast(Spell* spell, Unit* caster, SpellInfo const* spellInfo, bool skipCheck);
|
||||
void OnSpellPrepare(Spell* spell, Unit* caster, SpellInfo const* spellInfo);
|
||||
|
||||
public: /* GameEventScript */
|
||||
void OnGameEventStart(uint16 EventID);
|
||||
|
||||
@@ -3717,6 +3717,8 @@ SpellCastResult Spell::prepare(SpellCastTargets const* targets, AuraEffect const
|
||||
TriggerGlobalCooldown();
|
||||
}
|
||||
|
||||
sScriptMgr->OnSpellPrepare(this, m_caster, m_spellInfo);
|
||||
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
@@ -3788,6 +3790,8 @@ void Spell::cancel(bool bySelf)
|
||||
//set state back so finish will be processed
|
||||
m_spellState = oldState;
|
||||
|
||||
sScriptMgr->OnSpellCastCancel(this, m_caster, m_spellInfo, bySelf);
|
||||
|
||||
finish(false);
|
||||
}
|
||||
|
||||
@@ -4114,6 +4118,8 @@ void Spell::_cast(bool skipCheck)
|
||||
if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
|
||||
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
|
||||
|
||||
sScriptMgr->OnSpellCast(this, m_caster, m_spellInfo, skipCheck);
|
||||
|
||||
SetExecutedCurrently(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -2644,8 +2644,6 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
|
||||
// some explicitly required dummy effect sets
|
||||
switch (Id)
|
||||
{
|
||||
case 28441:
|
||||
return false; // AB Effect 000
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -207,14 +207,14 @@ public:
|
||||
switch (mode)
|
||||
{
|
||||
case BAN_ACCOUNT:
|
||||
banReturn = sBan->BanAccount(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "");
|
||||
banReturn = sBan->BanAccount(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Console");
|
||||
break;
|
||||
case BAN_CHARACTER:
|
||||
banReturn = sBan->BanAccountByPlayerName(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "");
|
||||
banReturn = sBan->BanAccountByPlayerName(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Console");
|
||||
break;
|
||||
case BAN_IP:
|
||||
default:
|
||||
banReturn = sBan->BanIP(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "");
|
||||
banReturn = sBan->BanIP(nameOrIP, durationStr, reasonStr, handler->GetSession() ? handler->GetSession()->GetPlayerName() : "Console");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -444,7 +444,7 @@ public:
|
||||
if (banResult)
|
||||
{
|
||||
Field* fields2 = banResult->Fetch();
|
||||
handler->PSendSysMessage("%s", fields2[0].Get<std::string>());
|
||||
handler->PSendSysMessage("{}", fields2[0].Get<std::string>());
|
||||
}
|
||||
} while (result->NextRow());
|
||||
}
|
||||
@@ -480,14 +480,14 @@ public:
|
||||
|
||||
if (fields2[0].Get<uint32>() == fields2[1].Get<uint32>())
|
||||
{
|
||||
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|",
|
||||
handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}| permanent |{:<15.15}|{:<15.15}|",
|
||||
accountName, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
|
||||
fields2[2].Get<std::string>(), fields2[3].Get<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
tm tmUnban = Acore::Time::TimeBreakdown(fields2[1].Get<uint32>());
|
||||
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|",
|
||||
handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}|{:02}-{:02}-{:02} {:02}:{:02}|{:<15.15}|{:<15.15}|",
|
||||
accountName, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
|
||||
tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min,
|
||||
fields2[2].Get<std::string>(), fields2[3].Get<std::string>());
|
||||
@@ -534,7 +534,7 @@ public:
|
||||
|
||||
PreparedQueryResult banResult = CharacterDatabase.Query(stmt2);
|
||||
if (banResult)
|
||||
handler->PSendSysMessage("%s", (*banResult)[0].Get<std::string>());
|
||||
handler->PSendSysMessage("{}", (*banResult)[0].Get<std::string>());
|
||||
} while (result->NextRow());
|
||||
}
|
||||
// Console wide output
|
||||
@@ -564,14 +564,14 @@ public:
|
||||
|
||||
if (banFields[0].Get<uint32>() == banFields[1].Get<uint32>())
|
||||
{
|
||||
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|",
|
||||
handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}| permanent |{:<15.15}|{:<15.15}|",
|
||||
char_name, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
|
||||
banFields[2].Get<std::string>(), banFields[3].Get<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
tm tmUnban = Acore::Time::TimeBreakdown(banFields[1].Get<uint32>());
|
||||
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|",
|
||||
handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}|{:02}-{:02}-{:02} {:02}:{:02}|{:<15.15}|{:<15.15}|",
|
||||
char_name, tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
|
||||
tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min,
|
||||
banFields[2].Get<std::string>(), banFields[3].Get<std::string>());
|
||||
@@ -621,7 +621,7 @@ public:
|
||||
do
|
||||
{
|
||||
Field* fields = result->Fetch();
|
||||
handler->PSendSysMessage("%s", fields[0].Get<std::string>());
|
||||
handler->PSendSysMessage("{}", fields[0].Get<std::string>());
|
||||
} while (result->NextRow());
|
||||
}
|
||||
// Console wide output
|
||||
@@ -637,14 +637,14 @@ public:
|
||||
tm tmBan = Acore::Time::TimeBreakdown(fields[1].Get<uint32>());
|
||||
if (fields[1].Get<uint32>() == fields[2].Get<uint32>())
|
||||
{
|
||||
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|",
|
||||
handler->PSendSysMessage("{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}| permanent |{:<15.15}|{:<15.15}|",
|
||||
fields[0].Get<std::string>(), tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
|
||||
fields[3].Get<std::string>(), fields[4].Get<std::string>());
|
||||
}
|
||||
else
|
||||
{
|
||||
tm tmUnban = Acore::Time::TimeBreakdown(fields[2].Get<uint32>());
|
||||
handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|",
|
||||
handler->PSendSysMessage("|{:<15.15}|{:02}-{:02}-{:02} {:02}:{:02}|{:02}-{:02}-{:02} {:02}:{:02}|{:<15.15}|{:<15.15}|",
|
||||
fields[0].Get<std::string>(), tmBan.tm_year % 100, tmBan.tm_mon + 1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min,
|
||||
tmUnban.tm_year % 100, tmUnban.tm_mon + 1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min,
|
||||
fields[3].Get<std::string>(), fields[4].Get<std::string>());
|
||||
|
||||
@@ -924,7 +924,7 @@ public:
|
||||
passenger->EnterVehicle(target, *seatId);
|
||||
}
|
||||
|
||||
handler->PSendSysMessage("Unit {} entered vehicle %hhd", entry, *seatId);
|
||||
handler->PSendSysMessage("Unit {} entered vehicle {:d}", entry, *seatId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
if (plr->isUsingLfg())
|
||||
if (plr->IsUsingLfg())
|
||||
{
|
||||
error = 4;
|
||||
break;
|
||||
|
||||
@@ -217,7 +217,7 @@ public:
|
||||
static bool HandleMmapStatsCommand(ChatHandler* handler)
|
||||
{
|
||||
handler->PSendSysMessage("mmap stats:");
|
||||
//handler->PSendSysMessage(" global mmap pathfinding is %sabled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis");
|
||||
//handler->PSendSysMessage(" global mmap pathfinding is {}abled", DisableMgr::IsPathfindingEnabled(mapId) ? "en" : "dis");
|
||||
|
||||
MMAP::MMapMgr* manager = MMAP::MMapFactory::createOrGetMMapMgr();
|
||||
handler->PSendSysMessage(" {} maps loaded with {} tiles overall", manager->getLoadedMapsCount(), manager->getLoadedTilesCount());
|
||||
|
||||
@@ -807,8 +807,8 @@ public:
|
||||
|
||||
if (!result)
|
||||
{
|
||||
handler->SendSysMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM);
|
||||
return true;
|
||||
handler->SendErrorMessage(LANG_WAYPOINT_NOTFOUNDDBPROBLEM, target->GetSpawnId());
|
||||
return false;
|
||||
}
|
||||
|
||||
handler->SendSysMessage("|cff00ffffDEBUG: wp show info:|r");
|
||||
@@ -912,15 +912,16 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
|
||||
|
||||
// Set "wpguid" column to the visual waypoint
|
||||
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_UPD_WAYPOINT_DATA_WPGUID);
|
||||
stmt->SetData(0, int32(wpCreature->GetSpawnId()));
|
||||
stmt->SetData(0, wpCreature->GetSpawnId());
|
||||
stmt->SetData(1, pathid);
|
||||
stmt->SetData(2, point);
|
||||
|
||||
WorldDatabase.Execute(stmt);
|
||||
|
||||
wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn());
|
||||
// To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
|
||||
if (!wpCreature->LoadCreatureFromDB(wpCreature->GetSpawnId(), map, true, true))
|
||||
{
|
||||
|
||||
@@ -31,7 +31,8 @@ enum Says
|
||||
SAY_GRAVITY_LAPSE = 3,
|
||||
SAY_TIRED = 4,
|
||||
SAY_RECAST_GRAVITY = 5,
|
||||
SAY_DEATH = 6
|
||||
SAY_DEATH = 6,
|
||||
SAY_AGGRO_2 = 7
|
||||
};
|
||||
|
||||
enum Spells
|
||||
@@ -78,6 +79,8 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
_gravityLapseCounter = 0;
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false);
|
||||
me->SetImmuneToAll(false);
|
||||
summons.DespawnAll();
|
||||
|
||||
ScheduleHealthCheckEvent(50, [&]{
|
||||
me->CastStop();
|
||||
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
|
||||
@@ -170,6 +173,7 @@ struct boss_felblood_kaelthas : public BossAI
|
||||
if (!_hasDoneIntro && me->IsWithinDistInMap(who, 40.0f) && who->IsPlayer())
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
Talk(SAY_AGGRO_2, 20s);
|
||||
_hasDoneIntro = true;
|
||||
_OOCScheduler.Schedule(35s, [this](TaskContext){
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
|
||||
@@ -161,7 +161,7 @@ struct boss_selin_fireheart : public BossAI
|
||||
if (Creature* crystal = SelectNearestCrystal(false))
|
||||
{
|
||||
Talk(EMOTE_CRYSTAL);
|
||||
crystal->ReplaceAllUnitFlags(UNIT_FLAG_NONE);
|
||||
crystal->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
crystal->SetInCombatWithZone();
|
||||
crystal->AI()->DoCast(me, SPELL_MANA_RAGE, true);
|
||||
DoCast(crystal, SPELL_FEL_CRYSTAL_COSMETIC, true);
|
||||
|
||||
@@ -51,24 +51,34 @@ enum Misc
|
||||
|
||||
struct boss_vexallus : public BossAI
|
||||
{
|
||||
boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS) { }
|
||||
boss_vexallus(Creature* creature) : BossAI(creature, DATA_VEXALLUS), _energyCooldown(false) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
_energyCooldown = false;
|
||||
|
||||
ScheduleHealthCheckEvent({ 85, 70, 55, 40 }, [&]
|
||||
ScheduleHealthCheckEvent({ 85, 70, 55, 40, 25 }, [&]
|
||||
{
|
||||
Talk(SAY_ENERGY);
|
||||
Talk(EMOTE_DISCHARGE_ENERGY);
|
||||
|
||||
if (IsHeroic())
|
||||
if (!_energyCooldown)
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
|
||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
|
||||
Talk(SAY_ENERGY);
|
||||
Talk(EMOTE_DISCHARGE_ENERGY);
|
||||
|
||||
if (IsHeroic())
|
||||
{
|
||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H1);
|
||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_H2);
|
||||
}
|
||||
else
|
||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
|
||||
|
||||
_energyCooldown = true;
|
||||
scheduler.Schedule(5s, [this](TaskContext)
|
||||
{
|
||||
_energyCooldown = false;
|
||||
});
|
||||
}
|
||||
else
|
||||
DoCastSelf(SPELL_SUMMON_PURE_ENERGY_N);
|
||||
});
|
||||
|
||||
ScheduleHealthCheckEvent(20, [&]
|
||||
@@ -117,6 +127,9 @@ struct boss_vexallus : public BossAI
|
||||
if (killer)
|
||||
killer->CastSpell(killer, SPELL_ENERGY_FEEDBACK, true, 0, 0, summon->GetGUID());
|
||||
}
|
||||
|
||||
private:
|
||||
bool _energyCooldown;
|
||||
};
|
||||
|
||||
void AddSC_boss_vexallus()
|
||||
|
||||
+170
-587
@@ -15,50 +15,63 @@
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "CreatureScript.h"
|
||||
#include "InstanceMapScript.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SmartAI.h"
|
||||
#include "scarletmonastery.h"
|
||||
#include "ScriptedCreature.h"
|
||||
|
||||
enum AshbringerEventMisc
|
||||
{
|
||||
AURA_OF_ASHBRINGER = 28282,
|
||||
NPC_SCARLET_MYRIDON = 4295,
|
||||
NPC_SCARLET_DEFENDER = 4298,
|
||||
NPC_SCARLET_CENTURION = 4301,
|
||||
NPC_SCARLET_SORCERER = 4294,
|
||||
NPC_SCARLET_WIZARD = 4300,
|
||||
NPC_SCARLET_ABBOT = 4303,
|
||||
NPC_SCARLET_MONK = 4540,
|
||||
NPC_SCARLET_CHAMPION = 4302,
|
||||
NPC_SCARLET_CHAPLAIN = 4299,
|
||||
NPC_FAIRBANKS = 4542,
|
||||
NPC_COMMANDER_MOGRAINE = 3976,
|
||||
NPC_INQUISITOR_WHITEMANE = 3977,
|
||||
DOOR_HIGH_INQUISITOR_ID = 104600,
|
||||
NPC_COMMANDER_MOGRAINE = 3976,
|
||||
NPC_INQUISITOR_WHITEMANE = 3977,
|
||||
NPC_SCARLET_SORCERER = 4294,
|
||||
NPC_SCARLET_MYRIDON = 4295,
|
||||
NPC_SCARLET_DEFENDER = 4298,
|
||||
NPC_SCARLET_CHAPLAIN = 4299,
|
||||
NPC_SCARLET_WIZARD = 4300,
|
||||
NPC_SCARLET_CENTURION = 4301,
|
||||
NPC_SCARLET_CHAMPION = 4302,
|
||||
NPC_SCARLET_ABBOT = 4303,
|
||||
NPC_SCARLET_MONK = 4540,
|
||||
NPC_FAIRBANKS = 4542,
|
||||
NPC_HIGHLORD_MOGRAINE = 16062,
|
||||
|
||||
GO_CHAPEL_DOOR = 104591,
|
||||
GO_HIGH_INQUISITOR_DOOR = 104600
|
||||
};
|
||||
|
||||
enum AshbringerSpell
|
||||
{
|
||||
//Highlord Mograine Spells
|
||||
//Needs Fix: Increased the visual effect of spells on hit
|
||||
SPELL_FORGIVENESS = 28697,
|
||||
|
||||
//High Inquisitor Fairbanks
|
||||
//Needs Fix: Increased the visual effect of spells on hit
|
||||
SPELL_TRANSFORM_GHOST = 28443
|
||||
};
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
TYPE_MOGRAINE_AND_WHITE_EVENT = 1,
|
||||
TYPE_MOGRAINE_AND_WHITE_EVENT = 1,
|
||||
TYPE_ASHBRINGER_EVENT = 2,
|
||||
|
||||
DATA_MOGRAINE = 2,
|
||||
DATA_WHITEMANE = 3,
|
||||
DATA_DOOR_WHITEMANE = 4,
|
||||
DATA_MOGRAINE = 3,
|
||||
DATA_WHITEMANE = 4,
|
||||
DATA_DOOR_WHITEMANE = 5,
|
||||
DATA_HORSEMAN_EVENT = 6,
|
||||
DATA_VORREL = 7,
|
||||
DATA_ARCANIST_DOAN = 8,
|
||||
DATA_DOOR_CHAPEL = 9,
|
||||
|
||||
DATA_HORSEMAN_EVENT = 5,
|
||||
GAMEOBJECT_PUMPKIN_SHRINE = 6,
|
||||
|
||||
DATA_VORREL = 7,
|
||||
DATA_ARCANIST_DOAN = 8
|
||||
GAMEOBJECT_PUMPKIN_SHRINE = 10
|
||||
};
|
||||
|
||||
float const CATHEDRAL_PULL_RANGE = 80.0f; // Distance from the Cathedral doors to where Mograine is standing
|
||||
|
||||
class instance_scarlet_monastery : public InstanceMapScript
|
||||
{
|
||||
public:
|
||||
instance_scarlet_monastery() : InstanceMapScript("instance_scarlet_monastery", 189) { }
|
||||
instance_scarlet_monastery() : InstanceMapScript("instance_scarlet_monastery", 189) {}
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
{
|
||||
@@ -72,55 +85,18 @@ public:
|
||||
SetHeaders(DataHeader);
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (player->HasAura(AURA_OF_ASHBRINGER))
|
||||
{
|
||||
std::list<Creature*> ScarletList;
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MYRIDON, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_DEFENDER, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CENTURION, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_SORCERER, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_WIZARD, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_ABBOT, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MONK, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAMPION, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAPLAIN, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_COMMANDER_MOGRAINE, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_FAIRBANKS, 4000.0f);
|
||||
if (!ScarletList.empty())
|
||||
for (std::list<Creature*>::iterator itr = ScarletList.begin(); itr != ScarletList.end(); itr++) (*itr)->SetFaction(FACTION_FRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayerAreaUpdate(Player* player, uint32 /*oldArea*/, uint32 /*newArea*/) override
|
||||
{
|
||||
if (player->HasAura(AURA_OF_ASHBRINGER))
|
||||
{
|
||||
std::list<Creature*> ScarletList;
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MYRIDON, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_DEFENDER, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CENTURION, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_SORCERER, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_WIZARD, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_ABBOT, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_MONK, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAMPION, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_SCARLET_CHAPLAIN, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_COMMANDER_MOGRAINE, 4000.0f);
|
||||
player->GetCreatureListWithEntryInGrid(ScarletList, NPC_FAIRBANKS, 4000.0f);
|
||||
if (!ScarletList.empty())
|
||||
for (std::list<Creature*>::iterator itr = ScarletList.begin(); itr != ScarletList.end(); itr++) (*itr)->SetFaction(FACTION_FRIENDLY);
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
//case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = go->GetGUID(); break;
|
||||
case DOOR_HIGH_INQUISITOR_ID:
|
||||
DoorHighInquisitorGUID = go->GetGUID();
|
||||
// case ENTRY_PUMPKIN_SHRINE: PumpkinShrineGUID = go->GetGUID(); break;
|
||||
case GO_HIGH_INQUISITOR_DOOR:
|
||||
_doorHighInquisitorGUID = go->GetGUID();
|
||||
break;
|
||||
case GO_CHAPEL_DOOR:
|
||||
_doorChapelGUID = go->GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -129,11 +105,26 @@ public:
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_SCARLET_MYRIDON:
|
||||
case NPC_SCARLET_DEFENDER:
|
||||
case NPC_SCARLET_CENTURION:
|
||||
case NPC_SCARLET_SORCERER:
|
||||
case NPC_SCARLET_WIZARD:
|
||||
case NPC_SCARLET_ABBOT:
|
||||
case NPC_SCARLET_MONK:
|
||||
case NPC_SCARLET_CHAMPION:
|
||||
case NPC_SCARLET_CHAPLAIN:
|
||||
case NPC_FAIRBANKS:
|
||||
_ashbringerNpcGUID.emplace(creature->GetGUID());
|
||||
break;
|
||||
case NPC_COMMANDER_MOGRAINE:
|
||||
MograineGUID = creature->GetGUID();
|
||||
_mograineGUID = creature->GetGUID();
|
||||
_ashbringerNpcGUID.emplace(creature->GetGUID());
|
||||
break;
|
||||
case NPC_INQUISITOR_WHITEMANE:
|
||||
WhitemaneGUID = creature->GetGUID();
|
||||
_whitemaneGUID = creature->GetGUID();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -145,19 +136,90 @@ public:
|
||||
case TYPE_MOGRAINE_AND_WHITE_EVENT:
|
||||
if (data == IN_PROGRESS)
|
||||
{
|
||||
DoUseDoorOrButton(DoorHighInquisitorGUID);
|
||||
encounter = IN_PROGRESS;
|
||||
if (Creature* mograine = instance->GetCreature(_mograineGUID))
|
||||
{
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_MONK, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_ABBOT, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_CHAMPION, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_CENTURION, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_WIZARD, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, mograine, NPC_SCARLET_CHAPLAIN, CATHEDRAL_PULL_RANGE);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
{
|
||||
if (Creature* creature = *itr)
|
||||
creature->AI()->AttackStart(mograine->GetVictim());
|
||||
}
|
||||
}
|
||||
_encounter = IN_PROGRESS;
|
||||
}
|
||||
if (data == FAIL)
|
||||
{
|
||||
DoUseDoorOrButton(DoorHighInquisitorGUID);
|
||||
encounter = FAIL;
|
||||
Creature* whitemane = instance->GetCreature(_whitemaneGUID);
|
||||
if (!whitemane)
|
||||
return;
|
||||
|
||||
Creature* mograine = instance->GetCreature(_mograineGUID);
|
||||
if (!mograine)
|
||||
return;
|
||||
|
||||
if (whitemane->IsAlive() && mograine->IsAlive())
|
||||
{
|
||||
// When Whitemane emerges from the main gate, Whitemane will stand next to Mograine's corpse and will not reset Whitemane
|
||||
if (whitemane->IsEngaged()||whitemane->IsInEvadeMode())
|
||||
whitemane->DespawnOnEvade(20s);
|
||||
|
||||
mograine->DespawnOnEvade(20s);
|
||||
_encounter = NOT_STARTED;
|
||||
return;
|
||||
}
|
||||
|
||||
// Whitemane will not be able to fight Mograine again when he dies
|
||||
if (!whitemane->IsAlive())
|
||||
{
|
||||
mograine->DespawnOrUnsummon();
|
||||
_encounter = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if (whitemane->IsAlive() && !mograine->IsAlive())
|
||||
{
|
||||
whitemane->DespawnOnEvade(20s);
|
||||
_encounter = data;
|
||||
return;
|
||||
}
|
||||
|
||||
_encounter = data;
|
||||
}
|
||||
if (data == SPECIAL)
|
||||
encounter = SPECIAL;
|
||||
if (data == DONE)
|
||||
_encounter = DONE;
|
||||
break;
|
||||
case TYPE_ASHBRINGER_EVENT:
|
||||
if (data == IN_PROGRESS)
|
||||
{
|
||||
// the ashbringer incident did not sniff out any data from whitemane
|
||||
if (Creature* whitemane = instance->GetCreature(_whitemaneGUID))
|
||||
if (whitemane->IsAlive() && !whitemane->IsEngaged())
|
||||
whitemane->DespawnOrUnsummon();
|
||||
|
||||
if (GameObject* go = instance->GetGameObject(_doorChapelGUID))
|
||||
{
|
||||
go->SetGoState(GO_STATE_ACTIVE);
|
||||
go->SetLootState(GO_ACTIVATED);
|
||||
go->SetGameObjectFlag(GO_FLAG_IN_USE);
|
||||
}
|
||||
|
||||
for (auto const& scarletCathedralNpcGuid : _ashbringerNpcGUID)
|
||||
if (Creature* scarletNpc = instance->GetCreature(scarletCathedralNpcGuid))
|
||||
if (scarletNpc->IsAlive() && !scarletNpc->IsEngaged())
|
||||
scarletNpc->SetFaction(FACTION_FRIENDLY);
|
||||
}
|
||||
_ashencounter = data;
|
||||
break;
|
||||
case DATA_HORSEMAN_EVENT:
|
||||
encounter = data;
|
||||
_encounter = data;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -167,528 +229,49 @@ public:
|
||||
switch (type)
|
||||
{
|
||||
case DATA_MOGRAINE:
|
||||
return MograineGUID;
|
||||
return _mograineGUID;
|
||||
case DATA_WHITEMANE:
|
||||
return WhitemaneGUID;
|
||||
return _whitemaneGUID;
|
||||
case DATA_DOOR_WHITEMANE:
|
||||
return DoorHighInquisitorGUID;
|
||||
return _doorHighInquisitorGUID;
|
||||
case DATA_DOOR_CHAPEL:
|
||||
return _doorChapelGUID;
|
||||
default:
|
||||
return ObjectGuid::Empty;
|
||||
break;
|
||||
}
|
||||
|
||||
return ObjectGuid::Empty;
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
if (type == TYPE_MOGRAINE_AND_WHITE_EVENT)
|
||||
return encounter;
|
||||
else if (type == DATA_HORSEMAN_EVENT)
|
||||
return encounter;
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
ObjectGuid DoorHighInquisitorGUID;
|
||||
ObjectGuid MograineGUID;
|
||||
ObjectGuid WhitemaneGUID;
|
||||
uint32 encounter;
|
||||
};
|
||||
};
|
||||
|
||||
enum ScarletMonasteryTrashMisc
|
||||
{
|
||||
SAY_WELCOME = 0,
|
||||
AURA_ASHBRINGER = 28282,
|
||||
//FACTION_FRIENDLY_TO_ALL = 35,
|
||||
NPC_HIGHLORD_MOGRAINE = 16440,
|
||||
SPELL_COSMETIC_CHAIN = 45537,
|
||||
SPELL_COSMETIC_EXPLODE = 45935,
|
||||
SPELL_FORGIVENESS = 28697,
|
||||
};
|
||||
|
||||
enum MograineEvents
|
||||
{
|
||||
EVENT_SPELL_CRUSADER_STRIKE = 1,
|
||||
EVENT_SPELL_HAMMER_OF_JUSTICE = 2,
|
||||
EVENT_PULL_CATHEDRAL = 3
|
||||
};
|
||||
|
||||
enum WhitemaneEvents
|
||||
{
|
||||
EVENT_SPELL_HOLY_SMITE = 1,
|
||||
EVENT_SPELL_POWER_WORLD_SHIELD = 2,
|
||||
EVENT_SPELL_HEAL = 3
|
||||
};
|
||||
|
||||
enum Spells
|
||||
{
|
||||
//Mograine Spells
|
||||
SPELL_CRUSADER_STRIKE = 14518,
|
||||
SPELL_HAMMER_OF_JUSTICE = 5589,
|
||||
SPELL_LAY_ON_HANDS = 9257,
|
||||
SPELL_RETRIBUTION_AURA = 8990,
|
||||
SPELL_PERMANENT_FEIGN_DEATH = 29266,
|
||||
|
||||
//Whitemanes Spells
|
||||
SPELL_SCARLET_RESURRECTION = 9232,
|
||||
SPELL_DEEP_SLEEP = 9256,
|
||||
SPELL_DOMINATE_MIND = 14515,
|
||||
SPELL_HOLY_SMITE = 9481,
|
||||
SPELL_HEAL = 12039,
|
||||
SPELL_POWER_WORD_SHIELD = 22187
|
||||
};
|
||||
|
||||
enum Says
|
||||
{
|
||||
//Mograine says
|
||||
SAY_MO_AGGRO = 0,
|
||||
SAY_MO_KILL = 1,
|
||||
SAY_MO_RESURRECTED = 2,
|
||||
|
||||
//Whitemane says
|
||||
SAY_WH_INTRO = 0,
|
||||
SAY_WH_KILL = 1,
|
||||
SAY_WH_RESURRECT = 2,
|
||||
};
|
||||
|
||||
float const CATHEDRAL_PULL_RANGE = 80.0f; // Distance from the Cathedral doors to where Mograine is standing
|
||||
|
||||
class npc_mograine : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_mograine() : CreatureScript("npc_scarlet_commander_mograine") { }
|
||||
|
||||
struct npc_mograineAI : public ScriptedAI
|
||||
{
|
||||
npc_mograineAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
uint32 AshbringerEvent(uint32 uiSteps)
|
||||
{
|
||||
Creature* mograine = me->FindNearestCreature(NPC_HIGHLORD_MOGRAINE, 200.0f);
|
||||
|
||||
switch (uiSteps)
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
me->GetMotionMaster()->MovePoint(0, 1152.039795f, 1398.405518f, 32.527878f);
|
||||
return 2 * IN_MILLISECONDS;
|
||||
case 2:
|
||||
me->SetSheath(SHEATH_STATE_UNARMED);
|
||||
me->SetStandState(UNIT_STAND_STATE_KNEEL);
|
||||
return 2 * IN_MILLISECONDS;
|
||||
case 3:
|
||||
Talk(3);
|
||||
return 10 * IN_MILLISECONDS;
|
||||
case 4:
|
||||
me->SummonCreature(NPC_HIGHLORD_MOGRAINE, 1065.130737f, 1399.350586f, 30.763723f, 6.282961f, TEMPSUMMON_TIMED_DESPAWN, 400000)->SetName("Highlord Mograine");
|
||||
me->FindNearestCreature(NPC_HIGHLORD_MOGRAINE, 200.0f)->SetFaction(FACTION_FRIENDLY);
|
||||
return 30 * IN_MILLISECONDS;
|
||||
case 5:
|
||||
mograine->StopMovingOnCurrentPos();
|
||||
mograine->AI()->Talk(0);
|
||||
mograine->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
|
||||
return 4 * IN_MILLISECONDS;
|
||||
case 6:
|
||||
me->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
return 2 * IN_MILLISECONDS;
|
||||
case 7:
|
||||
Talk(4);
|
||||
return 4 * IN_MILLISECONDS;
|
||||
case 8:
|
||||
mograine->AI()->Talk(1);
|
||||
return 11 * IN_MILLISECONDS;
|
||||
case 9:
|
||||
mograine->HandleEmoteCommand(EMOTE_ONESHOT_BATTLE_ROAR);
|
||||
return 4 * IN_MILLISECONDS;
|
||||
case 10:
|
||||
me->SetSheath(SHEATH_STATE_UNARMED);
|
||||
me->SetStandState(UNIT_STAND_STATE_KNEEL);
|
||||
Talk(5);
|
||||
return 2 * IN_MILLISECONDS;
|
||||
case 11:
|
||||
mograine->CastSpell(me, SPELL_FORGIVENESS, false);
|
||||
return 1 * IN_MILLISECONDS;
|
||||
case 12:
|
||||
mograine->CastSpell(me, SPELL_COSMETIC_CHAIN, true);
|
||||
return 0.5 * IN_MILLISECONDS;
|
||||
case 13:
|
||||
mograine->AI()->Talk(2);
|
||||
mograine->DespawnOrUnsummon(3 * IN_MILLISECONDS);
|
||||
mograine->Kill(me, me, true);
|
||||
return 0;
|
||||
case TYPE_MOGRAINE_AND_WHITE_EVENT:
|
||||
return _encounter;
|
||||
break;
|
||||
case DATA_HORSEMAN_EVENT:
|
||||
return _encounter;
|
||||
break;
|
||||
case TYPE_ASHBRINGER_EVENT:
|
||||
return _ashencounter;
|
||||
break;
|
||||
default:
|
||||
if (mograine)
|
||||
mograine->DespawnOrUnsummon(0);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PullCathedral() // CallForHelp will ignore any npcs without LOS
|
||||
{
|
||||
std::list<Creature*> creatureList;
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_MONK, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_ABBOT, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_CHAMPION, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_CENTURION, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_WIZARD, CATHEDRAL_PULL_RANGE);
|
||||
GetCreatureListWithEntryInGrid(creatureList, me, NPC_SCARLET_CHAPLAIN, CATHEDRAL_PULL_RANGE);
|
||||
for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
|
||||
{
|
||||
if (Creature* creature = *itr)
|
||||
creature->AI()->AttackStart(me->GetVictim());
|
||||
}
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
//Incase wipe during phase that mograine fake death
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
|
||||
SayAshbringer = false;
|
||||
timer = 0;
|
||||
step = 1;
|
||||
hasDied = false;
|
||||
heal = false;
|
||||
fakeDeath = false;
|
||||
events.Reset();
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who && who->GetDistance2d(me) < 15.0f)
|
||||
if (Player* player = who->ToPlayer())
|
||||
if (player->HasAura(AURA_ASHBRINGER) && !SayAshbringer)
|
||||
{
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetSheath(SHEATH_STATE_UNARMED);
|
||||
me->SetStandState(UNIT_STAND_STATE_KNEEL);
|
||||
me->SetFacingToObject(player);
|
||||
// me->Yell(12389, LANG_UNIVERSAL, player); // Doesn't exist
|
||||
SayAshbringer = true;
|
||||
}
|
||||
|
||||
ScriptedAI::MoveInLineOfSight(who);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_MO_AGGRO);
|
||||
me->CastSpell(me, SPELL_RETRIBUTION_AURA, true);
|
||||
events.ScheduleEvent(EVENT_PULL_CATHEDRAL, 1s); // Has to be done via event, otherwise mob aggroing Mograine DOES NOT aggro the room
|
||||
events.ScheduleEvent(EVENT_SPELL_CRUSADER_STRIKE, 1s, 5s);
|
||||
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 6s, 11s);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if (damage < me->GetHealth() || hasDied || fakeDeath)
|
||||
return;
|
||||
|
||||
//On first death, fake death and open door, as well as initiate whitemane if exist
|
||||
if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE)))
|
||||
{
|
||||
instance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS);
|
||||
Whitemane->GetMotionMaster()->MovePoint(1, 1163.113370f, 1398.856812f, 32.527786f);
|
||||
me->GetMotionMaster()->MovementExpired();
|
||||
me->GetMotionMaster()->MoveIdle();
|
||||
me->SetHealth(0);
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
me->ClearComboPointHolders();
|
||||
me->RemoveAllAuras();
|
||||
me->ClearAllReactives();
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->CastSpell(me, SPELL_PERMANENT_FEIGN_DEATH, true);
|
||||
|
||||
hasDied = true;
|
||||
fakeDeath = true;
|
||||
damage = 0;
|
||||
ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_WHITEMANE))->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_MO_KILL);
|
||||
}
|
||||
|
||||
void SpellHit(Unit* /*who*/, SpellInfo const* spell) override
|
||||
{
|
||||
//When hit with resurrection say text
|
||||
if (spell->Id == SPELL_SCARLET_RESURRECTION)
|
||||
{
|
||||
Talk(SAY_MO_RESURRECTED);
|
||||
fakeDeath = false;
|
||||
instance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
timer = timer - diff;
|
||||
if (SayAshbringer && step < 15)
|
||||
{
|
||||
if (timer <= 0)
|
||||
{
|
||||
timer = AshbringerEvent(step);
|
||||
step++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (hasDied && !heal && instance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL)
|
||||
{
|
||||
//On resurrection, stop fake death and heal whitemane and resume fight
|
||||
if (Unit* Whitemane = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_WHITEMANE)))
|
||||
{
|
||||
//Incase wipe during phase that mograine fake death
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveAurasDueToSpell(SPELL_PERMANENT_FEIGN_DEATH);
|
||||
me->CastSpell(me, SPELL_RETRIBUTION_AURA, true);
|
||||
me->CastSpell(Whitemane, SPELL_LAY_ON_HANDS, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_CRUSADER_STRIKE, 1s, 5s);
|
||||
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 6s, 11s);
|
||||
if (me->GetVictim())
|
||||
me->GetMotionMaster()->MoveChase(me->GetVictim());
|
||||
heal = true;
|
||||
}
|
||||
}
|
||||
|
||||
//This if-check to make sure mograine does not attack while fake death
|
||||
if (fakeDeath)
|
||||
return;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SPELL_CRUSADER_STRIKE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_CRUSADER_STRIKE, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_CRUSADER_STRIKE, 10s);
|
||||
break;
|
||||
case EVENT_SPELL_HAMMER_OF_JUSTICE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_HAMMER_OF_JUSTICE, true);
|
||||
events.ScheduleEvent(EVENT_SPELL_HAMMER_OF_JUSTICE, 60s);
|
||||
break;
|
||||
case EVENT_PULL_CATHEDRAL:
|
||||
PullCathedral();
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
bool SayAshbringer = false;
|
||||
int timer = 0;
|
||||
int step = 1;
|
||||
bool hasDied;
|
||||
bool heal;
|
||||
bool fakeDeath;
|
||||
EventMap events;
|
||||
InstanceScript* instance;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetScarletMonasteryAI<npc_mograineAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class boss_high_inquisitor_whitemane : public CreatureScript
|
||||
{
|
||||
public:
|
||||
boss_high_inquisitor_whitemane() : CreatureScript("boss_high_inquisitor_whitemane") { }
|
||||
|
||||
struct boss_high_inquisitor_whitemaneAI : public ScriptedAI
|
||||
{
|
||||
boss_high_inquisitor_whitemaneAI(Creature* creature) : ScriptedAI(creature)
|
||||
{
|
||||
instance = creature->GetInstanceScript();
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
canResurrectCheck = false;
|
||||
canResurrect = false;
|
||||
Wait_Timer = 7000;
|
||||
Heal_Timer = 10000;
|
||||
}
|
||||
|
||||
void JustReachedHome() override
|
||||
{
|
||||
instance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL);
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_WH_INTRO);
|
||||
events.ScheduleEvent(EVENT_SPELL_HOLY_SMITE, 1s, 3s);
|
||||
events.ScheduleEvent(EVENT_SPELL_POWER_WORLD_SHIELD, 6s);
|
||||
events.ScheduleEvent(EVENT_SPELL_HEAL, 9s);
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* /*doneBy*/, uint32& damage, DamageEffectType, SpellSchoolMask) override
|
||||
{
|
||||
if ((!canResurrectCheck || canResurrect) && damage >= me->GetHealth())
|
||||
damage = me->GetHealth() - 1;
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
Talk(SAY_WH_KILL);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
if (canResurrect)
|
||||
{
|
||||
//When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out
|
||||
if (Wait_Timer <= diff)
|
||||
{
|
||||
if (ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
|
||||
{
|
||||
DoCast(SPELL_SCARLET_RESURRECTION);
|
||||
Talk(SAY_WH_RESURRECT);
|
||||
canResurrect = false;
|
||||
}
|
||||
}
|
||||
else Wait_Timer -= diff;
|
||||
}
|
||||
|
||||
//Cast Deep sleep when health is less than 50%
|
||||
if (!canResurrectCheck && !HealthAbovePct(50))
|
||||
{
|
||||
if (me->IsNonMeleeSpellCast(false))
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
|
||||
me->CastSpell(me->GetVictim(), SPELL_DEEP_SLEEP, true);
|
||||
canResurrectCheck = true;
|
||||
canResurrect = true;
|
||||
return;
|
||||
}
|
||||
|
||||
//while in "resurrect-mode", don't do anything
|
||||
if (canResurrect)
|
||||
return;
|
||||
|
||||
//If we are <75% hp cast healing spells at self or Mograine
|
||||
if (Heal_Timer <= diff)
|
||||
{
|
||||
Creature* target = nullptr;
|
||||
|
||||
if (!HealthAbovePct(75))
|
||||
target = me;
|
||||
|
||||
if (Creature* mograine = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MOGRAINE)))
|
||||
{
|
||||
// checking canResurrectCheck prevents her healing Mograine while he is "faking death"
|
||||
if (canResurrectCheck && mograine->IsAlive() && !mograine->HealthAbovePct(75))
|
||||
target = mograine;
|
||||
}
|
||||
|
||||
if (target)
|
||||
me->CastSpell(target, SPELL_HEAL, false);
|
||||
|
||||
Heal_Timer = 13000;
|
||||
}
|
||||
else Heal_Timer -= diff;
|
||||
|
||||
events.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
while (uint32 eventId = events.ExecuteEvent())
|
||||
{
|
||||
switch (eventId)
|
||||
{
|
||||
case EVENT_SPELL_POWER_WORLD_SHIELD:
|
||||
me->CastSpell(me, SPELL_POWER_WORD_SHIELD, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_POWER_WORLD_SHIELD, 15s);
|
||||
break;
|
||||
case EVENT_SPELL_HOLY_SMITE:
|
||||
me->CastSpell(me->GetVictim(), SPELL_HOLY_SMITE, false);
|
||||
events.ScheduleEvent(EVENT_SPELL_HOLY_SMITE, 6s);
|
||||
break;
|
||||
case EVENT_SPELL_HEAL:
|
||||
me->CastSpell(me, SPELL_HEAL, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
InstanceScript* instance;
|
||||
uint32 Heal_Timer;
|
||||
uint32 Wait_Timer;
|
||||
bool canResurrectCheck;
|
||||
bool canResurrect;
|
||||
EventMap events;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetScarletMonasteryAI<boss_high_inquisitor_whitemaneAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
class npc_fairbanks : public CreatureScript
|
||||
{
|
||||
public:
|
||||
npc_fairbanks() : CreatureScript("npc_fairbanks") { }
|
||||
|
||||
struct npc_fairbanksAI : public SmartAI
|
||||
{
|
||||
npc_fairbanksAI(Creature* creature) : SmartAI(creature) { }
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
SayAshbringer = false;
|
||||
}
|
||||
|
||||
void MoveInLineOfSight(Unit* who) override
|
||||
{
|
||||
if (who && who->GetDistance2d(me) < 2.0f)
|
||||
if (Player* player = who->ToPlayer())
|
||||
if (player->HasAura(AURA_ASHBRINGER) && !SayAshbringer)
|
||||
{
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
me->SetNpcFlag(UNIT_NPC_FLAG_GOSSIP);
|
||||
me->CastSpell(me, 57767, true);
|
||||
me->SetDisplayId(16179);
|
||||
me->SetFacingToObject(player);
|
||||
SayAshbringer = true;
|
||||
}
|
||||
|
||||
SmartAI::MoveInLineOfSight(who);
|
||||
}
|
||||
private:
|
||||
bool SayAshbringer = false;
|
||||
ObjectGuid _doorHighInquisitorGUID;
|
||||
ObjectGuid _doorChapelGUID;
|
||||
ObjectGuid _mograineGUID;
|
||||
ObjectGuid _whitemaneGUID;
|
||||
uint32 _encounter{};
|
||||
uint32 _ashencounter{};
|
||||
GuidSet _ashbringerNpcGUID;
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
{
|
||||
return GetScarletMonasteryAI<npc_fairbanksAI>(creature);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_instance_scarlet_monastery()
|
||||
{
|
||||
new instance_scarlet_monastery();
|
||||
new npc_fairbanks();
|
||||
new npc_mograine();
|
||||
new boss_high_inquisitor_whitemane();
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ ObjectData const creatureData[] =
|
||||
{ NPC_JANALAI, DATA_JANALAI },
|
||||
{ NPC_SPIRIT_LYNX, DATA_SPIRIT_LYNX },
|
||||
{ NPC_HARRISON_JONES, DATA_HARRISON_JONES },
|
||||
{ NPC_AMINISHI_LOOKOUT, DATA_LOOKOUT },
|
||||
{ NPC_AMANISHI_LOOKOUT, DATA_LOOKOUT },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -127,13 +127,18 @@ public:
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_AMANISHI_GUARDIAN:
|
||||
case NPC_AMANISHI_SAVAGE:
|
||||
if (creature->GetPositionY() >= 1500.0f) // gate
|
||||
creature->SetImmuneToAll(true);
|
||||
break;
|
||||
// Akil'zon gauntlet
|
||||
case NPC_AMINISHI_TEMPEST:
|
||||
case NPC_AMANISHI_TEMPEST:
|
||||
if (creature->GetPositionZ() >= 50.0f) // excludes Tempest in Hexlord Malacrass' trash
|
||||
AkilzonTrash.insert(creature->GetGUID());
|
||||
break;
|
||||
case NPC_AMINISHI_LOOKOUT:
|
||||
case NPC_AMINISHI_PROTECTOR:
|
||||
case NPC_AMANISHI_LOOKOUT:
|
||||
case NPC_AMANISHI_PROTECTOR:
|
||||
case NPC_EAGLE_TRASH_AGGRO_TRIGGER:
|
||||
AkilzonTrash.insert(creature->GetGUID());
|
||||
break;
|
||||
@@ -226,8 +231,8 @@ public:
|
||||
case NPC_EAGLE_TRASH_AGGRO_TRIGGER:
|
||||
creature->DisappearAndDie();
|
||||
break;
|
||||
case NPC_AMINISHI_LOOKOUT:
|
||||
case NPC_AMINISHI_TEMPEST:
|
||||
case NPC_AMANISHI_LOOKOUT:
|
||||
case NPC_AMANISHI_TEMPEST:
|
||||
creature->AI()->DoAction(ACTION_START_AKILZON_GAUNTLET);
|
||||
break;
|
||||
default:
|
||||
@@ -243,7 +248,7 @@ public:
|
||||
{
|
||||
if (!creature->IsAlive())
|
||||
creature->Respawn();
|
||||
else if (creature->GetEntry() == NPC_AMINISHI_TEMPEST)
|
||||
else if (creature->GetEntry() == NPC_AMANISHI_TEMPEST)
|
||||
creature->AI()->DoAction(ACTION_RESET_AKILZON_GAUNTLET);
|
||||
}
|
||||
if (Creature* creature = GetCreature(DATA_LOOKOUT))
|
||||
@@ -259,7 +264,7 @@ public:
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_AMINISHI_PROTECTOR:
|
||||
case NPC_AMANISHI_PROTECTOR:
|
||||
case NPC_AMANISHI_WIND_WALKER:
|
||||
if (_akilzonGauntlet == NOT_STARTED && AkilzonTrash.contains(creature->GetGUID()))
|
||||
creature->DespawnOrUnsummon(30s, 1s);
|
||||
@@ -272,8 +277,8 @@ public:
|
||||
{
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_AMINISHI_TEMPEST:
|
||||
case NPC_AMINISHI_PROTECTOR:
|
||||
case NPC_AMANISHI_TEMPEST:
|
||||
case NPC_AMANISHI_PROTECTOR:
|
||||
case NPC_AMANISHI_WIND_WALKER:
|
||||
if (AkilzonTrash.contains(creature->GetGUID()))
|
||||
ResetAkilzonGauntlet();
|
||||
|
||||
@@ -358,8 +358,7 @@ enum DisplayIds
|
||||
enum EntryIds
|
||||
{
|
||||
NPC_HARRISON_JONES_1 = 24375,
|
||||
NPC_HARRISON_JONES_2 = 24365,
|
||||
NPC_AMANISHI_GUARDIAN = 23597,
|
||||
NPC_HARRISON_JONES_2 = 24365
|
||||
};
|
||||
|
||||
enum Weapons
|
||||
@@ -417,7 +416,10 @@ struct npc_harrison_jones : public ScriptedAI
|
||||
std::list<Creature*> creatures;
|
||||
me->GetCreatureListWithEntryInGrid(creatures, NPC_AMANISHI_SAVAGE, 100.0f);
|
||||
for (Creature* creature : creatures)
|
||||
{
|
||||
creature->SetImmuneToAll(false);
|
||||
creature->SetInCombatWithZone();
|
||||
}
|
||||
});
|
||||
_instance->StorePersistentData(DATA_TIMED_RUN, 21);
|
||||
_instance->DoAction(ACTION_START_TIMED_RUN);
|
||||
|
||||
@@ -60,11 +60,12 @@ enum CreatureIds
|
||||
NPC_AMANISHI_MEDICINE_MAN = 23581,
|
||||
NPC_AMANISHI_AXE_THROWER = 23542,
|
||||
NPC_AMANI_HATCHLING = 23598, // 42493
|
||||
NPC_AMANISHI_GUARDIAN = 23597,
|
||||
// Akil'zon gauntlet
|
||||
NPC_AMANISHI_WIND_WALKER = 24179,
|
||||
NPC_AMINISHI_LOOKOUT = 24175,
|
||||
NPC_AMINISHI_PROTECTOR = 24180,
|
||||
NPC_AMINISHI_TEMPEST = 24549,
|
||||
NPC_AMANISHI_LOOKOUT = 24175,
|
||||
NPC_AMANISHI_PROTECTOR = 24180,
|
||||
NPC_AMANISHI_TEMPEST = 24549,
|
||||
NPC_EAGLE_TRASH_AGGRO_TRIGGER = 24223
|
||||
};
|
||||
|
||||
|
||||
@@ -161,136 +161,37 @@ static float PyrewoodSpawnPoints[3][4] =
|
||||
{-397.018219f, 1510.208740f, 18.868748f, 4.731330f},
|
||||
};
|
||||
|
||||
#define WAIT_SECS 6000
|
||||
|
||||
class pyrewood_ambush : public CreatureScript
|
||||
struct npc_deathstalker_fearleia : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
pyrewood_ambush() : CreatureScript("pyrewood_ambush") { }
|
||||
|
||||
bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest) override
|
||||
npc_deathstalker_fearleia(Creature* creature) : ScriptedAI(creature), _summons(me)
|
||||
{
|
||||
if (quest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->QuestInProgress)
|
||||
{
|
||||
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->QuestInProgress = true;
|
||||
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->Phase = 0;
|
||||
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->KillCount = 0;
|
||||
CAST_AI(pyrewood_ambush::pyrewood_ambushAI, creature->AI())->PlayerGUID = player->GetGUID();
|
||||
}
|
||||
|
||||
return true;
|
||||
_questInProgress = false;
|
||||
}
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
void Reset() override
|
||||
{
|
||||
return new pyrewood_ambushAI(creature);
|
||||
if (!_questInProgress)
|
||||
{
|
||||
_playerGUID.Clear();
|
||||
_summons.DespawnAll();
|
||||
}
|
||||
}
|
||||
|
||||
struct pyrewood_ambushAI : public ScriptedAI
|
||||
void sQuestAccept(Player* player, Quest const* quest) override
|
||||
{
|
||||
pyrewood_ambushAI(Creature* creature) : ScriptedAI(creature), Summons(me)
|
||||
if (quest->GetQuestId() == QUEST_PYREWOOD_AMBUSH && !_questInProgress)
|
||||
{
|
||||
QuestInProgress = false;
|
||||
_questInProgress = true;
|
||||
_playerGUID = player->GetGUID();
|
||||
}
|
||||
|
||||
uint32 Phase;
|
||||
int8 KillCount;
|
||||
uint32 WaitTimer;
|
||||
ObjectGuid PlayerGUID;
|
||||
SummonList Summons;
|
||||
Talk(NPCSAY_INIT, player);
|
||||
|
||||
bool QuestInProgress;
|
||||
|
||||
void Reset() override
|
||||
scheduler.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
WaitTimer = WAIT_SECS;
|
||||
|
||||
if (!QuestInProgress) //fix reset values (see UpdateVictim)
|
||||
{
|
||||
Phase = 0;
|
||||
KillCount = 0;
|
||||
PlayerGUID.Clear();
|
||||
Summons.DespawnAll();
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override { }
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
Summons.Summon(summoned);
|
||||
++KillCount;
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
Summons.Despawn(summoned);
|
||||
--KillCount;
|
||||
}
|
||||
|
||||
void SummonCreatureWithRandomTarget(uint32 creatureId, int position)
|
||||
{
|
||||
if (Creature* summoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000))
|
||||
{
|
||||
Unit* target = nullptr;
|
||||
if (PlayerGUID)
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
|
||||
if (player->IsAlive() && RAND(0, 1))
|
||||
target = player;
|
||||
|
||||
if (!target)
|
||||
target = me;
|
||||
|
||||
summoned->SetFaction(FACTION_STORMWIND);
|
||||
summoned->AddThreat(target, 32.0f);
|
||||
summoned->AI()->AttackStart(target);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (PlayerGUID)
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
|
||||
if (player->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE)
|
||||
player->FailQuest(QUEST_PYREWOOD_AMBUSH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
//LOG_INFO("scripts", "DEBUG: p({}) k({}) d({}) W({})", Phase, KillCount, diff, WaitTimer);
|
||||
|
||||
if (!QuestInProgress)
|
||||
return;
|
||||
|
||||
if (KillCount && Phase < 6)
|
||||
{
|
||||
if (!UpdateVictim()) //reset() on target Despawn...
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (Phase)
|
||||
switch (context.GetRepeatCounter())
|
||||
{
|
||||
case 0:
|
||||
if (WaitTimer == WAIT_SECS)
|
||||
{
|
||||
if (PlayerGUID)
|
||||
{
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
|
||||
{
|
||||
me->AI()->Talk(NPCSAY_INIT, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (WaitTimer <= diff)
|
||||
{
|
||||
WaitTimer -= diff;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
SummonCreatureWithRandomTarget(2060, 1);
|
||||
break;
|
||||
case 2:
|
||||
@@ -309,21 +210,73 @@ public:
|
||||
SummonCreatureWithRandomTarget(2068, 2);
|
||||
break;
|
||||
case 5: //end
|
||||
if (PlayerGUID)
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
{
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID))
|
||||
{
|
||||
me->AI()->Talk(NPCSAY_END, player);
|
||||
player->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me);
|
||||
}
|
||||
Talk(NPCSAY_END, player);
|
||||
player->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, me);
|
||||
}
|
||||
QuestInProgress = false;
|
||||
_questInProgress = false;
|
||||
Reset();
|
||||
break;
|
||||
}
|
||||
++Phase; //prepare next phase
|
||||
|
||||
if (context.GetRepeatCounter() < 5)
|
||||
context.Repeat();
|
||||
});
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override {}
|
||||
|
||||
void JustSummoned(Creature* summoned) override
|
||||
{
|
||||
_summons.Summon(summoned);
|
||||
}
|
||||
|
||||
void SummonedCreatureDespawn(Creature* summoned) override
|
||||
{
|
||||
_summons.Despawn(summoned);
|
||||
}
|
||||
|
||||
void SummonCreatureWithRandomTarget(uint32 creatureId, int position)
|
||||
{
|
||||
if (Creature* summoned = me->SummonCreature(creatureId, PyrewoodSpawnPoints[position][0], PyrewoodSpawnPoints[position][1], PyrewoodSpawnPoints[position][2], PyrewoodSpawnPoints[position][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000))
|
||||
{
|
||||
Unit* target = nullptr;
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
if (player->IsAlive() && RAND(0, 1))
|
||||
target = player;
|
||||
|
||||
if (!target)
|
||||
target = me;
|
||||
|
||||
summoned->SetFaction(FACTION_STORMWIND);
|
||||
summoned->AddThreat(target, 32.0f);
|
||||
summoned->AI()->AttackStart(target);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
|
||||
if (player->GetQuestStatus(QUEST_PYREWOOD_AMBUSH) == QUEST_STATUS_INCOMPLETE)
|
||||
player->FailQuest(QUEST_PYREWOOD_AMBUSH);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (_questInProgress && !_summons.IsAnyCreatureAlive())
|
||||
scheduler.Update(diff);
|
||||
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _playerGUID;
|
||||
SummonList _summons;
|
||||
bool _questInProgress;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -485,6 +438,6 @@ public:
|
||||
void AddSC_silverpine_forest()
|
||||
{
|
||||
new npc_deathstalker_erland();
|
||||
new pyrewood_ambush();
|
||||
RegisterCreatureAI(npc_deathstalker_fearleia);
|
||||
new npc_ravenclaw_apparition();
|
||||
}
|
||||
|
||||
+13
-55
@@ -57,7 +57,6 @@ public:
|
||||
}
|
||||
|
||||
bool CLEANED;
|
||||
TeamId TeamIdInInstance;
|
||||
uint32 InstanceProgress;
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
std::string str_data;
|
||||
@@ -83,7 +82,6 @@ public:
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
InstanceProgress = 0;
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
|
||||
@@ -109,67 +107,49 @@ public:
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* pPlayer = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = pPlayer->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = pPlayer->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = pPlayer->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
// Grand Champions:
|
||||
case NPC_MOKRA:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_JACOB);
|
||||
break;
|
||||
case NPC_ERESSEA:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_AMBROSE);
|
||||
break;
|
||||
case NPC_RUNOK:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_COLOSOS);
|
||||
break;
|
||||
case NPC_ZULTORE:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_JAELYNE);
|
||||
break;
|
||||
case NPC_VISCERI:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_LANA);
|
||||
break;
|
||||
|
||||
// Grand Champion Minions:
|
||||
case NPC_ORGRIMMAR_MINION:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_STORMWIND_MINION);
|
||||
break;
|
||||
case NPC_SILVERMOON_MINION:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_GNOMEREGAN_MINION);
|
||||
break;
|
||||
case NPC_THUNDER_BLUFF_MINION:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_EXODAR_MINION);
|
||||
break;
|
||||
case NPC_SENJIN_MINION:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_DARNASSUS_MINION);
|
||||
break;
|
||||
case NPC_UNDERCITY_MINION:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_IRONFORGE_MINION);
|
||||
break;
|
||||
|
||||
@@ -183,7 +163,7 @@ public:
|
||||
case NPC_JAEREN:
|
||||
case NPC_ARELAS:
|
||||
NPC_AnnouncerGUID = creature->GetGUID();
|
||||
//if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
//if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
// creature->UpdateEntry(NPC_ARELAS);
|
||||
creature->SetReactState(REACT_PASSIVE);
|
||||
break;
|
||||
@@ -283,36 +263,14 @@ public:
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
InstanceScript::OnPlayerEnter(player);
|
||||
|
||||
if (DoNeedCleanup(player))
|
||||
{
|
||||
InstanceCleanup();
|
||||
}
|
||||
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, CLEANUP_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
bool DoNeedCleanup(Player* ignoredPlayer = nullptr)
|
||||
{
|
||||
uint8 aliveCount = 0;
|
||||
@@ -497,7 +455,7 @@ public:
|
||||
case DATA_INSTANCE_PROGRESS:
|
||||
return InstanceProgress;
|
||||
case DATA_TEAMID_IN_INSTANCE:
|
||||
return TeamIdInInstance;
|
||||
return GetTeamIdInInstance();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+21
-79
@@ -41,7 +41,6 @@ public:
|
||||
uint32 EncounterStatus;
|
||||
uint32 InstanceProgress;
|
||||
uint32 AttemptsLeft;
|
||||
TeamId TeamIdInInstance;
|
||||
uint8 Counter;
|
||||
uint8 northrendBeastsMask;
|
||||
uint32 AchievementTimer;
|
||||
@@ -168,7 +167,6 @@ public:
|
||||
EncounterStatus = NOT_STARTED;
|
||||
InstanceProgress = INSTANCE_PROGRESS_INITIAL;
|
||||
AttemptsLeft = 50;
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
Counter = 0;
|
||||
northrendBeastsMask = 0;
|
||||
AchievementTimer = 0;
|
||||
@@ -475,7 +473,7 @@ public:
|
||||
case TYPE_FACTION_CHAMPIONS_PLAYER_DIED:
|
||||
if (urand(0, 2) == 0 )
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
{
|
||||
if (Creature* pTemp = instance->GetCreature(NPC_VarianGUID))
|
||||
pTemp->AI()->Talk(SAY_VARIAN_KILL_HORDE_PLAYER_1);
|
||||
@@ -971,16 +969,7 @@ public:
|
||||
}
|
||||
case EVENT_SCENE_202:
|
||||
{
|
||||
Map::PlayerList const& pl = instance->GetPlayers();
|
||||
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
|
||||
if (Player* plr = itr->GetSource())
|
||||
if (!plr->IsGameMaster())
|
||||
{
|
||||
TeamIdInInstance = plr->GetTeamId();
|
||||
break;
|
||||
}
|
||||
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
{
|
||||
if (Creature* c = instance->GetCreature(NPC_GarroshGUID))
|
||||
c->AI()->Talk(SAY_STAGE_2_02h);
|
||||
@@ -1004,7 +993,7 @@ public:
|
||||
}
|
||||
case EVENT_SCENE_204:
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
{
|
||||
if (Creature* c = instance->GetCreature(NPC_GarroshGUID))
|
||||
c->AI()->Talk(SAY_STAGE_2_04h);
|
||||
@@ -1022,26 +1011,26 @@ public:
|
||||
}
|
||||
case EVENT_SCENE_205:
|
||||
{
|
||||
if (Creature* c = instance->GetCreature(TeamIdInInstance == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
|
||||
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_STAGE_2_05a : SAY_STAGE_2_05h);
|
||||
if (Creature* c = instance->GetCreature(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
|
||||
c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_STAGE_2_05a : SAY_STAGE_2_05h);
|
||||
|
||||
break;
|
||||
}
|
||||
case EVENT_SUMMON_CHAMPIONS:
|
||||
{
|
||||
std::vector<uint32> vHealerEntries;
|
||||
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_DRUID_RESTORATION : NPC_ALLIANCE_DRUID_RESTORATION);
|
||||
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_PALADIN_HOLY : NPC_ALLIANCE_PALADIN_HOLY);
|
||||
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_PRIEST_DISCIPLINE : NPC_ALLIANCE_PRIEST_DISCIPLINE);
|
||||
vHealerEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_SHAMAN_RESTORATION : NPC_ALLIANCE_SHAMAN_RESTORATION);
|
||||
vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_DRUID_RESTORATION : NPC_ALLIANCE_DRUID_RESTORATION);
|
||||
vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_PALADIN_HOLY : NPC_ALLIANCE_PALADIN_HOLY);
|
||||
vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_PRIEST_DISCIPLINE : NPC_ALLIANCE_PRIEST_DISCIPLINE);
|
||||
vHealerEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_SHAMAN_RESTORATION : NPC_ALLIANCE_SHAMAN_RESTORATION);
|
||||
|
||||
std::vector<uint32> vOtherEntries;
|
||||
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_DEATH_KNIGHT : NPC_ALLIANCE_DEATH_KNIGHT);
|
||||
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_HUNTER : NPC_ALLIANCE_HUNTER);
|
||||
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_MAGE : NPC_ALLIANCE_MAGE);
|
||||
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_ROGUE : NPC_ALLIANCE_ROGUE);
|
||||
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_WARLOCK : NPC_ALLIANCE_WARLOCK);
|
||||
vOtherEntries.push_back(TeamIdInInstance == TEAM_ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR);
|
||||
vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_DEATH_KNIGHT : NPC_ALLIANCE_DEATH_KNIGHT);
|
||||
vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_HUNTER : NPC_ALLIANCE_HUNTER);
|
||||
vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_MAGE : NPC_ALLIANCE_MAGE);
|
||||
vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_ROGUE : NPC_ALLIANCE_ROGUE);
|
||||
vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_WARLOCK : NPC_ALLIANCE_WARLOCK);
|
||||
vOtherEntries.push_back(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_HORDE_WARRIOR : NPC_ALLIANCE_WARRIOR);
|
||||
|
||||
uint8 healersSubtracted = 2;
|
||||
if (instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_NORMAL || instance->GetSpawnMode() == RAID_DIFFICULTY_25MAN_HEROIC )
|
||||
@@ -1089,11 +1078,11 @@ public:
|
||||
uint8 pos2 = 10;
|
||||
for( std::vector<uint32>::iterator itr = vOtherEntries.begin(); itr != vOtherEntries.end(); ++itr )
|
||||
{
|
||||
if (Creature* pTemp = instance->SummonCreature(*itr, FactionChampionLoc[urand(0, 4) + (TeamIdInInstance == TEAM_ALLIANCE ? 0 : 5)]))
|
||||
if (Creature* pTemp = instance->SummonCreature(*itr, FactionChampionLoc[urand(0, 4) + (GetTeamIdInInstance() == TEAM_ALLIANCE ? 0 : 5)]))
|
||||
{
|
||||
NPC_ChampionGUIDs.push_back(pTemp->GetGUID());
|
||||
pTemp->SetHomePosition((TeamIdInInstance == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 0.0f);
|
||||
pTemp->GetMotionMaster()->MoveJump((TeamIdInInstance == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 20.0f, 20.0f);
|
||||
pTemp->SetHomePosition((GetTeamIdInInstance() == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 0.0f);
|
||||
pTemp->GetMotionMaster()->MoveJump((GetTeamIdInInstance() == TEAM_ALLIANCE ? FactionChampionLoc[pos2].GetPositionX() : (Locs[LOC_CENTER].GetPositionX() * 2 - FactionChampionLoc[pos2].GetPositionX())), FactionChampionLoc[pos2].GetPositionY(), FactionChampionLoc[pos2].GetPositionZ(), 20.0f, 20.0f);
|
||||
}
|
||||
++pos2;
|
||||
}
|
||||
@@ -1196,35 +1185,8 @@ public:
|
||||
}
|
||||
case EVENT_SCENE_VALKYR_DEAD:
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& pl = instance->GetPlayers();
|
||||
for( Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr )
|
||||
if (Player* plr = itr->GetSource())
|
||||
if (!plr->IsGameMaster())
|
||||
{
|
||||
if (Group* group = plr->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
{
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
TeamIdInInstance = plr->GetTeamId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TeamIdInInstance = plr->GetTeamId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Creature* c = instance->GetCreature(TeamIdInInstance == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
|
||||
c->AI()->Talk((TeamIdInInstance == TEAM_ALLIANCE ? SAY_STAGE_3_03a : SAY_STAGE_3_03h));
|
||||
if (Creature* c = instance->GetCreature(GetTeamIdInInstance() == TEAM_ALLIANCE ? NPC_VarianGUID : NPC_GarroshGUID))
|
||||
c->AI()->Talk((GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_STAGE_3_03a : SAY_STAGE_3_03h));
|
||||
|
||||
events.RescheduleEvent(EVENT_SCENE_401, 60000);
|
||||
break;
|
||||
@@ -1413,21 +1375,7 @@ public:
|
||||
|
||||
void OnPlayerEnter(Player* plr) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = plr->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = plr->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = plr->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
plr->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
InstanceScript::OnPlayerEnter(plr);
|
||||
|
||||
if (instance->IsHeroic())
|
||||
{
|
||||
@@ -1448,12 +1396,6 @@ public:
|
||||
events.RescheduleEvent(EVENT_CHECK_PLAYERS, 5s);
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
bool DoNeedCleanup(Player* ignoredPlayer = nullptr)
|
||||
{
|
||||
uint8 aliveCount = 0;
|
||||
|
||||
@@ -96,12 +96,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (teamIdInInstance == TEAM_NEUTRAL)
|
||||
|
||||
+16
-72
@@ -144,7 +144,6 @@ public:
|
||||
};
|
||||
|
||||
uint32 EncounterMask;
|
||||
TeamId TeamIdInInstance;
|
||||
ObjectGuid NPC_FalricGUID;
|
||||
ObjectGuid NPC_MarwynGUID;
|
||||
ObjectGuid NPC_LichKingIntroGUID;
|
||||
@@ -190,7 +189,6 @@ public:
|
||||
void Initialize() override
|
||||
{
|
||||
EncounterMask = 0;
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
memset(&TrashActive, 0, sizeof(TrashActive));
|
||||
TrashCounter = 0;
|
||||
memset(&chosenComposition, 0, sizeof(chosenComposition));
|
||||
@@ -214,69 +212,15 @@ public:
|
||||
return (instance->HavePlayers() && WaveNumber) || IsDuringLKFight; // during LK fight npcs are active and will unset this variable
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
|
||||
if (Player* p = itr->GetSource())
|
||||
if (!p->IsGameMaster())
|
||||
{
|
||||
if (Group* group = p->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
{
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
TeamIdInInstance = p->GetTeamId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TeamIdInInstance = p->GetTeamId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_SYLVANAS_PART1:
|
||||
creature->SetVisible(false);
|
||||
creature->SetSpeed(MOVE_RUN, 1.1);
|
||||
NPC_LeaderIntroGUID = creature->GetGUID();
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART1);
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
|
||||
creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
@@ -284,7 +228,7 @@ public:
|
||||
case NPC_DARK_RANGER_LORALEN:
|
||||
creature->SetVisible(false);
|
||||
NPC_GuardGUID = creature->GetGUID();
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ARCHMAGE_KORELN);
|
||||
break;
|
||||
case NPC_UTHER:
|
||||
@@ -345,7 +289,7 @@ public:
|
||||
creature->CastSpell(creature, SPELL_SOUL_REAPER, true);
|
||||
}
|
||||
else if (!(EncounterMask & (1 << DATA_LICH_KING)))
|
||||
creature->AddAura(TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, creature);
|
||||
creature->AddAura(GetTeamIdInInstance() == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, creature);
|
||||
else
|
||||
creature->SetVisible(false);
|
||||
|
||||
@@ -359,7 +303,7 @@ public:
|
||||
NPC_LeaderGUID = creature->GetGUID();
|
||||
creature->SetWalk(false);
|
||||
creature->SetSheath(SHEATH_STATE_MELEE);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART2);
|
||||
creature->SetWalk(false);
|
||||
creature->SetHealth(creature->GetMaxHealth() / 20);
|
||||
@@ -368,9 +312,9 @@ public:
|
||||
if (!(EncounterMask & (1 << DATA_LK_INTRO)))
|
||||
{
|
||||
creature->SetSheath(SHEATH_STATE_MELEE);
|
||||
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, TeamIdInInstance == TEAM_ALLIANCE ? EMOTE_ONESHOT_ATTACK2HTIGHT : EMOTE_ONESHOT_ATTACK1H); //the fight cannot be in the form of an emote, it is causing bugs.
|
||||
creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, GetTeamIdInInstance() == TEAM_ALLIANCE ? EMOTE_ONESHOT_ATTACK2HTIGHT : EMOTE_ONESHOT_ATTACK1H); //the fight cannot be in the form of an emote, it is causing bugs.
|
||||
creature->RemoveNpcFlag(UNIT_NPC_FLAG_GOSSIP | UNIT_NPC_FLAG_QUESTGIVER);
|
||||
creature->CastSpell(creature, TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_BARRIER : SPELL_SYLVANAS_CLOAK_OF_DARKNESS, true);
|
||||
creature->CastSpell(creature, GetTeamIdInInstance() == TEAM_ALLIANCE ? SPELL_JAINA_ICE_BARRIER : SPELL_SYLVANAS_CLOAK_OF_DARKNESS, true);
|
||||
}
|
||||
else if (!(EncounterMask & (1 << DATA_LICH_KING)))
|
||||
{
|
||||
@@ -577,7 +521,7 @@ public:
|
||||
if (!c->IsAlive())
|
||||
{
|
||||
c->Respawn();
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
c->UpdateEntry(NPC_JAINA_PART2);
|
||||
}
|
||||
c->GetThreatMgr().ClearAllThreat();
|
||||
@@ -605,7 +549,7 @@ public:
|
||||
c->UpdatePosition(c->GetHomePosition(), true);
|
||||
c->StopMovingOnCurrentPos();
|
||||
c->RemoveAllAuras();
|
||||
c->AddAura(TeamIdInInstance == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, c);
|
||||
c->AddAura(GetTeamIdInInstance() == TEAM_ALLIANCE ? SPELL_JAINA_ICE_PRISON : SPELL_SYLVANAS_DARK_BINDING, c);
|
||||
c->AI()->Reset();
|
||||
c->setActive(false);
|
||||
c->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
@@ -1126,18 +1070,18 @@ public:
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
uint32 entry = TeamIdInInstance == TEAM_ALLIANCE ? GO_THE_SKYBREAKER : GO_ORGRIMS_HAMMER;
|
||||
uint32 entry = GetTeamIdInInstance() == TEAM_ALLIANCE ? GO_THE_SKYBREAKER : GO_ORGRIMS_HAMMER;
|
||||
T1 = sTransportMgr->CreateTransport(entry, 0, instance);
|
||||
|
||||
++outroStep;
|
||||
outroTimer = TeamIdInInstance == TEAM_ALLIANCE ? 10000 : 10500;
|
||||
outroTimer = GetTeamIdInInstance() == TEAM_ALLIANCE ? 10000 : 10500;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (T1)
|
||||
T1->EnableMovement(false);
|
||||
if (Creature* c = instance->GetCreature(NPC_ShipCaptainGUID))
|
||||
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_FIRE_ALLY : SAY_FIRE_HORDE);
|
||||
c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_FIRE_ALLY : SAY_FIRE_HORDE);
|
||||
if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
|
||||
{
|
||||
c->RemoveAllAuras();
|
||||
@@ -1185,10 +1129,10 @@ public:
|
||||
T1->EnableMovement(false);
|
||||
if (Creature* leader = instance->GetCreature(NPC_LeaderGUID))
|
||||
{
|
||||
uint8 index = TeamIdInInstance == TEAM_ALLIANCE ? 0 : 1;
|
||||
uint8 index = GetTeamIdInInstance() == TEAM_ALLIANCE ? 0 : 1;
|
||||
for (uint8 i = 0; i < 3; ++i)
|
||||
if (StairsPos[index][i].GetPositionX())
|
||||
if (GameObject* go = leader->SummonGameObject(TeamIdInInstance == TEAM_ALLIANCE ? GO_STAIRS_ALLIANCE : GO_STAIRS_HORDE, StairsPos[index][i].GetPositionX(), StairsPos[index][i].GetPositionY(), StairsPos[index][i].GetPositionZ(), StairsPos[index][i].GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400, false))
|
||||
if (GameObject* go = leader->SummonGameObject(GetTeamIdInInstance() == TEAM_ALLIANCE ? GO_STAIRS_ALLIANCE : GO_STAIRS_HORDE, StairsPos[index][i].GetPositionX(), StairsPos[index][i].GetPositionY(), StairsPos[index][i].GetPositionZ(), StairsPos[index][i].GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400, false))
|
||||
go->SetGameObjectFlag(GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE);
|
||||
//Position pos = TeamIdInInstance == TEAM_ALLIANCE ? AllyPortalPos : HordePortalPos;
|
||||
//leader->SummonGameObject(GO_PORTAL_TO_DALARAN, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 86400);
|
||||
@@ -1200,7 +1144,7 @@ public:
|
||||
break;
|
||||
case 8:
|
||||
if (Creature* c = instance->GetCreature(NPC_ShipCaptainGUID))
|
||||
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_ONBOARD_ALLY : SAY_ONBOARD_HORDE);
|
||||
c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_ONBOARD_ALLY : SAY_ONBOARD_HORDE);
|
||||
if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
|
||||
{
|
||||
c->AddUnitMovementFlag(MOVEMENTFLAG_WALKING);
|
||||
@@ -1212,7 +1156,7 @@ public:
|
||||
break;
|
||||
case 9:
|
||||
if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
|
||||
c->AI()->Talk(TeamIdInInstance == TEAM_ALLIANCE ? SAY_JAINA_FINAL_1 : SAY_SYLVANA_FINAL);
|
||||
c->AI()->Talk(GetTeamIdInInstance() == TEAM_ALLIANCE ? SAY_JAINA_FINAL_1 : SAY_SYLVANA_FINAL);
|
||||
HandleGameObject(GO_CaveInGUID, true);
|
||||
++outroStep;
|
||||
outroTimer = 11000;
|
||||
@@ -1223,7 +1167,7 @@ public:
|
||||
for (Map::PlayerList::const_iterator itr = instance->GetPlayers().begin(); itr != instance->GetPlayers().end(); ++itr)
|
||||
if (Player* p = itr->GetSource())
|
||||
p->KilledMonsterCredit(NPC_WRATH_OF_THE_LICH_KING_CREDIT);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
if (Creature* c = instance->GetCreature(NPC_LeaderGUID))
|
||||
{
|
||||
c->AI()->Talk(SAY_JAINA_FINAL_2);
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
}
|
||||
|
||||
uint32 m_auiEncounter[MAX_ENCOUNTER];
|
||||
TeamId teamIdInInstance;
|
||||
uint32 InstanceProgress;
|
||||
std::string str_data;
|
||||
|
||||
@@ -61,7 +60,6 @@ public:
|
||||
void Initialize() override
|
||||
{
|
||||
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
|
||||
teamIdInInstance = TEAM_NEUTRAL;
|
||||
InstanceProgress = INSTANCE_PROGRESS_NONE;
|
||||
|
||||
bAchievEleven = true;
|
||||
@@ -78,62 +76,24 @@ public:
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (teamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
teamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
teamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
teamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFaction((teamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
InstanceScript::OnPlayerEnter(player);
|
||||
|
||||
instance->LoadGrid(LeaderIntroPos.GetPositionX(), LeaderIntroPos.GetPositionY());
|
||||
if (Creature* c = instance->GetCreature(GetGuidData(DATA_LEADER_FIRST_GUID)))
|
||||
c->AI()->SetData(DATA_START_INTRO, 0);
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
|
||||
{
|
||||
if (teamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
teamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
teamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
teamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 entry = data->id1;
|
||||
switch (entry)
|
||||
{
|
||||
case NPC_RESCUED_ALLIANCE_SLAVE:
|
||||
if (teamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
return 0;
|
||||
break;
|
||||
case NPC_RESCUED_HORDE_SLAVE:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
@@ -143,28 +103,10 @@ public:
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (teamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
teamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
teamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
teamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_SYLVANAS_PART1:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART1);
|
||||
NPC_LeaderFirstGUID = creature->GetGUID();
|
||||
|
||||
@@ -183,7 +125,7 @@ public:
|
||||
}
|
||||
break;
|
||||
case NPC_SYLVANAS_PART2:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JAINA_PART2);
|
||||
NPC_LeaderSecondGUID = creature->GetGUID();
|
||||
break;
|
||||
@@ -213,50 +155,50 @@ public:
|
||||
}
|
||||
break;
|
||||
case NPC_LORALEN:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ELANDRA);
|
||||
if (!NPC_GuardFirstGUID)
|
||||
NPC_GuardFirstGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_KALIRA:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_KORELN);
|
||||
if (!NPC_GuardSecondGUID)
|
||||
NPC_GuardSecondGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_HORDE_SLAVE_1:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_1);
|
||||
break;
|
||||
case NPC_HORDE_SLAVE_2:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_2);
|
||||
break;
|
||||
case NPC_HORDE_SLAVE_3:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_3);
|
||||
break;
|
||||
case NPC_HORDE_SLAVE_4:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ALLIANCE_SLAVE_4);
|
||||
break;
|
||||
case NPC_GORKUN_IRONSKULL_1:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_MARTIN_VICTUS_1);
|
||||
break;
|
||||
case NPC_GARFROST:
|
||||
NPC_GarfrostGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_FREED_SLAVE_1_HORDE:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_FREED_SLAVE_1_ALLIANCE);
|
||||
break;
|
||||
case NPC_FREED_SLAVE_2_HORDE:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_FREED_SLAVE_2_ALLIANCE);
|
||||
break;
|
||||
case NPC_FREED_SLAVE_3_HORDE:
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_FREED_SLAVE_3_ALLIANCE);
|
||||
break;
|
||||
case NPC_GORKUN_IRONSKULL_2:
|
||||
@@ -266,7 +208,7 @@ public:
|
||||
c->AI()->DoAction(1); // despawn summons
|
||||
c->DespawnOrUnsummon();
|
||||
}
|
||||
if (teamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_MARTIN_VICTUS_2);
|
||||
NPC_MartinOrGorkunGUID = creature->GetGUID();
|
||||
break;
|
||||
@@ -370,7 +312,7 @@ public:
|
||||
case DATA_INSTANCE_PROGRESS:
|
||||
return InstanceProgress;
|
||||
case DATA_TEAMID_IN_INSTANCE:
|
||||
return teamIdInInstance;
|
||||
return GetTeamIdInInstance();
|
||||
case DATA_GARFROST:
|
||||
return m_auiEncounter[0];
|
||||
case DATA_ICK:
|
||||
|
||||
@@ -218,7 +218,6 @@ public:
|
||||
LoadBossBoundaries(boundaries);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
HeroicAttempts = MaxHeroicAttempts;
|
||||
IsBonedEligible = true;
|
||||
IsOozeDanceEligible = true;
|
||||
@@ -261,22 +260,7 @@ public:
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
|
||||
InstanceScript::OnPlayerEnter(player);
|
||||
// for professor putricide hc
|
||||
DoRemoveAurasDueToSpellOnPlayers(SPELL_GAS_VARIABLE);
|
||||
DoRemoveAurasDueToSpellOnPlayers(SPELL_OOZE_VARIABLE);
|
||||
@@ -306,32 +290,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
// apply ICC buff to pets/summons
|
||||
if (GetData(DATA_BUFF_AVAILABLE) && creature->GetOwnerGUID().IsPlayer() && creature->HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && creature->CanHaveThreatList())
|
||||
if (Unit* owner = creature->GetOwner())
|
||||
@@ -377,39 +337,39 @@ public:
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_KOR_KRON_GENERAL:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ALLIANCE_COMMANDER);
|
||||
break;
|
||||
case NPC_KOR_KRON_LIEUTENANT:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_SKYBREAKER_LIEUTENANT);
|
||||
break;
|
||||
case NPC_TORTUNOK:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_ALANA_MOONSTRIKE);
|
||||
break;
|
||||
case NPC_GERARDO_THE_SUAVE:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_TALAN_MOONSTRIKE);
|
||||
break;
|
||||
case NPC_UVLUS_BANEFIRE:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_MALFUS_GRIMFROST);
|
||||
break;
|
||||
case NPC_IKFIRUS_THE_VILE:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_YILI);
|
||||
break;
|
||||
case NPC_VOL_GUK:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_JEDEBIA);
|
||||
break;
|
||||
case NPC_HARAGG_THE_UNSEEN:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_NIBY_THE_ALMIGHTY);
|
||||
break;
|
||||
case NPC_GARROSH_HELLSCREAM:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_KING_VARIAN_WRYNN);
|
||||
|
||||
// Xinef: summon in case of instance unload
|
||||
@@ -428,7 +388,7 @@ public:
|
||||
DeathbringerSaurfangGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_SE_HIGH_OVERLORD_SAURFANG:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
{
|
||||
creature->UpdateEntry(NPC_SE_MURADIN_BRONZEBEARD, true);
|
||||
creature->LoadEquipment();
|
||||
@@ -440,14 +400,14 @@ public:
|
||||
DeathbringerSaurfangEventGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_HIGH_OVERLORD_SAURFANG_DUMMY:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
{
|
||||
creature->UpdateEntry(NPC_MURADIN_BRONZEBEARD_DUMMY, creature->GetCreatureData());
|
||||
creature->LoadEquipment();
|
||||
}
|
||||
break;
|
||||
case NPC_SE_KOR_KRON_REAVER:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_SE_SKYBREAKER_MARINE);
|
||||
break;
|
||||
case NPC_FESTERGUT:
|
||||
@@ -579,52 +539,34 @@ public:
|
||||
|
||||
uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
uint32 entry = data->id1;
|
||||
switch (entry)
|
||||
{
|
||||
case NPC_HORDE_GUNSHIP_CANNON:
|
||||
case NPC_ORGRIMS_HAMMER_CREW:
|
||||
case NPC_SKY_REAVER_KORM_BLACKSCAR:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
return 0;
|
||||
break;
|
||||
case NPC_ALLIANCE_GUNSHIP_CANNON:
|
||||
case NPC_SKYBREAKER_DECKHAND:
|
||||
case NPC_HIGH_CAPTAIN_JUSTIN_BARTLETT:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
return 0;
|
||||
break;
|
||||
case NPC_ZAFOD_BOOMBOX:
|
||||
if (GameObjectTemplate const* go = sObjectMgr->GetGameObjectTemplate(GO_THE_SKYBREAKER_A))
|
||||
if ((TeamIdInInstance == TEAM_ALLIANCE && data->mapid == go->moTransport.mapID) ||
|
||||
(TeamIdInInstance == TEAM_HORDE && data->mapid != go->moTransport.mapID))
|
||||
if ((GetTeamIdInInstance() == TEAM_ALLIANCE && data->mapid == go->moTransport.mapID) ||
|
||||
(GetTeamIdInInstance() == TEAM_HORDE && data->mapid != go->moTransport.mapID))
|
||||
return entry;
|
||||
return 0;
|
||||
case NPC_IGB_MURADIN_BRONZEBEARD:
|
||||
if ((TeamIdInInstance == TEAM_ALLIANCE && data->posX > 10.0f) ||
|
||||
(TeamIdInInstance == TEAM_HORDE && data->posX < 10.0f))
|
||||
if ((GetTeamIdInInstance() == TEAM_ALLIANCE && data->posX > 10.0f) ||
|
||||
(GetTeamIdInInstance() == TEAM_HORDE && data->posX < 10.0f))
|
||||
return entry;
|
||||
return 0;
|
||||
case NPC_SPIRE_FROSTWYRM:
|
||||
if ((TeamIdInInstance == TEAM_ALLIANCE && data->posY < 2200.0f) || (TeamIdInInstance == TEAM_HORDE && data->posY > 2200.0f))
|
||||
if ((GetTeamIdInInstance() == TEAM_ALLIANCE && data->posY < 2200.0f) || (GetTeamIdInInstance() == TEAM_HORDE && data->posY > 2200.0f))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
@@ -634,38 +576,20 @@ public:
|
||||
|
||||
uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
switch (entry)
|
||||
{
|
||||
case GO_GUNSHIP_ARMORY_H_10N:
|
||||
case GO_GUNSHIP_ARMORY_H_25N:
|
||||
case GO_GUNSHIP_ARMORY_H_10H:
|
||||
case GO_GUNSHIP_ARMORY_H_25H:
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
return 0;
|
||||
break;
|
||||
case GO_GUNSHIP_ARMORY_A_10N:
|
||||
case GO_GUNSHIP_ARMORY_A_25N:
|
||||
case GO_GUNSHIP_ARMORY_A_10H:
|
||||
case GO_GUNSHIP_ARMORY_A_25H:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
@@ -748,24 +672,6 @@ public:
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
switch (go->GetEntry())
|
||||
{
|
||||
case GO_SPIRIT_ALARM_1:
|
||||
@@ -1021,7 +927,7 @@ public:
|
||||
case DATA_COLDFLAME_JETS:
|
||||
return ColdflameJetsState;
|
||||
case DATA_TEAMID_IN_INSTANCE:
|
||||
return TeamIdInInstance;
|
||||
return GetTeamIdInInstance();
|
||||
case DATA_BLOOD_QUICKENING_STATE:
|
||||
return BloodQuickeningState;
|
||||
case DATA_HEROIC_ATTEMPTS:
|
||||
@@ -1315,7 +1221,7 @@ public:
|
||||
if (!GunshipGUID && instance->HavePlayers())
|
||||
{
|
||||
SetBossState(DATA_ICECROWN_GUNSHIP_BATTLE, NOT_STARTED);
|
||||
uint32 gunshipEntry = TeamIdInInstance == TEAM_HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A;
|
||||
uint32 gunshipEntry = GetTeamIdInInstance() == TEAM_HORDE ? GO_ORGRIMS_HAMMER_H : GO_THE_SKYBREAKER_A;
|
||||
if (MotionTransport* gunship = sTransportMgr->CreateTransport(gunshipEntry, 0, instance))
|
||||
{
|
||||
GunshipGUID = gunship->GetGUID();
|
||||
@@ -1880,7 +1786,7 @@ public:
|
||||
}
|
||||
break;
|
||||
case EVENT_ENEMY_GUNSHIP_COMBAT:
|
||||
if (Creature* captain = source->FindNearestCreature(TeamIdInInstance == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
|
||||
if (Creature* captain = source->FindNearestCreature(GetTeamIdInInstance() == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
|
||||
{
|
||||
captain->AI()->DoAction(ACTION_ENEMY_GUNSHIP_TALK);
|
||||
}
|
||||
@@ -1900,7 +1806,7 @@ public:
|
||||
//After movement is stopped remove the backpack
|
||||
RemoveBackPack();
|
||||
}
|
||||
if (Creature* captain = source->FindNearestCreature(TeamIdInInstance == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
|
||||
if (Creature* captain = source->FindNearestCreature(GetTeamIdInInstance() == TEAM_HORDE ? NPC_IGB_HIGH_OVERLORD_SAURFANG : NPC_IGB_MURADIN_BRONZEBEARD, 200.0f))
|
||||
captain->AI()->DoAction(ACTION_EXIT_SHIP);
|
||||
break;
|
||||
|
||||
@@ -2066,7 +1972,6 @@ public:
|
||||
ObjectGuid FrozenBolvarGUID;
|
||||
ObjectGuid PillarsChainedGUID;
|
||||
ObjectGuid PillarsUnchainedGUID;
|
||||
TeamId TeamIdInInstance;
|
||||
uint32 ColdflameJetsState;
|
||||
std::set<ObjectGuid::LowType> FrostwyrmGUIDs;
|
||||
std::set<ObjectGuid::LowType> SpinestalkerTrash;
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "naxxramas.h"
|
||||
|
||||
static constexpr uint8 HorsemanCount = 4;
|
||||
|
||||
const float HeiganPos[2] = {2796, -3707};
|
||||
const float HeiganEruptionSlope[3] =
|
||||
{
|
||||
@@ -94,13 +96,12 @@ public:
|
||||
PatchwerkRoomTrash.clear();
|
||||
|
||||
// Controls
|
||||
_horsemanKilled = 0;
|
||||
_speakTimer = 0;
|
||||
_horsemanTimer = 0;
|
||||
_screamTimer = 2 * MINUTE * IN_MILLISECONDS;
|
||||
_hadThaddiusGreet = false;
|
||||
_currentWingTaunt = SAY_FIRST_WING_TAUNT;
|
||||
_horsemanLoadDoneState = false;
|
||||
_horsemanLoaded = 0;
|
||||
|
||||
// Achievements
|
||||
abominationsKilled = 0;
|
||||
@@ -167,14 +168,13 @@ public:
|
||||
ObjectGuid _lichkingGUID;
|
||||
|
||||
// Controls
|
||||
uint8 _horsemanKilled;
|
||||
uint32 _speakTimer;
|
||||
uint32 _horsemanTimer;
|
||||
uint32 _screamTimer;
|
||||
bool _hadThaddiusGreet;
|
||||
EventMap events;
|
||||
uint8 _currentWingTaunt;
|
||||
bool _horsemanLoadDoneState;
|
||||
uint8 _horsemanLoaded;
|
||||
|
||||
// Achievements
|
||||
uint8 abominationsKilled;
|
||||
@@ -251,15 +251,19 @@ public:
|
||||
return;
|
||||
case NPC_LADY_BLAUMEUX:
|
||||
_blaumeuxGUID = creature->GetGUID();
|
||||
++_horsemanLoaded;
|
||||
return;
|
||||
case NPC_SIR_ZELIEK:
|
||||
_zeliekGUID = creature->GetGUID();
|
||||
++_horsemanLoaded;
|
||||
return;
|
||||
case NPC_BARON_RIVENDARE:
|
||||
_rivendareGUID = creature->GetGUID();
|
||||
++_horsemanLoaded;
|
||||
return;
|
||||
case NPC_THANE_KORTHAZZ:
|
||||
_korthazzGUID = creature->GetGUID();
|
||||
++_horsemanLoaded;
|
||||
return;
|
||||
case NPC_SAPPHIRON:
|
||||
_sapphironGUID = creature->GetGUID();
|
||||
@@ -272,6 +276,9 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
if (_horsemanLoaded == HorsemanCount)
|
||||
SetBossState(BOSS_HORSEMAN, GetBossState(BOSS_HORSEMAN));
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
|
||||
@@ -681,13 +688,25 @@ public:
|
||||
}
|
||||
|
||||
// Horseman handling
|
||||
if (bossId == BOSS_HORSEMAN && !_horsemanLoadDoneState)
|
||||
if (bossId == BOSS_HORSEMAN && _horsemanLoaded == HorsemanCount)
|
||||
{
|
||||
uint8 horsemanKilled {};
|
||||
if (Creature* cr = instance->GetCreature(_blaumeuxGUID))
|
||||
horsemanKilled += !cr->IsAlive();
|
||||
|
||||
if (Creature* cr = instance->GetCreature(_rivendareGUID))
|
||||
horsemanKilled += !cr->IsAlive();
|
||||
|
||||
if (Creature* cr = instance->GetCreature(_zeliekGUID))
|
||||
horsemanKilled += !cr->IsAlive();
|
||||
|
||||
if (Creature* cr = instance->GetCreature(_korthazzGUID))
|
||||
horsemanKilled += !cr->IsAlive();
|
||||
|
||||
if (state == DONE)
|
||||
{
|
||||
_horsemanTimer++;
|
||||
_horsemanKilled++;
|
||||
if (_horsemanKilled < 4)
|
||||
if (horsemanKilled < HorsemanCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -699,10 +718,9 @@ public:
|
||||
}
|
||||
|
||||
// respawn
|
||||
else if (state == NOT_STARTED && _horsemanKilled > 0)
|
||||
else if (state == NOT_STARTED && horsemanKilled > 0)
|
||||
{
|
||||
Creature* cr;
|
||||
_horsemanKilled = 0;
|
||||
if ((cr = instance->GetCreature(_blaumeuxGUID)))
|
||||
{
|
||||
if (!cr->IsAlive())
|
||||
|
||||
@@ -49,85 +49,40 @@ public:
|
||||
SetHeaders(DataHeader);
|
||||
SetBossNumber(MAX_ENCOUNTERS);
|
||||
LoadDoorData(doorData);
|
||||
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* pPlayer = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = pPlayer->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = pPlayer->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = pPlayer->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_ALLIANCE_RANGER:
|
||||
creature->SetFaction(FACTION_MONSTER_2);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_HORDE_RANGER);
|
||||
break;
|
||||
case NPC_ALLIANCE_BERSERKER:
|
||||
creature->SetFaction(FACTION_MONSTER_2);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_HORDE_BERSERKER);
|
||||
break;
|
||||
case NPC_ALLIANCE_COMMANDER:
|
||||
creature->SetFaction(FACTION_MONSTER_2);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_HORDE_COMMANDER);
|
||||
break;
|
||||
case NPC_ALLIANCE_CLERIC:
|
||||
creature->SetFaction(FACTION_MONSTER_2);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_HORDE_CLERIC);
|
||||
break;
|
||||
case NPC_COMMANDER_STOUTBEARD:
|
||||
creature->SetFaction(FACTION_MONSTER_2);
|
||||
if (TeamIdInInstance == TEAM_ALLIANCE)
|
||||
if (GetTeamIdInInstance() == TEAM_ALLIANCE)
|
||||
creature->UpdateEntry(NPC_COMMANDER_KOLURG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
void OnGameObjectCreate(GameObject* gameObject) override
|
||||
{
|
||||
switch (gameObject->GetEntry())
|
||||
@@ -194,8 +149,6 @@ public:
|
||||
(*i)->RemoveGameObjectFlag(GO_FLAG_NOT_SELECTABLE);
|
||||
return true;
|
||||
}
|
||||
protected:
|
||||
TeamId TeamIdInInstance;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -33,12 +33,8 @@ enum bloodFurnace
|
||||
DATA_KELIDAN = 2,
|
||||
MAX_ENCOUNTER = 3,
|
||||
|
||||
DATA_DOOR1 = 10,
|
||||
DATA_DOOR2 = 11,
|
||||
DATA_DOOR3 = 12,
|
||||
DATA_BROGGOK_REAR_DOOR = 13,
|
||||
DATA_BROGGOK_LEVER = 14,
|
||||
DATA_DOOR6 = 15,
|
||||
|
||||
DATA_PRISON_CELL1 = 20,
|
||||
DATA_PRISON_CELL2 = 21,
|
||||
@@ -62,7 +58,11 @@ enum BloodFurnaceGO
|
||||
{
|
||||
GO_BROGGOK_DOOR_FRONT = 181822,
|
||||
GO_BROGGOK_DOOR_REAR = 181819,
|
||||
GO_BROGGOK_LEVER = 181982
|
||||
GO_BROGGOK_LEVER = 181982,
|
||||
GO_KELIDAN_DOOR_EXIT1 = 181823,
|
||||
GO_KELIDAN_DOOR_EXIT2 = 181766,
|
||||
GO_MAKER_DOOR_FRONT = 181811,
|
||||
GO_MAKER_DOOR_REAR = 181812
|
||||
};
|
||||
|
||||
template <class AI, class T>
|
||||
|
||||
@@ -101,15 +101,10 @@ public:
|
||||
bool OnGossipHello(Player* /*player*/, GameObject* go) override
|
||||
{
|
||||
if (InstanceScript* instance = go->GetInstanceScript())
|
||||
{
|
||||
if (instance->GetBossState(DATA_BROGGOK) == NOT_STARTED)
|
||||
{
|
||||
if (Creature* broggok = instance->GetCreature(DATA_BROGGOK))
|
||||
{
|
||||
broggok->AI()->DoAction(ACTION_PREPARE_BROGGOK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go->UseDoorOrButton();
|
||||
return false;
|
||||
}
|
||||
|
||||
+6
-27
@@ -67,10 +67,6 @@ struct boss_kelidan_the_breaker : public BossAI
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
DoCastSelf(SPELL_EVOCATION);
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(DATA_KELIDAN, NOT_STARTED);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
@@ -78,10 +74,7 @@ struct boss_kelidan_the_breaker : public BossAI
|
||||
Talk(SAY_WAKE);
|
||||
_JustEngagedWith();
|
||||
me->InterruptNonMeleeSpells(false);
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(DATA_KELIDAN, IN_PROGRESS);
|
||||
}
|
||||
|
||||
scheduler.Schedule(1s, [this](TaskContext context)
|
||||
{
|
||||
DoCastAOE(SPELL_SHADOW_BOLT_VOLLEY);
|
||||
@@ -97,9 +90,7 @@ struct boss_kelidan_the_breaker : public BossAI
|
||||
me->AddAura(SPELL_BURNING_NOVA, me);
|
||||
ApplyImmunities(true);
|
||||
if (IsHeroic())
|
||||
{
|
||||
DoCastAOE(SPELL_VORTEX);
|
||||
}
|
||||
scheduler.DelayGroup(0, 6s);
|
||||
scheduler.Schedule(5s, [this](TaskContext /*context*/)
|
||||
{
|
||||
@@ -112,41 +103,29 @@ struct boss_kelidan_the_breaker : public BossAI
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
{
|
||||
if (urand(0, 1))
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void DoAction(int32 param) override
|
||||
{
|
||||
if (param == ACTION_CHANNELER_DIED)
|
||||
{
|
||||
if (me->FindNearestCreature(NPC_SHADOWMOON_CHANNELER, 100.0f))
|
||||
if (!me->FindNearestCreature(NPC_SHADOWMOON_CHANNELER, 100.0f))
|
||||
{
|
||||
return;
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetReactState(REACT_AGGRESSIVE);
|
||||
me->SetInCombatWithZone();
|
||||
}
|
||||
|
||||
else if (param == ACTION_CHANNELER_AGGRO)
|
||||
{
|
||||
Talk(SAY_ADD_AGGRO);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
if (instance)
|
||||
{
|
||||
me->GetMap()->LoadGrid(0, -111.0f);
|
||||
instance->SetData(DATA_KELIDAN, DONE);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR1), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR6), true);
|
||||
}
|
||||
me->GetMap()->LoadGrid(0, -111.0f);
|
||||
}
|
||||
|
||||
void ApplyImmunities(bool apply)
|
||||
|
||||
@@ -42,22 +42,10 @@ struct boss_the_maker : public BossAI
|
||||
});
|
||||
}
|
||||
|
||||
void Reset() override
|
||||
{
|
||||
_Reset();
|
||||
if (instance)
|
||||
{
|
||||
instance->SetData(DATA_THE_MAKER, NOT_STARTED);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
|
||||
}
|
||||
}
|
||||
|
||||
void JustEngagedWith(Unit* /*who*/) override
|
||||
{
|
||||
Talk(SAY_AGGRO);
|
||||
_JustEngagedWith();
|
||||
instance->SetData(DATA_THE_MAKER, IN_PROGRESS);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), false);
|
||||
scheduler.Schedule(6s, [this](TaskContext context)
|
||||
{
|
||||
DoCastRandomTarget(SPELL_EXPLODING_BEAKER);
|
||||
@@ -72,30 +60,13 @@ struct boss_the_maker : public BossAI
|
||||
void KilledUnit(Unit* victim) override
|
||||
{
|
||||
if (victim->IsPlayer() && urand(0, 1))
|
||||
{
|
||||
Talk(SAY_KILL);
|
||||
}
|
||||
}
|
||||
|
||||
void JustDied(Unit* /*killer*/) override
|
||||
{
|
||||
Talk(SAY_DIE);
|
||||
_JustDied();
|
||||
instance->SetData(DATA_THE_MAKER, DONE);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR2), true);
|
||||
instance->HandleGameObject(instance->GetGuidData(DATA_DOOR3), true);
|
||||
}
|
||||
|
||||
void UpdateAI(uint32 diff) override
|
||||
{
|
||||
if (!UpdateVictim())
|
||||
return;
|
||||
|
||||
scheduler.Update(diff);
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING))
|
||||
return;
|
||||
|
||||
DoMeleeAttackIfReady();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+13
-72
@@ -22,9 +22,13 @@
|
||||
|
||||
DoorData const doorData[] =
|
||||
{
|
||||
{ GO_BROGGOK_DOOR_FRONT, DATA_BROGGOK, DOOR_TYPE_ROOM },
|
||||
{ GO_BROGGOK_DOOR_REAR, DATA_BROGGOK, DOOR_TYPE_PASSAGE },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
{ GO_MAKER_DOOR_FRONT, DATA_THE_MAKER, DOOR_TYPE_ROOM },
|
||||
{ GO_MAKER_DOOR_REAR, DATA_THE_MAKER, DOOR_TYPE_PASSAGE },
|
||||
{ GO_BROGGOK_DOOR_FRONT, DATA_BROGGOK, DOOR_TYPE_ROOM },
|
||||
{ GO_BROGGOK_DOOR_REAR, DATA_BROGGOK, DOOR_TYPE_PASSAGE },
|
||||
{ GO_KELIDAN_DOOR_EXIT1, DATA_KELIDAN, DOOR_TYPE_PASSAGE },
|
||||
{ GO_KELIDAN_DOOR_EXIT2, DATA_KELIDAN, DOOR_TYPE_PASSAGE },
|
||||
{ 0, 0, DOOR_TYPE_ROOM } // END
|
||||
};
|
||||
|
||||
ObjectData const gameobjectData[] =
|
||||
@@ -56,26 +60,15 @@ public:
|
||||
LoadObjectData(creatureData, gameobjectData);
|
||||
}
|
||||
|
||||
uint32 _auiEncounter[MAX_ENCOUNTER];
|
||||
ObjectGuid _doorGUIDs[6];
|
||||
ObjectGuid _prisonGUIDs[4];
|
||||
|
||||
GuidSet _prisonersCell[4];
|
||||
|
||||
uint8 _prisonerCounter[4];
|
||||
|
||||
void Initialize() override
|
||||
{
|
||||
memset(&_auiEncounter, 0, sizeof(_auiEncounter));
|
||||
memset(&_prisonerCounter, 0, sizeof(_prisonerCounter));
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (creature->GetEntry() == NPC_NASCENT_FEL_ORC)
|
||||
{
|
||||
StorePrisoner(creature);
|
||||
}
|
||||
|
||||
InstanceScript::OnCreatureCreate(creature);
|
||||
}
|
||||
@@ -88,20 +81,6 @@ public:
|
||||
|
||||
void OnGameObjectCreate(GameObject* go) override
|
||||
{
|
||||
if (go->GetEntry() == 181766) //Final exit door
|
||||
_doorGUIDs[0] = go->GetGUID();
|
||||
if (go->GetEntry() == 181811) //The Maker Front door
|
||||
_doorGUIDs[1] = go->GetGUID();
|
||||
if (go->GetEntry() == 181812) //The Maker Rear door
|
||||
{
|
||||
_doorGUIDs[2] = go->GetGUID();
|
||||
if (GetData(DATA_THE_MAKER) == DONE)
|
||||
HandleGameObject(go->GetGUID(), true);
|
||||
}
|
||||
|
||||
if (go->GetEntry() == 181823) //Kelidan exit door
|
||||
_doorGUIDs[5] = go->GetGUID();
|
||||
|
||||
if (go->GetEntry() == 181821) //Broggok prison cell front right
|
||||
_prisonGUIDs[0] = go->GetGUID();
|
||||
if (go->GetEntry() == 181818) //Broggok prison cell back right
|
||||
@@ -118,12 +97,6 @@ public:
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case DATA_DOOR1:
|
||||
case DATA_DOOR2:
|
||||
case DATA_DOOR3:
|
||||
case DATA_DOOR6:
|
||||
return _doorGUIDs[data - DATA_DOOR1];
|
||||
|
||||
case DATA_PRISON_CELL1:
|
||||
case DATA_PRISON_CELL2:
|
||||
case DATA_PRISON_CELL3:
|
||||
@@ -142,50 +115,17 @@ public:
|
||||
if (type == DATA_BROGGOK)
|
||||
{
|
||||
if (state == IN_PROGRESS)
|
||||
{
|
||||
ActivateCell(DATA_PRISON_CELL1);
|
||||
HandleGameObject(_doorGUIDs[3], false);
|
||||
}
|
||||
else if (state == NOT_STARTED)
|
||||
{
|
||||
ResetPrisons();
|
||||
HandleGameObject(_doorGUIDs[4], false);
|
||||
HandleGameObject(_doorGUIDs[3], true);
|
||||
if (GameObject* lever = GetGameObject(DATA_BROGGOK_LEVER))
|
||||
{
|
||||
lever->Respawn();
|
||||
}
|
||||
DoRespawnGameObject(DATA_BROGGOK_LEVER);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetData(uint32 type, uint32 data) override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_THE_MAKER:
|
||||
case DATA_KELIDAN:
|
||||
_auiEncounter[type] = data;
|
||||
break;
|
||||
}
|
||||
|
||||
if (data == DONE)
|
||||
SaveToDB();
|
||||
}
|
||||
|
||||
uint32 GetData(uint32 type) const override
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DATA_THE_MAKER:
|
||||
case DATA_KELIDAN:
|
||||
return _auiEncounter[type];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ResetPrisons()
|
||||
{
|
||||
for (uint8 i = 0; i < 4; ++i)
|
||||
@@ -273,13 +213,9 @@ public:
|
||||
break;
|
||||
case DATA_BROGGOK_REAR_DOOR:
|
||||
if (GameObject* go = GetGameObject(DATA_BROGGOK_REAR_DOOR))
|
||||
{
|
||||
HandleGameObject(ObjectGuid::Empty, true, go);
|
||||
}
|
||||
if (Creature* broggok = GetCreature(DATA_BROGGOK))
|
||||
{
|
||||
broggok->AI()->DoAction(ACTION_ACTIVATE_BROGGOK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -294,6 +230,11 @@ public:
|
||||
prisoner->SetInCombatWithZone();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ObjectGuid _prisonGUIDs[4];
|
||||
GuidSet _prisonersCell[4];
|
||||
uint8 _prisonerCounter[4];
|
||||
};
|
||||
|
||||
InstanceScript* GetInstanceScript(InstanceMap* map) const override
|
||||
|
||||
+5
-51
@@ -59,56 +59,11 @@ public:
|
||||
SetBossNumber(ENCOUNTER_COUNT);
|
||||
LoadObjectData(creatureData, nullptr);
|
||||
LoadDoorData(doorData);
|
||||
|
||||
TeamIdInInstance = TEAM_NEUTRAL;
|
||||
RescueTimer = 100 * MINUTE * IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
void OnPlayerEnter(Player* player) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFaction((TeamIdInInstance == TEAM_HORDE) ? 1610 : 1);
|
||||
}
|
||||
|
||||
void OnPlayerLeave(Player* player) override
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP))
|
||||
player->SetFactionForRace(player->getRace());
|
||||
}
|
||||
|
||||
void OnCreatureCreate(Creature* creature) override
|
||||
{
|
||||
if (TeamIdInInstance == TEAM_NEUTRAL)
|
||||
{
|
||||
Map::PlayerList const& players = instance->GetPlayers();
|
||||
if (!players.IsEmpty())
|
||||
if (Player* player = players.begin()->GetSource())
|
||||
{
|
||||
if (Group* group = player->GetGroup())
|
||||
{
|
||||
if (Player* gLeader = ObjectAccessor::FindPlayer(group->GetLeaderGUID()))
|
||||
TeamIdInInstance = Player::TeamIdForRace(gLeader->getRace());
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
else
|
||||
TeamIdInInstance = player->GetTeamId();
|
||||
}
|
||||
}
|
||||
|
||||
switch (creature->GetEntry())
|
||||
{
|
||||
case NPC_SHATTERED_EXECUTIONER:
|
||||
@@ -117,22 +72,22 @@ public:
|
||||
ExecutionerGUID = creature->GetGUID();
|
||||
break;
|
||||
case NPC_RIFLEMAN_BROWNBEARD:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_KORAG_PROUDMANE);
|
||||
PrisonerGUID[0] = creature->GetGUID();
|
||||
break;
|
||||
case NPC_CAPTAIN_ALINA:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_CAPTAIN_BONESHATTER);
|
||||
PrisonerGUID[1] = creature->GetGUID();
|
||||
break;
|
||||
case NPC_PRIVATE_JACINT:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_SCOUT_ORGARR);
|
||||
PrisonerGUID[2] = creature->GetGUID();
|
||||
break;
|
||||
case NPC_RANDY_WHIZZLESPROCKET:
|
||||
if (TeamIdInInstance == TEAM_HORDE)
|
||||
if (GetTeamIdInInstance() == TEAM_HORDE)
|
||||
creature->UpdateEntry(NPC_DRISELLA);
|
||||
break;
|
||||
}
|
||||
@@ -147,7 +102,7 @@ public:
|
||||
instance->LoadGrid(230, -80);
|
||||
|
||||
if (Creature* kargath = GetCreature(DATA_KARGATH))
|
||||
sCreatureTextMgr->SendChat(kargath, TeamIdInInstance == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
|
||||
sCreatureTextMgr->SendChat(kargath, GetTeamIdInInstance() == TEAM_ALLIANCE ? 3 : 4, nullptr, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP);
|
||||
|
||||
RescueTimer = 80 * MINUTE * IN_MILLISECONDS;
|
||||
}
|
||||
@@ -213,7 +168,6 @@ public:
|
||||
ObjectGuid ExecutionerGUID;
|
||||
ObjectGuid PrisonerGUID[3];
|
||||
uint32 RescueTimer;
|
||||
TeamId TeamIdInInstance;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user