TrinityCore
CellImpl.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITY_CELLIMPL_H
19#define TRINITY_CELLIMPL_H
20
21#include "Cell.h"
22#include "Map.h"
23#include "Object.h"
24
25inline Cell::Cell(CellCoord const& p)
26{
27 data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS;
28 data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS;
29 data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS;
30 data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS;
31 data.Part.nocreate = 0;
32 data.Part.reserved = 0;
33}
34
35inline Cell::Cell(float x, float y)
36{
38 data.Part.grid_x = p.x_coord / MAX_NUMBER_OF_CELLS;
39 data.Part.grid_y = p.y_coord / MAX_NUMBER_OF_CELLS;
40 data.Part.cell_x = p.x_coord % MAX_NUMBER_OF_CELLS;
41 data.Part.cell_y = p.y_coord % MAX_NUMBER_OF_CELLS;
42 data.Part.nocreate = 0;
43 data.Part.reserved = 0;
44}
45
46inline CellArea Cell::CalculateCellArea(float x, float y, float radius)
47{
48 if (radius <= 0.0f)
49 {
51 return CellArea(center, center);
52 }
53
54 CellCoord centerX = Trinity::ComputeCellCoord(x - radius, y - radius).normalize();
55 CellCoord centerY = Trinity::ComputeCellCoord(x + radius, y + radius).normalize();
56
57 return CellArea(centerX, centerY);
58}
59
60template<class T, class CONTAINER>
61inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, WorldObject const& obj, float radius) const
62{
63 //we should increase search radius by object's radius, otherwise
64 //we could have problems with huge creatures, which won't attack nearest players etc
65 Visit(standing_cell, visitor, map, obj.GetPositionX(), obj.GetPositionY(), radius + obj.GetCombatReach());
66}
67
68template<class T, class CONTAINER>
69inline void Cell::Visit(CellCoord const& standing_cell, TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, float x_off, float y_off, float radius) const
70{
71 if (!standing_cell.IsCoordValid())
72 return;
73
74 //no jokes here... Actually placing ASSERT() here was good idea, but
75 //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?)
76 //maybe it is better to just return when radius <= 0.0f?
77 if (radius <= 0.0f)
78 {
79 map.Visit(*this, visitor);
80 return;
81 }
82 //lets limit the upper value for search radius
83 if (radius > SIZE_OF_GRIDS)
84 radius = SIZE_OF_GRIDS;
85
86 //lets calculate object coord offsets from cell borders.
87 CellArea area = Cell::CalculateCellArea(x_off, y_off, radius);
88 //if radius fits inside standing cell
89 if (!area)
90 {
91 map.Visit(*this, visitor);
92 return;
93 }
94
95 //visit all cells, found in CalculateCellArea()
96 //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle
97 //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values
98 //there are nothing to optimize because SIZE_OF_GRID_CELL is too big...
99 if ((area.high_bound.x_coord > (area.low_bound.x_coord + 4)) && (area.high_bound.y_coord > (area.low_bound.y_coord + 4)))
100 {
101 VisitCircle(visitor, map, area.low_bound, area.high_bound);
102 return;
103 }
104
105 //ALWAYS visit standing cell first!!! Since we deal with small radiuses
106 //it is very essential to call visitor for standing cell firstly...
107 map.Visit(*this, visitor);
108
109 // loop the cell range
110 for (uint32 x = area.low_bound.x_coord; x <= area.high_bound.x_coord; ++x)
111 {
112 for (uint32 y = area.low_bound.y_coord; y <= area.high_bound.y_coord; ++y)
113 {
114 CellCoord cellCoord(x, y);
115 //lets skip standing cell since we already visited it
116 if (cellCoord != standing_cell)
117 {
118 Cell r_zone(cellCoord);
119 r_zone.data.Part.nocreate = this->data.Part.nocreate;
120 map.Visit(r_zone, visitor);
121 }
122 }
123 }
124}
125
126template<class T, class CONTAINER>
127inline void Cell::VisitCircle(TypeContainerVisitor<T, CONTAINER>& visitor, Map& map, CellCoord const& begin_cell, CellCoord const& end_cell) const
128{
129 //here is an algorithm for 'filling' circum-squared octagon
130 uint32 x_shift = (uint32)ceilf((end_cell.x_coord - begin_cell.x_coord) * 0.3f - 0.5f);
131 //lets calculate x_start/x_end coords for central strip...
132 const uint32 x_start = begin_cell.x_coord + x_shift;
133 const uint32 x_end = end_cell.x_coord - x_shift;
134
135 //visit central strip with constant width...
136 for (uint32 x = x_start; x <= x_end; ++x)
137 {
138 for (uint32 y = begin_cell.y_coord; y <= end_cell.y_coord; ++y)
139 {
140 CellCoord cellCoord(x, y);
141 Cell r_zone(cellCoord);
142 r_zone.data.Part.nocreate = this->data.Part.nocreate;
143 map.Visit(r_zone, visitor);
144 }
145 }
146
147 //if x_shift == 0 then we have too small cell area, which were already
148 //visited at previous step, so just return from procedure...
149 if (x_shift == 0)
150 return;
151
152 uint32 y_start = end_cell.y_coord;
153 uint32 y_end = begin_cell.y_coord;
154 //now we are visiting borders of an octagon...
155 for (uint32 step = 1; step <= (x_start - begin_cell.x_coord); ++step)
156 {
157 //each step reduces strip height by 2 cells...
158 y_end += 1;
159 y_start -= 1;
160 for (uint32 y = y_start; y >= y_end; --y)
161 {
162 //we visit cells symmetrically from both sides, heading from center to sides and from up to bottom
163 //e.g. filling 2 trapezoids after filling central cell strip...
164 CellCoord cellCoord_left(x_start - step, y);
165 Cell r_zone_left(cellCoord_left);
166 r_zone_left.data.Part.nocreate = this->data.Part.nocreate;
167 map.Visit(r_zone_left, visitor);
168
169 //right trapezoid cell visit
170 CellCoord cellCoord_right(x_end + step, y);
171 Cell r_zone_right(cellCoord_right);
172 r_zone_right.data.Part.nocreate = this->data.Part.nocreate;
173 map.Visit(r_zone_right, visitor);
174 }
175 }
176}
177
178template<class T>
179inline void Cell::VisitGridObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load)
180{
181 CellCoord p(Trinity::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
182 Cell cell(p);
183 if (dont_load)
184 cell.SetNoCreate();
185
187 cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius);
188}
189
190template<class T>
191inline void Cell::VisitWorldObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load)
192{
193 CellCoord p(Trinity::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
194 Cell cell(p);
195 if (dont_load)
196 cell.SetNoCreate();
197
199 cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius);
200}
201
202template<class T>
203inline void Cell::VisitAllObjects(WorldObject const* center_obj, T& visitor, float radius, bool dont_load)
204{
205 CellCoord p(Trinity::ComputeCellCoord(center_obj->GetPositionX(), center_obj->GetPositionY()));
206 Cell cell(p);
207 if (dont_load)
208 cell.SetNoCreate();
209
211 cell.Visit(p, wnotifier, *center_obj->GetMap(), *center_obj, radius);
213 cell.Visit(p, gnotifier, *center_obj->GetMap(), *center_obj, radius);
214}
215
216template<class T>
217inline void Cell::VisitGridObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load)
218{
220 Cell cell(p);
221 if (dont_load)
222 cell.SetNoCreate();
223
225 cell.Visit(p, gnotifier, *map, x, y, radius);
226}
227
228template<class T>
229inline void Cell::VisitWorldObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load)
230{
232 Cell cell(p);
233 if (dont_load)
234 cell.SetNoCreate();
235
237 cell.Visit(p, gnotifier, *map, x, y, radius);
238}
239
240template<class T>
241inline void Cell::VisitAllObjects(float x, float y, Map* map, T& visitor, float radius, bool dont_load)
242{
244 Cell cell(p);
245 if (dont_load)
246 cell.SetNoCreate();
247
249 cell.Visit(p, wnotifier, *map, x, y, radius);
251 cell.Visit(p, gnotifier, *map, x, y, radius);
252}
253
254#endif
uint32_t uint32
Definition: Define.h:142
#define MAX_NUMBER_OF_CELLS
Definition: GridDefines.h:36
#define SIZE_OF_GRIDS
Definition: GridDefines.h:40
Definition: Map.h:189
void Visit(Cell const &cell, TypeContainerVisitor< T, CONTAINER > &visitor)
Definition: Map.h:921
Map * GetMap() const
Definition: Object.h:624
virtual float GetCombatReach() const
Definition: Object.h:514
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:206
Definition: Cell.h:30
CellCoord high_bound
Definition: Cell.h:43
CellCoord low_bound
Definition: Cell.h:42
Definition: Cell.h:47
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:203
unsigned nocreate
Definition: Cell.h:100
void SetNoCreate()
Definition: Cell.h:76
Cell()
Definition: Cell.h:48
union Cell::@313 data
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:179
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:191
void VisitCircle(TypeContainerVisitor< T, CONTAINER > &, Map &, CellCoord const &, CellCoord const &) const
Definition: CellImpl.h:127
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &obj, float radius) const
Definition: CellImpl.h:61
static CellArea CalculateCellArea(float x, float y, float radius)
Definition: CellImpl.h:46
struct Cell::@313::@314 Part
bool IsCoordValid() const
Definition: GridDefines.h:154
uint32 x_coord
Definition: GridDefines.h:173
uint32 y_coord
Definition: GridDefines.h:174
CoordPair & normalize()
Definition: GridDefines.h:159
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77