diff options
Diffstat (limited to 'src/game/Object.h')
-rw-r--r-- | src/game/Object.h | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/src/game/Object.h b/src/game/Object.h new file mode 100644 index 00000000000..c870e9452c9 --- /dev/null +++ b/src/game/Object.h @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECT_H +#define _OBJECT_H + +#include "Common.h" +#include "ByteBuffer.h" +#include "UpdateFields.h" +#include "UpdateData.h" +#include "GameSystem/GridReference.h" +#include "ObjectDefines.h" + +#include <set> +#include <string> + +#define CONTACT_DISTANCE 0.5f +#define INTERACTION_DISTANCE 5 +#define ATTACK_DISTANCE 5 +#define DETECT_DISTANCE 20 // max distance to successful detect stealthed unit +#define MAX_VISIBILITY_DISTANCE (5*SIZE_OF_GRID_CELL/2.0f) // max distance for visible object show, limited by active zone for player based at cell size (active zone = 5x5 cells) +#define DEFAULT_VISIBILITY_DISTANCE (SIZE_OF_GRID_CELL) // default visible distance + +#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects + +enum TypeMask +{ + TYPEMASK_OBJECT = 0x0001, + TYPEMASK_ITEM = 0x0002, + TYPEMASK_CONTAINER = 0x0006, // TYPEMASK_ITEM | 0x0004 + TYPEMASK_UNIT = 0x0008, + TYPEMASK_PLAYER = 0x0010, + TYPEMASK_GAMEOBJECT = 0x0020, + TYPEMASK_DYNAMICOBJECT = 0x0040, + TYPEMASK_CORPSE = 0x0080, + TYPEMASK_AIGROUP = 0x0100, + TYPEMASK_AREATRIGGER = 0x0200 +}; + +enum TypeID +{ + TYPEID_OBJECT = 0, + TYPEID_ITEM = 1, + TYPEID_CONTAINER = 2, + TYPEID_UNIT = 3, + TYPEID_PLAYER = 4, + TYPEID_GAMEOBJECT = 5, + TYPEID_DYNAMICOBJECT = 6, + TYPEID_CORPSE = 7, + TYPEID_AIGROUP = 8, + TYPEID_AREATRIGGER = 9 +}; + +uint32 GuidHigh2TypeId(uint32 guid_hi); + +enum TempSummonType +{ + TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears + TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN = 2, // despawns after a specified time OR when the creature dies + TEMPSUMMON_TIMED_DESPAWN = 3, // despawns after a specified time + TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT = 4, // despawns after a specified time after the creature is out of combat + TEMPSUMMON_CORPSE_DESPAWN = 5, // despawns instantly after death + TEMPSUMMON_CORPSE_TIMED_DESPAWN = 6, // despawns after a specified time after death + TEMPSUMMON_DEAD_DESPAWN = 7, // despawns when the creature disappears + TEMPSUMMON_MANUAL_DESPAWN = 8 // despawns when UnSummon() is called +}; + +class WorldPacket; +class UpdateData; +class ByteBuffer; +class WorldSession; +class Creature; +class Player; +class Map; +class UpdateMask; +class InstanceData; + +typedef HM_NAMESPACE::hash_map<Player*, UpdateData> UpdateDataMapType; + +struct WorldLocation +{ + uint32 mapid; + float x; + float y; + float z; + float o; + explicit WorldLocation(uint32 mapid = 0, float x = 0, float y = 0, float z = 0, float o = 0) + : mapid(mapid), x(x), y(y), z(z), o(o) {} + WorldLocation(WorldLocation const &loc) + : mapid(loc.mapid), x(loc.x), y(loc.y), z(loc.z), o(loc.o) {} +}; + +class MANGOS_DLL_SPEC Object +{ + public: + virtual ~Object ( ); + + const bool& IsInWorld() const { return m_inWorld; } + virtual void AddToWorld() + { + if(m_inWorld) + return; + + m_inWorld = true; + + // synchronize values mirror with values array (changes will send in updatecreate opcode any way + ClearUpdateMask(true); + } + virtual void RemoveFromWorld() + { + // if we remove from world then sending changes not required + if(m_uint32Values) + ClearUpdateMask(true); + m_inWorld = false; + } + + const uint64& GetGUID() const { return GetUInt64Value(0); } + uint32 GetGUIDLow() const { return GUID_LOPART(GetUInt64Value(0)); } + uint32 GetGUIDMid() const { return GUID_ENPART(GetUInt64Value(0)); } + uint32 GetGUIDHigh() const { return GUID_HIPART(GetUInt64Value(0)); } + const ByteBuffer& GetPackGUID() const { return m_PackGUID; } + uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } + + uint8 GetTypeId() const { return m_objectTypeId; } + bool isType(uint16 mask) const { return (mask & m_objectType); } + + virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const; + void SendUpdateToPlayer(Player* player); + + void BuildValuesUpdateBlockForPlayer( UpdateData *data, Player *target ) const; + void BuildOutOfRangeUpdateBlock( UpdateData *data ) const; + void BuildMovementUpdateBlock( UpdateData * data, uint32 flags = 0 ) const; + void BuildUpdate(UpdateDataMapType &); + + virtual void DestroyForPlayer( Player *target ) const; + + const int32& GetInt32Value( uint16 index ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + return m_int32Values[ index ]; + } + + const uint32& GetUInt32Value( uint16 index ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + return m_uint32Values[ index ]; + } + + const uint64& GetUInt64Value( uint16 index ) const + { + ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , false) ); + return *((uint64*)&(m_uint32Values[ index ])); + } + + const float& GetFloatValue( uint16 index ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); + return m_floatValues[ index ]; + } + + uint8 GetByteValue( uint16 index, uint8 offset) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + ASSERT( offset < 4 ); + return *(((uint8*)&m_uint32Values[ index ])+offset); + } + + uint8 GetUInt16Value( uint16 index, uint8 offset) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false) ); + ASSERT( offset < 2 ); + return *(((uint16*)&m_uint32Values[ index ])+offset); + } + + void SetInt32Value( uint16 index, int32 value ); + void SetUInt32Value( uint16 index, uint32 value ); + void SetUInt64Value( uint16 index, const uint64 &value ); + void SetFloatValue( uint16 index, float value ); + void SetByteValue( uint16 index, uint8 offset, uint8 value ); + void SetUInt16Value( uint16 index, uint8 offset, uint16 value ); + void SetInt16Value( uint16 index, uint8 offset, int16 value ) { SetUInt16Value(index,offset,(uint16)value); } + void SetStatFloatValue( uint16 index, float value); + void SetStatInt32Value( uint16 index, int32 value); + + void ApplyModUInt32Value(uint16 index, int32 val, bool apply); + void ApplyModInt32Value(uint16 index, int32 val, bool apply); + void ApplyModUInt64Value(uint16 index, int32 val, bool apply); + void ApplyModPositiveFloatValue( uint16 index, float val, bool apply); + void ApplyModSignedFloatValue( uint16 index, float val, bool apply); + + void ApplyPercentModFloatValue(uint16 index, float val, bool apply) + { + val = val != -100.0f ? val : -99.9f ; + SetFloatValue(index, GetFloatValue(index) * (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val)) ); + } + + void SetFlag( uint16 index, uint32 newFlag ); + void RemoveFlag( uint16 index, uint32 oldFlag ); + + void ToggleFlag( uint16 index, uint32 flag) + { + if(HasFlag(index, flag)) + RemoveFlag(index, flag); + else + SetFlag(index, flag); + } + + bool HasFlag( uint16 index, uint32 flag ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); + return (m_uint32Values[ index ] & flag) != 0; + } + + void ApplyModFlag( uint16 index, uint32 flag, bool apply) + { + if(apply) SetFlag(index,flag); else RemoveFlag(index,flag); + } + + void SetFlag64( uint16 index, uint64 newFlag ) + { + uint64 oldval = GetUInt64Value(index); + uint64 newval = oldval | newFlag; + SetUInt64Value(index,newval); + } + + void RemoveFlag64( uint16 index, uint64 oldFlag ) + { + uint64 oldval = GetUInt64Value(index); + uint64 newval = oldval & ~oldFlag; + SetUInt64Value(index,newval); + } + + void ToggleFlag64( uint16 index, uint64 flag) + { + if(HasFlag64(index, flag)) + RemoveFlag64(index, flag); + else + SetFlag64(index, flag); + } + + bool HasFlag64( uint16 index, uint64 flag ) const + { + ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); + return (GetUInt64Value( index ) & flag) != 0; + } + + void ApplyModFlag64( uint16 index, uint64 flag, bool apply) + { + if(apply) SetFlag64(index,flag); else RemoveFlag64(index,flag); + } + + void ClearUpdateMask(bool remove); + void SendUpdateObjectToAllExcept(Player* exceptPlayer); + + bool LoadValues(const char* data); + + uint16 GetValuesCount() const { return m_valuesCount; } + + void InitValues() { _InitValues(); } + + virtual bool hasQuest(uint32 /* quest_id */) const { return false; } + virtual bool hasInvolvedQuest(uint32 /* quest_id */) const { return false; } + protected: + + Object ( ); + + void _InitValues(); + void _Create (uint32 guidlow, uint32 entry, HighGuid guidhigh); + + virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; + + virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const; + void _BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const; + void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + + uint16 m_objectType; + + uint8 m_objectTypeId; + uint8 m_updateFlag; + + union + { + int32 *m_int32Values; + uint32 *m_uint32Values; + float *m_floatValues; + }; + + uint32 *m_uint32Values_mirror; + + uint16 m_valuesCount; + + bool m_objectUpdated; + + private: + bool m_inWorld; + + ByteBuffer m_PackGUID; + + // for output helpfull error messages from asserts + bool PrintIndexError(uint32 index, bool set) const; + Object(const Object&); // prevent generation copy constructor + Object& operator=(Object const&); // prevent generation assigment operator +}; + +class MANGOS_DLL_SPEC WorldObject : public Object +{ + public: + virtual ~WorldObject ( ) {} + + virtual void Update ( uint32 /*time_diff*/ ) { } + + void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid ); + + void Relocate(float x, float y, float z, float orientation) + { + m_positionX = x; + m_positionY = y; + m_positionZ = z; + m_orientation = orientation; + } + + void Relocate(float x, float y, float z) + { + m_positionX = x; + m_positionY = y; + m_positionZ = z; + } + + void Relocate(WorldLocation const & loc) + { + SetMapId(loc.mapid); + Relocate(loc.x, loc.y, loc.z, loc.o); + } + + void SetOrientation(float orientation) { m_orientation = orientation; } + + float GetPositionX( ) const { return m_positionX; } + float GetPositionY( ) const { return m_positionY; } + float GetPositionZ( ) const { return m_positionZ; } + void GetPosition( float &x, float &y, float &z ) const + { x = m_positionX; y = m_positionY; z = m_positionZ; } + void GetPosition( WorldLocation &loc ) const + { loc.mapid = GetMapId(); GetPosition(loc.x, loc.y, loc.z); loc.o = GetOrientation(); } + float GetOrientation( ) const { return m_orientation; } + void GetNearPoint2D( float &x, float &y, float distance, float absAngle) const; + void GetNearPoint( WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d,float absAngle) const; + void GetClosePoint(float &x, float &y, float &z, float size, float distance2d = 0, float angle = 0) const + { + // angle calculated from current orientation + GetNearPoint(NULL,x,y,z,size,distance2d,GetOrientation() + angle); + } + void GetContactPoint( const WorldObject* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const + { + // angle to face `obj` to `this` using distance includes size of `obj` + GetNearPoint(obj,x,y,z,obj->GetObjectSize(),distance2d,GetAngle( obj )); + } + + float GetObjectSize() const + { + return ( m_valuesCount > UNIT_FIELD_BOUNDINGRADIUS ) ? m_floatValues[UNIT_FIELD_BOUNDINGRADIUS] : DEFAULT_WORLD_OBJECT_SIZE; + } + bool IsPositionValid() const; + void UpdateGroundPositionZ(float x, float y, float &z) const; + + void GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z ) const; + + void SetMapId(uint32 newMap) { m_mapId = newMap; } + + uint32 GetMapId() const { return m_mapId; } + + uint32 GetZoneId() const; + uint32 GetAreaId() const; + + InstanceData* GetInstanceData(); + + const char* GetName() const { return m_name.c_str(); } + void SetName(std::string newname) { m_name=newname; } + + float GetDistance( const WorldObject* obj ) const; + float GetDistance(const float x, const float y, const float z) const; + float GetDistance2d(const WorldObject* obj) const; + float GetDistance2d(const float x, const float y) const; + float GetDistanceZ(const WorldObject* obj) const; + bool IsInMap(const WorldObject* obj) const { return GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId(); } + bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare) const; + bool IsWithinLOS(const float x, const float y, const float z ) const; + bool IsWithinLOSInMap(const WorldObject* obj) const; + + float GetAngle( const WorldObject* obj ) const; + float GetAngle( const float x, const float y ) const; + bool HasInArc( const float arcangle, const WorldObject* obj ) const; + + virtual void SendMessageToSet(WorldPacket *data, bool self); + virtual void SendMessageToSetInRange(WorldPacket *data, float dist, bool self); + void BuildHeartBeatMsg( WorldPacket *data ) const; + void BuildTeleportAckMsg( WorldPacket *data, float x, float y, float z, float ang) const; + bool IsBeingTeleported() { return mSemaphoreTeleport; } + void SetSemaphoreTeleport(bool semphsetting) { mSemaphoreTeleport = semphsetting; } + + void MonsterSay(const char* text, uint32 language, uint64 TargetGuid); + void MonsterYell(const char* text, uint32 language, uint64 TargetGuid); + void MonsterTextEmote(const char* text, uint64 TargetGuid, bool IsBossEmote = false); + void MonsterWhisper(const char* text, uint64 receiver, bool IsBossWhisper = false); + void MonsterSay(int32 textId, uint32 language, uint64 TargetGuid); + void MonsterYell(int32 textId, uint32 language, uint64 TargetGuid); + void MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote = false); + void MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper = false); + void BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const* text, uint32 language, char const* name, uint64 TargetGuid) const; + + void SendObjectDeSpawnAnim(uint64 guid); + + virtual void SaveRespawnTime() {} + + uint32 GetInstanceId() const { return m_InstanceId; } + void SetInstanceId(uint32 val) { m_InstanceId = val; } + + void AddObjectToRemoveList(); + + // main visibility check function in normal case (ignore grey zone distance check) + bool isVisibleFor(Player const* u) const { return isVisibleForInState(u,false); } + + // low level function for visibility change code, must be define in all main world object subclasses + virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0; + + Map * GetMap() const; + Map const* GetBaseMap() const; + Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); + + protected: + explicit WorldObject(); + std::string m_name; + + private: + uint32 m_mapId; + + float m_positionX; + float m_positionY; + float m_positionZ; + float m_orientation; + + bool mSemaphoreTeleport; + + uint32 m_InstanceId; +}; +#endif |