void MoonInstanceScript::SetCellForcedStates(float pMinX, float pMaxX, float pMinY, float pMaxY, bool pActivate) { if(pMinX == pMaxX || pMinY == pMaxY) return; float Y = pMinY; while(pMinX < pMaxX) { while(pMinY < pMaxY) { MapCell* CurrentCell = mInstance->GetCellByCoords(pMinX, pMinY); if(pActivate && CurrentCell == NULL) { CurrentCell = mInstance->CreateByCoords(pMinX, pMinY); if(CurrentCell != NULL) CurrentCell->Init(mInstance->GetPosX(pMinX), mInstance->GetPosY(pMinY), mInstance); } if(CurrentCell != NULL) pActivate ? mInstance->AddForcedCell(CurrentCell) : mInstance->RemoveForcedCell(CurrentCell); pMinY += 40.0f; } pMinY = Y; pMinX += 40.0f; } }
void MapMgr::SendChatMessageToCellPlayers(Object * obj, WorldPacket * packet, uint32 cell_radius, uint32 langpos, int32 lang, WorldSession * originator) { uint32 cellX = GetPosX(obj->GetPositionX()); uint32 cellY = GetPosY(obj->GetPositionY()); uint32 endX = ((cellX+cell_radius) <= _sizeX) ? cellX + cell_radius : (_sizeX-1); uint32 endY = ((cellY+cell_radius) <= _sizeY) ? cellY + cell_radius : (_sizeY-1); uint32 startX = (cellX-cell_radius) > 0 ? cellX - cell_radius : 0; uint32 startY = (cellY-cell_radius) > 0 ? cellY - cell_radius : 0; uint32 posX, posY; MapCell *cell; MapCell::ObjectSet::iterator iter, iend; for (posX = startX; posX <= endX; ++posX ) { for (posY = startY; posY <= endY; ++posY ) { cell = GetCell(posX, posY); if (cell && cell->HasPlayers() ) { iter = cell->Begin(); iend = cell->End(); for(; iter != iend; ++iter) { if((*iter)->IsPlayer()) { //static_cast< Player* >(*iter)->GetSession()->SendPacket(packet); static_cast< Player* >(*iter)->GetSession()->SendChatPacket(packet, langpos, lang, originator); } } } } } }
bool MapMgr::_CellActive(uint32 x, uint32 y) { uint32 endX = ((x+1) <= _sizeX) ? x + 1 : (_sizeX-1); uint32 endY = ((y+1) <= _sizeY) ? y + 1 : (_sizeY-1); uint32 startX = x > 0 ? x - 1 : 0; uint32 startY = y > 0 ? y - 1 : 0; uint32 posX, posY; MapCell *objCell; for (posX = startX; posX <= endX; posX++ ) { for (posY = startY; posY <= endY; posY++ ) { objCell = GetCell(posX, posY); if (objCell) { if (objCell->HasPlayers()) { return true; } } } } return false; }
void SystemManager::select_stage_code_map(int stage_id) { vector<MapCell>& map = Stage::GetInstance() -> m_Map; map.clear(); try { Kompex::SQLiteDatabase *pDatabase = new Kompex::SQLiteDatabase(m_db_full_path.c_str(), SQLITE_OPEN_READWRITE, 0); Kompex::SQLiteStatement *pStmt = new Kompex::SQLiteStatement(pDatabase); pStmt -> Sql("SELECT * FROM stage_code_map WHERE stage_id = @stage_id"); pStmt -> BindInt(1, stage_id); while (pStmt -> FetchRow()) { MapCell mc; CCPoint loc = Stage::GetInstance() -> idx2loc(pStmt -> GetColumnInt("cell_idx")); mc.setMapCell(loc, (enumMapCellCode)(pStmt -> GetColumnInt("cell_code"))); mc.poll_code = (enumMapCellPollCode)(pStmt -> GetColumnInt("cell_poll_code")); //mc.setPollCode((enumMapCellPollCode)(pStmt -> GetColumnInt("cell_poll_code"))); map.push_back(mc); } delete pStmt; delete pDatabase; } catch(Kompex::SQLiteException &exception) { //std::cerr << "\nException Occured" << std::endl; CCLOGERROR("\nException Occured: \n%s", exception.GetString().c_str()); exception.Show(); } }
void MapMgr::UnloadCell(uint32 x,uint32 y) { MapCell * c = GetCell(x,y); if(c == NULL || c->HasPlayers() || _CellActive(x,y) || !c->IsUnloadPending()) return; sLog.outDetail("Unloading Cell [%d][%d] on map %d (instance %d)...", x,y,_mapId,m_instanceID); c->Unload(); }
void MapMgr::UnloadCell(uint32 x, uint32 y) { MapCell* c = GetCell(x, y); if(c == NULL || c->HasPlayers() || _CellActive(x, y) || !c->IsUnloadPending()) return; LOG_DETAIL("Unloading Cell [%u][%u] on map %u (instance %u)...", x, y, _mapId, m_instanceID); c->Unload(); }
void MapMgr::ChangeFarsightLocation(Player *plr, DynamicObject *farsight) { if(farsight == 0) { // We're clearing. for(ObjectSet::iterator itr = plr->m_visibleFarsightObjects.begin(); itr != plr->m_visibleFarsightObjects.end(); ++itr) { if(plr->IsVisible((*itr)) && !plr->CanSee((*itr))) { // Send destroy plr->PushOutOfRange((*itr)->GetNewGUID()); } } plr->m_visibleFarsightObjects.clear(); } else { uint32 cellX = GetPosX(farsight->GetPositionX()); uint32 cellY = GetPosY(farsight->GetPositionY()); 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) && farsight->GetDistance2dSq(obj) <= m_UpdateDistance) { ByteBuffer buf; count = obj->BuildCreateUpdateBlockForPlayer(&buf, plr); plr->PushCreationData(&buf, count); plr->m_visibleFarsightObjects.insert(obj); } } } } } } }
void Corpse::SetOwner(uint64 guid) { SetUInt64Value(CORPSE_FIELD_OWNER, guid); if(guid == 0) { //notify the MapCell that the Corpse has no more an owner so the MapCell can go idle (if there's nothing else) MapCell* cell = GetMapCell(); if(cell != NULL) cell->CorpseGoneIdle(this); } }
// Spawns the object too, without which you can not interact with the object GameObject* MapMgr::CreateAndSpawnGameObject(uint32 entryID, float x, float y, float z, float o, float scale) { GameObjectInfo* goi = GameObjectNameStorage.LookupEntry(entryID); if(!goi) { LOG_DEBUG("Error looking up entry in CreateAndSpawnGameObject"); return NULL; } LOG_DEBUG("CreateAndSpawnGameObject: By Entry '%u'", entryID); GameObject* go = CreateGameObject(entryID); //Player *chr = m_session->GetPlayer(); uint32 mapid = GetMapId(); // Setup game object go->CreateFromProto(entryID, mapid, x, y, z, o); go->SetScale(scale); go->InitAI(); go->PushToWorld(this); // Create spawn instance GOSpawn* gs = new GOSpawn; gs->entry = go->GetEntry(); gs->facing = go->GetOrientation(); gs->faction = go->GetFaction(); gs->flags = go->GetUInt32Value(GAMEOBJECT_FLAGS); gs->id = objmgr.GenerateGameObjectSpawnID(); gs->o = 0.0f; gs->o1 = go->GetParentRotation(0); gs->o2 = go->GetParentRotation(2); gs->o3 = go->GetParentRotation(3); gs->scale = go->GetScale(); gs->x = go->GetPositionX(); gs->y = go->GetPositionY(); gs->z = go->GetPositionZ(); gs->state = go->GetByte(GAMEOBJECT_BYTES_1, 0); //gs->stateNpcLink = 0; gs->overrides = go->GetOverrides(); uint32 cx = GetPosX(x); uint32 cy = GetPosY(y); GetBaseMap()->GetSpawnsListAndCreate(cx, cy)->GOSpawns.push_back(gs); go->m_spawn = gs; MapCell* mCell = GetCell(cx, cy); if(mCell != NULL) mCell->SetLoaded(); return go; }
bool ChatHandler::HandleGOPhaseCommand(const char* args, WorldSession* m_session) { char* sPhase = strtok((char*)args, " "); if(!sPhase) return false; uint32 newphase = atoi(sPhase); bool Save = false; char* pSave = strtok(NULL, " "); if(pSave) Save = (atoi(pSave) > 0 ? true : false); GameObject* go = m_session->GetPlayer()->GetSelectedGo(); if(!go) { RedSystemMessage(m_session, "No selected GameObject..."); return true; } go->Phase(PHASE_SET, newphase); GOSpawn* gs = go->m_spawn; if(gs == NULL) { RedSystemMessage(m_session, "The GameObject got no spawn, not saving and not logging..."); return true; } //VLack: We have to have a spawn, or SaveToDB would write a 0 into the first column (ID), and would erroneously overwrite something in the DB. //The code which saves creatures is a bit more forgiving, as it creates a new spawn on-demand, but the gameobject code does not. gs->phase = go->GetPhase(); uint32 cx = m_session->GetPlayer()->GetMapMgr()->GetPosX(m_session->GetPlayer()->GetPositionX()); uint32 cy = m_session->GetPlayer()->GetMapMgr()->GetPosY(m_session->GetPlayer()->GetPositionY()); MapCell* mCell = m_session->GetPlayer()->GetMapMgr()->GetCell(cx, cy); if(mCell != NULL) mCell->SetLoaded(); if(Save == true) { // If we're saving, create template and add index go->SaveToDB(); go->m_loadedFromDB = true; } sGMLog.writefromsession(m_session, "phased gameobject %s to %u, entry %u at %u %f %f %f%s", GameObjectNameStorage.LookupEntry(gs->entry)->Name, newphase, gs->entry, m_session->GetPlayer()->GetMapId(), gs->x, gs->y, gs->z, Save ? ", saved in DB" : ""); return true; }
void MapMgr::RemoveObject(Object *obj) { ASSERT(obj); ASSERT(obj->GetMapId() == _mapId); ASSERT(obj->GetPositionX() > _minX && obj->GetPositionX() < _maxX); ASSERT(obj->GetPositionY() > _minY && obj->GetPositionY() < _maxY); ASSERT(_cells); sLog.outDetail("Removing object "I64FMT" with type %i from the world.", obj->GetGUID(), obj->GetTypeId()); // That object types are not map objects. TODO: add AI groups here? if(obj->GetTypeId() == TYPEID_ITEM || obj->GetTypeId() == TYPEID_CONTAINER) { // remove updatable flag and exit obj->RemoveFromWorld(); return; } obj->RemoveFromWorld(); ObjectMap::iterator itr = _objects.find(obj->GetGUID()); _objects.erase(itr); // remove us from updated objects list ObjectSet::iterator updi = _updatedObjects.find(obj); if(updi != _updatedObjects.end()) _updatedObjects.erase(updi); MapCell *objCell = obj->GetMapCell(); obj->SetMapCell(0); objCell->RemoveObject(obj); for (Object::InRangeSet::iterator iter = obj->GetInRangeSetBegin(); iter != obj->GetInRangeSetEnd(); iter++) { (*iter)->RemoveInRangeObject(obj); if((*iter)->GetTypeId() == TYPEID_PLAYER) obj->DestroyForPlayer( (Player*)*iter ); } obj->ClearInRangeSet(); }
void MapMgr::LoadAllCells() { // eek MapCell * cellInfo; CellSpawns * spawns; for( uint32 x = 0 ; x < _sizeX ; x ++ ) { for( uint32 y = 0 ; y < _sizeY ; y ++ ) { cellInfo = GetCell( x , y ); if( !cellInfo ) { // Cell doesn't exist, create it. // There is no spoon. Err... cell. cellInfo = Create( x , y ); cellInfo->Init( x , y , _mapId , this ); sLog.outDetail( "Created cell [%u,%u] on map %d (instance %d)." , x , y , _mapId , m_instanceID ); cellInfo->SetActivity( true ); _map->CellGoneActive( x , y ); ASSERT( !cellInfo->IsLoaded() ); spawns = _map->GetSpawnsList( x , y ); if( spawns ) cellInfo->LoadObjects( spawns ); } else { // Cell exists, but is inactive if ( !cellInfo->IsActive() ) { sLog.outDetail("Activated cell [%u,%u] on map %d (instance %d).", x, y, _mapId, m_instanceID ); _map->CellGoneActive( x , y ); cellInfo->SetActivity( true ); if (!cellInfo->IsLoaded()) { //sLog.outDetail("Loading objects for Cell [%d][%d] on map %d (instance %d)...", // posX, posY, this->_mapId, m_instanceID); spawns = _map->GetSpawnsList( x , y ); if( spawns ) cellInfo->LoadObjects( spawns ); } } } } } }
uint32 MapScriptInterface::GetPlayerCountInRadius(float x, float y, float z /* = 0.0f */, float radius /* = 5.0f */) { // use a cell radius of 2 uint32 PlayerCount = 0; uint32 cellX = mapMgr.GetPosX(x); uint32 cellY = mapMgr.GetPosY(y); 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; MapCell* pCell; ObjectSet::iterator iter, iter_end; for(uint32 cx = startX; cx < endX; ++cx) { for(uint32 cy = startY; cy < endY; ++cy) { pCell = mapMgr.GetCell(cx, cy); if(pCell == 0 || pCell->GetPlayerCount() == 0) continue; iter = pCell->Begin(); iter_end = pCell->End(); for(; iter != iter_end; ++iter) { if((*iter)->IsPlayer() && (*iter)->CalcDistance(x, y, (z == 0.0f ? (*iter)->GetPositionZ() : z)) < radius) { ++PlayerCount; } } } } return PlayerCount; }
bool ChatHandler::HandleGOSpawn(const char *args, WorldSession *m_session) { std::stringstream sstext; char* pEntryID = strtok((char*)args, " "); if (!pEntryID) return false; uint32 EntryID = atoi(pEntryID); bool Save = false; char* pSave = strtok(NULL, " "); if (pSave) Save = (atoi(pSave)>0?true:false); GameObjectInfo* goi = GameObjectNameStorage.LookupEntry(EntryID); if(!goi) { sstext << "GameObject Info '" << EntryID << "' Not Found" << '\0'; SystemMessage(m_session, sstext.str().c_str()); return true; } sLog.outDebug("Spawning GameObject By Entry '%u'", EntryID); sstext << "Spawning GameObject By Entry '" << EntryID << "'" << '\0'; SystemMessage(m_session, sstext.str().c_str()); GameObject *go = m_session->GetPlayer()->GetMapMgr()->CreateGameObject(EntryID); Player *chr = m_session->GetPlayer(); uint32 mapid = chr->GetMapId(); float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); go->SetInstanceID(chr->GetInstanceID()); go->CreateFromProto(EntryID,mapid,x,y,z,o); /* f**k blizz coordinate system */ go->SetFloatValue(GAMEOBJECT_ROTATION_02, sinf(o / 2)); go->SetFloatValue(GAMEOBJECT_ROTATION_03, cosf(o / 2)); go->PushToWorld(m_session->GetPlayer()->GetMapMgr()); // Create sapwn instance GOSpawn * gs = new GOSpawn; gs->entry = go->GetEntry(); gs->facing = go->GetOrientation(); gs->faction = go->GetUInt32Value(GAMEOBJECT_FACTION); gs->flags = go->GetUInt32Value(GAMEOBJECT_FLAGS); gs->id = objmgr.GenerateGameObjectSpawnID(); gs->o = go->GetFloatValue(GAMEOBJECT_ROTATION); gs->o1 = go->GetFloatValue(GAMEOBJECT_ROTATION_01); gs->o2 = go->GetFloatValue(GAMEOBJECT_ROTATION_02); gs->o3 = go->GetFloatValue(GAMEOBJECT_ROTATION_03); gs->scale = go->GetFloatValue(OBJECT_FIELD_SCALE_X); gs->x = go->GetPositionX(); gs->y = go->GetPositionY(); gs->z = go->GetPositionZ(); gs->state = go->GetUInt32Value(GAMEOBJECT_STATE); //gs->stateNpcLink = 0; uint32 cx = m_session->GetPlayer()->GetMapMgr()->GetPosX(m_session->GetPlayer()->GetPositionX()); uint32 cy = m_session->GetPlayer()->GetMapMgr()->GetPosY(m_session->GetPlayer()->GetPositionY()); m_session->GetPlayer()->GetMapMgr()->GetBaseMap()->GetSpawnsListAndCreate(cx,cy)->GOSpawns.push_back(gs); go->m_spawn = gs; MapCell * mCell = m_session->GetPlayer()->GetMapMgr()->GetCell( cx, cy ); if( mCell != NULL ) mCell->SetLoaded(); if(Save == true) { // If we're saving, create template and add index go->SaveToDB(); go->m_loadedFromDB = true; } sGMLog.writefromsession( m_session, "spawned gameobject %s, entry %u at %u %f %f %f%s", GameObjectNameStorage.LookupEntry(gs->entry)->Name, gs->entry, m_session->GetPlayer()->GetMapId(), gs->x, gs->y, gs->z, Save ? ", saved in DB" : "" ); return true; }
void MapMgr::PushObject(Object* obj) { ///////////// // Assertions ///////////// ARCEMU_ASSERT(obj != NULL); // That object types are not map objects. TODO: add AI groups here? if(obj->IsItem() || obj->IsContainer()) { // mark object as updatable and exit return; } if(obj->IsCorpse()) { m_corpses.insert(TO< Corpse* >(obj)); } obj->ClearInRangeSet(); ARCEMU_ASSERT(obj->GetMapId() == _mapId); if(!(obj->GetPositionX() < _maxX && obj->GetPositionX() > _minX) || !(obj->GetPositionY() < _maxY && obj->GetPositionY() > _minY)) { if(obj->IsPlayer()) { Player* plr = TO< 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."); plr->SendTeleportAckMsg(plr->GetPosition()); } } else { obj->GetPositionV()->ChangeCoords(0, 0, 0, 0); } } ARCEMU_ASSERT(obj->GetPositionY() < _maxY && obj->GetPositionY() > _minY); ARCEMU_ASSERT(_cells != NULL); /////////////////////// // Get cell coordinates /////////////////////// uint32 x = GetPosX(obj->GetPositionX()); uint32 y = GetPosY(obj->GetPositionY()); if(x >= _sizeX || y >= _sizeY) { if(obj->IsPlayer()) { Player* plr = TO< 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."); plr->SendTeleportAckMsg(plr->GetPosition()); } } else { obj->GetPositionV()->ChangeCoords(0, 0, 0, 0); } x = GetPosX(obj->GetPositionX()); y = GetPosY(obj->GetPositionY()); } MapCell* objCell = GetCell(x, y); if(objCell == NULL) { objCell = Create(x, y); objCell->Init(x, y, this); } ARCEMU_ASSERT(objCell != NULL); uint32 endX = (x <= _sizeX) ? x + 1 : (_sizeX - 1); uint32 endY = (y <= _sizeY) ? y + 1 : (_sizeY - 1); uint32 startX = x > 0 ? x - 1 : 0; uint32 startY = y > 0 ? y - 1 : 0; uint32 posX, posY; MapCell* cell; //MapCell::ObjectSet::iterator iter; ByteBuffer* buf = 0; uint32 count; Player* plObj; if(obj->IsPlayer()) plObj = TO< Player* >(obj); else plObj = NULL; if(plObj != NULL) { LOG_DETAIL("Creating player " I64FMT " for himself.", obj->GetGUID()); ByteBuffer pbuf(10000); count = plObj->BuildCreateUpdateBlockForPlayer(&pbuf, plObj); plObj->PushCreationData(&pbuf, count); } ////////////////////// // Build in-range data ////////////////////// for(posX = startX; posX <= endX; posX++) { for(posY = startY; posY <= endY; posY++) { cell = GetCell(posX, posY); if(cell) { UpdateInRangeSet(obj, plObj, cell, &buf); } } } //Add to the cell's object list objCell->AddObject(obj); obj->SetMapCell(objCell); //Add to the mapmanager's object list if(plObj != NULL) { m_PlayerStorage[plObj->GetLowGUID()] = plObj; UpdateCellActivity(x, y, 2); } else { switch(obj->GetTypeFromGUID()) { case HIGHGUID_TYPE_PET: m_PetStorage[obj->GetUIdFromGUID()] = TO< Pet* >(obj); break; case HIGHGUID_TYPE_UNIT: case HIGHGUID_TYPE_VEHICLE: { ARCEMU_ASSERT(obj->GetUIdFromGUID() <= m_CreatureHighGuid); CreatureStorage[ obj->GetUIdFromGUID() ] = TO< Creature* >(obj); if(TO_CREATURE(obj)->m_spawn != NULL) { _sqlids_creatures.insert(make_pair(TO_CREATURE(obj)->m_spawn->id, TO_CREATURE(obj))); } } break; case HIGHGUID_TYPE_GAMEOBJECT: { GOStorage[ obj->GetUIdFromGUID() ] = TO< GameObject* >(obj); if(TO_GAMEOBJECT(obj)->m_spawn != NULL) { _sqlids_gameobjects.insert(make_pair(TO_GAMEOBJECT(obj)->m_spawn->id, TO_GAMEOBJECT(obj))); } } break; case HIGHGUID_TYPE_DYNAMICOBJECT: m_DynamicObjectStorage[obj->GetLowGUID()] = (DynamicObject*)obj; break; } } // Handle activation of that object. if(objCell->IsActive() && obj->CanActivate()) obj->Activate(this); // Add the session to our set if it is a player. if(plObj != NULL) { Sessions.insert(plObj->GetSession()); // Change the instance ID, this will cause it to be removed from the world thread (return value 1) plObj->GetSession()->SetInstance(GetInstanceID()); /* Add the map wide objects */ if(_mapWideStaticObjects.size()) { uint32 globalcount = 0; if(!buf) buf = new ByteBuffer(300); for(set<Object*>::iterator itr = _mapWideStaticObjects.begin(); itr != _mapWideStaticObjects.end(); ++itr) { count = (*itr)->BuildCreateUpdateBlockForPlayer(buf, plObj); globalcount += count; } //VLack: It seems if we use the same buffer then it is a BAD idea to try and push created data one by one, add them at once! // If you try to add them one by one, then as the buffer already contains data, they'll end up repeating some object. // Like 6 object updates for Deeprun Tram, but the built package will contain these entries: 2AFD0, 2AFD0, 2AFD1, 2AFD0, 2AFD1, 2AFD2 if(globalcount > 0) plObj->PushCreationData(buf, globalcount); } } if(buf) delete buf; if(plObj != NULL && InactiveMoveTime && !forced_expire) InactiveMoveTime = 0; }
void MapMgr::RemoveObject(Object* obj, bool free_guid) { ///////////// // Assertions ///////////// ARCEMU_ASSERT(obj != NULL); ARCEMU_ASSERT(obj->GetMapId() == _mapId); //ARCEMU_ASSERT( obj->GetPositionX() > _minX && obj->GetPositionX() < _maxX); //ARCEMU_ASSERT( obj->GetPositionY() > _minY && obj->GetPositionY() < _maxY); ARCEMU_ASSERT(_cells != NULL); if(obj->IsActive()) obj->Deactivate(this); //there is a very small chance that on double player ports on same update player is added to multiple insertpools but not removed //one clear example was the double port proc when exploiting double resurrect m_objectinsertlock.Acquire(); m_objectinsertpool.erase(obj); m_objectinsertlock.Release(); _updates.erase(obj); obj->ClearUpdateMask(); /////////////////////////////////////// // Remove object from all needed places /////////////////////////////////////// switch(obj->GetTypeFromGUID()) { case HIGHGUID_TYPE_UNIT: case HIGHGUID_TYPE_VEHICLE: ARCEMU_ASSERT(obj->GetUIdFromGUID() <= m_CreatureHighGuid); CreatureStorage[ obj->GetUIdFromGUID() ] = NULL; if(TO_CREATURE(obj)->m_spawn != NULL) { _sqlids_creatures.erase(TO_CREATURE(obj)->m_spawn->id); } if(free_guid) _reusable_guids_creature.push_back(obj->GetUIdFromGUID()); break; case HIGHGUID_TYPE_PET: if(pet_iterator != m_PetStorage.end() && pet_iterator->second->GetGUID() == obj->GetGUID()) ++pet_iterator; m_PetStorage.erase(obj->GetUIdFromGUID()); break; case HIGHGUID_TYPE_DYNAMICOBJECT: m_DynamicObjectStorage.erase(obj->GetLowGUID()); break; case HIGHGUID_TYPE_GAMEOBJECT: ARCEMU_ASSERT(obj->GetUIdFromGUID() <= m_GOHighGuid); GOStorage[ obj->GetUIdFromGUID() ] = NULL; if(TO_GAMEOBJECT(obj)->m_spawn != NULL) { _sqlids_gameobjects.erase(TO_GAMEOBJECT(obj)->m_spawn->id); } if(free_guid) _reusable_guids_gameobject.push_back(obj->GetUIdFromGUID()); break; } // That object types are not map objects. TODO: add AI groups here? if(obj->IsItem() || obj->IsContainer()) { return; } if(obj->IsCorpse()) { m_corpses.erase(TO< Corpse* >(obj)); } MapCell* cell = GetCell(obj->GetMapCellX(), obj->GetMapCellY()); if(cell == NULL) { /* set the map cell correctly */ if(obj->GetPositionX() >= _maxX || obj->GetPositionX() <= _minY || obj->GetPositionY() >= _maxY || obj->GetPositionY() <= _minY) { // do nothing } else { cell = this->GetCellByCoords(obj->GetPositionX(), obj->GetPositionY()); obj->SetMapCell(cell); } } if(cell != NULL) { // Remove object from cell cell->RemoveObject(obj); // Unset object's cell obj->SetMapCell(NULL); } Player* plObj = NULL; // Clear any updates pending if(obj->IsPlayer()) { plObj = TO_PLAYER(obj); _processQueue.erase(plObj); plObj->ClearAllPendingUpdates(); } obj->RemoveSelfFromInrangeSets(); // Clear object's in-range set obj->ClearInRangeSet(); // If it's a player - update his nearby cells if(!_shutdown && obj->IsPlayer()) { // get x/y if(obj->GetPositionX() >= _maxX || obj->GetPositionX() <= _minY || obj->GetPositionY() >= _maxY || obj->GetPositionY() <= _minY) { // do nothing } else { uint32 x = GetPosX(obj->GetPositionX()); uint32 y = GetPosY(obj->GetPositionY()); UpdateCellActivity(x, y, 2); } m_PlayerStorage.erase(TO< Player* >(obj)->GetLowGUID()); } // Remove the session from our set if it is a player. if(obj->IsPlayer()) { for(set<Object*>::iterator itr = _mapWideStaticObjects.begin(); itr != _mapWideStaticObjects.end(); ++itr) { plObj->PushOutOfRange((*itr)->GetNewGUID()); } // Setting an instance ID here will trigger the session to be removed // by MapMgr::run(). :) plObj->GetSession()->SetInstance(0); // Add it to the global session set. // Don't "re-add" to session if it is being deleted. if(!plObj->GetSession()->bDeleted) sWorld.AddGlobalSession(plObj->GetSession()); } if(!HasPlayers()) { if(this->pInstance != NULL && this->pInstance->m_persistent) this->pInstance->m_creatorGroup = 0; if(!InactiveMoveTime && !forced_expire && GetMapInfo()->type != INSTANCE_NULL) { InactiveMoveTime = UNIXTIME + (MAPMGR_INACTIVE_MOVE_TIME * 60); Log.Debug("MapMgr", "Instance %u is now idle. (%s)", m_instanceID, GetBaseMap()->GetName()); } } }
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; }
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; }
bool ChatHandler::HandleVehicleSpawn(const char * args, WorldSession * m_session) { uint32 entry = atol(args); uint8 gender = 0; if(entry == 0) return false; CreatureProto * proto = CreatureProtoStorage.LookupEntry(entry); CreatureInfo * info = CreatureNameStorage.LookupEntry(entry); if(proto == 0 || info == 0) { RedSystemMessage(m_session, "Invalid entry id."); return true; } CreatureSpawn * sp = new CreatureSpawn; gender = info->GenerateModelId(&sp->displayid); sp->entry = entry; sp->entry = entry; sp->form = 0; sp->id = objmgr.GenerateCreatureSpawnID(); sp->movetype = 0; sp->x = m_session->GetPlayer()->GetPositionX(); sp->y = m_session->GetPlayer()->GetPositionY(); sp->z = m_session->GetPlayer()->GetPositionZ(); sp->o = m_session->GetPlayer()->GetOrientation(); sp->emote_state = 0; sp->flags = 0; sp->factionid = proto->Faction; sp->bytes0 = sp->setbyte(0,2,gender); sp->bytes1 = 0; sp->bytes2 = 0; //sp->respawnNpcLink = 0; sp->stand_state = 0; sp->channel_target_creature = sp->channel_target_go = sp->channel_spell = 0; sp->MountedDisplayID = 0; sp->Item1SlotDisplay = 0; sp->Item2SlotDisplay = 0; sp->Item3SlotDisplay = 0; Creature * p = m_session->GetPlayer()->GetMapMgr()->CreateCreature(entry, true); Arcemu::Util::ARCEMU_ASSERT( p != NULL ); p->Load(sp, (uint32)NULL, NULL); p->m_loadedFromDB = true; p->PushToWorld(m_session->GetPlayer()->GetMapMgr()); uint32 x = m_session->GetPlayer()->GetMapMgr()->GetPosX(m_session->GetPlayer()->GetPositionX()); uint32 y = m_session->GetPlayer()->GetMapMgr()->GetPosY(m_session->GetPlayer()->GetPositionY()); // Add spawn to map m_session->GetPlayer()->GetMapMgr()->GetBaseMap()->GetSpawnsListAndCreate( x, y)->CreatureSpawns.push_back(sp); MapCell * mCell = m_session->GetPlayer()->GetMapMgr()->GetCell( x, y ); if( mCell != NULL ) mCell->SetLoaded(); BlueSystemMessage(m_session, "Spawned a vehicle `%s` with entry %u at %f %f %f on map %u", info->Name, entry, sp->x, sp->y, sp->z, m_session->GetPlayer()->GetMapId()); sGMLog.writefromsession(m_session, "spawned a %s at %u %f %f %f", info->Name, m_session->GetPlayer()->GetMapId(),sp->x,sp->y,sp->z); return true; }
void MapMgr::PushObject(Object *obj) { ///////////// // Assertions ///////////// ASSERT(obj); // That object types are not map objects. TODO: add AI groups here? if(obj->GetTypeId() == TYPEID_ITEM || obj->GetTypeId() == TYPEID_CONTAINER) { // mark object as updatable and exit return; } if(obj->GetTypeId() == TYPEID_CORPSE) { m_corpses.insert(((Corpse*)obj)); } obj->ClearInRangeSet(); ASSERT(obj->GetMapId() == _mapId); 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); } } ASSERT(obj->GetPositionY() < _maxY && obj->GetPositionY() > _minY); ASSERT(_cells); /////////////////////// // Get cell coordinates /////////////////////// uint32 x = GetPosX(obj->GetPositionX()); uint32 y = GetPosY(obj->GetPositionY()); if(x >= _sizeX || y >= _sizeY) { 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); } x = GetPosX(obj->GetPositionX()); y = GetPosY(obj->GetPositionY()); } MapCell *objCell = GetCell(x,y); if (!objCell) { objCell = Create(x,y); objCell->Init(x, y, _mapId, this); } uint32 endX = (x <= _sizeX) ? x + 1 : (_sizeX-1); uint32 endY = (y <= _sizeY) ? y + 1 : (_sizeY-1); uint32 startX = x > 0 ? x - 1 : 0; uint32 startY = y > 0 ? y - 1 : 0; uint32 posX, posY; MapCell *cell; MapCell::ObjectSet::iterator iter; ByteBuffer * buf = 0; uint32 count; Player *plObj; if(obj->GetTypeId() == TYPEID_PLAYER) plObj = static_cast< Player* >( obj ); else plObj = NULL; if(plObj) { sLog.outDetail("Creating player "I64FMT" for himself.", obj->GetGUID()); ByteBuffer pbuf(10000); count = plObj->BuildCreateUpdateBlockForPlayer(&pbuf, plObj); plObj->PushCreationData(&pbuf, count); } ////////////////////// // Build in-range data ////////////////////// for (posX = startX; posX <= endX; posX++ ) { for (posY = startY; posY <= endY; posY++ ) { cell = GetCell(posX, posY); if (cell) { UpdateInRangeSet(obj, plObj, cell, &buf); } } } //Add to the cell's object list objCell->AddObject(obj); obj->SetMapCell(objCell); //Add to the mapmanager's object list if(plObj) { m_PlayerStorage[plObj->GetLowGUID()] = plObj; UpdateCellActivity(x, y, 2); } else { switch(obj->GetTypeFromGUID()) { case HIGHGUID_TYPE_PET: m_PetStorage[obj->GetUIdFromGUID()] = static_cast< Pet* >( obj ); break; case HIGHGUID_TYPE_UNIT: { ASSERT((obj->GetUIdFromGUID()) <= m_CreatureHighGuid); m_CreatureStorage[obj->GetUIdFromGUID()] = (Creature*)obj; if(((Creature*)obj)->m_spawn != NULL) { _sqlids_creatures.insert(make_pair( ((Creature*)obj)->m_spawn->id, ((Creature*)obj) ) ); } }break; case HIGHGUID_TYPE_GAMEOBJECT: { m_GOStorage[obj->GetUIdFromGUID()] = (GameObject*)obj; if(((GameObject*)obj)->m_spawn != NULL) { _sqlids_gameobjects.insert(make_pair( ((GameObject*)obj)->m_spawn->id, ((GameObject*)obj) ) ); } }break; case HIGHGUID_TYPE_DYNAMICOBJECT: m_DynamicObjectStorage[obj->GetLowGUID()] = (DynamicObject*)obj; break; } } // Handle activation of that object. if(objCell->IsActive() && obj->CanActivate()) obj->Activate(this); // Add the session to our set if it is a player. if(plObj) { Sessions.insert(plObj->GetSession()); // Change the instance ID, this will cause it to be removed from the world thread (return value 1) plObj->GetSession()->SetInstance(GetInstanceID()); /* Add the map wide objects */ if(_mapWideStaticObjects.size()) { if(!buf) buf = new ByteBuffer(300); for(set<Object*>::iterator itr = _mapWideStaticObjects.begin(); itr != _mapWideStaticObjects.end(); ++itr) { count = (*itr)->BuildCreateUpdateBlockForPlayer(buf, plObj); plObj->PushCreationData(buf, count); } } } if(buf) delete buf; if(plObj && InactiveMoveTime && !forced_expire) InactiveMoveTime = 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 ); } }
void MapMgr::UpdateCellActivity(uint32 x, uint32 y, int radius) { CellSpawns * sp; uint32 endX = (x + radius) <= _sizeX ? x + radius : (_sizeX-1); uint32 endY = (y + radius) <= _sizeY ? y + radius : (_sizeY-1); uint32 startX = x - radius > 0 ? x - radius : 0; uint32 startY = y - radius > 0 ? y - radius : 0; uint32 posX, posY; MapCell *objCell; for (posX = startX; posX <= endX; posX++ ) { for (posY = startY; posY <= endY; posY++ ) { objCell = GetCell(posX, posY); if (!objCell) { if (_CellActive(posX, posY)) { objCell = Create(posX, posY); objCell->Init(posX, posY, _mapId, this); sLog.outDetail("Cell [%d,%d] on map %d (instance %d) is now active.", posX, posY, this->_mapId, m_instanceID); objCell->SetActivity(true); _map->CellGoneActive(posX, posY); ASSERT(!objCell->IsLoaded()); sLog.outDetail("Loading objects for Cell [%d][%d] on map %d (instance %d)...", posX, posY, this->_mapId, m_instanceID); sp = _map->GetSpawnsList(posX, posY); if(sp) objCell->LoadObjects(sp); } } else { //Cell is now active if (_CellActive(posX, posY) && !objCell->IsActive()) { sLog.outDetail("Cell [%d,%d] on map %d (instance %d) is now active.", posX, posY, this->_mapId, m_instanceID); _map->CellGoneActive(posX, posY); objCell->SetActivity(true); if (!objCell->IsLoaded()) { sLog.outDetail("Loading objects for Cell [%d][%d] on map %d (instance %d)...", posX, posY, this->_mapId, m_instanceID); sp = _map->GetSpawnsList(posX, posY); if(sp) objCell->LoadObjects(sp); } } //Cell is no longer active else if (!_CellActive(posX, posY) && objCell->IsActive()) { sLog.outDetail("Cell [%d,%d] on map %d (instance %d) is now idle.", posX, posY, this->_mapId, m_instanceID); _map->CellGoneIdle(posX, posY); objCell->SetActivity(false); } } } } }
void MapMgr::UpdateCellActivity(uint32 x, uint32 y, uint32 radius) { CellSpawns* sp; uint32 endX = (x + radius) <= _sizeX ? x + radius : (_sizeX - 1); uint32 endY = (y + radius) <= _sizeY ? y + radius : (_sizeY - 1); uint32 startX = x > radius ? x - radius : 0; uint32 startY = y > radius ? y - radius : 0; uint32 posX, posY; MapCell* objCell; for(posX = startX; posX <= endX; posX++) { for(posY = startY; posY <= endY; posY++) { objCell = GetCell(posX, posY); if(!objCell) { if(_CellActive(posX, posY)) { objCell = Create(posX, posY); objCell->Init(posX, posY, this); LOG_DETAIL("Cell [%u,%u] on map %u (instance %u) is now active.", posX, posY, this->_mapId, m_instanceID); objCell->SetActivity(true); _map->CellGoneActive(posX, posY); _terrain->LoadTile((int32)posX / 8, (int32)posY / 8); ARCEMU_ASSERT(!objCell->IsLoaded()); LOG_DETAIL("Loading objects for Cell [%u][%u] on map %u (instance %u)...", posX, posY, this->_mapId, m_instanceID); sp = _map->GetSpawnsList(posX, posY); if(sp) objCell->LoadObjects(sp); } } else { //Cell is now active if(_CellActive(posX, posY) && !objCell->IsActive()) { LOG_DETAIL("Cell [%u,%u] on map %u (instance %u) is now active.", posX, posY, this->_mapId, m_instanceID); _map->CellGoneActive(posX, posY); _terrain->LoadTile((int32)posX / 8, (int32)posY / 8); objCell->SetActivity(true); if(!objCell->IsLoaded()) { LOG_DETAIL("Loading objects for Cell [%u][%u] on map %u (instance %u)...", posX, posY, this->_mapId, m_instanceID); sp = _map->GetSpawnsList(posX, posY); if(sp) objCell->LoadObjects(sp); } } //Cell is no longer active else if(!_CellActive(posX, posY) && objCell->IsActive()) { LOG_DETAIL("Cell [%u,%u] on map %u (instance %u) is now idle.", posX, posY, _mapId, m_instanceID); _map->CellGoneIdle(posX, posY); objCell->SetActivity(false); _terrain->UnloadTile((int32)posX / 8, (int32)posY / 8); } } } } }
void GameMapRecrusive::makeMap(int mLevel, int vLevel) { m_mLevel = mLevel; m_vLevel = vLevel; //10*20 -> 20*20 -> 20*30 -> 30*30 m_mapRows = 10* (vLevel/2+1); m_mapCols = 20+10*vLevel/2; m_mapCols = min(50, m_mapCols); m_roomSize = 5;//5-vLevel/3;//3 + vLevel/2; m_roomSize = max(3, m_roomSize); m_mineCount = 5 + 20*vLevel; m_coinCount = 5+vLevel;// + 10*vLevel; m_propCount = 5+vLevel;// + 10*vLevel; // m_hallMin = max(2, 5 - vLevel/2); // m_objects.resize(m_mapRows); for(int r=0; r<m_mapRows; ++r) { m_objects[r].resize(m_mapCols); for(int c=0; c<m_mapCols; ++c) { MapCell* cell = MapCell::create(); cell->setPosition(Point(c*m_tw, r*m_th) + Point(0, m_th) /*+ m_border*/); cell->setLocalZOrder((m_mapRows-r-1)*m_mapCols + c); addChild(cell); m_objects[r][c] = cell; } } // this->setContentSize(Size(m_mapCols*m_tw/*+m_border.width*2*/, m_mapRows*m_th/*+m_border.height*2*/)); generate(0, 0, m_mapRows, m_mapCols); while(m_mineCount>0) { int r = rand()% (m_mapRows-2)+1; int c = rand()% (m_mapCols-2)+1; setTrap(r, c); } while(m_coinCount>0) { int r = rand()% (m_mapRows-2)+1; int c = rand()% (m_mapCols-2)+1; setCoin(r, c); } while(m_propCount > 0) { int r = rand()% (m_mapRows-2)+1; int c = rand()% (m_mapCols-2)+1; setProp(r, c); } for (int r = 0; r < m_mapRows; ++r) { for (int j=0; j < m_mapCols; ++j) { if (m_objects[r][j]->empty()) { if (rand()%100<70) { setSoil(r, j, false); } } } } // const Index2 pos(rand()%m_mapRows,0); m_pPlayer = Player::create(); m_pPlayer->setPosition(index2ToPoint(pos)+Point(m_tw/2, m_th/2)); addChild(m_pPlayer, m_mapRows*m_mapCols+1); m_objects[pos.first][pos.second]->clear(); for(auto x : getSurrounding(pos)) { m_objects[x.first][x.second]->clear(); } // ValueMap val; val["type"] = "LevelStair"; const Index2 win(rand()%m_mapRows, m_mapCols-1); m_objects[win.first][win.second]->clear(); m_objects[win.first][win.second]->pushObjBy(val); }
bool ChatHandler::HandleGOSpawn(const char* args, WorldSession* m_session) { std::stringstream sstext; char* pEntryID = strtok((char*)args, " "); if(!pEntryID) return false; uint32 EntryID = atoi(pEntryID); bool Save = false; char* pSave = strtok(NULL, " "); if(pSave) Save = (atoi(pSave) > 0 ? true : false); GameObjectInfo* goi = GameObjectNameStorage.LookupEntry(EntryID); if(!goi) { sstext << "GameObject Info '" << EntryID << "' Not Found" << '\0'; SystemMessage(m_session, sstext.str().c_str()); return true; } LOG_DEBUG("Spawning GameObject By Entry '%u'", EntryID); sstext << "Spawning GameObject By Entry '" << EntryID << "'" << '\0'; SystemMessage(m_session, sstext.str().c_str()); Player* chr = m_session->GetPlayer(); GameObject* go = chr->GetMapMgr()->CreateGameObject(EntryID); uint32 mapid = chr->GetMapId(); float x = chr->GetPositionX(); float y = chr->GetPositionY(); float z = chr->GetPositionZ(); float o = chr->GetOrientation(); go->CreateFromProto(EntryID, mapid, x, y, z, o); go->PushToWorld(chr->GetMapMgr()); go->Phase(PHASE_SET, chr->GetPhase()); // Create spawn instance GOSpawn* gs = new GOSpawn; gs->entry = go->GetEntry(); gs->facing = go->GetOrientation(); gs->faction = go->GetFaction(); gs->flags = go->GetUInt32Value(GAMEOBJECT_FLAGS); gs->id = objmgr.GenerateGameObjectSpawnID(); gs->o = 0.0f; gs->o1 = go->GetParentRotation(0); gs->o2 = go->GetParentRotation(2); gs->o3 = go->GetParentRotation(3); gs->scale = go->GetScale(); gs->x = go->GetPositionX(); gs->y = go->GetPositionY(); gs->z = go->GetPositionZ(); gs->state = go->GetByte(GAMEOBJECT_BYTES_1, 0); //gs->stateNpcLink = 0; gs->phase = go->GetPhase(); gs->overrides = go->GetOverrides(); uint32 cx = chr->GetMapMgr()->GetPosX(chr->GetPositionX()); uint32 cy = chr->GetMapMgr()->GetPosY(chr->GetPositionY()); chr->GetMapMgr()->GetBaseMap()->GetSpawnsListAndCreate(cx, cy)->GOSpawns.push_back(gs); go->m_spawn = gs; MapCell* mCell = chr->GetMapMgr()->GetCell(cx, cy); if(mCell != NULL) mCell->SetLoaded(); if(Save == true) { // If we're saving, create template and add index go->SaveToDB(); go->m_loadedFromDB = true; } sGMLog.writefromsession(m_session, "spawned gameobject %s, entry %u at %u %f %f %f%s", GameObjectNameStorage.LookupEntry(gs->entry)->Name, gs->entry, chr->GetMapId(), gs->x, gs->y, gs->z, Save ? ", saved in DB" : ""); return true; }
list<GameMap::Index2> GameMap::getPath( const Index2& from, const Index2& to ) { if (from==to || (to.first<0 || to.first>=m_objects.size() || to.second<0 || to.second>=m_objects[0].size())) return list<Index2>(); struct AStarInfo { int g; int h; Index2 parent; int f(){ return g+h; } AStarInfo(int argg, int argh){ g = argg; h = argh; parent.first = parent.second = -1; } }; map<Index2, AStarInfo> opened; map<Index2, AStarInfo> closed; auto last_obj = opened.end(); opened.insert( make_pair(from, AStarInfo(0,0)) ); do { Break_If( opened.empty() ); int min_cost = INT_MAX; Index2 curPos(-1,-1); AStarInfo curInfo(INT_MAX, 0); map<Index2, AStarInfo>::iterator cur; for (map<Index2, AStarInfo>::iterator it = opened.begin(); it != opened.end(); ++it) { if (it->second.f() < curInfo.f()) { curPos = it->first; curInfo = it->second; cur = it; } } opened.erase(cur); closed.insert( make_pair(curPos, curInfo) ); auto surround = getSurrounding(curPos, 1); for (auto it = surround.begin(); it != surround.end(); ++it) { MapCell* cell = m_objects[it->first][it->second]; if ( *it == to ) { AStarInfo info( curInfo.g+loss(curPos,*it), loss(*it, to) ); info.parent = curPos; opened.insert( make_pair(*it, info) ); } else if ( cell->getAStarCost()==INT_MAX || closed.find(*it)!=closed.end() ) { //do nothing } else if ( opened.find(*it) == opened.end() ) { AStarInfo info( curInfo.g+loss(curPos,*it), loss(*it, to) ); info.parent = curPos; opened.insert( make_pair(*it, info) ); } else//已经在开启列表中,检查新的路径是否更好 { auto has = opened.find(*it); if (has->second.g > curInfo.g+loss(curPos,*it)) { has->second.parent = curPos; has->second.g = curInfo.g+loss(curPos,*it); } } } last_obj = opened.find(to); if (last_obj != opened.end()) break; } while (true); if (last_obj == opened.end()) { return list<Index2>(); } list<Index2> ret; ret.push_front( last_obj->first ); auto path = closed.find( last_obj->second.parent ); while (path != closed.end()) { ret.push_front(path->first); path = closed.find( path->second.parent ); } if (!ret.empty()) ret.pop_front(); if (ret.size() > 10) { ret.clear(); } return ret; }
void MapMgr::AddObject(Object *obj) { ASSERT(obj); // make sure object is a virgin ASSERT(obj->GetInRangeSetBegin() == obj->GetInRangeSetEnd()); ASSERT(obj->GetMapId() == _mapId); ASSERT(obj->GetPositionX() < _maxX && obj->GetPositionX() > _minX); ASSERT(obj->GetPositionY() < _maxY && obj->GetPositionY() > _minY); ASSERT(_cells); // That object types are not map objects. TODO: add AI groups here? if(obj->GetTypeId() == TYPEID_ITEM || obj->GetTypeId() == TYPEID_CONTAINER) { // mark object as updatable and exit obj->AddToWorld(); return; } uint32 x = (uint32)(obj->GetPositionX() > 0 ? abs(_minX) + obj->GetPositionX() : abs(_minX) - abs(obj->GetPositionX())); uint32 y = (uint32)(obj->GetPositionY() > 0 ? abs(_minY) + obj->GetPositionY() : abs(_minY) - abs(obj->GetPositionY())); x /= _sizeX; y /= _sizeY; /* sLog.outDetail("Obj position: %f %f Cell position: %u %u", obj->GetPositionX(), obj->GetPositionY(), x, y); */ MapCell *objCell = &(_cells[x][y]); uint32 endX = x < _sizeX ? x + 1 : _sizeX; uint32 endY = y < _sizeY ? y + 1 : _sizeY; uint32 startX = x > 0 ? x - 1 : 0; uint32 startY = y > 0 ? y - 1 : 0; uint32 posX, posY; MapCell *cell; MapCell::ObjectSet::iterator iter; WorldPacket packet; UpdateData data; UpdateData playerData; 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++) { if ((*iter)->GetDistance2dSq(obj) <= UPDATE_DISTANCE*UPDATE_DISTANCE) { // Object in range, add to set if((*iter)->GetTypeId() == TYPEID_PLAYER) { sLog.outDetail("Creating object "I64FMT" for player "I64FMT".", obj->GetGUID(), (*iter)->GetGUID()); data.Clear(); obj->BuildCreateUpdateBlockForPlayer( &data, (Player*)*iter ); data.BuildPacket(&packet); ((Player*)*iter)->GetSession()->SendPacket( &packet ); } (*iter)->AddInRangeObject(obj); if(obj->GetTypeId() == TYPEID_PLAYER) { sLog.outDetail("Creating object "I64FMT" for player "I64FMT".", (*iter)->GetGUID(), obj->GetGUID()); (*iter)->BuildCreateUpdateBlockForPlayer( &playerData, (Player*)obj ); } obj->AddInRangeObject(*iter); } } } } if(obj->GetTypeId() == TYPEID_PLAYER) { sLog.outDetail("Creating player "I64FMT" for himself.", obj->GetGUID()); obj->BuildCreateUpdateBlockForPlayer( &playerData, (Player*)obj ); playerData.BuildPacket( &packet ); ((Player*)obj)->GetSession()->SendPacket( &packet ); } objCell->AddObject(obj); _objects[obj->GetGUID()] = obj; obj->SetMapCell(objCell); obj->AddToWorld(); }