aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2014-06-07 20:27:23 -0500
committerSubv <subv2112@gmail.com>2014-06-07 20:27:23 -0500
commitf71abd173ebad2da329c04f5ea3b1d8704007303 (patch)
tree993fad51c1ab97b1b83adc4f1e0640033c7ae56f /src
parentbbe51bbd130908603c0a5c0c5d14eae2f0495ede (diff)
parente1e5f2a196240707f1671a02df6bd4966fed67f3 (diff)
Merge branch '4.3.4' of github.com:TrinityCore/TrinityCore into 4.3.4_phases
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Main.cpp16
-rw-r--r--src/server/game/AI/CreatureAIImpl.h349
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp1
-rw-r--r--src/server/game/Entities/Player/Player.cpp38
-rw-r--r--src/server/game/Entities/Player/Player.h6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp3
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp82
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp2
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp1
-rw-r--r--src/server/game/Handlers/PetHandler.cpp7
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp39
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp7
-rw-r--r--src/server/game/Maps/Map.cpp7
-rw-r--r--src/server/game/Quests/QuestDef.cpp2
-rw-r--r--src/server/game/Quests/QuestDef.h4
-rw-r--r--src/server/game/Server/WorldSession.cpp9
-rw-r--r--src/server/game/Server/WorldSession.h3
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp20
-rw-r--r--src/server/game/Spells/SpellMgr.cpp15
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp13
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp101
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp149
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp139
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp163
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp88
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp99
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp118
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp114
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp103
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp240
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp8
-rw-r--r--src/server/scripts/World/npcs_special.cpp56
-rw-r--r--src/server/shared/Database/DatabaseWorkerPool.h2
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp2
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h2
-rw-r--r--src/server/shared/Packets/ByteBuffer.h12
-rw-r--r--src/server/shared/Utilities/Util.h350
-rw-r--r--src/server/worldserver/Master.cpp18
39 files changed, 1334 insertions, 1056 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index d1b2b614037..be6623c7fa3 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -179,24 +179,24 @@ extern int main(int argc, char** argv)
Handler.register_handler(SIGTERM, &SignalTERM);
#if defined(_WIN32) || defined(__linux__)
-
+
///- Handle affinity for multiple processors and process priority
uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0);
bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false);
#ifdef _WIN32 // Windows
-
+
HANDLE hProcess = GetCurrentProcess();
if (affinity > 0)
{
ULONG_PTR appAff;
ULONG_PTR sysAff;
-
+
if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
{
// remove non accessible processors
ULONG_PTR currentAffinity = affinity & appAff;
-
+
if (!currentAffinity)
TC_LOG_ERROR("server.authserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the authserver. Accessible processors bitmask (hex): %x", affinity, appAff);
else if (SetProcessAffinityMask(hProcess, currentAffinity))
@@ -205,7 +205,7 @@ extern int main(int argc, char** argv)
TC_LOG_ERROR("server.authserver", "Can't set used processors (hex): %x", currentAffinity);
}
}
-
+
if (highPriority)
{
if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
@@ -213,9 +213,9 @@ extern int main(int argc, char** argv)
else
TC_LOG_ERROR("server.authserver", "Can't set authserver process priority class.");
}
-
+
#else // Linux
-
+
if (affinity > 0)
{
cpu_set_t mask;
@@ -242,7 +242,7 @@ extern int main(int argc, char** argv)
else
TC_LOG_INFO("server.authserver", "authserver process priority class set to %i", getpriority(PRIO_PROCESS, 0));
}
-
+
#endif
#endif
diff --git a/src/server/game/AI/CreatureAIImpl.h b/src/server/game/AI/CreatureAIImpl.h
index 378d3ca18ab..838171a544e 100644
--- a/src/server/game/AI/CreatureAIImpl.h
+++ b/src/server/game/AI/CreatureAIImpl.h
@@ -311,355 +311,6 @@ const T& RAND(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, c
}
}
-class EventMap
-{
- /**
- * Internal storage type.
- * Key: Time as uint32 when the event should occur.
- * Value: The event data as uint32.
- *
- * Structure of event data:
- * - Bit 0 - 15: Event Id.
- * - Bit 16 - 23: Group
- * - Bit 24 - 31: Phase
- * - Pattern: 0xPPGGEEEE
- */
- typedef std::multimap<uint32, uint32> EventStore;
-
- public:
- EventMap() : _time(0), _phase(0), _lastEvent(0) { }
-
- /**
- * @name Reset
- * @brief Removes all scheduled events and resets time and phase.
- */
- void Reset()
- {
- _eventMap.clear();
- _time = 0;
- _phase = 0;
- }
-
- /**
- * @name Update
- * @brief Updates the timer of the event map.
- * @param time Value to be added to time.
- */
- void Update(uint32 time)
- {
- _time += time;
- }
-
- /**
- * @name GetTimer
- * @return Current timer value.
- */
- uint32 GetTimer() const
- {
- return _time;
- }
-
- /**
- * @name GetPhaseMask
- * @return Active phases as mask.
- */
- uint8 GetPhaseMask() const
- {
- return _phase;
- }
-
- /**
- * @name Empty
- * @return True, if there are no events scheduled.
- */
- bool Empty() const
- {
- return _eventMap.empty();
- }
-
- /**
- * @name SetPhase
- * @brief Sets the phase of the map (absolute).
- * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase.
- */
- void SetPhase(uint8 phase)
- {
- if (!phase)
- _phase = 0;
- else if (phase <= 8)
- _phase = (1 << (phase - 1));
- }
-
- /**
- * @name AddPhase
- * @brief Activates the given phase (bitwise).
- * @param phase Phase which should be activated. Values: 1 - 8
- */
- void AddPhase(uint8 phase)
- {
- if (phase && phase <= 8)
- _phase |= (1 << (phase - 1));
- }
-
- /**
- * @name RemovePhase
- * @brief Deactivates the given phase (bitwise).
- * @param phase Phase which should be deactivated. Values: 1 - 8.
- */
- void RemovePhase(uint8 phase)
- {
- if (phase && phase <= 8)
- _phase &= ~(1 << (phase - 1));
- }
-
- /**
- * @name ScheduleEvent
- * @brief Creates new event entry in map.
- * @param eventId The id of the new event.
- * @param time The time in milliseconds until the event occurs.
- * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
- * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
- */
- void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0)
- {
- if (group && group <= 8)
- eventId |= (1 << (group + 15));
-
- if (phase && phase <= 8)
- eventId |= (1 << (phase + 23));
-
- _eventMap.insert(EventStore::value_type(_time + time, eventId));
- }
-
- /**
- * @name RescheduleEvent
- * @brief Cancels the given event and reschedules it.
- * @param eventId The id of the event.
- * @param time The time in milliseconds until the event occurs.
- * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
- * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
- */
- void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0)
- {
- CancelEvent(eventId);
- ScheduleEvent(eventId, time, group, phase);
- }
-
- /**
- * @name RepeatEvent
- * @brief Repeats the mostly recently executed event.
- * @param time Time until the event occurs.
- */
- void Repeat(uint32 time)
- {
- _eventMap.insert(EventStore::value_type(_time + time, _lastEvent));
- }
-
- /**
- * @name RepeatEvent
- * @brief Repeats the mostly recently executed event.
- * @param time Time until the event occurs. Equivalent to Repeat(urand(minTime, maxTime).
- */
- void Repeat(uint32 minTime, uint32 maxTime)
- {
- Repeat(urand(minTime, maxTime));
- }
-
- /**
- * @name ExecuteEvent
- * @brief Returns the next event to execute and removes it from map.
- * @return Id of the event to execute.
- */
- uint32 ExecuteEvent()
- {
- while (!Empty())
- {
- EventStore::iterator itr = _eventMap.begin();
-
- if (itr->first > _time)
- return 0;
- else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase))
- _eventMap.erase(itr);
- else
- {
- uint32 eventId = (itr->second & 0x0000FFFF);
- _lastEvent = itr->second; // include phase/group
- _eventMap.erase(itr);
- return eventId;
- }
- }
-
- return 0;
- }
-
- /**
- * @name DelayEvents
- * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0.
- * @param delay Amount of delay.
- */
- void DelayEvents(uint32 delay)
- {
- _time = delay < _time ? _time - delay : 0;
- }
-
- /**
- * @name DelayEvents
- * @brief Delay all events of the same group.
- * @param delay Amount of delay.
- * @param group Group of the events.
- */
- void DelayEvents(uint32 delay, uint32 group)
- {
- if (!group || group > 8 || Empty())
- 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++);
- }
- else
- ++itr;
- }
-
- _eventMap.insert(delayed.begin(), delayed.end());
- }
-
- /**
- * @name CancelEvent
- * @brief Cancels all events of the specified id.
- * @param eventId Event id to cancel.
- */
- void CancelEvent(uint32 eventId)
- {
- if (Empty())
- return;
-
- for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
- {
- if (eventId == (itr->second & 0x0000FFFF))
- _eventMap.erase(itr++);
- else
- ++itr;
- }
- }
-
- /**
- * @name CancelEventGroup
- * @brief Cancel events belonging to specified group.
- * @param group Group to cancel.
- */
- void CancelEventGroup(uint32 group)
- {
- if (!group || group > 8 || Empty())
- return;
-
- for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
- {
- if (itr->second & (1 << (group + 15)))
- _eventMap.erase(itr++);
- else
- ++itr;
- }
- }
-
- /**
- * @name GetNextEventTime
- * @brief Returns closest occurence of specified event.
- * @param eventId Wanted event id.
- * @return Time of found event.
- */
- uint32 GetNextEventTime(uint32 eventId) const
- {
- if (Empty())
- return 0;
-
- for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
- if (eventId == (itr->second & 0x0000FFFF))
- return itr->first;
-
- return 0;
- }
-
- /**
- * @name GetNextEventTime
- * @return Time of next event.
- */
- uint32 GetNextEventTime() const
- {
- return Empty() ? 0 : _eventMap.begin()->first;
- }
-
- /**
- * @name IsInPhase
- * @brief Returns wether event map is in specified phase or not.
- * @param phase Wanted phase.
- * @return True, if phase of event map contains specified phase.
- */
- bool IsInPhase(uint8 phase)
- {
- return phase <= 8 && (!phase || _phase & (1 << (phase - 1)));
- }
-
- /**
- * @name GetTimeUntilEvent
- * @brief Returns time in milliseconds until next event.
- * @param Id of the event.
- * @return Time of next event.
- */
- uint32 GetTimeUntilEvent(uint32 eventId) const
- {
- for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
- if (eventId == (itr->second & 0x0000FFFF))
- return itr->first - _time;
-
- return std::numeric_limits<uint32>::max();
- }
-
- private:
- /**
- * @name _time
- * @brief Internal timer.
- *
- * This does not represent the real date/time value.
- * It's more like a stopwatch: It can run, it can be stopped,
- * it can be resetted and so on. Events occur when this timer
- * has reached their time value. Its value is changed in the
- * Update method.
- */
- uint32 _time;
-
- /**
- * @name _phase
- * @brief Phase mask of the event map.
- *
- * Contains the phases the event map is in. Multiple
- * phases from 1 to 8 can be set with SetPhase or
- * AddPhase. RemovePhase deactives a phase.
- */
- uint8 _phase;
-
- /**
- * @name _eventMap
- * @brief Internal event storage map. Contains the scheduled events.
- *
- * See typedef at the beginning of the class for more
- * details.
- */
- EventStore _eventMap;
-
-
- /**
- * @name _lastEvent
- * @brief Stores information on the most recently executed event
- */
- uint32 _lastEvent;
-};
-
enum AITarget
{
AITARGET_SELF,
diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp
index c21d730b04c..9e72a124ae0 100644
--- a/src/server/game/Entities/Creature/GossipDef.cpp
+++ b/src/server/game/Entities/Creature/GossipDef.cpp
@@ -513,7 +513,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const
data << uint32(quest->GetRewHonorAddition());
data << float(quest->GetRewHonorMultiplier());
data << uint32(quest->GetSrcItemId()); // source item id
- data << uint32(quest->GetFlags() & 0xFFFF); // quest flags
+ data << uint32(quest->GetFlags()); // quest flags
data << uint32(quest->GetMinimapTargetMark()); // minimap target mark (skull, etc. missing enum)
data << uint32(quest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles)
data << uint32(quest->GetPlayersSlain()); // players slain
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 9b931f0ba6a..d07c3cb4bad 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1413,6 +1413,7 @@ void GameObject::Use(Unit* user)
// prevent removing GO at spell cancel
RemoveFromOwner();
SetOwnerGUID(player->GetGUID());
+ SetSpellId(0); // prevent removing unintended auras at Unit::RemoveGameObject
/// @todo find reasonable value for fishing hole search
GameObject* ok = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index b1d0cc88cde..283d4ead1a7 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -14846,7 +14846,7 @@ void Player::SendPreparedQuest(uint64 guid)
if (quest->IsAutoAccept() && CanAddQuest(quest, true) && CanTakeQuest(quest, true))
AddQuestAndCheckCompletion(quest, object);
- if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, CanCompleteRepeatableQuest(quest), true);
else
PlayerTalkClass->SendQuestGiverQuestDetails(quest, guid, true);
@@ -14914,7 +14914,7 @@ Quest const* Player::GetNextQuest(uint64 guid, Quest const* quest)
switch (GUID_HIPART(guid))
{
case HIGHGUID_PLAYER:
- ASSERT(quest->HasFlag(QUEST_FLAGS_AUTO_SUBMIT));
+ ASSERT(quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE));
return sObjectMgr->GetQuestTemplate(nextQuestID);
case HIGHGUID_UNIT:
case HIGHGUID_PET:
@@ -15015,7 +15015,7 @@ bool Player::CanCompleteQuest(uint32 quest_id)
return false; // not allow re-complete quest
// auto complete quest
- if ((qInfo->IsAutoComplete() || qInfo->GetFlags() & QUEST_FLAGS_AUTOCOMPLETE) && CanTakeQuest(qInfo, false))
+ if (qInfo->IsAutoComplete() && CanTakeQuest(qInfo, false))
return true;
QuestStatusMap::iterator itr = m_QuestStatus.find(quest_id);
@@ -15095,7 +15095,7 @@ bool Player::CanCompleteRepeatableQuest(Quest const* quest)
bool Player::CanRewardQuest(Quest const* quest, bool msg)
{
// not auto complete quest and not completed quest (only cheating case, then ignore without message)
- if (!quest->IsDFQuest() && !quest->IsAutoComplete() && !(quest->GetFlags() & QUEST_FLAGS_AUTOCOMPLETE) && GetQuestStatus(quest->GetQuestId()) != QUEST_STATUS_COMPLETE)
+ if (!quest->IsDFQuest() && !quest->IsAutoComplete() && GetQuestStatus(quest->GetQuestId()) != QUEST_STATUS_COMPLETE)
return false;
// daily quest can't be rewarded (25 daily quest already completed)
@@ -16450,9 +16450,7 @@ void Player::ItemAddedQuestCheck(uint32 entry, uint32 count)
uint16 curitemcount = q_status.ItemCount[j];
if (curitemcount < reqitemcount)
{
- uint16 additemcount = curitemcount + count <= reqitemcount ? count : reqitemcount - curitemcount;
- q_status.ItemCount[j] += additemcount;
-
+ q_status.ItemCount[j] = std::min<uint16>(q_status.ItemCount[j] + count, reqitemcount);
m_QuestStatusSave[questid] = true;
//SendQuestUpdateAddItem(qInfo, j, additemcount);
@@ -16474,9 +16472,11 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count)
uint32 questid = GetQuestSlotQuestId(i);
if (!questid)
continue;
+
Quest const* qInfo = sObjectMgr->GetQuestTemplate(questid);
if (!qInfo)
continue;
+
if (!qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_DELIVER))
continue;
@@ -16488,18 +16488,17 @@ void Player::ItemRemovedQuestCheck(uint32 entry, uint32 count)
QuestStatusData& q_status = m_QuestStatus[questid];
uint32 reqitemcount = qInfo->RequiredItemCount[j];
- uint16 curitemcount;
- if (q_status.Status != QUEST_STATUS_COMPLETE)
- curitemcount = q_status.ItemCount[j];
- else
- curitemcount = GetItemCount(entry, true);
- if (curitemcount < reqitemcount + count)
- {
- uint16 remitemcount = curitemcount <= reqitemcount ? count : count + reqitemcount - curitemcount;
- q_status.ItemCount[j] = (curitemcount <= remitemcount) ? 0 : curitemcount - remitemcount;
+ uint16 curitemcount = q_status.ItemCount[j];
- m_QuestStatusSave[questid] = true;
+ if (q_status.ItemCount[j] >= reqitemcount) // we may have more than what the status shows
+ curitemcount = GetItemCount(entry, false);
+ uint16 newItemCount = (count > curitemcount) ? 0 : curitemcount - count;
+ newItemCount = std::min<uint16>(newItemCount, reqitemcount);
+ if (newItemCount != q_status.ItemCount[j])
+ {
+ q_status.ItemCount[j] = newItemCount;
+ m_QuestStatusSave[questid] = true;
IncompleteQuest(questid);
}
return;
@@ -27573,6 +27572,11 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
return pet;
}
+bool Player::IsLoading() const
+{
+ return GetSession()->PlayerLoading();
+}
+
bool Player::CanUseMastery() const
{
return HasSpell(MasterySpells[getClass()]);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 1758ed20808..3d0300a681b 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1894,7 +1894,7 @@ class Player : public Unit, public GridObject<Player>
void UpdateZone(uint32 newZone, uint32 newArea);
void UpdateArea(uint32 newArea);
void SetNeedsZoneUpdate(bool needsUpdate) { m_needsZoneUpdate = needsUpdate; }
-
+
void UpdateZoneDependentAuras(uint32 zone_id); // zones
void UpdateAreaDependentAuras(uint32 area_id); // subzones
@@ -2523,6 +2523,8 @@ class Player : public Unit, public GridObject<Player>
std::string GetMapAreaAndZoneString();
std::string GetCoordsMapAreaAndZoneString();
+ bool IsLoading() const;
+
// Void Storage
bool IsVoidStorageUnlocked() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
void UnlockVoidStorage() { SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_VOID_UNLOCKED); }
@@ -2813,7 +2815,7 @@ class Player : public Unit, public GridObject<Player>
bool IsAlwaysDetectableFor(WorldObject const* seer) const;
uint8 m_grantableLevels;
-
+
bool m_needsZoneUpdate;
CUFProfile* _CUFProfiles[MAX_CUF_PROFILES];
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 7c042dad0c1..31425faf584 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -9473,8 +9473,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
// Check for immune to application of harmful magical effects
AuraEffectList const& immuneAuraApply = GetAuraEffectsByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL);
for (AuraEffectList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter)
- if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff
- ((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school
+ if (((*iter)->GetMiscValue() & spellInfo->GetSchoolMask()) && // Check school
!spellInfo->IsPositiveEffect(index)) // Harmful
return true;
}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index b72d79539aa..741dec9bfec 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -87,6 +87,18 @@ void WorldSession::HandleSwapInvItemOpcode(WorldPacket& recvData)
return;
}
+ if (_player->IsBankPos(INVENTORY_SLOT_BAG_0, srcslot) && !CanUseBank())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleSwapInvItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID)));
+ return;
+ }
+
+ if (_player->IsBankPos(INVENTORY_SLOT_BAG_0, dstslot) && !CanUseBank())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleSwapInvItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID)));
+ return;
+ }
+
uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot);
uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot);
@@ -139,6 +151,18 @@ void WorldSession::HandleSwapItem(WorldPacket& recvData)
return;
}
+ if (_player->IsBankPos(srcbag, srcslot) && !CanUseBank())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleSwapItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID)));
+ return;
+ }
+
+ if (_player->IsBankPos(dstbag, dstslot) && !CanUseBank())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleSwapItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID)));
+ return;
+ }
+
_player->SwapItem(src, dst);
}
@@ -780,15 +804,11 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& recvPacket)
uint64 guid;
recvPacket >> guid;
- // cheating protection
- /* not critical if "cheated", and check skip allow by slots in bank windows open by .bank command.
- Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_BANKER);
- if (!creature)
+ if (!CanUseBank(guid))
{
- TC_LOG_DEBUG("WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
+ TC_LOG_DEBUG("network", "WORLD: HandleBuyBankSlotOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
return;
}
- */
uint32 slot = _player->GetBankBagSlotCount();
@@ -834,6 +854,12 @@ void WorldSession::HandleAutoBankItemOpcode(WorldPacket& recvPacket)
recvPacket >> srcbag >> srcslot;
TC_LOG_DEBUG("network", "STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
+ if (!CanUseBank())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleAutoBankItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID)));
+ return;
+ }
+
Item* pItem = _player->GetItemByPos(srcbag, srcslot);
if (!pItem)
return;
@@ -865,6 +891,12 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket)
recvPacket >> srcbag >> srcslot;
TC_LOG_DEBUG("network", "STORAGE: receive srcbag = %u, srcslot = %u", srcbag, srcslot);
+ if (!CanUseBank())
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleAutoStoreBankItemOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(m_currentBankerGUID)));
+ return;
+ }
+
Item* pItem = _player->GetItemByPos(srcbag, srcslot);
if (!pItem)
return;
@@ -1463,6 +1495,12 @@ void WorldSession::HandleTransmogrifyItems(WorldPacket& recvData)
}
else
{
+ if (itemTransmogrifier->GetEntry() != newEntries[i])
+ {
+ TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) tried to transmogrify with an invalid entry (entry: %u) for item (lowguid: %u).", player->GetGUIDLow(), player->GetName().c_str(), newEntries[i], GUID_LOPART(itemGuids[i]));
+ return;
+ }
+
if (!Item::CanTransmogrifyItemWithItem(itemTransmogrified, itemTransmogrifier))
{
TC_LOG_DEBUG("network", "WORLD: HandleTransmogrifyItems - Player (GUID: %u, name: %s) failed CanTransmogrifyItemWithItem (%u with %u).", player->GetGUIDLow(), player->GetName().c_str(), itemTransmogrified->GetEntry(), itemTransmogrifier->GetEntry());
@@ -1549,6 +1587,13 @@ void WorldSession::HandleReforgeItemOpcode(WorldPacket& recvData)
if (!reforgeEntry)
{
+ if (!item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT))
+ {
+ TC_LOG_ERROR("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to remove reforge from non-reforged item (Entry: %u)", player->GetGUIDLow(), player->GetName().c_str(), item->GetEntry());
+ SendReforgeResult(false);
+ return;
+ }
+
// Reset the item
if (item->IsEquipped())
player->ApplyReforgeEnchantment(item, false);
@@ -1557,6 +1602,13 @@ void WorldSession::HandleReforgeItemOpcode(WorldPacket& recvData)
return;
}
+ if (item->GetEnchantmentId(REFORGE_ENCHANTMENT_SLOT))
+ {
+ TC_LOG_ERROR("network", "WORLD: HandleReforgeItemOpcode - Player (Guid: %u Name: %s) tried to reforge an already reforged item (Entry: %u)", player->GetGUIDLow(), player->GetName().c_str(), item->GetEntry());
+ SendReforgeResult(false);
+ return;
+ }
+
ItemReforgeEntry const* stats = sItemReforgeStore.LookupEntry(reforgeEntry);
if (!stats)
{
@@ -1586,3 +1638,21 @@ void WorldSession::HandleReforgeItemOpcode(WorldPacket& recvData)
if (item->IsEquipped())
player->ApplyReforgeEnchantment(item, true);
}
+
+bool WorldSession::CanUseBank(uint64 bankerGUID) const
+{
+ // bankerGUID parameter is optional, set to 0 by default.
+ if (!bankerGUID)
+ bankerGUID = m_currentBankerGUID;
+
+ bool isUsingBankCommand = (bankerGUID == GetPlayer()->GetGUID() && bankerGUID == m_currentBankerGUID);
+
+ if (!isUsingBankCommand)
+ {
+ Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(bankerGUID, UNIT_NPC_FLAG_BANKER);
+ if (!creature)
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 1d4c2f57311..3b5f9e16637 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -496,7 +496,7 @@ void WorldSession::HandleZoneUpdateOpcode(WorldPacket& recvData)
// use server side data, but only after update the player position. See Player::UpdatePosition().
GetPlayer()->SetNeedsZoneUpdate(true);
-
+
//GetPlayer()->SendInitWorldStates(true, newZone);
}
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 59ab27968f4..0a77a941b5f 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -101,6 +101,7 @@ void WorldSession::SendShowBank(uint64 guid)
{
WorldPacket data(SMSG_SHOW_BANK, 8);
data << guid;
+ m_currentBankerGUID = guid;
SendPacket(&data);
}
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 974f06975fa..301e9a7d2c8 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -874,7 +874,10 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData)
uint32 talentId, talentRank;
- for (uint32 i = 0; i < talentsCount; ++i)
+ // Client has max 19 talents, rounded up : 25
+ uint32 const MaxTalentsCount = 25;
+
+ for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i)
{
recvData >> talentId >> talentRank;
@@ -882,4 +885,6 @@ void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData)
}
_player->SendTalentsInfoData(true);
+
+ recvData.rfinish();
}
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 206238cbea2..19473edb6b4 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -273,7 +273,7 @@ void WorldSession::HandleQuestgiverChooseRewardOpcode(WorldPacket& recvData)
Object* object = _player;
- if (!quest->HasFlag(QUEST_FLAGS_AUTO_SUBMIT))
+ if (!quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
{
object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
if (!object || !object->hasInvolvedQuest(questId))
@@ -469,26 +469,43 @@ void WorldSession::HandleQuestConfirmAccept(WorldPacket& recvData)
void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
{
uint32 questId;
- uint64 playerGuid;
+ uint64 guid; // NPC / GameObject guid for normal quest completion. Player guid for self-completed quests
bool autoCompleteMode; // 0 - standart complete quest mode with npc, 1 - auto-complete mode
- recvData >> playerGuid >> questId >> autoCompleteMode;
+ recvData >> guid >> questId >> autoCompleteMode;
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u", uint32(GUID_LOPART(playerGuid)), questId);
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u self-complete: %u", uint32(GUID_LOPART(guid)), questId, autoCompleteMode ? 1 : 0);
Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
if (!quest)
return;
- Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, playerGuid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
- if (!object || !object->hasInvolvedQuest(questId))
+ if (autoCompleteMode && !quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ return;
+
+ Object* object = nullptr;
+ if (autoCompleteMode)
+ object = _player;
+ else
+ object = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT | TYPEMASK_GAMEOBJECT);
+
+ if (!object)
return;
if (autoCompleteMode == 0)
{
+ if (!object->hasInvolvedQuest(questId))
+ return;
+
// some kind of WPE protection
if (!_player->CanInteractWithQuestGiver(object))
return;
}
+ else
+ {
+ // Do not allow completing quests on other players.
+ if (guid != _player->GetGUID())
+ return;
+ }
if (!_player->CanSeeStartQuest(quest) && _player->GetQuestStatus(questId) == QUEST_STATUS_NONE)
{
@@ -503,16 +520,16 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
if (_player->GetQuestStatus(questId) != QUEST_STATUS_COMPLETE)
{
if (quest->IsRepeatable())
- _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanCompleteRepeatableQuest(quest), false);
+ _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanCompleteRepeatableQuest(quest), false);
else
- _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false);
+ _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false);
}
else
{
if (quest->GetReqItemsCount()) // some items required
- _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, playerGuid, _player->CanRewardQuest(quest, false), false);
+ _player->PlayerTalkClass->SendQuestGiverRequestItems(quest, guid, _player->CanRewardQuest(quest, false), false);
else // no items required
- _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, playerGuid, true);
+ _player->PlayerTalkClass->SendQuestGiverOfferReward(quest, guid, true);
}
if (Creature* creature = object->ToCreature())
@@ -586,7 +603,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket)
if (quest->IsAutoAccept() && receiver->CanAddQuest(quest, true) && receiver->CanTakeQuest(quest, true))
receiver->AddQuestAndCheckCompletion(quest, sender);
- if ((quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) || quest->HasFlag(QUEST_FLAGS_AUTOCOMPLETE))
+ if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly())
receiver->PlayerTalkClass->SendQuestGiverRequestItems(quest, sender->GetGUID(), receiver->CanCompleteRepeatableQuest(quest), true);
else
{
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index 2108b654d6b..67c36b1940e 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -61,7 +61,10 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
uint32 talentId, talentRank;
- for (uint32 i = 0; i < talentsCount; ++i)
+ // Client has max 21 talents for tree for 3 trees, rounded up : 70
+ uint32 const MaxTalentsCount = 70;
+
+ for (uint32 i = 0; i < talentsCount && i < MaxTalentsCount; ++i)
{
recvPacket >> talentId >> talentRank;
@@ -73,6 +76,8 @@ void WorldSession::HandleLearnPreviewTalents(WorldPacket& recvPacket)
}
_player->SendTalentsInfoData(false);
+
+ recvPacket.rfinish();
}
void WorldSession::HandleTalentWipeConfirmOpcode(WorldPacket& recvData)
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 3dbc4e99e52..92467487525 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2879,10 +2879,9 @@ bool InstanceMap::CanEnter(Player* player)
return false;
}
- // cannot enter while an encounter is in progress on raids
- /*Group* group = player->GetGroup();
- if (!player->IsGameMaster() && group && group->InCombatToInstance(GetInstanceId()) && player->GetMapId() != GetId())*/
- if (IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress())
+ // cannot enter while an encounter is in progress
+ // allow if just loading
+ if (!player->IsLoading() && IsRaid() && GetInstanceScript() && GetInstanceScript()->IsEncounterInProgress())
{
player->SendTransferAborted(GetId(), TRANSFER_ABORT_ZONE_IN_COMBAT);
return false;
diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp
index 9a17175b1a8..5f811714f3a 100644
--- a/src/server/game/Quests/QuestDef.cpp
+++ b/src/server/game/Quests/QuestDef.cpp
@@ -326,7 +326,7 @@ bool Quest::IsAutoAccept() const
bool Quest::IsAutoComplete() const
{
- return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) ? false : (Method == 0 || HasFlag(QUEST_FLAGS_AUTOCOMPLETE));
+ return sWorld->getBoolConfig(CONFIG_QUEST_IGNORE_AUTO_COMPLETE) || (Method == 0);
}
bool Quest::IsRaidQuest(Difficulty difficulty) const
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 4ab41ba13f8..3a9fdf024bf 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -147,11 +147,11 @@ enum QuestFlags
QUEST_FLAGS_FLAGS_PVP = 0x00002000, // Having this quest in log forces PvP flag
QUEST_FLAGS_UNAVAILABLE = 0x00004000, // Used on quests that are not generically available
QUEST_FLAGS_WEEKLY = 0x00008000,
- QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // auto complete
+ QUEST_FLAGS_AUTOCOMPLETE = 0x00010000, // Quests with this flag player submit automatically by special button in player gui
QUEST_FLAGS_DISPLAY_ITEM_IN_TRACKER = 0x00020000, // Displays usable item in quest tracker
QUEST_FLAGS_OBJ_TEXT = 0x00040000, // use Objective text as Complete text
QUEST_FLAGS_AUTO_ACCEPT = 0x00080000, // The client recognizes this flag as auto-accept. However, NONE of the current quests (3.3.5a) have this flag. Maybe blizz used to use it, or will use it in the future.
- QUEST_FLAGS_AUTO_SUBMIT = 0x00100000, // Quests with this flag player submit automatically by special button in player gui
+ QUEST_FLAGS_UNK1 = 0x00100000, //
QUEST_FLAGS_AUTO_TAKE = 0x00200000, // Automatically suggestion of accepting quest. Not from npc.
//QUEST_FLAGS_UNK2 = 0x00400000,
//QUEST_FLAGS_UNK3 = 0x00800000, // Found in quest 14069
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index e40470c5cdb..201235b4a40 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -126,7 +126,8 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
isRecruiter(isARecruiter),
_RBACData(NULL),
expireTime(60000), // 1 min after socket loss, session is deleted
- forceExit(false)
+ forceExit(false),
+ m_currentBankerGUID(0)
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
@@ -1199,11 +1200,11 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co
if (++packetCounter.amountCounter > maxPacketCounterAllowed)
{
dosTriggered = true;
- TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Character: %s, flooding packet (opc: %s (0x%X), count: %u)",
- Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetPlayerName().c_str(),
+ TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)",
+ Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(),
opcodeTable[p.GetOpcode()]->Name, p.GetOpcode(), packetCounter.amountCounter);
}
-
+
// Then check if player is sending packets not allowed
if (!IsOpcodeAllowed(p.GetOpcode()))
{
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 9e6f52ac8dd..3eb9f5cb3c5 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -1032,6 +1032,8 @@ class WorldSession
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);
+ bool CanUseBank(uint64 bankerGUID = 0) const;
+
// logging helper
void LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char *reason);
void LogUnprocessedTail(WorldPacket* packet);
@@ -1083,6 +1085,7 @@ class WorldSession
rbac::RBACData* _RBACData;
uint32 expireTime;
bool forceExit;
+ uint64 m_currentBankerGUID;
WorldSession(WorldSession const& right) = delete;
WorldSession& operator=(WorldSession const& right) = delete;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 94295878c4f..c767d4da9ed 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1756,9 +1756,6 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
if (aurApp->GetRemoveMode())
return;
- if (modelid > 0)
- target->SetDisplayId(modelid);
-
if (PowerType != POWER_MANA)
{
int32 oldPower = target->GetPower(PowerType);
@@ -1788,6 +1785,12 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
return;
target->SetShapeshiftForm(form);
+ if (modelid > 0)
+ {
+ SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm());
+ if (!transformSpellInfo || !GetSpellInfo()->IsPositive())
+ target->SetDisplayId(modelid);
+ }
}
else
{
@@ -1907,9 +1910,11 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
if (apply)
{
- // update active transform spell only when transform or shapeshift not set or not overwriting negative by positive case
- if (!target->GetModelForForm(target->GetShapeshiftForm()) || !GetSpellInfo()->IsPositive())
+ // update active transform spell only when transform not set or not overwriting negative by positive case
+ SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm());
+ if (!transformSpellInfo || !GetSpellInfo()->IsPositive() || transformSpellInfo->IsPositive())
{
+ target->setTransForm(GetId());
// special case (spell specific functionality)
if (GetMiscValue() == 0)
{
@@ -2078,11 +2083,6 @@ void AuraEffect::HandleAuraTransform(AuraApplication const* aurApp, uint8 mode,
}
}
- // update active transform spell only when transform or shapeshift not set or not overwriting negative by positive case
- SpellInfo const* transformSpellInfo = sSpellMgr->GetSpellInfo(target->getTransForm());
- if (!transformSpellInfo || !GetSpellInfo()->IsPositive() || transformSpellInfo->IsPositive())
- target->setTransForm(GetId());
-
// polymorph case
if ((mode & AURA_EFFECT_HANDLE_REAL) && target->GetTypeId() == TYPEID_PLAYER && target->IsPolymorphed())
{
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 218f7b5a37d..277d2b701c4 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -787,14 +787,14 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell
bool hasFamilyMask = false;
- /**
-
+ /**
+
* @brief Check auras procced by periodics
*Only damaging Dots can proc auras with PROC_FLAG_TAKEN_DAMAGE
*Only Dots can proc if ONLY has PROC_FLAG_DONE_PERIODIC or PROC_FLAG_TAKEN_PERIODIC.
-
+
*Hots can proc if ONLY has PROC_FLAG_DONE_PERIODIC and spellfamily != 0
*Only Dots can proc auras with PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG or PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG
@@ -809,7 +809,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell
* @param procFlags proc_flags of spellProc
* @param procExtra proc_EX of procSpell
* @param EventProcFlag proc_flags of aura to be procced
- * @param spellProto SpellInfo of aura to be procced
+ * @param spellProto SpellInfo of aura to be procced
*/
@@ -818,7 +818,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell
return true;
if (procFlags & PROC_FLAG_DONE_PERIODIC && EventProcFlag & PROC_FLAG_DONE_PERIODIC)
- {
+ {
if (procExtra & PROC_EX_INTERNAL_HOT)
{
if (EventProcFlag == PROC_FLAG_DONE_PERIODIC)
@@ -838,7 +838,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellInfo const* spellProto, Spell
}
if (procFlags & PROC_FLAG_TAKEN_PERIODIC && EventProcFlag & PROC_FLAG_TAKEN_PERIODIC)
- {
+ {
if (procExtra & PROC_EX_INTERNAL_HOT)
{
/// No aura that only has PROC_FLAG_TAKEN_PERIODIC can proc from a HOT.
@@ -3395,6 +3395,9 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd
spellInfo->Effects[EFFECT_1].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_60_YARDS); // 60yd
break;
+ case 72830: // Achievement Check
+ spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_50000_YARDS); // 50000yd
+ break;
case 72900: // Start Halls of Reflection Quest AE
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_200_YARDS); // 200yd
break;
diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp
index 35f5cb82036..3fbbd34777b 100644
--- a/src/server/game/Texts/CreatureTextMgr.cpp
+++ b/src/server/game/Texts/CreatureTextMgr.cpp
@@ -24,6 +24,7 @@
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CreatureTextMgr.h"
+#include "Group.h"
class CreatureTextBuilder
{
@@ -347,6 +348,18 @@ void CreatureTextMgr::SendNonChatPacket(WorldObject* source, WorldPacket* data,
}
break;
}
+ case CHAT_MSG_MONSTER_PARTY:
+ if (!whisperTarget)
+ return;
+
+ if (Player const* player = whisperTarget->ToPlayer())
+ {
+ if (Group* group = const_cast<Group*>(player->GetGroup()))
+ for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
+ if (Player* member = itr->GetSource())
+ member->GetSession()->SendPacket(data);
+ }
+ return;
default:
break;
}
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp
index 4ac039e9138..3e4097daf20 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_ambassador_flamelash.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -24,64 +23,74 @@ enum Spells
SPELL_FIREBLAST = 15573
};
-class boss_ambassador_flamelash : public CreatureScript
+enum Events
{
-public:
- boss_ambassador_flamelash() : CreatureScript("boss_ambassador_flamelash") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_ambassador_flamelashAI(creature);
- }
-
- struct boss_ambassador_flamelashAI : public ScriptedAI
- {
- boss_ambassador_flamelashAI(Creature* creature) : ScriptedAI(creature) { }
+ EVENT_FIREBLAST = 1,
+ EVENT_SUMMON_SPIRITS = 2
+};
- uint32 FireBlast_Timer;
- uint32 Spirit_Timer;
+class boss_ambassador_flamelash : public CreatureScript
+{
+ public:
+ boss_ambassador_flamelash() : CreatureScript("boss_ambassador_flamelash") { }
- void Reset() override
+ struct boss_ambassador_flamelashAI : public ScriptedAI
{
- FireBlast_Timer = 2000;
- Spirit_Timer = 24000;
- }
+ boss_ambassador_flamelashAI(Creature* creature) : ScriptedAI(creature) { }
- void EnterCombat(Unit* /*who*/) override { }
-
- void SummonSpirits(Unit* victim)
- {
- if (Creature* Spirit = DoSpawnCreature(9178, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000))
- Spirit->AI()->AttackStart(victim);
- }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_FIREBLAST, 2000);
+ _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 24000);
+ }
- //FireBlast_Timer
- if (FireBlast_Timer <= diff)
+ void SummonSpirit(Unit* victim)
{
- DoCastVictim(SPELL_FIREBLAST);
- FireBlast_Timer = 7000;
- } else FireBlast_Timer -= diff;
+ if (Creature* spirit = DoSpawnCreature(9178, frand(-9, 9), frand(-9, 9), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000))
+ spirit->AI()->AttackStart(victim);
+ }
- //Spirit_Timer
- if (Spirit_Timer <= diff)
+ void UpdateAI(uint32 diff) override
{
- SummonSpirits(me->GetVictim());
- SummonSpirits(me->GetVictim());
- SummonSpirits(me->GetVictim());
- SummonSpirits(me->GetVictim());
+ if (!UpdateVictim())
+ return;
- Spirit_Timer = 30000;
- } else Spirit_Timer -= diff;
+ _events.Update(diff);
- DoMeleeAttackIfReady();
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FIREBLAST:
+ DoCastVictim(SPELL_FIREBLAST);
+ _events.ScheduleEvent(EVENT_FIREBLAST, 7000);
+ break;
+ case EVENT_SUMMON_SPIRITS:
+ for (uint32 i = 0; i < 4; ++i)
+ SummonSpirit(me->GetVictim());
+ _events.ScheduleEvent(EVENT_SUMMON_SPIRITS, 30000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_ambassador_flamelashAI(creature);
}
- };
};
void AddSC_boss_ambassador_flamelash()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp
index fd8b77ea8d4..894b528c03c 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_anubshiah.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -21,90 +20,94 @@
enum Spells
{
- SPELL_SHADOWBOLT = 17228,
- SPELL_CURSEOFTONGUES = 15470,
- SPELL_CURSEOFWEAKNESS = 17227,
- SPELL_DEMONARMOR = 11735,
- SPELL_ENVELOPINGWEB = 15471
+ SPELL_SHADOWBOLT = 17228,
+ SPELL_CURSEOFTONGUES = 15470,
+ SPELL_CURSEOFWEAKNESS = 17227,
+ SPELL_DEMONARMOR = 11735,
+ SPELL_ENVELOPINGWEB = 15471
};
-class boss_anubshiah : public CreatureScript
+enum Events
{
-public:
- boss_anubshiah() : CreatureScript("boss_anubshiah") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_anubshiahAI(creature);
- }
-
- struct boss_anubshiahAI : public ScriptedAI
- {
- boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 ShadowBolt_Timer;
- uint32 CurseOfTongues_Timer;
- uint32 CurseOfWeakness_Timer;
- uint32 DemonArmor_Timer;
- uint32 EnvelopingWeb_Timer;
-
- void Reset() override
- {
- ShadowBolt_Timer = 7000;
- CurseOfTongues_Timer = 24000;
- CurseOfWeakness_Timer = 12000;
- DemonArmor_Timer = 3000;
- EnvelopingWeb_Timer = 16000;
- }
+ EVENT_SHADOWBOLT = 1,
+ EVENT_CURSE_OF_TONGUES = 2,
+ EVENT_CURSE_OF_WEAKNESS = 3,
+ EVENT_DEMON_ARMOR = 4,
+ EVENT_ENVELOPING_WEB = 5
+};
- void EnterCombat(Unit* /*who*/) override { }
+class boss_anubshiah : public CreatureScript
+{
+ public:
+ boss_anubshiah() : CreatureScript("boss_anubshiah") { }
- void UpdateAI(uint32 diff) override
+ struct boss_anubshiahAI : public ScriptedAI
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- //ShadowBolt_Timer
- if (ShadowBolt_Timer <= diff)
- {
- DoCastVictim(SPELL_SHADOWBOLT);
- ShadowBolt_Timer = 7000;
- } else ShadowBolt_Timer -= diff;
-
- //CurseOfTongues_Timer
- if (CurseOfTongues_Timer <= diff)
- {
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_CURSEOFTONGUES);
- CurseOfTongues_Timer = 18000;
- } else CurseOfTongues_Timer -= diff;
+ boss_anubshiahAI(Creature* creature) : ScriptedAI(creature) { }
- //CurseOfWeakness_Timer
- if (CurseOfWeakness_Timer <= diff)
+ void Reset() override
{
- DoCastVictim(SPELL_CURSEOFWEAKNESS);
- CurseOfWeakness_Timer = 45000;
- } else CurseOfWeakness_Timer -= diff;
+ _events.Reset();
+ }
- //DemonArmor_Timer
- if (DemonArmor_Timer <= diff)
+ void EnterCombat(Unit* /*who*/) override
{
- DoCast(me, SPELL_DEMONARMOR);
- DemonArmor_Timer = 300000;
- } else DemonArmor_Timer -= diff;
-
- //EnvelopingWeb_Timer
- if (EnvelopingWeb_Timer <= diff)
+ _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000);
+ _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 24000);
+ _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 12000);
+ _events.ScheduleEvent(EVENT_DEMON_ARMOR, 3000);
+ _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 16000);
+ }
+
+ void UpdateAI(uint32 diff) override
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_ENVELOPINGWEB);
- EnvelopingWeb_Timer = 12000;
- } else EnvelopingWeb_Timer -= diff;
-
- DoMeleeAttackIfReady();
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOWBOLT:
+ DoCast(me, SPELL_SHADOWBOLT);
+ _events.ScheduleEvent(EVENT_SHADOWBOLT, 7000);
+ break;
+ case EVENT_CURSE_OF_TONGUES:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_CURSEOFTONGUES);
+ _events.ScheduleEvent(EVENT_CURSE_OF_TONGUES, 18000);
+ break;
+ case EVENT_CURSE_OF_WEAKNESS:
+ DoCastVictim(SPELL_CURSEOFWEAKNESS);
+ _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 45000);
+ break;
+ case EVENT_DEMON_ARMOR:
+ DoCast(me, SPELL_DEMONARMOR);
+ _events.ScheduleEvent(EVENT_DEMON_ARMOR, 300000);
+ break;
+ case EVENT_ENVELOPING_WEB:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
+ DoCast(target, SPELL_ENVELOPINGWEB);
+ _events.ScheduleEvent(EVENT_ENVELOPING_WEB, 12000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_anubshiahAI(creature);
}
- };
};
void AddSC_boss_anubshiah()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp
index fffdf9c7514..cec29bcd4d1 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -32,89 +31,89 @@ enum Spells
SPELL_AVATAROFFLAME = 15636
};
-class boss_emperor_dagran_thaurissan : public CreatureScript
+enum Events
{
-public:
- boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_draganthaurissanAI>(creature);
- }
-
- struct boss_draganthaurissanAI : public ScriptedAI
- {
- boss_draganthaurissanAI(Creature* creature) : ScriptedAI(creature)
- {
- instance = me->GetInstanceScript();
- }
-
- InstanceScript* instance;
- uint32 HandOfThaurissan_Timer;
- uint32 AvatarOfFlame_Timer;
- //uint32 Counter;
+ EVENT_HANDOFTHAURISSAN = 1,
+ EVENT_AVATAROFFLAME = 2
+};
- void Reset() override
- {
- HandOfThaurissan_Timer = 4000;
- AvatarOfFlame_Timer = 25000;
- //Counter= 0;
- }
+class boss_emperor_dagran_thaurissan : public CreatureScript
+{
+ public:
+ boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") { }
- void EnterCombat(Unit* /*who*/) override
+ struct boss_draganthaurissanAI : public ScriptedAI
{
- Talk(SAY_AGGRO);
- me->CallForHelp(VISIBLE_RANGE);
- }
+ boss_draganthaurissanAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ }
- void KilledUnit(Unit* /*victim*/) override
- {
- Talk(SAY_SLAY);
- }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void JustDied(Unit* /*killer*/) override
- {
- if (Creature* Moira = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MOIRA)))
+ void EnterCombat(Unit* /*who*/) override
{
- Moira->AI()->EnterEvadeMode();
- Moira->setFaction(35);
+ Talk(SAY_AGGRO);
+ me->CallForHelp(VISIBLE_RANGE);
+ _events.ScheduleEvent(EVENT_HANDOFTHAURISSAN, 4000);
+ _events.ScheduleEvent(EVENT_AVATAROFFLAME, 25000);
}
- }
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_SLAY);
+ }
- if (HandOfThaurissan_Timer <= diff)
+ void JustDied(Unit* /*killer*/) override
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
- DoCast(target, SPELL_HANDOFTHAURISSAN);
-
- //3 Hands of Thaurissan will be cast
- //if (Counter < 3)
- //{
- // HandOfThaurissan_Timer = 1000;
- // ++Counter;
- //}
- //else
- //{
- HandOfThaurissan_Timer = 5000;
- //Counter = 0;
- //}
- } else HandOfThaurissan_Timer -= diff;
-
- //AvatarOfFlame_Timer
- if (AvatarOfFlame_Timer <= diff)
+ if (Creature* moira = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_MOIRA)))
+ {
+ moira->AI()->EnterEvadeMode();
+ moira->setFaction(35);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
{
- DoCastVictim(SPELL_AVATAROFFLAME);
- AvatarOfFlame_Timer = 18000;
- } else AvatarOfFlame_Timer -= diff;
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_HANDOFTHAURISSAN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
+ DoCast(target, SPELL_HANDOFTHAURISSAN);
+ _events.ScheduleEvent(EVENT_HANDOFTHAURISSAN, 5000);
+ break;
+ case EVENT_AVATAROFFLAME:
+ DoCastVictim(SPELL_AVATAROFFLAME);
+ _events.ScheduleEvent(EVENT_AVATAROFFLAME, 18000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ };
- DoMeleeAttackIfReady();
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_draganthaurissanAI>(creature);
}
- };
};
void AddSC_boss_draganthaurissan()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp
index 34ce2276a54..d5b8d1deadd 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_general_angerforge.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -26,101 +25,113 @@ enum Spells
SPELL_CLEAVE = 20691
};
-class boss_general_angerforge : public CreatureScript
+enum Events
{
-public:
- boss_general_angerforge() : CreatureScript("boss_general_angerforge") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_general_angerforgeAI(creature);
- }
-
- struct boss_general_angerforgeAI : public ScriptedAI
- {
- boss_general_angerforgeAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 MightyBlow_Timer;
- uint32 HamString_Timer;
- uint32 Cleave_Timer;
- uint32 Adds_Timer;
- bool Medics;
-
- void Reset() override
- {
- MightyBlow_Timer = 8000;
- HamString_Timer = 12000;
- Cleave_Timer = 16000;
- Adds_Timer = 0;
- Medics = false;
- }
-
- void EnterCombat(Unit* /*who*/) override { }
+ EVENT_MIGHTYBLOW = 1,
+ EVENT_HAMSTRING = 2,
+ EVENT_CLEAVE = 3,
+ EVENT_MEDIC = 4,
+ EVENT_ADDS = 5
+};
- void SummonAdds(Unit* victim)
- {
- if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
- SummonedAdd->AI()->AttackStart(victim);
- }
+enum Phases
+{
+ PHASE_ONE = 1,
+ PHASE_TWO = 2
+};
- void SummonMedics(Unit* victim)
- {
- if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
- SummonedMedic->AI()->AttackStart(victim);
- }
+class boss_general_angerforge : public CreatureScript
+{
+ public:
+ boss_general_angerforge() : CreatureScript("boss_general_angerforge") { }
- void UpdateAI(uint32 diff) override
+ struct boss_general_angerforgeAI : public ScriptedAI
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ boss_general_angerforgeAI(Creature* creature) : ScriptedAI(creature) { }
- //MightyBlow_Timer
- if (MightyBlow_Timer <= diff)
+ void Reset() override
{
- DoCastVictim(SPELL_MIGHTYBLOW);
- MightyBlow_Timer = 18000;
- } else MightyBlow_Timer -= diff;
+ _events.Reset();
+ }
- //HamString_Timer
- if (HamString_Timer <= diff)
+ void EnterCombat(Unit* /*who*/) override
{
- DoCastVictim(SPELL_HAMSTRING);
- HamString_Timer = 15000;
- } else HamString_Timer -= diff;
+ _events.SetPhase(PHASE_ONE);
+ _events.ScheduleEvent(EVENT_MIGHTYBLOW, 8000);
+ _events.ScheduleEvent(EVENT_HAMSTRING, 12000);
+ _events.ScheduleEvent(EVENT_CLEAVE, 16000);
+ }
- //Cleave_Timer
- if (Cleave_Timer <= diff)
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- DoCastVictim(SPELL_CLEAVE);
- Cleave_Timer = 9000;
- } else Cleave_Timer -= diff;
+ if (me->HealthBelowPctDamaged(20, damage) && _events.IsInPhase(PHASE_ONE))
+ {
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_MEDIC, 0, 0, PHASE_TWO);
+ _events.ScheduleEvent(EVENT_ADDS, 0, 0, PHASE_TWO);
+ }
+ }
- //Adds_Timer
- if (HealthBelowPct(21))
+ void SummonAdd(Unit* victim)
{
- if (Adds_Timer <= diff)
- {
- // summon 3 Adds every 25s
- SummonAdds(me->GetVictim());
- SummonAdds(me->GetVictim());
- SummonAdds(me->GetVictim());
+ if (Creature* SummonedAdd = DoSpawnCreature(8901, float(irand(-14, 14)), float(irand(-14, 14)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
+ SummonedAdd->AI()->AttackStart(victim);
+ }
- Adds_Timer = 25000;
- } else Adds_Timer -= diff;
+ void SummonMedic(Unit* victim)
+ {
+ if (Creature* SummonedMedic = DoSpawnCreature(8894, float(irand(-9, 9)), float(irand(-9, 9)), 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000))
+ SummonedMedic->AI()->AttackStart(victim);
}
- //Summon Medics
- if (!Medics && HealthBelowPct(21))
+ void UpdateAI(uint32 diff) override
{
- SummonMedics(me->GetVictim());
- SummonMedics(me->GetVictim());
- Medics = true;
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MIGHTYBLOW:
+ DoCastVictim(SPELL_MIGHTYBLOW);
+ _events.ScheduleEvent(EVENT_MIGHTYBLOW, 18000);
+ break;
+ case EVENT_HAMSTRING:
+ DoCastVictim(SPELL_HAMSTRING);
+ _events.ScheduleEvent(EVENT_HAMSTRING, 15000);
+ break;
+ case EVENT_CLEAVE:
+ DoCastVictim(SPELL_CLEAVE);
+ _events.ScheduleEvent(EVENT_CLEAVE, 9000);
+ break;
+ case EVENT_MEDIC:
+ for (uint8 i = 0; i < 2; ++i)
+ SummonMedic(me->GetVictim());
+ break;
+ case EVENT_ADDS:
+ for (uint8 i = 0; i < 3; ++i)
+ SummonAdd(me->GetVictim());
+ _events.ScheduleEvent(EVENT_ADDS, 25000, 0, PHASE_TWO);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_general_angerforgeAI(creature);
}
- };
};
void AddSC_boss_general_angerforge()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp
index b5998576f24..e9034e17d83 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_gorosh_the_dervish.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -25,56 +24,67 @@ enum Spells
SPELL_MORTALSTRIKE = 24573
};
+enum Events
+{
+ EVENT_WHIRLWIND = 1,
+ EVENT_MORTALSTRIKE = 2
+};
+
class boss_gorosh_the_dervish : public CreatureScript
{
-public:
- boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { }
+ public:
+ boss_gorosh_the_dervish() : CreatureScript("boss_gorosh_the_dervish") { }
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_gorosh_the_dervishAI(creature);
- }
+ struct boss_gorosh_the_dervishAI : public ScriptedAI
+ {
+ boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { }
- struct boss_gorosh_the_dervishAI : public ScriptedAI
- {
- boss_gorosh_the_dervishAI(Creature* creature) : ScriptedAI(creature) { }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- uint32 WhirlWind_Timer;
- uint32 MortalStrike_Timer;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_WHIRLWIND, 12000);
+ _events.ScheduleEvent(EVENT_MORTALSTRIKE, 22000);
+ }
- void Reset() override
- {
- WhirlWind_Timer = 12000;
- MortalStrike_Timer = 22000;
- }
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
- void EnterCombat(Unit* /*who*/) override
- {
- }
+ _events.Update(diff);
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_WHIRLWIND:
+ DoCast(me, SPELL_WHIRLWIND);
+ _events.ScheduleEvent(EVENT_WHIRLWIND, 15000);
+ break;
+ case EVENT_MORTALSTRIKE:
+ DoCastVictim(SPELL_MORTALSTRIKE);
+ _events.ScheduleEvent(EVENT_MORTALSTRIKE, 15000);
+ break;
+ default:
+ break;
+ }
+ }
- //WhirlWind_Timer
- if (WhirlWind_Timer <= diff)
- {
- DoCast(me, SPELL_WHIRLWIND);
- WhirlWind_Timer = 15000;
- } else WhirlWind_Timer -= diff;
+ DoMeleeAttackIfReady();
+ }
- //MortalStrike_Timer
- if (MortalStrike_Timer <= diff)
- {
- DoCastVictim(SPELL_MORTALSTRIKE);
- MortalStrike_Timer = 15000;
- } else MortalStrike_Timer -= diff;
+ private:
+ EventMap _events;
+ };
- DoMeleeAttackIfReady();
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_gorosh_the_dervishAI(creature);
}
- };
};
void AddSC_boss_gorosh_the_dervish()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp
index c4277c2447e..f53fd0f65b3 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_grizzle.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -26,59 +25,83 @@ enum Grizzle
EMOTE_FRENZY_KILL = 0
};
-class boss_grizzle : public CreatureScript
+enum Events
{
-public:
- boss_grizzle() : CreatureScript("boss_grizzle") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_grizzleAI(creature);
- }
+ EVENT_GROUNDTREMOR = 1,
+ EVENT_FRENZY = 2
+};
- struct boss_grizzleAI : public ScriptedAI
- {
- boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { }
+enum Phases
+{
+ PHASE_ONE = 1,
+ PHASE_TWO = 2
+};
- uint32 GroundTremor_Timer;
- uint32 Frenzy_Timer;
+class boss_grizzle : public CreatureScript
+{
+ public:
+ boss_grizzle() : CreatureScript("boss_grizzle") { }
- void Reset() override
+ struct boss_grizzleAI : public ScriptedAI
{
- GroundTremor_Timer = 12000;
- Frenzy_Timer =0;
- }
+ boss_grizzleAI(Creature* creature) : ScriptedAI(creature) { }
- void EnterCombat(Unit* /*who*/) override { }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.SetPhase(PHASE_ONE);
+ _events.ScheduleEvent(EVENT_GROUNDTREMOR, 12000);
+ }
- //GroundTremor_Timer
- if (GroundTremor_Timer <= diff)
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- DoCastVictim(SPELL_GROUNDTREMOR);
- GroundTremor_Timer = 8000;
- } else GroundTremor_Timer -= diff;
+ if (me->HealthBelowPctDamaged(50, damage) && _events.IsInPhase(PHASE_ONE))
+ {
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_FRENZY, 0, 0, PHASE_TWO);
+ }
+ }
- //Frenzy_Timer
- if (HealthBelowPct(51))
+ void UpdateAI(uint32 diff) override
{
- if (Frenzy_Timer <= diff)
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- DoCast(me, SPELL_FRENZY);
- Talk(EMOTE_FRENZY_KILL);
+ switch (eventId)
+ {
+ case EVENT_GROUNDTREMOR:
+ DoCastVictim(SPELL_GROUNDTREMOR);
+ _events.ScheduleEvent(EVENT_GROUNDTREMOR, 8000);
+ break;
+ case EVENT_FRENZY:
+ DoCast(me, SPELL_FRENZY);
+ Talk(EMOTE_FRENZY_KILL);
+ _events.ScheduleEvent(EVENT_FRENZY, 15000, 0, PHASE_TWO);
+ break;
+ default:
+ break;
+ }
+ }
- Frenzy_Timer = 15000;
- } else Frenzy_Timer -= diff;
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_grizzleAI(creature);
}
- };
};
void AddSC_boss_grizzle()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp
index 6aa89aa491d..c41ddf9d98b 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_high_interrogator_gerstahn.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -27,74 +26,81 @@ enum Spells
SPELL_SHADOWSHIELD = 22417
};
-class boss_high_interrogator_gerstahn : public CreatureScript
+enum Events
{
-public:
- boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_high_interrogator_gerstahnAI(creature);
- }
-
- struct boss_high_interrogator_gerstahnAI : public ScriptedAI
- {
- boss_high_interrogator_gerstahnAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 ShadowWordPain_Timer;
- uint32 ManaBurn_Timer;
- uint32 PsychicScream_Timer;
- uint32 ShadowShield_Timer;
-
- void Reset() override
- {
- ShadowWordPain_Timer = 4000;
- ManaBurn_Timer = 14000;
- PsychicScream_Timer = 32000;
- ShadowShield_Timer = 8000;
- }
+ EVENT_SHADOW_WORD_PAIN = 1,
+ EVENT_MANABURN = 2,
+ EVENT_PSYCHIC_SCREAM = 3,
+ EVENT_SHADOWSHIELD = 4
+};
- void EnterCombat(Unit* /*who*/) override { }
+class boss_high_interrogator_gerstahn : public CreatureScript
+{
+ public:
+ boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") { }
- void UpdateAI(uint32 diff) override
+ struct boss_high_interrogator_gerstahnAI : public ScriptedAI
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ boss_high_interrogator_gerstahnAI(Creature* creature) : ScriptedAI(creature) { }
- //ShadowWordPain_Timer
- if (ShadowWordPain_Timer <= diff)
+ void Reset() override
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_SHADOWWORDPAIN);
- ShadowWordPain_Timer = 7000;
- } else ShadowWordPain_Timer -= diff;
+ _events.Reset();
+ }
- //ManaBurn_Timer
- if (ManaBurn_Timer <= diff)
+ void EnterCombat(Unit* /*who*/) override
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_MANABURN);
- ManaBurn_Timer = 10000;
- } else ManaBurn_Timer -= diff;
+ _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 4000);
+ _events.ScheduleEvent(EVENT_MANABURN, 14000);
+ _events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, 32000);
+ _events.ScheduleEvent(EVENT_SHADOWSHIELD, 8000);
+ }
- //PsychicScream_Timer
- if (PsychicScream_Timer <= diff)
+ void UpdateAI(uint32 diff) override
{
- DoCastVictim(SPELL_PSYCHICSCREAM);
- PsychicScream_Timer = 30000;
- } else PsychicScream_Timer -= diff;
+ if (!UpdateVictim())
+ return;
- //ShadowShield_Timer
- if (ShadowShield_Timer <= diff)
- {
- DoCast(me, SPELL_SHADOWSHIELD);
- ShadowShield_Timer = 25000;
- } else ShadowShield_Timer -= diff;
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOW_WORD_PAIN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_SHADOWWORDPAIN);
+ _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 7000);
+ break;
+ case EVENT_PSYCHIC_SCREAM:
+ DoCastVictim(SPELL_PSYCHICSCREAM);
+ _events.ScheduleEvent(EVENT_PSYCHIC_SCREAM, 30000);
+ break;
+ case EVENT_MANABURN:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_MANABURN);
+ _events.ScheduleEvent(EVENT_MANABURN, 10000);
+ break;
+ case EVENT_SHADOWSHIELD:
+ DoCast(me, SPELL_SHADOWSHIELD);
+ _events.ScheduleEvent(EVENT_SHADOWSHIELD, 25000);
+ break;
+ default:
+ break;
+ }
+ }
- DoMeleeAttackIfReady();
+ DoMeleeAttackIfReady();
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_high_interrogator_gerstahnAI(creature);
}
- };
};
void AddSC_boss_high_interrogator_gerstahn()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp
index 4cf968ad3b7..e6bbbaa73a9 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_magmus.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,75 +17,96 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "blackrock_depths.h"
enum Spells
{
- SPELL_FIERYBURST = 13900,
- SPELL_WARSTOMP = 24375
+ SPELL_FIERYBURST = 13900,
+ SPELL_WARSTOMP = 24375
};
-enum Misc
+enum Events
{
- DATA_THRONE_DOOR = 24 // not id or guid of doors but number of enum in blackrock_depths.h
+ EVENT_FIERY_BURST = 1,
+ EVENT_WARSTOMP = 2
};
-class boss_magmus : public CreatureScript
+enum Phases
{
-public:
- boss_magmus() : CreatureScript("boss_magmus") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_magmusAI(creature);
- }
-
- struct boss_magmusAI : public ScriptedAI
- {
- boss_magmusAI(Creature* creature) : ScriptedAI(creature) { }
+ PHASE_ONE = 1,
+ PHASE_TWO = 2
+};
- uint32 FieryBurst_Timer;
- uint32 WarStomp_Timer;
+class boss_magmus : public CreatureScript
+{
+ public:
+ boss_magmus() : CreatureScript("boss_magmus") { }
- void Reset() override
+ struct boss_magmusAI : public ScriptedAI
{
- FieryBurst_Timer = 5000;
- WarStomp_Timer =0;
- }
+ boss_magmusAI(Creature* creature) : ScriptedAI(creature) { }
- void EnterCombat(Unit* /*who*/) override { }
+ void Reset() override
+ {
+ _events.Reset();
+ }
- void UpdateAI(uint32 diff) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.SetPhase(PHASE_ONE);
+ _events.ScheduleEvent(EVENT_FIERY_BURST, 5000);
+ }
- //FieryBurst_Timer
- if (FieryBurst_Timer <= diff)
+ void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
- DoCastVictim(SPELL_FIERYBURST);
- FieryBurst_Timer = 6000;
- } else FieryBurst_Timer -= diff;
+ if (me->HealthBelowPctDamaged(50, damage) && _events.IsInPhase(PHASE_ONE))
+ {
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_WARSTOMP, 0, 0, PHASE_TWO);
+ }
+ }
- //WarStomp_Timer
- if (HealthBelowPct(51))
+ void UpdateAI(uint32 diff) override
{
- if (WarStomp_Timer <= diff)
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
{
- DoCastVictim(SPELL_WARSTOMP);
- WarStomp_Timer = 8000;
- } else WarStomp_Timer -= diff;
+ switch (eventId)
+ {
+ case EVENT_FIERY_BURST:
+ DoCastVictim(SPELL_FIERYBURST);
+ _events.ScheduleEvent(EVENT_FIERY_BURST, 6000);
+ break;
+ case EVENT_WARSTOMP:
+ DoCastVictim(SPELL_WARSTOMP);
+ _events.ScheduleEvent(EVENT_WARSTOMP, 8000, 0, PHASE_TWO);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
- }
- // When he die open door to last chamber
- void JustDied(Unit* killer) override
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (InstanceScript* instance = me->GetInstanceScript())
+ instance->HandleGameObject(instance->GetData64(DATA_THRONE_DOOR), true);
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
{
- if (InstanceScript* instance = killer->GetInstanceScript())
- instance->HandleGameObject(instance->GetData64(DATA_THRONE_DOOR), true);
+ return new boss_magmusAI(creature);
}
- };
};
void AddSC_boss_magmus()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp
index 98f5f75ae3f..8342bef682b 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_moira_bronzebeard.cpp
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -29,63 +28,73 @@ enum Spells
SPELL_SMITE = 10934
};
-class boss_moira_bronzebeard : public CreatureScript
+enum Events
{
-public:
- boss_moira_bronzebeard() : CreatureScript("boss_moira_bronzebeard") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_moira_bronzebeardAI(creature);
- }
-
- struct boss_moira_bronzebeardAI : public ScriptedAI
- {
- boss_moira_bronzebeardAI(Creature* creature) : ScriptedAI(creature) { }
-
- uint32 Heal_Timer;
- uint32 MindBlast_Timer;
- uint32 ShadowWordPain_Timer;
- uint32 Smite_Timer;
-
- void Reset() override
- {
- Heal_Timer = 12000; //These times are probably wrong
- MindBlast_Timer = 16000;
- ShadowWordPain_Timer = 2000;
- Smite_Timer = 8000;
- }
+ EVENT_MINDBLAST = 1,
+ EVENT_SHADOW_WORD_PAIN = 2,
+ EVENT_SMITE = 3,
+ EVENT_HEAL = 4 // not used atm
+};
- void EnterCombat(Unit* /*who*/) override { }
+class boss_moira_bronzebeard : public CreatureScript
+{
+ public:
+ boss_moira_bronzebeard() : CreatureScript("boss_moira_bronzebeard") { }
- void UpdateAI(uint32 diff) override
+ struct boss_moira_bronzebeardAI : public ScriptedAI
{
- //Return since we have no target
- if (!UpdateVictim())
- return;
+ boss_moira_bronzebeardAI(Creature* creature) : ScriptedAI(creature) { }
- //MindBlast_Timer
- if (MindBlast_Timer <= diff)
+ void Reset() override
{
- DoCastVictim(SPELL_MINDBLAST);
- MindBlast_Timer = 14000;
- } else MindBlast_Timer -= diff;
+ _events.Reset();
+ }
- //ShadowWordPain_Timer
- if (ShadowWordPain_Timer <= diff)
+ void EnterCombat(Unit* /*who*/) override
{
- DoCastVictim(SPELL_SHADOWWORDPAIN);
- ShadowWordPain_Timer = 18000;
- } else ShadowWordPain_Timer -= diff;
+ //_events.ScheduleEvent(EVENT_HEAL, 12000); // not used atm // These times are probably wrong
+ _events.ScheduleEvent(EVENT_MINDBLAST, 16000);
+ _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 2000);
+ _events.ScheduleEvent(EVENT_SMITE, 8000);
+ }
- //Smite_Timer
- if (Smite_Timer <= diff)
+ void UpdateAI(uint32 diff) override
{
- DoCastVictim(SPELL_SMITE);
- Smite_Timer = 10000;
- } else Smite_Timer -= diff;
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_MINDBLAST:
+ DoCastVictim(SPELL_MINDBLAST);
+ _events.ScheduleEvent(EVENT_MINDBLAST, 14000);
+ break;
+ case EVENT_SHADOW_WORD_PAIN:
+ DoCastVictim(SPELL_SHADOWWORDPAIN);
+ _events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 18000);
+ break;
+ case EVENT_SMITE:
+ DoCastVictim(SPELL_SMITE);
+ _events.ScheduleEvent(EVENT_SMITE, 10000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new boss_moira_bronzebeardAI(creature);
}
- };
};
void AddSC_boss_moira_bronzebeard()
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp
index cbcafa32a89..83464c12230 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp
@@ -24,18 +24,24 @@
enum Spells
{
- SPELL_SMELT_DARK_IRON = 14891,
- SPELL_LEARN_SMELT = 14894,
+ SPELL_SMELT_DARK_IRON = 14891,
+ SPELL_LEARN_SMELT = 14894,
};
enum Quests
{
- QUEST_SPECTRAL_CHALICE = 4083
+ QUEST_SPECTRAL_CHALICE = 4083
};
enum Misc
{
- DATA_SKILLPOINT_MIN = 230
+ DATA_SKILLPOINT_MIN = 230
+};
+
+enum Phases
+{
+ PHASE_ONE = 1,
+ PHASE_TWO = 2
};
#define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron"
@@ -99,149 +105,151 @@ enum DoomrelSpells
SPELL_SUMMON_VOIDWALKERS = 15092
};
+enum DoomrelEvents
+{
+ EVENT_SHADOW_BOLT_VOLLEY = 1,
+ EVENT_IMMOLATE = 2,
+ EVENT_CURSE_OF_WEAKNESS = 3,
+ EVENT_DEMONARMOR = 4,
+ EVENT_SUMMON_VOIDWALKERS = 5
+};
+
#define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!"
#define GOSSIP_SELECT_DOOMREL "[PH] Continue..."
class boss_doomrel : public CreatureScript
{
-public:
- boss_doomrel() : CreatureScript("boss_doomrel") { }
+ public:
+ boss_doomrel() : CreatureScript("boss_doomrel") { }
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- switch (action)
+ bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
- case GOSSIP_ACTION_INFO_DEF+1:
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
- player->SEND_GOSSIP_MENU(2605, creature->GetGUID());
- break;
- case GOSSIP_ACTION_INFO_DEF+2:
- player->CLOSE_GOSSIP_MENU();
- //start event here
- creature->setFaction(FACTION_HOSTILE);
- creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- creature->AI()->AttackStart(player);
- InstanceScript* instance = creature->GetInstanceScript();
- if (instance)
- instance->SetData64(DATA_EVENSTARTER, player->GetGUID());
- break;
+ player->PlayerTalkClass->ClearMenus();
+ switch (action)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELECT_DOOMREL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ player->SEND_GOSSIP_MENU(2605, creature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ player->CLOSE_GOSSIP_MENU();
+ //start event here
+ creature->setFaction(FACTION_HOSTILE);
+ creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ creature->AI()->AttackStart(player);
+ InstanceScript* instance = creature->GetInstanceScript();
+ if (instance)
+ instance->SetData64(DATA_EVENSTARTER, player->GetGUID());
+ break;
+ }
+ return true;
}
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
- player->SEND_GOSSIP_MENU(2601, creature->GetGUID());
- return true;
- }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_doomrelAI>(creature);
- }
-
- struct boss_doomrelAI : public ScriptedAI
- {
- boss_doomrelAI(Creature* creature) : ScriptedAI(creature)
+ bool OnGossipHello(Player* player, Creature* creature) override
{
- instance = creature->GetInstanceScript();
- }
+ player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ player->SEND_GOSSIP_MENU(2601, creature->GetGUID());
- InstanceScript* instance;
- uint32 ShadowVolley_Timer;
- uint32 Immolate_Timer;
- uint32 CurseOfWeakness_Timer;
- uint32 DemonArmor_Timer;
- bool Voidwalkers;
+ return true;
+ }
- void Reset() override
+ struct boss_doomrelAI : public ScriptedAI
{
- ShadowVolley_Timer = 10000;
- Immolate_Timer = 18000;
- CurseOfWeakness_Timer = 5000;
- DemonArmor_Timer = 16000;
- Voidwalkers = false;
+ boss_doomrelAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = creature->GetInstanceScript();
+ }
- me->setFaction(FACTION_FRIEND);
+ void Reset() override
+ {
+ _voidwalkers = false;
- // was set before event start, so set again
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
+ me->setFaction(FACTION_FRIEND);
- if (instance->GetData(DATA_GHOSTKILL) >= 7)
- me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
- else
- me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
- }
+ // was set before event start, so set again
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
- void EnterCombat(Unit* /*who*/) override
- {
- }
-
- void EnterEvadeMode() override
- {
- me->RemoveAllAuras();
- me->DeleteThreatList();
- me->CombatStop(true);
- me->LoadCreaturesAddon();
- if (me->IsAlive())
- me->GetMotionMaster()->MoveTargetedHome();
- me->SetLootRecipient(NULL);
- instance->SetData64(DATA_EVENSTARTER, 0);
- }
-
- void JustDied(Unit* /*killer*/) override
- {
- instance->SetData(DATA_GHOSTKILL, 1);
- }
+ if (_instance->GetData(DATA_GHOSTKILL) >= 7)
+ me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ else
+ me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 10000);
+ _events.ScheduleEvent(EVENT_IMMOLATE, 18000);
+ _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 5000);
+ _events.ScheduleEvent(EVENT_DEMONARMOR, 16000);
+ }
- //ShadowVolley_Timer
- if (ShadowVolley_Timer <= diff)
+ void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
{
- DoCastVictim(SPELL_SHADOWBOLTVOLLEY);
- ShadowVolley_Timer = 12000;
- } else ShadowVolley_Timer -= diff;
+ if (!_voidwalkers && !HealthAbovePct(50))
+ {
+ DoCastVictim(SPELL_SUMMON_VOIDWALKERS, true);
+ _voidwalkers = true;
+ }
+ }
- //Immolate_Timer
- if (Immolate_Timer <= diff)
+ void EnterEvadeMode() override
{
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true))
- DoCast(target, SPELL_IMMOLATE);
+ ScriptedAI::EnterEvadeMode();
- Immolate_Timer = 25000;
- } else Immolate_Timer -= diff;
+ _instance->SetData64(DATA_EVENSTARTER, 0);
+ }
- //CurseOfWeakness_Timer
- if (CurseOfWeakness_Timer <= diff)
+ void JustDied(Unit* /*killer*/) override
{
- DoCastVictim(SPELL_CURSEOFWEAKNESS);
- CurseOfWeakness_Timer = 45000;
- } else CurseOfWeakness_Timer -= diff;
+ _instance->SetData(DATA_GHOSTKILL, 1);
+ }
- //DemonArmor_Timer
- if (DemonArmor_Timer <= diff)
+ void UpdateAI(uint32 diff) override
{
- DoCast(me, SPELL_DEMONARMOR);
- DemonArmor_Timer = 300000;
- } else DemonArmor_Timer -= diff;
+ if (!UpdateVictim())
+ return;
- //Summon Voidwalkers
- if (!Voidwalkers && HealthBelowPct(51))
- {
- DoCastVictim(SPELL_SUMMON_VOIDWALKERS, true);
- Voidwalkers = true;
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SHADOW_BOLT_VOLLEY:
+ DoCastVictim(SPELL_SHADOWBOLTVOLLEY);
+ _events.ScheduleEvent(EVENT_SHADOW_BOLT_VOLLEY, 12000);
+ break;
+ case EVENT_IMMOLATE:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_IMMOLATE);
+ _events.ScheduleEvent(EVENT_IMMOLATE, 25000);
+ break;
+ case EVENT_CURSE_OF_WEAKNESS:
+ DoCastVictim(SPELL_CURSEOFWEAKNESS);
+ _events.ScheduleEvent(EVENT_CURSE_OF_WEAKNESS, 45000);
+ break;
+ case EVENT_DEMONARMOR:
+ DoCast(me, SPELL_DEMONARMOR);
+ _events.ScheduleEvent(EVENT_DEMONARMOR, 300000);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
}
- DoMeleeAttackIfReady();
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ bool _voidwalkers;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_doomrelAI>(creature);
}
- };
};
void AddSC_boss_tomb_of_seven()
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index dfca72efa6a..21a0f92c7b5 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -1100,7 +1100,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
Talk(SAY_JAINA_ESCAPE_9);
if (Transport* gunship = ObjectAccessor::GetTransport(*me, _instance->GetData64(DATA_GUNSHIP)))
gunship->EnableMovement(true);
- _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE);
+ _instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, DONE);
break;
case EVENT_ESCAPE_17:
if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
@@ -1139,7 +1139,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript
struct npc_the_lich_king_escape_horAI : public ScriptedAI
{
- npc_the_lich_king_escape_horAI(Creature* creature) : ScriptedAI(creature)
+ npc_the_lich_king_escape_horAI(Creature* creature) : ScriptedAI(creature)
{
_instance = me->GetInstanceScript();
_instance->SetBossState(DATA_THE_LICH_KING_ESCAPE, NOT_STARTED);
@@ -1248,12 +1248,12 @@ class npc_the_lich_king_escape_hor : public CreatureScript
_events.ScheduleEvent(EVENT_ESCAPE_SUMMON_WITCH_DOCTOR, 66000);
_events.ScheduleEvent(EVENT_ESCAPE_SUMMON_LUMBERING_ABOMINATION, 14000);
Talk(SAY_LK_ESCAPE_ICEWALL_SUMMONED_4);
- break;
+ break;
default:
break;
}
}
-
+
void EnterEvadeMode() override
{
if (_despawn)
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index e6857659d2e..321c3d67dc5 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -56,6 +56,7 @@ EndContentData */
#include "CellImpl.h"
#include "SpellAuras.h"
#include "Pet.h"
+#include "CreatureTextMgr.h"
/*########
# npc_air_force_bots
@@ -2351,6 +2352,60 @@ public:
};
};
+class npc_imp_in_a_ball : public CreatureScript
+{
+private:
+ enum
+ {
+ SAY_RANDOM,
+
+ EVENT_TALK = 1,
+ };
+
+public:
+ npc_imp_in_a_ball() : CreatureScript("npc_imp_in_a_ball") { }
+
+ struct npc_imp_in_a_ballAI : public ScriptedAI
+ {
+ npc_imp_in_a_ballAI(Creature* creature) : ScriptedAI(creature)
+ {
+ summonerGUID = 0;
+ }
+
+ void IsSummonedBy(Unit* summoner) override
+ {
+ if (summoner->GetTypeId() == TYPEID_PLAYER)
+ {
+ summonerGUID = summoner->GetGUID();
+ events.ScheduleEvent(EVENT_TALK, 3000);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ events.Update(diff);
+
+ if (events.ExecuteEvent() == EVENT_TALK)
+ {
+ if (Player* owner = ObjectAccessor::GetPlayer(*me, summonerGUID))
+ {
+ sCreatureTextMgr->SendChat(me, SAY_RANDOM, owner,
+ owner->GetGroup() ? CHAT_MSG_MONSTER_PARTY : CHAT_MSG_MONSTER_WHISPER, LANG_ADDON, TEXT_RANGE_NORMAL);
+ }
+ }
+ }
+
+ private:
+ EventMap events;
+ uint64 summonerGUID;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_imp_in_a_ballAI(creature);
+ }
+};
+
void AddSC_npcs_special()
{
new npc_air_force_bots();
@@ -2373,4 +2428,5 @@ void AddSC_npcs_special()
new npc_experience();
new npc_firework();
new npc_spring_rabbit();
+ new npc_imp_in_a_ball();
}
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index 3665a388854..9c56c75bf71 100644
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -99,7 +99,7 @@ class DatabaseWorkerPool
(_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
else
TC_LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
- "for specific errors.", GetDatabaseName());
+ "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName());
return res;
}
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index 3b6bd3d2cc8..81825c9055b 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -45,7 +45,7 @@ inline LPTSTR ErrorMessage(DWORD dw)
sprintf(msgBuf, "Unknown error: %u", dw);
return msgBuf;
}
-
+
}
//============================== Global Variables =============================
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h
index f6d6b7f4b9e..e1cc3050929 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.h
+++ b/src/server/shared/Debugging/WheatyExceptionReport.h
@@ -83,7 +83,7 @@ struct SymbolPair
bool operator<(const SymbolPair& other) const
{
- return _offset < other._offset ||
+ return _offset < other._offset ||
(_offset == other._offset && _type < other._type);
}
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index 2638224acff..418f6677e76 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -510,18 +510,18 @@ class ByteBuffer
return *this;
}
- uint8 * contents()
- {
+ uint8 * contents()
+ {
if (_storage.empty())
throw ByteBufferException();
- return &_storage[0];
+ return &_storage[0];
}
- const uint8 *contents() const
- {
+ const uint8 *contents() const
+ {
if (_storage.empty())
throw ByteBufferException();
- return &_storage[0];
+ return &_storage[0];
}
size_t size() const { return _storage.size(); }
diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h
index 236670e5cf1..4d7a37d77cf 100644
--- a/src/server/shared/Utilities/Util.h
+++ b/src/server/shared/Utilities/Util.h
@@ -26,6 +26,7 @@
#include <string>
#include <vector>
#include <list>
+#include <map>
#include <ace/INET_Addr.h>
// Searcher for map of structs
@@ -565,4 +566,353 @@ bool CompareValues(ComparisionType type, T val1, T val2)
}
}
+class EventMap
+{
+ /**
+ * Internal storage type.
+ * Key: Time as uint32 when the event should occur.
+ * Value: The event data as uint32.
+ *
+ * Structure of event data:
+ * - Bit 0 - 15: Event Id.
+ * - Bit 16 - 23: Group
+ * - Bit 24 - 31: Phase
+ * - Pattern: 0xPPGGEEEE
+ */
+ typedef std::multimap<uint32, uint32> EventStore;
+
+ public:
+ EventMap() : _time(0), _phase(0), _lastEvent(0) { }
+
+ /**
+ * @name Reset
+ * @brief Removes all scheduled events and resets time and phase.
+ */
+ void Reset()
+ {
+ _eventMap.clear();
+ _time = 0;
+ _phase = 0;
+ }
+
+ /**
+ * @name Update
+ * @brief Updates the timer of the event map.
+ * @param time Value to be added to time.
+ */
+ void Update(uint32 time)
+ {
+ _time += time;
+ }
+
+ /**
+ * @name GetTimer
+ * @return Current timer value.
+ */
+ uint32 GetTimer() const
+ {
+ return _time;
+ }
+
+ /**
+ * @name GetPhaseMask
+ * @return Active phases as mask.
+ */
+ uint8 GetPhaseMask() const
+ {
+ return _phase;
+ }
+
+ /**
+ * @name Empty
+ * @return True, if there are no events scheduled.
+ */
+ bool Empty() const
+ {
+ return _eventMap.empty();
+ }
+
+ /**
+ * @name SetPhase
+ * @brief Sets the phase of the map (absolute).
+ * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase.
+ */
+ void SetPhase(uint8 phase)
+ {
+ if (!phase)
+ _phase = 0;
+ else if (phase <= 8)
+ _phase = (1 << (phase - 1));
+ }
+
+ /**
+ * @name AddPhase
+ * @brief Activates the given phase (bitwise).
+ * @param phase Phase which should be activated. Values: 1 - 8
+ */
+ void AddPhase(uint8 phase)
+ {
+ if (phase && phase <= 8)
+ _phase |= (1 << (phase - 1));
+ }
+
+ /**
+ * @name RemovePhase
+ * @brief Deactivates the given phase (bitwise).
+ * @param phase Phase which should be deactivated. Values: 1 - 8.
+ */
+ void RemovePhase(uint8 phase)
+ {
+ if (phase && phase <= 8)
+ _phase &= ~(1 << (phase - 1));
+ }
+
+ /**
+ * @name ScheduleEvent
+ * @brief Creates new event entry in map.
+ * @param eventId The id of the new event.
+ * @param time The time in milliseconds until the event occurs.
+ * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
+ * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
+ */
+ void ScheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0)
+ {
+ if (group && group <= 8)
+ eventId |= (1 << (group + 15));
+
+ if (phase && phase <= 8)
+ eventId |= (1 << (phase + 23));
+
+ _eventMap.insert(EventStore::value_type(_time + time, eventId));
+ }
+
+ /**
+ * @name RescheduleEvent
+ * @brief Cancels the given event and reschedules it.
+ * @param eventId The id of the event.
+ * @param time The time in milliseconds until the event occurs.
+ * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group.
+ * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases.
+ */
+ void RescheduleEvent(uint32 eventId, uint32 time, uint32 group = 0, uint8 phase = 0)
+ {
+ CancelEvent(eventId);
+ ScheduleEvent(eventId, time, group, phase);
+ }
+
+ /**
+ * @name RepeatEvent
+ * @brief Repeats the mostly recently executed event.
+ * @param time Time until the event occurs.
+ */
+ void Repeat(uint32 time)
+ {
+ _eventMap.insert(EventStore::value_type(_time + time, _lastEvent));
+ }
+
+ /**
+ * @name RepeatEvent
+ * @brief Repeats the mostly recently executed event.
+ * @param time Time until the event occurs. Equivalent to Repeat(urand(minTime, maxTime).
+ */
+ void Repeat(uint32 minTime, uint32 maxTime)
+ {
+ Repeat(urand(minTime, maxTime));
+ }
+
+ /**
+ * @name ExecuteEvent
+ * @brief Returns the next event to execute and removes it from map.
+ * @return Id of the event to execute.
+ */
+ uint32 ExecuteEvent()
+ {
+ while (!Empty())
+ {
+ EventStore::iterator itr = _eventMap.begin();
+
+ if (itr->first > _time)
+ return 0;
+ else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase))
+ _eventMap.erase(itr);
+ else
+ {
+ uint32 eventId = (itr->second & 0x0000FFFF);
+ _lastEvent = itr->second; // include phase/group
+ _eventMap.erase(itr);
+ return eventId;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * @name DelayEvents
+ * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0.
+ * @param delay Amount of delay.
+ */
+ void DelayEvents(uint32 delay)
+ {
+ _time = delay < _time ? _time - delay : 0;
+ }
+
+ /**
+ * @name DelayEvents
+ * @brief Delay all events of the same group.
+ * @param delay Amount of delay.
+ * @param group Group of the events.
+ */
+ void DelayEvents(uint32 delay, uint32 group)
+ {
+ if (!group || group > 8 || Empty())
+ 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++);
+ }
+ else
+ ++itr;
+ }
+
+ _eventMap.insert(delayed.begin(), delayed.end());
+ }
+
+ /**
+ * @name CancelEvent
+ * @brief Cancels all events of the specified id.
+ * @param eventId Event id to cancel.
+ */
+ void CancelEvent(uint32 eventId)
+ {
+ if (Empty())
+ return;
+
+ for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
+ {
+ if (eventId == (itr->second & 0x0000FFFF))
+ _eventMap.erase(itr++);
+ else
+ ++itr;
+ }
+ }
+
+ /**
+ * @name CancelEventGroup
+ * @brief Cancel events belonging to specified group.
+ * @param group Group to cancel.
+ */
+ void CancelEventGroup(uint32 group)
+ {
+ if (!group || group > 8 || Empty())
+ return;
+
+ for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();)
+ {
+ if (itr->second & (1 << (group + 15)))
+ _eventMap.erase(itr++);
+ else
+ ++itr;
+ }
+ }
+
+ /**
+ * @name GetNextEventTime
+ * @brief Returns closest occurence of specified event.
+ * @param eventId Wanted event id.
+ * @return Time of found event.
+ */
+ uint32 GetNextEventTime(uint32 eventId) const
+ {
+ if (Empty())
+ return 0;
+
+ for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
+ if (eventId == (itr->second & 0x0000FFFF))
+ return itr->first;
+
+ return 0;
+ }
+
+ /**
+ * @name GetNextEventTime
+ * @return Time of next event.
+ */
+ uint32 GetNextEventTime() const
+ {
+ return Empty() ? 0 : _eventMap.begin()->first;
+ }
+
+ /**
+ * @name IsInPhase
+ * @brief Returns wether event map is in specified phase or not.
+ * @param phase Wanted phase.
+ * @return True, if phase of event map contains specified phase.
+ */
+ bool IsInPhase(uint8 phase)
+ {
+ return phase <= 8 && (!phase || _phase & (1 << (phase - 1)));
+ }
+
+ /**
+ * @name GetTimeUntilEvent
+ * @brief Returns time in milliseconds until next event.
+ * @param Id of the event.
+ * @return Time of next event.
+ */
+ uint32 GetTimeUntilEvent(uint32 eventId) const
+ {
+ for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr)
+ if (eventId == (itr->second & 0x0000FFFF))
+ return itr->first - _time;
+
+ return std::numeric_limits<uint32>::max();
+ }
+
+ private:
+ /**
+ * @name _time
+ * @brief Internal timer.
+ *
+ * This does not represent the real date/time value.
+ * It's more like a stopwatch: It can run, it can be stopped,
+ * it can be resetted and so on. Events occur when this timer
+ * has reached their time value. Its value is changed in the
+ * Update method.
+ */
+ uint32 _time;
+
+ /**
+ * @name _phase
+ * @brief Phase mask of the event map.
+ *
+ * Contains the phases the event map is in. Multiple
+ * phases from 1 to 8 can be set with SetPhase or
+ * AddPhase. RemovePhase deactives a phase.
+ */
+ uint8 _phase;
+
+ /**
+ * @name _eventMap
+ * @brief Internal event storage map. Contains the scheduled events.
+ *
+ * See typedef at the beginning of the class for more
+ * details.
+ */
+ EventStore _eventMap;
+
+
+ /**
+ * @name _lastEvent
+ * @brief Stores information on the most recently executed event
+ */
+ uint32 _lastEvent;
+};
+
#endif
diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp
index c5424374f5a..6e4214603cb 100644
--- a/src/server/worldserver/Master.cpp
+++ b/src/server/worldserver/Master.cpp
@@ -201,24 +201,24 @@ int Master::Run()
ACE_Based::Thread rarThread(new RARunnable);
#if defined(_WIN32) || defined(__linux__)
-
+
///- Handle affinity for multiple processors and process priority
uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0);
bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false);
#ifdef _WIN32 // Windows
-
+
HANDLE hProcess = GetCurrentProcess();
-
+
if (affinity > 0)
{
ULONG_PTR appAff;
ULONG_PTR sysAff;
-
+
if (GetProcessAffinityMask(hProcess, &appAff, &sysAff))
{
ULONG_PTR currentAffinity = affinity & appAff; // remove non accessible processors
-
+
if (!currentAffinity)
TC_LOG_ERROR("server.worldserver", "Processors marked in UseProcessors bitmask (hex) %x are not accessible for the worldserver. Accessible processors bitmask (hex): %x", affinity, appAff);
else if (SetProcessAffinityMask(hProcess, currentAffinity))
@@ -227,7 +227,7 @@ int Master::Run()
TC_LOG_ERROR("server.worldserver", "Can't set used processors (hex): %x", currentAffinity);
}
}
-
+
if (highPriority)
{
if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS))
@@ -235,9 +235,9 @@ int Master::Run()
else
TC_LOG_ERROR("server.worldserver", "Can't set worldserver process priority class.");
}
-
+
#else // Linux
-
+
if (affinity > 0)
{
cpu_set_t mask;
@@ -264,7 +264,7 @@ int Master::Run()
else
TC_LOG_INFO("server.worldserver", "worldserver process priority class set to %i", getpriority(PRIO_PROCESS, 0));
}
-
+
#endif
#endif