diff options
Diffstat (limited to 'engines/lastexpress/game/beetle.cpp')
-rw-r--r-- | engines/lastexpress/game/beetle.cpp | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/engines/lastexpress/game/beetle.cpp b/engines/lastexpress/game/beetle.cpp new file mode 100644 index 0000000000..665edb79a5 --- /dev/null +++ b/engines/lastexpress/game/beetle.cpp @@ -0,0 +1,517 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#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::updateSequence: 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 |