Example #1
0
void MapMgr::ChangeFarsightLocation(Player* plr, float X, float Y, bool apply)
{
	if(!apply)
	{
		// We're clearing.
		for(ObjectSet::iterator itr = plr->m_visibleFarsightObjects.begin(); itr != plr->m_visibleFarsightObjects.end();
			++itr)
		{
			// Send destroy
			plr->PushOutOfRange((*itr)->GetNewGUID());
		}
		plr->m_visibleFarsightObjects.clear();
	}
	else
	{
		uint32 cellX = GetPosX(X);
		uint32 cellY = GetPosY(Y);
		uint32 endX = (cellX <= _sizeX) ? cellX + 1 : (_sizeX-1);
		uint32 endY = (cellY <= _sizeY) ? cellY + 1 : (_sizeY-1);
		uint32 startX = cellX > 0 ? cellX - 1 : 0;
		uint32 startY = cellY > 0 ? cellY - 1 : 0;
		uint32 posX, posY;
		MapCell *cell;
		Object *obj;
		MapCell::ObjectSet::iterator iter, iend;
		uint32 count;
		for (posX = startX; posX <= endX; ++posX )
		{
			for (posY = startY; posY <= endY; ++posY )
			{
				cell = GetCell(posX, posY);
				if (cell)
				{
					iter = cell->Begin();
					iend = cell->End();
					for(; iter != iend; ++iter)
					{
						obj = (*iter);
						if(!plr->IsVisible(obj) && plr->CanSee(obj) && obj->GetDistance2dSq(X, Y) <= m_UpdateDistance)
						{
							ByteBuffer buf;
							count = obj->BuildCreateUpdateBlockForPlayer(&buf, plr);
							plr->PushCreationData(&buf, count);
							plr->m_visibleFarsightObjects.insert(obj);
						}
					}
					
				}
			}
		}
	}
}
	void AIUpdate()
	{
		std::set<Object*>::iterator itr = _unit->GetInRangeOppFactsSetBegin();
		for(; itr != _unit->GetInRangeOppFactsSetEnd(); itr++)
		{
			Object * pObj = (*itr);
			if( pObj->IsUnit() && _unit->CanSee( static_cast<Unit*>(pObj) ))
			{
				if( pObj->IsPlayer() && TO_PLAYER(pObj)->m_isGmInvisible )
					continue;

				if( pObj->GetDistance2dSq(_unit) > (60*60) )
					continue;

				_unit->CastSpell(TO_UNIT(pObj), dbcSpell.LookupEntryForced(BOWMAN_SHOOT), true);
				return;
			}
		}
	}
Example #3
0
void MapMgr::UpdateInRangeSet( Object *obj, Player *plObj, MapCell* cell, ByteBuffer ** buf )
{
	#define CHECK_BUF if(!*buf) *buf = new ByteBuffer(2500)

	if( cell == NULL )
		return;

	Object* curObj;
	Player* plObj2;
	int count;
	ObjectSet::iterator iter = cell->Begin();
	ObjectSet::iterator itr;
	float fRange;
	bool cansee, isvisible;

	while( iter != cell->End() )
	{
		curObj = *iter;
		++iter;

		if( curObj == NULL )
			continue;

		if( curObj->IsPlayer() && obj->IsPlayer() && plObj->m_TransporterGUID && plObj->m_TransporterGUID == static_cast< Player* >( curObj )->m_TransporterGUID )
			fRange = 0.0f; // unlimited distance for people on same boat
		else if( curObj->GetTypeFromGUID() == HIGHGUID_TYPE_TRANSPORTER )
			fRange = 0.0f; // unlimited distance for transporters (only up to 2 cells +/- anyway.)
		else
			fRange = m_UpdateDistance; // normal distance

		if ( curObj != obj && ( curObj->GetDistance2dSq( obj ) <= fRange || fRange == 0.0f ) )
		{
			if( !obj->IsInRangeSet( curObj ) )
			{
				// Object in range, add to set
				obj->AddInRangeObject( curObj );
				curObj->AddInRangeObject( obj );

				if( curObj->IsPlayer() )
				{
					plObj2 = static_cast< Player* >( curObj );

					if( plObj2 != NULL && plObj2->CanSee( obj ) && !plObj2->IsVisible( obj ) )
					{
						CHECK_BUF;
						count = obj->BuildCreateUpdateBlockForPlayer(*buf, plObj2);
						plObj2->PushCreationData(*buf, count);
						plObj2->AddVisibleObject(obj);
						(*buf)->clear();
					}
				}

				if( plObj != NULL )
				{
					if( plObj->CanSee( curObj ) && !plObj->IsVisible( curObj ) )
					{
						CHECK_BUF;
						count = curObj->BuildCreateUpdateBlockForPlayer( *buf, plObj );
						plObj->PushCreationData( *buf, count );
						plObj->AddVisibleObject( curObj );
						(*buf)->clear();
					}
				}
			}
			else
			{
				// Check visiblility
				if( curObj->IsPlayer() )
				{
					plObj2 = static_cast< Player* >( curObj );
					cansee = plObj2->CanSee(obj);
					isvisible = plObj2->GetVisibility(obj, &itr);
					if(!cansee && isvisible)
					{
						plObj2->PushOutOfRange(obj->GetNewGUID());
						plObj2->RemoveVisibleObject(itr);
					}
					else if(cansee && !isvisible)
					{
						CHECK_BUF;
						count = obj->BuildCreateUpdateBlockForPlayer(*buf, plObj2);
						plObj2->PushCreationData(*buf, count);
						plObj2->AddVisibleObject(obj);
						(*buf)->clear();
					}
				}

				if( plObj )
				{
					cansee = plObj->CanSee( curObj );
					isvisible = plObj->GetVisibility( curObj, &itr );
					if(!cansee && isvisible)
					{
						plObj->PushOutOfRange( curObj->GetNewGUID() );
						plObj->RemoveVisibleObject( itr );
					}
					else if(cansee && !isvisible)
					{
						CHECK_BUF;
						count = curObj->BuildCreateUpdateBlockForPlayer( *buf, plObj );
						plObj->PushCreationData( *buf, count );
						plObj->AddVisibleObject( curObj );
						(*buf)->clear();
					}
				}
			}
		}
	}
/*
#define IN_RANGE_LOOP_P1 \
	while(iter != cell->End()) \
	{ \
		curObj = *iter; \
		++iter; \
		if(curObj->IsPlayer() && obj->IsPlayer() && plObj && plObj->m_TransporterGUID && plObj->m_TransporterGUID == static_cast< Player* >( curObj )->m_TransporterGUID) \
			fRange = 0.0f; \
		else if((curObj->GetGUIDHigh() == HIGHGUID_TRANSPORTER ||obj->GetGUIDHigh() == HIGHGUID_TRANSPORTER)) \
			fRange = 0.0f; \
		else if((curObj->GetGUIDHigh() == HIGHGUID_GAMEOBJECT && curObj->GetUInt32Value(GAMEOBJECT_TYPE_ID) == GAMEOBJECT_TYPE_TRANSPORT || obj->GetGUIDHigh() == HIGHGUID_GAMEOBJECT && obj->GetUInt32Value(GAMEOBJECT_TYPE_ID) == GAMEOBJECT_TYPE_TRANSPORT)) \
			fRange = 0.0f; \
		else \
			fRange = m_UpdateDistance; \
		if ( curObj != obj && (fRange == 0.0f || curObj->GetDistance2dSq(obj) < fRange ) ) \
		{ \
			if(!obj->IsInRangeSet(curObj)) \
			{ \
				if(curObj->NeedsInRangeSet()) \
				{ \
					curObj->AddInRangeObject(obj); \
				} else if(obj->IsPlayer()) \
				{ \
					curObj->AddInRangePlayer(obj); \
				} \
				if(curObj->IsPlayer()) \
				{ \
					plObj2 = static_cast< Player* >( curObj ); \
					if (plObj2->CanSee(obj) && !plObj2->IsVisible(obj))  \
					{ \
						CHECK_BUF; \
						count = obj->BuildCreateUpdateBlockForPlayer(*buf, plObj2); \
						plObj2->PushCreationData(*buf, count); \
						plObj2->AddVisibleObject(obj); \
						(*buf)->clear(); \
					} \
				} 

#define IN_RANGE_LOOP_P2 \
			} \
			else \
			{ \
				if(curObj->IsPlayer()) \
				{ \
					plObj2 = static_cast< Player* >( curObj ); \
					cansee = plObj2->CanSee(obj); \
					isvisible = plObj2->GetVisibility(obj, &itr); \
					if(!cansee && isvisible) \
					{ \
						plObj2->RemoveVisibleObject(itr); \
						plObj2->PushOutOfRange(obj->GetNewGUID()); \
					} \
					else if(cansee && !isvisible) \
					{ \
						CHECK_BUF; \
						count = obj->BuildCreateUpdateBlockForPlayer(*buf, plObj2); \
						plObj2->PushCreationData(*buf, count); \
						plObj2->AddVisibleObject(obj); \
						(*buf)->clear(); \
					} \
				} \

#define IN_RANGE_LOOP_P3 \
			} \
		} \
	} \


	if(plObj)
	{
		IN_RANGE_LOOP_P1

			obj->AddInRangeObject(curObj);
			if(plObj->CanSee(curObj) && !plObj->IsVisible(curObj))
			{
				CHECK_BUF;
				count = curObj->BuildCreateUpdateBlockForPlayer(*buf, plObj);
				plObj->PushCreationData(*buf, count);
				plObj->AddVisibleObject(curObj);
				(*buf)->clear();
			}

		IN_RANGE_LOOP_P2

			if(plObj)
			{
				cansee = plObj->CanSee(curObj);
				isvisible = plObj->GetVisibility(curObj, &itr);
				if(!cansee && isvisible)
				{
					plObj->PushOutOfRange(curObj->GetNewGUID());
					plObj->RemoveVisibleObject(itr);
				}
				else if(cansee && !isvisible)
				{
					CHECK_BUF;
					count = curObj->BuildCreateUpdateBlockForPlayer(*buf, plObj);
					plObj->PushCreationData(*buf, count);
					plObj->AddVisibleObject(curObj);
					(*buf)->clear();
				}
			}

		IN_RANGE_LOOP_P3
	} else if(obj->NeedsInRangeSet())
	{
		IN_RANGE_LOOP_P1
			obj->AddInRangeObject(curObj);
		IN_RANGE_LOOP_P2
		IN_RANGE_LOOP_P3
	}
	else
	{
		IN_RANGE_LOOP_P1
			if(curObj->IsPlayer())
				obj->AddInRangePlayer(obj);

		IN_RANGE_LOOP_P2
		IN_RANGE_LOOP_P3
	}

#undef IN_RANGE_LOOP_P1
#undef IN_RANGE_LOOP_P2
#undef IN_RANGE_LOOP_P3*/
}
Example #4
0
void MapMgr::ChangeObjectLocation( Object *obj )
{
	// Items and containers are of no interest for us
	if( obj->GetTypeId() == TYPEID_ITEM || obj->GetTypeId() == TYPEID_CONTAINER || obj->GetMapMgr() != this )
	{
		return;
	}

	Player* plObj;
	ByteBuffer * buf = 0;

	if( obj->GetTypeId() == TYPEID_PLAYER )
	{
		plObj = static_cast< Player* >( obj );
	}
	else
	{
		plObj = NULL;
	}

	Object* curObj;
	float fRange;

	///////////////////////////////////////
	// Update in-range data for old objects
	///////////////////////////////////////

	/** let's duplicate some code here :P Less branching is always good.
	 * - Burlex
	 */
/*#define IN_RANGE_LOOP \
	for (Object::InRangeSet::iterator iter = obj->GetInRangeSetBegin(), iter2; \
		iter != obj->GetInRangeSetEnd();) \
	{ \
		curObj = *iter; \
		iter2 = iter; \
		++iter; \
		if(curObj->IsPlayer() && obj->IsPlayer() && plObj->m_TransporterGUID && plObj->m_TransporterGUID == static_cast< Player* >( curObj )->m_TransporterGUID ) \
			fRange = 0.0f;		\
		else if((curObj->GetGUIDHigh() == HIGHGUID_TRANSPORTER || obj->GetGUIDHigh() == HIGHGUID_TRANSPORTER)) \
			fRange = 0.0f;		\
		else if((curObj->GetGUIDHigh() == HIGHGUID_GAMEOBJECT && curObj->GetUInt32Value(GAMEOBJECT_TYPE_ID) == GAMEOBJECT_TYPE_TRANSPORT || obj->GetGUIDHigh() == HIGHGUID_GAMEOBJECT && obj->GetUInt32Value(GAMEOBJECT_TYPE_ID) == GAMEOBJECT_TYPE_TRANSPORT)) \
			fRange = 0.0f;		\
		else \
			fRange = m_UpdateDistance;	\
		if (curObj->GetDistance2dSq(obj) > fRange && fRange > 0) \

#define END_IN_RANGE_LOOP } \

	if(plObj)
	{
		IN_RANGE_LOOP
		{
			plObj->RemoveIfVisible(curObj);
			plObj->RemoveInRangeObject(iter2);

			if(curObj->NeedsInRangeSet())
				curObj->RemoveInRangeObject(obj);

			if(curObj->IsPlayer())
				static_cast< Player* >( curObj )->RemoveIfVisible(obj);
		}
		END_IN_RANGE_LOOP
	}
	else if(obj->NeedsInRangeSet())
	{
		IN_RANGE_LOOP
		{
			if(curObj->NeedsInRangeSet())
				curObj->RemoveInRangeObject(obj);

			if(curObj->IsPlayer())
				static_cast< Player* >( curObj )->RemoveIfVisible(obj);

			obj->RemoveInRangeObject(iter2);
		}
		END_IN_RANGE_LOOP
	}
	else
	{
		IN_RANGE_LOOP
		{
			if(curObj->NeedsInRangeSet())
				curObj->RemoveInRangeObject(obj);

			if(curObj->IsPlayer())
			{
				static_cast< Player* >( curObj )->RemoveIfVisible(obj);
				obj->RemoveInRangePlayer(curObj);
			}
		}
		END_IN_RANGE_LOOP
	}

#undef IN_RANGE_LOOP
#undef END_IN_RANGE_LOOP*/

	if(obj->HasInRangeObjects()) {
		for (Object::InRangeSet::iterator iter = obj->GetInRangeSetBegin(), iter2;
			iter != obj->GetInRangeSetEnd();)
		{
			curObj = *iter;
			iter2 = iter++;
			if( curObj->IsPlayer() && obj->IsPlayer() && plObj->m_TransporterGUID && plObj->m_TransporterGUID == static_cast< Player* >( curObj )->m_TransporterGUID )
				fRange = 0.0f; // unlimited distance for people on same boat
			else if( curObj->GetTypeFromGUID() == HIGHGUID_TYPE_TRANSPORTER )
				fRange = 0.0f; // unlimited distance for transporters (only up to 2 cells +/- anyway.)
			else
				fRange = m_UpdateDistance; // normal distance

			if( fRange > 0.0f && curObj->GetDistance2dSq(obj) > fRange )
			{
				if( plObj )
					plObj->RemoveIfVisible(curObj);

				if( curObj->IsPlayer() )
					static_cast< Player* >( curObj )->RemoveIfVisible(obj);

				curObj->RemoveInRangeObject(obj);

				if( obj->GetMapMgr() != this )
				{
					/* Something removed us. */
					return;
				}
				obj->RemoveInRangeObject(iter2);
			}
		}
	}

	///////////////////////////
	// Get new cell coordinates
	///////////////////////////
	if(obj->GetMapMgr() != this)
	{
		/* Something removed us. */
		return;
	}

	if(obj->GetPositionX() >= _maxX || obj->GetPositionX() <= _minX ||
		obj->GetPositionY() >= _maxY || obj->GetPositionY() <= _minY)
	{
		if(obj->IsPlayer())
		{
			Player* plr = static_cast< Player* >( obj );
			if(plr->GetBindMapId() != GetMapId())
			{
				plr->SafeTeleport(plr->GetBindMapId(),0,plr->GetBindPositionX(),plr->GetBindPositionY(),plr->GetBindPositionZ(),0);
				plr->GetSession()->SystemMessage("Teleported you to your hearthstone location as you were out of the map boundaries.");
				return;
			}
			else
			{
				obj->GetPositionV()->ChangeCoords(plr->GetBindPositionX(),plr->GetBindPositionY(),plr->GetBindPositionZ(),0);
				plr->GetSession()->SystemMessage("Teleported you to your hearthstone location as you were out of the map boundaries.");
				WorldPacket * data = plr->BuildTeleportAckMsg(plr->GetPosition());
				plr->GetSession()->SendPacket(data);
				delete data;
			}
		}
		else
		{
			obj->GetPositionV()->ChangeCoords(0,0,0,0);
		}
	}

	uint32 cellX = GetPosX(obj->GetPositionX());
	uint32 cellY = GetPosY(obj->GetPositionY());

	if(cellX >= _sizeX || cellY >= _sizeY)
	{
		return;
	}

	MapCell *objCell = GetCell(cellX, cellY);
	MapCell * pOldCell = obj->GetMapCell();
	if (!objCell)
	{
		objCell = Create(cellX,cellY);
		objCell->Init(cellX, cellY, _mapId, this);
	}

	// If object moved cell
	if (objCell != obj->GetMapCell())
	{
		// THIS IS A HACK!
		// Current code, if a creature on a long waypoint path moves from an active
		// cell into an inactive one, it will disable itself and will never return.
		// This is to prevent cpu leaks. I will think of a better solution very soon :P

		if(!objCell->IsActive() && !plObj && obj->Active)
			obj->Deactivate(this);

		if(obj->GetMapCell())
			obj->GetMapCell()->RemoveObject(obj);
	
		objCell->AddObject(obj);
		obj->SetMapCell(objCell);

		// if player we need to update cell activity
		// radius = 2 is used in order to update both
		// old and new cells
		if(obj->GetTypeId() == TYPEID_PLAYER)
		{
			// have to unlock/lock here to avoid a deadlock situation.
			UpdateCellActivity(cellX, cellY, 2);
			if( pOldCell != NULL )
			{
				// only do the second check if theres -/+ 2 difference
				if( abs( (int)cellX - (int)pOldCell->_x ) > 2 ||
					abs( (int)cellY - (int)pOldCell->_y ) > 2 )
				{
					UpdateCellActivity( pOldCell->_x, pOldCell->_y, 2 );
				}
			}
		}
	}


	//////////////////////////////////////
	// Update in-range set for new objects
	//////////////////////////////////////

	uint32 endX = cellX <= _sizeX ? cellX + 1 : (_sizeX-1);
	uint32 endY = cellY <= _sizeY ? cellY + 1 : (_sizeY-1);
	uint32 startX = cellX > 0 ? cellX - 1 : 0;
	uint32 startY = cellY > 0 ? cellY - 1 : 0;
	uint32 posX, posY;
	MapCell *cell;
	MapCell::ObjectSet::iterator iter;

	for (posX = startX; posX <= endX; ++posX )
	{
		for (posY = startY; posY <= endY; ++posY )
		{
			cell = GetCell(posX, posY);
			if (cell)
			UpdateInRangeSet(obj, plObj, cell, &buf);
		}
	}

	if(buf)
		delete buf;
}
Example #5
0
void MapMgr::ChangeObjectLocation(Object *obj)
{
    ASSERT(obj);
    ASSERT(obj->GetMapId() == _mapId);
    ASSERT(_cells);

    if(obj->GetTypeId() == TYPEID_ITEM || obj->GetTypeId() == TYPEID_CONTAINER)
        return;

    WorldPacket packet;
    UpdateData data;
    UpdateData playerData;

    Object* curObj;

    for (Object::InRangeSet::iterator iter = obj->GetInRangeSetBegin();
        iter != obj->GetInRangeSetEnd();)
    {
        curObj = *iter;
        iter++;

        if (curObj->GetDistance2dSq(obj) > UPDATE_DISTANCE*UPDATE_DISTANCE)
        {
            sLog.outDetail("Object "I64FMT" no longer in field of view of object "I64FMT".",
                obj->GetGUID(), (curObj)->GetGUID());

            if( obj->GetTypeId() == TYPEID_PLAYER )
                curObj->BuildOutOfRangeUpdateBlock( &playerData );

            obj->RemoveInRangeObject(curObj);

            if( curObj->GetTypeId() == TYPEID_PLAYER )
            {
                data.Clear();
                obj->BuildOutOfRangeUpdateBlock( &data );
                data.BuildPacket(&packet);
                ((Player*)curObj)->GetSession()->SendPacket( &packet );
            }

            curObj->RemoveInRangeObject(obj);
        }
    }

    uint32 cellX = (uint32)(obj->GetPositionX() > 0 ? abs(_minX) + obj->GetPositionX() :
    abs(_minX) - abs(obj->GetPositionX()));
    uint32 cellY = (uint32)(obj->GetPositionY() > 0 ? abs(_minY) + obj->GetPositionY() :
    abs(_minY) - abs(obj->GetPositionY()));
    cellX /= _sizeX;
    cellY /= _sizeY;

/*
    sLog.outDetail("Obj position: %f %f Cell position: %u %u",
    obj->GetPositionX(), obj->GetPositionY(), cellX, cellY);
*/

    MapCell *objCell = &(_cells[cellX][cellY]);

    if (objCell != obj->GetMapCell())
    {
        obj->GetMapCell()->RemoveObject(obj);
        objCell->AddObject(obj);
        obj->SetMapCell(objCell);
    }

    uint32 endX = cellX < _sizeX ? cellX + 1 : _sizeX;
    uint32 endY = cellY < _sizeY ? cellY + 1 : _sizeY;
    uint32 startX = cellX > 0 ? cellX - 1 : 0;
    uint32 startY = cellY > 0 ? cellY - 1 : 0;
    uint32 posX, posY;
    MapCell *cell;
    MapCell::ObjectSet::iterator iter;

    for (posX = startX; posX <= endX; posX++ )
    {
        for (posY = startY; posY <= endY; posY++ )
        {
            cell = &(_cells[posX][posY]);
            ASSERT(cell);

            for (iter = cell->Begin(); iter != cell->End(); iter++)
            {
                curObj = *iter;
                if (curObj != obj &&
                    (curObj)->GetDistance2dSq(obj) <= UPDATE_DISTANCE*UPDATE_DISTANCE &&
                    !obj->IsInRangeSet(curObj))
                {
                    // Object in range, add to set
                    if((curObj)->GetTypeId() == TYPEID_PLAYER)
                    {
                        sLog.outDetail("Creating object "I64FMT" for player "I64FMT".",
                            obj->GetGUID(), (curObj)->GetGUID());

                        data.Clear();
                        obj->BuildCreateUpdateBlockForPlayer( &data, (Player*)curObj );
                        data.BuildPacket(&packet);

                        ((Player*)curObj)->GetSession()->SendPacket( &packet );
                    }

                    (curObj)->AddInRangeObject(obj);

                    if(obj->GetTypeId() == TYPEID_PLAYER)
                    {
                        sLog.outDetail("Creating object "I64FMT" for player "I64FMT".",
                            (curObj)->GetGUID(), obj->GetGUID());

                        (curObj)->BuildCreateUpdateBlockForPlayer( &playerData, (Player*)obj );
                    }

                    obj->AddInRangeObject(curObj);
                }
            }
        }
    }

    if (obj->GetTypeId() == TYPEID_PLAYER)
    {
        playerData.BuildPacket(&packet);
        ((Player*)obj)->GetSession()->SendPacket( &packet );
    }
}
Example #6
0
void MapMgr::UpdateInRangeSet(Object* obj, Player* plObj, MapCell* cell, ByteBuffer** buf)
{
#define CHECK_BUF if(!*buf) *buf = new ByteBuffer(2500)

	if(cell == NULL)
		return;

	Object* curObj;
	Player* plObj2;
	int count;
	float fRange;
	bool cansee, isvisible;

	ObjectSet::iterator iter = cell->Begin();
	while(iter != cell->End())
	{
		curObj = *iter;
		++iter;

		if(curObj == NULL)
			continue;

		if(curObj->IsPlayer() && obj->IsPlayer() && plObj != NULL && plObj->transporter_info.guid && plObj->transporter_info.guid == TO< Player* >(curObj)->transporter_info.guid)
			fRange = 0.0f; // unlimited distance for people on same boat
		else if(curObj->GetTypeFromGUID() == HIGHGUID_TYPE_TRANSPORTER)
			fRange = 0.0f; // unlimited distance for transporters (only up to 2 cells +/- anyway.)

		//If the object announcing its position is a transport, or other special object, then deleting it from visible objects should be avoided. - By: VLack
		else if(obj->IsGameObject() && (TO< GameObject* >(obj)->GetOverrides() & GAMEOBJECT_INFVIS) && obj->GetMapId() == curObj->GetMapId())
			fRange = 0.0f;
		//If the object we're checking for possible removal is a transport or other special object, and we are players on the same map, don't remove it, and add it whenever possible...
		else if(plObj && curObj->IsGameObject() && (TO< GameObject* >(curObj)->GetOverrides() & GAMEOBJECT_INFVIS) && obj->GetMapId() == curObj->GetMapId())
			fRange = 0.0f;
		else
			fRange = m_UpdateDistance; // normal distance

		if(curObj != obj && (curObj->GetDistance2dSq(obj) <= fRange || fRange == 0.0f))
		{
			if(!obj->IsInRangeSet(curObj))
			{
				// Object in range, add to set
				obj->AddInRangeObject(curObj);
				curObj->AddInRangeObject(obj);

				if(curObj->IsPlayer())
				{
					plObj2 = TO< Player* >(curObj);

					if(plObj2->CanSee(obj) && !plObj2->IsVisible(obj->GetGUID()))
					{
						CHECK_BUF;
						count = obj->BuildCreateUpdateBlockForPlayer(*buf, plObj2);
						plObj2->PushCreationData(*buf, count);
						plObj2->AddVisibleObject(obj->GetGUID());
						(*buf)->clear();
					}
				}

				if(plObj != NULL)
				{
					if(plObj->CanSee(curObj) && !plObj->IsVisible(curObj->GetGUID()))
					{
						CHECK_BUF;
						count = curObj->BuildCreateUpdateBlockForPlayer(*buf, plObj);
						plObj->PushCreationData(*buf, count);
						plObj->AddVisibleObject(curObj->GetGUID());
						(*buf)->clear();
					}
				}
			}
			else
			{
				// Check visibility
				if(curObj->IsPlayer())
				{
					plObj2 = TO< Player* >(curObj);
					cansee = plObj2->CanSee(obj);
					isvisible = plObj2->IsVisible(obj->GetGUID());
					if(!cansee && isvisible)
					{
						plObj2->PushOutOfRange(obj->GetNewGUID());
						plObj2->RemoveVisibleObject(obj->GetGUID());
					}
					else if(cansee && !isvisible)
					{
						CHECK_BUF;
						count = obj->BuildCreateUpdateBlockForPlayer(*buf, plObj2);
						plObj2->PushCreationData(*buf, count);
						plObj2->AddVisibleObject(obj->GetGUID());
						(*buf)->clear();
					}
				}

				if(plObj != NULL)
				{
					cansee = plObj->CanSee(curObj);
					isvisible = plObj->IsVisible(curObj->GetGUID());
					if(!cansee && isvisible)
					{
						plObj->PushOutOfRange(curObj->GetNewGUID());
						plObj->RemoveVisibleObject(curObj->GetGUID());
					}
					else if(cansee && !isvisible)
					{
						CHECK_BUF;
						count = curObj->BuildCreateUpdateBlockForPlayer(*buf, plObj);
						plObj->PushCreationData(*buf, count);
						plObj->AddVisibleObject(curObj->GetGUID());
						(*buf)->clear();
					}
				}
			}
		}
	}
}
Example #7
0
void MapMgr::ChangeObjectLocation(Object* obj)
{
	/*
	if ( !obj ) return; // crashfix
	*/

	ARCEMU_ASSERT(obj != NULL);

	// Items and containers are of no interest for us
	if(obj->IsItem() || obj->IsContainer() || obj->GetMapMgr() != this)
	{
		return;
	}

	Player* plObj = NULL;
	ByteBuffer* buf = 0;

	if(obj->IsPlayer())
	{
		plObj = TO< Player* >(obj);
	}

	Object* curObj;
	float fRange = 0.0f;

	///////////////////////////////////////
	// Update in-range data for old objects
	///////////////////////////////////////

	if(obj->HasInRangeObjects())
	{
		for(Object::InRangeSet::iterator iter = obj->GetInRangeSetBegin(); iter != obj->GetInRangeSetEnd();)
		{
			curObj = *iter;
			++iter;

			if(curObj->IsPlayer() && plObj != NULL && plObj->transporter_info.guid && plObj->transporter_info.guid == TO< Player* >(curObj)->transporter_info.guid)
				fRange = 0.0f; // unlimited distance for people on same boat
			else if(curObj->GetTypeFromGUID() == HIGHGUID_TYPE_TRANSPORTER)
				fRange = 0.0f; // unlimited distance for transporters (only up to 2 cells +/- anyway.)
			//If the object announcing its position is a transport, or other special object, then deleting it from visible objects should be avoided. - By: VLack
			else if(obj->IsGameObject() && (TO< GameObject* >(obj)->GetOverrides() & GAMEOBJECT_INFVIS) && obj->GetMapId() == curObj->GetMapId())
				fRange = 0.0f;
			//If the object we're checking for possible removal is a transport or other special object, and we are players on the same map, don't remove it...
			else if(plObj && curObj->IsGameObject() && (TO< GameObject* >(curObj)->GetOverrides() & GAMEOBJECT_INFVIS) && obj->GetMapId() == curObj->GetMapId())
				fRange = 0.0f;
			else if(curObj->IsPlayer() && TO< Player* >(curObj)->GetFarsightTarget() == obj->GetGUID())
				fRange = 0.0f;//Mind Vision, Eye of Kilrogg
			else
				fRange = m_UpdateDistance; // normal distance

			if(fRange > 0.0f && (curObj->GetDistance2dSq(obj) > fRange))
			{
				if(plObj != NULL)
					plObj->RemoveIfVisible(curObj->GetGUID());

				if(curObj->IsPlayer())
					TO< Player* >(curObj)->RemoveIfVisible(obj->GetGUID());

				curObj->RemoveInRangeObject(obj);

				if(obj->GetMapMgr() != this)
				{
					/* Something removed us. */
					return;
				}
				obj->RemoveInRangeObject(curObj);
			}
		}
	}

	///////////////////////////
	// Get new cell coordinates
	///////////////////////////
	if(obj->GetMapMgr() != this)
	{
		/* Something removed us. */
		return;
	}

	if(obj->GetPositionX() >= _maxX || obj->GetPositionX() <= _minX ||
	        obj->GetPositionY() >= _maxY || obj->GetPositionY() <= _minY)
	{
		if(plObj != NULL)
		{
			if(plObj->GetBindMapId() != GetMapId())
			{
				plObj->SafeTeleport(plObj->GetBindMapId(), 0, plObj->GetBindPositionX(), plObj->GetBindPositionY(), plObj->GetBindPositionZ(), 0);
				plObj->GetSession()->SystemMessage("Teleported you to your hearthstone location as you were out of the map boundaries.");
				return;
			}
			else
			{
				obj->GetPositionV()->ChangeCoords(plObj->GetBindPositionX(), plObj->GetBindPositionY(), plObj->GetBindPositionZ(), 0);
				plObj->GetSession()->SystemMessage("Teleported you to your hearthstone location as you were out of the map boundaries.");
				plObj->SendTeleportAckMsg(plObj->GetPosition());
			}
		}
		else
		{
			obj->GetPositionV()->ChangeCoords(0, 0, 0, 0);
		}
	}

	uint32 cellX = GetPosX(obj->GetPositionX());
	uint32 cellY = GetPosY(obj->GetPositionY());

	if(cellX >= _sizeX || cellY >= _sizeY)
	{
		return;
	}

	MapCell* objCell = GetCell(cellX, cellY);
	MapCell* pOldCell = obj->GetMapCell();
	if(objCell == NULL)
	{
		objCell = Create(cellX, cellY);
		objCell->Init(cellX, cellY, this);
	}

	ARCEMU_ASSERT(objCell != NULL);

	// If object moved cell
	if(objCell != pOldCell)
	{
		// THIS IS A HACK!
		// Current code, if a creature on a long waypoint path moves from an active
		// cell into an inactive one, it will disable itself and will never return.
		// This is to prevent cpu leaks. I will think of a better solution very soon :P

		if(!objCell->IsActive() && !plObj && obj->IsActive())
			obj->Deactivate(this);

		if(pOldCell != NULL)
			pOldCell->RemoveObject(obj);

		objCell->AddObject(obj);
		obj->SetMapCell(objCell);

		// if player we need to update cell activity
		// radius = 2 is used in order to update both
		// old and new cells
		if(obj->IsPlayer())
		{
			// have to unlock/lock here to avoid a deadlock situation.
			UpdateCellActivity(cellX, cellY, 2);
			if(pOldCell != NULL)
			{
				// only do the second check if there's -/+ 2 difference
				if(abs((int)cellX - (int)pOldCell->_x) > 2 ||
				        abs((int)cellY - (int)pOldCell->_y) > 2)
				{
					UpdateCellActivity(pOldCell->_x, pOldCell->_y, 2);
				}
			}
		}
	}


	//////////////////////////////////////
	// Update in-range set for new objects
	//////////////////////////////////////

	uint32 endX = cellX <= _sizeX ? cellX + 1 : (_sizeX - 1);
	uint32 endY = cellY <= _sizeY ? cellY + 1 : (_sizeY - 1);
	uint32 startX = cellX > 0 ? cellX - 1 : 0;
	uint32 startY = cellY > 0 ? cellY - 1 : 0;
	uint32 posX, posY;
	MapCell* cell;

	//If the object announcing it's position is a special one, then it should do so in a much wider area - like the distance between the two transport towers in Orgrimmar, or more. - By: VLack
	if(obj->IsGameObject() && (TO< GameObject* >(obj)->GetOverrides() & GAMEOBJECT_ONMOVEWIDE))
	{
		endX = cellX + 5 <= _sizeX ? cellX + 6 : (_sizeX - 1);
		endY = cellY + 5 <= _sizeY ? cellY + 6 : (_sizeY - 1);
		startX = cellX > 5 ? cellX - 6 : 0;
		startY = cellY > 5 ? cellY - 6 : 0;
	}

	for(posX = startX; posX <= endX; ++posX)
	{
		for(posY = startY; posY <= endY; ++posY)
		{
			cell = GetCell(posX, posY);
			if(cell)
				UpdateInRangeSet(obj, plObj, cell, &buf);
		}
	}

	if(buf)
		delete buf;
}