[8483] Implement glyph 43361.
[getmangos.git] / src / game / ObjectGridLoader.cpp
blob896c0726dab6003f43a436559c1d5eeaea6ae06c
1 /*
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"
22 #include "Creature.h"
23 #include "GameObject.h"
24 #include "DynamicObject.h"
25 #include "Corpse.h"
26 #include "World.h"
27 #include "CellImpl.h"
29 class MANGOS_DLL_DECL ObjectGridRespawnMover
31 public:
32 ObjectGridRespawnMover() {}
34 void Move(GridType &grid);
36 template<class T> void Visit(GridRefManager<T> &) {}
37 void Visit(CreatureMapType &m);
40 void
41 ObjectGridRespawnMover::Move(GridType &grid)
43 TypeContainerVisitor<ObjectGridRespawnMover, GridTypeMapContainer > mover(*this);
44 grid.Visit(mover);
47 void
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)
55 next = 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
79 public:
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>&) { }
88 private:
89 Cell i_cell;
90 NGridType &i_grid;
91 Map* i_map;
92 public:
93 uint32 i_corpses;
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);
109 template <class T>
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)
114 T* obj = new T;
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))
119 delete obj;
120 continue;
123 obj->GetGridRef().link(&m, obj);
125 addUnitState(obj,cell);
126 obj->SetMap(map);
127 obj->AddToWorld();
128 if(obj->isActiveObject())
129 map->AddToActive(obj);
131 ++count;
136 void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map)
138 if(cell_corpses.empty())
139 return;
141 for(CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr)
143 if(itr->second != map->GetInstanceId())
144 continue;
146 uint32 player_guid = itr->first;
148 Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid);
149 if(!obj)
150 continue;
152 obj->GetGridRef().link(&m, obj);
154 addUnitState(obj,cell);
155 obj->SetMap(map);
156 obj->AddToWorld();
157 if(obj->isActiveObject())
158 map->AddToActive(obj);
160 ++count;
164 void
165 ObjectGridLoader::Visit(GameObjectMapType &m)
167 uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX();
168 uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY();
169 CellPair cell_pair(x,y);
170 uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord;
172 CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id);
174 LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map);
177 void
178 ObjectGridLoader::Visit(CreatureMapType &m)
180 uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX();
181 uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY();
182 CellPair cell_pair(x,y);
183 uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord;
185 CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id);
187 LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map);
190 void
191 ObjectWorldLoader::Visit(CorpseMapType &m)
193 uint32 x = (i_cell.GridX()*MAX_NUMBER_OF_CELLS) + i_cell.CellX();
194 uint32 y = (i_cell.GridY()*MAX_NUMBER_OF_CELLS) + i_cell.CellY();
195 CellPair cell_pair(x,y);
196 uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord;
198 // corpses are always added to spawn mode 0 and they are spawned by their instance id
199 CellObjectGuids const& cell_guids = objmgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id);
200 LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map);
203 void
204 ObjectGridLoader::Load(GridType &grid)
207 TypeContainerVisitor<ObjectGridLoader, GridTypeMapContainer > loader(*this);
208 grid.Visit(loader);
212 ObjectWorldLoader wloader(*this);
213 TypeContainerVisitor<ObjectWorldLoader, WorldTypeMapContainer > loader(wloader);
214 grid.Visit(loader);
215 i_corpses = wloader.i_corpses;
219 void ObjectGridLoader::LoadN(void)
221 i_gameObjects = 0; i_creatures = 0; i_corpses = 0;
222 i_cell.data.Part.cell_y = 0;
223 for(unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x)
225 i_cell.data.Part.cell_x = x;
226 for(unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y)
228 i_cell.data.Part.cell_y = y;
229 GridLoader<Player, AllWorldObjectTypes, AllGridObjectTypes> loader;
230 loader.Load(i_grid(x, y), *this);
233 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());
236 void ObjectGridUnloader::MoveToRespawnN()
238 for(unsigned int x=0; x < MAX_NUMBER_OF_CELLS; ++x)
240 for(unsigned int y=0; y < MAX_NUMBER_OF_CELLS; ++y)
242 ObjectGridRespawnMover mover;
243 mover.Move(i_grid(x, y));
248 void
249 ObjectGridUnloader::Unload(GridType &grid)
251 TypeContainerVisitor<ObjectGridUnloader, GridTypeMapContainer > unloader(*this);
252 grid.Visit(unloader);
255 template<class T>
256 void
257 ObjectGridUnloader::Visit(GridRefManager<T> &m)
259 // remove all cross-reference before deleting
260 for(typename GridRefManager<T>::iterator iter=m.begin(); iter != m.end(); ++iter)
261 iter->getSource()->CleanupsBeforeDelete();
263 while(!m.isEmpty())
265 T *obj = m.getFirst()->getSource();
266 // if option set then object already saved at this moment
267 if(!sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATLY))
268 obj->SaveRespawnTime();
269 ///- object must be out of world before delete
270 obj->RemoveFromWorld();
271 ///- object will get delinked from the manager when deleted
272 delete obj;
276 void
277 ObjectGridStoper::Stop(GridType &grid)
279 TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer > stoper(*this);
280 grid.Visit(stoper);
283 void
284 ObjectGridStoper::Visit(CreatureMapType &m)
286 // stop any fights at grid de-activation and remove dynobjects created at cast by creatures
287 for(CreatureMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
289 iter->getSource()->CombatStop();
290 iter->getSource()->DeleteThreatList();
291 iter->getSource()->RemoveAllDynObjects();
295 template void ObjectGridUnloader::Visit(GameObjectMapType &);
296 template void ObjectGridUnloader::Visit(DynamicObjectMapType &);