scummvm/engines/gob/map.cpp
Sven Hesse 34dae22c1a More goblin handling functions, now the deactivated goblin shows
his boredom. It's the wrong goblin that's deactivated, though.
Also, the entering animation is still missing (now nothing is drawn
instead).

svn-id: r22979
2006-06-07 18:49:20 +00:00

463 lines
8.7 KiB
C++

/* ScummVM - Scumm Interpreter
* Copyright (C) 2004 Ivan Dubrov
* Copyright (C) 2004-2006 The ScummVM project
*
* 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
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* $URL$
* $Id$
*
*/
#include "common/stdafx.h"
#include "common/endian.h"
#include "gob/gob.h"
#include "gob/map.h"
#include "gob/video.h"
#include "gob/util.h"
#include "gob/dataio.h"
#include "gob/inter.h"
#include "gob/goblin.h"
#include "gob/sound.h"
#include "gob/scenery.h"
#include "gob/mult.h"
namespace Gob {
Map::Map(GobEngine *vm) : _vm(vm) {
int i;
_mapWidth = -1;
_mapHeight = -1;
_screenWidth = 0;
_tilesWidth = 0;
_tilesHeight = 0;
_passWidth = 0;
_passMap = 0;
_itemsMap = 0;
_wayPointsCount = 0;
_wayPoints = 0;
_bigTiles = false;
for (i = 0; i < 40; i++) {
_itemPoses[i].x = 0;
_itemPoses[i].y = 0;
_itemPoses[i].orient = 0;
}
_nearestWayPoint = 0;
_nearestDest = 0;
_curGoblinX = 0;
_curGoblinY = 0;
_destX = 0;
_destY = 0;
_loadFromAvo = 0;
_sourceFile[0] = 0;
_avoDataPtr = 0;
}
void Map::placeItem(int16 x, int16 y, int16 id) {
if ((_itemsMap[y][x] & 0xff00) != 0)
_itemsMap[y][x] = (_itemsMap[y][x] & 0xff00) | id;
else
_itemsMap[y][x] = (_itemsMap[y][x] & 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;
if (x0 == x1 && y0 == y1)
return 0;
if (!(x1 >= 0 && x1 < _mapWidth && y1 >= 0 && y1 < _mapHeight))
return 0;
if (y1 > y0)
dir |= kDown;
else if (y1 < y0)
dir |= kUp;
if (x1 > x0)
dir |= kRight;
else if (x1 < x0)
dir |= kLeft;
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;
}
if (getPass(x0, y0) == 6 && (dir & kUp)) {
if (getPass(x0, y0 - 1) != 0)
return kDirN;
}
if (getPass(x0, y0) == 6 && (dir & kDown)) {
if (getPass(x0, y0 + 1) != 0)
return kDirS;
}
if (dir == kLeft) {
if (x0 - 1 >= 0 && getPass(x0 - 1, y0) != 0)
return kDirW;
return 0;
}
if (dir == kRight) {
if (x0 + 1 < _mapWidth && getPass(x0 + 1, y0) != 0)
return kDirE;
return 0;
}
if (dir == kUp) {
if (y0 - 1 >= 0 && getPass(x0, y0 - 1) != 0)
return kDirN;
if (y0 - 1 >= 0 && x0 - 1 >= 0
&& getPass(x0 - 1, y0 - 1) != 0)
return kDirNW;
if (y0 - 1 >= 0 && x0 + 1 < _mapWidth
&& getPass(x0 + 1, y0 - 1) != 0)
return kDirNE;
return 0;
}
if (dir == kDown) {
if (y0 + 1 < _mapHeight && getPass(x0, y0 + 1) != 0)
return kDirS;
if (y0 + 1 < _mapHeight && x0 - 1 >= 0
&& getPass(x0 - 1, y0 + 1) != 0)
return kDirSW;
if (y0 + 1 < _mapHeight && x0 + 1 < _mapWidth
&& getPass(x0 + 1, y0 + 1) != 0)
return kDirSE;
return 0;
}
if (dir == (kRight | kUp)) {
if (y0 - 1 >= 0 && x0 + 1 < _mapWidth
&& getPass(x0 + 1, y0 - 1) != 0)
return kDirNE;
if (y0 - 1 >= 0 && getPass(x0, y0 - 1) != 0)
return kDirN;
if (x0 + 1 < _mapWidth && getPass(x0 + 1, y0) != 0)
return kDirE;
return 0;
}
if (dir == (kRight | kDown)) {
if (x0 + 1 < _mapWidth && y0 + 1 < _mapHeight
&& getPass(x0 + 1, y0 + 1) != 0)
return kDirSE;
if (y0 + 1 < _mapHeight && getPass(x0, y0 + 1) != 0)
return kDirS;
if (x0 + 1 < _mapWidth && getPass(x0 + 1, y0) != 0)
return kDirE;
return 0;
}
if (dir == (kLeft | kUp)) {
if (x0 - 1 >= 0 && y0 - 1 >= 0
&& getPass(x0 - 1, y0 - 1) != 0)
return kDirNW;
if (y0 - 1 >= 0 && getPass(x0, y0 - 1) != 0)
return kDirN;
if (x0 - 1 >= 0 && getPass(x0 - 1, y0) != 0)
return kDirW;
return 0;
}
if (dir == (kLeft | kDown)) {
if (x0 - 1 >= 0 && y0 + 1 < _mapHeight
&& getPass(x0 - 1, y0 + 1) != 0)
return kDirSW;
if (y0 + 1 < _mapHeight && getPass(x0, y0 + 1) != 0)
return kDirS;
if (x0 - 1 >= 0 && getPass(x0 - 1, y0) != 0)
return kDirW;
return 0;
}
return -1;
}
int16 Map::findNearestWayPoint(int16 x, int16 y) {
int16 lnearestWayPoint = -1;
int16 length;
int16 i;
int16 tmp;
length = 30000;
for (i = 0; i < _wayPointsCount; i++) {
if (_wayPoints[i].x < 0 ||
_wayPoints[i].x >= _mapWidth ||
_wayPoints[i].y < 0 || _wayPoints[i].y >= _mapHeight)
return -1;
tmp = ABS(x - _wayPoints[i].x) + ABS(y - _wayPoints[i].y);
if (tmp <= length) {
lnearestWayPoint = i;
length = tmp;
}
}
return lnearestWayPoint;
}
int16 Map::checkDirectPath(Mult::Mult_Object *obj, int16 x0, int16 y0, int16 x1, int16 y1) {
uint16 dir;
while (1) {
dir = getDirection(x0, y0, x1, y1);
if (obj) {
if (obj->nearestWayPoint < obj->nearestDest)
if (_wayPoints[obj->nearestWayPoint + 1].field_2 == 1)
return 3;
if (_wayPoints[obj->nearestDest - 1].field_2 == 1)
return 3;
}
if (x0 == x1 && y0 == y1)
return 1;
if (dir == 0)
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;
}
}
}
int16 Map::checkLongPath(int16 x0, int16 y0, int16 x1, int16 y1, int16 i0, int16 i1) {
uint16 dir;
int16 curX;
int16 curY;
int16 nextLink;
curX = x0;
curY = y0;
dir = 0;
nextLink = 1;
while (1) {
if (x0 == curX && y0 == curY)
nextLink = 1;
if (nextLink != 0) {
if (checkDirectPath(0, x0, y0, x1, y1) == 1)
return 1;
nextLink = 0;
if (i0 > i1) {
curX = _wayPoints[i0].x;
curY = _wayPoints[i0].y;
i0--;
} else if (i0 < i1) {
curX = _wayPoints[i0].x;
curY = _wayPoints[i0].y;
i0++;
} else if (i0 == i1) {
curX = _wayPoints[i0].x;
curY = _wayPoints[i0].y;
}
}
if (i0 == i1 && _wayPoints[i0].x == x0
&& _wayPoints[i0].y == y0) {
if (checkDirectPath(0, x0, y0, x1, y1) == 1)
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;
case kDirSE:
x0++;
y0++;
break;
}
}
}
void Map::loadDataFromAvo(char *dest, int16 size) {
memcpy(dest, _avoDataPtr, size);
_avoDataPtr += size;
}
uint16 Map::loadFromAvo_LE_UINT16() {
uint16 tmp = READ_LE_UINT16(_avoDataPtr);
_avoDataPtr += 2;
return tmp;
}
void Map::loadItemToObject(void) {
int16 flag;
int16 count;
int16 i;
flag = loadFromAvo_LE_UINT16();
if (flag == 0)
return;
_avoDataPtr += 1456;
count = loadFromAvo_LE_UINT16();
for (i = 0; i < count; i++) {
_avoDataPtr += 20;
_vm->_goblin->_itemToObject[i] = loadFromAvo_LE_UINT16();
_avoDataPtr += 5;
}
}
void Map::loadMapsInitGobs(void) {
int16 layer;
int16 i;
if (_loadFromAvo == 0)
error("load: Loading .pas/.pos files is not supported!");
for (i = 0; i < 3; i++) {
_vm->_goblin->nextLayer(_vm->_goblin->_goblins[i]);
}
for (i = 0; i < 3; i++) {
layer =
_vm->_goblin->_goblins[i]->stateMach[_vm->_goblin->_goblins[i]->state][0]->layer;
_vm->_scenery->updateAnim(layer, 0, _vm->_goblin->_goblins[i]->animation, 0,
_vm->_goblin->_goblins[i]->xPos, _vm->_goblin->_goblins[i]->yPos, 0);
_vm->_goblin->_goblins[i]->yPos = (_vm->_goblin->_gobPositions[i].y + 1) * 6 -
(_vm->_scenery->_toRedrawBottom - _vm->_scenery->_animTop);
_vm->_goblin->_goblins[i]->xPos = _vm->_goblin->_gobPositions[i].x * 12 -
(_vm->_scenery->_toRedrawLeft - _vm->_scenery->_animLeft);
_vm->_goblin->_goblins[i]->order = _vm->_scenery->_toRedrawBottom / 24 + 3;
}
_vm->_goblin->_currentGoblin = 0;
_vm->_goblin->_pressedMapX = _vm->_goblin->_gobPositions[0].x;
_vm->_goblin->_pressedMapY = _vm->_goblin->_gobPositions[0].y;
_vm->_goblin->_pathExistence = 0;
_vm->_goblin->_goblins[0]->doAnim = 0;
_vm->_goblin->_goblins[1]->doAnim = 1;
_vm->_goblin->_goblins[2]->doAnim = 1;
}
} // End of namespace Gob