aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AI/CreatureAIImpl.h349
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp1
-rw-r--r--src/server/game/Entities/Player/Player.cpp30
-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.cpp62
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp1
-rw-r--r--src/server/game/Maps/Map.cpp7
-rw-r--r--src/server/game/Server/WorldSession.cpp3
-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.cpp3
-rw-r--r--src/server/game/Texts/CreatureTextMgr.cpp13
13 files changed, 114 insertions, 387 deletions
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/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index d6a029d29bf..f473428d41b 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1405,6 +1405,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 ac6b6a97fbb..1c439229ec3 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -16486,9 +16486,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);
@@ -16510,9 +16508,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;
@@ -16524,18 +16524,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;
@@ -27606,6 +27605,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 9099a7466d1..94d90de8813 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1898,7 +1898,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
@@ -2525,6 +2525,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); }
@@ -2815,7 +2817,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 30c20b08cac..8d5aa293d06 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..9ab11be9858 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;
@@ -1586,3 +1618,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/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/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 22c0b332f33..cd91af11a92 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2859,10 +2859,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/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index d157715c496..811304145d8 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));
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index ae32f48f622..3c5e27f6f52 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 efc24792a7c..7226ebe12c2 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1768,9 +1768,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);
@@ -1800,6 +1797,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
{
@@ -1919,9 +1922,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)
{
@@ -2090,11 +2095,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..c4f081591a0 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -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;
}