2 * Copyright (C) 2005-2009 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"
23 #include "GameObject.h"
24 #include "DynamicObject.h"
29 class MANGOS_DLL_DECL ObjectGridRespawnMover
32 ObjectGridRespawnMover() {}
34 void Move(GridType
&grid
);
36 template<class T
> void Visit(GridRefManager
<T
> &) {}
37 void Visit(CreatureMapType
&m
);
41 ObjectGridRespawnMover::Move(GridType
&grid
)
43 TypeContainerVisitor
<ObjectGridRespawnMover
, GridTypeMapContainer
> mover(*this);
48 ObjectGridRespawnMover::Visit(CreatureMapType
&m
)
50 // creature in unloading grid can have respawn point in another grid
51 // if it will be unloaded then it will not respawn in original grid until unload/load original grid
52 // move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
53 for(CreatureMapType::iterator iter
=m
.begin(), next
; iter
!= m
.end(); iter
= next
)
57 Creature
* c
= iter
->getSource();
59 assert((!c
->isPet() || !c
->isVehicle()) && "ObjectGridRespawnMover don't must be called for pets");
61 Cell
const& cur_cell
= c
->GetCurrentCell();
63 float resp_x
, resp_y
, resp_z
;
64 c
->GetRespawnCoord(resp_x
, resp_y
, resp_z
);
65 CellPair resp_val
= MaNGOS::ComputeCellPair(resp_x
, resp_y
);
66 Cell
resp_cell(resp_val
);
68 if(cur_cell
.DiffGrid(resp_cell
))
70 c
->GetMap()->CreatureRespawnRelocation(c
);
71 // false result ignored: will be unload with other creatures at grid
76 // for loading world object at grid loading (Corpses)
77 class ObjectWorldLoader
80 explicit ObjectWorldLoader(ObjectGridLoader
& gloader
)
81 : i_cell(gloader
.i_cell
), i_grid(gloader
.i_grid
), i_map(gloader
.i_map
), i_corpses (0)
84 void Visit(CorpseMapType
&m
);
86 template<class T
> void Visit(GridRefManager
<T
>&) { }
96 template<class T
> void addUnitState(T
* /*obj*/, CellPair
const& /*cell_pair*/)
100 template<> void addUnitState(Creature
*obj
, CellPair
const& cell_pair
)
102 Cell
cell(cell_pair
);
104 obj
->SetCurrentCell(cell
);
105 if(obj
->isSpiritService())
106 obj
->setDeathState(DEAD
);
110 void LoadHelper(CellGuidSet
const& guid_set
, CellPair
&cell
, GridRefManager
<T
> &m
, uint32
&count
, Map
* map
)
112 for(CellGuidSet::const_iterator i_guid
= guid_set
.begin(); i_guid
!= guid_set
.end(); ++i_guid
)
115 uint32 guid
= *i_guid
;
116 //sLog.outString("DEBUG: LoadHelper from table: %s for (guid: %u) Loading",table,guid);
117 if(!obj
->LoadFromDB(guid
, map
))
123 obj
->GetGridRef().link(&m
, obj
);
125 addUnitState(obj
,cell
);
127 if(obj
->isActiveObject())
128 map
->AddToActive(obj
);
135 void LoadHelper(CellCorpseSet
const& cell_corpses
, CellPair
&cell
, CorpseMapType
&m
, uint32
&count
, Map
* map
)
137 if(cell_corpses
.empty())
140 for(CellCorpseSet::const_iterator itr
= cell_corpses
.begin(); itr
!= cell_corpses
.end(); ++itr
)
142 if(itr
->second
!= map
->GetInstanceId())
145 uint32 player_guid
= itr
->first
;
147 Corpse
*obj
= ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid
);
151 obj
->GetGridRef().link(&m
, obj
);
153 addUnitState(obj
,cell
);
155 if(obj
->isActiveObject())
156 map
->AddToActive(obj
);
163 ObjectGridLoader::Visit(GameObjectMapType
&m
)
165 uint32 x
= (i_cell
.GridX()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellX();
166 uint32 y
= (i_cell
.GridY()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellY();
167 CellPair
cell_pair(x
,y
);
168 uint32 cell_id
= (cell_pair
.y_coord
*TOTAL_NUMBER_OF_CELLS_PER_MAP
) + cell_pair
.x_coord
;
170 CellObjectGuids
const& cell_guids
= objmgr
.GetCellObjectGuids(i_map
->GetId(), i_map
->GetSpawnMode(), cell_id
);
172 LoadHelper(cell_guids
.gameobjects
, cell_pair
, m
, i_gameObjects
, i_map
);
176 ObjectGridLoader::Visit(CreatureMapType
&m
)
178 uint32 x
= (i_cell
.GridX()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellX();
179 uint32 y
= (i_cell
.GridY()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellY();
180 CellPair
cell_pair(x
,y
);
181 uint32 cell_id
= (cell_pair
.y_coord
*TOTAL_NUMBER_OF_CELLS_PER_MAP
) + cell_pair
.x_coord
;
183 CellObjectGuids
const& cell_guids
= objmgr
.GetCellObjectGuids(i_map
->GetId(), i_map
->GetSpawnMode(), cell_id
);
185 LoadHelper(cell_guids
.creatures
, cell_pair
, m
, i_creatures
, i_map
);
189 ObjectWorldLoader::Visit(CorpseMapType
&m
)
191 uint32 x
= (i_cell
.GridX()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellX();
192 uint32 y
= (i_cell
.GridY()*MAX_NUMBER_OF_CELLS
) + i_cell
.CellY();
193 CellPair
cell_pair(x
,y
);
194 uint32 cell_id
= (cell_pair
.y_coord
*TOTAL_NUMBER_OF_CELLS_PER_MAP
) + cell_pair
.x_coord
;
196 // corpses are always added to spawn mode 0 and they are spawned by their instance id
197 CellObjectGuids
const& cell_guids
= objmgr
.GetCellObjectGuids(i_map
->GetId(), 0, cell_id
);
198 LoadHelper(cell_guids
.corpses
, cell_pair
, m
, i_corpses
, i_map
);
202 ObjectGridLoader::Load(GridType
&grid
)
205 TypeContainerVisitor
<ObjectGridLoader
, GridTypeMapContainer
> loader(*this);
210 ObjectWorldLoader
wloader(*this);
211 TypeContainerVisitor
<ObjectWorldLoader
, WorldTypeMapContainer
> loader(wloader
);
213 i_corpses
= wloader
.i_corpses
;
217 void ObjectGridLoader::LoadN(void)
219 i_gameObjects
= 0; i_creatures
= 0; i_corpses
= 0;
220 i_cell
.data
.Part
.cell_y
= 0;
221 for(unsigned int x
=0; x
< MAX_NUMBER_OF_CELLS
; ++x
)
223 i_cell
.data
.Part
.cell_x
= x
;
224 for(unsigned int y
=0; y
< MAX_NUMBER_OF_CELLS
; ++y
)
226 i_cell
.data
.Part
.cell_y
= y
;
227 GridLoader
<Player
, AllWorldObjectTypes
, AllGridObjectTypes
> loader
;
228 loader
.Load(i_grid(x
, y
), *this);
231 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());
234 void ObjectGridUnloader::MoveToRespawnN()
236 for(unsigned int x
=0; x
< MAX_NUMBER_OF_CELLS
; ++x
)
238 for(unsigned int y
=0; y
< MAX_NUMBER_OF_CELLS
; ++y
)
240 ObjectGridRespawnMover mover
;
241 mover
.Move(i_grid(x
, y
));
247 ObjectGridUnloader::Unload(GridType
&grid
)
249 TypeContainerVisitor
<ObjectGridUnloader
, GridTypeMapContainer
> unloader(*this);
250 grid
.Visit(unloader
);
255 ObjectGridUnloader::Visit(GridRefManager
<T
> &m
)
259 T
*obj
= m
.getFirst()->getSource();
260 // if option set then object already saved at this moment
261 if(!sWorld
.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY
))
262 obj
->SaveRespawnTime();
263 ///- object must be out of world before delete
264 obj
->RemoveFromWorld();
265 ///- object will get delinked from the manager when deleted
272 ObjectGridUnloader::Visit(CreatureMapType
&m
)
274 // remove all cross-reference before deleting
275 for(CreatureMapType::iterator iter
=m
.begin(); iter
!= m
.end(); ++iter
)
276 iter
->getSource()->CleanupsBeforeDelete();
280 Creature
*obj
= m
.getFirst()->getSource();
281 // if option set then object already saved at this moment
282 if(!sWorld
.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY
))
283 obj
->SaveRespawnTime();
284 ///- object will get delinked from the manager when deleted
290 ObjectGridStoper::Stop(GridType
&grid
)
292 TypeContainerVisitor
<ObjectGridStoper
, GridTypeMapContainer
> stoper(*this);
297 ObjectGridStoper::Visit(CreatureMapType
&m
)
299 // stop any fights at grid de-activation and remove dynobjects created at cast by creatures
300 for(CreatureMapType::iterator iter
=m
.begin(); iter
!= m
.end(); ++iter
)
302 iter
->getSource()->CombatStop();
303 iter
->getSource()->DeleteThreatList();
304 iter
->getSource()->RemoveAllDynObjects();
308 template void ObjectGridUnloader::Visit(GameObjectMapType
&);
309 template void ObjectGridUnloader::Visit(DynamicObjectMapType
&);