mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 09:21:08 +00:00
288 lines
7.6 KiB
C++
288 lines
7.6 KiB
C++
/* 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.
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include "common/stream.h"
|
|
|
|
#include "gob/gob.h"
|
|
#include "gob/map.h"
|
|
#include "gob/global.h"
|
|
#include "gob/goblin.h"
|
|
#include "gob/inter.h"
|
|
#include "gob/game.h"
|
|
#include "gob/script.h"
|
|
#include "gob/resources.h"
|
|
#include "gob/mult.h"
|
|
|
|
namespace Gob {
|
|
|
|
Map_v2::Map_v2(GobEngine *vm) : Map_v1(vm) {
|
|
_screenHeight = 200;
|
|
}
|
|
|
|
Map_v2::~Map_v2() {
|
|
_passMap = 0;
|
|
}
|
|
|
|
void Map_v2::loadMapObjects(const char *avjFile) {
|
|
uint8 wayPointsCount;
|
|
uint16 var;
|
|
int16 id;
|
|
int16 mapWidth, mapHeight;
|
|
int16 tmp;
|
|
byte *variables;
|
|
uint32 tmpPos;
|
|
uint32 passPos;
|
|
|
|
var = _vm->_game->_script->readVarIndex();
|
|
variables = _vm->_inter->_variables->getAddressOff8(var);
|
|
|
|
id = _vm->_game->_script->readInt16();
|
|
|
|
if (((uint16) id) >= 65520) {
|
|
switch ((uint16) id) {
|
|
case 65530:
|
|
for (int i = 0; i < _mapWidth * _mapHeight; i++)
|
|
_passMap[i] -= READ_VARO_UINT8(var + i);
|
|
break;
|
|
case 65531:
|
|
for (int i = 0; i < _mapWidth * _mapHeight; i++)
|
|
_passMap[i] += READ_VARO_UINT8(var + i);
|
|
break;
|
|
case 65532:
|
|
for (int i = 0; i < _mapWidth * _mapHeight; i++)
|
|
WRITE_VARO_UINT8(var + i, 0x00);
|
|
break;
|
|
case 65533: {
|
|
int index = READ_VARO_UINT16(var);
|
|
// _vm->_mult->_objects[index].field_6E = 0;
|
|
// _vm->_mult->_objects[index].field_6A = variables;
|
|
warning("Map_v2::loadMapObjects(): ID == 65533 (%d)", index);
|
|
break;
|
|
}
|
|
case 65534:
|
|
_tilesWidth = READ_VARO_UINT8(var);
|
|
_tilesHeight = READ_VARO_UINT8(var + 1);
|
|
_mapWidth = READ_VARO_UINT8(var + 2);
|
|
_mapHeight = READ_VARO_UINT8(var + 3);
|
|
_mapUnknownBool = READ_VARO_UINT8(var + 4) ? true : false;
|
|
if (_mapUnknownBool)
|
|
warning("Map_v2::loadMapObjects(): _mapUnknownBool == true");
|
|
break;
|
|
case 65535:
|
|
_passMap = (int8 *)_vm->_inter->_variables->getAddressOff8(var);
|
|
break;
|
|
default:
|
|
warning("Map_v2::loadMapObjects(): ID == %d", (uint16) id);
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
Resource *resource = _vm->_game->_resources->getResource(id);
|
|
if (!resource)
|
|
return;
|
|
|
|
Common::SeekableReadStream &mapData = *resource->stream();
|
|
|
|
_mapVersion = mapData.readByte();
|
|
if (_mapVersion == 4) {
|
|
_screenWidth = 640;
|
|
_screenHeight = 400;
|
|
} else if (_mapVersion == 3) {
|
|
_passWidth = 65;
|
|
_screenWidth = 640;
|
|
_screenHeight = 200;
|
|
} else {
|
|
_passWidth = 40;
|
|
_screenWidth = 320;
|
|
_screenHeight = 200;
|
|
}
|
|
|
|
_wayPointCount = mapData.readByte();
|
|
_tilesWidth = mapData.readSint16LE();
|
|
_tilesHeight = mapData.readSint16LE();
|
|
|
|
_bigTiles = !(_tilesHeight & 0xFF00);
|
|
_tilesHeight &= 0xFF;
|
|
|
|
if (_mapVersion == 4) {
|
|
_screenWidth = mapData.readSint16LE();
|
|
_screenHeight = mapData.readSint16LE();
|
|
}
|
|
|
|
_mapWidth = _screenWidth / _tilesWidth;
|
|
_mapHeight = _screenHeight / _tilesHeight;
|
|
|
|
passPos = mapData.pos();
|
|
mapData.skip(_mapWidth * _mapHeight);
|
|
|
|
if (resource->getData()[0] == 1)
|
|
wayPointsCount = _wayPointCount = 40;
|
|
else
|
|
wayPointsCount = _wayPointCount == 0 ? 1 : _wayPointCount;
|
|
|
|
delete[] _wayPoints;
|
|
_wayPoints = new WayPoint[wayPointsCount];
|
|
for (int i = 0; i < _wayPointCount; i++) {
|
|
_wayPoints[i].x = mapData.readSByte();
|
|
_wayPoints[i].y = mapData.readSByte();
|
|
_wayPoints[i].notWalkable = mapData.readSByte();
|
|
}
|
|
|
|
if (_mapVersion == 4) {
|
|
_mapWidth = VAR(17);
|
|
_passWidth = _mapWidth;
|
|
}
|
|
|
|
// In the original asm, this writes byte-wise into the variables-array
|
|
tmpPos = mapData.pos();
|
|
mapData.seek(passPos);
|
|
if ((variables != 0) &&
|
|
(variables != _vm->_inter->_variables->getAddressOff8(0))) {
|
|
|
|
_passMap = (int8 *)variables;
|
|
mapHeight = _screenHeight / _tilesHeight;
|
|
mapWidth = _screenWidth / _tilesWidth;
|
|
|
|
for (int i = 0; i < mapHeight; i++) {
|
|
for (int j = 0; j < mapWidth; j++)
|
|
setPass(j, i, mapData.readSByte());
|
|
_vm->_inter->_variables->getAddressOff8(var + i * _passWidth);
|
|
}
|
|
}
|
|
mapData.seek(tmpPos);
|
|
|
|
tmp = mapData.readSint16LE();
|
|
mapData.skip(tmp * 14);
|
|
tmp = mapData.readSint16LE();
|
|
mapData.skip(tmp * 14 + 28);
|
|
tmp = mapData.readSint16LE();
|
|
mapData.skip(tmp * 14);
|
|
|
|
_vm->_goblin->_gobsCount = tmp;
|
|
for (int i = 0; i < _vm->_goblin->_gobsCount; i++)
|
|
loadGoblinStates(mapData, i);
|
|
|
|
_vm->_goblin->_soundSlotsCount = _vm->_game->_script->readInt16();
|
|
for (int i = 0; i < _vm->_goblin->_soundSlotsCount; i++)
|
|
_vm->_goblin->_soundSlots[i] = _vm->_inter->loadSound(1);
|
|
|
|
delete resource;
|
|
}
|
|
|
|
void Map_v2::loadGoblinStates(Common::SeekableReadStream &data, int index) {
|
|
Mult::Mult_GobState *statesPtr;
|
|
Mult::Mult_GobState *gobState;
|
|
int8 indices[102];
|
|
uint8 statesCount;
|
|
uint8 dataCount;
|
|
int16 state;
|
|
uint32 tmpPos;
|
|
|
|
memset(indices, -1, 101);
|
|
_vm->_mult->_objects[index].goblinStates = new Mult::Mult_GobState*[101];
|
|
memset(_vm->_mult->_objects[index].goblinStates, 0,
|
|
101 * sizeof(Mult::Mult_GobState *));
|
|
|
|
data.read(indices, 100);
|
|
tmpPos = data.pos();
|
|
statesCount = 0;
|
|
for (int i = 0; i < 100; i++) {
|
|
if (indices[i] != -1) {
|
|
statesCount++;
|
|
data.skip(4);
|
|
dataCount = data.readByte();
|
|
statesCount += dataCount;
|
|
data.skip(dataCount * 9);
|
|
}
|
|
}
|
|
|
|
data.seek(tmpPos);
|
|
|
|
statesPtr = new Mult::Mult_GobState[statesCount];
|
|
_vm->_mult->_objects[index].goblinStates[0] = statesPtr;
|
|
for (int i = 0; i < 100; i++) {
|
|
state = indices[i];
|
|
if (state != -1) {
|
|
_vm->_mult->_objects[index].goblinStates[state] = statesPtr++;
|
|
gobState = _vm->_mult->_objects[index].goblinStates[state];
|
|
|
|
gobState[0].animation = data.readSint16LE();
|
|
gobState[0].layer = data.readSint16LE();
|
|
dataCount = data.readByte();
|
|
gobState[0].dataCount = dataCount;
|
|
for (uint8 j = 1; j <= dataCount; j++) {
|
|
data.skip(1);
|
|
gobState[j].sndItem = data.readSByte();
|
|
data.skip(1);
|
|
gobState[j].sndFrame = data.readByte();
|
|
data.skip(1);
|
|
gobState[j].freq = data.readSint16LE();
|
|
gobState[j].repCount = data.readSByte();
|
|
gobState[j].speaker = data.readByte();
|
|
statesPtr++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Map_v2::findNearestToGob(Mult::Mult_Object *obj) {
|
|
int16 wayPoint = findNearestWayPoint(obj->goblinX, obj->goblinY);
|
|
|
|
if (wayPoint != -1)
|
|
obj->nearestWayPoint = wayPoint;
|
|
}
|
|
|
|
void Map_v2::findNearestToDest(Mult::Mult_Object *obj) {
|
|
int16 wayPoint = findNearestWayPoint(obj->destX, obj->destY);
|
|
|
|
if (wayPoint != -1)
|
|
obj->nearestDest = wayPoint;
|
|
}
|
|
|
|
void Map_v2::optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y) {
|
|
if (!_wayPoints)
|
|
return;
|
|
|
|
if (obj->nearestWayPoint < obj->nearestDest) {
|
|
|
|
for (int i = obj->nearestWayPoint; i <= obj->nearestDest; i++) {
|
|
if (checkDirectPath(obj, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1)
|
|
obj->nearestWayPoint = i;
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = obj->nearestWayPoint; i >= obj->nearestDest; i--) {
|
|
if (_wayPoints[i].notWalkable == 1)
|
|
break;
|
|
|
|
if (checkDirectPath(obj, x, y, _wayPoints[i].x, _wayPoints[i].y) == 1)
|
|
obj->nearestWayPoint = i;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // End of namespace Gob
|