2008-10-02 16:23:55 -05:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2009-02-04 12:04:12 +01:00
* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
2008-10-02 16:23:55 -05:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2008-11-18 19:40:06 -06:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-02 16:23:55 -05:00
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
2008-11-18 19:40:06 -06:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-02 16:23:55 -05:00
*/
#include "MapInstanced.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#include "BattleGround.h"
#include "VMapFactory.h"
#include "InstanceSaveMgr.h"
#include "World.h"
2008-11-18 19:40:06 -06:00
MapInstanced :: MapInstanced ( uint32 id , time_t expiry ) : Map ( id , expiry , 0 , 0 )
2008-10-02 16:23:55 -05:00
{
// initialize instanced maps list
m_InstancedMaps . clear ();
// fill with zero
memset ( & GridMapReference , 0 , MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS * sizeof ( uint16 ));
}
void MapInstanced :: Update ( const uint32 & t )
{
// take care of loaded GridMaps (when unused, unload it!)
Map :: Update ( t );
// update the instanced maps
InstancedMaps :: iterator i = m_InstancedMaps . begin ();
while ( i != m_InstancedMaps . end ())
{
if ( i -> second -> CanUnload ( t ))
{
DestroyInstance ( i ); // iterator incremented
}
else
{
// update only here, because it may schedule some bad things before delete
i -> second -> Update ( t );
++ i ;
}
}
}
void MapInstanced :: MoveAllCreaturesInMoveList ()
{
2008-12-08 16:34:03 -06:00
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
2008-10-02 16:23:55 -05:00
{
i -> second -> MoveAllCreaturesInMoveList ();
}
Map :: MoveAllCreaturesInMoveList ();
}
void MapInstanced :: RemoveAllObjectsInRemoveList ()
{
2008-12-08 16:34:03 -06:00
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
2008-10-02 16:23:55 -05:00
{
i -> second -> RemoveAllObjectsInRemoveList ();
}
Map :: RemoveAllObjectsInRemoveList ();
}
bool MapInstanced :: RemoveBones ( uint64 guid , float x , float y )
{
bool remove_result = false ;
2008-12-08 16:34:03 -06:00
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
2008-10-02 16:23:55 -05:00
{
remove_result = remove_result || i -> second -> RemoveBones ( guid , x , y );
}
return remove_result || Map :: RemoveBones ( guid , x , y );
}
2009-02-25 17:53:05 -06:00
void MapInstanced :: UnloadAll ()
2008-10-02 16:23:55 -05:00
{
// Unload instanced maps
2008-12-08 16:34:03 -06:00
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
2009-02-25 17:53:05 -06:00
i -> second -> UnloadAll ();
2008-10-02 16:23:55 -05:00
// Delete the maps only after everything is unloaded to prevent crashes
2008-12-08 16:34:03 -06:00
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
2008-10-02 16:23:55 -05:00
delete i -> second ;
m_InstancedMaps . clear ();
// Unload own grids (just dummy(placeholder) grids, neccesary to unload GridMaps!)
2009-02-25 17:53:05 -06:00
Map :: UnloadAll ();
2008-10-02 16:23:55 -05:00
}
/*
- return the right instance for the object, based on its InstanceId
- create the instance if it's not created already
- the player is not actually added to the instance (only in InstanceMap::Add)
*/
Map * MapInstanced :: GetInstance ( const WorldObject * obj )
{
2009-05-16 14:52:41 -05:00
if ( obj -> GetTypeId () == TYPEID_UNIT )
2008-10-02 16:23:55 -05:00
{
2009-05-16 14:52:41 -05:00
assert ( obj -> GetMapId () == GetId () && obj -> GetInstanceId ());
return _FindMap ( obj -> GetInstanceId ());
2008-10-02 16:23:55 -05:00
}
2009-05-16 14:52:41 -05:00
Player * player = ( Player * ) obj ;
uint32 instanceId = player -> GetInstanceId ();
if ( IsBattleGroundOrArena ())
2008-10-02 16:23:55 -05:00
{
2009-05-16 14:52:41 -05:00
if ( ! instanceId )
instanceId = player -> GetBattleGroundId ();
if ( instanceId )
return _FindMap ( instanceId );
else
2008-10-02 16:23:55 -05:00
return NULL ;
2009-05-16 14:52:41 -05:00
}
if ( instanceId )
if ( Map * map = _FindMap ( instanceId ))
return map ;
InstancePlayerBind * pBind = player -> GetBoundInstance ( GetId (), player -> GetDifficulty ());
InstanceSave * pSave = pBind ? pBind -> save : NULL ;
if ( ! pBind || ! pBind -> perm )
{
if ( Group * group = player -> GetGroup ())
if ( InstanceGroupBind * groupBind = group -> GetBoundInstance ( GetId (), player -> GetDifficulty ()))
pSave = groupBind -> save ;
}
if ( instanceId && pSave && instanceId != pSave -> GetInstanceId ())
return NULL ;
if ( ! player -> GetSession () -> PlayerLoading ()) // enter a new map
{
if ( pSave )
return CreateInstance ( pSave -> GetInstanceId (), pSave , pSave -> GetDifficulty ());
2008-10-02 16:23:55 -05:00
else
2009-05-16 14:52:41 -05:00
return CreateInstance ( MapManager :: Instance (). GenerateInstanceId (), NULL , player -> GetDifficulty ());
2008-10-02 16:23:55 -05:00
}
2009-05-16 14:52:41 -05:00
return NULL ;
2008-10-02 16:23:55 -05:00
}
InstanceMap * MapInstanced :: CreateInstance ( uint32 InstanceId , InstanceSave * save , uint8 difficulty )
{
// load/create a map
Guard guard ( * this );
// make sure we have a valid map id
const MapEntry * entry = sMapStore . LookupEntry ( GetId ());
if ( ! entry )
{
sLog . outError ( "CreateInstance: no entry for map %d" , GetId ());
assert ( false );
}
const InstanceTemplate * iTemplate = objmgr . GetInstanceTemplate ( GetId ());
if ( ! iTemplate )
{
sLog . outError ( "CreateInstance: no instance template for map %d" , GetId ());
assert ( false );
}
// some instances only have one difficulty
2009-04-27 18:42:35 -05:00
if ( entry && ! entry -> SupportsHeroicMode ()) difficulty = DIFFICULTY_NORMAL ;
2008-10-02 16:23:55 -05:00
sLog . outDebug ( "MapInstanced::CreateInstance: %smap instance %d for %d created with difficulty %s" , save ? "" : "new " , InstanceId , GetId (), difficulty ? "heroic" : "normal" );
InstanceMap * map = new InstanceMap ( GetId (), GetGridExpiry (), InstanceId , difficulty );
assert ( map -> IsDungeon ());
bool load_data = save != NULL ;
map -> CreateInstanceData ( load_data );
m_InstancedMaps [ InstanceId ] = map ;
return map ;
}
BattleGroundMap * MapInstanced :: CreateBattleGround ( uint32 InstanceId )
{
// load/create a map
Guard guard ( * this );
sLog . outDebug ( "MapInstanced::CreateBattleGround: map bg %d for %d created." , InstanceId , GetId ());
BattleGroundMap * map = new BattleGroundMap ( GetId (), GetGridExpiry (), InstanceId );
assert ( map -> IsBattleGroundOrArena ());
m_InstancedMaps [ InstanceId ] = map ;
return map ;
}
void MapInstanced :: DestroyInstance ( uint32 InstanceId )
{
InstancedMaps :: iterator itr = m_InstancedMaps . find ( InstanceId );
if ( itr != m_InstancedMaps . end ())
DestroyInstance ( itr );
}
// increments the iterator after erase
void MapInstanced :: DestroyInstance ( InstancedMaps :: iterator & itr )
{
2009-02-25 17:53:05 -06:00
itr -> second -> UnloadAll ();
2008-10-02 16:23:55 -05:00
// should only unload VMaps if this is the last instance and grid unloading is enabled
if ( m_InstancedMaps . size () <= 1 && sWorld . getConfig ( CONFIG_GRID_UNLOAD ))
{
VMAP :: VMapFactory :: createOrGetVMapManager () -> unloadMap ( itr -> second -> GetId ());
// in that case, unload grids of the base map, too
// so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
2009-02-25 17:53:05 -06:00
Map :: UnloadAll ();
2008-10-02 16:23:55 -05:00
}
// erase map
delete itr -> second ;
m_InstancedMaps . erase ( itr ++ );
}
2009-02-13 23:53:06 +01:00
bool MapInstanced :: CanEnter ( Player * player )
{
if ( Map * map = GetInstance ( player ))
return map -> CanEnter ( player );
return false ;
}
2009-02-17 20:07:49 -06:00