2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "ObjectGridLoader.h"
20 #include "ObjectAccessor.h"
21 #include "ObjectMgr.h"
22 #include "MapManager.h"
24 #include "GameObject.h"
25 #include "DynamicObject.h"
30 class MANGOS_DLL_DECL ObjectGridRespawnMover
33 ObjectGridRespawnMover() {}
35 void Move(GridType
&grid
);
37 template<class T
> void Visit(GridRefManager
<T
> &) {}
38 void Visit(CreatureMapType
&m
);
42 ObjectGridRespawnMover::Move(GridType
&grid
)
44 TypeContainerVisitor
<ObjectGridRespawnMover
, GridTypeMapContainer
> mover(*this);
49 ObjectGridRespawnMover::Visit(CreatureMapType
&m
)
51 // creature in unloading grid can have respawn point in another grid
52 // if it will be unloaded then it will not respawn in original grid until unload/load original grid
53 // move to respwn point to prevent this case. For player view in respawn grid this wll be normal respawn.
54 for(CreatureMapType::iterator iter
=m
.begin(), next
; iter
!= m
.end(); iter
= next
)
58 Creature
* c
= iter
->getSource();
60 assert(!c
->isPet() && "ObjectGridRespawnMover don't must be called for pets");
62 Cell
const& cur_cell
= c
->GetCurrentCell();
64 float resp_x
, resp_y
, resp_z
;
65 c
->GetRespawnCoord(resp_x
, resp_y
, resp_z
);
66 CellPair resp_val
= MaNGOS::ComputeCellPair(resp_x
, resp_y
);
67 Cell
resp_cell(resp_val
);
69 if(cur_cell
.DiffGrid(resp_cell
))
71 c
->GetMap()->CreatureRespawnRelocation(c
);
72 // false result ignored: will be unload with other creatures at grid
77 // for loading world object at grid loading (Corpses)
78 class ObjectWorldLoader
81 explicit ObjectWorldLoader(ObjectGridLoader
& gloader
)
82 : i_cell(gloader
.i_cell
), i_grid(gloader
.i_grid
), i_map(gloader
.i_map
), i_corpses (0)
85 void Visit(CorpseMapType
&m
);
87 template<class T
> void Visit(GridRefManager
<T
>&) { }
97 template<class T
> void addUnitState(T
* /*obj*/, CellPair
const& /*cell_pair*/)
101 template<> void addUnitState(Creature
*obj
, CellPair
const& cell_pair
)
103 Cell
cell(cell_pair
);
105 obj
->SetCurrentCell(cell
);
106 if(obj
->isSpiritService())
107 obj
->setDeathState(DEAD
);
111 void LoadHelper(CellGuidSet
const& guid_set
, CellPair
&cell
, GridRefManager
<T
> &m
, uint32
&count
, Map
* map
)
113 for(CellGuidSet::const_iterator i_guid
= guid_set
.begin(); i_guid
!= guid_set
.end(); ++i_guid
)
116 uint32 guid
= *i_guid
;
117 //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid);
118 if(!obj
->LoadFromDB(guid
, map
))
124 obj
->GetGridRef().link(&m
, obj
);
126 addUnitState(obj
,cell
);
133 void LoadHelper(CellCorpseSet
const& cell_corpses
, CellPair
&cell
, CorpseMapType
&m
, uint32
&count
, Map
* map
)
135 if(cell_corpses
.empty())
138 for(CellCorpseSet::const_iterator itr
= cell_corpses
.begin(); itr
!= cell_corpses
.end(); ++itr
)
140 if(itr
->second
!= map
->GetInstanceId())
143 uint32 player_guid
= itr
->first
;
145 Corpse
*obj
= ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid
);
149 obj
->GetGridRef().link(&m
, obj
);
151 addUnitState(obj
,cell
);
158 ObjectGridLoader::Visit(GameObjectMapType
&m
)
160 uint32 x
= (i_cell
.GridX()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellX();
161 uint32 y
= (i_cell
.GridY()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellY();
162 CellPair
cell_pair(x
,y
);
163 uint32 cell_id
= (cell_pair
.y_coord
*TOTAL_NUMBER_OF_CELLS_PER_MAP
) + cell_pair
.x_coord
;
165 CellObjectGuids
const& cell_guids
= objmgr
.GetCellObjectGuids(i_map
->GetId(), i_map
->GetSpawnMode(), cell_id
);
167 LoadHelper(cell_guids
.gameobjects
, cell_pair
, m
, i_gameObjects
, i_map
);
171 ObjectGridLoader::Visit(CreatureMapType
&m
)
173 uint32 x
= (i_cell
.GridX()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellX();
174 uint32 y
= (i_cell
.GridY()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellY();
175 CellPair
cell_pair(x
,y
);
176 uint32 cell_id
= (cell_pair
.y_coord
*TOTAL_NUMBER_OF_CELLS_PER_MAP
) + cell_pair
.x_coord
;
178 CellObjectGuids
const& cell_guids
= objmgr
.GetCellObjectGuids(i_map
->GetId(), i_map
->GetSpawnMode(), cell_id
);
180 LoadHelper(cell_guids
.creatures
, cell_pair
, m
, i_creatures
, i_map
);
184 ObjectWorldLoader::Visit(CorpseMapType
&m
)
186 uint32 x
= (i_cell
.GridX()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellX();
187 uint32 y
= (i_cell
.GridY()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellY();
188 CellPair
cell_pair(x
,y
);
189 uint32 cell_id
= (cell_pair
.y_coord
*TOTAL_NUMBER_OF_CELLS_PER_MAP
) + cell_pair
.x_coord
;
191 // corpses are always added to spawn mode 0 and they are spawned by their instance id
192 CellObjectGuids
const& cell_guids
= objmgr
.GetCellObjectGuids(i_map
->GetId(), 0, cell_id
);
193 LoadHelper(cell_guids
.corpses
, cell_pair
, m
, i_corpses
, i_map
);
197 ObjectGridLoader::Load(GridType
&grid
)
200 TypeContainerVisitor
<ObjectGridLoader
, GridTypeMapContainer
> loader(*this);
205 ObjectWorldLoader
wloader(*this);
206 TypeContainerVisitor
<ObjectWorldLoader
, WorldTypeMapContainer
> loader(wloader
);
208 i_corpses
= wloader
.i_corpses
;
212 void ObjectGridLoader::LoadN(void)
214 i_gameObjects
= 0; i_creatures
= 0; i_corpses
= 0;
215 i_cell
.data
.Part
.cell_y
= 0;
216 for(unsigned int x
=0; x
< MAX_NUMBER_OF_CELLS
; ++x
)
218 i_cell
.data
.Part
.cell_x
= x
;
219 for(unsigned int y
=0; y
< MAX_NUMBER_OF_CELLS
; ++y
)
221 i_cell
.data
.Part
.cell_y
= y
;
222 GridLoader
<Player
, AllWorldObjectTypes
, AllGridObjectTypes
> loader
;
223 loader
.Load(i_grid(x
, y
), *this);
226 sLog
.outDebug("%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());
229 void ObjectGridUnloader::MoveToRespawnN()
231 for(unsigned int x
=0; x
< MAX_NUMBER_OF_CELLS
; ++x
)
233 for(unsigned int y
=0; y
< MAX_NUMBER_OF_CELLS
; ++y
)
235 ObjectGridRespawnMover mover
;
236 mover
.Move(i_grid(x
, y
));
242 ObjectGridUnloader::Unload(GridType
&grid
)
244 TypeContainerVisitor
<ObjectGridUnloader
, GridTypeMapContainer
> unloader(*this);
245 grid
.Visit(unloader
);
250 ObjectGridUnloader::Visit(GridRefManager
<T
> &m
)
254 T
*obj
= m
.getFirst()->getSource();
255 // if option set then object already saved at this moment
256 if(!sWorld
.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY
))
257 obj
->SaveRespawnTime();
258 ///- object must be out of world before delete
259 obj
->RemoveFromWorld();
260 ///- object will get delinked from the manager when deleted
267 ObjectGridUnloader::Visit(CreatureMapType
&m
)
269 // remove all cross-reference before deleting
270 for(CreatureMapType::iterator iter
=m
.begin(); iter
!= m
.end(); ++iter
)
271 iter
->getSource()->CleanupsBeforeDelete();
275 Creature
*obj
= m
.getFirst()->getSource();
276 // if option set then object already saved at this moment
277 if(!sWorld
.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY
))
278 obj
->SaveRespawnTime();
279 ///- object will get delinked from the manager when deleted
285 ObjectGridStoper::Stop(GridType
&grid
)
287 TypeContainerVisitor
<ObjectGridStoper
, GridTypeMapContainer
> stoper(*this);
292 ObjectGridStoper::Visit(CreatureMapType
&m
)
294 // stop any fights at grid de-activation and remove dynobjects created at cast by creatures
295 for(CreatureMapType::iterator iter
=m
.begin(); iter
!= m
.end(); ++iter
)
297 iter
->getSource()->CombatStop();
298 iter
->getSource()->DeleteThreatList();
299 iter
->getSource()->RemoveAllDynObjects();
303 template void ObjectGridUnloader::Visit(GameObjectMapType
&);
304 template void ObjectGridUnloader::Visit(DynamicObjectMapType
&);