2007-05-30 21:56:52 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
2005-04-05 18:08:02 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2008-01-05 12:45:14 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2005-04-05 18:08:02 +00:00
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2005-04-09 19:19:54 +00:00
|
|
|
* along with this program; if not, write to the Free Software
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2005-04-05 18:08:02 +00:00
|
|
|
*
|
|
|
|
*/
|
2006-03-29 15:59:37 +00:00
|
|
|
|
2005-04-05 15:07:40 +00:00
|
|
|
#include "gob/gob.h"
|
|
|
|
#include "gob/map.h"
|
|
|
|
#include "gob/goblin.h"
|
2005-04-09 19:32:29 +00:00
|
|
|
#include "gob/scenery.h"
|
2006-05-29 18:24:52 +00:00
|
|
|
#include "gob/mult.h"
|
2005-04-05 15:07:40 +00:00
|
|
|
|
|
|
|
namespace Gob {
|
|
|
|
|
2006-01-03 23:14:39 +00:00
|
|
|
Map::Map(GobEngine *vm) : _vm(vm) {
|
2010-10-30 17:27:23 +00:00
|
|
|
_mapVersion = 0;
|
|
|
|
|
2010-10-30 17:26:06 +00:00
|
|
|
_passWidth = 0;
|
|
|
|
_mapWidth = -1;
|
2006-05-29 18:24:52 +00:00
|
|
|
_mapHeight = -1;
|
2010-10-30 17:26:06 +00:00
|
|
|
_passMap = 0;
|
|
|
|
|
|
|
|
_screenWidth = 0;
|
2007-08-13 14:04:50 +00:00
|
|
|
_screenHeight = 0;
|
2010-10-30 17:28:27 +00:00
|
|
|
|
|
|
|
_tilesWidth = 0;
|
|
|
|
_tilesHeight = 0;
|
2006-05-29 18:24:52 +00:00
|
|
|
|
|
|
|
_bigTiles = false;
|
|
|
|
|
2011-01-30 13:14:32 +00:00
|
|
|
_mapUnknownBool = false;
|
|
|
|
|
2010-10-30 17:26:06 +00:00
|
|
|
_wayPointCount = 0;
|
|
|
|
_wayPoints = 0;
|
|
|
|
|
|
|
|
_nearestWayPoint = 0;
|
|
|
|
_nearestDest = 0;
|
|
|
|
|
|
|
|
_itemsMap = 0;
|
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
for (int i = 0; i < 40; i++) {
|
2010-10-30 17:26:06 +00:00
|
|
|
_itemPoses[i].x = 0;
|
|
|
|
_itemPoses[i].y = 0;
|
2006-01-04 01:23:20 +00:00
|
|
|
_itemPoses[i].orient = 0;
|
2006-01-03 23:14:39 +00:00
|
|
|
}
|
|
|
|
|
2006-01-04 01:23:20 +00:00
|
|
|
_curGoblinX = 0;
|
|
|
|
_curGoblinY = 0;
|
|
|
|
_destX = 0;
|
|
|
|
_destY = 0;
|
2010-10-30 17:26:06 +00:00
|
|
|
|
2006-01-04 01:23:20 +00:00
|
|
|
_sourceFile[0] = 0;
|
2007-03-20 14:51:57 +00:00
|
|
|
|
|
|
|
_loadFromAvo = false;
|
2006-01-03 23:14:39 +00:00
|
|
|
}
|
|
|
|
|
2007-02-17 09:56:09 +00:00
|
|
|
Map::~Map() {
|
2007-03-20 14:51:57 +00:00
|
|
|
delete[] _passMap;
|
2007-02-17 09:56:09 +00:00
|
|
|
|
|
|
|
if (_itemsMap) {
|
|
|
|
for (int i = 0; i < _mapHeight; i++)
|
|
|
|
delete[] _itemsMap[i];
|
|
|
|
delete[] _itemsMap;
|
|
|
|
}
|
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
delete[] _wayPoints;
|
2007-02-17 09:56:09 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 17:27:23 +00:00
|
|
|
uint8 Map::getVersion() const {
|
|
|
|
return _mapVersion;
|
|
|
|
}
|
|
|
|
|
2010-10-30 17:28:27 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-30 17:25:29 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-10-30 17:26:49 +00:00
|
|
|
const WayPoint &Map::getWayPoint(int n) const {
|
|
|
|
assert(_wayPoints);
|
|
|
|
assert(n < _wayPointCount);
|
|
|
|
|
|
|
|
return _wayPoints[n];
|
|
|
|
}
|
|
|
|
|
2010-10-30 17:28:54 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-01-03 23:14:39 +00:00
|
|
|
void Map::placeItem(int16 x, int16 y, int16 id) {
|
2008-08-23 14:18:12 +00:00
|
|
|
if ((getItem(x, y) & 0xFF00) != 0)
|
|
|
|
setItem(x, y, (getItem(x, y) & 0xFF00) | id);
|
This should fix a crash which could happen when placing several objects too
close to each other on the ground. (Happened to me on the first level after
destroying the voodoo doll, where I'd drop the banana, the soap and the
false nose close to each other on the ground after using them.)
Reasoning behind the change:
From what I understand, map_itemsMap[] contains information for each "cell"
of the map about which objects are there. Each cell can contain two objects
which are stored in the upper and lower byte of a 16-bit word.
When dropping an object, it is written into map_itemsMap[], but not just to
the indicated cell but also to a few of the surrounding ones. Presumably to
make it easier to pick it up afterwards.
When writing an object to a cell, we check if one of the bytes is already
occupied. If it is, write to the other byte. Otherwise, write to that byte.
(If both bytes are occupied, one will be overwritten.)
The old code assumed that if one byte was free at position (x,y) the same
byte would automatically be the free one in the surrounding cells. This
could cause bad values in the array, since the item was added to an
existing value, rather than replacing it.
This new code makes the check for each cell that is modified. (It also gets
rid of some code duplication.)
svn-id: r17851
2005-04-28 10:34:48 +00:00
|
|
|
else
|
2008-08-23 14:18:12 +00:00
|
|
|
setItem(x, y, (getItem(x, y) & 0x00FF) | (id << 8));
|
This should fix a crash which could happen when placing several objects too
close to each other on the ground. (Happened to me on the first level after
destroying the voodoo doll, where I'd drop the banana, the soap and the
false nose close to each other on the ground after using them.)
Reasoning behind the change:
From what I understand, map_itemsMap[] contains information for each "cell"
of the map about which objects are there. Each cell can contain two objects
which are stored in the upper and lower byte of a 16-bit word.
When dropping an object, it is written into map_itemsMap[], but not just to
the indicated cell but also to a few of the surrounding ones. Presumably to
make it easier to pick it up afterwards.
When writing an object to a cell, we check if one of the bytes is already
occupied. If it is, write to the other byte. Otherwise, write to that byte.
(If both bytes are occupied, one will be overwritten.)
The old code assumed that if one byte was free at position (x,y) the same
byte would automatically be the free one in the surrounding cells. This
could cause bad values in the array, since the item was added to an
existing value, rather than replacing it.
This new code makes the check for each cell that is modified. (It also gets
rid of some code duplication.)
svn-id: r17851
2005-04-28 10:34:48 +00:00
|
|
|
}
|
|
|
|
|
2010-10-30 17:24:52 +00:00
|
|
|
Direction Map::getDirection(int16 x0, int16 y0, int16 x1, int16 y1) {
|
2007-03-20 14:51:57 +00:00
|
|
|
if ((x0 == x1) && (y0 == y1))
|
2010-10-25 03:37:48 +00:00
|
|
|
// Already at the destination
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2007-03-01 14:41:40 +00:00
|
|
|
if ((x1 < 0) || (x1 > _mapWidth) || (y1 < 0) || (y1 > _mapHeight))
|
2010-10-25 03:37:48 +00:00
|
|
|
// Destination out of range
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-30 17:24:52 +00:00
|
|
|
RelativeDirection relDir = kRelDirNone;
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
// Find the direct direction we want to move
|
2005-04-05 15:07:40 +00:00
|
|
|
if (y1 > y0)
|
2010-10-30 17:24:52 +00:00
|
|
|
relDir = kRelDirDown;
|
2005-04-05 15:07:40 +00:00
|
|
|
else if (y1 < y0)
|
2010-10-30 17:24:52 +00:00
|
|
|
relDir = kRelDirUp;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
|
|
|
if (x1 > x0)
|
2010-10-30 17:24:52 +00:00
|
|
|
relDir = (RelativeDirection)(relDir | kRelDirRight);
|
2005-04-05 15:07:40 +00:00
|
|
|
else if (x1 < x0)
|
2010-10-30 17:24:52 +00:00
|
|
|
relDir = (RelativeDirection)(relDir | kRelDirLeft);
|
2005-04-05 15:07:40 +00:00
|
|
|
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Are we on ladders and can continue the ladder in the wanted direction?
|
2010-10-30 17:24:52 +00:00
|
|
|
if ((getPass(x0, y0) == 3) && (relDir & kRelDirUp ) && (getPass(x0, y0 - 1) != 0))
|
2010-10-25 03:37:48 +00:00
|
|
|
return kDirN;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-30 17:24:52 +00:00
|
|
|
if ((getPass(x0, y0) == 3) && (relDir & kRelDirDown) && (getPass(x0, y0 + 1) != 0))
|
2010-10-25 03:37:48 +00:00
|
|
|
return kDirS;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-30 17:24:52 +00:00
|
|
|
if ((getPass(x0, y0) == 6) && (relDir & kRelDirUp ) && (getPass(x0, y0 - 1) != 0))
|
2010-10-25 03:37:48 +00:00
|
|
|
return kDirN;
|
|
|
|
|
2010-10-30 17:24:52 +00:00
|
|
|
if ((getPass(x0, y0) == 6) && (relDir & kRelDirDown) && (getPass(x0, y0 + 1) != 0))
|
2010-10-25 03:37:48 +00:00
|
|
|
return kDirS;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
// Want to go left
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirLeft) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0) != 0)
|
|
|
|
// Can go west
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirW;
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
// Can't go
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Want to go left
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirRight) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0) != 0)
|
|
|
|
// Can go east
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirE;
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
// Can't go
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
// Want to go up
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirUp) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 , y0 - 1) != 0)
|
|
|
|
// Can go north
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirN;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0 - 1) != 0)
|
|
|
|
// Can up north-west instead
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirNW;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0 - 1) != 0)
|
|
|
|
// Can up north-east instead
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirNE;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Can't go at all
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Want to go down
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirDown) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 , y0 + 1) != 0)
|
|
|
|
// Can go south
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirS;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0 + 1) != 0)
|
|
|
|
// Can up south-west instead
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirSW;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0 + 1) != 0)
|
|
|
|
// Can up south-east instead
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirSE;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Can't go at all
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
// Want to go up and right
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirRightUp) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0 - 1) != 0)
|
|
|
|
// Can go north-east
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirNE;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 , y0 - 1) != 0)
|
|
|
|
// Can only go north
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirN;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0 ) != 0)
|
|
|
|
// Can only go east
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirE;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Can't go at all
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Want to go down and right
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirRightDown) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0 + 1) != 0)
|
|
|
|
// Can go south-east
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirSE;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 , y0 + 1) != 0)
|
|
|
|
// Can only go south
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirS;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 + 1, y0 ) != 0)
|
|
|
|
// Can only go east
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirE;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Can't go at all
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Want to go up and left
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirLeftUp) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0 - 1) != 0)
|
|
|
|
// Can go north-west
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirNW;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 , y0 - 1) != 0)
|
|
|
|
// Can only go north
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirN;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0 ) != 0)
|
|
|
|
// Can only go west
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirW;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Can't go at all
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Want to go left and down
|
2010-10-30 17:24:52 +00:00
|
|
|
if (relDir == kRelDirLeftDown) {
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0 + 1) != 0)
|
|
|
|
// Can go south-west
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirSW;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 , y0 + 1) != 0)
|
|
|
|
// Can only go south
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirS;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
if (getPass(x0 - 1, y0 ) != 0)
|
|
|
|
// Can only go west
|
2005-07-10 13:37:03 +00:00
|
|
|
return kDirW;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:37:48 +00:00
|
|
|
// Can't go at all
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
2010-10-25 03:37:48 +00:00
|
|
|
|
|
|
|
warning("Map::getDirection(): Invalid direction?!?");
|
2010-10-25 03:38:34 +00:00
|
|
|
return kDirNone;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2006-01-03 23:14:39 +00:00
|
|
|
int16 Map::findNearestWayPoint(int16 x, int16 y) {
|
2007-03-01 14:41:40 +00:00
|
|
|
int16 nearestWayPoint = -1;
|
2005-04-05 15:07:40 +00:00
|
|
|
int16 length;
|
|
|
|
int16 tmp;
|
|
|
|
|
|
|
|
length = 30000;
|
|
|
|
|
2010-10-30 17:26:06 +00:00
|
|
|
for (int i = 0; i < _wayPointCount; i++) {
|
2007-03-20 14:51:57 +00:00
|
|
|
if ((_wayPoints[i].x < 0) || (_wayPoints[i].x >= _mapWidth) ||
|
|
|
|
(_wayPoints[i].y < 0) || (_wayPoints[i].y >= _mapHeight))
|
2007-03-01 14:41:40 +00:00
|
|
|
break;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2006-01-04 01:23:20 +00:00
|
|
|
tmp = ABS(x - _wayPoints[i].x) + ABS(y - _wayPoints[i].y);
|
2005-04-05 15:07:40 +00:00
|
|
|
|
|
|
|
if (tmp <= length) {
|
2007-03-01 14:41:40 +00:00
|
|
|
nearestWayPoint = i;
|
2005-04-05 15:07:40 +00:00
|
|
|
length = tmp;
|
|
|
|
}
|
|
|
|
}
|
2005-07-10 13:37:03 +00:00
|
|
|
|
2007-03-01 14:41:40 +00:00
|
|
|
return nearestWayPoint;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
void Map::findNearestWalkable(int16 &gobDestX, int16 &gobDestY,
|
|
|
|
int16 mouseX, int16 mouseY) {
|
|
|
|
int16 mapWidth, mapHeight;
|
|
|
|
int16 pos1 = -1, pos2 = -1;
|
|
|
|
int16 distance;
|
|
|
|
int16 direction;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
mapWidth = _screenWidth / _tilesWidth;
|
2011-11-03 15:58:54 +00:00
|
|
|
mapHeight = _vm->_height / _tilesHeight;
|
2007-03-20 14:51:57 +00:00
|
|
|
direction = 0;
|
|
|
|
|
|
|
|
for (i = 1; i <= gobDestX; i++)
|
|
|
|
if (getPass(gobDestX - i, gobDestY) != 0)
|
|
|
|
break;
|
|
|
|
if (i <= gobDestX)
|
|
|
|
pos1 = ((i - 1) * _tilesWidth) + (mouseX % _tilesWidth) + 1;
|
|
|
|
distance = i;
|
|
|
|
|
|
|
|
for (i = 1; (gobDestX + i) < mapWidth; i++)
|
|
|
|
if (getPass(gobDestX + i, gobDestY) != 0)
|
|
|
|
break;
|
|
|
|
if ((gobDestX + i) < mapWidth)
|
|
|
|
pos2 = (i * _tilesWidth) - (mouseX % _tilesWidth);
|
|
|
|
|
|
|
|
if ((pos2 != -1) && ((pos1 == -1) || (pos1 > pos2))) {
|
|
|
|
pos1 = pos2;
|
|
|
|
direction = 1;
|
|
|
|
distance = i;
|
|
|
|
}
|
|
|
|
pos2 = -1;
|
|
|
|
|
|
|
|
for (i = 1; (gobDestY + i) < mapHeight; i++)
|
|
|
|
if (getPass(gobDestX, gobDestY + i) != 0)
|
|
|
|
break;
|
|
|
|
if ((gobDestY + i) < mapHeight)
|
|
|
|
pos2 = (i * _tilesHeight) - (mouseY % _tilesHeight);
|
|
|
|
|
|
|
|
if ((pos2 != -1) && ((pos1 == -1) || (pos1 > pos2))) {
|
|
|
|
pos1 = pos2;
|
|
|
|
direction = 2;
|
|
|
|
distance = i;
|
|
|
|
}
|
|
|
|
pos2 = -1;
|
|
|
|
|
|
|
|
for (i = 1; i <= gobDestY; i++)
|
|
|
|
if (getPass(gobDestX, gobDestY - i) != 0)
|
|
|
|
break;
|
|
|
|
if (i <= gobDestY)
|
|
|
|
pos2 = ((i - 1) * _tilesHeight) + (mouseY % _tilesHeight) + 1;
|
|
|
|
|
|
|
|
if ((pos2 != -1) && ((pos1 == -1) || (pos1 > pos2))) {
|
|
|
|
direction = 3;
|
|
|
|
distance = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direction == 0)
|
|
|
|
gobDestX -= distance;
|
|
|
|
else if (direction == 1)
|
|
|
|
gobDestX += distance;
|
|
|
|
else if (direction == 2)
|
|
|
|
gobDestY += distance;
|
|
|
|
else if (direction == 3)
|
|
|
|
gobDestY -= distance;
|
|
|
|
}
|
|
|
|
|
2010-10-25 03:38:34 +00:00
|
|
|
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) {
|
2005-04-05 15:07:40 +00:00
|
|
|
|
|
|
|
while (1) {
|
2010-10-25 03:38:34 +00:00
|
|
|
Direction dir = getDirection(x0, y0, x1, y1);
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2006-05-29 18:24:52 +00:00
|
|
|
if (obj) {
|
2010-10-25 03:38:34 +00:00
|
|
|
// Check for a blocking waypoint
|
|
|
|
|
2010-10-25 03:38:12 +00:00
|
|
|
if (obj->nearestWayPoint < obj->nearestDest)
|
2010-10-30 17:26:06 +00:00
|
|
|
if ((obj->nearestWayPoint + 1) < _wayPointCount)
|
2010-10-25 03:38:12 +00:00
|
|
|
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)
|
2007-03-01 14:41:40 +00:00
|
|
|
return 3;
|
2006-05-29 18:24:52 +00:00
|
|
|
}
|
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
if ((x0 == x1) && (y0 == y1))
|
2010-10-25 03:38:34 +00:00
|
|
|
// Successfully reached the destination
|
2005-04-05 15:07:40 +00:00
|
|
|
return 1;
|
|
|
|
|
2010-10-25 03:38:34 +00:00
|
|
|
if (dir == kDirNone)
|
|
|
|
// No way
|
2005-04-05 15:07:40 +00:00
|
|
|
return 3;
|
|
|
|
|
2010-10-25 03:38:34 +00:00
|
|
|
moveDirection(dir, x0, y0);
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-25 03:38:34 +00:00
|
|
|
int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 i1) {
|
2007-03-20 14:51:57 +00:00
|
|
|
int16 curX = x0;
|
|
|
|
int16 curY = y0;
|
|
|
|
int16 nextLink = 1;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
|
|
|
while (1) {
|
2007-03-20 14:51:57 +00:00
|
|
|
if ((x0 == curX) && (y0 == curY))
|
2005-04-05 15:07:40 +00:00
|
|
|
nextLink = 1;
|
|
|
|
|
|
|
|
if (nextLink != 0) {
|
2006-06-07 18:49:20 +00:00
|
|
|
if (checkDirectPath(0, x0, y0, x1, y1) == 1)
|
2005-04-05 15:07:40 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
nextLink = 0;
|
|
|
|
if (i0 > i1) {
|
2006-01-04 01:23:20 +00:00
|
|
|
curX = _wayPoints[i0].x;
|
|
|
|
curY = _wayPoints[i0].y;
|
2005-04-05 15:07:40 +00:00
|
|
|
i0--;
|
|
|
|
} else if (i0 < i1) {
|
2006-01-04 01:23:20 +00:00
|
|
|
curX = _wayPoints[i0].x;
|
|
|
|
curY = _wayPoints[i0].y;
|
2005-04-05 15:07:40 +00:00
|
|
|
i0++;
|
|
|
|
} else if (i0 == i1) {
|
2006-01-04 01:23:20 +00:00
|
|
|
curX = _wayPoints[i0].x;
|
|
|
|
curY = _wayPoints[i0].y;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
2007-03-20 14:51:57 +00:00
|
|
|
if ((i0 == i1) && (_wayPoints[i0].x == x0) &&
|
|
|
|
(_wayPoints[i0].y == y0)) {
|
2006-06-07 18:49:20 +00:00
|
|
|
if (checkDirectPath(0, x0, y0, x1, y1) == 1)
|
2005-04-05 15:07:40 +00:00
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-10-25 03:38:34 +00:00
|
|
|
Direction dir = getDirection(x0, y0, curX, curY);
|
|
|
|
if (dir == kDirNone)
|
|
|
|
// No way
|
|
|
|
return 0;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2010-10-25 03:38:34 +00:00
|
|
|
moveDirection(dir, x0, y0);
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-02 21:54:57 +00:00
|
|
|
void Map::loadMapsInitGobs() {
|
2005-04-05 15:07:40 +00:00
|
|
|
int16 layer;
|
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
if (!_loadFromAvo)
|
2009-05-31 10:02:16 +00:00
|
|
|
error("Map::loadMapsInitGobs(): Loading .pas/.pos files is not supported");
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
for (int i = 0; i < 3; i++)
|
2006-01-07 22:28:54 +00:00
|
|
|
_vm->_goblin->nextLayer(_vm->_goblin->_goblins[i]);
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
for (int i = 0; i < 3; i++) {
|
|
|
|
Goblin::Gob_Object &gob = *_vm->_goblin->_goblins[i];
|
|
|
|
|
|
|
|
layer = gob.stateMach[gob.state][0]->layer;
|
|
|
|
_vm->_scenery->updateAnim(layer, 0, gob.animation, 0,
|
|
|
|
gob.xPos, gob.yPos, 0);
|
|
|
|
gob.yPos = (_vm->_goblin->_gobPositions[i].y + 1) * 6 -
|
|
|
|
(_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
|
|
|
|
gob.xPos = _vm->_goblin->_gobPositions[i].x * 12 -
|
|
|
|
(_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
|
|
|
|
gob.order = _vm->_scenery->_toRedrawBottom / 24 + 3;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2006-01-07 22:28:54 +00:00
|
|
|
_vm->_goblin->_currentGoblin = 0;
|
|
|
|
_vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[0].x;
|
|
|
|
_vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[0].y;
|
|
|
|
_vm->_goblin->_pathExistence = 0;
|
2005-04-05 15:07:40 +00:00
|
|
|
|
2006-01-07 22:28:54 +00:00
|
|
|
_vm->_goblin->_goblins[0]->doAnim = 0;
|
|
|
|
_vm->_goblin->_goblins[1]->doAnim = 1;
|
|
|
|
_vm->_goblin->_goblins[2]->doAnim = 1;
|
2005-04-05 15:07:40 +00:00
|
|
|
}
|
|
|
|
|
2007-03-20 14:51:57 +00:00
|
|
|
} // End of namespace Gob
|