2010-10-07 15:35:36 +02:00
/*
2011-01-01 15:01:13 +01:00
* Copyright (C) 2008-2011 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* 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 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 <http://www.gnu.org/licenses/>.
2008-10-02 16:23:55 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
#include "ObjectGridLoader.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Creature.h"
2009-03-28 22:44:09 -06:00
#include "Vehicle.h"
2008-10-02 16:23:55 -05:00
#include "GameObject.h"
#include "DynamicObject.h"
#include "Corpse.h"
#include "World.h"
#include "CellImpl.h"
2009-04-07 19:38:09 -05:00
#include "CreatureAI.h"
2009-10-17 15:51:44 -07:00
2010-02-05 00:31:28 +01:00
class ObjectGridRespawnMover
2008-10-02 16:23:55 -05:00
{
public :
ObjectGridRespawnMover () {}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void Move ( GridType & grid );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
template < class T > void Visit ( GridRefManager < T > & ) {}
void Visit ( CreatureMapType & m );
};
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridRespawnMover :: Move ( GridType & grid )
{
TypeContainerVisitor < ObjectGridRespawnMover , GridTypeMapContainer > mover ( * this );
grid . Visit ( mover );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridRespawnMover :: Visit ( CreatureMapType & m )
{
// creature in unloading grid can have respawn point in another grid
// if it will be unloaded then it will not respawn in original grid until unload/load original grid
2008-12-12 11:21:28 -06:00
// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
2009-11-20 19:11:28 -08:00
for ( CreatureMapType :: iterator iter = m . begin (); iter != m . end ();)
2008-10-02 16:23:55 -05:00
{
Creature * c = iter -> getSource ();
2009-04-08 12:20:39 -05:00
++ iter ;
2009-10-17 15:51:44 -07:00
2010-07-30 20:04:28 +02:00
ASSERT ( ! c -> isPet () && "ObjectGridRespawnMover don't must be called for pets" );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
Cell const & cur_cell = c -> GetCurrentCell ();
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
float resp_x , resp_y , resp_z ;
c -> GetRespawnCoord ( resp_x , resp_y , resp_z );
2008-10-14 11:57:03 -05:00
CellPair resp_val = Trinity :: ComputeCellPair ( resp_x , resp_y );
2008-10-02 16:23:55 -05:00
Cell resp_cell ( resp_val );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( cur_cell . DiffGrid ( resp_cell ))
2008-10-02 16:23:55 -05:00
{
2009-03-08 13:05:56 -06:00
c -> GetMap () -> CreatureRespawnRelocation ( c );
2008-10-02 16:23:55 -05:00
// false result ignored: will be unload with other creatures at grid
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// for loading world object at grid loading (Corpses)
class ObjectWorldLoader
{
public :
explicit ObjectWorldLoader ( ObjectGridLoader & gloader )
: i_cell ( gloader . i_cell ), i_grid ( gloader . i_grid ), i_map ( gloader . i_map ), i_corpses ( 0 )
{}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void Visit ( CorpseMapType & m );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
template < class T > void Visit ( GridRefManager < T >& ) { }
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
private :
Cell i_cell ;
NGridType & i_grid ;
Map * i_map ;
public :
uint32 i_corpses ;
};
2009-10-17 15:51:44 -07:00
2010-12-17 13:43:24 +01:00
template < class T > void AddUnitState ( T * /*obj*/ , CellPair const & /*cell_pair*/ )
2008-10-02 16:23:55 -05:00
{
}
2009-10-17 15:51:44 -07:00
2010-12-17 13:43:24 +01:00
template <> void AddUnitState ( Creature * obj , CellPair const & cell_pair )
2008-10-02 16:23:55 -05:00
{
Cell cell ( cell_pair );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
obj -> SetCurrentCell ( cell );
}
2009-10-17 15:51:44 -07:00
2009-08-11 11:11:22 -05:00
template < class T >
void AddObjectHelper ( CellPair & cell , GridRefManager < T > & m , uint32 & count , Map * map , T * obj )
{
obj -> GetGridRef (). link ( & m , obj );
2011-04-29 20:47:02 +02:00
AddUnitState ( obj , cell );
2009-08-11 11:11:22 -05:00
obj -> AddToWorld ();
2010-04-07 19:14:10 +02:00
if ( obj -> isActiveObject ())
2009-08-11 11:11:22 -05:00
map -> AddToActive ( obj );
2009-10-17 15:51:44 -07:00
2009-08-11 11:11:22 -05:00
++ count ;
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
template < class T >
void LoadHelper ( CellGuidSet const & guid_set , CellPair & cell , GridRefManager < T > & m , uint32 & count , Map * map )
{
2009-10-17 16:20:24 -07:00
for ( CellGuidSet :: const_iterator i_guid = guid_set . begin (); i_guid != guid_set . end (); ++ i_guid )
2008-10-02 16:23:55 -05:00
{
T * obj = new T ;
uint32 guid = * i_guid ;
2011-04-29 20:47:02 +02:00
//sLog->outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid);
2010-04-07 19:14:10 +02:00
if ( ! obj -> LoadFromDB ( guid , map ))
2008-10-02 16:23:55 -05:00
{
delete obj ;
continue ;
}
2009-10-17 15:51:44 -07:00
2009-08-11 11:11:22 -05:00
AddObjectHelper ( cell , m , count , map , obj );
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void LoadHelper ( CellCorpseSet const & cell_corpses , CellPair & cell , CorpseMapType & m , uint32 & count , Map * map )
{
2010-04-07 19:14:10 +02:00
if ( cell_corpses . empty ())
2008-10-02 16:23:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( CellCorpseSet :: const_iterator itr = cell_corpses . begin (); itr != cell_corpses . end (); ++ itr )
2008-10-02 16:23:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( itr -> second != map -> GetInstanceId ())
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
uint32 player_guid = itr -> first ;
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
Corpse * obj = sObjectAccessor -> GetCorpseForPlayerGUID ( player_guid );
2010-04-07 19:14:10 +02:00
if ( ! obj )
2008-10-02 16:23:55 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-08-11 15:40:43 -05:00
// TODO: this is a hack
// corpse's map should be reset when the map is unloaded
2009-08-26 18:11:14 -05:00
// but it may still exist when the grid is unloaded but map is not
// in that case map == currMap
2009-08-11 15:40:43 -05:00
obj -> SetMap ( map );
2009-10-17 15:51:44 -07:00
2009-08-11 11:11:22 -05:00
AddObjectHelper ( cell , m , count , map , obj );
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridLoader :: Visit ( GameObjectMapType & m )
{
uint32 x = ( i_cell . GridX () * MAX_NUMBER_OF_CELLS ) + i_cell . CellX ();
uint32 y = ( i_cell . GridY () * MAX_NUMBER_OF_CELLS ) + i_cell . CellY ();
2011-04-29 20:47:02 +02:00
CellPair cell_pair ( x , y );
2008-10-02 16:23:55 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
CellObjectGuids const & cell_guids = sObjectMgr -> GetCellObjectGuids ( i_map -> GetId (), i_map -> GetSpawnMode (), cell_id );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
LoadHelper ( cell_guids . gameobjects , cell_pair , m , i_gameObjects , i_map );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridLoader :: Visit ( CreatureMapType & m )
{
uint32 x = ( i_cell . GridX () * MAX_NUMBER_OF_CELLS ) + i_cell . CellX ();
uint32 y = ( i_cell . GridY () * MAX_NUMBER_OF_CELLS ) + i_cell . CellY ();
2011-04-29 20:47:02 +02:00
CellPair cell_pair ( x , y );
2008-10-02 16:23:55 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
CellObjectGuids const & cell_guids = sObjectMgr -> GetCellObjectGuids ( i_map -> GetId (), i_map -> GetSpawnMode (), cell_id );
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
LoadHelper ( cell_guids . creatures , cell_pair , m , i_creatures , i_map );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectWorldLoader :: Visit ( CorpseMapType & m )
{
uint32 x = ( i_cell . GridX () * MAX_NUMBER_OF_CELLS ) + i_cell . CellX ();
uint32 y = ( i_cell . GridY () * MAX_NUMBER_OF_CELLS ) + i_cell . CellY ();
2011-04-29 20:47:02 +02:00
CellPair cell_pair ( x , y );
2008-10-02 16:23:55 -05:00
uint32 cell_id = ( cell_pair . y_coord * TOTAL_NUMBER_OF_CELLS_PER_MAP ) + cell_pair . x_coord ;
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
// corpses are always added to spawn mode 0 and they are spawned by their instance id
2010-12-22 21:25:23 +01:00
CellObjectGuids const & cell_guids = sObjectMgr -> GetCellObjectGuids ( i_map -> GetId (), 0 , cell_id );
2008-10-02 16:23:55 -05:00
LoadHelper ( cell_guids . corpses , cell_pair , m , i_corpses , i_map );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridLoader :: Load ( GridType & grid )
{
{
TypeContainerVisitor < ObjectGridLoader , GridTypeMapContainer > loader ( * this );
grid . Visit ( loader );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
{
ObjectWorldLoader wloader ( * this );
TypeContainerVisitor < ObjectWorldLoader , WorldTypeMapContainer > loader ( wloader );
grid . Visit ( loader );
i_corpses = wloader . i_corpses ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void ObjectGridLoader :: LoadN ( void )
{
i_gameObjects = 0 ; i_creatures = 0 ; i_corpses = 0 ;
i_cell . data . Part . cell_y = 0 ;
2009-10-17 16:20:24 -07:00
for ( unsigned int x = 0 ; x < MAX_NUMBER_OF_CELLS ; ++ x )
2008-10-02 16:23:55 -05:00
{
i_cell . data . Part . cell_x = x ;
2009-10-17 16:20:24 -07:00
for ( unsigned int y = 0 ; y < MAX_NUMBER_OF_CELLS ; ++ y )
2008-10-02 16:23:55 -05:00
{
i_cell . data . Part . cell_y = y ;
GridLoader < Player , AllWorldObjectTypes , AllGridObjectTypes > loader ;
loader . Load ( i_grid ( x , y ), * this );
}
}
2011-04-29 20:47:02 +02:00
sLog -> outDebug ( LOG_FILTER_MAPS , "%u GameObjects, %u Creatures, and %u Corpses/Bones loaded for grid %u on map %u" , i_gameObjects , i_creatures , i_corpses , i_grid . GetGridId (), i_map -> GetId ());
2008-10-02 16:23:55 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void ObjectGridUnloader :: MoveToRespawnN ()
{
2009-10-17 16:20:24 -07:00
for ( unsigned int x = 0 ; x < MAX_NUMBER_OF_CELLS ; ++ x )
2008-10-02 16:23:55 -05:00
{
2009-10-17 16:20:24 -07:00
for ( unsigned int y = 0 ; y < MAX_NUMBER_OF_CELLS ; ++ y )
2008-10-02 16:23:55 -05:00
{
ObjectGridRespawnMover mover ;
mover . Move ( i_grid ( x , y ));
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridUnloader :: Unload ( GridType & grid )
{
TypeContainerVisitor < ObjectGridUnloader , GridTypeMapContainer > unloader ( * this );
grid . Visit ( unloader );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
template < class T >
void
ObjectGridUnloader :: Visit ( GridRefManager < T > & m )
{
2010-04-07 19:13:19 +02:00
while ( ! m . isEmpty ())
2008-10-02 16:23:55 -05:00
{
T * obj = m . getFirst () -> getSource ();
// if option set then object already saved at this moment
2010-12-23 23:25:44 +01:00
if ( ! sWorld -> getBoolConfig ( CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY ))
2008-10-02 16:23:55 -05:00
obj -> SaveRespawnTime ();
///- object will get delinked from the manager when deleted
delete obj ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridStoper :: Stop ( GridType & grid )
{
TypeContainerVisitor < ObjectGridStoper , GridTypeMapContainer > stoper ( * this );
grid . Visit ( stoper );
}
2009-10-17 15:51:44 -07:00
2008-10-02 16:23:55 -05:00
void
ObjectGridStoper :: Visit ( CreatureMapType & m )
{
// stop any fights at grid de-activation and remove dynobjects created at cast by creatures
2009-10-17 16:20:24 -07:00
for ( CreatureMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
2008-10-02 16:23:55 -05:00
{
2011-02-04 00:27:43 +01:00
iter -> getSource () -> RemoveAllDynObjects ();
2010-04-07 19:14:10 +02:00
if ( iter -> getSource () -> isInCombat ())
2009-04-13 17:11:23 -05:00
{
iter -> getSource () -> CombatStop ();
iter -> getSource () -> DeleteThreatList ();
2011-02-04 00:27:43 +01:00
iter -> getSource () -> AI () -> EnterEvadeMode ();
2009-04-13 17:11:23 -05:00
}
2008-10-02 16:23:55 -05:00
}
}
2009-10-17 15:51:44 -07:00
2009-03-29 11:58:19 -06:00
void
ObjectGridCleaner :: Stop ( GridType & grid )
{
TypeContainerVisitor < ObjectGridCleaner , GridTypeMapContainer > stoper ( * this );
grid . Visit ( stoper );
}
2009-10-17 15:51:44 -07:00
2009-03-29 11:58:19 -06:00
void
ObjectGridCleaner :: Visit ( CreatureMapType & m )
{
2009-10-17 16:20:24 -07:00
for ( CreatureMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
2009-03-29 11:58:19 -06:00
iter -> getSource () -> CleanupsBeforeDelete ();
}
2009-10-17 15:51:44 -07:00
2009-03-29 11:58:19 -06:00
template < class T >
void
ObjectGridCleaner :: Visit ( GridRefManager < T > & m )
{
2009-10-17 16:20:24 -07:00
for ( typename GridRefManager < T >:: iterator iter = m . begin (); iter != m . end (); ++ iter )
2009-03-29 11:58:19 -06:00
iter -> getSource () -> RemoveFromWorld ();
}
2009-10-17 15:51:44 -07:00
2009-03-29 13:38:50 -06:00
template void ObjectGridUnloader :: Visit ( CreatureMapType & );
template void ObjectGridUnloader :: Visit ( GameObjectMapType & );
2009-03-29 11:58:19 -06:00
template void ObjectGridUnloader :: Visit ( DynamicObjectMapType & );
2009-03-29 13:38:50 -06:00
template void ObjectGridUnloader :: Visit ( CorpseMapType & );
2009-03-29 15:03:50 -06:00
template void ObjectGridCleaner :: Visit < GameObject > ( GameObjectMapType & );
template void ObjectGridCleaner :: Visit < DynamicObject > ( DynamicObjectMapType & );
template void ObjectGridCleaner :: Visit < Corpse > ( CorpseMapType & );