diff options
author | Shauren <shauren.trinity@gmail.com> | 2021-10-11 12:59:19 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2021-10-11 12:59:19 +0200 |
commit | d7302ffd1499433fef2cc4e824ae9443c3d2c79f (patch) | |
tree | 7be39461e047ef032c5419e1cd5772be704fd464 /src/server | |
parent | 8492c273dd50227ca01ead785eda6c4de9361e74 (diff) |
Core/Scenes: Implemented spell created SceneObjects
Diffstat (limited to 'src/server')
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Entities/SceneObject/SceneObject.cpp | 193 | ||||
-rw-r--r-- | src/server/game/Entities/SceneObject/SceneObject.h | 76 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectAccessor.cpp | 10 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectAccessor.h | 2 | ||||
-rw-r--r-- | src/server/game/Grids/GridDefines.h | 11 | ||||
-rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.h | 14 | ||||
-rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiersImpl.h | 50 | ||||
-rw-r--r-- | src/server/game/Grids/ObjectGridLoader.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Grids/ObjectGridLoader.h | 3 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 58 | ||||
-rw-r--r-- | src/server/shared/Dynamic/TypeList.h | 1 |
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 |