24 #include "resources/map/map.h"
27 #include "render/graphics.h"
73 #include "utils/timer.h"
88 bool operator()(const
Actor *const a,
89 const
Actor *const b)
const
91 if ((a ==
nullptr) || (b ==
nullptr))
93 return a->getSortPixelY() < b->getSortPixelY();
101 const int tileHeight) :
103 mWidth(width), mHeight(height),
104 mTileWidth(tileWidth), mTileHeight(tileHeight),
105 mMaxTileHeight(height),
125 mOverlayDetail(
config.getIntValue(
"OverlayDetail")),
126 mOpacity(
config.getFloatValue(
"guialpha")),
133 mTilesetsIndexed(false),
135 mIndexedTilesetsSize(0),
157 mBeingOpacity(false),
167 mDrawOnlyFringe(false),
213 if (value ==
"OverlayDetail")
217 else if (value ==
"guialpha")
220 if (mOpacity != 1.0F)
223 mBeingOpacity =
false;
225 else if (value ==
"beingopacity")
227 if (mOpacity != 1.0F)
230 mBeingOpacity =
false;
237 for (
int i = 0; ; i++)
245 else if (
hasProperty(std::string(
"overlay").append(
259 int mask = atoi(
getProperty(name +
"mask", std::string()).c_str());
281 for (
int i = 0;
hasProperty(std::string(
"background").append(
282 toString(i)).append(
"image")); i ++)
284 const std::string name(
"background" +
toString(i));
290 int mask = atoi(
getProperty(name +
"mask", std::string()).c_str());
315 mLayers.push_back(layer);
316 if (layer->isFringeLayer() && (mFringeLayer ==
nullptr))
317 mFringeLayer = layer;
322 mTilesets.push_back(tileset);
323 const int height = tileset->getHeight();
324 if (height > mMaxTileHeight)
325 mMaxTileHeight = height;
334 if ((tileAni !=
nullptr) && tileAni->update(ticks))
350 const int endPixelY = graphics->mHeight + scrollY + mTileHeight - 1
351 + mMaxTileHeight - mTileHeight;
352 const int startX = scrollX / mTileWidth - 2;
353 const int startY = scrollY / mTileHeight;
354 const int endX = (graphics->mWidth + scrollX + mTileWidth - 1)
356 const int endY = endPixelY / mTileHeight + 1;
365 updateAmbientLayers(
static_cast<float>(scrollX),
366 static_cast<float>(scrollY));
369 drawAmbientLayers(graphics,
378 graphics->fillRectangle(
Rect(0, 0,
379 graphics->mWidth, graphics->mHeight));
387 if (mLastX != startX || mLastY != startY || mLastScrollX != scrollX
388 || mLastScrollY != scrollY)
392 mLastScrollX = scrollX;
393 mLastScrollY = scrollY;
396 else if (mRedrawMap || startX != mDrawX || startY != mDrawY ||
397 scrollX != mDrawScrollX || scrollY != mDrawScrollY)
402 mDrawScrollX = scrollX;
403 mDrawScrollY = scrollY;
411 if (mFringeLayer !=
nullptr)
413 mFringeLayer->setSpecialLayer(mSpecialLayer);
414 mFringeLayer->setTempLayer(mTempLayer);
415 mFringeLayer->drawFringe(graphics,
429 FOR_EACH (Layers::iterator, it, mDrawUnderLayers)
431 (*it)->updateOGL(graphics,
436 FOR_EACH (Layers::iterator, it, mDrawOverLayers)
438 (*it)->updateOGL(graphics,
445 FOR_EACH (Layers::iterator, it, mDrawUnderLayers)
446 (*it)->drawOGL(graphics);
448 if (mFringeLayer !=
nullptr)
450 mFringeLayer->setSpecialLayer(mSpecialLayer);
451 mFringeLayer->setTempLayer(mTempLayer);
452 mFringeLayer->drawFringe(graphics,
459 FOR_EACH (Layers::iterator, it, mDrawOverLayers)
460 (*it)->drawOGL(graphics);
465 FOR_EACH (Layers::iterator, it, mDrawUnderLayers)
467 (*it)->draw(graphics,
473 if (mFringeLayer !=
nullptr)
475 mFringeLayer->setSpecialLayer(mSpecialLayer);
476 mFringeLayer->setTempLayer(mTempLayer);
477 mFringeLayer->drawFringe(graphics,
484 FOR_EACH (Layers::iterator, it, mDrawOverLayers)
486 (*it)->draw(graphics, startX, startY,
507 const int x = actor->getTileX();
508 const int y = actor->getTileY();
509 if (x < startX || x > endX || y < startY || y > endY)
515 if (actor->getNumberOfLayers() == 1)
517 actor->setAlpha(0.3F);
518 actor->draw(graphics, -scrollX, -scrollY);
519 actor->setAlpha(1.0F);
529 if (
Actor *
const actor = *ai)
531 actor->setAlpha(0.3F);
532 actor->draw(graphics, -scrollX, -scrollY);
533 actor->setAlpha(1.0F);
540 drawAmbientLayers(graphics,
546 #define fillCollision(collision, color) \
547 if (x < endX && mMetaTiles[tilePtr].blockmask & (collision))\
549 width = mapTileSize;\
550 for (int x2 = tilePtr + 1; x < endX; x2 ++)\
552 if (!(mMetaTiles[x2].blockmask & (collision)))\
554 width += mapTileSize;\
558 if (width && userPalette)\
560 graphics->setColor(userPalette->getColorWithAlpha(\
561 UserColorId::color));\
562 graphics->fillRectangle(Rect(\
563 x0 * mTileWidth - scrollX, \
564 y * mTileHeight - scrollY, \
565 width, mapTileSize));\
574 const int endPixelY = graphics->mHeight + scrollY + mTileHeight - 1;
575 int startX = scrollX / mTileWidth;
576 int startY = scrollY / mTileHeight;
577 int endX = (graphics->mWidth + scrollX + mTileWidth - 1) / mTileWidth;
578 int endY = endPixelY / mTileHeight;
593 startX * mTileWidth - scrollX,
594 startY * mTileHeight - scrollY,
595 endX * mTileWidth - scrollX,
596 endY * mTileHeight - scrollY,
600 for (
int y = startY;
y < endY;
y++)
602 const int yWidth =
y * mWidth;
603 int tilePtr = startX + yWidth;
604 for (
int x = startX;
x < endX;
x++, tilePtr++)
625 if (mLastAScrollX == 0.0F && mLastAScrollY == 0.0F)
628 mLastAScrollX = scrollX;
629 mLastAScrollY = scrollY;
633 const float dx = scrollX - mLastAScrollX;
634 const float dy = scrollY - mLastAScrollY;
642 if ((layer !=
nullptr) && ((layer->
mMask & mMask) != 0))
643 layer->
update(timePassed, dx, dy);
649 if ((layer !=
nullptr) && ((layer->
mMask & mMask) != 0))
650 layer->
update(timePassed, dx, dy);
653 mLastAScrollX = scrollX;
654 mLastAScrollY = scrollY;
676 layers = &mForegrounds;
679 layers = &mBackgrounds;
690 if ((layer !=
nullptr) && ((layer->mMask & mMask) != 0))
691 (layer)->draw(graphics, graphics->mWidth, graphics->mHeight);
702 if (gid >= 0 && gid < mIndexedTilesetsSize)
703 return mIndexedTilesets[gid];
713 const int tileNum =
x +
y * mWidth;
752 const int tileNum =
x +
y * mWidth;
789 if (
x < 0 || y < 0 || x >= mWidth ||
y >= mHeight)
800 if (
x < 0 || y < 0 || x >= mWidth ||
y >= mHeight)
804 return mMetaTiles[
x +
y * mWidth].blockmask;
814 return x >= 0 &&
y >= 0 &&
x < mWidth &&
y < mHeight;
819 return &mMetaTiles[
x +
y * mWidth];
824 mActors.push_front(actor);
826 return mActors.begin();
831 mActors.erase(iterator);
851 const size_t lastSlash =
fileName.rfind(
'/') + 1;
860 fileName.rfind(
'.') - lastSlash).append(
".gat");
864 const int destX,
const int destY,
870 static const int basicCost = 100;
871 const int basicCost2 = 100 * 362 / 256;
872 const float basicCostF = 100.0 * 362 / 256;
877 if (startX >= mWidth || startY >= mHeight || startX < 0 || startY < 0)
891 MetaTile *
const startTile = &mMetaTiles[startX + startY * mWidth];
892 if (startTile ==
nullptr)
898 startTile->
Gcost = 0;
901 std::priority_queue<Location> openList;
904 openList.push(
Location(startX, startY, startTile));
906 bool foundPath =
false;
909 while (!openList.empty() && !foundPath)
912 const Location curr = openList.top();
925 const int curWidth = curr.
y * mWidth;
926 const int tileGcost = tile->
Gcost;
929 for (
int dy = -1; dy <= 1; dy++)
931 const int y = curr.
y + dy;
932 if (y < 0 || y >= mHeight)
935 const int yWidth =
y * mWidth;
936 const int dy1 = std::abs(
y - destY);
938 for (
int dx = -1; dx <= 1; dx++)
941 const int x = curr.
x + dx;
945 if ((dx == 0 && dy == 0) || x < 0 || x >= mWidth)
948 MetaTile *
const newTile = &mMetaTiles[
x + yWidth];
955 if (newTile->
whichList == mOnClosedList ||
957 && !(
x == destX &&
y == destY))
965 if (dx != 0 && dy != 0)
967 const MetaTile *
const t1 = &mMetaTiles[curr.
x +
968 (curr.
y + dy) * mWidth];
969 const MetaTile *
const t2 = &mMetaTiles[curr.
x +
978 int Gcost = tileGcost + (dx == 0 || dy == 0
979 ? basicCost : basicCost2);
986 if (dx == 0 || dy == 0)
1004 if (maxCost > 0 && Gcost > maxCost * basicCost)
1015 const int dx1 = std::abs(
x - destX);
1016 newTile->
Hcost = std::abs(dx1 - dy1) * basicCost +
1017 CAST_S32(
static_cast<float>(std::min(dx1, dy1)) *
1025 newTile->
Gcost = Gcost;
1028 if (
x != destX ||
y != destY)
1040 else if (Gcost < newTile->Gcost)
1044 newTile->
Gcost = Gcost;
1061 if (mOnOpenList > UINT_MAX - 2)
1068 const int size = mWidth * mHeight;
1069 for (
int i = 0; i <
size; ++i)
1070 mMetaTiles[i].whichList = 0;
1085 while (pathX != startX || pathY != startY)
1088 path.push_front(
Position(pathX, pathY));
1091 const MetaTile *
const tile = &mMetaTiles[pathX + pathY * mWidth];
1102 const int x,
const int y,
1106 mParticleEffects.push_back(newEffect);
1114 BLOCK_END(
"Map::initializeParticleEffects")
1120 for (STD_VECTOR<ParticleEffectData>::const_iterator
1131 if ((p !=
nullptr) &&
1139 BLOCK_END(
"Map::initializeParticleEffects")
1153 logger->
log(
"loading extra layer: " + mapFileName);
1154 struct stat statbuf;
1155 if (stat(mapFileName.c_str(), &statbuf) == 0 &&
1156 S_ISREG(statbuf.st_mode))
1158 std::ifstream mapFile;
1159 mapFile.open(mapFileName.c_str(), std::ios::in);
1160 if (!mapFile.is_open())
1168 while (mapFile.getline(line, 200))
1171 std::string str = line;
1177 std::string comment;
1178 std::stringstream ss(str);
1184 comment.append(
" ").append(buf);
1186 const int type = atoi(type1.c_str());
1188 if (comment.empty())
1193 comment =
"unknown";
1235 logger->
log(
"saving extra layer: " + mapFileName);
1244 std::ofstream mapFile;
1245 mapFile.open(mapFileName.c_str(), std::ios::binary);
1246 if (!mapFile.is_open())
1249 mapFileName.c_str())
1256 for (
int x = 0;
x < width;
x ++)
1258 for (
int y = 0;
y < height;
y ++)
1264 mapFile <<
x <<
" " <<
y <<
" "
1266 << item->mComment << std::endl;
1281 const int x,
const int y,
1284 if (mObjects ==
nullptr)
1293 const int x,
const int y,
1304 if (mSpecialLayer !=
nullptr)
1306 mSpecialLayer->setTile(
x,
y,
new MapItem(type, name,
x,
y));
1307 mSpecialLayer->updateCache();
1310 mMapPortals.push_back(
new MapItem(type, name,
x,
y));
1315 const int x,
const int y,
1319 if (item !=
nullptr)
1321 item->mComment = name;
1322 item->setType(type);
1325 if (mSpecialLayer !=
nullptr)
1328 mSpecialLayer->setTile(
x,
y, item);
1329 mSpecialLayer->updateCache();
1334 addPortalTile(name, type,
x,
y);
1340 FOR_EACH (STD_VECTOR<MapItem*>::const_iterator, it, mMapPortals)
1346 if (item->mX ==
x && item->mY ==
y)
1354 if (mTileAnimations.empty())
1358 return (i == mTileAnimations.end()) ?
nullptr : i->second;
1363 const int oldMode = mPvp;
1396 if (mObjects ==
nullptr)
1400 if (list ==
nullptr)
1403 STD_VECTOR<MapObject>::const_iterator it = list->objects.begin();
1404 const STD_VECTOR<MapObject>::const_iterator it_end = list->objects.end();
1405 while (it != it_end)
1407 if ((*it).type == type)
1426 const size_t sz = (*it)->size();
1427 if ((s ==
nullptr) ||
CAST_SIZE(s->getFirstGid()) + sSz
1452 const int start = s2->getFirstGid();
1454 for (
int f =
start; f < end; f ++)
1489 bool dontHaveAlpha(
false);
1494 if (
x >= layer->mWidth ||
y >= layer->mHeight)
1498 if (layer->mTileCondition != -1 || layer->mMask != 1)
1502 layer->mTiles[
x +
y * layer->mWidth].image;
1505 if (img->hasAlphaChannel() && img->isAlphaCalculated())
1507 if (!img->isAlphaVisible())
1509 dontHaveAlpha =
true;
1510 img->setAlphaVisible(
false);
1517 img->setAlphaVisible(
true);
1520 else if (!img->isHasAlphaChannel())
1522 dontHaveAlpha =
true;
1523 img->setAlphaVisible(
false);
1525 else if (img->hasAlphaChannel())
1527 const uint8_t *
restrict const arr =
1528 img->SDLgetAlphaChannel();
1537 if (subImg !=
nullptr)
1540 width = img->mBounds.w;
1542 for (
int f = img->mBounds.x;
1543 f < img->mBounds.x + img->mBounds.w; f ++)
1545 for (
int d = img->mBounds.y;
1546 d < img->mBounds.y + img->mBounds.h; d ++)
1548 const uint8_t chan = arr[f + d * width];
1561 dontHaveAlpha =
true;
1562 img->setAlphaVisible(
false);
1566 img->setAlphaVisible(
true);
1569 img->setAlphaCalculated(
true);
1572 if (!correct || !dontHaveAlpha)
1575 Layers::reverse_iterator ri =
mLayers.rbegin();
1579 if (
x >= layer->mWidth ||
y >= layer->mHeight)
1586 if (layer->mTileCondition != -1 || layer->mMask != 1)
1593 layer->mTiles[
x +
y * layer->mWidth].image;
1594 if ((img !=
nullptr) && !img->isAlphaVisible())
1601 if (layer2->mTileCondition != -1 || layer2->mMask != 1)
1606 const size_t pos =
x +
y *
CAST_SIZE(layer2->mWidth);
1607 img = layer2->mTiles[pos].image;
1610 layer2->mTiles[pos].image =
nullptr;
1633 if (mHeights ==
nullptr)
1635 return mHeights->getHeight(
x,
y);
1648 for (; layers != layers_end; ++ layers)
1666 for (; layers != layers_end; ++ layers)
1682 updateDrawLayersList();
1688 setProperty(
"music", file);
1694 std::map<int, TileAnimation*>::iterator it = mTileAnimations.find(gid);
1695 if (it != mTileAnimations.end())
1697 logger->
log(
"duplicate map animation with gid = %d", gid);
1698 delete (*it).second;
1700 mTileAnimations[gid] = animation;
1705 mDrawLayersFlags = n;
1710 mDrawOnlyFringe =
true;
1714 mDrawOnlyFringe =
false;
1716 updateDrawLayersList();
1717 FOR_EACH (Layers::iterator, it, mLayers)
1720 layer->setDrawLayerFlags(mDrawLayersFlags);
1728 if (mFringeLayer !=
nullptr)
1729 mFringeLayer->setActorsFix(
y);
1739 if ((layer ==
nullptr) || layer->mTileCondition == -1)
1751 if (layer !=
nullptr)
1758 return static_cast<int>(
sizeof(
Map) +
1782 sz += (*it)->calcMemory(level + 1);
1786 sz += (*it)->calcMemory(level + 1);
1790 sz += (*it)->calcMemory(level + 1);
1794 sz += (*it)->calcMemory(level + 1);
Actors::const_iterator ActorsCIter
#define reportAlways(...)
void update(const int timePassed, const float dx, const float dy)
std::vector< TextureAtlas * > atlases
bool getBoolValue(const std::string &key) const
float getFloatValue(const std::string &key) const
void addListener(const std::string &key, ConfigListener *const listener)
void removeListeners(ConfigListener *const listener)
int getIntValue(const std::string &key) const
virtual void clearScreen() const
void log(const char *const log_text,...)
void log1(const char *const log_text)
bool isFringeLayer() const
Actors::iterator addActor(Actor *const actor)
void setMask(const int mask)
std::map< int, TileAnimation * > mTileAnimations
void setBlockMask(const int x, const int y, const BlockTypeT type)
Map(const std::string &name, const int width, const int height, const int tileWidth, const int tileHeight)
const MapHeights * mHeights
void addParticleEffect(const std::string &effectFile, const int x, const int y, const int w, const int h)
uint8_t getHeightOffset(const int x, const int y) const
void saveExtraLayer() const
std::vector< ParticleEffectData > mParticleEffects
void removeActor(const Actors::iterator &iterator)
void setPvpMode(const int mode)
const std::string getFilename() const
void drawAmbientLayers(Graphics *const graphics, const MapLayerPositionT type, const int detail) const
void setDrawLayersFlags(const MapTypeT &n)
SpecialLayer * mTempLayer
bool contains(const int x, const int y) const
void addPortalTile(const std::string &name, const int type, const int x, const int y)
void updateConditionLayers()
void addTileset(Tileset *const tileset)
std::vector< MapItem * > mMapPortals
void addLayer(MapLayer *const layer)
void updatePortalTile(const std::string &name, const int type, const int x, const int y, const bool addNew)
void update(const int ticks)
MetaTile *const mMetaTiles
void draw(Graphics *const graphics, int scrollX, int scrollY)
std::string getObjectData(const unsigned x, const unsigned y, const int type) const
bool getWalk(const int x, const int y, const unsigned char blockWalkMask) const
void updateAmbientLayers(const float scrollX, const float scrollY)
void drawCollision(Graphics *const graphics, const int scrollX, const int scrollY, const MapTypeT drawFlags) const
Path findPath(const int startX, const int startY, const int destX, const int destY, const unsigned char blockWalkmask, const int maxCost)
const std::string getName() const
void addBlockMask(const int x, const int y, const BlockTypeT type)
void addRange(const std::string &name, const int type, const int x, const int y, const int dx, const int dy)
const TileAnimation * getAnimationForGid(const int gid) const
Tileset ** mIndexedTilesets
void initializeParticleEffects() const
SpecialLayer * mSpecialLayer
const std::string getGatName() const
void updateDrawLayersList()
void setActorsFix(const int x, const int y)
void addHeights(const MapHeights *const heights)
void initializeAmbientLayers()
unsigned char getBlockMask(const int x, const int y) const
void optionChanged(const std::string &value)
int calcMemoryLocal() const
void addPortal(const std::string &name, const int type, const int x, const int y, const int dx, const int dy)
int getAtlasCount() const
int calcMemoryChilds(const int level) const
void addAnimation(const int gid, TileAnimation *const animation)
const std::string getMusicFile() const
MapItem * findPortalXY(const int x, const int y) const
AmbientLayerVector mBackgrounds
const MetaTile * getMetaTile(const int x, const int y) const
std::string getUserMapDirectory() const
void setMusicFile(const std::string &file)
AmbientLayerVector mForegrounds
void clearIndexedTilesets()
MapTypeT mDrawLayersFlags
const Tileset * getTilesetWithGid(const int gid) const
void setWalk(const int x, const int y)
int calcMemory(const int level) const
Particle * addEffect(const std::string &particleEffectFile, const int pixelX, const int pixelY, const int rotation)
void adjustEmitterSize(const int w, const int h)
bool hasProperty(const std::string &name) const
bool getBoolProperty(const std::string &name, const bool def) const
const std::string getProperty(const std::string &name, const std::string &def) const
float getFloatProperty(const std::string &name, const float def) const
std::string serverConfigDir
MapItem * getTile(const int x, const int y) const
const Color & getColorWithAlpha(const UserColorIdT type)
static const int mapTileSize
void delete_all(Container &c)
#define FOR_EACHP(type, iter, array)
#define FOR_EACH(type, iter, array)
#define A_DEFAULT_COPY(func)
LocalPlayer * localPlayer
#define fillCollision(collision, color)
class ActorFunctuator actorCompare
MapLayerPosition ::T MapLayerPositionT
int mkdir_r(const char *const pathname)
Create a directory, making leading components first if necessary.
bool contains(std::string const &s, std::string const &infix)
std::string toString(T const &value)
converts any type to a string
Image * getImage(const std::string &idPath)
void notify(const unsigned int message)
@ AIR_COLLISION_HIGHLIGHT
@ MONSTER_COLLISION_HIGHLIGHT
@ GROUNDTOP_COLLISION_HIGHLIGHT
@ WATER_COLLISION_HIGHLIGHT
static const int blockWalkMask
ParticleEngine * particleEngine
#define BLOCK_START(name)
std::list< Position > Path
RenderType intToRenderType(const int mode)
Layers::const_iterator LayersCIter
std::vector< AmbientLayer * > AmbientLayerVector
AmbientLayerVector::const_iterator AmbientLayerVectorCIter
AmbientLayerVector::iterator AmbientLayerVectorIter
std::string strprintf(const char *const format,...)
size_t rfindSepatator(const std::string &str1)
std::string pathJoin(std::string str1, const std::string &str2)
TileAnimationMap::const_iterator TileAnimationMapCIter
int get_elapsed_time(const int startTime)
UserPalette * userPalette