aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Object/Object.cpp14
-rw-r--r--src/server/game/Entities/Player/Player.cpp1
-rw-r--r--src/server/game/Entities/SceneObject/SceneObject.cpp193
-rw-r--r--src/server/game/Entities/SceneObject/SceneObject.h76
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp10
-rw-r--r--src/server/game/Globals/ObjectAccessor.h2
-rw-r--r--src/server/game/Grids/GridDefines.h11
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp1
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h14
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiersImpl.h50
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp7
-rw-r--r--src/server/game/Grids/ObjectGridLoader.h3
-rw-r--r--src/server/game/Maps/Map.cpp7
-rw-r--r--src/server/game/Maps/Map.h1
-rw-r--r--src/server/game/Spells/Spell.h2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp58
-rw-r--r--src/server/shared/Dynamic/TypeList.h1
17 files changed, 435 insertions, 16 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index a2dac19476c..3ea5484e0aa 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -145,7 +145,6 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
uint16 objectTypeMask = m_objectType;
CreateObjectBits flags = m_updateFlag;
- /** lower flag1 **/
if (target == this) // building packet for yourself
{
flags.ThisIsYou = true;
@@ -161,6 +160,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
case HighGuid::Corpse:
case HighGuid::DynamicObject:
case HighGuid::AreaTrigger:
+ case HighGuid::SceneObject:
case HighGuid::Conversation:
updateType = UPDATETYPE_CREATE_OBJECT2;
break;
@@ -620,11 +620,11 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const
// *data << ObjectGuid(ReplaceObject);
//}
- //if (flags.SceneObject)
- //{
- // data->WriteBit(HasLocalScriptData);
- // data->WriteBit(HasPetBattleFullUpdate);
- // data->FlushBits();
+ if (flags.SceneObject)
+ {
+ data->WriteBit(false); // HasLocalScriptData
+ data->WriteBit(false); // HasPetBattleFullUpdate
+ data->FlushBits();
// if (HasLocalScriptData)
// {
@@ -728,7 +728,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const
// data->WriteBit(CanAwardXP);
// data->FlushBits();
// }
- //}
+ }
if (flags.ActivePlayer)
{
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 78b10322eda..6d1f0a09066 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -24053,6 +24053,7 @@ template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data
template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(AreaTrigger* target, UpdateData& data, std::set<Unit*>& visibleNow);
+template void Player::UpdateVisibilityOf(SceneObject* target, UpdateData& data, std::set<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Conversation* target, UpdateData& data, std::set<Unit*>& visibleNow);
void Player::UpdateObjectVisibility(bool forced)
diff --git a/src/server/game/Entities/SceneObject/SceneObject.cpp b/src/server/game/Entities/SceneObject/SceneObject.cpp
new file mode 100644
index 00000000000..de79d7f1c31
--- /dev/null
+++ b/src/server/game/Entities/SceneObject/SceneObject.cpp
@@ -0,0 +1,193 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "SceneObject.h"
+#include "GameTime.h"
+#include "Map.h"
+#include "ObjectAccessor.h"
+#include "ObjectMgr.h"
+#include "PhasingHandler.h"
+#include "SpellAuras.h"
+#include "Unit.h"
+#include "UpdateData.h"
+#include "Util.h"
+
+SceneObject::SceneObject() : WorldObject(false)
+{
+ m_objectType |= TYPEMASK_SCENEOBJECT;
+ m_objectTypeId = TYPEID_SCENEOBJECT;
+
+ m_updateFlag.Stationary = true;
+ m_updateFlag.SceneObject = true;
+}
+
+SceneObject::~SceneObject() = default;
+
+void SceneObject::AddToWorld()
+{
+ if (!IsInWorld())
+ {
+ GetMap()->GetObjectsStore().Insert<SceneObject>(GetGUID(), this);
+ WorldObject::AddToWorld();
+ }
+}
+
+void SceneObject::RemoveFromWorld()
+{
+ if (IsInWorld())
+ {
+ WorldObject::RemoveFromWorld();
+ GetMap()->GetObjectsStore().Remove<SceneObject>(GetGUID());
+ }
+}
+
+void SceneObject::Update(uint32 diff)
+{
+ WorldObject::Update(diff);
+
+ if (ShouldBeRemoved())
+ Remove();
+}
+
+void SceneObject::Remove()
+{
+ if (IsInWorld())
+ AddObjectToRemoveList();
+}
+
+bool SceneObject::ShouldBeRemoved() const
+{
+ Unit* creator = ObjectAccessor::GetUnit(*this, GetOwnerGUID());
+ if (!creator)
+ return true;
+
+ if (!_createdBySpellCast.IsEmpty())
+ {
+ // search for a dummy aura on creator
+ Aura const* linkedAura = creator->GetAura(_createdBySpellCast.GetEntry(), [this](Aura const* aura)
+ {
+ return aura->GetCastId() == _createdBySpellCast;
+ });
+ if (!linkedAura)
+ return true;
+ }
+
+ return false;
+}
+
+SceneObject* SceneObject::CreateSceneObject(uint32 sceneId, Unit* creator, Position const& pos, ObjectGuid privateObjectOwner)
+{
+ SceneTemplate const* sceneTemplate = sObjectMgr->GetSceneTemplate(sceneId);
+ if (!sceneTemplate)
+ return nullptr;
+
+ ObjectGuid::LowType lowGuid = creator->GetMap()->GenerateLowGuid<HighGuid::SceneObject>();
+
+ SceneObject* sceneObject = new SceneObject();
+ if (!sceneObject->Create(lowGuid, SceneType::Normal, sceneId, sceneTemplate ? sceneTemplate->ScenePackageId : 0, creator->GetMap(), creator, pos, privateObjectOwner))
+ {
+ delete sceneObject;
+ return nullptr;
+ }
+
+ return sceneObject;
+}
+
+bool SceneObject::Create(ObjectGuid::LowType lowGuid, SceneType type, uint32 sceneId, uint32 scriptPackageId, Map* map, Unit* creator,
+ Position const& pos, ObjectGuid privateObjectOwner)
+{
+ SetMap(map);
+ Relocate(pos);
+ RelocateStationaryPosition(pos);
+
+ SetPrivateObjectOwner(privateObjectOwner);
+
+ Object::_Create(ObjectGuid::Create<HighGuid::SceneObject>(GetMapId(), sceneId, lowGuid));
+ PhasingHandler::InheritPhaseShift(this, creator);
+
+ SetEntry(scriptPackageId);
+ SetObjectScale(1.0f);
+
+ SetUpdateFieldValue(m_values.ModifyValue(&SceneObject::m_sceneObjectData).ModifyValue(&UF::SceneObjectData::ScriptPackageID), scriptPackageId);
+ SetUpdateFieldValue(m_values.ModifyValue(&SceneObject::m_sceneObjectData).ModifyValue(&UF::SceneObjectData::RndSeedVal), GameTime::GetGameTimeMS());
+ SetUpdateFieldValue(m_values.ModifyValue(&SceneObject::m_sceneObjectData).ModifyValue(&UF::SceneObjectData::CreatedBy), creator->GetGUID());
+ SetUpdateFieldValue(m_values.ModifyValue(&SceneObject::m_sceneObjectData).ModifyValue(&UF::SceneObjectData::SceneType), AsUnderlyingType(type));
+
+ if (!GetMap()->AddToMap(this))
+ return false;
+
+ return true;
+}
+
+void SceneObject::BuildValuesCreate(ByteBuffer* data, Player const* target) const
+{
+ UF::UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
+ std::size_t sizePos = data->wpos();
+ *data << uint32(0);
+ *data << uint8(flags);
+ m_objectData->WriteCreate(*data, flags, this, target);
+ m_sceneObjectData->WriteCreate(*data, flags, this, target);
+ data->put<uint32>(sizePos, data->wpos() - sizePos - 4);
+}
+
+void SceneObject::BuildValuesUpdate(ByteBuffer* data, Player const* target) const
+{
+ UF::UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target);
+ std::size_t sizePos = data->wpos();
+ *data << uint32(0);
+ *data << uint32(m_values.GetChangedObjectTypeMask());
+
+ if (m_values.HasChanged(TYPEID_OBJECT))
+ m_objectData->WriteUpdate(*data, flags, this, target);
+
+ if (m_values.HasChanged(TYPEID_SCENEOBJECT))
+ m_sceneObjectData->WriteUpdate(*data, flags, this, target);
+
+ data->put<uint32>(sizePos, data->wpos() - sizePos - 4);
+}
+
+void SceneObject::BuildValuesUpdateForPlayerWithMask(UpdateData* data, UF::ObjectData::Mask const& requestedObjectMask,
+ UF::SceneObjectData::Mask const& requestedSceneObjectMask, Player const* target) const
+{
+ UpdateMask<NUM_CLIENT_OBJECT_TYPES> valuesMask;
+ if (requestedObjectMask.IsAnySet())
+ valuesMask.Set(TYPEID_OBJECT);
+
+ if (requestedSceneObjectMask.IsAnySet())
+ valuesMask.Set(TYPEID_SCENEOBJECT);
+
+ ByteBuffer buffer = PrepareValuesUpdateBuffer();
+ std::size_t sizePos = buffer.wpos();
+ buffer << uint32(0);
+ buffer << uint32(valuesMask.GetBlock(0));
+
+ if (valuesMask[TYPEID_OBJECT])
+ m_objectData->WriteUpdate(buffer, requestedObjectMask, true, this, target);
+
+ if (valuesMask[TYPEID_SCENEOBJECT])
+ m_sceneObjectData->WriteUpdate(buffer, requestedSceneObjectMask, true, this, target);
+
+ buffer.put<uint32>(sizePos, buffer.wpos() - sizePos - 4);
+
+ data->AddUpdateBlock(buffer);
+}
+
+void SceneObject::ClearUpdateMask(bool remove)
+{
+ m_values.ClearChangesMask(&SceneObject::m_sceneObjectData);
+ Object::ClearUpdateMask(remove);
+}
diff --git a/src/server/game/Entities/SceneObject/SceneObject.h b/src/server/game/Entities/SceneObject/SceneObject.h
new file mode 100644
index 00000000000..ca1e6c5449f
--- /dev/null
+++ b/src/server/game/Entities/SceneObject/SceneObject.h
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SceneObject_h__
+#define SceneObject_h__
+
+#include "Object.h"
+
+struct SceneTemplate;
+
+enum class SceneType : uint32
+{
+ Normal = 0,
+ PetBattle = 1
+};
+
+class TC_GAME_API SceneObject : public WorldObject, public GridObject<SceneObject>
+{
+public:
+ SceneObject();
+ ~SceneObject();
+
+protected:
+ void BuildValuesCreate(ByteBuffer* data, Player const* target) const override;
+ void BuildValuesUpdate(ByteBuffer* data, Player const* target) const override;
+ void ClearUpdateMask(bool remove) override;
+
+public:
+ void BuildValuesUpdateForPlayerWithMask(UpdateData* data, UF::ObjectData::Mask const& requestedObjectMask,
+ UF::SceneObjectData::Mask const& requestedSceneObjectMask, Player const* target) const;
+
+ void AddToWorld() override;
+ void RemoveFromWorld() override;
+
+ void Update(uint32 diff) override;
+ void Remove();
+
+ static SceneObject* CreateSceneObject(uint32 sceneId, Unit* creator, Position const& pos, ObjectGuid privateObjectOwner);
+ bool Create(ObjectGuid::LowType lowGuid, SceneType type, uint32 sceneId, uint32 scriptPackageId, Map* map, Unit* creator,
+ Position const& pos, ObjectGuid privateObjectOwner);
+
+ ObjectGuid GetOwnerGUID() const override { return *m_sceneObjectData->CreatedBy; }
+ uint32 GetFaction() const override { return 0; }
+
+ float GetStationaryX() const override { return _stationaryPosition.GetPositionX(); }
+ float GetStationaryY() const override { return _stationaryPosition.GetPositionY(); }
+ float GetStationaryZ() const override { return _stationaryPosition.GetPositionZ(); }
+ float GetStationaryO() const override { return _stationaryPosition.GetOrientation(); }
+ void RelocateStationaryPosition(Position const& pos) { _stationaryPosition.Relocate(pos); }
+
+ void SetCreatedBySpellCast(ObjectGuid castId) { _createdBySpellCast = castId; }
+
+ UF::UpdateField<UF::SceneObjectData, 0, TYPEID_SCENEOBJECT> m_sceneObjectData;
+
+private:
+ bool ShouldBeRemoved() const;
+
+ Position _stationaryPosition;
+ ObjectGuid _createdBySpellCast;
+};
+
+#endif // SceneObject_h__
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index 65889a35e73..69da03752ef 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -118,6 +118,7 @@ WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid con
case HighGuid::DynamicObject: return GetDynamicObject(p, guid);
case HighGuid::AreaTrigger: return GetAreaTrigger(p, guid);
case HighGuid::Corpse: return GetCorpse(p, guid);
+ case HighGuid::SceneObject: return GetSceneObject(p, guid);
case HighGuid::Conversation: return GetConversation(p, guid);
default: return nullptr;
}
@@ -157,6 +158,10 @@ Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const& p, ObjectGuid con
if (typemask & TYPEMASK_AREATRIGGER)
return GetAreaTrigger(p, guid);
break;
+ case HighGuid::SceneObject:
+ if (typemask & TYPEMASK_SCENEOBJECT)
+ return GetSceneObject(p, guid);
+ break;
case HighGuid::Conversation:
if (typemask & TYPEMASK_CONVERSATION)
return GetConversation(p, guid);
@@ -200,6 +205,11 @@ AreaTrigger* ObjectAccessor::GetAreaTrigger(WorldObject const& u, ObjectGuid con
return u.GetMap()->GetAreaTrigger(guid);
}
+SceneObject* ObjectAccessor::GetSceneObject(WorldObject const& u, ObjectGuid const& guid)
+{
+ return u.GetMap()->GetSceneObject(guid);
+}
+
Conversation* ObjectAccessor::GetConversation(WorldObject const& u, ObjectGuid const& guid)
{
return u.GetMap()->GetConversation(guid);
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index 089da4e0f20..b8b360e7a40 100644
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -31,6 +31,7 @@ class Map;
class Object;
class Pet;
class Player;
+class SceneObject;
class Transport;
class Unit;
class WorldObject;
@@ -72,6 +73,7 @@ namespace ObjectAccessor
TC_GAME_API Transport* GetTransport(ObjectGuid const& guid);
TC_GAME_API DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API AreaTrigger* GetAreaTrigger(WorldObject const& u, ObjectGuid const& guid);
+ TC_GAME_API SceneObject* GetSceneObject(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API Conversation* GetConversation(WorldObject const& u, ObjectGuid const& guid);
TC_GAME_API Unit* GetUnit(WorldObject const&, ObjectGuid const& guid);
TC_GAME_API Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid);
diff --git a/src/server/game/Grids/GridDefines.h b/src/server/game/Grids/GridDefines.h
index e01f6d25e5c..81248a93102 100644
--- a/src/server/game/Grids/GridDefines.h
+++ b/src/server/game/Grids/GridDefines.h
@@ -30,6 +30,7 @@ class GameObject;
class Pet;
class Player;
class AreaTrigger;
+class SceneObject;
class Conversation;
#define MAX_NUMBER_OF_CELLS 8
@@ -58,8 +59,8 @@ class Conversation;
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
-typedef TYPELIST_6(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/, AreaTrigger, Conversation) AllGridObjectTypes;
-typedef TYPELIST_7(Creature, GameObject, DynamicObject, Pet, Corpse, AreaTrigger, Conversation) AllMapStoredObjectTypes;
+typedef TYPELIST_7(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/, AreaTrigger, SceneObject, Conversation) AllGridObjectTypes;
+typedef TYPELIST_8(Creature, GameObject, DynamicObject, Pet, Corpse, AreaTrigger, SceneObject, Conversation) AllMapStoredObjectTypes;
typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType;
@@ -67,6 +68,7 @@ typedef GridRefManager<DynamicObject> DynamicObjectMapType;
typedef GridRefManager<GameObject> GameObjectMapType;
typedef GridRefManager<Player> PlayerMapType;
typedef GridRefManager<AreaTrigger> AreaTriggerMapType;
+typedef GridRefManager<SceneObject> SceneObjectMapType;
typedef GridRefManager<Conversation> ConversationMapType;
enum GridMapTypeMask
@@ -77,8 +79,9 @@ enum GridMapTypeMask
GRID_MAP_TYPE_MASK_GAMEOBJECT = 0x08,
GRID_MAP_TYPE_MASK_PLAYER = 0x10,
GRID_MAP_TYPE_MASK_AREATRIGGER = 0x20,
- GRID_MAP_TYPE_MASK_CONVERSATION = 0x40,
- GRID_MAP_TYPE_MASK_ALL = 0x7F
+ GRID_MAP_TYPE_MASK_SCENEOBJECT = 0x40,
+ GRID_MAP_TYPE_MASK_CONVERSATION = 0x80,
+ GRID_MAP_TYPE_MASK_ALL = 0xFF
};
typedef Grid<Player, AllWorldObjectTypes, AllGridObjectTypes> GridType;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index 287976bf774..b68d366dbfb 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -303,4 +303,5 @@ template void ObjectUpdater::Visit<Creature>(CreatureMapType&);
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType&);
template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType&);
template void ObjectUpdater::Visit<AreaTrigger>(AreaTriggerMapType &);
+template void ObjectUpdater::Visit<SceneObject>(SceneObjectMapType &);
template void ObjectUpdater::Visit<Conversation>(ConversationMapType &);
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 09ee2936b0d..a0c31f76348 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -26,6 +26,7 @@
#include "GameObject.h"
#include "Packet.h"
#include "Player.h"
+#include "SceneObject.h"
#include "Spell.h"
#include "SpellInfo.h"
#include "TemporarySummon.h"
@@ -115,6 +116,7 @@ namespace Trinity
void Visit(DynamicObjectMapType &m) { updateObjects<DynamicObject>(m); }
void Visit(CorpseMapType &m) { updateObjects<Corpse>(m); }
void Visit(AreaTriggerMapType &m) { updateObjects<AreaTrigger>(m); }
+ void Visit(SceneObjectMapType &m) { updateObjects<SceneObject>(m); }
void Visit(ConversationMapType &m) { updateObjects<Conversation>(m); }
};
@@ -259,6 +261,7 @@ namespace Trinity
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
void Visit(AreaTriggerMapType &m);
+ void Visit(SceneObjectMapType &m);
void Visit(ConversationMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
@@ -281,6 +284,7 @@ namespace Trinity
void Visit(CorpseMapType &m);
void Visit(DynamicObjectMapType &m);
void Visit(AreaTriggerMapType &m);
+ void Visit(SceneObjectMapType &m);
void Visit(ConversationMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
@@ -304,6 +308,7 @@ namespace Trinity
void Visit(GameObjectMapType &m);
void Visit(DynamicObjectMapType &m);
void Visit(AreaTriggerMapType &m);
+ void Visit(SceneObjectMapType &m);
void Visit(ConversationMapType &m);
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) { }
@@ -372,6 +377,15 @@ namespace Trinity
i_do(itr->GetSource());
}
+ void Visit(SceneObjectMapType& m)
+ {
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
+ return;
+ for (SceneObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ if (itr->GetSource()->IsInPhase(_searcher))
+ i_do(itr->GetSource());
+ }
+
void Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
diff --git a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
index 63daf6b6482..f09de34e4c9 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiersImpl.h
@@ -322,6 +322,29 @@ void Trinity::WorldObjectSearcher<Check>::Visit(AreaTriggerMapType &m)
}
template<class Check>
+void Trinity::WorldObjectSearcher<Check>::Visit(SceneObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
+ return;
+
+ // already found
+ if (i_object)
+ return;
+
+ for (SceneObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->GetSource()->IsInPhase(_searcher))
+ continue;
+
+ if (i_check(itr->GetSource()))
+ {
+ i_object = itr->GetSource();
+ return;
+ }
+ }
+}
+
+template<class Check>
void Trinity::WorldObjectSearcher<Check>::Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
@@ -441,6 +464,22 @@ void Trinity::WorldObjectLastSearcher<Check>::Visit(AreaTriggerMapType &m)
}
template<class Check>
+void Trinity::WorldObjectLastSearcher<Check>::Visit(SceneObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
+ return;
+
+ for (SceneObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ {
+ if (!itr->GetSource()->IsInPhase(_searcher))
+ continue;
+
+ if (i_check(itr->GetSource()))
+ i_object = itr->GetSource();
+ }
+}
+
+template<class Check>
void Trinity::WorldObjectLastSearcher<Check>::Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
@@ -523,6 +562,17 @@ void Trinity::WorldObjectListSearcher<Check>::Visit(AreaTriggerMapType &m)
}
template<class Check>
+void Trinity::WorldObjectListSearcher<Check>::Visit(SceneObjectMapType &m)
+{
+ if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_SCENEOBJECT))
+ return;
+
+ for (SceneObjectMapType::iterator itr = m.begin(); itr != m.end(); ++itr)
+ if (i_check(itr->GetSource()))
+ Insert(itr->GetSource());
+}
+
+template<class Check>
void Trinity::WorldObjectListSearcher<Check>::Visit(ConversationMapType &m)
{
if (!(i_mapTypeMask & GRID_MAP_TYPE_MASK_CONVERSATION))
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index 39f3bf9dc47..237d7196284 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -30,6 +30,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "PhasingHandler.h"
+#include "SceneObject.h"
#include "World.h"
#include "ScriptMgr.h"
@@ -285,12 +286,14 @@ void ObjectGridCleaner::Visit(GridRefManager<T> &m)
template void ObjectGridUnloader::Visit(CreatureMapType &);
template void ObjectGridUnloader::Visit(GameObjectMapType &);
template void ObjectGridUnloader::Visit(DynamicObjectMapType &);
-template void ObjectGridUnloader::Visit(ConversationMapType &);
+template void ObjectGridUnloader::Visit(AreaTriggerMapType&);
+template void ObjectGridUnloader::Visit(SceneObjectMapType&);
+template void ObjectGridUnloader::Visit(ConversationMapType&);
-template void ObjectGridUnloader::Visit(AreaTriggerMapType &);
template void ObjectGridCleaner::Visit(CreatureMapType &);
template void ObjectGridCleaner::Visit<GameObject>(GameObjectMapType &);
template void ObjectGridCleaner::Visit<DynamicObject>(DynamicObjectMapType &);
template void ObjectGridCleaner::Visit<Corpse>(CorpseMapType &);
template void ObjectGridCleaner::Visit<AreaTrigger>(AreaTriggerMapType &);
+template void ObjectGridCleaner::Visit<SceneObject>(SceneObjectMapType &);
template void ObjectGridCleaner::Visit<Conversation>(ConversationMapType &);
diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h
index e88a2813d93..dfd02011001 100644
--- a/src/server/game/Grids/ObjectGridLoader.h
+++ b/src/server/game/Grids/ObjectGridLoader.h
@@ -40,7 +40,8 @@ class TC_GAME_API ObjectGridLoader
void Visit(AreaTriggerMapType &m);
void Visit(CorpseMapType &) const { }
void Visit(DynamicObjectMapType&) const { }
- void Visit(ConversationMapType &) const { }
+ void Visit(SceneObjectMapType&) const { }
+ void Visit(ConversationMapType&) const { }
void LoadN(void);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 01880d7bcea..ac4760f72fc 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3823,6 +3823,7 @@ template TC_GAME_API bool Map::AddToMap(Creature*);
template TC_GAME_API bool Map::AddToMap(GameObject*);
template TC_GAME_API bool Map::AddToMap(DynamicObject*);
template TC_GAME_API bool Map::AddToMap(AreaTrigger*);
+template TC_GAME_API bool Map::AddToMap(SceneObject*);
template TC_GAME_API bool Map::AddToMap(Conversation*);
template TC_GAME_API void Map::RemoveFromMap(Corpse*, bool);
@@ -3830,6 +3831,7 @@ template TC_GAME_API void Map::RemoveFromMap(Creature*, bool);
template TC_GAME_API void Map::RemoveFromMap(GameObject*, bool);
template TC_GAME_API void Map::RemoveFromMap(DynamicObject*, bool);
template TC_GAME_API void Map::RemoveFromMap(AreaTrigger*, bool);
+template TC_GAME_API void Map::RemoveFromMap(SceneObject*, bool);
template TC_GAME_API void Map::RemoveFromMap(Conversation*, bool);
/* ******* Dungeon Instance Maps ******* */
@@ -4421,6 +4423,11 @@ AreaTrigger* Map::GetAreaTrigger(ObjectGuid const& guid)
return _objectsStore.Find<AreaTrigger>(guid);
}
+SceneObject* Map::GetSceneObject(ObjectGuid const& guid)
+{
+ return _objectsStore.Find<SceneObject>(guid);
+}
+
Conversation* Map::GetConversation(ObjectGuid const& guid)
{
return _objectsStore.Find<Conversation>(guid);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 811aba5082b..cdc49d3d8a9 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -442,6 +442,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
TempSummon* SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties = nullptr, uint32 duration = 0, Unit* summoner = nullptr, uint32 spellId = 0, uint32 vehId = 0, ObjectGuid privateObjectOwner = ObjectGuid::Empty);
void SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list = nullptr);
AreaTrigger* GetAreaTrigger(ObjectGuid const& guid);
+ SceneObject* GetSceneObject(ObjectGuid const& guid);
Conversation* GetConversation(ObjectGuid const& guid);
Player* GetPlayer(ObjectGuid const& guid);
Corpse* GetCorpse(ObjectGuid const& guid);
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index bd86cf8a98e..1d25fcaf267 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -385,6 +385,8 @@ class TC_GAME_API Spell
void EffectGiveArtifactPower();
void EffectGiveArtifactPowerNoBonus();
void EffectPlaySceneScriptPackage();
+ void EffectCreateSceneObject();
+ void EffectCreatePrivateSceneObject();
void EffectPlayScene();
void EffectGiveHonor();
void EffectLearnTransmogSet();
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index d94d3163a20..c0e0af8045b 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -60,6 +60,7 @@
#include "PhasingHandler.h"
#include "Player.h"
#include "ReputationMgr.h"
+#include "SceneObject.h"
#include "ScriptMgr.h"
#include "SharedDefines.h"
#include "SkillExtraItems.h"
@@ -276,8 +277,8 @@ NonDefaultConstructible<SpellEffectHandlerFn> SpellEffectHandlers[TOTAL_SPELL_EF
&Spell::EffectNULL, //193 SPELL_EFFECT_START_PET_BATTLE
&Spell::EffectUnused, //194 SPELL_EFFECT_194
&Spell::EffectPlaySceneScriptPackage, //195 SPELL_EFFECT_PLAY_SCENE_SCRIPT_PACKAGE
- &Spell::EffectNULL, //196 SPELL_EFFECT_CREATE_SCENE_OBJECT
- &Spell::EffectNULL, //197 SPELL_EFFECT_CREATE_PERSONAL_SCENE_OBJECT
+ &Spell::EffectCreateSceneObject, //196 SPELL_EFFECT_CREATE_SCENE_OBJECT
+ &Spell::EffectCreatePrivateSceneObject, //197 SPELL_EFFECT_CREATE_PERSONAL_SCENE_OBJECT
&Spell::EffectPlayScene, //198 SPELL_EFFECT_PLAY_SCENE
&Spell::EffectNULL, //199 SPELL_EFFECT_DESPAWN_SUMMON
&Spell::EffectHealBattlePetPct, //200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
@@ -5770,6 +5771,59 @@ void Spell::EffectPlaySceneScriptPackage()
m_caster->ToPlayer()->GetSceneMgr().PlaySceneByPackageId(effectInfo->MiscValue, SceneFlag::PlayerNonInteractablePhased, destTarget);
}
+template<typename TargetInfo>
+bool IsUnitTargetSceneObjectAura(Spell const* spell, TargetInfo const& target)
+{
+ if (target.TargetGUID != spell->GetCaster()->GetGUID())
+ return false;
+
+ for (SpellEffectInfo const& spellEffectInfo : spell->GetSpellInfo()->GetEffects())
+ if (target.EffectMask & (1 << spellEffectInfo.EffectIndex) && spellEffectInfo.IsUnitOwnedAuraEffect())
+ return true;
+
+ return false;
+}
+
+void Spell::EffectCreateSceneObject()
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ if (!unitCaster || !m_targets.HasDst())
+ return;
+
+ if (SceneObject* sceneObject = SceneObject::CreateSceneObject(effectInfo->MiscValue, unitCaster, destTarget->GetPosition(), ObjectGuid::Empty))
+ {
+ bool hasAuraTargetingCaster = std::find_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [this](TargetInfo const& target)
+ {
+ return IsUnitTargetSceneObjectAura(this, target);
+ }) != m_UniqueTargetInfo.end();
+
+ if (hasAuraTargetingCaster)
+ sceneObject->SetCreatedBySpellCast(m_castId);
+ }
+}
+
+void Spell::EffectCreatePrivateSceneObject()
+{
+ if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
+ return;
+
+ if (!unitCaster || !m_targets.HasDst())
+ return;
+
+ if (SceneObject* sceneObject = SceneObject::CreateSceneObject(effectInfo->MiscValue, unitCaster, destTarget->GetPosition(), unitCaster->GetGUID()))
+ {
+ bool hasAuraTargetingCaster = std::find_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [this](TargetInfo const& target)
+ {
+ return IsUnitTargetSceneObjectAura(this, target);
+ }) != m_UniqueTargetInfo.end();
+
+ if (hasAuraTargetingCaster)
+ sceneObject->SetCreatedBySpellCast(m_castId);
+ }
+}
+
void Spell::EffectPlayScene()
{
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT)
diff --git a/src/server/shared/Dynamic/TypeList.h b/src/server/shared/Dynamic/TypeList.h
index 6d8c045dce1..32000b7de80 100644
--- a/src/server/shared/Dynamic/TypeList.h
+++ b/src/server/shared/Dynamic/TypeList.h
@@ -41,4 +41,5 @@ struct TypeList
#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList<T1, TYPELIST_4(T2, T3, T4, T5) >
#define TYPELIST_6(T1, T2, T3, T4, T5, T6) TypeList<T1, TYPELIST_5(T2, T3, T4, T5, T6) >
#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) TypeList<T1, TYPELIST_6(T2, T3, T4, T5, T6, T7) >
+#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) TypeList<T1, TYPELIST_7(T2, T3, T4, T5, T6, T7, T8) >
#endif