mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Misc: Remove a bunch of code from headers
This commit is contained in:
@@ -18,6 +18,10 @@
|
||||
#include "EventMap.h"
|
||||
#include "Random.h"
|
||||
|
||||
EventMap::EventMap(EventMap const& other) = default;
|
||||
EventMap& EventMap::operator=(EventMap const& other) = default;
|
||||
EventMap::~EventMap() = default;
|
||||
|
||||
void EventMap::Reset()
|
||||
{
|
||||
_eventMap.clear();
|
||||
@@ -41,7 +45,7 @@ void EventMap::ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group /*=
|
||||
if (phase && phase <= 8)
|
||||
eventId |= (1 << (phase + 23));
|
||||
|
||||
_eventMap.insert(EventStore::value_type(_time + time, eventId));
|
||||
_eventMap.insert({ _time + time, eventId });
|
||||
}
|
||||
|
||||
void EventMap::ScheduleEvent(uint32 eventId, Milliseconds minTime, Milliseconds maxTime, uint32 group /*= 0*/, uint8 phase /*= 0*/)
|
||||
@@ -102,7 +106,7 @@ void EventMap::DelayEvents(Milliseconds delay)
|
||||
for (EventStore::iterator itr = delayed.begin(); itr != delayed.end();)
|
||||
{
|
||||
EventStore::node_type node = delayed.extract(itr++);
|
||||
node.key() = node.key() + delay;
|
||||
node.key() += delay;
|
||||
_eventMap.insert(_eventMap.end(), std::move(node));
|
||||
}
|
||||
}
|
||||
@@ -113,19 +117,19 @@ void EventMap::DelayEvents(Milliseconds delay, uint32 group)
|
||||
return;
|
||||
|
||||
EventStore delayed;
|
||||
|
||||
for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
|
||||
{
|
||||
if (itr->second & (1 << (group + 15)))
|
||||
{
|
||||
delayed.insert(EventStore::value_type(itr->first + delay, itr->second));
|
||||
_eventMap.erase(itr++);
|
||||
EventStore::node_type node = _eventMap.extract(itr++);
|
||||
node.key() += delay;
|
||||
delayed.insert(delayed.end(), std::move(node));
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
||||
_eventMap.insert(delayed.begin(), delayed.end());
|
||||
_eventMap.merge(delayed);
|
||||
}
|
||||
|
||||
void EventMap::CancelEvent(uint32 eventId)
|
||||
@@ -187,33 +191,32 @@ void EventMap::ScheduleNextFromSeries(uint32 eventData)
|
||||
if (itr == _timerSeries.end())
|
||||
return;
|
||||
|
||||
if (itr->first != eventData)
|
||||
return;
|
||||
ScheduleEvent(eventData, itr->second.front());
|
||||
|
||||
if (itr->second.size() == 0)
|
||||
return;
|
||||
|
||||
Milliseconds time = itr->second.front();
|
||||
itr->second.pop();
|
||||
|
||||
ScheduleEvent(eventData, time);
|
||||
if (itr->second.size() > 1)
|
||||
itr->second.erase(itr->second.begin());
|
||||
else
|
||||
_timerSeries.erase(itr);
|
||||
}
|
||||
|
||||
void EventMap::ScheduleEventSeries(uint32 eventId, uint8 group, uint8 phase, std::initializer_list<Milliseconds> const& timeSeries)
|
||||
void EventMap::ScheduleEventSeries(uint32 eventId, uint8 group, uint8 phase, std::initializer_list<Milliseconds> timeSeries)
|
||||
{
|
||||
if (!timeSeries.size())
|
||||
return;
|
||||
|
||||
if (group && group <= 8)
|
||||
eventId |= (1 << (group + 15));
|
||||
|
||||
if (phase && phase <= 8)
|
||||
eventId |= (1 << (phase + 23));
|
||||
|
||||
for (Milliseconds const& time : timeSeries)
|
||||
_timerSeries[eventId].push(time);
|
||||
std::vector<Milliseconds>& series = _timerSeries[eventId];
|
||||
series.insert(series.end(), timeSeries.begin(), timeSeries.end());
|
||||
|
||||
ScheduleNextFromSeries(eventId);
|
||||
}
|
||||
|
||||
void EventMap::ScheduleEventSeries(uint32 eventId, std::initializer_list<Milliseconds> const& timeSeries)
|
||||
void EventMap::ScheduleEventSeries(uint32 eventId, std::initializer_list<Milliseconds> timeSeries)
|
||||
{
|
||||
ScheduleEventSeries(eventId, 0, 0, timeSeries);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "Define.h"
|
||||
#include "Duration.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
class TC_COMMON_API EventMap
|
||||
{
|
||||
@@ -37,10 +37,15 @@ class TC_COMMON_API EventMap
|
||||
* - Pattern: 0xPPGGEEEE
|
||||
*/
|
||||
typedef std::multimap<TimePoint, uint32> EventStore;
|
||||
typedef std::map<uint32 /*event data*/, std::queue<Milliseconds>> EventSeriesStore;
|
||||
typedef std::map<uint32 /*event data*/, std::vector<Milliseconds>> EventSeriesStore;
|
||||
|
||||
public:
|
||||
EventMap() : _time(TimePoint::min()), _phase(0), _lastEvent(0) { }
|
||||
EventMap(EventMap const& other);
|
||||
EventMap(EventMap&& other) noexcept = default;
|
||||
EventMap& operator=(EventMap const& other);
|
||||
EventMap& operator=(EventMap&& other) noexcept = default;
|
||||
~EventMap();
|
||||
|
||||
/**
|
||||
* @name Reset
|
||||
@@ -242,7 +247,7 @@ public:
|
||||
* @param phase of the event.
|
||||
* @param timeSeries specifying the times the event should be automatically scheduled after each trigger (first value is initial schedule)
|
||||
*/
|
||||
void ScheduleEventSeries(uint32 eventId, uint8 group, uint8 phase, std::initializer_list<Milliseconds> const& timeSeries);
|
||||
void ScheduleEventSeries(uint32 eventId, uint8 group, uint8 phase, std::initializer_list<Milliseconds> timeSeries);
|
||||
|
||||
/**
|
||||
* @name ScheduleEventSeries
|
||||
@@ -250,7 +255,7 @@ public:
|
||||
* @param eventId of the event.
|
||||
* @param timeSeries specifying the times the event should be automatically scheduled after each trigger (first value is initial schedule)
|
||||
*/
|
||||
void ScheduleEventSeries(uint32 eventId, std::initializer_list<Milliseconds> const& series);
|
||||
void ScheduleEventSeries(uint32 eventId, std::initializer_list<Milliseconds> series);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,15 @@
|
||||
#include "TaskScheduler.h"
|
||||
#include "Errors.h"
|
||||
|
||||
TaskScheduler::TaskScheduler()
|
||||
: self_reference(this, [](TaskScheduler const*) { }),
|
||||
_now(clock_t::now()),
|
||||
_predicate(EmptyValidator)
|
||||
{
|
||||
}
|
||||
|
||||
TaskScheduler::~TaskScheduler() = default;
|
||||
|
||||
TaskScheduler& TaskScheduler::ClearValidator()
|
||||
{
|
||||
_predicate = EmptyValidator;
|
||||
@@ -36,6 +45,13 @@ TaskScheduler& TaskScheduler::Update(size_t milliseconds, success_t const& callb
|
||||
return Update(std::chrono::milliseconds(milliseconds), callback);
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::Update(duration_t difftime, success_t const& callback/* = nullptr*/)
|
||||
{
|
||||
_now += difftime;
|
||||
Dispatch(callback);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::Async(std::function<void()> callable)
|
||||
{
|
||||
_asyncHolder.emplace(std::move(callable));
|
||||
@@ -67,12 +83,75 @@ TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups)
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::DelayAll(duration_t duration)
|
||||
{
|
||||
_task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool
|
||||
{
|
||||
task->_end += duration;
|
||||
return true;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::DelayGroup(group_t const group, duration_t duration)
|
||||
{
|
||||
_task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool
|
||||
{
|
||||
if (task->IsInGroup(group))
|
||||
{
|
||||
task->_end += duration;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::RescheduleAll(duration_t duration)
|
||||
{
|
||||
auto const end = _now + duration;
|
||||
_task_holder.ModifyIf([end](TaskContainer const& task) -> bool
|
||||
{
|
||||
task->_end = end;
|
||||
return true;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::RescheduleGroup(group_t const group, duration_t duration)
|
||||
{
|
||||
auto const end = _now + duration;
|
||||
_task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool
|
||||
{
|
||||
if (task->IsInGroup(group))
|
||||
{
|
||||
task->_end = end;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
|
||||
{
|
||||
_task_holder.Push(std::move(task));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::ScheduleAt(timepoint_t end, duration_t time, task_handler_t task)
|
||||
{
|
||||
return InsertTask(TaskContainer(new Task(end + time, time, std::move(task))));
|
||||
}
|
||||
|
||||
TaskScheduler& TaskScheduler::ScheduleAt(timepoint_t end, duration_t time, group_t const group, task_handler_t task)
|
||||
{
|
||||
static constexpr repeated_t DEFAULT_REPEATED = 0;
|
||||
return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, std::move(task))));
|
||||
}
|
||||
|
||||
void TaskScheduler::Dispatch(success_t const& callback/* = nullptr*/)
|
||||
{
|
||||
// If the validation failed abort the dispatching here.
|
||||
@@ -198,6 +277,21 @@ TaskScheduler::repeated_t TaskContext::GetRepeatCounter() const
|
||||
return _task->_repeated;
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::Repeat(TaskScheduler::duration_t duration)
|
||||
{
|
||||
AssertOnConsumed();
|
||||
|
||||
// Set new duration, in-context timing and increment repeat counter
|
||||
_task->_duration = duration;
|
||||
_task->_end += duration;
|
||||
_task->_repeated += 1;
|
||||
(*_consumed) = true;
|
||||
return this->Dispatch([this](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.InsertTask(_task);
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::Async(std::function<void()> const& callable)
|
||||
{
|
||||
return Dispatch([&](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
@@ -206,6 +300,24 @@ TaskContext& TaskContext::Async(std::function<void()> const& callable)
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::Schedule(TaskScheduler::duration_t time, TaskScheduler::task_handler_t task)
|
||||
{
|
||||
auto const end = _task->_end;
|
||||
return this->Dispatch([end, time, task = std::move(task)](TaskScheduler& scheduler) mutable -> TaskScheduler&
|
||||
{
|
||||
return scheduler.ScheduleAt(end, time, std::move(task));
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::Schedule(TaskScheduler::duration_t time, TaskScheduler::group_t const group, TaskScheduler::task_handler_t task)
|
||||
{
|
||||
auto const end = _task->_end;
|
||||
return this->Dispatch([end, time, group, task = std::move(task)](TaskScheduler& scheduler) mutable -> TaskScheduler&
|
||||
{
|
||||
return scheduler.ScheduleAt(end, time, group, std::move(task));
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::CancelAll()
|
||||
{
|
||||
return Dispatch(&TaskScheduler::CancelAll);
|
||||
@@ -227,6 +339,38 @@ TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> con
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::DelayAll(TaskScheduler::duration_t duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.DelayAll(duration);
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::DelayGroup(TaskScheduler::group_t const group, TaskScheduler::duration_t duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.DelayGroup(group, duration);
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::RescheduleAll(TaskScheduler::duration_t duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.RescheduleAll(duration);
|
||||
});
|
||||
}
|
||||
|
||||
TaskContext& TaskContext::RescheduleGroup(TaskScheduler::group_t const group, TaskScheduler::duration_t duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.RescheduleGroup(group, duration);
|
||||
});
|
||||
}
|
||||
|
||||
void TaskContext::AssertOnConsumed() const
|
||||
{
|
||||
// This was adapted to TC to prevent static analysis tools from complaining.
|
||||
|
||||
@@ -171,11 +171,10 @@ class TC_COMMON_API TaskScheduler
|
||||
}
|
||||
|
||||
public:
|
||||
TaskScheduler()
|
||||
: self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(EmptyValidator) { }
|
||||
TaskScheduler();
|
||||
|
||||
template<typename P>
|
||||
TaskScheduler(P&& predicate)
|
||||
explicit TaskScheduler(P&& predicate)
|
||||
: self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(std::forward<P>(predicate)) { }
|
||||
|
||||
TaskScheduler(TaskScheduler const&) = delete;
|
||||
@@ -183,7 +182,7 @@ public:
|
||||
TaskScheduler& operator= (TaskScheduler const&) = delete;
|
||||
TaskScheduler& operator= (TaskScheduler&&) = delete;
|
||||
|
||||
~TaskScheduler() = default;
|
||||
~TaskScheduler();
|
||||
|
||||
/// Sets a validator which is asked if tasks are allowed to be executed.
|
||||
template<typename P>
|
||||
@@ -206,14 +205,7 @@ public:
|
||||
|
||||
/// Update the scheduler with a difftime.
|
||||
/// Calls the optional callback on successfully finish.
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& Update(std::chrono::duration<Rep, Period> difftime,
|
||||
success_t const& callback = nullptr)
|
||||
{
|
||||
_now += difftime;
|
||||
Dispatch(callback);
|
||||
return *this;
|
||||
}
|
||||
TaskScheduler& Update(duration_t difftime, success_t const& callback = nullptr);
|
||||
|
||||
/// Schedule an callable function that is executed at the next update tick.
|
||||
/// Its safe to modify the TaskScheduler from within the callable.
|
||||
@@ -221,8 +213,7 @@ public:
|
||||
|
||||
/// Schedule an event with a fixed rate.
|
||||
/// Never call this from within a task context! Use TaskContext::Schedule instead!
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& Schedule(std::chrono::duration<Rep, Period> time,
|
||||
TaskScheduler& Schedule(duration_t time,
|
||||
task_handler_t task)
|
||||
{
|
||||
return this->ScheduleAt(_now, time, std::move(task));
|
||||
@@ -230,8 +221,7 @@ public:
|
||||
|
||||
/// Schedule an event with a fixed rate.
|
||||
/// Never call this from within a task context! Use TaskContext::Schedule instead!
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& Schedule(std::chrono::duration<Rep, Period> time,
|
||||
TaskScheduler& Schedule(duration_t time,
|
||||
group_t const group, task_handler_t task)
|
||||
{
|
||||
return this->ScheduleAt(_now, time, group, std::move(task));
|
||||
@@ -239,18 +229,16 @@ public:
|
||||
|
||||
/// Schedule an event with a randomized rate between min and max rate.
|
||||
/// Never call this from within a task context! Use TaskContext::Schedule instead!
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskScheduler& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max, task_handler_t task)
|
||||
TaskScheduler& Schedule(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max, task_handler_t task)
|
||||
{
|
||||
return this->Schedule(::randtime(min, max), std::move(task));
|
||||
}
|
||||
|
||||
/// Schedule an event with a fixed rate.
|
||||
/// Never call this from within a task context! Use TaskContext::Schedule instead!
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskScheduler& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max, group_t const group,
|
||||
TaskScheduler& Schedule(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max, group_t const group,
|
||||
task_handler_t task)
|
||||
{
|
||||
return this->Schedule(::randtime(min, max), group, std::move(task));
|
||||
@@ -269,95 +257,42 @@ public:
|
||||
TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups);
|
||||
|
||||
/// Delays all tasks with the given duration.
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& DelayAll(std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
_task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool
|
||||
{
|
||||
task->_end += duration;
|
||||
return true;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
TaskScheduler& DelayAll(duration_t duration);
|
||||
|
||||
/// Delays all tasks with a random duration between min and max.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskScheduler& DelayAll(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
TaskScheduler& DelayAll(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->DelayAll(::randtime(min, max));
|
||||
}
|
||||
|
||||
/// Delays all tasks of a group with the given duration.
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
_task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool
|
||||
{
|
||||
if (task->IsInGroup(group))
|
||||
{
|
||||
task->_end += duration;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
TaskScheduler& DelayGroup(group_t const group, duration_t duration);
|
||||
|
||||
/// Delays all tasks of a group with a random duration between min and max.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskScheduler& DelayGroup(group_t const group,
|
||||
std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->DelayGroup(group, ::randtime(min, max));
|
||||
}
|
||||
|
||||
/// Reschedule all tasks with a given duration.
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& RescheduleAll(std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
auto const end = _now + duration;
|
||||
_task_holder.ModifyIf([end](TaskContainer const& task) -> bool
|
||||
{
|
||||
task->_end = end;
|
||||
return true;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
TaskScheduler& RescheduleAll(duration_t duration);
|
||||
|
||||
/// Reschedule all tasks with a random duration between min and max.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskScheduler& RescheduleAll(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
TaskScheduler& RescheduleAll(std::chrono::milliseconds min, std::chrono::milliseconds max)
|
||||
{
|
||||
return this->RescheduleAll(::randtime(min, max));
|
||||
}
|
||||
|
||||
/// Reschedule all tasks of a group with the given duration.
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
auto const end = _now + duration;
|
||||
_task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool
|
||||
{
|
||||
if (task->IsInGroup(group))
|
||||
{
|
||||
task->_end = end;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
TaskScheduler& RescheduleGroup(group_t const group, duration_t duration);
|
||||
|
||||
/// Reschedule all tasks of a group with a random duration between min and max.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskScheduler& RescheduleGroup(group_t const group,
|
||||
std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->RescheduleGroup(group, ::randtime(min, max));
|
||||
}
|
||||
@@ -366,23 +301,14 @@ private:
|
||||
/// Insert a new task to the enqueued tasks.
|
||||
TaskScheduler& InsertTask(TaskContainer task);
|
||||
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& ScheduleAt(timepoint_t end,
|
||||
std::chrono::duration<Rep, Period> time, task_handler_t task)
|
||||
{
|
||||
return InsertTask(TaskContainer(new Task(end + time, time, std::move(task))));
|
||||
}
|
||||
duration_t time, task_handler_t task);
|
||||
|
||||
/// Schedule an event with a fixed rate.
|
||||
/// Never call this from within a task context! Use TaskContext::schedule instead!
|
||||
template<class Rep, class Period>
|
||||
TaskScheduler& ScheduleAt(timepoint_t end,
|
||||
std::chrono::duration<Rep, Period> time,
|
||||
group_t const group, task_handler_t task)
|
||||
{
|
||||
static constexpr repeated_t DEFAULT_REPEATED = 0;
|
||||
return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, std::move(task))));
|
||||
}
|
||||
duration_t time,
|
||||
group_t const group, task_handler_t task);
|
||||
|
||||
/// Dispatch remaining tasks
|
||||
void Dispatch(success_t const& callback);
|
||||
@@ -414,36 +340,16 @@ public:
|
||||
: _task(std::move(task)), _owner(std::move(owner)), _consumed(std::make_shared<bool>(false)) { }
|
||||
|
||||
// Copy construct
|
||||
TaskContext(TaskContext const& right)
|
||||
: _task(right._task), _owner(right._owner), _consumed(right._consumed) { }
|
||||
TaskContext(TaskContext const& right) = default;
|
||||
|
||||
// Move construct
|
||||
TaskContext(TaskContext&& right) noexcept
|
||||
: _task(std::move(right._task)), _owner(std::move(right._owner)), _consumed(std::move(right._consumed)) { }
|
||||
TaskContext(TaskContext&& right) noexcept = default;
|
||||
|
||||
// Copy assign
|
||||
TaskContext& operator=(TaskContext const& right)
|
||||
{
|
||||
if (this != &right)
|
||||
{
|
||||
_task = right._task;
|
||||
_owner = right._owner;
|
||||
_consumed = right._consumed;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
TaskContext& operator=(TaskContext const& right) = default;
|
||||
|
||||
// Move assign
|
||||
TaskContext& operator=(TaskContext&& right) noexcept
|
||||
{
|
||||
if (this != &right)
|
||||
{
|
||||
_task = std::move(right._task);
|
||||
_owner = std::move(right._owner);
|
||||
_consumed = std::move(right._consumed);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
TaskContext& operator=(TaskContext&& right) noexcept = default;
|
||||
|
||||
~TaskContext() = default;
|
||||
|
||||
@@ -466,21 +372,7 @@ public:
|
||||
/// std::chrono::seconds(5) for example.
|
||||
/// This will consume the task context, its not possible to repeat the task again
|
||||
/// from the same task context!
|
||||
template<class Rep, class Period>
|
||||
TaskContext& Repeat(std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
AssertOnConsumed();
|
||||
|
||||
// Set new duration, in-context timing and increment repeat counter
|
||||
_task->_duration = duration;
|
||||
_task->_end += duration;
|
||||
_task->_repeated += 1;
|
||||
(*_consumed) = true;
|
||||
return this->Dispatch([this](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.InsertTask(_task);
|
||||
});
|
||||
}
|
||||
TaskContext& Repeat(TaskScheduler::duration_t duration);
|
||||
|
||||
/// Repeats the event with the same duration.
|
||||
/// This will consume the task context, its not possible to repeat the task again
|
||||
@@ -494,9 +386,8 @@ public:
|
||||
/// std::chrono::seconds(5) for example.
|
||||
/// This will consume the task context, its not possible to repeat the task again
|
||||
/// from the same task context!
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& Repeat(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
TaskContext& Repeat(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->Repeat(::randtime(min, max));
|
||||
}
|
||||
@@ -509,39 +400,22 @@ public:
|
||||
/// Its possible that the new event is executed immediately!
|
||||
/// Use TaskScheduler::Async to create a task
|
||||
/// which will be called at the next update tick.
|
||||
template<class Rep, class Period>
|
||||
TaskContext& Schedule(std::chrono::duration<Rep, Period> time,
|
||||
TaskScheduler::task_handler_t task)
|
||||
{
|
||||
auto const end = _task->_end;
|
||||
return this->Dispatch([end, time, task = std::move(task)](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.ScheduleAt<Rep, Period>(end, time, std::move(task));
|
||||
});
|
||||
}
|
||||
TaskContext& Schedule(TaskScheduler::duration_t time,
|
||||
TaskScheduler::task_handler_t task);
|
||||
|
||||
/// Schedule an event with a fixed rate from within the context.
|
||||
/// Its possible that the new event is executed immediately!
|
||||
/// Use TaskScheduler::Async to create a task
|
||||
/// which will be called at the next update tick.
|
||||
template<class Rep, class Period>
|
||||
TaskContext& Schedule(std::chrono::duration<Rep, Period> time,
|
||||
TaskScheduler::group_t const group, TaskScheduler::task_handler_t task)
|
||||
{
|
||||
auto const end = _task->_end;
|
||||
return this->Dispatch([end, time, group, task = std::move(task)](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.ScheduleAt<Rep, Period>(end, time, group, std::move(task));
|
||||
});
|
||||
}
|
||||
TaskContext& Schedule(TaskScheduler::duration_t time,
|
||||
TaskScheduler::group_t const group, TaskScheduler::task_handler_t task);
|
||||
|
||||
/// Schedule an event with a randomized rate between min and max rate from within the context.
|
||||
/// Its possible that the new event is executed immediately!
|
||||
/// Use TaskScheduler::Async to create a task
|
||||
/// which will be called at the next update tick.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max, TaskScheduler::task_handler_t task)
|
||||
TaskContext& Schedule(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max, TaskScheduler::task_handler_t task)
|
||||
{
|
||||
return this->Schedule(::randtime(min, max), std::move(task));
|
||||
}
|
||||
@@ -550,9 +424,8 @@ public:
|
||||
/// Its possible that the new event is executed immediately!
|
||||
/// Use TaskScheduler::Async to create a task
|
||||
/// which will be called at the next update tick.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max, TaskScheduler::group_t const group,
|
||||
TaskContext& Schedule(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max, TaskScheduler::group_t const group,
|
||||
TaskScheduler::task_handler_t task)
|
||||
{
|
||||
return this->Schedule(::randtime(min, max), group, std::move(task));
|
||||
@@ -569,75 +442,43 @@ public:
|
||||
TaskContext& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups);
|
||||
|
||||
/// Delays all tasks with the given duration from within the context.
|
||||
template<class Rep, class Period>
|
||||
TaskContext& DelayAll(std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.DelayAll(duration);
|
||||
});
|
||||
}
|
||||
TaskContext& DelayAll(TaskScheduler::duration_t duration);
|
||||
|
||||
/// Delays all tasks with a random duration between min and max from within the context.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& DelayAll(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
TaskContext& DelayAll(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->DelayAll(::randtime(min, max));
|
||||
}
|
||||
|
||||
/// Delays all tasks of a group with the given duration from within the context.
|
||||
template<class Rep, class Period>
|
||||
TaskContext& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.DelayGroup(group, duration);
|
||||
});
|
||||
}
|
||||
TaskContext& DelayGroup(TaskScheduler::group_t const group, TaskScheduler::duration_t duration);
|
||||
|
||||
/// Delays all tasks of a group with a random duration between min and max from within the context.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& DelayGroup(TaskScheduler::group_t const group,
|
||||
std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->DelayGroup(group, ::randtime(min, max));
|
||||
}
|
||||
|
||||
/// Reschedule all tasks with the given duration.
|
||||
template<class Rep, class Period>
|
||||
TaskContext& RescheduleAll(std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.RescheduleAll(duration);
|
||||
});
|
||||
}
|
||||
TaskContext& RescheduleAll(TaskScheduler::duration_t duration);
|
||||
|
||||
/// Reschedule all tasks with a random duration between min and max.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& RescheduleAll(std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
TaskContext& RescheduleAll(std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->RescheduleAll(::randtime(min, max));
|
||||
}
|
||||
|
||||
/// Reschedule all tasks of a group with the given duration.
|
||||
template<class Rep, class Period>
|
||||
TaskContext& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<Rep, Period> duration)
|
||||
{
|
||||
return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
|
||||
{
|
||||
return scheduler.RescheduleGroup(group, duration);
|
||||
});
|
||||
}
|
||||
TaskContext& RescheduleGroup(TaskScheduler::group_t const group, TaskScheduler::duration_t duration);
|
||||
|
||||
/// Reschedule all tasks of a group with a random duration between min and max.
|
||||
template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
|
||||
TaskContext& RescheduleGroup(TaskScheduler::group_t const group,
|
||||
std::chrono::duration<RepLeft, PeriodLeft> min,
|
||||
std::chrono::duration<RepRight, PeriodRight> max)
|
||||
std::chrono::milliseconds min,
|
||||
std::chrono::milliseconds max)
|
||||
{
|
||||
return this->RescheduleGroup(group, ::randtime(min, max));
|
||||
}
|
||||
|
||||
@@ -482,7 +482,7 @@ TC_COMMON_API void StringReplaceAll(std::string* str, std::string_view text, std
|
||||
|
||||
// simple class for not-modifyable list
|
||||
template <typename T>
|
||||
class HookList final
|
||||
class HookList
|
||||
{
|
||||
private:
|
||||
typedef std::vector<T> ContainerType;
|
||||
@@ -495,7 +495,7 @@ class HookList final
|
||||
|
||||
HookList<T>& operator+=(T&& t)
|
||||
{
|
||||
_container.push_back(std::move(t));
|
||||
_container.emplace_back(std::move(t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ void SummonList::DoActionImpl(int32 action, StorageType& summons, uint16 max)
|
||||
|
||||
ScriptedAI::ScriptedAI(Creature* creature) : ScriptedAI(creature, creature->GetScriptId()) { }
|
||||
|
||||
ScriptedAI::ScriptedAI(Creature* creature, uint32 scriptId) : CreatureAI(creature, scriptId), IsFleeing(false), _isCombatMovementAllowed(true)
|
||||
ScriptedAI::ScriptedAI(Creature* creature, uint32 scriptId) : CreatureAI(creature, scriptId), _isCombatMovementAllowed(true)
|
||||
{
|
||||
_difficulty = me->GetMap()->GetDifficultyID();
|
||||
}
|
||||
@@ -538,6 +538,8 @@ BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature), instan
|
||||
});
|
||||
}
|
||||
|
||||
BossAI::~BossAI() = default;
|
||||
|
||||
void BossAI::_Reset()
|
||||
{
|
||||
if (!me->IsAlive())
|
||||
@@ -657,6 +659,8 @@ void BossAI::_DespawnAtEvade(Seconds delayToRespawn /*= 30s*/, Creature* who /*=
|
||||
// WorldBossAI - for non-instanced bosses
|
||||
WorldBossAI::WorldBossAI(Creature* creature) : ScriptedAI(creature), summons(creature) { }
|
||||
|
||||
WorldBossAI::~WorldBossAI() = default;
|
||||
|
||||
void WorldBossAI::_Reset()
|
||||
{
|
||||
if (!me->IsAlive())
|
||||
|
||||
@@ -150,9 +150,6 @@ struct TC_GAME_API ScriptedAI : public CreatureAI
|
||||
// Variables
|
||||
// *************
|
||||
|
||||
// For fleeing
|
||||
bool IsFleeing;
|
||||
|
||||
// *************
|
||||
// Pure virtual functions
|
||||
// *************
|
||||
@@ -312,7 +309,7 @@ class TC_GAME_API BossAI : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
BossAI(Creature* creature, uint32 bossId);
|
||||
virtual ~BossAI() { }
|
||||
virtual ~BossAI();
|
||||
|
||||
InstanceScript* const instance;
|
||||
|
||||
@@ -359,7 +356,7 @@ class TC_GAME_API WorldBossAI : public ScriptedAI
|
||||
{
|
||||
public:
|
||||
WorldBossAI(Creature* creature);
|
||||
virtual ~WorldBossAI() { }
|
||||
virtual ~WorldBossAI();
|
||||
|
||||
void JustSummoned(Creature* summon) override;
|
||||
void SummonedCreatureDespawn(Creature* summon) override;
|
||||
|
||||
@@ -159,6 +159,11 @@ void InstanceScript::SetHeaders(std::string const& dataHeaders)
|
||||
headers = dataHeaders;
|
||||
}
|
||||
|
||||
void InstanceScript::SetBossNumber(uint32 number)
|
||||
{
|
||||
bosses.resize(number);
|
||||
}
|
||||
|
||||
void InstanceScript::LoadBossBoundaries(BossBoundaryData const& data)
|
||||
{
|
||||
for (BossBoundaryEntry const& entry : data)
|
||||
|
||||
@@ -322,7 +322,7 @@ class TC_GAME_API InstanceScript : public ZoneScript
|
||||
|
||||
protected:
|
||||
void SetHeaders(std::string const& dataHeaders);
|
||||
void SetBossNumber(uint32 number) { bosses.resize(number); }
|
||||
void SetBossNumber(uint32 number);
|
||||
void LoadBossBoundaries(BossBoundaryData const& data);
|
||||
void LoadDoorData(DoorData const* data);
|
||||
void LoadMinionData(MinionData const* data);
|
||||
|
||||
@@ -102,6 +102,13 @@ std::string_view SpellScriptBase::GetScriptName() const
|
||||
return m_scriptName;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SpellScriptBase::HookList<T>& SpellScriptBase::HookList<T>::operator+=(T&& t)
|
||||
{
|
||||
::HookList<T>::operator+=(std::move(t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpellScriptBase::EffectHook::EffectHook(uint8 effIndex)
|
||||
{
|
||||
// effect index must be in range <0;2>, allow use of special effindexes
|
||||
@@ -248,6 +255,19 @@ bool SpellScript::TargetHook::CheckEffect(SpellInfo const* spellInfo, uint8 effI
|
||||
return false;
|
||||
}
|
||||
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::CastHandler>& SpellScriptBase::HookList<SpellScript::CastHandler>::operator+=(SpellScript::CastHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::CheckCastHandler>& SpellScriptBase::HookList<SpellScript::CheckCastHandler>::operator+=(SpellScript::CheckCastHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::EffectHandler>& SpellScriptBase::HookList<SpellScript::EffectHandler>::operator+=(SpellScript::EffectHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::BeforeHitHandler>& SpellScriptBase::HookList<SpellScript::BeforeHitHandler>::operator+=(SpellScript::BeforeHitHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::HitHandler>& SpellScriptBase::HookList<SpellScript::HitHandler>::operator+=(SpellScript::HitHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::OnCalcCritChanceHandler>& SpellScriptBase::HookList<SpellScript::OnCalcCritChanceHandler>::operator+=(SpellScript::OnCalcCritChanceHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::ObjectAreaTargetSelectHandler>& SpellScriptBase::HookList<SpellScript::ObjectAreaTargetSelectHandler>::operator+=(SpellScript::ObjectAreaTargetSelectHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::ObjectTargetSelectHandler>& SpellScriptBase::HookList<SpellScript::ObjectTargetSelectHandler>::operator+=(SpellScript::ObjectTargetSelectHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::DestinationTargetSelectHandler>& SpellScriptBase::HookList<SpellScript::DestinationTargetSelectHandler>::operator+=(SpellScript::DestinationTargetSelectHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::DamageAndHealingCalcHandler>& SpellScriptBase::HookList<SpellScript::DamageAndHealingCalcHandler>::operator+=(SpellScript::DamageAndHealingCalcHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::OnCalculateResistAbsorbHandler>& SpellScriptBase::HookList<SpellScript::OnCalculateResistAbsorbHandler>::operator+=(SpellScript::OnCalculateResistAbsorbHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<SpellScript::EmpowerStageCompletedHandler>& SpellScriptBase::HookList<SpellScript::EmpowerStageCompletedHandler>::operator+=(SpellScript::EmpowerStageCompletedHandler&& hook);
|
||||
|
||||
SpellScript::SpellScript(): m_spell(nullptr), m_hitPreventEffectMask(0), m_hitPreventDefaultEffectMask(0)
|
||||
{
|
||||
}
|
||||
@@ -770,6 +790,25 @@ Difficulty SpellScript::GetCastDifficulty() const
|
||||
return m_spell->GetCastDifficulty();
|
||||
}
|
||||
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::CheckAreaTargetHandler>& SpellScriptBase::HookList<AuraScript::CheckAreaTargetHandler>::operator+=(AuraScript::CheckAreaTargetHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::AuraDispelHandler>& SpellScriptBase::HookList<AuraScript::AuraDispelHandler>::operator+=(AuraScript::AuraDispelHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::AuraHeartbeatHandler>& SpellScriptBase::HookList<AuraScript::AuraHeartbeatHandler>::operator+=(AuraScript::AuraHeartbeatHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectApplyHandler>& SpellScriptBase::HookList<AuraScript::EffectApplyHandler>::operator+=(AuraScript::EffectApplyHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectPeriodicHandler>& SpellScriptBase::HookList<AuraScript::EffectPeriodicHandler>::operator+=(AuraScript::EffectPeriodicHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectUpdatePeriodicHandler>& SpellScriptBase::HookList<AuraScript::EffectUpdatePeriodicHandler>::operator+=(AuraScript::EffectUpdatePeriodicHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectCalcAmountHandler>& SpellScriptBase::HookList<AuraScript::EffectCalcAmountHandler>::operator+=(AuraScript::EffectCalcAmountHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectCalcPeriodicHandler>& SpellScriptBase::HookList<AuraScript::EffectCalcPeriodicHandler>::operator+=(AuraScript::EffectCalcPeriodicHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectCalcSpellModHandler>& SpellScriptBase::HookList<AuraScript::EffectCalcSpellModHandler>::operator+=(AuraScript::EffectCalcSpellModHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectCalcCritChanceHandler>& SpellScriptBase::HookList<AuraScript::EffectCalcCritChanceHandler>::operator+=(AuraScript::EffectCalcCritChanceHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectCalcDamageAndHealingHandler>& SpellScriptBase::HookList<AuraScript::EffectCalcDamageAndHealingHandler>::operator+=(AuraScript::EffectCalcDamageAndHealingHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectAbsorbHandler>& SpellScriptBase::HookList<AuraScript::EffectAbsorbHandler>::operator+=(AuraScript::EffectAbsorbHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectAbsorbHealHandler>& SpellScriptBase::HookList<AuraScript::EffectAbsorbHealHandler>::operator+=(AuraScript::EffectAbsorbHealHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::CheckProcHandler>& SpellScriptBase::HookList<AuraScript::CheckProcHandler>::operator+=(AuraScript::CheckProcHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::CheckEffectProcHandler>& SpellScriptBase::HookList<AuraScript::CheckEffectProcHandler>::operator+=(AuraScript::CheckEffectProcHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::AuraProcHandler>& SpellScriptBase::HookList<AuraScript::AuraProcHandler>::operator+=(AuraScript::AuraProcHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EffectProcHandler>& SpellScriptBase::HookList<AuraScript::EffectProcHandler>::operator+=(AuraScript::EffectProcHandler&& hook);
|
||||
template TC_GAME_API SpellScriptBase::HookList<AuraScript::EnterLeaveCombatHandler>& SpellScriptBase::HookList<AuraScript::EnterLeaveCombatHandler>::operator+=(AuraScript::EnterLeaveCombatHandler&& hook);
|
||||
|
||||
bool AuraScript::_Validate(SpellInfo const* entry)
|
||||
{
|
||||
for (auto itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr)
|
||||
|
||||
@@ -89,6 +89,14 @@ public:
|
||||
protected:
|
||||
virtual bool _Validate(SpellInfo const* entry);
|
||||
|
||||
// compile barrier to avoid instantiating operator+= in every script file
|
||||
template <typename T>
|
||||
class HookList : public ::HookList<T>
|
||||
{
|
||||
public:
|
||||
HookList& operator+=(T&& t);
|
||||
};
|
||||
|
||||
class TC_GAME_API EffectHook
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -743,7 +743,8 @@ struct battleground_deephaul_ravine : BattlegroundScript
|
||||
return false;
|
||||
}
|
||||
|
||||
void DoForLeaders(std::function<void(Creature*)> const& fn) const
|
||||
template <std::invocable<Creature*> Action>
|
||||
void DoForLeaders(Action const& fn) const
|
||||
{
|
||||
for (ObjectGuid const& guid : _leaderGUIDs)
|
||||
if (Creature* creature = battlegroundMap->GetCreature(guid))
|
||||
|
||||
@@ -367,7 +367,8 @@ struct battleground_eye_of_the_storm : BattlegroundScript
|
||||
return baseCount;
|
||||
}
|
||||
|
||||
void DoForFlagKeepers(std::function<void(Player*)> const& action) const
|
||||
template <std::invocable<Player*> Action>
|
||||
void DoForFlagKeepers(Action const& action) const
|
||||
{
|
||||
if (GameObject const* flag = battlegroundMap->GetGameObject(_flagGUID))
|
||||
if (Player* carrier = ObjectAccessor::FindPlayer(flag->GetFlagCarrierGUID()))
|
||||
|
||||
@@ -339,7 +339,7 @@ struct battleground_isle_of_conquest : BattlegroundScript
|
||||
{
|
||||
BattlegroundScript::OnStart();
|
||||
|
||||
auto gameobjectAction = [&](GuidVector const& guids, std::function<void(GameObject*)> const& action) -> void
|
||||
auto gameobjectAction = [&]<std::invocable<GameObject*> Action>(GuidVector const& guids, Action const& action) -> void
|
||||
{
|
||||
for (ObjectGuid const& guid : guids)
|
||||
if (GameObject* gameObject = battlegroundMap->GetGameObject(guid))
|
||||
|
||||
@@ -715,7 +715,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void DoForPlayersInControlZone(std::function<void(GameObject const*, Player*)> const& fn) const
|
||||
template <std::invocable<GameObject const*, Player*> Action>
|
||||
void DoForPlayersInControlZone(Action const& fn) const
|
||||
{
|
||||
if (GameObject const* controlZone = GetControlZone())
|
||||
for (ObjectGuid const& playerGuid : *controlZone->GetInsidePlayers())
|
||||
|
||||
@@ -190,7 +190,8 @@ struct battleground_twin_peaks : BattlegroundScript
|
||||
TriggerGameEvent(TwinPeaks::Events::StartBattle);
|
||||
}
|
||||
|
||||
void DoForFlagKeepers(std::function<void(Player*)> const& action) const
|
||||
template <std::invocable<Player*> Action>
|
||||
void DoForFlagKeepers(Action const& action) const
|
||||
{
|
||||
for (ObjectGuid flagGUID : _flags)
|
||||
if (GameObject const* flag = battlegroundMap->GetGameObject(flagGUID))
|
||||
|
||||
@@ -227,7 +227,8 @@ struct battleground_warsong_gulch : BattlegroundScript
|
||||
battleground->RewardHonorToTeam(battleground->GetBonusHonorFromKill(_honorEndKills), HORDE);
|
||||
}
|
||||
|
||||
void DoForFlagKeepers(std::function<void(Player*)> const& action) const
|
||||
template <std::invocable<Player*> Action>
|
||||
void DoForFlagKeepers(Action const& action) const
|
||||
{
|
||||
for (ObjectGuid flagGUID : _flags)
|
||||
if (GameObject const* flag = battlegroundMap->GetGameObject(flagGUID))
|
||||
|
||||
@@ -637,12 +637,12 @@ struct npc_high_overlord_saurfang_icc : public ScriptedAI
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuardBroadcast(std::function<void(Creature*)>&& action) const
|
||||
void GuardBroadcast(int32 action) const
|
||||
{
|
||||
std::vector<Creature*> guardList;
|
||||
GetCreatureListWithEntryInGrid(guardList, me, NPC_SE_KOR_KRON_REAVER, 100.0f);
|
||||
for (Creature* guard : guardList)
|
||||
action(guard);
|
||||
guard->AI()->DoAction(action);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
@@ -681,19 +681,13 @@ struct npc_high_overlord_saurfang_icc : public ScriptedAI
|
||||
_events.ScheduleEvent(EVENT_OUTRO_HORDE_5, 30s); // move
|
||||
me->SetDisableGravity(false);
|
||||
me->GetMotionMaster()->MoveFall();
|
||||
GuardBroadcast([](Creature* guard)
|
||||
{
|
||||
guard->AI()->DoAction(ACTION_DESPAWN);
|
||||
});
|
||||
GuardBroadcast(ACTION_DESPAWN);
|
||||
break;
|
||||
}
|
||||
case ACTION_INTERRUPT_INTRO:
|
||||
{
|
||||
_events.Reset();
|
||||
GuardBroadcast([](Creature* guard)
|
||||
{
|
||||
guard->AI()->DoAction(ACTION_DESPAWN);
|
||||
});
|
||||
GuardBroadcast(ACTION_DESPAWN);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -774,10 +768,7 @@ struct npc_high_overlord_saurfang_icc : public ScriptedAI
|
||||
break;
|
||||
case EVENT_INTRO_HORDE_8:
|
||||
Talk(SAY_INTRO_HORDE_8);
|
||||
GuardBroadcast([](Creature* guard)
|
||||
{
|
||||
guard->AI()->DoAction(ACTION_CHARGE);
|
||||
});
|
||||
GuardBroadcast(ACTION_CHARGE);
|
||||
me->GetMotionMaster()->MoveCharge(chargePos[0].GetPositionX(), chargePos[0].GetPositionY(), chargePos[0].GetPositionZ(), 8.5f, POINT_CHARGE);
|
||||
break;
|
||||
case EVENT_OUTRO_HORDE_2: // say
|
||||
@@ -834,12 +825,12 @@ struct npc_muradin_bronzebeard_icc : public ScriptedAI
|
||||
return false;
|
||||
}
|
||||
|
||||
void GuardBroadcast(std::function<void(Creature*)>&& action) const
|
||||
void GuardBroadcast(int32 action) const
|
||||
{
|
||||
std::vector<Creature*> guardList;
|
||||
GetCreatureListWithEntryInGrid(guardList, me, NPC_SE_SKYBREAKER_MARINE, 100.0f);
|
||||
for (Creature* guard : guardList)
|
||||
action(guard);
|
||||
guard->AI()->DoAction(action);
|
||||
}
|
||||
|
||||
void DoAction(int32 action) override
|
||||
@@ -874,10 +865,7 @@ struct npc_muradin_bronzebeard_icc : public ScriptedAI
|
||||
Talk(SAY_OUTRO_ALLIANCE_1);
|
||||
me->SetDisableGravity(false);
|
||||
me->GetMotionMaster()->MoveFall();
|
||||
GuardBroadcast([](Creature* guard)
|
||||
{
|
||||
guard->AI()->DoAction(ACTION_DESPAWN);
|
||||
});
|
||||
GuardBroadcast(ACTION_DESPAWN);
|
||||
|
||||
// temp until outro fully done - to put deathbringer on respawn timer (until next reset)
|
||||
if (Creature* deathbringer = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_DEATHBRINGER_SAURFANG)))
|
||||
@@ -886,10 +874,7 @@ struct npc_muradin_bronzebeard_icc : public ScriptedAI
|
||||
}
|
||||
case ACTION_INTERRUPT_INTRO:
|
||||
_events.Reset();
|
||||
GuardBroadcast([](Creature* guard)
|
||||
{
|
||||
guard->AI()->DoAction(ACTION_DESPAWN);
|
||||
});
|
||||
GuardBroadcast(ACTION_DESPAWN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -932,10 +917,7 @@ struct npc_muradin_bronzebeard_icc : public ScriptedAI
|
||||
break;
|
||||
case EVENT_INTRO_ALLIANCE_5:
|
||||
Talk(SAY_INTRO_ALLIANCE_5);
|
||||
GuardBroadcast([](Creature* guard)
|
||||
{
|
||||
guard->AI()->DoAction(ACTION_CHARGE);
|
||||
});
|
||||
GuardBroadcast(ACTION_CHARGE);
|
||||
me->GetMotionMaster()->MoveCharge(chargePos[0].GetPositionX(), chargePos[0].GetPositionY(), chargePos[0].GetPositionZ(), 8.5f, POINT_CHARGE);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -160,12 +160,25 @@ static Player* FindEligibleTarget(Creature const* me, bool isGateOpen)
|
||||
}
|
||||
|
||||
/* Wave data */
|
||||
typedef std::pair<uint32, uint8> GothikWaveEntry; // (npcEntry, npcCount)
|
||||
typedef std::set<GothikWaveEntry> GothikWave;
|
||||
typedef std::pair<GothikWave, uint8> GothikWaveInfo; // (wave, secondsToNext)
|
||||
typedef std::vector<GothikWaveInfo> GothikWaveData;
|
||||
const GothikWaveData waves10 =
|
||||
struct GothikWaveEntry
|
||||
{
|
||||
uint32 CreatureId = 0;
|
||||
uint32 Count = 0;
|
||||
};
|
||||
|
||||
struct GothikWaveInfo
|
||||
{
|
||||
constexpr GothikWaveInfo(std::initializer_list<GothikWaveEntry> waves, int64 timeToNextWave) : TimeToNextWave(timeToNextWave)
|
||||
{
|
||||
std::ranges::copy_n(waves.begin(), std::min(std::ranges::ssize(waves), std::ranges::ssize(Creatures)), Creatures.begin());
|
||||
}
|
||||
|
||||
std::array<GothikWaveEntry, 3> Creatures;
|
||||
Seconds TimeToNextWave;
|
||||
};
|
||||
|
||||
static constexpr std::array<GothikWaveInfo, 19> waves10 =
|
||||
{ {
|
||||
{
|
||||
{{NPC_LIVE_TRAINEE, 2}},
|
||||
20},
|
||||
@@ -223,10 +236,10 @@ const GothikWaveData waves10 =
|
||||
{
|
||||
{{NPC_LIVE_TRAINEE, 2}},
|
||||
0}
|
||||
};
|
||||
} };
|
||||
|
||||
const GothikWaveData waves25 =
|
||||
{
|
||||
static constexpr std::array<GothikWaveInfo, 18> waves25 =
|
||||
{ {
|
||||
{
|
||||
{{NPC_LIVE_TRAINEE, 3}},
|
||||
20},
|
||||
@@ -281,7 +294,7 @@ const GothikWaveData waves25 =
|
||||
{
|
||||
{{NPC_LIVE_RIDER, 1}, {NPC_LIVE_KNIGHT, 2}, {NPC_LIVE_TRAINEE, 3}},
|
||||
0}
|
||||
};
|
||||
} };
|
||||
|
||||
// GUID of first trigger NPC (used as offset for guid checks)
|
||||
// 0-1 are living side soul triggers, 2-3 are spectral side soul triggers, 4 is living rider spawn trigger, 5-7 are living other spawn trigger, 8-12 are skull pile triggers
|
||||
@@ -426,7 +439,7 @@ struct boss_gothik : public BossAI
|
||||
{
|
||||
case EVENT_SUMMON:
|
||||
{
|
||||
if (RAID_MODE(waves10,waves25).size() <= _waveCount) // bounds check
|
||||
if (RAID_MODE(waves10.size(), waves25.size()) <= _waveCount) // bounds check
|
||||
{
|
||||
TC_LOG_INFO("scripts", "GothikAI: Wave count {} is out of range for difficulty {}.", _waveCount, static_cast<uint32>(GetDifficulty()));
|
||||
break;
|
||||
@@ -434,8 +447,9 @@ struct boss_gothik : public BossAI
|
||||
|
||||
std::list<Creature*> triggers;
|
||||
me->GetCreatureListWithEntryInGrid(triggers, NPC_TRIGGER, 150.0f);
|
||||
for (GothikWaveEntry entry : RAID_MODE(waves10, waves25)[_waveCount].first)
|
||||
for (uint8 i = 0; i < entry.second; ++i)
|
||||
for (GothikWaveEntry entry : RAID_MODE(waves10[_waveCount], waves25[_waveCount]).Creatures)
|
||||
{
|
||||
for (uint32 i = 0; i < entry.Count; ++i)
|
||||
{
|
||||
// GUID layout is as follows:
|
||||
// CGUID+4: center (back of platform) - primary rider spawn
|
||||
@@ -443,7 +457,7 @@ struct boss_gothik : public BossAI
|
||||
// CGUID+6: center (front of platform) - second spawn
|
||||
// CGUID+7: south (front of platform) - primary trainee spawn
|
||||
uint32 targetDBGuid;
|
||||
switch (entry.first)
|
||||
switch (entry.CreatureId)
|
||||
{
|
||||
case NPC_LIVE_RIDER: // only spawns from center (back) > north
|
||||
targetDBGuid = (CGUID_TRIGGER + 4) + (i % 2);
|
||||
@@ -455,19 +469,17 @@ struct boss_gothik : public BossAI
|
||||
targetDBGuid = (CGUID_TRIGGER + 7) - (i % 3);
|
||||
break;
|
||||
default:
|
||||
targetDBGuid = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Creature* trigger : triggers)
|
||||
if (trigger && trigger->GetSpawnId() == targetDBGuid)
|
||||
{
|
||||
DoSummon(entry.first, trigger, 1.0f, 15s, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
|
||||
break;
|
||||
}
|
||||
auto triggerItr = std::ranges::find(triggers, targetDBGuid, [](Creature const* trigger) { return trigger->GetSpawnId(); });
|
||||
if (triggerItr != triggers.end())
|
||||
DoSummon(entry.CreatureId, *triggerItr, 1.0f, 15s, TEMPSUMMON_CORPSE_TIMED_DESPAWN);
|
||||
}
|
||||
}
|
||||
|
||||
if (uint8 timeToNext = RAID_MODE(waves10, waves25)[_waveCount].second)
|
||||
events.Repeat(Seconds(timeToNext));
|
||||
if (Seconds timeToNext = RAID_MODE(waves10[_waveCount], waves25[_waveCount]).TimeToNextWave; timeToNext > 0s)
|
||||
events.Repeat(timeToNext);
|
||||
|
||||
++_waveCount;
|
||||
break;
|
||||
@@ -532,6 +544,8 @@ struct boss_gothik : public BossAI
|
||||
case EVENT_INTRO_4:
|
||||
Talk(SAY_INTRO_4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user