1//////////////////////////////////////////////////////////////////////
2// This file is part of Remere's Map Editor
3//////////////////////////////////////////////////////////////////////
4// Remere's Map Editor 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 3 of the License, or
7// (at your option) any later version.
8//
9// Remere's Map Editor 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.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//////////////////////////////////////////////////////////////////////
17
18#include "main.h"
19
20#include "map_region.h"
21#include "basemap.h"
22#include "position.h"
23#include "tile.h"
24
25//**************** Tile Location **********************
26
27TileLocation::TileLocation() :
28 tile(nullptr),
29 position(0, 0, 0),
30 spawn_count(0),
31 waypoint_count(0),
32 town_count(0),
33 house_exits(nullptr) {
34 ////
35}
36
37TileLocation::~TileLocation() {
38 delete tile;
39 delete house_exits;
40}
41
42int TileLocation::size() const {
43 if (tile) {
44 return tile->size();
45 }
46 return spawn_count + waypoint_count + (house_exits ? 1 : 0);
47}
48
49bool TileLocation::empty() const {
50 return size() == 0;
51}
52
53//**************** Floor **********************
54
55Floor::Floor(int sx, int sy, int z) {
56 sx = sx & ~3;
57 sy = sy & ~3;
58
59 for (int i = 0; i < MAP_LAYERS; ++i) {
60 locs[i].position.x = sx + (i >> 2);
61 locs[i].position.y = sy + (i & 3);
62 locs[i].position.z = z;
63 }
64}
65
66//**************** QTreeNode **********************
67
68QTreeNode::QTreeNode(BaseMap& map) :
69 map(map),
70 visible(0),
71 isLeaf(false) {
72 // Doesn't matter if we're leaf or node
73 for (int i = 0; i < MAP_LAYERS; ++i) {
74 child[i] = nullptr;
75 }
76}
77
78QTreeNode::~QTreeNode() {
79 if (isLeaf) {
80 for (int i = 0; i < MAP_LAYERS; ++i) {
81 delete array[i];
82 }
83 } else {
84 for (int i = 0; i < MAP_LAYERS; ++i) {
85 delete child[i];
86 }
87 }
88}
89
90QTreeNode* QTreeNode::getLeaf(int x, int y) {
91 QTreeNode* node = this;
92 uint32_t cx = x, cy = y;
93 while (node) {
94 if (node->isLeaf) {
95 return node;
96 } else {
97 uint32_t index = ((cx & 0xC000) >> 14) | ((cy & 0xC000) >> 12);
98 if (node->child[index]) {
99 node = node->child[index];
100 cx <<= 2;
101 cy <<= 2;
102 } else {
103 return nullptr;
104 }
105 }
106 }
107 return nullptr;
108}
109
110QTreeNode* QTreeNode::getLeafForce(int x, int y) {
111 QTreeNode* node = this;
112 uint32_t cx = x, cy = y;
113 int level = 6;
114 while (node) {
115 uint32_t index = ((cx & 0xC000) >> 14) | ((cy & 0xC000) >> 12);
116
117 QTreeNode*& qt = node->child[index];
118 if (qt) {
119 if (qt->isLeaf) {
120 return qt;
121 }
122
123 } else {
124 if (level == 0) {
125 qt = newd QTreeNode(map);
126 qt->isLeaf = true;
127 return qt;
128 } else {
129 qt = newd QTreeNode(map);
130 }
131 }
132 node = node->child[index];
133 cx <<= 2;
134 cy <<= 2;
135 level -= 1;
136 }
137
138 return nullptr;
139}
140
141Floor* QTreeNode::createFloor(int x, int y, int z) {
142 ASSERT(isLeaf);
143 if (!array[z]) {
144 array[z] = newd Floor(x, y, z);
145 }
146 return array[z];
147}
148
149bool QTreeNode::isVisible(bool underground) {
150 return testFlags(visible, underground + 1);
151}
152
153bool QTreeNode::isRequested(bool underground) {
154 if (underground) {
155 return testFlags(visible, 4);
156 } else {
157 return testFlags(visible, 8);
158 }
159}
160
161void QTreeNode::clearVisible(uint32_t u) {
162 if (isLeaf) {
163 visible &= u;
164 } else {
165 for (int i = 0; i < MAP_LAYERS; ++i) {
166 if (child[i]) {
167 child[i]->clearVisible(u);
168 }
169 }
170 }
171}
172
173bool QTreeNode::isVisible(uint32_t client, bool underground) {
174 if (underground) {
175 return testFlags(visible >> MAP_LAYERS, static_cast<uint64_t>(1) << client);
176 } else {
177 return testFlags(visible, static_cast<uint64_t>(1) << client);
178 }
179}
180
181void QTreeNode::setVisible(bool underground, bool value) {
182 if (underground) {
183 if (value) {
184 visible |= 2;
185 } else {
186 visible &= ~2;
187 }
188 } else { // overground
189 if (value) {
190 visible |= 1;
191 } else {
192 visible &= 1;
193 }
194 }
195}
196
197void QTreeNode::setRequested(bool underground, bool r) {
198 if (r) {
199 visible |= (underground ? 4 : 8);
200 } else {
201 visible &= ~(underground ? 4 : 8);
202 }
203}
204
205void QTreeNode::setVisible(uint32_t client, bool underground, bool value) {
206 if (value) {
207 visible |= (1 << client << (underground ? MAP_LAYERS : 0));
208 } else {
209 visible &= ~(1 << client << (underground ? MAP_LAYERS : 0));
210 }
211}
212
213TileLocation* QTreeNode::getTile(int x, int y, int z) {
214 ASSERT(isLeaf);
215 Floor* f = array[z];
216 if (!f) {
217 return nullptr;
218 }
219 return &f->locs[(x & 3) * 4 + (y & 3)];
220}
221
222TileLocation* QTreeNode::createTile(int x, int y, int z) {
223 ASSERT(isLeaf);
224 Floor* f = createFloor(x, y, z);
225 return &f->locs[(x & 3) * 4 + (y & 3)];
226}
227
228Tile* QTreeNode::setTile(int x, int y, int z, Tile* newtile) {
229 ASSERT(isLeaf);
230 Floor* f = createFloor(x, y, z);
231
232 int offset_x = x & 3;
233 int offset_y = y & 3;
234
235 TileLocation* tmp = &f->locs[offset_x * 4 + offset_y];
236 Tile* oldtile = tmp->tile;
237 tmp->tile = newtile;
238
239 if (newtile && !oldtile) {
240 ++map.tilecount;
241 } else if (oldtile && !newtile) {
242 --map.tilecount;
243 }
244
245 return oldtile;
246}
247
248void QTreeNode::clearTile(int x, int y, int z) {
249 ASSERT(isLeaf);
250 Floor* f = createFloor(x, y, z);
251
252 int offset_x = x & 3;
253 int offset_y = y & 3;
254
255 TileLocation* tmp = &f->locs[offset_x * 4 + offset_y];
256 delete tmp->tile;
257 tmp->tile = map.allocator(tmp);
258}
259