diff options
Diffstat (limited to 'engines/gob/map.cpp')
-rw-r--r-- | engines/gob/map.cpp | 451 |
1 files changed, 269 insertions, 182 deletions
diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp index 9f1f5bdc59..500f6515ec 100644 --- a/engines/gob/map.cpp +++ b/engines/gob/map.cpp @@ -32,33 +32,40 @@ namespace Gob { Map::Map(GobEngine *vm) : _vm(vm) { - _widthByte = 0; - _mapWidth = -1; + _mapVersion = 0; + + _passWidth = 0; + _mapWidth = -1; _mapHeight = -1; - _screenWidth = 0; + _passMap = 0; + + _screenWidth = 0; _screenHeight = 0; - _tilesWidth = 0; + + _tilesWidth = 0; _tilesHeight = 0; - _passWidth = 0; - _passMap = 0; - _itemsMap = 0; - _wayPointsCount = 0; - _wayPoints = 0; _bigTiles = false; + _wayPointCount = 0; + _wayPoints = 0; + + _nearestWayPoint = 0; + _nearestDest = 0; + + _itemsMap = 0; + for (int i = 0; i < 40; i++) { - _itemPoses[i].x = 0; - _itemPoses[i].y = 0; + _itemPoses[i].x = 0; + _itemPoses[i].y = 0; _itemPoses[i].orient = 0; } - _nearestWayPoint = 0; - _nearestDest = 0; _curGoblinX = 0; _curGoblinY = 0; _destX = 0; _destY = 0; + _sourceFile[0] = 0; _loadFromAvo = false; @@ -76,6 +83,87 @@ Map::~Map() { delete[] _wayPoints; } +uint8 Map::getVersion() const { + return _mapVersion; +} + +int16 Map::getMapWidth() const { + return _mapWidth; +} + +int16 Map::getMapHeight() const { + return _mapHeight; +} + +int16 Map::getScreenWidth() const { + return _screenWidth; +} + +int16 Map::getScreenHeight() const { + return _screenHeight; +} + +int16 Map::getTilesWidth() const { + return _tilesWidth; +} + +int16 Map::getTilesHeight() const { + return _tilesHeight; +} + +bool Map::hasBigTiles() const { + return _bigTiles; +} + +int8 Map::getPass(int x, int y, int width) const { + if (!_passMap) + return 0; + + if ((x < 0) || (y < 0) || (x >= _mapWidth) || (y >= _mapHeight)) + return 0; + + if (width == -1) + width = _passWidth; + return _passMap[y * width + x]; +} + +void Map::setPass(int x, int y, int8 pass, int width) { + if (!_passMap) + return; + + if ((x < 0) || (y < 0) || (x >= _mapWidth) || (y >= _mapHeight)) + return; + + if (width == -1) + width = _passWidth; + _passMap[y * width + x] = pass; +} + +const WayPoint &Map::getWayPoint(int n) const { + assert(_wayPoints); + assert(n < _wayPointCount); + + return _wayPoints[n]; +} + +int16 Map::getItem(int x, int y) const { + assert(_itemsMap); + + x = CLIP<int>(x, 0, _mapWidth - 1); + y = CLIP<int>(y, 0, _mapHeight - 1); + + return _itemsMap[y][x]; +} + +void Map::setItem(int x, int y, int16 item) { + assert(_itemsMap); + + x = CLIP<int>(x, 0, _mapWidth - 1); + y = CLIP<int>(y, 0, _mapHeight - 1); + + _itemsMap[y][x] = item; +} + void Map::placeItem(int16 x, int16 y, int16 id) { if ((getItem(x, y) & 0xFF00) != 0) setItem(x, y, (getItem(x, y) & 0xFF00) | id); @@ -83,150 +171,175 @@ void Map::placeItem(int16 x, int16 y, int16 id) { setItem(x, y, (getItem(x, y) & 0x00FF) | (id << 8)); } -enum { - kLeft = (1 << 0), - kUp = (1 << 1), - kRight = (1 << 2), - kDown = (1 << 3) -}; - -int16 Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { - int16 dir = 0; - +Direction Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) { if ((x0 == x1) && (y0 == y1)) - return 0; + // Already at the destination + return kDirNone; if ((x1 < 0) || (x1 > _mapWidth) || (y1 < 0) || (y1 > _mapHeight)) - return 0; + // Destination out of range + return kDirNone; + RelativeDirection relDir = kRelDirNone; + + // Find the direct direction we want to move if (y1 > y0) - dir |= kDown; + relDir = kRelDirDown; else if (y1 < y0) - dir |= kUp; + relDir = kRelDirUp; if (x1 > x0) - dir |= kRight; + relDir = (RelativeDirection)(relDir | kRelDirRight); else if (x1 < x0) - dir |= kLeft; + relDir = (RelativeDirection)(relDir | kRelDirLeft); - if ((getPass(x0, y0) == 3) && (dir & kUp)) { - if ((getPass(x0, y0 - 1) != 0)) - return kDirN; - } - if ((getPass(x0, y0) == 3) && (dir & kDown)) { - if ((getPass(x0, y0 + 1) != 0)) - return kDirS; - } + // Are we on ladders and can continue the ladder in the wanted direction? + if ((getPass(x0, y0) == 3) && (relDir & kRelDirUp ) && (getPass(x0, y0 - 1) != 0)) + return kDirN; - if ((getPass(x0, y0) == 6) && (dir & kUp)) { - if ((getPass(x0, y0 - 1) != 0)) - return kDirN; - } + if ((getPass(x0, y0) == 3) && (relDir & kRelDirDown) && (getPass(x0, y0 + 1) != 0)) + return kDirS; - if ((getPass(x0, y0) == 6) && (dir & kDown)) { - if ((getPass(x0, y0 + 1) != 0)) - return kDirS; - } + if ((getPass(x0, y0) == 6) && (relDir & kRelDirUp ) && (getPass(x0, y0 - 1) != 0)) + return kDirN; - if (dir == kLeft) { - if (((x0 - 1) >= 0) && (getPass(x0 - 1, y0) != 0)) + if ((getPass(x0, y0) == 6) && (relDir & kRelDirDown) && (getPass(x0, y0 + 1) != 0)) + return kDirS; + + + // Want to go left + if (relDir == kRelDirLeft) { + if (getPass(x0 - 1, y0) != 0) + // Can go west return kDirW; - return 0; + + // Can't go + return kDirNone; } - if (dir == kRight) { - if (((x0 + 1) < _mapWidth) && (getPass(x0 + 1, y0) != 0)) + // Want to go left + if (relDir == kRelDirRight) { + if (getPass(x0 + 1, y0) != 0) + // Can go east return kDirE; - return 0; + + // Can't go + return kDirNone; } - if (dir == kUp) { - if (((y0 - 1) >= 0) && (getPass(x0, y0 - 1) != 0)) + + // Want to go up + if (relDir == kRelDirUp) { + if (getPass(x0 , y0 - 1) != 0) + // Can go north return kDirN; - if (((y0 - 1) >= 0) && ((x0 - 1) >= 0) && - (getPass(x0 - 1, y0 - 1) != 0)) + if (getPass(x0 - 1, y0 - 1) != 0) + // Can up north-west instead return kDirNW; - if (((y0 - 1) >= 0) && ((x0 + 1) < _mapWidth) && - (getPass(x0 + 1, y0 - 1) != 0)) + if (getPass(x0 + 1, y0 - 1) != 0) + // Can up north-east instead return kDirNE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == kDown) { - if (((y0 + 1) < _mapHeight) && (getPass(x0, y0 + 1) != 0)) + // Want to go down + if (relDir == kRelDirDown) { + if (getPass(x0 , y0 + 1) != 0) + // Can go south return kDirS; - if (((y0 + 1) < _mapHeight) && ((x0 - 1) >= 0) && - (getPass(x0 - 1, y0 + 1) != 0)) + if (getPass(x0 - 1, y0 + 1) != 0) + // Can up south-west instead return kDirSW; - if (((y0 + 1) < _mapHeight) && ((x0 + 1) < _mapWidth) && - (getPass(x0 + 1, y0 + 1) != 0)) + if (getPass(x0 + 1, y0 + 1) != 0) + // Can up south-east instead return kDirSE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kRight | kUp)) { - if (((y0 - 1) >= 0) && ((x0 + 1) < _mapWidth) && - (getPass(x0 + 1, y0 - 1) != 0)) + + // Want to go up and right + if (relDir == kRelDirRightUp) { + if (getPass(x0 + 1, y0 - 1) != 0) + // Can go north-east return kDirNE; - if (((y0 - 1) >= 0) && (getPass(x0, y0 - 1) != 0)) + if (getPass(x0 , y0 - 1) != 0) + // Can only go north return kDirN; - if (((x0 + 1) < _mapWidth) && (getPass(x0 + 1, y0) != 0)) + if (getPass(x0 + 1, y0 ) != 0) + // Can only go east return kDirE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kRight | kDown)) { - if (((x0 + 1) < _mapWidth) && ((y0 + 1) < _mapHeight) && - (getPass(x0 + 1, y0 + 1) != 0)) + // Want to go down and right + if (relDir == kRelDirRightDown) { + if (getPass(x0 + 1, y0 + 1) != 0) + // Can go south-east return kDirSE; - if (((y0 + 1) < _mapHeight) && (getPass(x0, y0 + 1) != 0)) + if (getPass(x0 , y0 + 1) != 0) + // Can only go south return kDirS; - if (((x0 + 1) < _mapWidth) && (getPass(x0 + 1, y0) != 0)) + if (getPass(x0 + 1, y0 ) != 0) + // Can only go east return kDirE; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kLeft | kUp)) { - if (((x0 - 1) >= 0) && ((y0 - 1) >= 0) && - (getPass(x0 - 1, y0 - 1) != 0)) + // Want to go up and left + if (relDir == kRelDirLeftUp) { + if (getPass(x0 - 1, y0 - 1) != 0) + // Can go north-west return kDirNW; - if (((y0 - 1) >= 0) && (getPass(x0, y0 - 1) != 0)) + if (getPass(x0 , y0 - 1) != 0) + // Can only go north return kDirN; - if (((x0 - 1) >= 0) && (getPass(x0 - 1, y0) != 0)) + if (getPass(x0 - 1, y0 ) != 0) + // Can only go west return kDirW; - return 0; + // Can't go at all + return kDirNone; } - if (dir == (kLeft | kDown)) { - if (((x0 - 1) >= 0) && ((y0 + 1) < _mapHeight) && - (getPass(x0 - 1, y0 + 1) != 0)) + // Want to go left and down + if (relDir == kRelDirLeftDown) { + if (getPass(x0 - 1, y0 + 1) != 0) + // Can go south-west return kDirSW; - if (((y0 + 1) < _mapHeight) && (getPass(x0, y0 + 1) != 0)) + if (getPass(x0 , y0 + 1) != 0) + // Can only go south return kDirS; - if (((x0 - 1) >= 0) && (getPass(x0 - 1, y0) != 0)) + if (getPass(x0 - 1, y0 ) != 0) + // Can only go west return kDirW; - return 0; + // Can't go at all + return kDirNone; } - return -1; + + warning("Map::getDirection(): Invalid direction?!?"); + return kDirNone; } int16 Map::findNearestWayPoint(int16 x, int16 y) { @@ -236,7 +349,7 @@ int16 Map::findNearestWayPoint(int16 x, int16 y) { length = 30000; - for (int i = 0; i < _wayPointsCount; i++) { + for (int i = 0; i < _wayPointCount; i++) { if ((_wayPoints[i].x < 0) || (_wayPoints[i].x >= _mapWidth) || (_wayPoints[i].y < 0) || (_wayPoints[i].y >= _mapHeight)) break; @@ -318,73 +431,81 @@ void Map::findNearestWalkable(int16 &gobDestX, int16 &gobDestY, gobDestY -= distance; } -int16 Map::checkDirectPath(Mult::Mult_Object *obj, - int16 x0, int16 y0, int16 x1, int16 y1) { - uint16 dir; +void Map::moveDirection(Direction dir, int16 &x, int16 &y) { + switch (dir) { + case kDirNW: + x--; + y--; + break; + + case kDirN: + y--; + break; + + case kDirNE: + x++; + y--; + break; + + case kDirW: + x--; + break; + + case kDirE: + x++; + break; + + case kDirSW: + x--; + y++; + break; + + case kDirS: + y++; + break; + + case kDirSE: + x++; + y++; + break; + + default: + break; + } +} + +int16 Map::checkDirectPath(Mult::Mult_Object *obj, int16 x0, int16 y0, int16 x1, int16 y1) { while (1) { - dir = getDirection(x0, y0, x1, y1); + Direction dir = getDirection(x0, y0, x1, y1); if (obj) { - if (obj->nearestWayPoint < obj->nearestDest) { - if (_wayPoints[obj->nearestWayPoint + 1].notWalkable == 1) - return 3; - } else if (obj->nearestWayPoint > obj->nearestDest) { - if (obj->nearestDest > 0) - if (_wayPoints[obj->nearestDest - 1].notWalkable == 1) + // Check for a blocking waypoint + + if (obj->nearestWayPoint < obj->nearestDest) + if ((obj->nearestWayPoint + 1) < _wayPointCount) + if (_wayPoints[obj->nearestWayPoint + 1].notWalkable == 1) + return 3; + + if (obj->nearestWayPoint > obj->nearestDest) + if (obj->nearestWayPoint > 0) + if (_wayPoints[obj->nearestWayPoint - 1].notWalkable == 1) return 3; - } } if ((x0 == x1) && (y0 == y1)) + // Successfully reached the destination return 1; - if (dir == 0) + if (dir == kDirNone) + // No way return 3; - switch (dir) { - case kDirNW: - x0--; - y0--; - break; - - case kDirN: - y0--; - break; - - case kDirNE: - x0++; - y0--; - break; - - case kDirW: - x0--; - break; - - case kDirE: - x0++; - break; - - case kDirSW: - x0--; - y0++; - break; - - case kDirS: - y0++; - break; - - case kDirSE: - x0++; - y0++; - break; - } + moveDirection(dir, x0, y0); } } -int16 Map::checkLongPath(int16 x0, int16 y0, - int16 x1, int16 y1, int16 i0, int16 i1) { - uint16 dir = 0; +int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 i1) { int16 curX = x0; int16 curY = y0; int16 nextLink = 1; @@ -417,47 +538,13 @@ int16 Map::checkLongPath(int16 x0, int16 y0, return 1; return 0; } - dir = getDirection(x0, y0, curX, curY); - switch (dir) { - case 0: - return 0; - - case kDirNW: - x0--; - y0--; - break; - case kDirN: - y0--; - break; - - case kDirNE: - x0++; - y0--; - break; - - case kDirW: - x0--; - break; - - case kDirE: - x0++; - break; - - case kDirSW: - x0--; - y0++; - break; - - case kDirS: - y0++; - break; + Direction dir = getDirection(x0, y0, curX, curY); + if (dir == kDirNone) + // No way + return 0; - case kDirSE: - x0++; - y0++; - break; - } + moveDirection(dir, x0, y0); } } |