/*
* Ascent MMORPG Server
* Copyright (C) 2005-2007 Ascent Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
//
// MapCell.cpp
//
#include "StdAfx.h"
MapCell::~MapCell()
{
RemoveObjects();
}
void MapCell::Init(uint32 x, uint32 y, uint32 mapid, MapMgr *mapmgr)
{
_mapmgr = mapmgr;
_active = false;
_loaded = false;
_playerCount = 0;
_x=x;
_y=y;
_unloadpending=false;
}
void MapCell::AddObject(Object *obj)
{
if(obj->IsPlayer())
++_playerCount;
_objects.insert(obj);
}
void MapCell::RemoveObject(Object *obj)
{
if(obj->IsPlayer())
--_playerCount;
_objects.erase(obj);
}
void MapCell::SetActivity(bool state)
{
if(!_active && state)
{
// Move all objects to active set.
for(ObjectSet::iterator itr = _objects.begin(); itr != _objects.end(); ++itr)
{
if(!(*itr)->Active && (*itr)->CanActivate())
(*itr)->Activate(_mapmgr);
}
if(_unloadpending)
CancelPendingUnload();
} else if(_active && !state)
{
// Move all objects from active set.
for(ObjectSet::iterator itr = _objects.begin(); itr != _objects.end(); ++itr)
{
if((*itr)->Active)
(*itr)->Deactivate(_mapmgr);
}
if(sWorld.map_unload_time && !_unloadpending)
QueueUnloadPending();
}
_active = state;
}
void MapCell::RemoveObjects()
{
ObjectSet::iterator itr;
uint32 count = 0;
//uint32 ltime = getMSTime();
/* delete objects in pending respawn state */
for(itr = _respawnObjects.begin(); itr != _respawnObjects.end(); ++itr)
{
switch((*itr)->GetTypeId())
{
case TYPEID_UNIT: {
((Creature*)*itr)->m_respawnCell=NULL;
delete ((Creature*)*itr);
}break;
case TYPEID_GAMEOBJECT: {
((GameObject*)*itr)->m_respawnCell=NULL;
delete ((GameObject*)*itr);
}break;
}
}
_respawnObjects.clear();
//This time it's simpler! We just remove everything :)
for(itr = _objects.begin(); itr != _objects.end(); )
{
count++;
Object *obj = (*itr);
itr++;
if(_unloadpending && UINT32_LOPART(obj->GetGUIDHigh())==HIGHGUID_TRANSPORTER)
continue;
if(_unloadpending && obj->GetTypeId()==TYPEID_CORPSE)
continue;
if(obj->Active)
obj->Deactivate(_mapmgr);
if (obj->IsInWorld())
obj->RemoveFromWorld();
if (obj->GetTypeId() == TYPEID_UNIT)
{
if(obj->IsPet())
delete ((Pet*)(obj));
else
delete ((Creature*)obj);
}
else if (obj->GetTypeId() == TYPEID_GAMEOBJECT)
{
if(obj->GetGUIDHigh()==HIGHGUID_TRANSPORTER)
delete ((Transporter*)obj);
else
delete ((GameObject*)obj);
}
else if (obj->GetTypeId() == TYPEID_DYNAMICOBJECT)
delete ((DynamicObject*)obj);
else if (obj->GetTypeId() == TYPEID_CORPSE)
{
delete ((Corpse*)obj);
}
}
_objects.clear();
_playerCount = 0;
_loaded = false;
}
void MapCell::LoadObjects(CellSpawns * sp, Instance_Map_InstanceId_Holder * pInstance)
{
_loaded = true;
if(sp->CreatureSpawns.size())//got creatures
{
for(CreatureSpawnList::iterator i=sp->CreatureSpawns.begin();i!=sp->CreatureSpawns.end();i++)
{
if(pInstance && pInstance->FindObject((*i)->id) || pInstance && pInstance->FindObject((*i)->respawnNpcLink))
{
continue;
}
Creature * c=_mapmgr->CreateCreature();
c->SetMapId(_mapmgr->GetMapId());
c->SetInstanceID(_mapmgr->GetInstanceID());
if(c->Load(*i, _mapmgr->iInstanceMode, _mapmgr->GetMapInfo()))
{
if(!c->CanAddToWorld())
delete c;
c->PushToWorld(_mapmgr);
}
else
delete c;//missing proto or smth of that kind
}
}
if(sp->GOSpawns.size())//got GOs
{
for(GOSpawnList::iterator i=sp->GOSpawns.begin();i!=sp->GOSpawns.end();i++)
{
GameObject * go=_mapmgr->CreateGameObject();
if(go->Load(*i))
{
uint32 state = go->GetUInt32Value(GAMEOBJECT_STATE);
if(pInstance && pInstance->FindObject((*i)->stateNpcLink))
{
go->SetUInt32Value(GAMEOBJECT_STATE, (state ? 0 : 1));
}
go->PushToWorld(_mapmgr);
}
else
delete go;//missing proto or smth of that kind
}
}
}
void MapCell::QueueUnloadPending()
{
if(_unloadpending)
return;
_unloadpending = true;
//Log.Debug("MapCell", "Queueing pending unload of cell %u %u", _x, _y);
sEventMgr.AddEvent(_mapmgr, &MapMgr::UnloadCell,(uint32)_x,(uint32)_y,MAKE_CELL_EVENT(_x,_y),sWorld.map_unload_time * 1000,1,0);
}
void MapCell::CancelPendingUnload()
{
//Log.Debug("MapCell", "Cancelling pending unload of cell %u %u", _x, _y);
if(!_unloadpending)
return;
sEventMgr.RemoveEvents(_mapmgr,MAKE_CELL_EVENT(_x,_y));
}
void MapCell::Unload()
{
//Log.Debug("MapCell", "Unloading cell %u %u", _x, _y);
ASSERT(_unloadpending);
if(_active)
return;
RemoveObjects();
_unloadpending=false;
}