[7915] Implement more stricted checks and limitations at loading creature addon data.
[getmangos.git] / src / game / ObjectGridLoader.cpp
blobde73ee18399ae2ffbb619d39b1fdba8cbc6540c1
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->AddToWorld();
127 if(obj->isActiveObject())
128 map->AddToActive(obj);
130 ++count;
135 void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map)
137 if(cell_corpses.empty())
138 return;
140 for(CellCorpseSet::const_iterator itr = cell_corpses.begin(); itr != cell_corpses.end(); ++itr)
142 if(itr->second != map->GetInstanceId())
143 continue;
145 uint32 player_guid = itr->first;
147 Corpse *obj = ObjectAccessor::Instance().GetCorpseForPlayerGUID(player_guid);
148 if(!obj)
149 continue;
151 obj->GetGridRef().link(&m, obj);
153 addUnitState(obj,cell);
154 obj->AddToWorld();
155 if(obj->isActiveObject())
156 map->AddToActive(obj);
158 ++count;
162 void
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);
175 void
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);
188 void
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);
201 void
202 ObjectGridLoader::Load(GridType &grid)
205 TypeContainerVisitor<ObjectGridLoader, GridTypeMapContainer > loader(*this);
206 grid.Visit(loader);
210 ObjectWorldLoader wloader(*this);
211 TypeContainerVisitor<ObjectWorldLoader, WorldTypeMapContainer > loader(wloader);
212 grid.Visit(loader);
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));
246 void
247 ObjectGridUnloader::Unload(GridType &grid)
249 TypeContainerVisitor<ObjectGridUnloader, GridTypeMapContainer > unloader(*this);
250 grid.Visit(unloader);
253 template<class T>
254 void
255 ObjectGridUnloader::Visit(GridRefManager<T> &m)
257 while(!m.isEmpty())
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
266 delete obj;
270 template<>
271 void
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();
278 while(!m.isEmpty())
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
285 delete obj;
289 void
290 ObjectGridStoper::Stop(GridType &grid)
292 TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer > stoper(*this);
293 grid.Visit(stoper);
296 void
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 &);