mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-09 03:10:22 +00:00
515 lines
11 KiB
C++
515 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 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 "lastexpress/game/beetle.h"
|
|
|
|
#include "lastexpress/game/inventory.h"
|
|
#include "lastexpress/game/logic.h"
|
|
#include "lastexpress/game/scenes.h"
|
|
#include "lastexpress/game/state.h"
|
|
|
|
#include "lastexpress/helpers.h"
|
|
#include "lastexpress/lastexpress.h"
|
|
#include "lastexpress/resource.h"
|
|
|
|
namespace LastExpress {
|
|
|
|
Beetle::Beetle(LastExpressEngine *engine) : _engine(engine), _data(NULL) {}
|
|
|
|
Beetle::~Beetle() {
|
|
SAFE_DELETE(_data);
|
|
|
|
// Free passed pointers
|
|
_engine = NULL;
|
|
}
|
|
|
|
void Beetle::load() {
|
|
// Only load in chapter 2 & 3
|
|
if (getProgress().chapter != kChapter2 && getProgress().chapter != kChapter3)
|
|
return;
|
|
|
|
// Already loaded
|
|
if (_data)
|
|
return;
|
|
|
|
// Do not load if beetle is in the wrong location
|
|
if (getInventory()->get(kItemBeetle)->location != kObjectLocation3)
|
|
return;
|
|
|
|
///////////////////////
|
|
// Load Beetle data
|
|
_data = new BeetleData();
|
|
|
|
// Load sequences
|
|
_data->sequences.push_back(loadSequence("BW000.seq")); // 0
|
|
_data->sequences.push_back(loadSequence("BT000045.seq"));
|
|
_data->sequences.push_back(loadSequence("BT045000.seq"));
|
|
_data->sequences.push_back(loadSequence("BW045.seq"));
|
|
_data->sequences.push_back(loadSequence("BT045090.seq"));
|
|
_data->sequences.push_back(loadSequence("BT090045.seq")); // 5
|
|
_data->sequences.push_back(loadSequence("BW090.seq"));
|
|
_data->sequences.push_back(loadSequence("BT090135.seq"));
|
|
_data->sequences.push_back(loadSequence("BT135090.seq"));
|
|
_data->sequences.push_back(loadSequence("BW135.seq"));
|
|
_data->sequences.push_back(loadSequence("BT135180.seq")); // 10
|
|
_data->sequences.push_back(loadSequence("BT180135.seq"));
|
|
_data->sequences.push_back(loadSequence("BW180.seq"));
|
|
_data->sequences.push_back(loadSequence("BT180225.seq"));
|
|
_data->sequences.push_back(loadSequence("BT225180.seq"));
|
|
_data->sequences.push_back(loadSequence("BW225.seq")); // 15
|
|
_data->sequences.push_back(loadSequence("BT225270.seq"));
|
|
_data->sequences.push_back(loadSequence("BT270225.seq"));
|
|
_data->sequences.push_back(loadSequence("BW270.seq"));
|
|
_data->sequences.push_back(loadSequence("BT270315.seq"));
|
|
_data->sequences.push_back(loadSequence("BT315270.seq")); // 20
|
|
_data->sequences.push_back(loadSequence("BW315.seq"));
|
|
_data->sequences.push_back(loadSequence("BT315000.seq"));
|
|
_data->sequences.push_back(loadSequence("BT000315.seq"));
|
|
_data->sequences.push_back(loadSequence("BA135.seq"));
|
|
_data->sequences.push_back(loadSequence("BL045.seq")); // 25
|
|
_data->sequences.push_back(loadSequence("BL000.seq"));
|
|
_data->sequences.push_back(loadSequence("BL315.seq"));
|
|
_data->sequences.push_back(loadSequence("BL180.seq"));
|
|
|
|
// Init fields
|
|
_data->field_74 = 0;
|
|
|
|
// Check that all sequences are loaded properly
|
|
_data->isLoaded = true;
|
|
for (int i = 0; i < (int)_data->sequences.size(); i++) {
|
|
if (!_data->sequences[i]->isLoaded()) {
|
|
_data->isLoaded = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
_data->field_D9 = 10;
|
|
_data->coordOffset = 5;
|
|
_data->coordY = 178;
|
|
_data->currentSequence = 0;
|
|
_data->offset = 0;
|
|
_data->frame = NULL;
|
|
_data->field_D5 = 0;
|
|
_data->indexes[0] = 29;
|
|
_data->field_DD = 0;
|
|
}
|
|
|
|
void Beetle::unload() {
|
|
// Remove sequences from display list
|
|
if (_data)
|
|
getScenes()->removeFromQueue(_data->frame);
|
|
|
|
// Delete all loaded sequences
|
|
SAFE_DELETE(_data);
|
|
}
|
|
|
|
bool Beetle::isLoaded() const {
|
|
if (!_data)
|
|
return false;
|
|
|
|
return _data->isLoaded;
|
|
}
|
|
|
|
bool Beetle::catchBeetle() {
|
|
if (!_data)
|
|
error("[Beetle::catchBeetle] Sequences have not been loaded");
|
|
|
|
if (getInventory()->getSelectedItem() == kItemMatchBox
|
|
&& getInventory()->hasItem(kItemMatch)
|
|
&& ABS((int16)(getCoords().x - _data->coordX)) < 10
|
|
&& ABS((int16)(getCoords().y - _data->coordY)) < 10) {
|
|
return true;
|
|
}
|
|
|
|
_data->field_D5 = 0;
|
|
move();
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Beetle::isCatchable() const {
|
|
if (!_data)
|
|
error("[Beetle::isCatchable] Sequences have not been loaded");
|
|
|
|
return (_data->indexes[_data->offset] >= 30);
|
|
}
|
|
|
|
void Beetle::update() {
|
|
if (!_data)
|
|
error("[Beetle::update] Sequences have not been loaded");
|
|
|
|
if (!_data->isLoaded)
|
|
return;
|
|
|
|
move();
|
|
|
|
if (_data->field_D5)
|
|
_data->field_D5--;
|
|
|
|
if (_data->currentSequence && _data->indexes[_data->offset] != 29) {
|
|
drawUpdate();
|
|
return;
|
|
}
|
|
|
|
if (getInventory()->get(kItemBeetle)->location == kObjectLocation3) {
|
|
if ((!_data->field_DD && rnd(10) < 1)
|
|
|| (_data->field_DD && rnd(30) < 1)
|
|
|| rnd(100) < 1) {
|
|
|
|
_data->field_DD++;
|
|
if (_data->field_DD > 3)
|
|
_data->field_DD = 0;
|
|
|
|
updateData(24);
|
|
|
|
_data->coordX = (int16)(rnd(250) + 190);
|
|
_data->coordOffset = (int16)(rnd(5) + 5);
|
|
|
|
if (_data->field_D9 > 1)
|
|
_data->field_D9--;
|
|
|
|
drawUpdate();
|
|
}
|
|
}
|
|
}
|
|
|
|
void Beetle::drawUpdate() {
|
|
if (!_data)
|
|
error("[Beetle::drawUpdate] Sequences have not been loaded");
|
|
|
|
if (_data->frame != NULL) {
|
|
getScenes()->setCoordinates(_data->frame);
|
|
getScenes()->removeFromQueue(_data->frame);
|
|
}
|
|
|
|
// Update current frame
|
|
switch (_data->indexes[_data->offset]) {
|
|
default:
|
|
_data->currentFrame += 10;
|
|
break;
|
|
|
|
case 3:
|
|
case 6:
|
|
case 9:
|
|
case 12:
|
|
case 15:
|
|
case 18:
|
|
case 21:
|
|
case 24:
|
|
case 25:
|
|
case 26:
|
|
case 27:
|
|
case 28:
|
|
_data->currentFrame++;
|
|
break;
|
|
}
|
|
|
|
// Update current sequence
|
|
if (_data->currentSequence->count() <= _data->currentFrame) {
|
|
switch (_data->indexes[_data->offset]) {
|
|
default:
|
|
_data->offset++;
|
|
_data->currentSequence = _data->sequences[_data->indexes[_data->offset]];
|
|
break;
|
|
|
|
case 3:
|
|
case 6:
|
|
case 9:
|
|
case 12:
|
|
case 15:
|
|
case 18:
|
|
case 21:
|
|
break;
|
|
}
|
|
|
|
_data->currentFrame = 0;
|
|
if (_data->indexes[_data->offset] == 29) {
|
|
SAFE_DELETE(_data->frame);
|
|
_data->currentSequence = NULL; // pointer to existing sequence
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Update coordinates
|
|
switch (_data->indexes[_data->offset]) {
|
|
default:
|
|
break;
|
|
|
|
case 0:
|
|
_data->coordY -= _data->coordOffset;
|
|
break;
|
|
|
|
case 3:
|
|
_data->coordX += _data->coordOffset;
|
|
_data->coordY -= _data->coordOffset;
|
|
break;
|
|
|
|
case 6:
|
|
_data->coordX += _data->coordOffset;
|
|
break;
|
|
|
|
case 9:
|
|
_data->coordX += _data->coordOffset;
|
|
_data->coordY += _data->coordOffset;
|
|
break;
|
|
|
|
case 12:
|
|
_data->coordY += _data->coordOffset;
|
|
break;
|
|
|
|
case 15:
|
|
_data->coordX -= _data->coordOffset;
|
|
_data->coordY += _data->coordOffset;
|
|
break;
|
|
|
|
case 18:
|
|
_data->coordX -= _data->coordOffset;
|
|
break;
|
|
|
|
case 21:
|
|
_data->coordX -= _data->coordOffset;
|
|
_data->coordY -= _data->coordOffset;
|
|
break;
|
|
}
|
|
|
|
// Update beetle data
|
|
int rnd = rnd(100);
|
|
if (_data->coordX < 165 || _data->coordX > 465) {
|
|
uint index = 0;
|
|
|
|
if (rnd >= 30) {
|
|
if (rnd >= 70)
|
|
index = (_data->coordX < 165) ? 9 : 15;
|
|
else
|
|
index = (_data->coordX < 165) ? 6 : 18;
|
|
} else {
|
|
index = (_data->coordX < 165) ? 3 : 21;
|
|
}
|
|
|
|
updateData(index);
|
|
}
|
|
|
|
if (_data->coordY < 178) {
|
|
switch (_data->indexes[_data->offset]) {
|
|
default:
|
|
updateData(26);
|
|
break;
|
|
|
|
case 3:
|
|
updateData(25);
|
|
break;
|
|
|
|
case 21:
|
|
updateData(27);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (_data->coordY > 354) {
|
|
switch (_data->indexes[_data->offset]) {
|
|
default:
|
|
break;
|
|
|
|
case 9:
|
|
case 12:
|
|
case 15:
|
|
updateData(28);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#define INVERT_Y() \
|
|
switch (_data->indexes[_data->offset]) { \
|
|
default: \
|
|
break; \
|
|
case 24: \
|
|
case 25: \
|
|
case 26: \
|
|
case 27: \
|
|
case 28: \
|
|
_data->coordY = -_data->coordY; \
|
|
break; \
|
|
}
|
|
|
|
// Invert direction
|
|
INVERT_Y();
|
|
|
|
SequenceFrame *frame = new SequenceFrame(_data->currentSequence, (uint16)_data->currentFrame);
|
|
updateFrame(frame);
|
|
|
|
INVERT_Y();
|
|
|
|
getScenes()->addToQueue(frame);
|
|
|
|
SAFE_DELETE(_data->frame);
|
|
_data->frame = frame;
|
|
}
|
|
|
|
void Beetle::move() {
|
|
if (!_data)
|
|
error("[Beetle::move] Sequences have not been loaded");
|
|
|
|
if (_data->indexes[_data->offset] >= 24 && _data->indexes[_data->offset] <= 29)
|
|
return;
|
|
|
|
if (_data->field_D5)
|
|
return;
|
|
|
|
if (ABS((int)(getCoords().x - _data->coordX)) > 35)
|
|
return;
|
|
|
|
if (ABS((int)(getCoords().y - _data->coordY)) > 35)
|
|
return;
|
|
|
|
int32 deltaX = getCoords().x - _data->coordX;
|
|
int32 deltaY = -getCoords().y - _data->coordY;
|
|
uint32 index = 0;
|
|
|
|
// FIXME: check code path
|
|
if (deltaX >= 0) {
|
|
if (deltaY > 0) {
|
|
if (100 * deltaY - 241 * deltaX <= 0) {
|
|
if (100 * deltaY - 41 * deltaX <= 0)
|
|
index = 18;
|
|
else
|
|
index = 15;
|
|
} else {
|
|
index = 12;
|
|
}
|
|
|
|
goto update_data;
|
|
}
|
|
}
|
|
|
|
if (deltaX < 0) {
|
|
|
|
if (deltaY > 0) {
|
|
if (100 * deltaY + 241 * deltaX <= 0) {
|
|
if (100 * deltaY + 41 * deltaX <= 0)
|
|
index = 6;
|
|
else
|
|
index = 9;
|
|
} else {
|
|
index = 12;
|
|
}
|
|
|
|
goto update_data;
|
|
}
|
|
|
|
if (deltaY <= 0) {
|
|
if (100 * deltaY - 41 * deltaX <= 0) {
|
|
if (100 * deltaY - 241 * deltaX <= 0)
|
|
index = 0;
|
|
else
|
|
index = 3;
|
|
} else {
|
|
index = 6;
|
|
}
|
|
|
|
goto update_data;
|
|
}
|
|
}
|
|
|
|
update_data:
|
|
updateData(index);
|
|
|
|
if (_data->coordOffset >= 15) {
|
|
_data->field_D5 = 0;
|
|
return;
|
|
}
|
|
|
|
_data->coordOffset = _data->coordOffset + (int16)(4 * rnd(100)/100 + _data->field_D9);
|
|
_data->field_D5 = 0;
|
|
}
|
|
|
|
// Update the beetle sequence to show the correct frames in the correct place
|
|
void Beetle::updateFrame(SequenceFrame *frame) const {
|
|
if (!_data)
|
|
error("[Beetle::updateFrame] Sequences have not been loaded");
|
|
|
|
if (!frame)
|
|
return;
|
|
|
|
// Update coordinates
|
|
if (_data->coordX > 0)
|
|
frame->getInfo()->xPos1 = (uint16)_data->coordX;
|
|
|
|
if (_data->coordY > 0)
|
|
frame->getInfo()->yPos1 = (uint16)_data->coordY;
|
|
}
|
|
|
|
void Beetle::updateData(uint32 index) {
|
|
if (!_data)
|
|
error("[Beetle::updateData] Sequences have not been loaded");
|
|
|
|
if (!_data->isLoaded)
|
|
return;
|
|
|
|
if (index == 25 || index == 26 || index == 27 || index == 28) {
|
|
_data->indexes[0] = index;
|
|
_data->indexes[1] = 29;
|
|
_data->offset = 0;
|
|
|
|
_data->currentSequence = _data->sequences[index];
|
|
_data->currentFrame = 0;
|
|
_data->index = index;
|
|
} else {
|
|
if (!_data->sequences[index])
|
|
return;
|
|
|
|
if (_data->index == index)
|
|
return;
|
|
|
|
_data->offset = 0;
|
|
|
|
// Special case for sequence 24
|
|
if (index == 24) {
|
|
_data->indexes[0] = index;
|
|
_data->coordY = 178;
|
|
_data->index = _data->indexes[1];
|
|
_data->indexes[1] = (_data->coordX >= 265) ? 15 : 9;
|
|
_data->currentFrame = 0;
|
|
_data->currentSequence = _data->sequences[index];
|
|
} else {
|
|
if (index <= _data->index) {
|
|
for (uint32 i = _data->index - 1; i > index; ++_data->offset) {
|
|
_data->indexes[_data->offset] = i;
|
|
i -= 3;
|
|
}
|
|
} else {
|
|
for (uint32 i = _data->index + 1; i < index; ++_data->offset) {
|
|
_data->indexes[_data->offset] = i;
|
|
i += 3;
|
|
}
|
|
}
|
|
|
|
_data->index = index;
|
|
_data->indexes[_data->offset] = index;
|
|
_data->currentFrame = 0;
|
|
_data->offset = 0;
|
|
_data->currentSequence = _data->sequences[_data->indexes[0]];
|
|
}
|
|
}
|
|
}
|
|
|
|
} // End of namespace LastExpress
|