scummvm/engines/gob/map_v1.cpp
2021-12-26 18:48:43 +01:00

409 lines
11 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/memstream.h"
#include "gob/gob.h"
#include "gob/map.h"
#include "gob/dataio.h"
#include "gob/goblin.h"
#include "gob/mult.h"
#include "gob/sound/sound.h"
namespace Gob {
Map_v1::Map_v1(GobEngine *vm) : Map(vm) {
}
Map_v1::~Map_v1() {
}
void Map_v1::init() {
if (_passMap || _itemsMap)
return;
_passWidth = 26;
_mapWidth = 26;
_mapHeight = 28;
_passMap = new int8[_mapHeight * _mapWidth]();
_itemsMap = new int16*[_mapHeight];
for (int i = 0; i < _mapHeight; i++) {
_itemsMap[i] = new int16[_mapWidth]();
}
_wayPointCount = 40;
_wayPoints = new WayPoint[40]();
}
void Map_v1::loadMapObjects(const char *avjFile) {
char avoName[128];
byte *dataBuf;
int16 tmp;
int32 flag;
int16 gobDataCount;
int16 objDataCount;
uint32 gobsPos;
uint32 objsPos;
strcpy(avoName, _sourceFile);
strcat(avoName, ".avo");
int32 size;
dataBuf = _vm->_dataIO->getFile(avoName, size);
if (!dataBuf) {
dataBuf = _vm->_dataIO->getFile(avjFile, size);
_loadFromAvo = false;
} else
_loadFromAvo = true;
Common::MemoryReadStream mapData(dataBuf, 4294967295U);
init();
if (_loadFromAvo) {
mapData.read(_passMap, _mapHeight * _mapWidth);
for (int y = 0; y < _mapHeight; y++)
for (int x = 0; x < _mapWidth; x++)
_itemsMap[y][x] = mapData.readSByte();
for (int i = 0; i < 40; i++) {
_wayPoints[i].x = mapData.readUint16LE();
_wayPoints[i].y = mapData.readUint16LE();
}
for (int i = 0; i < 20; i++) {
_itemPoses[i].x = mapData.readByte();
_itemPoses[i].y = mapData.readByte();
_itemPoses[i].orient = mapData.readByte();
}
}
mapData.skip(32 + 76 + 4 + 20);
for (int i = 0; i < 3; i++) {
tmp = mapData.readUint16LE();
mapData.skip(tmp * 14);
}
loadSounds(mapData);
mapData.skip(4 + 24);
gobDataCount = mapData.readUint16LE();
objDataCount = mapData.readUint16LE();
gobsPos = mapData.pos();
Common::MemoryReadStream gobsData(dataBuf + gobsPos, 4294967295U);
mapData.skip(gobDataCount * 8);
objsPos = mapData.pos();
Common::MemoryReadStream objsData(dataBuf + objsPos, 4294967295U);
mapData.skip(objDataCount * 8);
loadGoblins(mapData, gobsPos);
loadObjects(mapData, objsPos);
tmp = mapData.readUint16LE();
for (int i = 0; i < tmp; i++) {
mapData.skip(30);
flag = mapData.readSint32LE();
mapData.skip(56);
if (flag != 0)
mapData.skip(30);
}
mapData.skip(50);
loadItemToObject(mapData);
delete[] dataBuf;
}
void Map_v1::loadSounds(Common::SeekableReadStream &data) {
int16 count;
char buf[19];
char sndNames[20][19];
count = data.readUint16LE();
for (int i = 0; i < count; i++) {
data.read(buf, 14);
buf[14] = 0;
strcat(buf, ".SND");
strcpy(sndNames[i], buf);
}
_vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], SOUND_SND, "diamant1.snd");
for (int i = 0; i < count; i++) {
if (!_vm->_dataIO->hasFile(sndNames[i]))
continue;
_vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], SOUND_SND, sndNames[i]);
}
}
void Map_v1::loadGoblins(Common::SeekableReadStream &data, uint32 gobsPos) {
Goblin::Gob_State *pState;
uint32 tmpStateData[40 * 6];
uint32 tmpPos;
_vm->_goblin->_gobsCount = data.readUint16LE();
for (int i = 0; i < _vm->_goblin->_gobsCount; i++) {
int linesCount = (i == 3) ? 70 : 40;
_vm->_goblin->_goblins[i] = new Goblin::Gob_Object;
memset(_vm->_goblin->_goblins[i], 0, sizeof(Goblin::Gob_Object));
tmpPos = data.pos();
data.seek(gobsPos);
_vm->_goblin->_goblins[i]->xPos = data.readUint16LE();
_vm->_goblin->_goblins[i]->yPos = data.readUint16LE();
_vm->_goblin->_goblins[i]->order = data.readUint16LE();
_vm->_goblin->_goblins[i]->state = data.readUint16LE();
gobsPos = data.pos();
data.seek(tmpPos);
_vm->_goblin->_goblins[i]->stateMach =
new Goblin::Gob_StateLine[linesCount];
for (int state = 0; state < linesCount; ++state)
for (int col = 0; col < 6; ++col)
_vm->_goblin->_goblins[i]->stateMach[state][col] = nullptr;
for (int state = 0; state < 40; ++state)
for (int col = 0; col < 6; ++col)
tmpStateData[state * 6 + col] = data.readUint32LE();
data.skip(160);
_vm->_goblin->_goblins[i]->multObjIndex = data.readByte();
data.skip(1);
_vm->_goblin->_goblins[i]->realStateMach =
_vm->_goblin->_goblins[i]->stateMach;
for (int state = 0; state < 40; state++) {
for (int col = 0; col < 6; col++) {
if (tmpStateData[state * 6 + col] == 0) {
_vm->_goblin->_goblins[i]->stateMach[state][col] = nullptr;
continue;
}
Goblin::Gob_State *tmpState = new Goblin::Gob_State;
memset(tmpState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_goblins[i]->stateMach[state][col] = tmpState;
tmpState->animation = data.readUint16LE();
tmpState->layer = data.readUint16LE();
data.skip(8);
tmpState->unk0 = data.readUint16LE();
tmpState->unk1 = data.readUint16LE();
data.skip(2);
if (data.readUint32LE() == 0) {
data.skip(2);
tmpState->sndItem = -1;
} else
tmpState->sndItem = data.readUint16LE();
tmpState->freq = data.readUint16LE();
tmpState->repCount = data.readUint16LE();
tmpState->sndFrame = data.readUint16LE();
}
}
}
pState = new Goblin::Gob_State;
memset(pState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_goblins[0]->stateMach[39][0] = pState;
pState->layer = 98;
pState->sndItem = -1;
pState = new Goblin::Gob_State;
memset(pState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_goblins[1]->stateMach[39][0] = pState;
pState->layer = 99;
pState->sndItem = -1;
pState = new Goblin::Gob_State;
memset(pState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_goblins[2]->stateMach[39][0] = pState;
pState->layer = 100;
pState->sndItem = -1;
_vm->_goblin->_goblins[2]->stateMach[10][0]->sndFrame = 13;
_vm->_goblin->_goblins[2]->stateMach[11][0]->sndFrame = 13;
_vm->_goblin->_goblins[2]->stateMach[28][0]->sndFrame = 13;
_vm->_goblin->_goblins[2]->stateMach[29][0]->sndFrame = 13;
_vm->_goblin->_goblins[1]->stateMach[10][0]->sndFrame = 13;
_vm->_goblin->_goblins[1]->stateMach[11][0]->sndFrame = 13;
for (int state = 40; state < 70; state++) {
pState = new Goblin::Gob_State;
memset(pState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_goblins[3]->stateMach[state][0] = pState;
_vm->_goblin->_goblins[3]->stateMach[state][1] = nullptr;
pState->animation = 9;
pState->layer = state - 40;
pState->sndItem = -1;
}
}
void Map_v1::loadObjects(Common::SeekableReadStream &data, uint32 objsPos) {
Goblin::Gob_State *pState;
uint32 tmpStateData[40 * 6];
uint32 tmpPos;
_vm->_goblin->_objCount = data.readUint16LE();
for (int i = 0; i < _vm->_goblin->_objCount; i++) {
_vm->_goblin->_objects[i] = new Goblin::Gob_Object;
memset(_vm->_goblin->_objects[i], 0, sizeof(Goblin::Gob_Object));
tmpPos = data.pos();
data.seek(objsPos);
_vm->_goblin->_objects[i]->xPos = data.readUint16LE();
_vm->_goblin->_objects[i]->yPos = data.readUint16LE();
_vm->_goblin->_objects[i]->order = data.readUint16LE();
_vm->_goblin->_objects[i]->state = data.readUint16LE();
objsPos = data.pos();
data.seek(tmpPos);
_vm->_goblin->_objects[i]->stateMach = new Goblin::Gob_StateLine[40];
for (int state = 0; state < 40; ++state) {
for (int col = 0; col < 6; ++col) {
_vm->_goblin->_objects[i]->stateMach[state][col] = nullptr;
tmpStateData[state * 6 + col] = data.readUint32LE();
}
}
data.skip(160);
_vm->_goblin->_objects[i]->multObjIndex = data.readByte();
data.skip(1);
_vm->_goblin->_objects[i]->realStateMach =
_vm->_goblin->_objects[i]->stateMach;
for (int state = 0; state < 40; state++) {
for (int col = 0; col < 6; col++) {
if (tmpStateData[state * 6 + col] == 0) {
_vm->_goblin->_objects[i]->stateMach[state][col] = nullptr;
continue;
}
Goblin::Gob_State *tmpState = new Goblin::Gob_State;
memset(tmpState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_objects[i]->stateMach[state][col] = tmpState;
tmpState->animation = data.readUint16LE();
tmpState->layer = data.readUint16LE();
data.skip(8);
tmpState->unk0 = data.readUint16LE();
tmpState->unk1 = data.readUint16LE();
data.skip(2);
if (data.readUint32LE() == 0) {
data.skip(2);
tmpState->sndItem = -1;
} else
tmpState->sndItem = data.readUint16LE();
tmpState->freq = data.readUint16LE();
tmpState->repCount = data.readUint16LE();
tmpState->sndFrame = data.readUint16LE();
}
}
}
_vm->_goblin->_objects[10] = new Goblin::Gob_Object;
memset(_vm->_goblin->_objects[10], 0, sizeof(Goblin::Gob_Object));
_vm->_goblin->_objects[10]->stateMach = new Goblin::Gob_StateLine[40];
for (int state = 0; state < 40; ++state)
for (int col = 0; col < 6; ++col)
_vm->_goblin->_objects[10]->stateMach[state][col] = nullptr;
pState = new Goblin::Gob_State;
memset(pState, 0, sizeof(Goblin::Gob_State));
_vm->_goblin->_objects[10]->stateMach[0][0] = pState;
pState->animation = 9;
pState->layer = 27;
pState->sndItem = -1;
_vm->_goblin->placeObject(_vm->_goblin->_objects[10], 1, 0, 0, 0, 0);
_vm->_goblin->_objects[10]->realStateMach =
_vm->_goblin->_objects[10]->stateMach;
_vm->_goblin->_objects[10]->type = 1;
_vm->_goblin->_objects[10]->unk14 = 1;
}
void Map_v1::loadItemToObject(Common::SeekableReadStream &data) {
int16 count;
if (data.readUint16LE() == 0)
return;
data.skip(1456);
count = data.readUint16LE();
for (int i = 0; i < count; i++) {
data.skip(20);
_vm->_goblin->_itemToObject[i] = data.readUint16LE();
data.skip(5);
}
}
void Map_v1::optimizePoints(Mult::Mult_Object *obj, int16 x, int16 y) {
if (_nearestWayPoint < _nearestDest) {
for (int i = _nearestWayPoint; i <= _nearestDest; i++) {
if (checkDirectPath(nullptr, _curGoblinX, _curGoblinY,
_wayPoints[i].x, _wayPoints[i].y) == 1)
_nearestWayPoint = i;
}
} else if (_nearestWayPoint > _nearestDest) {
for (int i = _nearestWayPoint; i >= _nearestDest; i--) {
if (checkDirectPath(nullptr, _curGoblinX, _curGoblinY,
_wayPoints[i].x, _wayPoints[i].y) == 1)
_nearestWayPoint = i;
}
}
}
void Map_v1::findNearestToGob(Mult::Mult_Object *obj) {
int16 wayPoint = findNearestWayPoint(_curGoblinX, _curGoblinY);
if (wayPoint != -1)
_nearestWayPoint = wayPoint;
}
void Map_v1::findNearestToDest(Mult::Mult_Object *obj) {
int16 wayPoint = findNearestWayPoint(_destX, _destY);
if (wayPoint != -1)
_nearestDest = wayPoint;
}
} // End of namespace Gob