aboutsummaryrefslogtreecommitdiff
path: root/src/game/Object.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/Object.cpp')
-rw-r--r--src/game/Object.cpp1318
1 files changed, 870 insertions, 448 deletions
diff --git a/src/game/Object.cpp b/src/game/Object.cpp
index 04f6646bea1..3561621f0bd 100644
--- a/src/game/Object.cpp
+++ b/src/game/Object.cpp
@@ -27,8 +27,8 @@
#include "Object.h"
#include "Creature.h"
#include "Player.h"
+#include "Vehicle.h"
#include "ObjectMgr.h"
-#include "WorldSession.h"
#include "UpdateData.h"
#include "UpdateMask.h"
#include "Util.h"
@@ -44,6 +44,8 @@
#include "GridNotifiersImpl.h"
#include "TemporarySummon.h"
+#include "Totem.h"
+#include "OutdoorPvPMgr.h"
uint32 GuidHigh2TypeId(uint32 guid_hi)
{
@@ -58,11 +60,12 @@ uint32 GuidHigh2TypeId(uint32 guid_hi)
case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT;
case HIGHGUID_CORPSE: return TYPEID_CORPSE;
case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT;
+ case HIGHGUID_VEHICLE: return TYPEID_UNIT;
}
- return 10; // unknown
+ return NUM_CLIENT_OBJECT_TYPES; // unknown
}
-Object::Object( )
+Object::Object( ) : m_PackGUID(sizeof(uint64)+1)
{
m_objectTypeId = TYPEID_OBJECT;
m_objectType = TYPEMASK_OBJECT;
@@ -74,31 +77,32 @@ Object::Object( )
m_inWorld = false;
m_objectUpdated = false;
- m_PackGUID.clear();
m_PackGUID.appendPackGUID(0);
}
Object::~Object( )
{
- //if(m_objectUpdated)
- // ObjectAccessor::Instance().RemoveUpdateObject(this);
-
- if(m_uint32Values)
+ if(IsInWorld())
{
- if(IsInWorld())
- {
- ///- Do NOT call RemoveFromWorld here, if the object is a player it will crash
- sLog.outError("Object::~Object - guid="I64FMTD", typeid=%d deleted but still in world!!", GetGUID(), GetTypeId());
- assert(false);
- }
+ sLog.outCrash("Object::~Object - guid="UI64FMTD", typeid=%d, entry=%u deleted but still in world!!", GetGUID(), GetTypeId(), GetEntry());
+ if(isType(TYPEMASK_ITEM))
+ sLog.outCrash("Item slot %u", ((Item*)this)->GetSlot());
+ assert(false);
+ RemoveFromWorld();
+ }
- assert(!m_objectUpdated);
+ if(m_objectUpdated)
+ {
+ sLog.outCrash("Object::~Object - guid="UI64FMTD", typeid=%d, entry=%u deleted but still in update list!!", GetGUID(), GetTypeId(), GetEntry());
+ assert(false);
+ ObjectAccessor::Instance().RemoveUpdateObject(this);
+ }
+ if(m_uint32Values)
+ {
//DEBUG_LOG("Object desctr 1 check (%p)",(void*)this);
delete [] m_uint32Values;
delete [] m_uint32Values_mirror;
- m_uint32Values = NULL;
- m_uint32Values_mirror = NULL;
//DEBUG_LOG("Object desctr 2 check (%p)",(void*)this);
}
}
@@ -118,10 +122,23 @@ void Object::_Create( uint32 guidlow, uint32 entry, HighGuid guidhigh )
{
if(!m_uint32Values) _InitValues();
- uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh); // required more changes to make it working
+ uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh);
SetUInt64Value( OBJECT_FIELD_GUID, guid );
- SetUInt32Value( OBJECT_FIELD_TYPE, m_objectType );
- m_PackGUID.clear();
+ uint32 type = 0;
+ switch(m_objectType)
+ {
+ //case TYPEID_ITEM: type = 3; break;
+ //case TYPEID_CONTAINER: type = 7; break; //+4
+ //case TYPEID_UNIT: type = 9; break; //+2
+ //case TYPEID_PLAYER: type = 25; break; //+16
+ //case TYPEID_GAMEOBJECT: type = 33; break; //+8
+ case TYPEID_DYNAMICOBJECT: type = 65; break; //+32
+ //case TYPEID_CORPSE: type = 129; break; //+64
+ default: type = m_objectType; break;
+ }
+ SetUInt32Value( OBJECT_FIELD_TYPE, type );
+ //SetUInt32Value( OBJECT_FIELD_TYPE, m_objectType );
+ m_PackGUID.wpos(0);
m_PackGUID.appendPackGUID(GetGUID());
}
@@ -130,9 +147,9 @@ void Object::BuildMovementUpdateBlock(UpdateData * data, uint32 flags ) const
ByteBuffer buf(500);
buf << uint8( UPDATETYPE_MOVEMENT );
- buf << GetGUID();
+ buf.append(GetPackGUID());
- _BuildMovementUpdate(&buf, flags, 0x00000000);
+ _BuildMovementUpdate(&buf, flags);
data->AddUpdateBlock(buf);
}
@@ -140,19 +157,16 @@ void Object::BuildMovementUpdateBlock(UpdateData * data, uint32 flags ) const
void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
{
if(!target)
- {
return;
- }
uint8 updatetype = UPDATETYPE_CREATE_OBJECT;
- uint8 flags = m_updateFlag;
- uint32 flags2 = 0;
+ uint16 flags = m_updateFlag;
/** lower flag1 **/
- if(target == this) // building packet for oneself
+ if(target == this) // building packet for yourself
flags |= UPDATEFLAG_SELF;
- if(flags & UPDATEFLAG_HASPOSITION)
+ if(flags & UPDATEFLAG_HAS_POSITION)
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
if(isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER))
@@ -176,24 +190,31 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c
case GAMEOBJECT_TYPE_TRANSPORT:
flags |= UPDATEFLAG_TRANSPORT;
break;
+ default:
+ break;
}
}
+
+ if(isType(TYPEMASK_UNIT))
+ {
+ if(((Unit*)this)->getVictim())
+ flags |= UPDATEFLAG_HAS_TARGET;
+ }
}
//sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2);
ByteBuffer buf(500);
buf << (uint8)updatetype;
- //buf.append(GetPackGUID()); //client crashes when using this
- buf << (uint8)0xFF << GetGUID();
+ buf.append(GetPackGUID());
buf << (uint8)m_objectTypeId;
- _BuildMovementUpdate(&buf, flags, flags2);
+ _BuildMovementUpdate(&buf, flags);
UpdateMask updateMask;
updateMask.SetCount( m_valuesCount );
_SetCreateBits( &updateMask, target );
- _BuildValuesUpdate(updatetype, &buf, &updateMask, target );
+ _BuildValuesUpdate(updatetype, &buf, &updateMask, target);
data->AddUpdateBlock(buf);
}
@@ -215,8 +236,6 @@ void Object::SendUpdateToPlayer(Player* player)
BuildCreateUpdateBlockForPlayer(&upd, player);
upd.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet);
-
- // now object updated/(create updated)
}
void Object::BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) const
@@ -224,15 +243,13 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) c
ByteBuffer buf(500);
buf << (uint8) UPDATETYPE_VALUES;
- //buf.append(GetPackGUID()); //client crashes when using this. but not have crash in debug mode
- buf << (uint8)0xFF;
- buf << GetGUID();
+ buf.append(GetPackGUID());
UpdateMask updateMask;
updateMask.SetCount( m_valuesCount );
_SetUpdateBits( &updateMask, target );
- _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target );
+ _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target);
data->AddUpdateBlock(buf);
}
@@ -247,131 +264,19 @@ void Object::DestroyForPlayer(Player *target) const
ASSERT(target);
WorldPacket data(SMSG_DESTROY_OBJECT, 8);
- data << GetGUID();
+ data << uint64(GetGUID());
+ data << uint8(0); // WotLK (bool)
target->GetSession()->SendPacket( &data );
}
-void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const
+void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags) const
{
- *data << (uint8)flags; // update flags
+ *data << (uint16)flags; // update flags
// 0x20
if (flags & UPDATEFLAG_LIVING)
{
- switch(GetTypeId())
- {
- case TYPEID_UNIT:
- {
- flags2 = ((Unit*)this)->GetUnitMovementFlags();
- flags2 &= ~MOVEMENTFLAG_ONTRANSPORT;
- flags2 &= ~MOVEMENTFLAG_SPLINE2;
- }
- break;
- case TYPEID_PLAYER:
- {
- flags2 = ((Player*)this)->GetUnitMovementFlags();
-
- if(((Player*)this)->GetTransport())
- flags2 |= MOVEMENTFLAG_ONTRANSPORT;
- else
- flags2 &= ~MOVEMENTFLAG_ONTRANSPORT;
-
- // remove unknown, unused etc flags for now
- flags2 &= ~MOVEMENTFLAG_SPLINE2; // will be set manually
-
- if(((Player*)this)->isInFlight())
- {
- WPAssert(((Player*)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
- flags2 = (MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_SPLINE2);
- }
- }
- break;
- }
-
- *data << uint32(flags2); // movement flags
- *data << uint8(0); // unk 2.3.0
- *data << uint32(getMSTime()); // time (in milliseconds)
- }
-
- // 0x40
- if (flags & UPDATEFLAG_HASPOSITION)
- {
- // 0x02
- if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT)
- {
- *data << (float)0;
- *data << (float)0;
- *data << (float)0;
- *data << ((WorldObject *)this)->GetOrientation();
- }
- else
- {
- *data << ((WorldObject *)this)->GetPositionX();
- *data << ((WorldObject *)this)->GetPositionY();
- *data << ((WorldObject *)this)->GetPositionZ();
- *data << ((WorldObject *)this)->GetOrientation();
- }
- }
-
- // 0x20
- if(flags & UPDATEFLAG_LIVING)
- {
- // 0x00000200
- if(flags2 & MOVEMENTFLAG_ONTRANSPORT)
- {
- if(GetTypeId() == TYPEID_PLAYER)
- {
- *data << (uint64)((Player*)this)->GetTransport()->GetGUID();
- *data << (float)((Player*)this)->GetTransOffsetX();
- *data << (float)((Player*)this)->GetTransOffsetY();
- *data << (float)((Player*)this)->GetTransOffsetZ();
- *data << (float)((Player*)this)->GetTransOffsetO();
- *data << (uint32)((Player*)this)->GetTransTime();
- }
- //TrinIty currently not have support for other than player on transport
- }
-
- // 0x02200000
- if(flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
- {
- if(GetTypeId() == TYPEID_PLAYER)
- *data << (float)((Player*)this)->m_movementInfo.s_pitch;
- else
- *data << (float)0; // is't part of movement packet, we must store and send it...
- }
-
- if(GetTypeId() == TYPEID_PLAYER)
- *data << (uint32)((Player*)this)->m_movementInfo.fallTime;
- else
- *data << (uint32)0; // last fall time
-
- // 0x00001000
- if(flags2 & MOVEMENTFLAG_JUMPING)
- {
- if(GetTypeId() == TYPEID_PLAYER)
- {
- *data << (float)((Player*)this)->m_movementInfo.j_unk;
- *data << (float)((Player*)this)->m_movementInfo.j_sinAngle;
- *data << (float)((Player*)this)->m_movementInfo.j_cosAngle;
- *data << (float)((Player*)this)->m_movementInfo.j_xyspeed;
- }
- else
- {
- *data << (float)0;
- *data << (float)0;
- *data << (float)0;
- *data << (float)0;
- }
- }
-
- // 0x04000000
- if(flags2 & MOVEMENTFLAG_SPLINE)
- {
- if(GetTypeId() == TYPEID_PLAYER)
- *data << (float)((Player*)this)->m_movementInfo.u_unk1;
- else
- *data << (float)0;
- }
+ ((Unit*)this)->BuildMovementPacket(data);
*data << ((Unit*)this)->GetSpeed( MOVE_WALK );
*data << ((Unit*)this)->GetSpeed( MOVE_RUN );
@@ -381,45 +286,36 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
*data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT );
*data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT_BACK );
*data << ((Unit*)this)->GetSpeed( MOVE_TURN_RATE );
+ *data << ((Unit*)this)->GetSpeed( MOVE_PITCH_RATE );
// 0x08000000
- if(flags2 & MOVEMENTFLAG_SPLINE2)
+ if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->isInFlight())
{
- if(GetTypeId() != TYPEID_PLAYER)
- {
- sLog.outDebug("_BuildMovementUpdate: MOVEMENTFLAG_SPLINE2 for non-player");
- return;
- }
-
- if(!((Player*)this)->isInFlight())
- {
- sLog.outDebug("_BuildMovementUpdate: MOVEMENTFLAG_SPLINE2 but not in flight");
- return;
- }
-
WPAssert(((Player*)this)->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
FlightPathMovementGenerator *fmg = (FlightPathMovementGenerator*)(((Player*)this)->GetMotionMaster()->top());
- uint32 flags3 = 0x00000300;
+ uint32 flags3 = MOVEFLAG_GLIDE;
*data << uint32(flags3); // splines flag?
- if(flags3 & 0x10000) // probably x,y,z coords there
+ if(flags3 & 0x20000) // may be orientation
{
*data << (float)0;
- *data << (float)0;
- *data << (float)0;
}
-
- if(flags3 & 0x20000) // probably guid there
+ else
{
- *data << uint64(0);
- }
+ if(flags3 & 0x8000) // probably x,y,z coords there
+ {
+ *data << (float)0;
+ *data << (float)0;
+ *data << (float)0;
+ }
- if(flags3 & 0x40000) // may be orientation
- {
- *data << (float)0;
+ if(flags3 & 0x10000) // probably guid there
+ {
+ *data << uint64(0);
+ }
}
Path &path = fmg->GetPath();
@@ -434,8 +330,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
*data << uint32(traveltime); // full move time?
*data << uint32(0); // ticks count?
- uint32 poscount = uint32(path.Size());
+ *data << float(0); // added in 3.1
+ *data << float(0); // added in 3.1
+ *data << float(0); // added in 3.1
+
+ *data << uint32(0); // added in 3.1
+ uint32 poscount = uint32(path.Size());
*data << uint32(poscount); // points count
for(uint32 i = 0; i < poscount; ++i)
@@ -445,22 +346,52 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
*data << path.GetNodes()[i].z;
}
- /*for(uint32 i = 0; i < poscount; i++)
- {
- // path points
- *data << (float)0;
- *data << (float)0;
- *data << (float)0;
- }*/
+ *data << uint8(0); // added in 3.0.8
*data << path.GetNodes()[poscount-1].x;
*data << path.GetNodes()[poscount-1].y;
*data << path.GetNodes()[poscount-1].z;
-
- // target position (path end)
- /**data << ((Unit*)this)->GetPositionX();
- *data << ((Unit*)this)->GetPositionY();
- *data << ((Unit*)this)->GetPositionZ();*/
+ }
+ }
+ else
+ {
+ if(flags & UPDATEFLAG_POSITION)
+ {
+ *data << uint8(0); // unk PGUID!
+ *data << ((WorldObject*)this)->GetPositionX();
+ *data << ((WorldObject*)this)->GetPositionY();
+ *data << ((WorldObject*)this)->GetPositionZ();
+ *data << ((WorldObject*)this)->GetPositionX();
+ *data << ((WorldObject*)this)->GetPositionY();
+ *data << ((WorldObject*)this)->GetPositionZ();
+ *data << ((WorldObject*)this)->GetOrientation();
+
+ if(GetTypeId() == TYPEID_CORPSE)
+ *data << float(((WorldObject*)this)->GetOrientation());
+ else
+ *data << float(0);
+ }
+ else
+ {
+ // 0x40
+ if (flags & UPDATEFLAG_HAS_POSITION)
+ {
+ // 0x02
+ if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT)
+ {
+ *data << (float)0;
+ *data << (float)0;
+ *data << (float)0;
+ *data << ((WorldObject *)this)->GetOrientation();
+ }
+ else
+ {
+ *data << ((WorldObject *)this)->GetPositionX();
+ *data << ((WorldObject *)this)->GetPositionY();
+ *data << ((WorldObject *)this)->GetPositionZ();
+ *data << ((WorldObject *)this)->GetOrientation();
+ }
+ }
}
}
@@ -482,7 +413,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
break;
case TYPEID_PLAYER:
if(flags & UPDATEFLAG_SELF)
- *data << uint32(0x00000015); // unk, can be 0x15 or 0x22
+ *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22
else
*data << uint32(0x00000008); // unk, can be 0x7 or 0x8
break;
@@ -495,26 +426,17 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
// 0x10
if(flags & UPDATEFLAG_HIGHGUID)
{
- switch(GetTypeId())
- {
- case TYPEID_OBJECT:
- case TYPEID_ITEM:
- case TYPEID_CONTAINER:
- case TYPEID_GAMEOBJECT:
- case TYPEID_DYNAMICOBJECT:
- case TYPEID_CORPSE:
- *data << uint32(GetGUIDHigh()); // GetGUIDHigh()
- break;
- default:
- *data << uint32(0x00000000); // unk
- break;
- }
+ // not high guid
+ *data << uint32(0x00000000); // unk
}
// 0x4
- if(flags & UPDATEFLAG_FULLGUID)
+ if(flags & UPDATEFLAG_HAS_TARGET) // packed guid (current target guid)
{
- *data << uint8(0); // packed guid (probably target guid)
+ if(Unit *victim = ((Unit*)this)->getVictim())
+ data->append(victim->GetPackGUID());
+ else
+ *data << uint8(0);
}
// 0x2
@@ -522,6 +444,19 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2
{
*data << uint32(getMSTime()); // ms time
}
+
+ // 0x80
+ if(flags & UPDATEFLAG_VEHICLE) // unused for now
+ {
+ *data << uint32(((Vehicle*)this)->GetVehicleInfo()->m_ID); // vehicle id
+ *data << float(0); // facing adjustment
+ }
+
+ // 0x200
+ if(flags & UPDATEFLAG_ROTATION)
+ {
+ *data << uint64(((GameObject*)this)->GetRotation());
+ }
}
void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const
@@ -537,13 +472,13 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
{
IsActivateToQuest = true;
- updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
+ updateMask->SetBit(GAMEOBJECT_DYNAMIC);
}
- if (GetUInt32Value(GAMEOBJECT_ARTKIT))
- updateMask->SetBit(GAMEOBJECT_ARTKIT);
+ if (((GameObject*)this)->GetGoArtKit())
+ updateMask->SetBit(GAMEOBJECT_BYTES_1);
}
}
- else //case UPDATETYPE_VALUES
+ else // case UPDATETYPE_VALUES
{
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
{
@@ -551,8 +486,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
{
IsActivateToQuest = true;
}
- updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
- updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS);
+ updateMask->SetBit(GAMEOBJECT_DYNAMIC);
+ updateMask->SetBit(GAMEOBJECT_BYTES_1);
}
}
@@ -564,13 +499,20 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
// 2 specialized loops for speed optimization in non-unit case
if(isType(TYPEMASK_UNIT)) // unit (creature/player) case
{
- for( uint16 index = 0; index < m_valuesCount; index ++ )
+ for( uint16 index = 0; index < m_valuesCount; ++index )
{
if( updateMask->GetBit( index ) )
{
- // remove custom flag before send
if( index == UNIT_NPC_FLAGS )
- *data << uint32(m_uint32Values[ index ] & ~(UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP));
+ {
+ // remove custom flag before sending
+ uint32 appendValue = m_uint32Values[ index ] & ~(UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP);
+
+ if (GetTypeId() == TYPEID_UNIT && !target->canSeeSpellClickOn((Creature*)this))
+ appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK;
+
+ *data << uint32(appendValue);
+ }
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
else if(index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
{
@@ -578,83 +520,93 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
*data << uint32(m_floatValues[ index ] < 0 ? 0 : m_floatValues[ index ]);
}
// there are some float values which may be negative or can't get negative due to other checks
- else if(index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4 ||
- index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6) ||
- index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6) ||
- index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4)
+ else if ((index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4) ||
+ (index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6)) ||
+ (index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= (UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6)) ||
+ (index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4))
{
*data << uint32(m_floatValues[ index ]);
}
// Gamemasters should be always able to select units - remove not selectable flag
- else if(index == UNIT_FIELD_FLAGS && target->isGameMaster())
+ else if(index == UNIT_FIELD_FLAGS)
{
- *data << (m_uint32Values[ index ] & ~UNIT_FLAG_NOT_SELECTABLE);
+ if(target->isGameMaster())
+ *data << (m_uint32Values[ index ] & ~UNIT_FLAG_NOT_SELECTABLE);
+ else
+ *data << m_uint32Values[ index ];
}
// use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
- else if(index == UNIT_FIELD_DISPLAYID && GetTypeId() == TYPEID_UNIT)
+ else if(index == UNIT_FIELD_DISPLAYID)
{
- const CreatureInfo* cinfo = ((Creature*)this)->GetCreatureInfo();
- if(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
+ if(GetTypeId() == TYPEID_UNIT)
{
- if(target->isGameMaster())
+ const CreatureInfo* cinfo = ((Creature*)this)->GetCreatureInfo();
+ if(cinfo->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER)
{
- if(cinfo->Modelid_A2)
- *data << cinfo->Modelid_A1;
+ if(target->isGameMaster())
+ {
+ if(cinfo->DisplayID_A[0])
+ *data << cinfo->DisplayID_A[0];
+ else
+ *data << 17519; // world invisible trigger's model
+ }
else
- *data << 17519; // world invisible trigger's model
+ {
+ if(cinfo->DisplayID_A[1])
+ *data << cinfo->DisplayID_A[1];
+ else
+ *data << 11686; // world invisible trigger's model
+ }
}
else
- {
- if(cinfo->Modelid_A2)
- *data << cinfo->Modelid_A2;
- else
- *data << 11686; // world invisible trigger's model
- }
+ *data << m_uint32Values[ index ];
}
else
*data << m_uint32Values[ index ];
}
// hide lootable animation for unallowed players
- else if(index == UNIT_DYNAMIC_FLAGS && GetTypeId() == TYPEID_UNIT)
+ else if(index == UNIT_DYNAMIC_FLAGS)
{
- if(!target->isAllowedToLoot((Creature*)this))
- *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_LOOTABLE);
+ if(GetTypeId() == TYPEID_UNIT)
+ {
+ if(!target->isAllowedToLoot((Creature*)this))
+ *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_LOOTABLE);
+ else
+ *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_OTHER_TAGGER);
+ }
else
- *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_OTHER_TAGGER);
+ *data << m_uint32Values[ index ];
}
// FG: pretend that OTHER players in own group are friendly ("blue")
else if(index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE)
{
- bool ch = false;
- if(target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER && target != this)
+ if(((Unit*)this)->IsControlledByPlayer() && target != this && sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && ((Unit*)this)->IsInRaidWith(target))
{
- if(target->IsInSameGroupWith((Player*)this) || target->IsInSameRaidWith((Player*)this))
- {
- if(index == UNIT_FIELD_BYTES_2)
+ FactionTemplateEntry const *ft1, *ft2;
+ ft1 = ((Unit*)this)->getFactionTemplateEntry();
+ ft2 = target->getFactionTemplateEntry();
+ if(ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
{
- DEBUG_LOG("-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (flag)", target->GetName(), ((Player*)this)->GetName());
- *data << ( m_uint32Values[ index ] & ((UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5) << 8) ); // this flag is at uint8 offset 1 !!
-
- ch = true;
- }
- else if(index == UNIT_FIELD_FACTIONTEMPLATE)
- {
- FactionTemplateEntry const *ft1, *ft2;
- ft1 = ((Player*)this)->getFactionTemplateEntry();
- ft2 = ((Player*)target)->getFactionTemplateEntry();
- if(ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
+ if(index == UNIT_FIELD_BYTES_2)
+ {
+ // Allow targetting opposite faction in party when enabled in config
+ DEBUG_LOG("-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (flag)", target->GetName(), ((Player*)this)->GetName());
+ *data << ( m_uint32Values[ index ] & ((UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/) << 8) ); // this flag is at uint8 offset 1 !!
+ }
+ else
{
- uint32 faction = ((Player*)target)->getFaction(); // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
+ // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
+ uint32 faction = target->getFaction();
DEBUG_LOG("-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (faction %u)", target->GetName(), ((Player*)this)->GetName(), faction);
*data << uint32(faction);
- ch = true;
}
}
+ else
+ *data << m_uint32Values[ index ];
}
- }
- if(!ch)
+ else
*data << m_uint32Values[ index ];
- }
+ }
else
{
// send in current format (float as float, uint32 as uint32)
@@ -665,12 +617,12 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
}
else if(isType(TYPEMASK_GAMEOBJECT)) // gameobject case
{
- for( uint16 index = 0; index < m_valuesCount; index ++ )
+ for( uint16 index = 0; index < m_valuesCount; ++index )
{
if( updateMask->GetBit( index ) )
{
// send in current format (float as float, uint32 as uint32)
- if ( index == GAMEOBJECT_DYN_FLAGS )
+ if (index == GAMEOBJECT_DYNAMIC )
{
if(IsActivateToQuest )
{
@@ -683,7 +635,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
*data << uint32(1);
break;
default:
- *data << uint32(0); // unknown. not happen.
+ *data << uint32(0); // unknown, not happen.
break;
}
}
@@ -697,7 +649,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
}
else // other objects case (no special index checks)
{
- for( uint16 index = 0; index < m_valuesCount; index ++ )
+ for( uint16 index = 0; index < m_valuesCount; ++index )
{
if( updateMask->GetBit( index ) )
{
@@ -710,11 +662,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask
void Object::ClearUpdateMask(bool remove)
{
- for( uint16 index = 0; index < m_valuesCount; index ++ )
- {
- if(m_uint32Values_mirror[index]!= m_uint32Values[index])
- m_uint32Values_mirror[index] = m_uint32Values[index];
- }
+ memcpy(m_uint32Values_mirror, m_uint32Values, m_valuesCount*sizeof(uint32));
+
if(m_objectUpdated)
{
if(remove)
@@ -758,18 +707,23 @@ bool Object::LoadValues(const char* data)
void Object::_SetUpdateBits(UpdateMask *updateMask, Player* /*target*/) const
{
- for( uint16 index = 0; index < m_valuesCount; index ++ )
+ uint32 *value = m_uint32Values;
+ uint32 *mirror = m_uint32Values_mirror;
+
+ for(uint16 index = 0; index < m_valuesCount; ++index, ++value, ++mirror)
{
- if(m_uint32Values_mirror[index]!= m_uint32Values[index])
+ if(*mirror != *value)
updateMask->SetBit(index);
}
}
void Object::_SetCreateBits(UpdateMask *updateMask, Player* /*target*/) const
{
- for( uint16 index = 0; index < m_valuesCount; index++ )
+ uint32 *value = m_uint32Values;
+
+ for(uint16 index = 0; index < m_valuesCount; ++index, ++value)
{
- if(GetUInt32Value(index) != 0)
+ if(*value)
updateMask->SetBit(index);
}
}
@@ -831,6 +785,48 @@ void Object::SetUInt64Value( uint16 index, const uint64 &value )
}
}
+bool Object::AddUInt64Value(uint16 index, const uint64 &value)
+{
+ ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , true ) );
+ if(value && !*((uint64*)&(m_uint32Values[index])))
+ {
+ m_uint32Values[ index ] = *((uint32*)&value);
+ m_uint32Values[ index + 1 ] = *(((uint32*)&value) + 1);
+
+ if(m_inWorld)
+ {
+ if(!m_objectUpdated)
+ {
+ ObjectAccessor::Instance().AddUpdateObject(this);
+ m_objectUpdated = true;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool Object::RemoveUInt64Value(uint16 index, const uint64 &value)
+{
+ ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , true ) );
+ if(value && *((uint64*)&(m_uint32Values[index])) == value)
+ {
+ m_uint32Values[ index ] = 0;
+ m_uint32Values[ index + 1 ] = 0;
+
+ if(m_inWorld)
+ {
+ if(!m_objectUpdated)
+ {
+ ObjectAccessor::Instance().AddUpdateObject(this);
+ m_objectUpdated = true;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
void Object::SetFloatValue( uint16 index, float value )
{
ASSERT( index < m_valuesCount || PrintIndexError( index , true ) );
@@ -886,7 +882,7 @@ void Object::SetUInt16Value( uint16 index, uint8 offset, uint16 value )
return;
}
- if(uint8(m_uint32Values[ index ] >> (offset * 16)) != value)
+ if(uint16(m_uint32Values[ index ] >> (offset * 16)) != value)
{
m_uint32Values[ index ] &= ~uint32(uint32(0xFFFF) << (offset * 16));
m_uint32Values[ index ] |= uint32(uint32(value) << (offset * 16));
@@ -924,21 +920,21 @@ void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply)
cur += (apply ? val : -val);
if(cur < 0)
cur = 0;
- SetUInt32Value(index,cur);
+ SetUInt32Value(index, cur);
}
void Object::ApplyModInt32Value(uint16 index, int32 val, bool apply)
{
int32 cur = GetInt32Value(index);
cur += (apply ? val : -val);
- SetInt32Value(index,cur);
+ SetInt32Value(index, cur);
}
void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply)
{
float cur = GetFloatValue(index);
cur += (apply ? val : -val);
- SetFloatValue(index,cur);
+ SetFloatValue(index, cur);
}
void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
@@ -947,7 +943,7 @@ void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
cur += (apply ? val : -val);
if(cur < 0)
cur = 0;
- SetFloatValue(index,cur);
+ SetFloatValue(index, cur);
}
void Object::SetFlag( uint16 index, uint32 newFlag )
@@ -1051,30 +1047,20 @@ bool Object::PrintIndexError(uint32 index, bool set) const
}
WorldObject::WorldObject()
+ : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
+ m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f)
+ , m_map(NULL), m_zoneScript(NULL)
+ , m_isActive(false), IsTempWorldObject(false)
+ , m_name("")
{
- m_positionX = 0.0f;
- m_positionY = 0.0f;
- m_positionZ = 0.0f;
- m_orientation = 0.0f;
-
- m_mapId = 0;
- m_InstanceId = 0;
- m_map = NULL;
-
- m_name = "";
-
- mSemaphoreTeleport = false;
-
- m_isActive = false;
- IsTempWorldObject = false;
}
void WorldObject::SetWorldObject(bool on)
{
if(!IsInWorld())
return;
-
- GetMap()->AddObjectToSwitchList(this, on);
+
+ GetMap()->AddObjectToSwitchList(this, on);
}
void WorldObject::setActive( bool on )
@@ -1110,21 +1096,27 @@ void WorldObject::setActive( bool on )
}
}
-void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid )
+void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask )
{
Object::_Create(guidlow, 0, guidhigh);
m_mapId = mapid;
+ m_phaseMask = phaseMask;
}
uint32 WorldObject::GetZoneId() const
{
- return MapManager::Instance().GetBaseMap(m_mapId)->GetZoneId(m_positionX,m_positionY);
+ return GetBaseMap()->GetZoneId(m_positionX, m_positionY, m_positionZ);
}
uint32 WorldObject::GetAreaId() const
{
- return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY);
+ return GetBaseMap()->GetAreaId(m_positionX, m_positionY, m_positionZ);
+}
+
+void WorldObject::GetZoneAndAreaId(uint32& zoneid, uint32& areaid) const
+{
+ GetBaseMap()->GetZoneAndAreaId(zoneid, areaid, m_positionX, m_positionY, m_positionZ);
}
InstanceData* WorldObject::GetInstanceData()
@@ -1132,7 +1124,6 @@ InstanceData* WorldObject::GetInstanceData()
Map *map = GetMap();
return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL;
}
-
//slow
float WorldObject::GetDistance(const WorldObject* obj) const
{
@@ -1160,7 +1151,7 @@ float WorldObject::GetExactDistance2d(const float x, const float y) const
return sqrt((dx*dx) + (dy*dy));
}
-float WorldObject::GetDistance(const float x, const float y, const float z) const
+float WorldObject::GetDistance(float x, float y, float z) const
{
float dx = GetPositionX() - x;
float dy = GetPositionY() - y;
@@ -1178,6 +1169,14 @@ float WorldObject::GetDistanceSq(const float &x, const float &y, const float &z)
return dx*dx + dy*dy + dz*dz;
}
+float WorldObject::GetDistanceSq(const WorldObject *obj) const
+{
+ float dx = GetPositionX() - obj->GetPositionX();
+ float dy = GetPositionY() - obj->GetPositionY();
+ float dz = GetPositionZ() - obj->GetPositionZ();
+ return dx*dx + dy*dy + dz*dz;
+}
+
float WorldObject::GetDistance2d(const WorldObject* obj) const
{
float dx = GetPositionX() - obj->GetPositionX();
@@ -1195,10 +1194,33 @@ float WorldObject::GetDistanceZ(const WorldObject* obj) const
return ( dist > 0 ? dist : 0);
}
-bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D) const
+bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist2compare) const
{
- if (!obj || !IsInMap(obj)) return false;
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float dz = GetPositionZ() - z;
+ float distsq = dx*dx + dy*dy + dz*dz;
+
+ float sizefactor = GetObjectSize();
+ float maxdist = dist2compare + sizefactor;
+
+ return distsq < maxdist * maxdist;
+}
+bool WorldObject::IsWithinDist2d(float x, float y, float dist2compare) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float distsq = dx*dx + dy*dy;
+
+ float sizefactor = GetObjectSize();
+ float maxdist = dist2compare + sizefactor;
+
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const
+{
float dx = GetPositionX() - obj->GetPositionX();
float dy = GetPositionY() - obj->GetPositionY();
float distsq = dx*dx + dy*dy;
@@ -1221,7 +1243,7 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
return(IsWithinLOS(ox, oy, oz ));
}
-bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) const
+bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
{
float x,y,z;
GetPosition(x,y,z);
@@ -1229,6 +1251,95 @@ bool WorldObject::IsWithinLOS(const float ox, const float oy, const float oz ) c
return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);
}
+bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const
+{
+ float dx1 = GetPositionX() - obj1->GetPositionX();
+ float dy1 = GetPositionY() - obj1->GetPositionY();
+ float distsq1 = dx1*dx1 + dy1*dy1;
+ if(is3D)
+ {
+ float dz1 = GetPositionZ() - obj1->GetPositionZ();
+ distsq1 += dz1*dz1;
+ }
+
+ float dx2 = GetPositionX() - obj2->GetPositionX();
+ float dy2 = GetPositionY() - obj2->GetPositionY();
+ float distsq2 = dx2*dx2 + dy2*dy2;
+ if(is3D)
+ {
+ float dz2 = GetPositionZ() - obj2->GetPositionZ();
+ distsq2 += dz2*dz2;
+ }
+
+ return distsq1 < distsq2;
+}
+
+bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const
+{
+ float dx = GetPositionX() - obj->GetPositionX();
+ float dy = GetPositionY() - obj->GetPositionY();
+ float distsq = dx*dx + dy*dy;
+ if(is3D)
+ {
+ float dz = GetPositionZ() - obj->GetPositionZ();
+ distsq += dz*dz;
+ }
+
+ float sizefactor = GetObjectSize() + obj->GetObjectSize();
+
+ // check only for real range
+ if(minRange > 0.0f)
+ {
+ float mindist = minRange + sizefactor;
+ if(distsq < mindist * mindist)
+ return false;
+ }
+
+ float maxdist = maxRange + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float distsq = dx*dx + dy*dy;
+
+ float sizefactor = GetObjectSize();
+
+ // check only for real range
+ if(minRange > 0.0f)
+ {
+ float mindist = minRange + sizefactor;
+ if(distsq < mindist * mindist)
+ return false;
+ }
+
+ float maxdist = maxRange + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
+bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float maxRange) const
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+ float dz = GetPositionZ() - z;
+ float distsq = dx*dx + dy*dy + dz*dz;
+
+ float sizefactor = GetObjectSize();
+
+ // check only for real range
+ if(minRange > 0.0f)
+ {
+ float mindist = minRange + sizefactor;
+ if(distsq < mindist * mindist)
+ return false;
+ }
+
+ float maxdist = maxRange + sizefactor;
+ return distsq < maxdist * maxdist;
+}
+
float WorldObject::GetAngle(const WorldObject* obj) const
{
if(!obj) return 0;
@@ -1246,6 +1357,25 @@ float WorldObject::GetAngle( const float x, const float y ) const
return ang;
}
+void WorldObject::GetSinCos(const float x, const float y, float &vsin, float &vcos)
+{
+ float dx = GetPositionX() - x;
+ float dy = GetPositionY() - y;
+
+ if(dx < 0.001f && dy < 0.001f)
+ {
+ float angle = rand_norm()*2*M_PI;
+ vcos = cos(angle);
+ vsin = sin(angle);
+ }
+ else
+ {
+ float dist = sqrt((dx*dx) + (dy*dy));
+ vcos = dx / dist;
+ vsin = dy / dist;
+ }
+}
+
bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
{
// always have self in arc
@@ -1263,6 +1393,15 @@ bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
float angle = GetAngle( obj );
angle -= m_orientation;
+ //if(angle > 100 || angle < -100)
+ //{
+ // sLog.outCrash("Invalid Angle %f: this %u %u %f %f %f %f, that %u %u %f %f %f %f", angle,
+ // GetEntry(), GetGUIDLow(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),
+ // obj->GetEntry(), obj->GetGUIDLow(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation());
+ // assert(false);
+ // return false;
+ //}
+
// move angle to range -pi ... +pi
while( angle > M_PI)
angle -= 2.0f * M_PI;
@@ -1274,6 +1413,21 @@ bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
return (( angle >= lborder ) && ( angle <= rborder ));
}
+bool WorldObject::IsInBetween(const WorldObject *obj1, const WorldObject *obj2, float size) const
+{
+ if(GetPositionX() > std::max(obj1->GetPositionX(), obj2->GetPositionX())
+ || GetPositionX() < std::min(obj1->GetPositionX(), obj2->GetPositionX())
+ || GetPositionY() > std::max(obj1->GetPositionY(), obj2->GetPositionY())
+ || GetPositionY() < std::min(obj1->GetPositionY(), obj2->GetPositionY()))
+ return false;
+
+ if(!size)
+ size = GetObjectSize() / 2;
+
+ float angle = obj1->GetAngle(this) - obj1->GetAngle(obj2);
+ return abs(sin(angle)) * GetExactDistance2d(obj1->GetPositionX(), obj1->GetPositionY()) < size;
+}
+
void WorldObject::GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z) const
{
if(distance==0)
@@ -1285,8 +1439,8 @@ void WorldObject::GetRandomPoint( float x, float y, float z, float distance, flo
}
// angle to face `obj` to `this`
- float angle = GetMap()->rand_norm()*2*M_PI;
- float new_dist = GetMap()->rand_norm()*distance;
+ float angle = rand_norm()*2*M_PI;
+ float new_dist = rand_norm()*distance;
rand_x = x + new_dist * cos(angle);
rand_y = y + new_dist * sin(angle);
@@ -1299,7 +1453,7 @@ void WorldObject::GetRandomPoint( float x, float y, float z, float distance, flo
void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
{
- float new_z = MapManager::Instance().GetBaseMap(GetMapId())->GetHeight(x,y,z,true);
+ float new_z = GetBaseMap()->GetHeight(x,y,z,true);
if(new_z > INVALID_HEIGHT)
z = new_z+ 0.05f; // just to be sure that we are not a few pixel under the surface
}
@@ -1367,50 +1521,17 @@ void Object::ForceValuesUpdateAtIndex(uint32 i)
namespace Trinity
{
- class MessageChatLocaleCacheDo
+ class MonsterChatBuilder
{
public:
- MessageChatLocaleCacheDo(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID, float dist)
- : i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language),
- i_targetGUID(targetGUID), i_dist(dist)
- {
- }
-
- ~MessageChatLocaleCacheDo()
- {
- for(int i = 0; i < i_data_cache.size(); ++i)
- delete i_data_cache[i];
- }
-
- void operator()(Player* p)
+ MonsterChatBuilder(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID)
+ : i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language), i_targetGUID(targetGUID) {}
+ void operator()(WorldPacket& data, int32 loc_idx)
{
- // skip far away players
- if(p->GetDistance(&i_object) > i_dist)
- return;
-
- uint32 loc_idx = p->GetSession()->GetSessionDbLocaleIndex();
- uint32 cache_idx = loc_idx+1;
- WorldPacket* data;
-
- // create if not cached yet
- if(i_data_cache.size() < cache_idx+1 || !i_data_cache[cache_idx])
- {
- if(i_data_cache.size() < cache_idx+1)
- i_data_cache.resize(cache_idx+1);
-
- char const* text = objmgr.GetTrinityString(i_textId,loc_idx);
-
- data = new WorldPacket(SMSG_MESSAGECHAT, 200);
-
- // TODO: i_object.GetName() also must be localized?
- i_object.BuildMonsterChat(data,i_msgtype,text,i_language,i_object.GetNameForLocaleIdx(loc_idx),i_targetGUID);
+ char const* text = objmgr.GetMangosString(i_textId,loc_idx);
- i_data_cache[cache_idx] = data;
- }
- else
- data = i_data_cache[cache_idx];
-
- p->SendDirectMessage(data);
+ // TODO: i_object.GetName() also must be localized?
+ i_object.BuildMonsterChat(&data,i_msgtype,text,i_language,i_object.GetNameForLocaleIdx(loc_idx),i_targetGUID);
}
private:
@@ -1419,8 +1540,6 @@ namespace Trinity
int32 i_textId;
uint32 i_language;
uint64 i_targetGUID;
- float i_dist;
- std::vector<WorldPacket*> i_data_cache; // 0 = default, i => i-1 locale index
};
} // namespace Trinity
@@ -1432,9 +1551,10 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
- Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do);
- TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
+ MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid);
+ MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
+ MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),say_do);
+ TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
}
@@ -1447,13 +1567,27 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL));
- Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do);
- TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
+ MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid);
+ MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
+ MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),say_do);
+ TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
}
+void WorldObject::MonsterYellToZone(int32 textId, uint32 language, uint64 TargetGuid)
+{
+ MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid);
+ MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
+
+ uint32 zoneid = GetZoneId();
+
+ Map::PlayerList const& pList = GetMap()->GetPlayers();
+ for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
+ if(itr->getSource()->GetZoneId()==zoneid)
+ say_do(itr->getSource());
+}
+
void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote)
{
CellPair p = Trinity::ComputeCellPair(GetPositionX(), GetPositionY());
@@ -1462,9 +1596,10 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
- Trinity::MessageChatLocaleCacheDo say_do(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
- Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do);
- TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker);
+ MaNGOS::MonsterChatBuilder say_build(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid);
+ MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
+ MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),say_do);
+ TypeContainerVisitor<MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> >, WorldTypeMapContainer > message(say_worker);
CellLock<GridReadGuard> cell_lock(cell, p);
cell_lock->Visit(cell_lock, message, *GetMap());
}
@@ -1479,7 +1614,7 @@ void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisp
char const* text = objmgr.GetTrinityString(textId,loc_idx);
WorldPacket data(SMSG_MESSAGECHAT, 200);
- BuildMonsterChat(&data,IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER,text,LANG_UNIVERSAL,GetName(),receiver);
+ BuildMonsterChat(&data,IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER,text,LANG_UNIVERSAL,GetNameForLocaleIdx(loc_idx),receiver);
player->GetSession()->SendPacket(&data);
}
@@ -1491,10 +1626,10 @@ void WorldObject::BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const*
*data << (uint8)msgtype;
*data << (uint32)language;
*data << (uint64)GetGUID();
- *data << (uint32)0; //2.1.0
+ *data << (uint32)0; // 2.1.0
*data << (uint32)(strlen(name)+1);
*data << name;
- *data << (uint64)targetGuid; //Unit Target
+ *data << (uint64)targetGuid; // Unit Target
if( targetGuid && !IS_PLAYER_GUID(targetGuid) )
{
*data << (uint32)1; // target name length
@@ -1507,51 +1642,27 @@ void WorldObject::BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const*
*data << (uint8)0; // ChatTag
}
-void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const
+void Unit::BuildHeartBeatMsg(WorldPacket *data) const
{
- //Heartbeat message cannot be used for non-units
- if (!isType(TYPEMASK_UNIT))
- return;
-
data->Initialize(MSG_MOVE_HEARTBEAT, 32);
data->append(GetPackGUID());
- *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags
- *data << uint8(0); // 2.3.0
- *data << getMSTime(); // time
- *data << m_positionX;
- *data << m_positionY;
- *data << m_positionZ;
- *data << m_orientation;
- *data << uint32(0);
+ BuildMovementPacket(data);
}
-void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float z, float ang) const
+void WorldObject::SendMessageToSet(WorldPacket *data, bool /*fake*/)
{
- //TeleportAck message cannot be used for non-units
- if (!isType(TYPEMASK_UNIT))
- return;
-
- data->Initialize(MSG_MOVE_TELEPORT_ACK, 41);
- data->append(GetPackGUID());
- *data << uint32(0); // this value increments every time
- *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags
- *data << uint8(0); // 2.3.0
- *data << getMSTime(); // time
- *data << x;
- *data << y;
- *data << z;
- *data << ang;
- *data << uint32(0);
+ //if object is in world, map for it already created!
+ Map * _map = IsInWorld() ? GetMap() : MapManager::Instance().FindMap(GetMapId(), GetInstanceId());
+ if(_map)
+ _map->MessageBroadcast(this, data);
}
-void WorldObject::SendMessageToSet(WorldPacket *data, bool /*fake*/, bool bToPossessor)
+void WorldObject::SendMessageToSetInRange(WorldPacket *data, float dist, bool /*bToSelf*/)
{
- MapManager::Instance().GetMap(m_mapId, this)->MessageBroadcast(this, data, bToPossessor);
-}
-
-void WorldObject::SendMessageToSetInRange(WorldPacket *data, float dist, bool /*bToSelf*/, bool bToPossessor)
-{
- MapManager::Instance().GetMap(m_mapId, this)->MessageDistBroadcast(this, data, dist, bToPossessor);
+ //if object is in world, map for it already created!
+ Map * _map = IsInWorld() ? GetMap() : MapManager::Instance().FindMap(GetMapId(), GetInstanceId());
+ if(_map)
+ _map->MessageDistBroadcast(this, data, dist);
}
void WorldObject::SendObjectDeSpawnAnim(uint64 guid)
@@ -1573,7 +1684,7 @@ Map* WorldObject::_findMap()
Map const* WorldObject::GetBaseMap() const
{
- return MapManager::Instance().GetBaseMap(GetMapId());
+ return MapManager::Instance().CreateBaseMap(GetMapId());
}
void WorldObject::AddObjectToRemoveList()
@@ -1590,60 +1701,133 @@ void WorldObject::AddObjectToRemoveList()
map->AddObjectToRemoveList(this);
}
-Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime)
+TempSummon *Map::SummonCreature(uint32 entry, float x, float y, float z, float angle, SummonPropertiesEntry const *properties, uint32 duration, Unit *summoner)
{
- TemporarySummon* pCreature = new TemporarySummon(GetGUID());
+ uint32 mask = SUMMON_MASK_SUMMON;
+ if(properties)
+ {
+ if(properties->Category == SUMMON_CATEGORY_PET
+ || properties->Type == SUMMON_TYPE_GUARDIAN
+ || properties->Type == SUMMON_TYPE_MINION)
+ mask = SUMMON_MASK_GUARDIAN;
+ else if(properties->Type == SUMMON_TYPE_TOTEM)
+ mask = SUMMON_MASK_TOTEM;
+ else if(properties->Category == SUMMON_CATEGORY_VEHICLE
+ || properties->Type == SUMMON_TYPE_VEHICLE
+ || properties->Type == SUMMON_TYPE_VEHICLE2)
+ mask = SUMMON_MASK_VEHICLE;
+ else if(properties->Category == SUMMON_CATEGORY_PUPPET)
+ mask = SUMMON_MASK_PUPPET;
+ else if(properties->Type == SUMMON_TYPE_MINIPET)
+ mask = SUMMON_MASK_MINION;
+ }
- uint32 team = 0;
- if (GetTypeId()==TYPEID_PLAYER)
- team = ((Player*)this)->GetTeam();
+ uint32 phase = PHASEMASK_NORMAL, team = 0;
+ if(summoner)
+ {
+ phase = summoner->GetPhaseMask();
+ if(summoner->GetTypeId() == TYPEID_PLAYER)
+ team = ((Player*)summoner)->GetTeam();
+ }
- if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), id, team))
+ TempSummon *summon = NULL;
+ switch(mask)
{
- delete pCreature;
+ case SUMMON_MASK_SUMMON: summon = new TempSummon (properties, summoner); break;
+ case SUMMON_MASK_GUARDIAN: summon = new Guardian (properties, summoner); break;
+ case SUMMON_MASK_PUPPET: summon = new Puppet (properties, summoner); break;
+ case SUMMON_MASK_TOTEM: summon = new Totem (properties, summoner); break;
+ case SUMMON_MASK_MINION: summon = new Minion (properties, summoner); break;
+ default: return NULL;
+ }
+
+ if(!summon->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), this, phase, entry, team, x, y, z, angle))
+ {
+ delete summon;
return NULL;
}
- if (x == 0.0f && y == 0.0f && z == 0.0f)
- GetClosePoint(x, y, z, pCreature->GetObjectSize());
+ summon->SetHomePosition(x, y, z, angle);
- pCreature->Relocate(x, y, z, ang);
+ summon->InitStats(duration);
+ Add((Creature*)summon);
+ summon->InitSummon();
+
+ //ObjectAccessor::UpdateObjectVisibility(summon);
+
+ return summon;
+}
- if(!pCreature->IsPositionValid())
+void WorldObject::SetZoneScript()
+{
+ if(Map *map = FindMap())
{
- sLog.outError("ERROR: Creature (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)",pCreature->GetGUIDLow(),pCreature->GetEntry(),pCreature->GetPositionX(),pCreature->GetPositionY());
- delete pCreature;
- return NULL;
+ if(map->IsDungeon())
+ m_zoneScript = (ZoneScript*)((InstanceMap*)map)->GetInstanceData();
+ else if(!map->IsBattleGroundOrArena())
+ m_zoneScript = sOutdoorPvPMgr.GetZoneScript(GetZoneId());
}
+}
+
+TempSummon* WorldObject::SummonCreature(uint32 entry, float x, float y, float z, float ang, TempSummonType spwtype, uint32 duration)
+{
+ Map *map = FindMap();
+ if(!map)
+ return NULL;
+
+ if (x == 0.0f && y == 0.0f && z == 0.0f)
+ GetClosePoint(x, y, z, GetObjectSize());
+
+ TempSummon *pCreature = map->SummonCreature(entry, x, y, z, ang, NULL, duration, isType(TYPEMASK_UNIT) ? (Unit*)this : NULL);
+ if(!pCreature)
+ return NULL;
+
+ pCreature->SetTempSummonType(spwtype);
+
+ return pCreature;
+}
- pCreature->SetHomePosition(x, y, z, ang);
- pCreature->Summon(spwtype, despwtime);
+Vehicle* WorldObject::SummonVehicle(uint32 entry, float x, float y, float z, float ang)
+{
+ CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry);
+ if(!ci)
+ return NULL;
- if(GetTypeId()==TYPEID_UNIT && ((Creature*)this)->IsAIEnabled)
- ((Creature*)this)->AI()->JustSummoned(pCreature);
+ uint32 id = ci->VehicleId; //temp store id here
+ if(!id) id = 156;
+ VehicleEntry const *ve = sVehicleStore.LookupEntry(id);
+ if(!ve)
+ return NULL;
- if(pCreature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER && pCreature->m_spells[0])
+ Vehicle *v = new Vehicle;
+ Map *map = GetMap();
+ uint32 team = 0;
+ if (GetTypeId()==TYPEID_PLAYER)
+ team = ((Player*)this)->GetTeam();
+ if(!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, GetPhaseMask(), entry, id, team, x, y, z, ang))
{
- if(GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER)
- pCreature->setFaction(((Unit*)this)->getFaction());
- pCreature->CastSpell(pCreature, pCreature->m_spells[0], false, 0, 0, GetGUID());
+ delete v;
+ return NULL;
}
- //return the creature therewith the summoner has access to it
- return pCreature;
+ map->Add((Creature*)v);
+
+ //ObjectAccessor::UpdateObjectVisibility(v);
+
+ return v;
}
Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 duration)
{
- Pet* pet = new Pet(petType);
+ Pet* pet = new Pet(this, petType);
if(petType == SUMMON_PET && pet->LoadPetFromDB(this, entry))
{
// Remove Demonic Sacrifice auras (known pet)
- Unit::AuraList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
+ Unit::AuraEffectList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(Unit::AuraEffectList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
{
- if((*itr)->GetModifier()->m_miscvalue==2228)
+ if((*itr)->GetMiscValue()==2228)
{
RemoveAurasDueToSpell((*itr)->GetId());
itr = auraClassScripts.begin();
@@ -1667,7 +1851,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
Map *map = GetMap();
uint32 pet_number = objmgr.GeneratePetNumber();
- if(!pet->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, entry, pet_number))
+ if(!pet->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, GetPhaseMask(), entry, pet_number))
{
sLog.outError("no such creature entry %u", entry);
delete pet;
@@ -1683,38 +1867,38 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
return NULL;
}
- pet->SetOwnerGUID(GetGUID());
pet->SetCreatorGUID(GetGUID());
pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
- // this enables pet details window (Shift+P)
- pet->GetCharmInfo()->SetPetNumber(pet_number, false);
-
- pet->AIM_Initialize();
-
- map->Add((Creature*)pet);
-
pet->setPowerType(POWER_MANA);
pet->SetUInt32Value(UNIT_NPC_FLAGS , 0);
pet->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
pet->InitStatsForLevel(getLevel());
+ SetMinion(pet, true);
+
switch(petType)
{
- case GUARDIAN_PET:
- case POSSESSED_PET:
- pet->SetUInt32Value(UNIT_FIELD_FLAGS,0);
- AddGuardian(pet);
- break;
case SUMMON_PET:
+ // this enables pet details window (Shift+P)
+ pet->GetCharmInfo()->SetPetNumber(pet_number, true);
pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
pet->SetHealth(pet->GetMaxHealth());
pet->SetPower(POWER_MANA, pet->GetMaxPower(POWER_MANA));
+ pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL));
+ break;
+ }
+
+ map->Add((Creature*)pet);
+
+ switch(petType)
+ {
+ case SUMMON_PET:
pet->InitPetCreateSpells();
+ pet->InitTalentForLevel();
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
- SetPet(pet);
PetSpellInitialize();
break;
}
@@ -1722,10 +1906,10 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
if(petType == SUMMON_PET)
{
// Remove Demonic Sacrifice auras (known pet)
- Unit::AuraList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
- for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
+ Unit::AuraEffectList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
+ for(Unit::AuraEffectList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
{
- if((*itr)->GetModifier()->m_miscvalue==2228)
+ if((*itr)->GetMiscValue()==2228)
{
RemoveAurasDueToSpell((*itr)->GetId());
itr = auraClassScripts.begin();
@@ -1738,6 +1922,8 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
if(duration > 0)
pet->SetDuration(duration);
+ //ObjectAccessor::UpdateObjectVisibility(pet);
+
return pet;
}
@@ -1754,7 +1940,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float
}
Map *map = GetMap();
GameObject *go = new GameObject();
- if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry,map,x,y,z,ang,rotation0,rotation1,rotation2,rotation3,100,1))
+ if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, GetPhaseMask(), x,y,z,ang,rotation0,rotation1,rotation2,rotation3,100,GO_STATE_READY))
{
delete go;
return NULL;
@@ -1788,6 +1974,99 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3
return summon;
}
+Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive)
+{
+ Creature *creature = NULL;
+ Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, entry, alive, range);
+ Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(this, creature, checker);
+ VisitNearbyObject(range, searcher);
+ return creature;
+}
+
+GameObject* WorldObject::FindNearestGameObject(uint32 entry, float range)
+{
+ GameObject *go = NULL;
+ Trinity::NearestGameObjectEntryInObjectRangeCheck checker(*this, entry, range);
+ Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> searcher(this, go, checker);
+ VisitNearbyGridObject(range, searcher);
+ return go;
+}
+
+/*
+namespace MaNGOS
+{
+ class NearUsedPosDo
+ {
+ public:
+ NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector)
+ : i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {}
+
+ void operator()(Corpse*) const {}
+ void operator()(DynamicObject*) const {}
+
+ void operator()(Creature* c) const
+ {
+ // skip self or target
+ if(c==i_searcher || c==&i_object)
+ return;
+
+ float x,y,z;
+
+ if( !c->isAlive() || c->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) ||
+ !c->GetMotionMaster()->GetDestination(x,y,z) )
+ {
+ x = c->GetPositionX();
+ y = c->GetPositionY();
+ }
+
+ add(c,x,y);
+ }
+
+ template<class T>
+ void operator()(T* u) const
+ {
+ // skip self or target
+ if(u==i_searcher || u==&i_object)
+ return;
+
+ float x,y;
+
+ x = u->GetPositionX();
+ y = u->GetPositionY();
+
+ add(u,x,y);
+ }
+
+ // we must add used pos that can fill places around center
+ void add(WorldObject* u, float x, float y) const
+ {
+ // u is too nearest/far away to i_object
+ if(!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size))
+ return;
+
+ float angle = i_object.GetAngle(u)-i_angle;
+
+ // move angle to range -pi ... +pi
+ while( angle > M_PI)
+ angle -= 2.0f * M_PI;
+ while(angle < -M_PI)
+ angle += 2.0f * M_PI;
+
+ // dist include size of u
+ float dist2d = i_object.GetDistance2d(x,y);
+ i_selector.AddUsedPos(u->GetObjectSize(),angle,dist2d + i_object.GetObjectSize());
+ }
+ private:
+ WorldObject const& i_object;
+ WorldObject const* i_searcher;
+ float i_angle;
+ ObjectPosSelector& i_selector;
+ };
+} // namespace MaNGOS
+*/
+
+//===================================================================================================
+
void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle ) const
{
x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle);
@@ -1800,10 +2079,127 @@ void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float abs
void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle ) const
{
GetNearPoint2D(x,y,distance2d+searcher_size,absAngle);
-
z = GetPositionZ();
-
UpdateGroundPositionZ(x,y,z);
+
+ /*
+ // if detection disabled, return first point
+ if(!sWorld.getConfig(CONFIG_DETECT_POS_COLLISION))
+ {
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+ return;
+ }
+
+ // or remember first point
+ float first_x = x;
+ float first_y = y;
+ bool first_los_conflict = false; // first point LOS problems
+
+ // prepare selector for work
+ ObjectPosSelector selector(GetPositionX(),GetPositionY(),GetObjectSize(),distance2d+searcher_size);
+
+ // adding used positions around object
+ {
+ CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ MaNGOS::NearUsedPosDo u_do(*this,searcher,absAngle,selector);
+ MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this,u_do);
+
+ TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker);
+ TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap());
+ cell_lock->Visit(cell_lock, world_obj_worker, *GetMap());
+ }
+
+ // maybe can just place in primary position
+ if( selector.CheckOriginal() )
+ {
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+
+ first_los_conflict = true; // first point have LOS problems
+ }
+
+ float angle; // candidate of angle for free pos
+
+ // special case when one from list empty and then empty side preferred
+ if(selector.FirstAngle(angle))
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+
+ // set first used pos in lists
+ selector.InitializeAngle();
+
+ // select in positions after current nodes (selection one by one)
+ while(selector.NextAngle(angle)) // angle for free pos
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+
+ // BAD NEWS: not free pos (or used or have LOS problems)
+ // Attempt find _used_ pos without LOS problem
+
+ if(!first_los_conflict)
+ {
+ x = first_x;
+ y = first_y;
+
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+ return;
+ }
+
+ // special case when one from list empty and then empty side preferred
+ if( selector.IsNonBalanced() )
+ {
+ if(!selector.FirstAngle(angle)) // _used_ pos
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+ }
+
+ // set first used pos in lists
+ selector.InitializeAngle();
+
+ // select in positions after current nodes (selection one by one)
+ while(selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
+ {
+ GetNearPoint2D(x,y,distance2d,absAngle+angle);
+ z = GetPositionZ();
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+
+ if(IsWithinLOS(x,y,z))
+ return;
+ }
+
+ // BAD BAD NEWS: all found pos (free and used) have LOS problem :(
+ x = first_x;
+ y = first_y;
+
+ UpdateGroundPositionZ(x,y,z); // update to LOS height if available
+ */
}
void WorldObject::GetGroundPoint(float &x, float &y, float &z, float dist, float angle)
@@ -1816,5 +2212,31 @@ void WorldObject::GetGroundPoint(float &x, float &y, float &z, float dist, float
UpdateGroundPositionZ(x, y, z);
}
+void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
+{
+ m_phaseMask = newPhaseMask;
+ if(update && IsInWorld())
+ ObjectAccessor::UpdateObjectVisibility(this);
+}
+void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
+{
+ WorldPacket data(SMSG_PLAY_OBJECT_SOUND,4+8);
+ data << uint32(sound_id);
+ data << uint64(GetGUID());
+ if (target)
+ target->SendDirectMessage( &data );
+ else
+ SendMessageToSet( &data, true );
+}
+
+void WorldObject::PlayDirectSound( uint32 sound_id, Player* target /*= NULL*/ )
+{
+ WorldPacket data(SMSG_PLAY_SOUND, 4);
+ data << uint32(sound_id);
+ if (target)
+ target->SendDirectMessage( &data );
+ else
+ SendMessageToSet( &data, true );
+}