diff options
author | Philipp Sehmisch <tmw@crushnet.org> | 2008-03-13 07:29:01 +0000 |
---|---|---|
committer | Philipp Sehmisch <tmw@crushnet.org> | 2008-03-13 07:29:01 +0000 |
commit | efe4ef65bedbaa66e35f3a4354f7422c313ce624 (patch) | |
tree | c1259e6a60e80ee5b8ba97c44f9223071aba4df7 /src/game-server/map.cpp | |
parent | 344fe375ff6e7db425da6ca266e02ea93dd7cc4d (diff) | |
download | manaserv-efe4ef65bedbaa66e35f3a4354f7422c313ce624.tar.gz manaserv-efe4ef65bedbaa66e35f3a4354f7422c313ce624.tar.bz2 manaserv-efe4ef65bedbaa66e35f3a4354f7422c313ce624.tar.xz manaserv-efe4ef65bedbaa66e35f3a4354f7422c313ce624.zip |
Implemented dynamic and selective pathblocking. Monsters are blocked by player characters and other monsters, player characters only by monsters.
Diffstat (limited to 'src/game-server/map.cpp')
-rw-r--r-- | src/game-server/map.cpp | 115 |
1 files changed, 92 insertions, 23 deletions
diff --git a/src/game-server/map.cpp b/src/game-server/map.cpp index 3699b6da..8ad9242a 100644 --- a/src/game-server/map.cpp +++ b/src/game-server/map.cpp @@ -27,7 +27,8 @@ #include "game-server/map.hpp" MetaTile::MetaTile(): - whichList(0) + whichList(0), + blockmask(0) { } @@ -44,62 +45,131 @@ bool Location::operator< (const Location &loc) const Map::Map(): - width(0), height(0), + mWidth(0), mHeight(0), tileWidth(32), tileHeight(32), onClosedList(1), onOpenList(2) { - metaTiles = new MetaTile[width * height]; + mMetaTiles = new MetaTile[mWidth * mHeight]; + for (int i=0; i < NB_BLOCKTYPES; i++) + { + mOccupation[i] = new int[mWidth * mHeight]; + memset(mOccupation[i], 0, mWidth * mHeight * sizeof(int)); + } } Map::Map(int width, int height): - width(width), height(height), + mWidth(width), mHeight(height), tileWidth(32), tileHeight(32), onClosedList(1), onOpenList(2) { - metaTiles = new MetaTile[width * height]; + mMetaTiles = new MetaTile[mWidth * mHeight]; + for (int i=0; i < NB_BLOCKTYPES; i++) + { + mOccupation[i] = new int[mWidth * mHeight]; + memset(mOccupation[i], 0, mWidth * mHeight * sizeof(int)); + } } Map::~Map() { - delete[] metaTiles; + delete[] mMetaTiles; + for (int i=0; i < NB_BLOCKTYPES; i++) + { + delete[] mOccupation[i]; + } } void Map::setSize(int width, int height) { - this->width = width; - this->height = height; - delete[] metaTiles; - metaTiles = new MetaTile[width * height]; + this->mWidth = width; + this->mHeight = height; + + delete[] mMetaTiles; + mMetaTiles = new MetaTile[mWidth * mHeight]; + + for (int i=0; i < NB_BLOCKTYPES; i++) + { + delete[] mOccupation[i]; + mOccupation[i] = new int[mWidth * mHeight]; + } +} + +void Map::blockTile(int x, int y, BlockType type) +{ + if (type == BLOCKTYPE_NONE) return; + int tileNum = x + y * mWidth; + assert (tileNum <= mWidth * mHeight); + + if (++mOccupation[type][tileNum]) + { + switch (type) + { + case BLOCKTYPE_WALL: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_WALL; + break; + case BLOCKTYPE_CHARACTER: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_CHARACTER; + break; + case BLOCKTYPE_MONSTER: + mMetaTiles[tileNum].blockmask |= BLOCKMASK_MONSTER; + break; + default: + // shut up! + break; + } + } } -void Map::setWalk(int x, int y, bool walkable) +void Map::freeTile(int x, int y, BlockType type) { - metaTiles[x + y * width].walkable = walkable; + if (type == BLOCKTYPE_NONE) return; + + int tileNum = x + y * mWidth; + assert (tileNum <= mWidth * mHeight); + + if (!(--mOccupation[type][tileNum])) + { + switch (type) + { + case BLOCKTYPE_WALL: + mMetaTiles[tileNum].blockmask &= (BLOCKMASK_WALL xor 0xff); + break; + case BLOCKTYPE_CHARACTER: + mMetaTiles[tileNum].blockmask &= (BLOCKMASK_CHARACTER xor 0xff); + break; + case BLOCKTYPE_MONSTER: + mMetaTiles[tileNum].blockmask &= (BLOCKMASK_MONSTER xor 0xff); + break; + default: + // shut up! + break; + } + } } -bool Map::getWalk(int x, int y) const +bool Map::getWalk(int x, int y, char walkmask) const { // You can't walk outside of the map - if (x < 0 || y < 0 || x >= width || y >= height) + if (x < 0 || y < 0 || x >= mWidth || y >= mHeight) { return false; } // Check if the tile is walkable - return metaTiles[x + y * width].walkable; + return !(mMetaTiles[x + y * mWidth].blockmask & walkmask); } MetaTile* Map::getMetaTile(int x, int y) { - return &metaTiles[x + y * width]; + return &mMetaTiles[x + y * mWidth]; } static int const basicCost = 100; std::list<PATH_NODE> -Map::findPath(int startX, int startY, int destX, int destY, int maxCost) +Map::findPath(int startX, int startY, int destX, int destY, unsigned char walkmask, int maxCost) { // Path to be built up (empty by default) std::list<PATH_NODE> path; @@ -108,7 +178,7 @@ Map::findPath(int startX, int startY, int destX, int destY, int maxCost) std::priority_queue<Location> openList; // Return when destination not walkable - if (!getWalk(destX, destY)) return path; + if (!getWalk(destX, destY, walkmask)) return path; // Reset starting tile's G cost to 0 MetaTile *startTile = getMetaTile(startX, startY); @@ -149,7 +219,7 @@ Map::findPath(int startX, int startY, int destX, int destY, int maxCost) // Skip if if we're checking the same tile we're leaving from, // or if the new location falls outside of the map boundaries if ((dx == 0 && dy == 0) || - (x < 0 || y < 0 || x >= width || y >= height)) + (x < 0 || y < 0 || x >= mWidth || y >= mHeight)) { continue; } @@ -157,20 +227,19 @@ Map::findPath(int startX, int startY, int destX, int destY, int maxCost) MetaTile *newTile = getMetaTile(x, y); // Skip if the tile is on the closed list or is not walkable - if (newTile->whichList == onClosedList || !newTile->walkable) + if (newTile->whichList == onClosedList || newTile->blockmask & walkmask) { continue; } // When taking a diagonal step, verify that we can skip the - // corner. We allow skipping past beings but not past non- - // walkable tiles. + // corner. if (dx != 0 && dy != 0) { MetaTile *t1 = getMetaTile(curr.x, curr.y + dy); MetaTile *t2 = getMetaTile(curr.x + dx, curr.y); - if (!(t1->walkable && t2->walkable)) + if (t1->blockmask & walkmask && !(t2->blockmask & walkmask)) // I hope I didn't fuck this line up { continue; } |