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 ));
}
2009-09-27 02:24:25 -07:00
void MapInstanced :: InitVisibilityDistance ()
{
if ( m_InstancedMaps . empty ())
return ;
//initialize visibility distances for all instance copies
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
{
( * i ). second -> InitVisibilityDistance ();
}
}
2008-10-02 16:23:55 -05:00
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 ))
{
2009-08-06 16:14:13 -05:00
if ( ! DestroyInstance ( i )) // iterator incremented
{
//m_unloadTimer
}
2008-10-02 16:23:55 -05:00
}
else
{
// update only here, because it may schedule some bad things before delete
i -> second -> Update ( t );
++ i ;
}
}
}
2009-08-25 15:12:22 -05:00
void MapInstanced :: DelayedUpdate ( const uint32 diff )
2008-10-02 16:23:55 -05:00
{
2008-12-08 16:34:03 -06:00
for ( InstancedMaps :: iterator i = m_InstancedMaps . begin (); i != m_InstancedMaps . end (); ++ i )
2009-08-25 15:12:22 -05:00
i -> second -> DelayedUpdate ( diff );
Map :: DelayedUpdate ( diff ); // this may be removed
2008-10-02 16:23:55 -05:00
}
2009-08-25 15:12:22 -05:00
/*
2009-06-09 23:52:45 -05:00
void MapInstanced::RelocationNotify()
{
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
i->second->RelocationNotify();
}
2009-08-25 15:12:22 -05:00
*/
2008-10-02 16:23:55 -05:00
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)
*/
2009-08-01 00:20:32 +02:00
Map * MapInstanced :: CreateInstance ( const uint32 mapId , Player * player , uint32 instanceId )
2008-10-02 16:23:55 -05:00
{
2009-05-17 09:28:38 -05:00
if ( instanceId )
if ( Map * map = _FindMap ( instanceId ))
return map ;
2009-05-16 14:52:41 -05:00
if ( IsBattleGroundOrArena ())
2008-10-02 16:23:55 -05:00
{
2009-08-01 03:37:40 +02:00
instanceId = player -> GetBattleGroundId ();
if ( instanceId )
if ( Map * map = _FindMap ( instanceId ))
return map ;
return CreateBattleGround ( instanceId );
2009-05-16 14:52:41 -05:00
}
2009-08-01 04:13:28 +02:00
else if ( InstanceSave * pSave = player -> GetInstanceSave ( GetId ()))
2009-05-16 14:52:41 -05:00
{
2009-05-16 16:52:45 -05:00
if ( ! instanceId )
{
instanceId = pSave -> GetInstanceId (); // go from outside to instance
if ( Map * map = _FindMap ( instanceId ))
return map ;
}
else if ( instanceId != pSave -> GetInstanceId ()) // cannot go from one instance to another
return NULL ;
// else log in at a saved instance
return CreateInstance ( instanceId , pSave , pSave -> GetDifficulty ());
}
else if ( ! player -> GetSession () -> PlayerLoading ())
{
if ( ! instanceId )
instanceId = MapManager :: Instance (). GenerateInstanceId ();
return CreateInstance ( instanceId , 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 ;
2009-07-16 11:49:00 +08:00
sLog . outDebug ( "MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s" , save ? "" : "new " , InstanceId , GetId (), difficulty ? "heroic" : "normal" );
InstanceMap * map = new InstanceMap ( GetId (), GetGridExpiry (), InstanceId , difficulty , this );
ASSERT ( map -> IsDungeon ());
2008-10-02 16:23:55 -05:00
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 ());
2009-07-16 11:49:00 +08:00
BattleGroundMap * map = new BattleGroundMap ( GetId (), GetGridExpiry (), InstanceId , this );
ASSERT ( map -> IsBattleGroundOrArena ());
2008-10-02 16:23:55 -05:00
m_InstancedMaps [ InstanceId ] = map ;
return map ;
}
// increments the iterator after erase
2009-08-06 16:14:13 -05:00
bool MapInstanced :: DestroyInstance ( InstancedMaps :: iterator & itr )
2008-10-02 16:23:55 -05:00
{
2009-08-06 16:14:13 -05:00
itr -> second -> RemoveAllPlayers ();
if ( itr -> second -> HavePlayers ())
{
++ itr ;
return false ;
}
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-08-06 16:14:13 -05:00
return true ;
2008-10-02 16:23:55 -05:00
}
2009-02-13 23:53:06 +01:00
bool MapInstanced :: CanEnter ( Player * player )
{
2009-07-16 11:49:00 +08:00
//assert(false);
return true ;
2009-02-13 23:53:06 +01:00
}
2009-02-17 20:07:49 -06:00