1 |
|
|
/* |
2 |
|
|
* The ManaPlus Client |
3 |
|
|
* Copyright (C) 2004-2009 The Mana World Development Team |
4 |
|
|
* Copyright (C) 2009-2010 The Mana Developers |
5 |
|
|
* Copyright (C) 2011-2019 The ManaPlus Developers |
6 |
|
|
* Copyright (C) 2019-2021 Andrei Karas |
7 |
|
|
* |
8 |
|
|
* This file is part of The ManaPlus Client. |
9 |
|
|
* |
10 |
|
|
* This program is free software; you can redistribute it and/or modify |
11 |
|
|
* it under the terms of the GNU General Public License as published by |
12 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
13 |
|
|
* any later version. |
14 |
|
|
* |
15 |
|
|
* This program is distributed in the hope that it will be useful, |
16 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
|
|
* GNU General Public License for more details. |
19 |
|
|
* |
20 |
|
|
* You should have received a copy of the GNU General Public License |
21 |
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "resources/map/maplayer.h" |
25 |
|
|
|
26 |
|
|
#include "configuration.h" |
27 |
|
|
|
28 |
|
|
#include "being/localplayer.h" |
29 |
|
|
|
30 |
|
|
#include "enums/resources/map/blockmask.h" |
31 |
|
|
#include "enums/resources/map/mapitemtype.h" |
32 |
|
|
|
33 |
|
|
#include "gui/userpalette.h" |
34 |
|
|
|
35 |
|
|
#ifdef USE_OPENGL |
36 |
|
|
#include "utils/foreach.h" |
37 |
|
|
#endif // USE_OPENGL |
38 |
|
|
|
39 |
|
|
#include "render/graphics.h" |
40 |
|
|
|
41 |
|
|
#include "resources/image/image.h" |
42 |
|
|
|
43 |
|
|
#include "resources/map/mapitem.h" |
44 |
|
|
#include "resources/map/maprowvertexes.h" |
45 |
|
|
#include "resources/map/metatile.h" |
46 |
|
|
#include "resources/map/speciallayer.h" |
47 |
|
|
|
48 |
|
|
#include "debug.h" |
49 |
|
|
|
50 |
|
69 |
MapLayer::MapLayer(const std::string &name, |
51 |
|
|
const int x, |
52 |
|
|
const int y, |
53 |
|
|
const int width, |
54 |
|
|
const int height, |
55 |
|
|
const bool fringeLayer, |
56 |
|
|
const int mask, |
57 |
|
69 |
const int tileCondition) : |
58 |
|
|
mX(x), |
59 |
|
|
mY(y), |
60 |
|
69 |
mPixelX(mX * mapTileSize), |
61 |
|
69 |
mPixelY(mY * mapTileSize + mapTileSize), |
62 |
|
|
mWidth(width), |
63 |
|
|
mHeight(height), |
64 |
✓✗✓✗ ✓✓ |
190191 |
mTiles(new TileInfo[mWidth * mHeight]), |
65 |
|
|
mDrawLayerFlags(MapType::NORMAL), |
66 |
|
|
mSpecialLayer(nullptr), |
67 |
|
|
mTempLayer(nullptr), |
68 |
|
|
mName(name), |
69 |
|
|
mTempRows(), |
70 |
|
|
mMask(mask), |
71 |
|
|
mTileCondition(tileCondition), |
72 |
|
|
mActorsFix(0), |
73 |
|
|
mIsFringeLayer(fringeLayer), |
74 |
✓✗✓✗
|
276 |
mHighlightAttackRange(config.getBoolValue("highlightAttackRange")), |
75 |
|
621 |
mSpecialFlag(true) |
76 |
|
|
{ |
77 |
|
|
// std::fill_n(mTiles, mWidth * mHeight, static_cast<Image*>(nullptr)); |
78 |
|
|
|
79 |
✓✗✓✗
|
276 |
config.addListener("highlightAttackRange", this); |
80 |
|
69 |
} |
81 |
|
|
|
82 |
|
345 |
MapLayer::~MapLayer() |
83 |
|
|
{ |
84 |
|
276 |
config.removeListener("highlightAttackRange", this); |
85 |
|
|
CHECKLISTENERS |
86 |
✓✗ |
69 |
delete []mTiles; |
87 |
|
138 |
delete_all(mTempRows); |
88 |
|
138 |
mTempRows.clear(); |
89 |
|
138 |
} |
90 |
|
|
|
91 |
|
|
void MapLayer::optionChanged(const std::string &value) restrict |
92 |
|
|
{ |
93 |
|
|
if (value == "highlightAttackRange") |
94 |
|
|
{ |
95 |
|
|
mHighlightAttackRange = |
96 |
|
|
config.getBoolValue("highlightAttackRange"); |
97 |
|
|
} |
98 |
|
|
} |
99 |
|
|
|
100 |
|
22 |
void MapLayer::draw(Graphics *const graphics, |
101 |
|
|
int startX, |
102 |
|
|
int startY, |
103 |
|
|
int endX, |
104 |
|
|
int endY, |
105 |
|
|
const int scrollX, |
106 |
|
|
const int scrollY) const restrict |
107 |
|
|
{ |
108 |
|
|
BLOCK_START("MapLayer::draw") |
109 |
|
22 |
startX -= mX; |
110 |
|
22 |
startY -= mY; |
111 |
|
22 |
endX -= mX; |
112 |
|
22 |
endY -= mY; |
113 |
|
|
|
114 |
✗✓ |
22 |
if (startX < 0) |
115 |
|
|
startX = 0; |
116 |
✗✓ |
22 |
if (startY < 0) |
117 |
|
|
startY = 0; |
118 |
✗✓ |
22 |
if (endX > mWidth) |
119 |
|
|
endX = mWidth; |
120 |
✗✓ |
22 |
if (endY > mHeight) |
121 |
|
|
endY = mHeight; |
122 |
|
|
|
123 |
|
22 |
const int dx = mPixelX - scrollX; |
124 |
|
22 |
const int dy = mPixelY - scrollY; |
125 |
✓✓ |
440 |
for (int y = startY; y < endY; y++) |
126 |
|
|
{ |
127 |
|
418 |
const int y32 = y * mapTileSize; |
128 |
|
418 |
const int yWidth = y * mWidth; |
129 |
|
|
|
130 |
|
418 |
const int py0 = y32 + dy; |
131 |
|
|
|
132 |
|
418 |
int x0 = startX; |
133 |
|
418 |
TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)]; |
134 |
✓✓ |
418 |
if (tilePtr->isEnabled == false) |
135 |
|
|
{ |
136 |
✓✓ |
402 |
if (x0 + tilePtr->nextTile + 1 >= endX) |
137 |
|
|
{ |
138 |
|
|
continue; |
139 |
|
|
} |
140 |
|
6 |
x0 += tilePtr->nextTile + 1; |
141 |
|
6 |
tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)]; |
142 |
✓✗ |
6 |
if (mTiles[x0 + yWidth].isEnabled == false) |
143 |
|
|
{ |
144 |
|
|
continue; |
145 |
|
|
} |
146 |
|
|
} |
147 |
✓✓ |
102 |
for (int x = x0; x < endX; x++, tilePtr++) |
148 |
|
|
{ |
149 |
|
40 |
const int x32 = x * mapTileSize; |
150 |
|
|
|
151 |
|
40 |
const Image *const img = tilePtr->image; |
152 |
|
40 |
const int px = x32 + dx; |
153 |
|
40 |
const int py = py0 - img->mBounds.h; |
154 |
✗✓✗✗
|
40 |
if (mSpecialFlag || |
155 |
|
|
img->mBounds.h <= mapTileSize) |
156 |
|
|
{ |
157 |
✓✓ |
40 |
if (tilePtr->count == 0) |
158 |
|
|
{ |
159 |
|
28 |
graphics->drawImage(img, px, py); |
160 |
|
|
} |
161 |
|
|
else |
162 |
|
|
{ |
163 |
|
12 |
graphics->drawPattern(img, |
164 |
|
|
px, |
165 |
|
|
py, |
166 |
|
|
tilePtr->width, |
167 |
|
24 |
img->mBounds.h); |
168 |
|
|
} |
169 |
|
|
} |
170 |
|
|
|
171 |
|
40 |
const int nextTile = tilePtr->nextTile; |
172 |
|
40 |
x += nextTile; |
173 |
|
40 |
tilePtr += nextTile; |
174 |
|
|
} |
175 |
|
|
} |
176 |
|
|
BLOCK_END("MapLayer::draw") |
177 |
|
22 |
} |
178 |
|
|
|
179 |
|
|
void MapLayer::drawSDL(Graphics *const graphics) const restrict2 |
180 |
|
|
{ |
181 |
|
|
BLOCK_START("MapLayer::drawSDL") |
182 |
|
|
MapRows::const_iterator rit = mTempRows.begin(); |
183 |
|
|
const MapRows::const_iterator rit_end = mTempRows.end(); |
184 |
|
|
while (rit != rit_end) |
185 |
|
|
{ |
186 |
|
|
MapRowImages *const images = &(*rit)->images; |
187 |
|
|
MapRowImages::const_iterator iit = images->begin(); |
188 |
|
|
const MapRowImages::const_iterator iit_end = images->end(); |
189 |
|
|
while (iit != iit_end) |
190 |
|
|
{ |
191 |
|
|
graphics->drawTileVertexes(*iit); |
192 |
|
|
++ iit; |
193 |
|
|
} |
194 |
|
|
++ rit; |
195 |
|
|
} |
196 |
|
|
BLOCK_END("MapLayer::drawSDL") |
197 |
|
|
} |
198 |
|
|
|
199 |
|
|
#ifdef USE_OPENGL |
200 |
|
|
void MapLayer::updateSDL(const Graphics *const graphics, |
201 |
|
|
int startX, |
202 |
|
|
int startY, |
203 |
|
|
int endX, |
204 |
|
|
int endY, |
205 |
|
|
const int scrollX, |
206 |
|
|
const int scrollY) restrict2 |
207 |
|
|
{ |
208 |
|
|
BLOCK_START("MapLayer::updateSDL") |
209 |
|
|
delete_all(mTempRows); |
210 |
|
|
mTempRows.clear(); |
211 |
|
|
|
212 |
|
|
startX -= mX; |
213 |
|
|
startY -= mY; |
214 |
|
|
endX -= mX; |
215 |
|
|
endY -= mY; |
216 |
|
|
|
217 |
|
|
if (startX < 0) |
218 |
|
|
startX = 0; |
219 |
|
|
if (startY < 0) |
220 |
|
|
startY = 0; |
221 |
|
|
if (endX > mWidth) |
222 |
|
|
endX = mWidth; |
223 |
|
|
if (endY > mHeight) |
224 |
|
|
endY = mHeight; |
225 |
|
|
|
226 |
|
|
const int dx = mPixelX - scrollX; |
227 |
|
|
const int dy = mPixelY - scrollY; |
228 |
|
|
|
229 |
|
|
for (int y = startY; y < endY; y++) |
230 |
|
|
{ |
231 |
|
|
MapRowVertexes *const row = new MapRowVertexes; |
232 |
|
|
mTempRows.push_back(row); |
233 |
|
|
|
234 |
|
|
const Image *lastImage = nullptr; |
235 |
|
|
ImageVertexes *imgVert = nullptr; |
236 |
|
|
|
237 |
|
|
const int yWidth = y * mWidth; |
238 |
|
|
const int py0 = y * mapTileSize + dy; |
239 |
|
|
TileInfo *tilePtr = &mTiles[CAST_SIZE(startX + yWidth)]; |
240 |
|
|
|
241 |
|
|
for (int x = startX; x < endX; x++, tilePtr++) |
242 |
|
|
{ |
243 |
|
|
if (!tilePtr->isEnabled) |
244 |
|
|
continue; |
245 |
|
|
Image *const img = (*tilePtr).image; |
246 |
|
|
const int px = x * mapTileSize + dx; |
247 |
|
|
const int py = py0 - img->mBounds.h; |
248 |
|
|
if (mSpecialFlag || |
249 |
|
|
img->mBounds.h <= mapTileSize) |
250 |
|
|
{ |
251 |
|
|
if (lastImage != img) |
252 |
|
|
{ |
253 |
|
|
imgVert = new ImageVertexes; |
254 |
|
|
imgVert->image = img; |
255 |
|
|
row->images.push_back(imgVert); |
256 |
|
|
lastImage = img; |
257 |
|
|
} |
258 |
|
|
graphics->calcTileSDL(imgVert, px, py); |
259 |
|
|
} |
260 |
|
|
} |
261 |
|
|
} |
262 |
|
|
BLOCK_END("MapLayer::updateSDL") |
263 |
|
|
} |
264 |
|
|
|
265 |
|
|
void MapLayer::updateOGL(Graphics *const graphics, |
266 |
|
|
int startX, |
267 |
|
|
int startY, |
268 |
|
|
int endX, |
269 |
|
|
int endY, |
270 |
|
|
const int scrollX, |
271 |
|
|
const int scrollY) restrict2 |
272 |
|
|
{ |
273 |
|
|
BLOCK_START("MapLayer::updateOGL") |
274 |
|
|
delete_all(mTempRows); |
275 |
|
|
mTempRows.clear(); |
276 |
|
|
|
277 |
|
|
startX -= mX; |
278 |
|
|
startY -= mY; |
279 |
|
|
endX -= mX; |
280 |
|
|
endY -= mY; |
281 |
|
|
|
282 |
|
|
if (startX < 0) |
283 |
|
|
startX = 0; |
284 |
|
|
if (startY < 0) |
285 |
|
|
startY = 0; |
286 |
|
|
if (endX > mWidth) |
287 |
|
|
endX = mWidth; |
288 |
|
|
if (endY > mHeight) |
289 |
|
|
endY = mHeight; |
290 |
|
|
|
291 |
|
|
const int dx = mPixelX - scrollX; |
292 |
|
|
const int dy = mPixelY - scrollY; |
293 |
|
|
|
294 |
|
|
MapRowVertexes *const row = new MapRowVertexes; |
295 |
|
|
mTempRows.push_back(row); |
296 |
|
|
Image *lastImage = nullptr; |
297 |
|
|
ImageVertexes *imgVert = nullptr; |
298 |
|
|
typedef std::map<int, ImageVertexes*> ImageVertexesMap; |
299 |
|
|
ImageVertexesMap imgSet; |
300 |
|
|
|
301 |
|
|
for (int y = startY; y < endY; y++) |
302 |
|
|
{ |
303 |
|
|
const int yWidth = y * mWidth; |
304 |
|
|
const int py0 = y * mapTileSize + dy; |
305 |
|
|
TileInfo *tilePtr = &mTiles[CAST_SIZE(startX + yWidth)]; |
306 |
|
|
for (int x = startX; x < endX; x++, tilePtr++) |
307 |
|
|
{ |
308 |
|
|
if (!tilePtr->isEnabled) |
309 |
|
|
continue; |
310 |
|
|
Image *const img = (*tilePtr).image; |
311 |
|
|
const int px = x * mapTileSize + dx; |
312 |
|
|
const int py = py0 - img->mBounds.h; |
313 |
|
|
const GLuint imgGlImage = img->mGLImage; |
314 |
|
|
if (mSpecialFlag || |
315 |
|
|
img->mBounds.h <= mapTileSize) |
316 |
|
|
{ |
317 |
|
|
if ((lastImage == nullptr) || |
318 |
|
|
lastImage->mGLImage != imgGlImage) |
319 |
|
|
{ |
320 |
|
|
if (img->mBounds.w > mapTileSize) |
321 |
|
|
imgSet.clear(); |
322 |
|
|
|
323 |
|
|
if (imgSet.find(imgGlImage) != imgSet.end()) |
324 |
|
|
{ |
325 |
|
|
imgVert = imgSet[imgGlImage]; |
326 |
|
|
} |
327 |
|
|
else |
328 |
|
|
{ |
329 |
|
|
if (lastImage != nullptr) |
330 |
|
|
imgSet[lastImage->mGLImage] = imgVert; |
331 |
|
|
imgVert = new ImageVertexes; |
332 |
|
|
imgVert->ogl.init(); |
333 |
|
|
imgVert->image = img; |
334 |
|
|
row->images.push_back(imgVert); |
335 |
|
|
} |
336 |
|
|
} |
337 |
|
|
lastImage = img; |
338 |
|
|
graphics->calcTileVertexes(imgVert, lastImage, px, py); |
339 |
|
|
} |
340 |
|
|
} |
341 |
|
|
} |
342 |
|
|
FOR_EACH (MapRowImages::iterator, it, row->images) |
343 |
|
|
{ |
344 |
|
|
graphics->finalize(*it); |
345 |
|
|
} |
346 |
|
|
BLOCK_END("MapLayer::updateOGL") |
347 |
|
|
} |
348 |
|
|
|
349 |
|
|
void MapLayer::drawOGL(Graphics *const graphics) const restrict2 |
350 |
|
|
{ |
351 |
|
|
BLOCK_START("MapLayer::drawOGL") |
352 |
|
|
MapRows::const_iterator rit = mTempRows.begin(); |
353 |
|
|
const MapRows::const_iterator rit_end = mTempRows.end(); |
354 |
|
|
while (rit != rit_end) |
355 |
|
|
{ |
356 |
|
|
const MapRowImages *const images = &(*rit)->images; |
357 |
|
|
MapRowImages::const_iterator iit = images->begin(); |
358 |
|
|
const MapRowImages::const_iterator iit_end = images->end(); |
359 |
|
|
while (iit != iit_end) |
360 |
|
|
{ |
361 |
|
|
graphics->drawTileVertexes(*iit); |
362 |
|
|
++ iit; |
363 |
|
|
} |
364 |
|
|
++ rit; |
365 |
|
|
} |
366 |
|
|
BLOCK_END("MapLayer::drawOGL") |
367 |
|
|
} |
368 |
|
|
#endif // USE_OPENGL |
369 |
|
|
|
370 |
|
892 |
void MapLayer::drawSpecialLayer(Graphics *const graphics, |
371 |
|
|
const int y, |
372 |
|
|
const int startX, |
373 |
|
|
const int endX, |
374 |
|
|
const int scrollX, |
375 |
|
|
const int scrollY) const restrict |
376 |
|
|
{ |
377 |
|
892 |
const int y32 = y * mapTileSize; |
378 |
|
892 |
const int py1 = y32 - scrollY; |
379 |
|
892 |
int endX1 = endX; |
380 |
|
892 |
int specialWidth = mSpecialLayer->mWidth; |
381 |
|
892 |
int ptr = y * specialWidth; |
382 |
✗✓ |
892 |
if (endX1 > specialWidth) |
383 |
|
|
endX1 = specialWidth; |
384 |
✗✓ |
892 |
if (endX1 < 0) |
385 |
|
|
endX1 = 0; |
386 |
|
892 |
int x0 = startX; |
387 |
|
892 |
const MapItem *item0 = mSpecialLayer->mTiles[ptr + startX]; |
388 |
✓✓✗✓
|
892 |
if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY) |
389 |
|
|
{ |
390 |
|
881 |
x0 += mSpecialLayer->mCache[ptr + startX] + 1; |
391 |
|
|
} |
392 |
✓✓ |
944 |
for (int x = x0; x < endX1; x++) |
393 |
|
|
{ |
394 |
|
26 |
const int px1 = x * mapTileSize - scrollX; |
395 |
|
26 |
const MapItem *const item = mSpecialLayer->mTiles[ptr + x]; |
396 |
✓✗ |
26 |
if (item != nullptr) |
397 |
|
|
{ |
398 |
|
|
item->draw(graphics, px1, py1, |
399 |
|
26 |
mapTileSize, mapTileSize); |
400 |
|
|
} |
401 |
|
26 |
x += mSpecialLayer->mCache[ptr + x]; |
402 |
|
|
} |
403 |
|
|
|
404 |
|
892 |
x0 = startX; |
405 |
|
892 |
specialWidth = mTempLayer->mWidth; |
406 |
|
892 |
ptr = y * specialWidth; |
407 |
|
892 |
endX1 = endX; |
408 |
✗✓ |
892 |
if (endX1 > specialWidth) |
409 |
|
|
endX1 = specialWidth; |
410 |
|
892 |
item0 = mTempLayer->mTiles[ptr + startX]; |
411 |
✓✓✗✓
|
892 |
if ((item0 == nullptr) || item0->mType == MapItemType::EMPTY) |
412 |
|
|
{ |
413 |
|
885 |
x0 += mTempLayer->mCache[ptr + startX] + 1; |
414 |
|
|
} |
415 |
✓✓ |
928 |
for (int x = x0; x < endX1; x++) |
416 |
|
|
{ |
417 |
|
18 |
const int px1 = x * mapTileSize - scrollX; |
418 |
|
18 |
const MapItem *const item = mTempLayer->mTiles[ptr + x]; |
419 |
|
|
item->draw(graphics, px1, py1, |
420 |
|
18 |
mapTileSize, mapTileSize); |
421 |
|
18 |
x += mTempLayer->mCache[ptr + x]; |
422 |
|
|
} |
423 |
|
892 |
} |
424 |
|
|
|
425 |
|
26 |
void MapLayer::drawFringe(Graphics *const graphics, |
426 |
|
|
int startX, |
427 |
|
|
int startY, |
428 |
|
|
int endX, |
429 |
|
|
int endY, |
430 |
|
|
const int scrollX, |
431 |
|
|
const int scrollY, |
432 |
|
|
const Actors &actors) const restrict |
433 |
|
|
{ |
434 |
|
|
BLOCK_START("MapLayer::drawFringe") |
435 |
✓✗✓✗
|
52 |
if ((localPlayer == nullptr) || |
436 |
✓✗ |
52 |
(mSpecialLayer == nullptr) || |
437 |
|
26 |
(mTempLayer == nullptr)) |
438 |
|
|
{ |
439 |
|
|
BLOCK_END("MapLayer::drawFringe") |
440 |
|
|
return; |
441 |
|
|
} |
442 |
|
|
|
443 |
|
26 |
startX -= mX; |
444 |
|
26 |
startY -= mY; |
445 |
|
26 |
endX -= mX; |
446 |
|
26 |
endY -= mY; |
447 |
|
|
|
448 |
✗✓ |
26 |
if (startX < 0) |
449 |
|
|
startX = 0; |
450 |
✗✓ |
26 |
if (startY < 0) |
451 |
|
|
startY = 0; |
452 |
✗✓ |
26 |
if (endX > mWidth) |
453 |
|
|
endX = mWidth; |
454 |
✗✓ |
26 |
if (endY > mHeight) |
455 |
|
|
endY = mHeight; |
456 |
|
|
|
457 |
|
52 |
ActorsCIter ai = actors.begin(); |
458 |
|
26 |
const ActorsCIter ai_end = actors.end(); |
459 |
|
|
|
460 |
|
26 |
const int dx = mPixelX - scrollX; |
461 |
|
26 |
const int dy = mPixelY - scrollY; |
462 |
|
|
|
463 |
|
26 |
const int specialHeight = mSpecialLayer->mHeight; |
464 |
|
|
|
465 |
|
26 |
const bool flag = mDrawLayerFlags == MapType::SPECIAL3 || |
466 |
|
26 |
mDrawLayerFlags == MapType::SPECIAL4 || |
467 |
|
26 |
mDrawLayerFlags == MapType::BLACKWHITE; |
468 |
|
|
|
469 |
|
26 |
const int minEndY = std::min(specialHeight, endY); |
470 |
|
|
|
471 |
✓✗ |
26 |
if (flag) |
472 |
|
|
{ // flag |
473 |
|
|
for (int y = startY; y < minEndY; y ++) |
474 |
|
|
{ |
475 |
|
|
const int y32s = (y + mActorsFix) * mapTileSize; |
476 |
|
|
|
477 |
|
|
BLOCK_START("MapLayer::drawFringe drawmobs") |
478 |
|
|
// If drawing the fringe layer, make sure all actors above this |
479 |
|
|
// row of tiles have been drawn |
480 |
|
|
while (ai != ai_end && (*ai)->getSortPixelY() <= y32s) |
481 |
|
|
{ |
482 |
|
|
(*ai)->draw(graphics, -scrollX, -scrollY); |
483 |
|
|
++ ai; |
484 |
|
|
} |
485 |
|
|
BLOCK_END("MapLayer::drawFringe drawmobs") |
486 |
|
|
|
487 |
|
|
// remove this condition, because it always true |
488 |
|
|
if (y < specialHeight) |
489 |
|
|
{ |
490 |
|
|
drawSpecialLayer(graphics, |
491 |
|
|
y, |
492 |
|
|
startX, |
493 |
|
|
endX, |
494 |
|
|
scrollX, |
495 |
|
|
scrollY); |
496 |
|
|
} |
497 |
|
|
} |
498 |
|
|
|
499 |
|
|
for (int y = minEndY; y < endY; y++) |
500 |
|
|
{ |
501 |
|
|
const int y32s = (y + mActorsFix) * mapTileSize; |
502 |
|
|
|
503 |
|
|
BLOCK_START("MapLayer::drawFringe drawmobs") |
504 |
|
|
// If drawing the fringe layer, make sure all actors above this |
505 |
|
|
// row of tiles have been drawn |
506 |
|
|
while (ai != ai_end && (*ai)->getSortPixelY() <= y32s) |
507 |
|
|
{ |
508 |
|
|
(*ai)->draw(graphics, -scrollX, -scrollY); |
509 |
|
|
++ ai; |
510 |
|
|
} |
511 |
|
|
BLOCK_END("MapLayer::drawFringe drawmobs") |
512 |
|
|
} |
513 |
|
|
} |
514 |
|
|
else |
515 |
|
|
{ // !flag |
516 |
✓✓ |
1662 |
for (int y = startY; y < minEndY; y ++) |
517 |
|
|
{ |
518 |
|
818 |
const int y32 = y * mapTileSize; |
519 |
|
818 |
const int y32s = (y + mActorsFix) * mapTileSize; |
520 |
|
818 |
const int yWidth = y * mWidth; |
521 |
|
|
|
522 |
|
|
BLOCK_START("MapLayer::drawFringe drawmobs") |
523 |
|
|
// If drawing the fringe layer, make sure all actors above this |
524 |
|
|
// row of tiles have been drawn |
525 |
✗✓✗✗ ✗✓ |
818 |
while (ai != ai_end && |
526 |
|
|
(*ai)->getSortPixelY() <= y32s) |
527 |
|
|
{ |
528 |
|
|
(*ai)->draw(graphics, -scrollX, -scrollY); |
529 |
|
|
++ ai; |
530 |
|
|
} |
531 |
|
|
BLOCK_END("MapLayer::drawFringe drawmobs") |
532 |
|
|
|
533 |
|
818 |
const int py0 = y32 + dy; |
534 |
|
|
|
535 |
|
818 |
int x0 = startX; |
536 |
|
818 |
TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)]; |
537 |
✓✓ |
818 |
if (tilePtr->isEnabled == false) |
538 |
|
|
{ |
539 |
|
802 |
drawSpecialLayer(graphics, |
540 |
|
|
y, |
541 |
|
|
0, |
542 |
|
2406 |
std::min(x0 + tilePtr->nextTile + 1, endX), |
543 |
|
|
scrollX, |
544 |
|
802 |
scrollY); |
545 |
✓✓ |
802 |
if (x0 + tilePtr->nextTile + 1 >= endX) |
546 |
|
|
{ |
547 |
|
|
continue; |
548 |
|
|
} |
549 |
|
10 |
x0 += tilePtr->nextTile + 1; |
550 |
|
10 |
tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)]; |
551 |
✓✗ |
10 |
if (mTiles[x0 + yWidth].isEnabled == false) |
552 |
|
|
continue; |
553 |
|
|
} |
554 |
✓✓ |
154 |
for (int x = x0; x < endX; x++, tilePtr++) |
555 |
|
|
{ |
556 |
|
64 |
const int x32 = x * mapTileSize; |
557 |
|
64 |
const Image *const img = tilePtr->image; |
558 |
✗✓✗✗
|
64 |
if (mSpecialFlag || |
559 |
|
|
img->mBounds.h <= mapTileSize) |
560 |
|
|
{ |
561 |
|
64 |
const int px = x32 + dx; |
562 |
|
64 |
const int py = py0 - img->mBounds.h; |
563 |
|
|
|
564 |
✓✓ |
64 |
if (tilePtr->count == 0) |
565 |
|
|
{ |
566 |
|
40 |
graphics->drawImage(img, px, py); |
567 |
|
|
} |
568 |
|
|
else |
569 |
|
|
{ |
570 |
|
24 |
graphics->drawPattern(img, |
571 |
|
|
px, |
572 |
|
|
py, |
573 |
|
|
tilePtr->width, |
574 |
|
48 |
img->mBounds.h); |
575 |
|
|
} |
576 |
|
|
} |
577 |
|
|
|
578 |
|
64 |
const int nextTile = tilePtr->nextTile; |
579 |
|
|
// remove this condition, because it always true |
580 |
✓✗ |
64 |
if (y < specialHeight) |
581 |
|
|
{ |
582 |
|
64 |
drawSpecialLayer(graphics, |
583 |
|
|
y, |
584 |
|
|
x, |
585 |
|
192 |
std::min(x + nextTile + 1, endX), |
586 |
|
|
scrollX, |
587 |
|
64 |
scrollY); |
588 |
|
|
} |
589 |
|
64 |
x += nextTile; |
590 |
|
64 |
tilePtr += nextTile; |
591 |
|
|
} |
592 |
|
|
} |
593 |
|
|
|
594 |
✗✓ |
26 |
for (int y = minEndY; y < endY; y++) |
595 |
|
|
{ |
596 |
|
|
const int y32 = y * mapTileSize; |
597 |
|
|
const int y32s = (y + mActorsFix) * mapTileSize; |
598 |
|
|
const int yWidth = y * mWidth; |
599 |
|
|
|
600 |
|
|
BLOCK_START("MapLayer::drawFringe drawmobs") |
601 |
|
|
// If drawing the fringe layer, make sure all actors above this |
602 |
|
|
// row of tiles have been drawn |
603 |
|
|
while (ai != ai_end && (*ai)->getSortPixelY() <= y32s) |
604 |
|
|
{ |
605 |
|
|
(*ai)->draw(graphics, -scrollX, -scrollY); |
606 |
|
|
++ ai; |
607 |
|
|
} |
608 |
|
|
BLOCK_END("MapLayer::drawFringe drawmobs") |
609 |
|
|
|
610 |
|
|
const int py0 = y32 + dy; |
611 |
|
|
|
612 |
|
|
int x0 = startX; |
613 |
|
|
TileInfo *tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)]; |
614 |
|
|
if (tilePtr->isEnabled == false) |
615 |
|
|
{ |
616 |
|
|
if (x0 + tilePtr->nextTile + 1 >= endX) |
617 |
|
|
continue; |
618 |
|
|
x0 += tilePtr->nextTile + 1; |
619 |
|
|
tilePtr = &mTiles[CAST_SIZE(x0 + yWidth)]; |
620 |
|
|
if (mTiles[x0 + yWidth].isEnabled == false) |
621 |
|
|
continue; |
622 |
|
|
} |
623 |
|
|
for (int x = x0; x < endX; x++, tilePtr++) |
624 |
|
|
{ |
625 |
|
|
const int x32 = x * mapTileSize; |
626 |
|
|
const Image *const img = tilePtr->image; |
627 |
|
|
const int px = x32 + dx; |
628 |
|
|
const int py = py0 - img->mBounds.h; |
629 |
|
|
if (mSpecialFlag || |
630 |
|
|
img->mBounds.h <= mapTileSize) |
631 |
|
|
{ |
632 |
|
|
const int c = tilePtr->count; |
633 |
|
|
|
634 |
|
|
if (c == 0) |
635 |
|
|
{ |
636 |
|
|
graphics->drawImage(img, px, py); |
637 |
|
|
} |
638 |
|
|
else |
639 |
|
|
{ |
640 |
|
|
graphics->drawPattern(img, |
641 |
|
|
px, |
642 |
|
|
py, |
643 |
|
|
tilePtr->width, |
644 |
|
|
img->mBounds.h); |
645 |
|
|
} |
646 |
|
|
} |
647 |
|
|
const int nextTile = tilePtr->nextTile; |
648 |
|
|
x += nextTile; |
649 |
|
|
tilePtr += nextTile; |
650 |
|
|
} |
651 |
|
|
} |
652 |
|
|
} // !flag |
653 |
|
|
|
654 |
|
|
// Draw any remaining actors |
655 |
✓✗ |
26 |
if (mDrawLayerFlags != MapType::SPECIAL3 && |
656 |
|
|
mDrawLayerFlags != MapType::SPECIAL4) |
657 |
|
|
{ |
658 |
|
|
BLOCK_START("MapLayer::drawFringe drawmobs") |
659 |
✗✓ |
26 |
while (ai != ai_end) |
660 |
|
|
{ |
661 |
|
|
(*ai)->draw(graphics, -scrollX, -scrollY); |
662 |
|
|
++ai; |
663 |
|
|
} |
664 |
|
|
BLOCK_END("MapLayer::drawFringe drawmobs") |
665 |
✗✓ |
26 |
if (mHighlightAttackRange) |
666 |
|
|
{ |
667 |
|
|
const int px = localPlayer->getPixelX() |
668 |
|
|
- scrollX - mapTileSize / 2; |
669 |
|
|
const int py = localPlayer->getPixelY() - scrollY - mapTileSize; |
670 |
|
|
const int attackRange = localPlayer->getAttackRange() |
671 |
|
|
* mapTileSize; |
672 |
|
|
|
673 |
|
|
int x = px - attackRange; |
674 |
|
|
int y = py - attackRange; |
675 |
|
|
int w = 2 * attackRange + mapTileSize; |
676 |
|
|
int h = w; |
677 |
|
|
if (attackRange <= mapTileSize) |
678 |
|
|
{ |
679 |
|
|
x -= mapTileSize / 2; |
680 |
|
|
y -= mapTileSize / 2; |
681 |
|
|
w += mapTileSize; |
682 |
|
|
h += mapTileSize; |
683 |
|
|
} |
684 |
|
|
|
685 |
|
|
if (userPalette != nullptr) |
686 |
|
|
{ |
687 |
|
|
graphics->setColor(userPalette->getColorWithAlpha( |
688 |
|
|
UserColorId::ATTACK_RANGE)); |
689 |
|
|
graphics->fillRectangle(Rect(x, y, w, h)); |
690 |
|
|
graphics->setColor(userPalette->getColorWithAlpha( |
691 |
|
|
UserColorId::ATTACK_RANGE_BORDER)); |
692 |
|
|
graphics->drawRectangle(Rect(x, y, w, h)); |
693 |
|
|
} |
694 |
|
|
} |
695 |
|
|
} |
696 |
|
|
BLOCK_END("MapLayer::drawFringe") |
697 |
|
|
} |
698 |
|
|
|
699 |
|
131 |
int MapLayer::getTileDrawWidth(const TileInfo *restrict tilePtr, |
700 |
|
|
const int endX, |
701 |
|
|
int &restrict width, |
702 |
|
|
int &restrict nextTile) |
703 |
|
|
{ |
704 |
|
|
BLOCK_START("MapLayer::getTileDrawWidth") |
705 |
|
131 |
const Image *const img1 = tilePtr->image; |
706 |
|
131 |
int c = 0; |
707 |
|
131 |
width = img1->mBounds.w; |
708 |
✓✓ |
185 |
for (int x = 1; x < endX; x++) |
709 |
|
|
{ |
710 |
|
155 |
tilePtr ++; |
711 |
|
155 |
const Image *const img = tilePtr->image; |
712 |
✓✓✓✓
|
258 |
if (img == nullptr || |
713 |
|
103 |
tilePtr->isEnabled == false) |
714 |
|
|
{ |
715 |
|
|
break; |
716 |
|
|
} |
717 |
✓✓ |
99 |
if (img != img1) |
718 |
|
|
{ |
719 |
|
45 |
nextTile = c; |
720 |
|
|
BLOCK_END("MapLayer::getTileDrawWidth") |
721 |
|
45 |
return c; |
722 |
|
|
} |
723 |
|
54 |
c ++; |
724 |
|
54 |
width += img->mBounds.w; |
725 |
|
|
} |
726 |
|
86 |
int c2 = c; |
727 |
✓✓ |
1789 |
for (int x2 = c2 + 1; x2 < endX; x2++) |
728 |
|
|
{ |
729 |
✓✓✓✓
|
1924 |
if (tilePtr->image != nullptr && |
730 |
|
198 |
tilePtr->isEnabled == true) |
731 |
|
|
{ |
732 |
|
|
break; |
733 |
|
|
} |
734 |
|
1703 |
c2 ++; |
735 |
|
1703 |
tilePtr ++; |
736 |
|
|
} |
737 |
|
86 |
nextTile = c2; |
738 |
|
|
BLOCK_END("MapLayer::getTileDrawWidth") |
739 |
|
86 |
return c; |
740 |
|
|
} |
741 |
|
|
|
742 |
|
10 |
int MapLayer::getEmptyTileDrawWidth(const TileInfo *restrict tilePtr, |
743 |
|
|
const int endX, |
744 |
|
|
int &restrict nextTile) |
745 |
|
|
{ |
746 |
|
|
BLOCK_START("MapLayer::getEmptyTileDrawWidth") |
747 |
|
79964 |
int c = 0; |
748 |
✓✓✓✓
|
4024412 |
for (int x = 1; x < endX; x++) |
749 |
|
|
{ |
750 |
|
3944620 |
tilePtr ++; |
751 |
|
3944620 |
const Image *const img = tilePtr->image; |
752 |
✓✓✓✓ ✓✓✗✓
|
3944620 |
if (img != nullptr && tilePtr->isEnabled == true) |
753 |
|
|
break; |
754 |
|
3944448 |
c ++; |
755 |
|
|
} |
756 |
|
|
BLOCK_END("MapLayer::getEmptyTileDrawWidth") |
757 |
|
|
|
758 |
|
79964 |
nextTile = c; |
759 |
|
10 |
return c; |
760 |
|
|
} |
761 |
|
|
|
762 |
|
6 |
void MapLayer::updateConditionTiles(const MetaTile *const metaTiles, |
763 |
|
|
const int width, |
764 |
|
|
const int height) restrict |
765 |
|
|
{ |
766 |
✓✗ |
6 |
const int width1 = width < mWidth ? width : mWidth; |
767 |
✓✗ |
6 |
const int height1 = height < mHeight ? height : mHeight; |
768 |
|
|
|
769 |
✓✓ |
808 |
for (int y = mY; y < height1; y ++) |
770 |
|
|
{ |
771 |
|
802 |
const MetaTile *metaPtr = metaTiles + (y - mY) * width; |
772 |
|
802 |
TileInfo *tilePtr = mTiles + y * mWidth; |
773 |
✓✓ |
80804 |
for (int x = mX; x < width1; x ++, metaPtr ++, tilePtr ++) |
774 |
|
|
{ |
775 |
✓✓✓✓
|
100012 |
if (tilePtr->image != nullptr && |
776 |
✓✗ |
40013 |
(((metaPtr->blockmask & mTileCondition) != 0) || |
777 |
✗✓ |
20003 |
(metaPtr->blockmask == 0 && |
778 |
|
|
mTileCondition == BlockMask::GROUND))) |
779 |
|
|
{ |
780 |
|
7 |
tilePtr->isEnabled = true; |
781 |
|
|
} |
782 |
|
|
else |
783 |
|
|
{ |
784 |
|
79995 |
tilePtr->isEnabled = false; |
785 |
|
|
} |
786 |
|
|
} |
787 |
|
|
} |
788 |
|
6 |
} |
789 |
|
|
|
790 |
|
32 |
void MapLayer::updateCache(const int width, |
791 |
|
|
const int height) restrict |
792 |
|
|
{ |
793 |
✓✗ |
32 |
const int width1 = width < mWidth ? width : mWidth; |
794 |
✓✗ |
32 |
const int height1 = height < mHeight ? height : mHeight; |
795 |
|
|
|
796 |
✓✓ |
856 |
for (int y = mY; y < height1; y ++) |
797 |
|
|
{ |
798 |
✓✓ |
80881 |
for (int x = mX; x < width1; x ++) |
799 |
|
|
{ |
800 |
|
80057 |
TileInfo *tilePtr = mTiles + y * mWidth + x; |
801 |
|
80057 |
int nextTile = 0; |
802 |
✓✓✓✓
|
80057 |
if (tilePtr->image == nullptr || tilePtr->isEnabled == false) |
803 |
|
|
{ |
804 |
|
79954 |
tilePtr->isEnabled = false; |
805 |
|
159908 |
tilePtr->count = getEmptyTileDrawWidth(tilePtr, |
806 |
|
|
width1 - x, |
807 |
|
|
nextTile); |
808 |
|
79954 |
tilePtr->width = 0; |
809 |
|
|
} |
810 |
|
|
else |
811 |
|
|
{ |
812 |
|
103 |
int tileWidth = 0; |
813 |
|
103 |
tilePtr->count = getTileDrawWidth(tilePtr, |
814 |
|
|
width1 - x, |
815 |
|
|
tileWidth, |
816 |
|
|
nextTile); |
817 |
|
103 |
tilePtr->width = tileWidth; |
818 |
|
|
} |
819 |
|
80057 |
tilePtr->nextTile = nextTile; |
820 |
|
|
} |
821 |
|
|
} |
822 |
|
32 |
} |
823 |
|
|
|
824 |
|
|
int MapLayer::calcMemoryLocal() const |
825 |
|
|
{ |
826 |
|
|
return static_cast<int>(sizeof(MapLayer) + |
827 |
|
|
sizeof(TileInfo) * mWidth * mHeight + |
828 |
|
|
sizeof(MapRowVertexes) * mTempRows.capacity()); |
829 |
|
|
} |
830 |
|
|
|
831 |
|
|
int MapLayer::calcMemoryChilds(const int level) const |
832 |
|
|
{ |
833 |
|
|
int sz = 0; |
834 |
|
|
if (mSpecialLayer != nullptr) |
835 |
|
|
sz += mSpecialLayer->calcMemory(level + 1); |
836 |
|
|
if (mTempLayer != nullptr) |
837 |
|
|
sz += mTempLayer->calcMemory(level + 1); |
838 |
|
|
return sz; |
839 |
|
2 |
} |