/*
* 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 .
*/
#ifndef _OBJECT_H
#define _OBJECT_H
#include "Common.h"
#include "Duration.h"
#include "Errors.h"
#include "EventProcessor.h"
#include "MapDefines.h"
#include "ModelIgnoreFlags.h"
#include "MovementInfo.h"
#include "ObjectDefines.h"
#include "ObjectGuid.h"
#include "Optional.h"
#include "PhaseShift.h"
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
#include "UniqueTrackablePtr.h"
#include "UpdateFields.h"
#include "WowCSEntityDefinitions.h"
#include
#include
class AreaTrigger;
class Conversation;
class Corpse;
class Creature;
class CreatureAI;
class DynamicObject;
class GameObject;
class InstanceScript;
class Item;
class Map;
class Object;
class Player;
class Scenario;
class SceneObject;
class SmoothPhasing;
class Spell;
class SpellCastTargets;
class SpellEffectInfo;
class SpellInfo;
class TempSummon;
class TransportBase;
class Unit;
class UpdateData;
class WorldObject;
class WorldPacket;
class ZoneScript;
struct FactionTemplateEntry;
struct Loot;
struct QuaternionData;
struct SpawnTrackingStateData;
struct SpellPowerCost;
namespace WorldPackets
{
namespace CombatLog
{
class CombatLogServerPacket;
}
}
typedef std::unordered_map UpdateDataMapType;
struct CreateObjectBits
{
bool NoBirthAnim : 1;
bool EnablePortals : 1;
bool PlayHoverAnim : 1;
bool MovementUpdate : 1;
bool MovementTransport : 1;
bool Stationary : 1;
bool CombatVictim : 1;
bool ServerTime : 1;
bool Vehicle : 1;
bool AnimKit : 1;
bool Rotation : 1;
bool GameObject : 1;
bool SmoothPhasing : 1;
bool ThisIsYou : 1;
bool SceneObject : 1;
bool ActivePlayer : 1;
bool Conversation : 1;
void Clear()
{
memset(this, 0, sizeof(CreateObjectBits));
}
};
namespace UF
{
class UpdateFieldHolder
{
public:
template
inline MutableFieldReference ModifyValue(UpdateField(Derived::* field));
template
inline OptionalUpdateFieldSetter ModifyValue(OptionalUpdateField(Derived::* field));
template
inline MutableFieldReference ModifyValue(OptionalUpdateField(Derived::* field), uint32 /*dummy*/);
template
inline void ClearChangesMask(UpdateField(Derived::* field));
template
inline void ClearChangesMask(OptionalUpdateField(Derived::* field));
uint32 GetChangedObjectTypeMask() const { return _changesMask; }
bool HasChanged(uint32 index) const { return (_changesMask & UpdateMaskHelpers::GetBlockFlag(index)) != 0; }
inline Object* GetOwner();
private:
friend Object;
// This class is tightly tied to Object::m_values member, do not construct elsewhere
UpdateFieldHolder() : _changesMask(0) { }
uint32 _changesMask;
};
template
inline bool SetUpdateFieldValue(UpdateFieldPrivateSetter& setter, typename UpdateFieldPrivateSetter::value_type&& value)
{
return setter.SetValue(std::move(value));
}
template
inline typename DynamicUpdateFieldSetter::insert_result AddDynamicUpdateFieldValue(DynamicUpdateFieldSetter& setter)
{
return setter.AddValue();
}
template
inline typename DynamicUpdateFieldSetter::insert_result InsertDynamicUpdateFieldValue(DynamicUpdateFieldSetter& setter, uint32 index)
{
return setter.InsertValue(index);
}
template
inline void RemoveDynamicUpdateFieldValue(DynamicUpdateFieldSetter& setter, uint32 index)
{
setter.RemoveValue(index);
}
template
inline void ClearDynamicUpdateFieldValues(DynamicUpdateFieldSetter& setter)
{
setter.Clear();
}
template
inline void RemoveOptionalUpdateFieldValue(OptionalUpdateFieldSetter& setter)
{
setter.RemoveValue();
}
}
float const DEFAULT_COLLISION_HEIGHT = 2.03128f; // Most common value in dbc
static constexpr Milliseconds const HEARTBEAT_INTERVAL = 5s + 200ms;
class TC_GAME_API Object
{
public:
virtual ~Object();
bool IsInWorld() const { return m_inWorld; }
virtual void AddToWorld();
virtual void RemoveFromWorld();
static ObjectGuid GetGUID(Object const* o) { return o ? o->GetGUID() : ObjectGuid::Empty; }
ObjectGuid const& GetGUID() const { return m_guid; }
uint32 GetEntry() const { return m_objectData->EntryID; }
void SetEntry(uint32 entry) { SetUpdateFieldValue(m_values.ModifyValue(&Object::m_objectData).ModifyValue(&UF::ObjectData::EntryID), entry); }
float GetObjectScale() const { return m_objectData->Scale; }
virtual void SetObjectScale(float scale) { SetUpdateFieldValue(m_values.ModifyValue(&Object::m_objectData).ModifyValue(&UF::ObjectData::Scale), scale); }
uint32 GetDynamicFlags() const { return m_objectData->DynamicFlags; }
bool HasDynamicFlag(uint32 flag) const { return (*m_objectData->DynamicFlags & flag) != 0; }
void SetDynamicFlag(uint32 flag) { SetUpdateFieldFlagValue(m_values.ModifyValue(&Object::m_objectData).ModifyValue(&UF::ObjectData::DynamicFlags), flag); }
void RemoveDynamicFlag(uint32 flag) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(&Object::m_objectData).ModifyValue(&UF::ObjectData::DynamicFlags), flag); }
void ReplaceAllDynamicFlags(uint32 flag) { SetUpdateFieldValue(m_values.ModifyValue(&Object::m_objectData).ModifyValue(&UF::ObjectData::DynamicFlags), flag); }
TypeID GetTypeId() const { return m_objectTypeId; }
bool isType(uint16 mask) const { return (mask & m_objectType) != 0; }
virtual void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const;
void SendUpdateToPlayer(Player* player);
void BuildValuesUpdateBlockForPlayer(UpdateData* data, Player const* target) const;
void BuildValuesUpdateBlockForPlayerWithFlag(UpdateData* data, UF::UpdateFieldFlag flags, Player const* target) const;
void BuildDestroyUpdateBlock(UpdateData* data) const;
void BuildOutOfRangeUpdateBlock(UpdateData* data) const;
ByteBuffer& PrepareValuesUpdateBuffer(UpdateData* data) const;
virtual void DestroyForPlayer(Player* target) const;
void SendOutOfRangeForPlayer(Player* target) const;
virtual void ClearUpdateMask(bool remove);
virtual std::string GetNameForLocaleIdx(LocaleConstant locale) const = 0;
virtual bool hasQuest(uint32 /* quest_id */) const { return false; }
virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; }
void SetIsNewObject(bool enable) { m_isNewObject = enable; }
bool IsDestroyedObject() const { return m_isDestroyedObject; }
void SetDestroyedObject(bool destroyed) { m_isDestroyedObject = destroyed; }
virtual void BuildUpdate(UpdateDataMapType&) { }
void BuildFieldsUpdate(Player*, UpdateDataMapType &) const;
inline bool IsWorldObject() const { return isType(TYPEMASK_WORLDOBJECT); }
static WorldObject* ToWorldObject(Object* o) { return o ? o->ToWorldObject() : nullptr; }
static WorldObject const* ToWorldObject(Object const* o) { return o ? o->ToWorldObject() : nullptr; }
WorldObject* ToWorldObject() { if (IsWorldObject()) return reinterpret_cast(this); else return nullptr; }
WorldObject const* ToWorldObject() const { if (IsWorldObject()) return reinterpret_cast(this); else return nullptr; }
inline bool IsItem() const { return isType(TYPEMASK_ITEM); }
static Item* ToItem(Object* o) { return o ? o->ToItem() : nullptr; }
static Item const* ToItem(Object const* o) { return o ? o->ToItem() : nullptr; }
Item* ToItem() { if (IsItem()) return reinterpret_cast- (this); else return nullptr; }
Item const* ToItem() const { if (IsItem()) return reinterpret_cast
- (this); else return nullptr; }
inline bool IsPlayer() const { return GetTypeId() == TYPEID_PLAYER; }
static Player* ToPlayer(Object* o) { return o ? o->ToPlayer() : nullptr; }
static Player const* ToPlayer(Object const* o) { return o ? o->ToPlayer() : nullptr; }
Player* ToPlayer() { if (IsPlayer()) return reinterpret_cast(this); else return nullptr; }
Player const* ToPlayer() const { if (IsPlayer()) return reinterpret_cast(this); else return nullptr; }
inline bool IsCreature() const { return GetTypeId() == TYPEID_UNIT; }
static Creature* ToCreature(Object* o) { return o ? o->ToCreature() : nullptr; }
static Creature const* ToCreature(Object const* o) { return o ? o->ToCreature() : nullptr; }
Creature* ToCreature() { if (IsCreature()) return reinterpret_cast(this); else return nullptr; }
Creature const* ToCreature() const { if (IsCreature()) return reinterpret_cast(this); else return nullptr; }
inline bool IsUnit() const { return isType(TYPEMASK_UNIT); }
static Unit* ToUnit(Object* o) { return o ? o->ToUnit() : nullptr; }
static Unit const* ToUnit(Object const* o) { return o ? o->ToUnit() : nullptr; }
Unit* ToUnit() { if (IsUnit()) return reinterpret_cast(this); else return nullptr; }
Unit const* ToUnit() const { if (IsUnit()) return reinterpret_cast(this); else return nullptr; }
inline bool IsGameObject() const { return GetTypeId() == TYPEID_GAMEOBJECT; }
static GameObject* ToGameObject(Object* o) { return o ? o->ToGameObject() : nullptr; }
static GameObject const* ToGameObject(Object const* o) { return o ? o->ToGameObject() : nullptr; }
GameObject* ToGameObject() { if (IsGameObject()) return reinterpret_cast(this); else return nullptr; }
GameObject const* ToGameObject() const { if (IsGameObject()) return reinterpret_cast(this); else return nullptr; }
inline bool IsCorpse() const { return GetTypeId() == TYPEID_CORPSE; }
static Corpse* ToCorpse(Object* o) { return o ? o->ToCorpse() : nullptr; }
static Corpse const* ToCorpse(Object const* o) { return o ? o->ToCorpse() : nullptr; }
Corpse* ToCorpse() { if (IsCorpse()) return reinterpret_cast(this); else return nullptr; }
Corpse const* ToCorpse() const { if (IsCorpse()) return reinterpret_cast(this); else return nullptr; }
inline bool IsDynObject() const { return GetTypeId() == TYPEID_DYNAMICOBJECT; }
static DynamicObject* ToDynObject(Object* o) { return o ? o->ToDynObject() : nullptr; }
static DynamicObject const* ToDynObject(Object const* o) { return o ? o->ToDynObject() : nullptr; }
DynamicObject* ToDynObject() { if (IsDynObject()) return reinterpret_cast(this); else return nullptr; }
DynamicObject const* ToDynObject() const { if (IsDynObject()) return reinterpret_cast(this); else return nullptr; }
inline bool IsAreaTrigger() const { return GetTypeId() == TYPEID_AREATRIGGER; }
static AreaTrigger* ToAreaTrigger(Object* o) { return o ? o->ToAreaTrigger() : nullptr; }
static AreaTrigger const* ToAreaTrigger(Object const* o) { return o ? o->ToAreaTrigger() : nullptr; }
AreaTrigger* ToAreaTrigger() { if (IsAreaTrigger()) return reinterpret_cast(this); else return nullptr; }
AreaTrigger const* ToAreaTrigger() const { if (IsAreaTrigger()) return reinterpret_cast(this); else return nullptr; }
inline bool IsSceneObject() const { return GetTypeId() == TYPEID_SCENEOBJECT; }
static SceneObject* ToSceneObject(Object* o) { return o ? o->ToSceneObject() : nullptr; }
static SceneObject const* ToSceneObject(Object const* o) { return o ? o->ToSceneObject() : nullptr; }
SceneObject* ToSceneObject() { if (IsSceneObject()) return reinterpret_cast(this); else return nullptr; }
SceneObject const* ToSceneObject() const { if (IsSceneObject()) return reinterpret_cast(this); else return nullptr; }
inline bool IsConversation() const { return GetTypeId() == TYPEID_CONVERSATION; }
static Conversation* ToConversation(Object* o) { return o ? o->ToConversation() : nullptr; }
static Conversation const* ToConversation(Object const* o) { return o ? o->ToConversation() : nullptr; }
Conversation* ToConversation() { if (IsConversation()) return reinterpret_cast(this); else return nullptr; }
Conversation const* ToConversation() const { if (IsConversation()) return reinterpret_cast(this); else return nullptr; }
friend UF::UpdateFieldHolder;
UF::UpdateFieldHolder m_values;
UF::UpdateField m_objectData;
template
void ForceUpdateFieldChange(UF::UpdateFieldPrivateSetter const& /*setter*/)
{
AddToObjectUpdateIfNeeded();
}
virtual std::string GetDebugInfo() const;
Trinity::unique_weak_ptr