diff options
Diffstat (limited to 'engines/gnap/scenes/arcade.cpp')
-rw-r--r-- | engines/gnap/scenes/arcade.cpp | 2729 |
1 files changed, 2729 insertions, 0 deletions
diff --git a/engines/gnap/scenes/arcade.cpp b/engines/gnap/scenes/arcade.cpp new file mode 100644 index 0000000000..db4999cb43 --- /dev/null +++ b/engines/gnap/scenes/arcade.cpp @@ -0,0 +1,2729 @@ +/* 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 "gnap/gnap.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" +#include "gnap/scenes/arcade.h" + +namespace Gnap { + +static const ObstacleDef kObstacleDefs[] = { + {0xB4, 15}, {0xCB, 14}, {0xCD, 13}, {0xCF, 15}, {0xBA, 14}, + {0xCD, 13}, {0xCF, 12}, {0xCB, 15}, {0xBD, 13}, {0xCF, 12}, + {0xCD, 11}, {0xCB, 15}, {0xB7, 12}, {0xCD, 11}, {0xCB, 10}, + {0xCF, 15}, {0xCF, 14}, {0xBD, 13}, {0xCF, 12}, {0xCD, 11}, + {0xCB, 15}, {0xCB, 13}, {0xB4, 12}, {0xCB, 11}, {0xCD, 10}, + {0xCF, 15}, {0xCD, 12}, {0xBA, 12}, {0xCD, 12}, {0xCF, 12}, + {0xCB, 15}, {0xCB, 9}, {0xCD, 9}, {0xCF, 9}, {0xCD, 9}, + {0xCB, 9}, {0xCD, 9}, {0xCF, 5}, {0xBD, 13}, {0xCF, 8}, + {0xCB, 8}, {0xCD, 15}, {0xB4, 1}, {0xBD, 7}, {0xCF, 7}, + {0xCD, 7}, {0xCB, 7}, {0xCD, 7}, {0xCF, 15}, {0xCF, 15} +}; + +Scene49::Scene49(GnapEngine *vm) : Scene(vm) { + _scoreBarFlash = false; + _scoreBarPos = -1; + _scoreLevel = -1; + _obstacleIndex = -1; + _truckSequenceId = -1; + _truckId = -1; + _truckLaneNum = -1; + + for (int i = 0; i < 5; i++) { + _obstacles[i]._currSequenceId = -1; + _obstacles[i]._closerSequenceId = -1; + _obstacles[i]._passedSequenceId = -1; + _obstacles[i]._splashSequenceId = -1; + _obstacles[i]._collisionSequenceId = -1; + _obstacles[i]._prevId = -1; + _obstacles[i]._currId = -1; + _obstacles[i]._laneNum = -1; + } +} + +int Scene49::init() { + GameSys& gameSys = *_vm->_gameSys; + + gameSys.setAnimation(0, 0, 0); + gameSys.setAnimation(0, 0, 1); + for (int i = 0; i < 5; ++i) + gameSys.setAnimation(0, 0, i + 2); + _vm->_timers[2] = 0; + _vm->_timers[0] = 0; + _vm->_timers[1] = 0; + _vm->clearKeyStatus1(Common::KEYCODE_ESCAPE); + _vm->clearKeyStatus1(Common::KEYCODE_RIGHT); + _vm->clearKeyStatus1(Common::KEYCODE_LEFT); + return 0xD5; +} + +void Scene49::updateHotspots() { + _vm->_hotspotsCount = 0; +} + +void Scene49::checkObstacles() { + if (_vm->_timers[2] == 0) { + if (_vm->_timers[3] == 0) { + for (int i = 0; i < 5; ++i) + clearObstacle(i); + } + + for (int j = 0; j < 5; ++j) { + if (_obstacles[j]._currSequenceId == 0) { + _vm->_timers[3] = 35; + _obstacles[j]._currSequenceId = kObstacleDefs[_obstacleIndex]._sequenceId; + switch (_obstacles[j]._currSequenceId) { + case 0xB4: + _obstacles[j]._laneNum = 1; + _obstacles[j]._closerSequenceId = 180; + _obstacles[j]._passedSequenceId = 181; + _obstacles[j]._splashSequenceId = 182; + _obstacles[j]._collisionSequenceId = 192; + break; + case 0xB7: + _obstacles[j]._laneNum = 2; + _obstacles[j]._closerSequenceId = 183; + _obstacles[j]._passedSequenceId = 184; + _obstacles[j]._splashSequenceId = 185; + _obstacles[j]._collisionSequenceId = 193; + break; + case 0xBD: + _obstacles[j]._laneNum = 3; + _obstacles[j]._closerSequenceId = 189; + _obstacles[j]._passedSequenceId = 190; + _obstacles[j]._splashSequenceId = 191; + _obstacles[j]._collisionSequenceId = 195; + break; + case 0xBA: + _obstacles[j]._laneNum = 2; + _obstacles[j]._closerSequenceId = 186; + _obstacles[j]._passedSequenceId = 187; + _obstacles[j]._splashSequenceId = 188; + _obstacles[j]._collisionSequenceId = 194; + break; + case 0xCB: + _obstacles[j]._laneNum = 1; + _obstacles[j]._closerSequenceId = 203; + _obstacles[j]._passedSequenceId = 204; + _obstacles[j]._splashSequenceId = 0; + _obstacles[j]._collisionSequenceId = 209; + break; + case 0xCD: + _obstacles[j]._laneNum = 2; + _obstacles[j]._closerSequenceId = 205; + _obstacles[j]._passedSequenceId = 206; + _obstacles[j]._splashSequenceId = 0; + _obstacles[j]._collisionSequenceId = 210; + break; + case 0xCF: + _obstacles[j]._laneNum = 3; + _obstacles[j]._closerSequenceId = 207; + _obstacles[j]._passedSequenceId = 208; + _obstacles[j]._splashSequenceId = 0; + _obstacles[j]._collisionSequenceId = 211; + break; + } + _obstacles[j]._prevId = _truckId; + _obstacles[j]._currId = _obstacles[j]._prevId; + _vm->_gameSys->setAnimation(_obstacles[j]._currSequenceId, _obstacles[j]._currId, j + 2); + _vm->_gameSys->insertSequence(_obstacles[j]._currSequenceId, _obstacles[j]._currId, 0, 0, kSeqNone, 0, 0, -50); + _vm->_timers[2] = kObstacleDefs[_obstacleIndex]._ticks; + ++_obstacleIndex; + if (_obstacleIndex == 50) + _obstacleIndex = 0; + break; + } + } + } +} + +void Scene49::updateObstacle(int id) { + GameSys& gameSys = *_vm->_gameSys; + + Scene49Obstacle &obstacle = _obstacles[id]; + obstacle._currId = obstacle._prevId; + + switch (obstacle._laneNum) { + case 1: + obstacle._prevId = _truckId + 1; + break; + case 2: + if (_truckLaneNum != 2 && _truckLaneNum != 3) + obstacle._prevId = _truckId - 1; + else + obstacle._prevId = _truckId + 1; + break; + case 3: + if (_truckLaneNum != 1 && _truckLaneNum != 2) + obstacle._prevId = _truckId; + else + obstacle._prevId = _truckId - 1; + break; + } + + if (obstacle._currSequenceId == obstacle._closerSequenceId) { + if (_truckLaneNum == obstacle._laneNum) { + if (obstacle._splashSequenceId) { + gameSys.setAnimation(obstacle._collisionSequenceId, obstacle._prevId, id + 2); + gameSys.insertSequence(obstacle._collisionSequenceId, obstacle._prevId, + obstacle._currSequenceId, obstacle._currId, + kSeqSyncWait, 0, 0, -50); + obstacle._currSequenceId = obstacle._collisionSequenceId; + _vm->playSound(0xE0, false); + increaseScore(30); + } else if ((obstacle._laneNum == 1 && _truckSequenceId == 0xB0) || + (obstacle._laneNum == 2 && (_truckSequenceId == 0xB1 || _truckSequenceId == 0xB2)) || + (obstacle._laneNum == 3 && _truckSequenceId == 0xB3)) { + gameSys.setAnimation(obstacle._passedSequenceId, obstacle._prevId, id + 2); + gameSys.insertSequence(obstacle._passedSequenceId, obstacle._prevId, + obstacle._currSequenceId, obstacle._currId, + kSeqSyncWait, 0, 0, -50); + obstacle._currSequenceId = obstacle._passedSequenceId; + } else { + gameSys.setAnimation(obstacle._collisionSequenceId, 256, 0); + gameSys.setAnimation(obstacle._passedSequenceId, obstacle._prevId, id + 2); + gameSys.insertSequence(obstacle._passedSequenceId, obstacle._prevId, + obstacle._currSequenceId, obstacle._currId, + kSeqSyncWait, 0, 0, -50); + gameSys.insertSequence(obstacle._collisionSequenceId, 256, + _truckSequenceId, _truckId, + kSeqSyncExists, 0, 0, -50); + _truckSequenceId = obstacle._collisionSequenceId; + _truckId = 256; + obstacle._currSequenceId = obstacle._passedSequenceId; + _vm->playSound(0xE1, false); + decreaseScore(30); + } + } else { + gameSys.setAnimation(obstacle._passedSequenceId, obstacle._prevId, id + 2); + gameSys.insertSequence(obstacle._passedSequenceId, obstacle._prevId, + obstacle._currSequenceId, obstacle._currId, + kSeqSyncWait, 0, 0, -50); + obstacle._currSequenceId = obstacle._passedSequenceId; + } + } else if (obstacle._currSequenceId == obstacle._passedSequenceId) { + if (_truckLaneNum == obstacle._laneNum) { + if (obstacle._splashSequenceId) { + gameSys.setAnimation(obstacle._collisionSequenceId, obstacle._prevId, id + 2); + gameSys.insertSequence(obstacle._collisionSequenceId, obstacle._prevId, + obstacle._currSequenceId, obstacle._currId, + kSeqSyncWait, 0, 0, -50); + obstacle._currSequenceId = obstacle._collisionSequenceId; + _vm->playSound(0xE0, false); + increaseScore(30); + } + } else if (obstacle._splashSequenceId) { + gameSys.setAnimation(obstacle._splashSequenceId, obstacle._prevId, id + 2); + gameSys.insertSequence(obstacle._splashSequenceId, obstacle._prevId, + obstacle._currSequenceId, obstacle._currId, + kSeqSyncWait, 0, 0, -50); + obstacle._currSequenceId = obstacle._splashSequenceId; + } + } else { + gameSys.setAnimation(0, 0, id + 2); + clearObstacle(id); + } +} + +void Scene49::increaseScore(int amount) { + if (_scoreBarPos + amount <= 556) { + _scoreBarPos += amount; + _vm->_gameSys->fillSurface(nullptr, _scoreBarPos, 508, amount, 22, 255, 0, 0); + } + + _scoreLevel = (_scoreBarPos + amount >= 556) ? 1 : 0; +} + +void Scene49::decreaseScore(int amount) { + if (_scoreBarPos >= 226 && _scoreLevel == 0) { + if (_scoreBarFlash) + refreshScoreBar(); + _vm->_gameSys->fillSurface(nullptr, _scoreBarPos, 508, amount, 22, 89, 0, 5); + _scoreBarPos -= amount; + _scoreLevel = 0; + } +} + +void Scene49::refreshScoreBar() { + if (_scoreBarFlash) + _vm->_gameSys->fillSurface(nullptr, 226, 508, 330, 22, 255, 0, 0); + else + _vm->_gameSys->fillSurface(nullptr, 226, 508, 330, 22, 89, 0, 5); + _scoreBarFlash = !_scoreBarFlash; +} + +void Scene49::clearObstacle(int index) { + _obstacles[index]._currSequenceId = 0; + _obstacles[index]._closerSequenceId = 0; + _obstacles[index]._passedSequenceId = 0; + _obstacles[index]._splashSequenceId = 0; + _obstacles[index]._collisionSequenceId = 0; + _obstacles[index]._prevId = 0; + _obstacles[index]._currId = 0; + _obstacles[index]._laneNum = 0; +} + +void Scene49::run() { + GameSys& gameSys = *_vm->_gameSys; + + bool animToggle6 = false; + bool animToggle5 = false; + bool animToggle4 = false; + bool animToggle3 = false; + bool streetAnimToggle = false; + bool bgAnimToggle = false; + + _vm->playSound(0xE2, true); + _vm->setSoundVolume(0xE2, 75); + + _vm->hideCursor(); + _vm->setGrabCursorSprite(-1); + + _scoreBarPos = 196; + _scoreLevel = 0; + _scoreBarFlash = false; + + switch (_vm->getRandom(3)) { + case 0: + _truckSequenceId = 0xAD; + _truckLaneNum = 1; + break; + case 1: + _truckSequenceId = 0xAE; + _truckLaneNum = 2; + break; + case 2: + _truckSequenceId = 0xAF; + _truckLaneNum = 3; + break; + } + + int bgWidth1 = gameSys.getSpriteWidthById(0x5E); + int bgX1 = 600; + + int bgWidth2 = gameSys.getSpriteWidthById(0x5F); + int bgX2 = 400; + + int bgWidth3 = gameSys.getSpriteWidthById(4); + int bgX3 = 700; + + int bgWidth4 = gameSys.getSpriteWidthById(5); + int bgX4 = 500; + + int bgWidth5 = gameSys.getSpriteWidthById(6); + int bgX5 = 300; + + int bgWidth6 = gameSys.getSpriteWidthById(7); + int bgX6 = 100; + + gameSys.setAnimation(0xC8, 251, 1); + gameSys.setAnimation(_truckSequenceId, 256, 0); + gameSys.insertSequence(0xC9, 256, 0, 0, kSeqNone, 0, 600, 85); + gameSys.insertSequence(0xCA, 257, 0, 0, kSeqNone, 0, 400, 100); + gameSys.insertSequence(0xC4, 256, 0, 0, kSeqNone, 0, 700, 140); + gameSys.insertSequence(0xC5, 257, 0, 0, kSeqNone, 0, 500, 160); + gameSys.insertSequence(0xC6, 258, 0, 0, kSeqNone, 0, 300, 140); + gameSys.insertSequence(0xC7, 259, 0, 0, kSeqNone, 0, 100, 140); + gameSys.insertSequence(0xC8, 251, 0, 0, kSeqNone, 0, 0, -50); + gameSys.insertSequence(_truckSequenceId, 256, 0, 0, kSeqNone, 0, 0, -50); + + _vm->_timers[0] = 2; + + for (int i = 0; i < 5; ++i) + clearObstacle(i); + + _obstacleIndex = 0; + + _vm->_timers[2] = _vm->getRandom(20) + 10; + + _truckId = 256; + _vm->_timers[3] = 35; + + while (!_vm->_sceneDone) { + if (_vm->_timers[0] == 0) { + // Update background animations (clouds etc.) + --bgX1; + bgX2 -= 2; + bgX3 -= 5; + --bgX4; + --bgX5; + --bgX6; + if (bgX1 <= -bgWidth1) + bgX1 = 799; + if (bgX2 <= -bgWidth2) + bgX2 = 799; + if (bgX3 <= -bgWidth3) + bgX3 = 799; + if (bgX4 <= -bgWidth4) + bgX4 = 799; + if (bgX5 <= -bgWidth5) + bgX5 = 799; + if (bgX6 <= -bgWidth6) + bgX6 = 799; + bgAnimToggle = !bgAnimToggle; + gameSys.insertSequence(0xC9, (bgAnimToggle ? 1 : 0) + 256, 0xC9, (bgAnimToggle ? 0 : 1) + 256, kSeqSyncWait, 0, bgX1, 85); + gameSys.insertSequence(0xCA, (bgAnimToggle ? 1 : 0) + 257, 0xCA, (bgAnimToggle ? 0 : 1) + 257, kSeqSyncWait, 0, bgX2, 100); + gameSys.insertSequence(0xC4, (bgAnimToggle ? 1 : 0) + 256, 0xC4, (bgAnimToggle ? 0 : 1) + 256, kSeqSyncWait, 0, bgX3, 140); + gameSys.insertSequence(0xC5, (bgAnimToggle ? 1 : 0) + 257, 0xC5, (bgAnimToggle ? 0 : 1) + 257, kSeqSyncWait, 0, bgX4, 160); + gameSys.insertSequence(0xC6, (bgAnimToggle ? 1 : 0) + 258, 0xC6, (bgAnimToggle ? 0 : 1) + 258, kSeqSyncWait, 0, bgX5, 140); + gameSys.insertSequence(0xC7, (bgAnimToggle ? 1 : 0) + 259, 0xC7, (bgAnimToggle ? 0 : 1) + 259, kSeqSyncWait, 0, bgX6, 140); + _vm->_timers[0] = 2; + } + + if (gameSys.getAnimationStatus(1) == 2) { + streetAnimToggle = !streetAnimToggle; + gameSys.setAnimation(0xC8, (streetAnimToggle ? 1 : 0) + 251, 1); + gameSys.insertSequence(0xC8, (streetAnimToggle ? 1 : 0) + 251, 200, (streetAnimToggle ? 0 : 1) + 251, kSeqSyncWait, 0, 0, -50); + } + + checkObstacles(); + + if (gameSys.getAnimationStatus(0) == 2) { + switch (_truckSequenceId) { + case 0xB1: + _truckLaneNum = 1; + break; + case 0xB0: + case 0xB3: + _truckLaneNum = 2; + break; + case 0xB2: + _truckLaneNum = 3; + break; + } + animToggle3 = !animToggle3; + if (_truckLaneNum == 1) { + gameSys.setAnimation(0xAD, (animToggle3 ? 1 : 0) + 256, 0); + gameSys.insertSequence(0xAD, (animToggle3 ? 1 : 0) + 256, _truckSequenceId, _truckId, kSeqSyncWait, 0, 0, -50); + _truckSequenceId = 0xAD; + } else if (_truckLaneNum == 2) { + gameSys.setAnimation(0xAE, (animToggle3 ? 1 : 0) + 256, 0); + gameSys.insertSequence(0xAE, (animToggle3 ? 1 : 0) + 256, _truckSequenceId, _truckId, kSeqSyncWait, 0, 0, -50); + _truckSequenceId = 0xAE; + } else { + gameSys.setAnimation(0xAF, (animToggle3 ? 1 : 0) + 256, 0); + gameSys.insertSequence(0xAF, (animToggle3 ? 1 : 0) + 256, _truckSequenceId, _truckId, kSeqSyncWait, 0, 0, -50); + _truckSequenceId = 0xAF; + } + _truckId = (animToggle3 ? 1 : 0) + 256; + if (_scoreLevel == 1) { + if (!gameSys.isSequenceActive(0xD4, 266)) { + gameSys.setAnimation(0xD4, 266, 8); + gameSys.insertSequence(0xD4, 266, 0, 0, kSeqNone, 0, 0, -50); + } + ++_scoreLevel; + _vm->_timers[1] = 2; + animToggle4 = false; + animToggle5 = false; + animToggle6 = false; + _scoreBarFlash = false; + } + } + + if (_scoreLevel != 0 && !_vm->_timers[1]) { + refreshScoreBar(); + _vm->_timers[1] = 8; + if (animToggle6) { + if (animToggle5) { + if (animToggle4 && !gameSys.isSequenceActive(212, 266)) + gameSys.insertSequence(212, 266, 0, 0, kSeqNone, 0, 0, -50); + animToggle4 = !animToggle4; + } + animToggle5 = !animToggle5; + } + animToggle6 = !animToggle6; + } + + updateAnimations(); + + if (clearKeyStatus()) { + _vm->_sceneDone = true; + _vm->_newSceneNum = 2; + _vm->_newCursorValue = 1; + } + + if (_vm->isKeyStatus1(Common::KEYCODE_RIGHT)) { + // Steer right + if (_truckSequenceId == 0xB3) + _truckLaneNum = 2; + if (_truckSequenceId == 0xB1) + _truckLaneNum = 1; + if (_truckLaneNum != 3 && _truckLaneNum != 2) { + if (_scoreLevel) { + _vm->_sceneDone = true; + _vm->_newSceneNum = 47; + } + } else { + int steerSequenceId = (_truckLaneNum == 3) ? 0xB3 : 0xB1; + if (_truckSequenceId == 0xAE || _truckSequenceId == 0xAF) { + gameSys.setAnimation(steerSequenceId, 256, 0); + gameSys.insertSequence(steerSequenceId, 256, _truckSequenceId, _truckId, kSeqSyncExists, 0, 0, -50); + _truckSequenceId = steerSequenceId; + _truckId = 256; + } + } + _vm->clearKeyStatus1(Common::KEYCODE_RIGHT); + } + + if (_vm->isKeyStatus1(Common::KEYCODE_LEFT)) { + // Steer left + if (_truckSequenceId == 0xB0) + _truckLaneNum = 2; + if (_truckSequenceId == 0xB2) + _truckLaneNum = 3; + if (_truckLaneNum == 1 || _truckLaneNum == 2) { + int steerSequenceId = (_truckLaneNum == 1) ? 0xB0 : 0xB2; + if (_truckSequenceId == 0xAD || _truckSequenceId == 0xAE) { + gameSys.setAnimation(steerSequenceId, 256, 0); + gameSys.insertSequence(steerSequenceId, 256, _truckSequenceId, _truckId, kSeqSyncExists, 0, 0, -50); + _truckSequenceId = steerSequenceId; + _truckId = 256; + } + } + _vm->clearKeyStatus1(Common::KEYCODE_LEFT); + } + _vm->gameUpdateTick(); + } + _vm->stopSound(0xE2); +} + +void Scene49::updateAnimations() { + GameSys& gameSys = *_vm->_gameSys; + + for (int i = 0; i < 5; ++i) { + if (gameSys.getAnimationStatus(i + 2) == 2) { + if (_obstacles[i]._currSequenceId) + updateObstacle(i); + } + } + + if (gameSys.getAnimationStatus(8) == 2) { + _vm->_sceneDone = true; + _vm->_newSceneNum = 47; + } +} + +/*****************************************************************************/ + +Scene50::Scene50(GnapEngine *vm) : Scene(vm) { + _fightDone = false; + + _roundNum = -1; + _timeRemaining = -1; + _leftTongueRoundsWon = -1; + _rightTongueRoundsWon = -1; + _leftTongueSequenceId = -1; + _leftTongueId = -1; + _leftTongueNextSequenceId = -1; + _leftTongueNextId = -1; + _rightTongueSequenceId = -1; + _rightTongueId = -1; + _rightTongueNextSequenceId = -1; + _rightTongueNextId = -1; + _leftTongueEnergy = -1; + _rightTongueEnergy = -1; + + _timesPlayed = 0; + _timesPlayedModifier = 0; + _attackCounter = 0; + _leftTongueEnergyBarPos = 10; + _leftTongueNextIdCtr = 0; + _rightTongueEnergyBarPos = 10; + _rightTongueNextIdCtr = 0; +} + +int Scene50::init() { + return 0xC7; +} + +void Scene50::updateHotspots() { + _vm->_hotspotsCount = 0; +} + +bool Scene50::tongueWinsRound(int tongueNum) { + if (tongueNum == 1) + ++_leftTongueRoundsWon; + else + ++_rightTongueRoundsWon; + playWinBadgeAnim(tongueNum); + bool fightOver = _rightTongueRoundsWon == 2 || _leftTongueRoundsWon == 2; + playWinAnim(tongueNum, fightOver); + return fightOver; +} + +void Scene50::playWinAnim(int tongueNum, bool fightOver) { + if (tongueNum == 1) { + if (fightOver) { + _vm->_gameSys->insertSequence(0xAD, 140, 0xAC, 140, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xB4, 100, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xBD, 100, _rightTongueSequenceId, _rightTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xBC, 100, 0xBD, 100, kSeqSyncWait, 0, 0, 0); + _leftTongueSequenceId = 0xB4; + _rightTongueSequenceId = 0xBC; + _rightTongueId = 100; + _leftTongueId = 100; + _vm->_gameSys->setAnimation(0xB4, 100, 6); + _vm->_gameSys->setAnimation(_rightTongueSequenceId, 100, 5); + waitForAnim(6); + waitForAnim(5); + _vm->invAdd(kItemGum); + _vm->setFlag(kGFUnk13); + } else { + _vm->_gameSys->insertSequence(0xB4, 100, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xBD, 100, _rightTongueSequenceId, _rightTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xBC, 100, 0xBD, 100, kSeqSyncWait, 0, 0, 0); + _leftTongueSequenceId = 0xB4; + _rightTongueSequenceId = 0xBC; + _rightTongueId = 100; + _leftTongueId = 100; + _vm->_gameSys->setAnimation(0xB4, 100, 6); + _vm->_gameSys->setAnimation(_rightTongueSequenceId, 100, 5); + waitForAnim(6); + waitForAnim(5); + } + } else { + _vm->_gameSys->insertSequence(0xBE, 100, _rightTongueSequenceId, _rightTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->setAnimation(0xBE, 100, 5); + waitForAnim(5); + _vm->_gameSys->insertSequence(0xBF, 100, 0xBE, 100, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xB5, 100, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _rightTongueSequenceId = 0xBF; + _leftTongueSequenceId = 0xB5; + _rightTongueId = 100; + _leftTongueId = 100; + _vm->_gameSys->setAnimation(0xB5, 100, 6); + _vm->_gameSys->setAnimation(_rightTongueSequenceId, 100, 5); + waitForAnim(6); + waitForAnim(5); + } + _vm->delayTicksA(1, 7); +} + +void Scene50::delayTicks() { + _vm->delayTicksA(3, 7); +} + +void Scene50::initRound() { + _leftTongueEnergy = 10; + _rightTongueEnergy = 10; + _fightDone = false; + _vm->_timers[3] = getRightTongueActionTicks(); + _vm->_timers[4] = 0; + _vm->_timers[6] = 0; + _vm->_gameSys->fillSurface(nullptr, 91, 73, 260, 30, 212, 0, 0); + _vm->_gameSys->fillSurface(nullptr, 450, 73, 260, 30, 212, 0, 0); + _timeRemaining = 40; + drawCountdown(40); +} + +bool Scene50::updateCountdown() { + if (!_vm->_timers[5]) { + --_timeRemaining; + if (_timeRemaining < 0) { + return true; + } else { + _vm->_timers[5] = 15; + drawCountdown(_timeRemaining); + } + } + return false; +} + +void Scene50::drawCountdown(int value) { + char str[8]; + sprintf(str, "%02d", value); + _vm->_gameSys->fillSurface(nullptr, 371, 505, 50, 27, 0, 0, 0); + _vm->_gameSys->drawTextToSurface(nullptr, 381, 504, 255, 255, 255, str); +} + +void Scene50::playTonguesIdle() { + _vm->_gameSys->insertSequence(0xBA, 100, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xC2, 100, _rightTongueSequenceId, _rightTongueId, kSeqSyncWait, 0, 0, 0); + _leftTongueSequenceId = 0xBA; + _rightTongueSequenceId = 0xC2; + _rightTongueNextSequenceId = -1; + _leftTongueNextSequenceId = -1; + _leftTongueId = 100; + _rightTongueId = 100; + _vm->_gameSys->setAnimation(0xC2, 100, 5); + _vm->_gameSys->setAnimation(_leftTongueSequenceId, _leftTongueId, 6); +} + +void Scene50::playRoundAnim(int roundNum) { + int sequenceId = 0; + + switch (roundNum) { + case 1: + sequenceId = 0xAF; + break; + case 2: + sequenceId = 0xB0; + break; + case 3: + sequenceId = 0xB1; + break; + } + + _vm->_gameSys->insertSequence(sequenceId, 256, 0, 0, kSeqNone, 0, 0, 0); + _vm->_gameSys->setAnimation(sequenceId, 256, 7); + waitForAnim(7); + + _vm->_gameSys->insertSequence(0xAB, 256, sequenceId, 256, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->setAnimation(0xAB, 256, 7); + waitForAnim(7); +} + +bool Scene50::updateEnergyBars(int newLeftBarPos, int newRightBarPos) { + if (newLeftBarPos != _leftTongueEnergyBarPos) { + if (newLeftBarPos < 0) + newLeftBarPos = 0; + _leftTongueEnergyBarPos = newLeftBarPos; + _vm->_gameSys->fillSurface(nullptr, 26 * newLeftBarPos + 91, 73, 260 - 26 * newLeftBarPos, 30, 0, 0, 0); + } + + if (newRightBarPos != _rightTongueEnergyBarPos) { + if (newRightBarPos < 0) + newRightBarPos = 0; + _rightTongueEnergyBarPos = newRightBarPos; + if (newRightBarPos != 10) + _vm->_gameSys->fillSurface(nullptr, 26 * (9 - newRightBarPos) + 450, 73, 26, 30, 0, 0, 0); + } + + if (newLeftBarPos * newRightBarPos > 0) + return false; + + _leftTongueEnergyBarPos = 10; + _rightTongueEnergyBarPos = 10; + return true; +} + +void Scene50::waitForAnim(int animationIndex) { + GameSys& gameSys = *_vm->_gameSys; + + while (gameSys.getAnimationStatus(animationIndex) != 2 && !_vm->_gameDone) + _vm->gameUpdateTick(); + + gameSys.setAnimation(0, 0, animationIndex); +} + +int Scene50::checkInput() { + int sequenceId = -1; + + if (_vm->isKeyStatus1(Common::KEYCODE_RIGHT)) { + _vm->clearKeyStatus1(Common::KEYCODE_RIGHT); + sequenceId = 0xB6; + } else if (_vm->isKeyStatus1(Common::KEYCODE_LEFT)) { + _vm->clearKeyStatus1(Common::KEYCODE_LEFT); + sequenceId = 0xB3; + } else if (_vm->isKeyStatus1(Common::KEYCODE_ESCAPE)) { + _vm->clearKeyStatus1(Common::KEYCODE_ESCAPE); + _fightDone = true; + } + + return sequenceId; +} + +int Scene50::getRightTongueAction() { + int sequenceId = -1; + + if (!_vm->_timers[3]) { + _vm->_timers[3] = getRightTongueActionTicks(); + if (_rightTongueEnergy >= _leftTongueEnergy) { + switch (_vm->getRandom(5)) { + case 0: + sequenceId = 0xBE; + break; + case 1: + sequenceId = 0xBE; + break; + case 2: + sequenceId = 0xBB; + break; + case 3: + sequenceId = 0xBB; + break; + case 4: + sequenceId = 0xBB; + break; + } + } else { + switch (_vm->getRandom(4)) { + case 0: + sequenceId = 0xBE; + break; + case 1: + sequenceId = 0xBB; + break; + case 2: + sequenceId = 0xBE; + break; + case 3: + sequenceId = 0xBE; + break; + } + } + } + + return sequenceId; +} + +void Scene50::updateAnimations() { + if (!_vm->_timers[4]) + _attackCounter = 0; + + if (_vm->_gameSys->getAnimationStatus(5) == 2) { + if (_rightTongueSequenceId == 0xBE) { + if (_leftTongueSequenceId != 0xB3 && _leftTongueSequenceId != 0xB8) + _rightTongueNextSequenceId = 0xBF; + else + _rightTongueNextSequenceId = 0xC0; + } + if (_rightTongueNextSequenceId == -1) + _rightTongueNextSequenceId = 0xC2; + if (_rightTongueNextSequenceId == 0xBF) { + _leftTongueNextId = getLeftTongueNextId(); + _rightTongueNextId = getRightTongueNextId(); + _vm->_gameSys->setAnimation(_rightTongueNextSequenceId, _rightTongueNextId, 5); + _vm->_gameSys->setAnimation(0xB9, _leftTongueNextId, 6); + _vm->_gameSys->insertSequence(_rightTongueNextSequenceId, _rightTongueNextId, _rightTongueSequenceId, _rightTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xB9, _leftTongueNextId, _leftTongueSequenceId, _leftTongueId, kSeqSyncExists, 0, 0, 0); + _rightTongueSequenceId = _rightTongueNextSequenceId; + _rightTongueNextSequenceId = -1; + _leftTongueSequenceId = 0xB9; + _leftTongueNextSequenceId = -1; + _rightTongueId = _rightTongueNextId; + _leftTongueId = _leftTongueNextId; + _leftTongueEnergy -= _vm->getRandom(1) + 1; + } else { + _rightTongueNextId = getRightTongueNextId(); + _vm->_gameSys->setAnimation(_rightTongueNextSequenceId, _rightTongueNextId, 5); + _vm->_gameSys->insertSequence(_rightTongueNextSequenceId, _rightTongueNextId, _rightTongueSequenceId, _rightTongueId, kSeqSyncWait, 0, 0, 0); + _rightTongueSequenceId = _rightTongueNextSequenceId; + _rightTongueNextSequenceId = -1; + _rightTongueId = _rightTongueNextId; + } + } + + if (_vm->_gameSys->getAnimationStatus(6) == 2) { + if (_leftTongueSequenceId == 0xB6) { + ++_attackCounter; + if (_timesPlayedModifier + 3 <= _attackCounter) { + _leftTongueNextSequenceId = 0xB8; + } else { + _vm->_timers[4] = 20; + if (_rightTongueSequenceId != 0xBB && _rightTongueSequenceId != 0xC0 && _vm->getRandom(7) != _roundNum) + _leftTongueNextSequenceId = 0xB7; + else + _leftTongueNextSequenceId = 0xB8; + } + } + if (_leftTongueNextSequenceId == 0xB3) + --_attackCounter; + if (_leftTongueNextSequenceId == -1) + _leftTongueNextSequenceId = 0xBA; + if (_leftTongueNextSequenceId == 0xB7) { + _leftTongueNextId = getLeftTongueNextId(); + _rightTongueNextId = getRightTongueNextId(); + _vm->_gameSys->setAnimation(_leftTongueNextSequenceId, _leftTongueNextId, 6); + _vm->_gameSys->setAnimation(0xC1, _rightTongueNextId, 5); + _vm->_gameSys->insertSequence(_leftTongueNextSequenceId, _leftTongueNextId, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xC1, _rightTongueNextId, _rightTongueSequenceId, _rightTongueId, kSeqSyncExists, 0, 0, 0); + _leftTongueSequenceId = _leftTongueNextSequenceId; + _leftTongueNextSequenceId = -1; + _rightTongueSequenceId = 0xC1; + _rightTongueNextSequenceId = -1; + _rightTongueId = _rightTongueNextId; + _leftTongueId = _leftTongueNextId; + --_rightTongueEnergy; + } else if (_leftTongueNextSequenceId != 0xB8 || _rightTongueSequenceId != 0xC2) { + _leftTongueNextId = getLeftTongueNextId(); + _vm->_gameSys->setAnimation(_leftTongueNextSequenceId, _leftTongueNextId, 6); + _vm->_gameSys->insertSequence(_leftTongueNextSequenceId, _leftTongueNextId, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _leftTongueSequenceId = _leftTongueNextSequenceId; + _leftTongueNextSequenceId = -1; + _leftTongueId = _leftTongueNextId; + } else { + _leftTongueNextId = getLeftTongueNextId(); + _rightTongueNextId = getRightTongueNextId(); + _vm->_gameSys->setAnimation(0xBB, _rightTongueNextId, 5); + _vm->_gameSys->setAnimation(_leftTongueNextSequenceId, _leftTongueNextId, 6); + _vm->_gameSys->insertSequence(_leftTongueNextSequenceId, _leftTongueNextId, _leftTongueSequenceId, _leftTongueId, kSeqSyncWait, 0, 0, 0); + _vm->_gameSys->insertSequence(0xBB, _rightTongueNextId, _rightTongueSequenceId, _rightTongueId, kSeqSyncExists, 0, 0, 0); + _rightTongueSequenceId = 0xBB; + _rightTongueId = _rightTongueNextId; + _rightTongueNextSequenceId = -1; + _leftTongueSequenceId = _leftTongueNextSequenceId; + _leftTongueNextSequenceId = -1; + _leftTongueId = _leftTongueNextId; + } + } +} + +int Scene50::getRightTongueActionTicks() { + return 15 - 5 * _roundNum + 1; +} + +int Scene50::getLeftTongueNextId() { + _leftTongueNextIdCtr = (_leftTongueNextIdCtr + 1) % 3; + return _leftTongueNextIdCtr + 100; +} + +int Scene50::getRightTongueNextId() { + _rightTongueNextIdCtr = (_rightTongueNextIdCtr + 1) % 3; + return _rightTongueNextIdCtr + 100; +} + +void Scene50::playWinBadgeAnim(int tongueNum) { + int sequenceId; + + if (tongueNum == 1) { + if (_leftTongueRoundsWon == 1) + sequenceId = 0xC3; + else + sequenceId = 0xC4; + } else { + if (_rightTongueRoundsWon == 1) + sequenceId = 0xC5; + else + sequenceId = 0xC6; + } + + _vm->_gameSys->setAnimation(sequenceId, 120, 7); + _vm->_gameSys->insertSequence(sequenceId, 120, 0, 0, kSeqNone, 0, 0, 0); + waitForAnim(7); +} + +void Scene50::run() { + ++_timesPlayed; + _timesPlayedModifier = _timesPlayed / 4; + _leftTongueRoundsWon = 0; + _rightTongueRoundsWon = 0; + _leftTongueSequenceId = 186; + _rightTongueSequenceId = 194; + _rightTongueNextSequenceId = -1; + _leftTongueNextSequenceId = -1; + _leftTongueId = 100; + _rightTongueId = 100; + + _vm->_gameSys->setAnimation(194, 100, 5); + _vm->_gameSys->setAnimation(_leftTongueSequenceId, _leftTongueId, 6); + _vm->_gameSys->insertSequence(_leftTongueSequenceId, _leftTongueId, 0, 0, kSeqNone, 0, 0, 0); + _vm->_gameSys->insertSequence(_rightTongueSequenceId, _rightTongueId, 0, 0, kSeqNone, 0, 0, 0); + _vm->_gameSys->insertSequence(172, 140, 0, 0, kSeqNone, 0, 0, 0); + _vm->endSceneInit(); + + initRound(); + + _roundNum = 1; + + _vm->setGrabCursorSprite(-1); + _vm->hideCursor(); + + _vm->delayTicksA(1, 7); + + playRoundAnim(_roundNum); + + _vm->_timers[5] = 15; + + while (!_fightDone && !_vm->_gameDone) { + int playerSequenceId = checkInput(); + if (playerSequenceId != -1) + _leftTongueNextSequenceId = playerSequenceId; + + int rightSequenceId = getRightTongueAction(); + if (rightSequenceId != -1) + _rightTongueNextSequenceId = rightSequenceId; + + updateAnimations(); + + if (updateCountdown() || + updateEnergyBars(_leftTongueEnergy, _rightTongueEnergy)) { + bool v0; + if (_rightTongueEnergy < _leftTongueEnergy) + v0 = tongueWinsRound(1); + else + v0 = tongueWinsRound(2); + if (v0) { + delayTicks(); + _fightDone = true; + } else { + ++_roundNum; + initRound(); + playTonguesIdle(); + updateEnergyBars(_leftTongueEnergy, _rightTongueEnergy); + playRoundAnim(_roundNum); + _vm->_timers[5] = 15; + } + } + _vm->gameUpdateTick(); + } + + _vm->_gameSys->setAnimation(0, 0, 7); + _vm->_gameSys->setAnimation(0, 0, 6); + _vm->_gameSys->setAnimation(0, 0, 5); + _vm->_gameSys->setAnimation(0, 0, 3); + + _vm->showCursor(); +} + +/*****************************************************************************/ + +static const int kDigitSequenceIds[] = { + 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, + 0xCF, 0xD0, 0xD1, 0xD2, 0xD3 +}; + +static const int kDigitPositions[4] = { + 0, 34, 83, 119 +}; + +/* + 0xBA Falling banana peel + 0xBC Banana peel goes away + 0xBD Falling coin + 0xBE Fallen coin + 0xC0 Falling banknote + 0xB6 Platypus tripping (right) + 0xB7 Platypus tripping (left) + 0x76 Platypus jumping (right) +*/ + +Scene51::Scene51(GnapEngine *vm) : Scene(vm) { + _dropLoseCash = false; + + _cashAmount = -1; + _guySequenceId = -1; + _guyNextSequenceId = -1; + _itemsCaughtCtr = -1; + _dropSpeedTicks = -1; + _nextDropItemKind = -1; + _itemInsertX = -1; + _itemInsertDirection = -1; + _platypusSequenceId = -1; + _platypusNextSequenceId = -1; + _platypusJumpSequenceId = -1; + _itemsCtr = -1; + _itemsCtr1 = -1; + _itemsCtr2 = -1; + + for (int i = 0; i < 4; i++) { + _digits[i] = 0; + _digitSequenceIds[i] = -1; + } + + for (int i = 0; i < 6; i++) { + _items[i]._currSequenceId = -1; + _items[i]._droppedSequenceId = 0; + _items[i]._x = 0; + _items[i]._y = 0; + _items[i]._collisionX = 0; + _items[i]._canCatch = false; + _items[i]._isCollision = false; + _items[i]._x2 = 0; + _items[i]._id = -1; + } +} + +int Scene51::init() { + _vm->_gameSys->setAnimation(0, 0, 0); + for (int i = 0; i < 6; ++i) + _vm->_gameSys->setAnimation(0, 0, i + 1); + return 0xD4; +} + +void Scene51::updateHotspots() { + _vm->_hotspotsCount = 0; +} + +void Scene51::clearItem(Scene51Item *item) { + item->_currSequenceId = 0; + item->_droppedSequenceId = 0; + item->_x = 0; + item->_y = 0; + item->_x2 = 0; + item->_collisionX = 0; + item->_canCatch = false; +} + +void Scene51::dropNextItem() { + if (_vm->_timers[0]) + return; + + int index = 0; + while (index < 6 && _items[index]._currSequenceId) + ++index; + + if (index == 6) + return; + + switch (_nextDropItemKind) { + case 0: + if (_vm->getRandom(10) != 0 || _itemsCtr2 >= 2) { + _items[index]._currSequenceId = 0xBD; + } else { + --_itemsCtr1; + _items[index]._currSequenceId = 0xBA; + ++_itemsCtr2; + } + break; + + case 1: + if (_vm->getRandom(8) != 0 || _itemsCtr2 >= 2) { + if (_vm->getRandom(5) == 0) { + if (_itemInsertDirection) + _itemInsertX -= 70; + else + _itemInsertX += 70; + } + _items[index]._currSequenceId = 0xBD; + } else { + --_itemsCtr1; + _items[index]._currSequenceId = 0xBA; + ++_itemsCtr2; + } + break; + + case 2: + if (_vm->getRandom(6) != 0 || _itemsCtr2 >= 2) { + _items[index]._currSequenceId = 0xBD; + } else { + --_itemsCtr1; + _items[index]._currSequenceId = 0xBA; + ++_itemsCtr2; + } + break; + + case 3: + case 4: + if (_itemsCtr == 0) + _itemsCtr1 = 3; + _items[index]._currSequenceId = 0xC0; + break; + + case 5: + case 6: + if (_vm->getRandom(5) != 0 || _itemsCtr2 >= 2) { + if (_vm->getRandom(5) != 0) + _items[index]._currSequenceId = 0xBD; + else + _items[index]._currSequenceId = 0xC0; + } else { + --_itemsCtr1; + _items[index]._currSequenceId = 0xBA; + ++_itemsCtr2; + } + break; + + case 7: + if (_vm->getRandom(5) != 0 || _itemsCtr2 >= 2) { + if (_vm->getRandom(5) == 0) { + if (_itemInsertDirection) + _itemInsertX -= 40; + else + _itemInsertX += 40; + } + if (_vm->getRandom(9) != 0) + _items[index]._currSequenceId = 0xBD; + else + _items[index]._currSequenceId = 0xC0; + } else { + --_itemsCtr1; + _items[index]._currSequenceId = 0xBA; + ++_itemsCtr2; + } + break; + + default: + if (_vm->getRandom(4) != 0 || _itemsCtr2 >= 2) { + if (_vm->getRandom(9) != 0) + _items[index]._currSequenceId = 0xBD; + else + _items[index]._currSequenceId = 0xC0; + } else { + --_itemsCtr1; + _items[index]._currSequenceId = 0xBA; + ++_itemsCtr2; + } + break; + } + + if (_itemInsertDirection) { + _itemInsertX -= 73; + if (_itemInsertX < 129) { + _itemInsertX += 146; + _itemInsertDirection = 0; + } + } else { + _itemInsertX += 73; + if (_itemInsertX > 685) { + _itemInsertX -= 146; + _itemInsertDirection = 1; + } + } + + if (_itemInsertX > 685) + _itemInsertX = 685; + + if (_itemInsertX < 129) + _itemInsertX = 129; + + if (_items[index]._currSequenceId == 0xBA) { + _items[index]._x2 = _vm->getRandom(350) + 200; + _items[index]._x = _items[index]._x2 - 362; + _items[index]._y = 15; + _items[index]._id = 249 - index; + } else { + _items[index]._collisionX = _itemInsertX; + _items[index]._x = _items[index]._collisionX - 395; + if (_items[index]._currSequenceId == 0xC0) + _items[index]._x -= 65; + _items[index]._id = index + 250; + _items[index]._canCatch = true; + } + + _vm->_gameSys->setAnimation(_items[index]._currSequenceId, _items[index]._id, index + 1); + _vm->_gameSys->insertSequence(_items[index]._currSequenceId, _items[index]._id, 0, 0, + kSeqNone, 0, _items[index]._x, _items[index]._y); + + _vm->_timers[0] = _dropSpeedTicks; + + if (_nextDropItemKind >= 3) + _vm->_timers[0] = 20; + + if (_nextDropItemKind >= 5) + _vm->_timers[0] = 5; + + if (_nextDropItemKind == 8) + _vm->_timers[0] = 4; + + ++_itemsCtr; +} + +void Scene51::updateItemAnimations() { + for (int i = 0; i < 6; ++i) { + if (_vm->_gameSys->getAnimationStatus(i + 1) == 2) + updateItemAnimation(&_items[i], i); + } +} + +int Scene51::checkCollision(int sequenceId) { + if (!isJumping(sequenceId)) + return false; + + bool jumpingLeft = false, jumpingRight = false; + int v8 = 0, v4 = 0; + int result = 0; + + bool checkFl = false; + for (int i = 0; i < 6; i++) + checkFl |= _items[i]._isCollision; + + if (!checkFl) + return false; + + if (isJumpingRight(sequenceId)) { + v8 = getPosRight(sequenceId); + v4 = getPosRight(sequenceId + 1); + jumpingRight = true; + } else if (isJumpingLeft(sequenceId)) { + v4 = getPosLeft(sequenceId - 1) + 33; + v8 = getPosLeft(sequenceId) + 33; + jumpingLeft = true; + } + + if (jumpingRight || jumpingLeft) { + int v5 = 0; + int i; + for (i = 0; i < 6; ++i) { + if (_items[i]._isCollision) { + if (jumpingRight && _items[i]._x2 > v8 && _items[i]._x2 < v4) { + v5 = v8 - 359; + if (v5 == 0) + v5 = 1; + _platypusNextSequenceId = 0xB6; + break; + } else if (jumpingLeft && _items[i]._x2 < v4 && _items[i]._x2 > v8) { + v5 = v8 - 344; + if (v5 == 0) + v5 = 1; + _platypusNextSequenceId = 0xB7; + break; + } + } + } + if (v5) { + _vm->_gameSys->setAnimation(0xBC, _items[i]._id, i + 1); + _vm->_gameSys->insertSequence(0xBC, _items[i]._id, _items[i]._currSequenceId, _items[i]._id, kSeqSyncWait, 0, _items[i]._x, 15); + _items[i]._isCollision = false; + _items[i]._currSequenceId = 0xBC; + --_itemsCtr2; + } + result = v5; + } + + return result; +} + +void Scene51::updateItemAnimation(Scene51Item *item, int index) { + + switch (item->_currSequenceId) { + case 0xBD: + case 0xC0: + case 0xC1: + // Falling coin and banknote + if (!itemIsCaught(item)) { + if (_dropLoseCash) { + if (item->_currSequenceId == 0xBD) + _cashAmount -= 2; + else + _cashAmount -= 25; + if (_cashAmount < 0) + _cashAmount = 0; + updateCash(_cashAmount); + } + item->_droppedSequenceId = item->_currSequenceId + 1; + if (item->_currSequenceId != 0xC0) { + item->_canCatch = false; + _dropLoseCash = true; + _itemsCtr = 0; + _vm->_timers[0] = 10; + } + if (item->_droppedSequenceId) { + _vm->_gameSys->setAnimation(item->_droppedSequenceId, item->_id, index + 1); + _vm->_gameSys->insertSequence(item->_droppedSequenceId, item->_id, item->_currSequenceId, item->_id, kSeqSyncWait, 0, item->_x, item->_y); + item->_currSequenceId = item->_droppedSequenceId; + item->_y = 0; + } + } else { + _vm->_gameSys->removeSequence(item->_currSequenceId, item->_id, true); + _vm->_gameSys->setAnimation(0, 0, index + 1); + _vm->playSound(0xDA, false); + if (incCashAmount(item->_currSequenceId) == 1995) { + winMinigame(); + _vm->_sceneDone = true; + } else { + clearItem(item); + ++_itemsCaughtCtr; + if (_itemsCaughtCtr == 5) + --_dropSpeedTicks; + if (_itemsCaughtCtr == 8) + --_dropSpeedTicks; + if (_itemsCaughtCtr == 11) + --_dropSpeedTicks; + if (_itemsCaughtCtr == 14) + --_dropSpeedTicks; + if (_itemsCaughtCtr >= 15 && _dropSpeedTicks > 4) + --_dropSpeedTicks; + if (_itemsCtr1 <= _itemsCaughtCtr) { + ++_nextDropItemKind; + _dropSpeedTicks = 10; + _itemsCtr = 0; + _itemsCtr1 = 20; + _dropLoseCash = false; + _itemsCaughtCtr = 0; + removeCollidedItems(); + } + } + } + break; + + case 0xBE: + // Fallen coin + item->_droppedSequenceId = item->_currSequenceId + 1; + if (item->_droppedSequenceId) { + _vm->_gameSys->setAnimation(item->_droppedSequenceId, item->_id, index + 1); + _vm->_gameSys->insertSequence(item->_droppedSequenceId, item->_id, item->_currSequenceId, item->_id, kSeqSyncWait, 0, item->_x, item->_y); + item->_currSequenceId = item->_droppedSequenceId; + item->_y = 0; + } + break; + + case 0xBF: + case 0xC2: + // Bouncing coin and banknote + _vm->_gameSys->setAnimation(0, 0, index + 1); + _vm->_gameSys->removeSequence(item->_currSequenceId, item->_id, true); + clearItem(item); + break; + + case 0xBA: + // Falling banana peel + item->_droppedSequenceId = 0xBB; + item->_y = 15; + if (item->_droppedSequenceId) { + _vm->_gameSys->setAnimation(item->_droppedSequenceId, item->_id, index + 1); + _vm->_gameSys->insertSequence(item->_droppedSequenceId, item->_id, item->_currSequenceId, item->_id, kSeqSyncWait, 0, item->_x, item->_y); + item->_currSequenceId = item->_droppedSequenceId; + item->_y = 0; + } + break; + + case 0xBB: + item->_isCollision = true; + item->_droppedSequenceId = 0; + _vm->_gameSys->setAnimation(0, 0, index + 1); + break; + + case 0xBC: + _vm->_gameSys->removeSequence(item->_currSequenceId, item->_id, true); + _vm->_gameSys->setAnimation(0, 0, index + 1); + clearItem(item); + break; + + default: + if (item->_droppedSequenceId) { + _vm->_gameSys->setAnimation(item->_droppedSequenceId, item->_id, index + 1); + _vm->_gameSys->insertSequence(item->_droppedSequenceId, item->_id, item->_currSequenceId, item->_id, kSeqSyncWait, 0, item->_x, item->_y); + item->_currSequenceId = item->_droppedSequenceId; + item->_y = 0; + } + break; + } +} + +void Scene51::removeCollidedItems() { + for (int i = 0; i < 6; ++i) { + if (_items[i]._isCollision) { + _vm->_gameSys->removeSequence(_items[i]._currSequenceId, _items[i]._id, true); + _vm->_gameSys->setAnimation(0, 0, i + 1); + clearItem(&_items[i]); + } + } + _itemsCtr2 = 0; +} + +int Scene51::itemIsCaught(Scene51Item *item) { + if (!item->_canCatch) + return 0; + + if (isJumpingRight(_platypusJumpSequenceId)) { + int v4 = getPosRight(_platypusJumpSequenceId) + 97; + if (item->_collisionX < v4 && v4 - item->_collisionX < 56) + return 1; + } else { + int v2 = getPosLeft(_platypusJumpSequenceId); + if (item->_collisionX > v2 && item->_collisionX - v2 < 56) + return 1; + } + + if (item->_currSequenceId == 0xC1) { + int v3 = item->_collisionX + 100; + if (isJumpingRight(_platypusJumpSequenceId)) { + if (ABS(getPosRight(_platypusJumpSequenceId) + 46 - v3) < 56) + return 1; + } else if (ABS(getPosLeft(_platypusJumpSequenceId) + 46 - v3) < 56) { + return 1; + } + } + + return 0; +} + +bool Scene51::isJumpingRight(int sequenceId) { + return sequenceId >= 0x76 && sequenceId <= 0x95; +} + +bool Scene51::isJumpingLeft(int sequenceId) { + return sequenceId >= 0x96 && sequenceId <= 0xB5; +} + +bool Scene51::isJumping(int sequenceId) { + return sequenceId >= 0x76 && sequenceId <= 0xB5; +} + +void Scene51::waitForAnim(int animationIndex) { + while (_vm->_gameSys->getAnimationStatus(animationIndex) != 2 && _vm->_gameDone) { + updateItemAnimations(); + _vm->gameUpdateTick(); + } +} + +int Scene51::getPosRight(int sequenceId) { + static const int kRightPosTbl[] = { + 131, 159, 178, 195, 203, 219, 238, 254, + 246, 274, 293, 310, 318, 334, 353, 369, + 362, 390, 409, 426, 434, 450, 469, 485, + 477, 505, 524, 541, 549, 565, 584, 600 + }; + + if (sequenceId >= 118 && sequenceId <= 149) + return kRightPosTbl[sequenceId - 118]; + return -1; +} + +int Scene51::getPosLeft(int sequenceId) { + static const int kLeftPosTbl[] = { + 580, 566, 550, 536, 526, 504, 488, 469, + 460, 446, 430, 416, 406, 384, 368, 349, + 342, 328, 312, 298, 288, 266, 250, 231, + 220, 206, 190, 176, 166, 144, 128, 109 + }; + + if (sequenceId >= 150 && sequenceId <= 181) + return kLeftPosTbl[sequenceId - 150]; + return -1; +} + +void Scene51::playIntroAnim() { + int soundCtr = 0; + + _platypusSequenceId = 0x76; + _platypusNextSequenceId = 0x76; + + for (int i = 0; i < 6; ++i) + clearItem(&_items[i]); + + _items[0]._currSequenceId = 0xBA; + _items[0]._x2 = 320; + _items[0]._x = -42; + _items[0]._y = 15; + _items[0]._id = 249; + _items[0]._isCollision = true; + + _vm->_gameSys->insertSequence(_platypusSequenceId, 256, 0, 0, kSeqNone, 0, -179, 0); + _vm->_gameSys->insertSequence(0xBA, 249, 0, 0, kSeqNone, 0, _items[0]._x, _items[0]._y); + _vm->_gameSys->setAnimation(0xBA, 249, 1); + _vm->_gameSys->setAnimation(_platypusSequenceId, 256, 0); + + while (_platypusSequenceId < 0x80) { + waitForAnim(0); + ++_platypusNextSequenceId; + _vm->_gameSys->setAnimation(_platypusNextSequenceId, 256, 0); + _vm->_gameSys->insertSequence(_platypusNextSequenceId, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, -179, 0); + _platypusSequenceId = _platypusNextSequenceId; + ++soundCtr; + if (soundCtr % 4 == 0) + _vm->playSound(0xD6, false); + } + + _platypusNextSequenceId = 0x75; + + while (_platypusSequenceId != 0x84) { + waitForAnim(0); + ++_platypusNextSequenceId; + int oldSequenceId = _platypusNextSequenceId; + int v0 = checkCollision(_platypusNextSequenceId); + _vm->_gameSys->setAnimation(_platypusNextSequenceId, 256, 0); + _vm->_gameSys->insertSequence(_platypusNextSequenceId, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, v0, 0); + _platypusSequenceId = _platypusNextSequenceId; + if (v0) { + _platypusNextSequenceId = oldSequenceId; + } else { + ++soundCtr; + if (soundCtr % 4 == 0) + _vm->playSound(0xD6, false); + } + } + waitForAnim(0); +} + +void Scene51::updateGuyAnimation() { + if (!_vm->_timers[4]) { + _vm->_timers[4] = _vm->getRandom(20) + 60; + + switch (_vm->getRandom(5)) { + case 0: + _guyNextSequenceId = 0xC3; + break; + case 1: + _guyNextSequenceId = 0xC4; + break; + case 2: + _guyNextSequenceId = 0xC5; + break; + case 3: + _guyNextSequenceId = 0xC6; + break; + case 4: + _guyNextSequenceId = 0xC7; + break; + } + + _vm->_gameSys->insertSequence(_guyNextSequenceId, 39, _guySequenceId, 39, kSeqSyncWait, 0, 0, 0); + _guySequenceId = _guyNextSequenceId; + _guyNextSequenceId = -1; + } +} + +int Scene51::incCashAmount(int sequenceId) { + switch (sequenceId) { + case 0xBD: + _cashAmount += 10; + break; + case 0xC0: + case 0xC1: + _cashAmount += 100; + break; + case 0xB6: + case 0xB7: + _cashAmount -= 10 * _vm->getRandom(5) + 50; + if (_cashAmount < 0) + _cashAmount = 0; + break; + } + if (_cashAmount > 1995) + _cashAmount = 1995; + updateCash(_cashAmount); + return _cashAmount; +} + +void Scene51::winMinigame() { + updateCash(1995); + _vm->playSound(0xDA, false); + _vm->delayTicksA(1, 5); + _vm->_newSceneNum = 48; + _vm->invRemove(kItemBanana); +} + +void Scene51::playCashAppearAnim() { + _vm->_gameSys->setAnimation(0xC8, 252, 0); + _vm->_gameSys->insertSequence(0xC8, 252, 0, 0, kSeqNone, 0, -20, -20); + + while (_vm->_gameSys->getAnimationStatus(0) != 2 && !_vm->_gameDone) + _vm->gameUpdateTick(); +} + +void Scene51::updateCash(int amount) { + drawDigit(amount / 1000, 0); + drawDigit(amount / 100 % 10, 1); + drawDigit(amount / 10 % 10, 2); + drawDigit(amount % 10, 3); +} + +void Scene51::drawDigit(int digit, int position) { + if (digit != _digits[position]) { + _vm->_gameSys->insertSequence(kDigitSequenceIds[digit], 253 + position, + _digitSequenceIds[position], 253 + position, + kSeqSyncWait, 0, kDigitPositions[position] - 20, -20); + _digitSequenceIds[position] = kDigitSequenceIds[digit]; + _digits[position] = digit; + } +} + +void Scene51::initCashDisplay() { + for (int position = 0; position < 4; ++position) { + _digits[position] = 0; + _digitSequenceIds[position] = kDigitSequenceIds[0]; + _vm->_gameSys->insertSequence(kDigitSequenceIds[0], 253 + position, 0, 0, kSeqNone, 0, kDigitPositions[position] - 20, -20); + } + _cashAmount = 0; +} + +void Scene51::run() { + int soundCtr = 0; + bool isIdle = true; + + _itemsCtr = 0; + _vm->_newSceneNum = _vm->_prevSceneNum; + _cashAmount = 0; + _platypusJumpSequenceId = 0x84; + _vm->endSceneInit(); + + _vm->hideCursor(); + _vm->setGrabCursorSprite(-1); + + _guySequenceId = 0xC3; + _guyNextSequenceId = -1; + + _vm->_gameSys->insertSequence(0xC3, 39, 0, 0, kSeqNone, 0, 0, 0); + _vm->_timers[4] = _vm->getRandom(20) + 60; + + playCashAppearAnim(); + initCashDisplay(); + playIntroAnim(); + + _platypusNextSequenceId = 0x74; + _vm->_gameSys->setAnimation(0x74, 256, 0); + _vm->_gameSys->insertSequence(_platypusNextSequenceId, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosRight(_platypusJumpSequenceId) - 362, 0); + _platypusSequenceId = _platypusNextSequenceId; + + _itemInsertDirection = 0; + _itemInsertX = 685; + _dropSpeedTicks = 10; + _nextDropItemKind = 0; + + for (int i = 0; i < 6; ++i) + clearItem(&_items[i]); + + _itemInsertX = _vm->getRandom(556) + 129; + _vm->_timers[0] = 15; + + _itemsCaughtCtr = 0; + _dropLoseCash = false; + _itemsCtr1 = 20; + + _vm->clearKeyStatus1(Common::KEYCODE_RIGHT); + _vm->clearKeyStatus1(Common::KEYCODE_LEFT); + _vm->clearKeyStatus1(Common::KEYCODE_UP); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + _vm->clearKeyStatus1(Common::KEYCODE_ESCAPE); + + bool isCollision = false; + bool startWalk = true; + + while (!_vm->_sceneDone) { + if (clearKeyStatus()) + _vm->_sceneDone = true; + + _vm->gameUpdateTick(); + + updateGuyAnimation(); + dropNextItem(); + updateItemAnimations(); + + if (_vm->isKeyStatus2(Common::KEYCODE_UP) || _vm->isKeyStatus2(Common::KEYCODE_SPACE)) { + _vm->clearKeyStatus1(Common::KEYCODE_UP); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + if (isJumpingRight(_platypusJumpSequenceId)) { + waitForAnim(0); + _vm->_gameSys->setAnimation(0xB8, 256, 0); + _vm->_gameSys->insertSequence(0xB8, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosRight(_platypusJumpSequenceId) - 348, 0); + _platypusSequenceId = 0xB8; + waitForAnim(0); + _platypusNextSequenceId += 6; + if (_platypusNextSequenceId > 0x95) + _platypusNextSequenceId = 0x95; + _platypusJumpSequenceId = _platypusNextSequenceId; + } else { + waitForAnim(0); + _vm->_gameSys->setAnimation(0xB9, 256, 0); + _vm->_gameSys->insertSequence(0xB9, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosLeft(_platypusJumpSequenceId) - 338, 0); + _platypusSequenceId = 0xB9; + waitForAnim(0); + _platypusNextSequenceId += 6; + if (_platypusNextSequenceId > 0xB5) + _platypusNextSequenceId = 0xB5; + _platypusJumpSequenceId = _platypusNextSequenceId; + } + isIdle = false; + } + + while (_vm->isKeyStatus2(Common::KEYCODE_RIGHT) && _platypusNextSequenceId != 0x96 && !_vm->_gameDone) { + if (_platypusNextSequenceId == 0xB6) + _platypusNextSequenceId = 0x76; + updateItemAnimations(); + if (startWalk) { + _platypusNextSequenceId = 0x86; + startWalk = false; + } + + if (_vm->_gameSys->getAnimationStatus(0) == 2) { + int collisionX = checkCollision(_platypusNextSequenceId); + if (collisionX) + incCashAmount(_platypusNextSequenceId); + _vm->_gameSys->setAnimation(_platypusNextSequenceId, 256, 0); + _vm->_gameSys->insertSequence(_platypusNextSequenceId, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, collisionX, 0); + _platypusSequenceId = _platypusNextSequenceId; + if (collisionX) { + isCollision = true; + ++_platypusJumpSequenceId; + _platypusNextSequenceId = _platypusJumpSequenceId; + } else { + _platypusJumpSequenceId = _platypusNextSequenceId; + } + if (isJumpingRight(_platypusJumpSequenceId)) { + ++_platypusNextSequenceId; + if (!isCollision) { + if (_vm->isKeyStatus2(Common::KEYCODE_UP) || _vm->isKeyStatus2(Common::KEYCODE_SPACE)) { + _vm->clearKeyStatus1(Common::KEYCODE_UP); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + waitForAnim(0); + _vm->_gameSys->setAnimation(0xB8, 256, 0); + _vm->_gameSys->insertSequence(0xB8, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosRight(_platypusJumpSequenceId) - 348, 0); + _platypusSequenceId = 0xB8; + waitForAnim(0); + _platypusNextSequenceId += 6; + if (_platypusNextSequenceId > 0x95) + _platypusNextSequenceId = 0x95; + _platypusJumpSequenceId = _platypusNextSequenceId; + } else { + ++soundCtr; + if (soundCtr % 4 == 0) + _vm->playSound(0xD6, false); + } + } + } else { + _platypusNextSequenceId = 150 - (_platypusJumpSequenceId - 150); + } + isCollision = false; + isIdle = false; + } + _vm->gameUpdateTick(); + } + + while (_vm->isKeyStatus2(Common::KEYCODE_LEFT) && _platypusNextSequenceId != 0xB6 && !_vm->_gameDone) { + updateItemAnimations(); + if (startWalk) { + _platypusNextSequenceId = 0xA5; + startWalk = false; + } + + if (_vm->_gameSys->getAnimationStatus(0) == 2) { + int collisionX = checkCollision(_platypusNextSequenceId); + if (collisionX) + incCashAmount(_platypusNextSequenceId); + _vm->_gameSys->setAnimation(_platypusNextSequenceId, 256, 0); + _vm->_gameSys->insertSequence(_platypusNextSequenceId, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, collisionX, 0); + _platypusSequenceId = _platypusNextSequenceId; + if (collisionX) { + isCollision = true; + ++_platypusJumpSequenceId; + _platypusNextSequenceId = _platypusJumpSequenceId; + } else { + _platypusJumpSequenceId = _platypusNextSequenceId; + } + if (isJumpingLeft(_platypusJumpSequenceId)) { + ++_platypusNextSequenceId; + if (!isCollision) { + if (_vm->isKeyStatus2(Common::KEYCODE_UP) || _vm->isKeyStatus2(Common::KEYCODE_SPACE)) { + _vm->clearKeyStatus1(Common::KEYCODE_UP); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + waitForAnim(0); + _vm->_gameSys->setAnimation(0xB9, 256, 0); + _vm->_gameSys->insertSequence(0xB9, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosLeft(_platypusJumpSequenceId) - 338, 0); + _platypusSequenceId = 0xB9; + waitForAnim(0); + _platypusNextSequenceId += 6; + if (_platypusNextSequenceId > 0xB5) + _platypusNextSequenceId = 0xB5; + _platypusJumpSequenceId = _platypusNextSequenceId; + } else { + ++soundCtr; + if (soundCtr % 4 == 0) + _vm->playSound(0xD6, false); + } + } + } else { + _platypusNextSequenceId = 182 - (_platypusJumpSequenceId - 118); + } + isCollision = false; + isIdle = false; + } + _vm->gameUpdateTick(); + } + + if (!isIdle && _vm->_gameSys->getAnimationStatus(0) == 2) { + if (isJumpingRight(_platypusJumpSequenceId)) { + _vm->_gameSys->setAnimation(0x74, 256, 0); + _vm->_gameSys->insertSequence(0x74, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosRight(_platypusJumpSequenceId) - 362, 0); + _platypusSequenceId = 0x74; + } else { + _vm->_gameSys->setAnimation(0x75, 256, 0); + _vm->_gameSys->insertSequence(0x75, 256, _platypusSequenceId, 256, kSeqSyncWait, 0, getPosLeft(_platypusJumpSequenceId) - 341, 0); + _platypusSequenceId = 0x75; + } + waitForAnim(0); + isIdle = true; + } + } + + _vm->clearKeyStatus1(Common::KEYCODE_ESCAPE); + _vm->clearKeyStatus1(Common::KEYCODE_UP); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + _vm->clearKeyStatus1(Common::KEYCODE_RIGHT); + _vm->clearKeyStatus1(Common::KEYCODE_LEFT); + + _vm->_gameSys->setAnimation(0, 0, 0); + for (int i = 0; i < 6; ++i) + _vm->_gameSys->setAnimation(0, 0, i + 1); + + _vm->showCursor(); +} + +/*****************************************************************************/ + +Scene52::Scene52(GnapEngine *vm) : Scene(vm) { + _gameScore = 0; + _aliensInitialized = false; + _alienDirection = 0; + _soundToggle = false; + _arcadeScreenBottom = 0; + _shipsLeft = 0; + _shipPosX = 0; + _shipCannonPosX = 0; + _shipCannonPosY = 0; + _shipCannonFiring = false; + _shipCannonFired = false; + _shipCannonWidth = 0; + _shipCannonHeight = 0; + _shipCannonTopY = 0; + _shipMidX = 0; + _shipMidY = 0; + _shipFlag = false; + _alienSpeed = 0; + _alienWidth = 0; + _alienHeight = 0; + _alienLeftX = 0; + _alienTopY = 0; + _alienRowDownCtr = 0; + _alienWave = false; + _alienSingle = false; + _alienCounter = 0; + _bottomAlienFlag = false; + _aliensCount = 0; + _nextUfoSequenceId = -1; + _ufoSequenceId = -1; + _liveAlienRows = 0; +} + +int Scene52::init() { + initAnims(); + return 0x2B; +} + +void Scene52::updateHotspots() { + _vm->_hotspotsCount = 0; +} + +void Scene52::update() { + for (int rowNum = 0; rowNum < 7 && !_vm->_gameDone; ++rowNum) { + _vm->gameUpdateTick(); + if (_vm->_gameSys->getAnimationStatus(_alienRowAnims[rowNum]) == 2) { + updateAlienRow(rowNum); + rowNum = 0; + } + } + + if (_liveAlienRows == 0 && !_alienSingle) { + _alienWave = false; + _vm->playSound(0x30, false); + ++_alienCounter; + if (_alienCounter != 3) { + _vm->_timers[0] = 50; + _vm->_timers[2] = 100; + _alienRowDownCtr = 0; + _alienSingle = true; + } + } + + if (_alienSingle && !_vm->_timers[0]) { + initAliens(); + _alienSingle = false; + _vm->_timers[2] = 5; + _alienWave = true; + } + + if ((_alienRowDownCtr || _liveAlienRows == 0) && !_alienSingle) { + moveDownAlienRow(); + _alienRowDownCtr = 0; + } + + if (_vm->isKeyStatus1(Common::KEYCODE_UP) || _vm->isKeyStatus1(Common::KEYCODE_SPACE)) { + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + _vm->clearKeyStatus1(Common::KEYCODE_UP); + if (!_aliensCount) + fireShipCannon(_shipPosX); + } + + if (_shipCannonFiring) + updateShipCannon(); + + fireAlienCannon(); + updateAlienCannons(); + + if (_aliensCount == 1) { + _alienWave = false; + _vm->_timers[3] = 20; + _vm->_timers[2] = 100; + ++_aliensCount; + } + + if (_aliensCount && !_vm->_timers[3]) { + updateAliens(); + loseShip(); + if (_shipsLeft != 0) { + _vm->_timers[3] = 40; + while (_vm->_timers[3] && !_vm->_gameDone) { + updateAlienCannons(); + if (_shipCannonFiring) + updateShipCannon(); + _vm->gameUpdateTick(); + } + initAliens(); + _shipPosX = (800 - _shipMidX) / 2; + _vm->_gameSys->setAnimation(_nextUfoSequenceId, 256, 7); + _vm->_gameSys->insertSequence(_nextUfoSequenceId, 256, 0, 0, kSeqNone, 0, _shipPosX, _arcadeScreenBottom); + _ufoSequenceId = _nextUfoSequenceId; + _vm->_timers[2] = 5; + _alienWave = true; + } else { + _vm->_sceneDone = true; + } + } + + _nextUfoSequenceId = 34; + if (_ufoSequenceId != 34) + _shipFlag = true; + + if (_shipFlag) { + if (_vm->_gameSys->getAnimationStatus(7) == 2) { + _vm->_gameSys->setAnimation(_nextUfoSequenceId, 256, 7); + _vm->_gameSys->insertSequence(_nextUfoSequenceId, 256, _ufoSequenceId, 256, kSeqSyncWait, 0, _shipPosX, _arcadeScreenBottom); + _ufoSequenceId = _nextUfoSequenceId; + } + _shipFlag = false; + } + + if (_alienWave && !_vm->_timers[0]) { + playSound(); + int delay = CLIP(_alienSpeed, 2, 10); + _vm->_timers[0] = delay; + } +} + +void Scene52::initShipCannon(int bottomY) { + _shipCannonFired = false; + _shipCannonWidth = MAX(_vm->_gameSys->getSpriteWidthById(14), _vm->_gameSys->getSpriteWidthById(16)); + _shipCannonHeight = MAX(_vm->_gameSys->getSpriteHeightById(14), _vm->_gameSys->getSpriteHeightById(16)); + _shipCannonTopY = bottomY - _shipCannonHeight; + _shipCannonFiring = false; +} + +void Scene52::initAlienCannons() { + for (int i = 0; i < 3; ++i) { + _alienCannonIds[i] = 0; + _alienCannonFired[i] = 0; + } + _alienCannonSequenceIds[0] = 30; + _alienCannonSequenceIds[1] = 31; + _alienCannonSequenceIds[2] = 32; +} + +void Scene52::fireShipCannon(int posX) { + if (_vm->_timers[1]) + return; + + int cannonNum = getFreeShipCannon(); + if (cannonNum != -1) { + _shipCannonPosX = _shipMidX / 2 + posX - _shipCannonWidth / 2; + _shipCannonPosY = _shipCannonTopY; + _vm->_gameSys->setAnimation(0x23, cannonNum + 256, cannonNum + 8); + _vm->_gameSys->insertSequence(0x23, cannonNum + 256, 0, 0, kSeqNone, 0, _shipCannonPosX, _shipCannonPosY); + _vm->playSound(0x2D, false); + if (shipCannonHitShield(cannonNum)) { + _vm->_gameSys->setAnimation(0, 0, cannonNum + 8); + _vm->_gameSys->removeSequence(0x23, cannonNum + 256, true); + } else { + _shipCannonFired = true; + _shipCannonPosY -= 13; + _shipCannonFiring = true; + } + _vm->_timers[1] = 5; + } +} + +void Scene52::fireAlienCannon() { + if (_vm->_timers[2]) + return; + + int cannonNum = getFreeAlienCannon(); + if (cannonNum != -1) { + int alienX1 = _alienLeftX + _alienRowXOfs[0]; + int alienX2 = _alienLeftX + _alienRowXOfs[0] + 5 * _alienWidth - (_alienWidth / 2 - 15); + _alienCannonPosX[cannonNum] = _vm->getRandom(alienX2 - alienX1) + alienX1; + _alienCannonPosY[cannonNum] = 104; + _alienCannonFired[cannonNum] = 1; + _vm->_gameSys->setAnimation(_alienCannonSequenceIds[cannonNum], _alienCannonIds[cannonNum] + 256, cannonNum + 9); + _vm->_gameSys->insertSequence(_alienCannonSequenceIds[cannonNum], _alienCannonIds[cannonNum] + 256, 0, 0, + kSeqNone, 0, _alienCannonPosX[cannonNum], _alienCannonPosY[cannonNum]); + _alienCannonPosY[cannonNum] -= 13; + _vm->_timers[2] = 5; + } +} + +int Scene52::getFreeShipCannon() { + if (!_shipCannonFired) + return 0; + return -1; +} + +int Scene52::getFreeAlienCannon() { + for (int i = 0; i < 3; ++i) + if (!_alienCannonFired[i]) + return i; + return -1; +} + +void Scene52::updateShipCannon() { + if (_shipCannonFired && _vm->_gameSys->getAnimationStatus(8) == 2) { + _shipCannonPosY -= 13; + if (_shipCannonPosY - 13 >= 135) { + if (updateHitAlien()) { + _vm->_gameSys->setAnimation(0, 0, 8); + _vm->_gameSys->removeSequence(35, 256, true); + _shipCannonFired = false; + drawScore(_gameScore); + } else { + _vm->_gameSys->setAnimation(35, 256, 8); + _vm->_gameSys->insertSequence(35, 256, 35, 256, kSeqSyncWait, 0, _shipCannonPosX, _shipCannonPosY); + _shipCannonPosY -= 13; + } + } else { + _vm->_gameSys->setAnimation(0, 0, 8); + _vm->_gameSys->removeSequence(35, 256, true); + _shipCannonFired = false; + } + } +} + +void Scene52::updateAlienCannons() { + for (int i = 0; i < 3; ++i) { + if (_alienCannonFired[i] && _vm->_gameSys->getAnimationStatus(i + 9) == 2) { + _alienCannonPosY[i] += 13; + if (_shipCannonHeight + _alienCannonPosY[i] + 13 <= 550) { + if (alienCannonHitShip(i)) { + _vm->_gameSys->setAnimation(0, 0, i + 9); + _alienCannonFired[i] = 0; + shipExplode(); + } else if (alienCannonHitShield(i)) { + _alienCannonFired[i] = 0; + } else { + _vm->_gameSys->insertSequence(_alienCannonSequenceIds[i], 1 - _alienCannonIds[i] + 256, 0, 0, + kSeqNone, 0, _alienCannonPosX[i], _alienCannonPosY[i]); + _vm->_gameSys->setAnimation(_alienCannonSequenceIds[i], 1 - _alienCannonIds[i] + 256, i + 9); + _alienCannonIds[i] = 1 - _alienCannonIds[i]; + _alienCannonPosY[i] += 13; + } + } else { + _vm->_gameSys->setAnimation(0, 0, i + 9); + _alienCannonFired[i] = 0; + } + } + } +} + +void Scene52::initAliens() { + if (!_aliensInitialized) { + initAlienSize(); + _aliensInitialized = true; + } + + _liveAlienRows = 0; + _alienSpeed = 0; + _bottomAlienFlag = false; + _aliensCount = 0; + _alienSingle = false; + _alienRowDownCtr = 0; + + initShields(); + + _alienRowKind[0] = -1; + _alienRowKind[1] = -1; + _alienRowKind[2] = -1; + _alienRowKind[3] = -1; + _alienRowKind[4] = _vm->getRandom(2) != 0 ? 24 : 27; + _alienRowKind[5] = _vm->getRandom(2) != 0 ? 25 : 28; + _alienRowKind[6] = _vm->getRandom(2) != 0 ? 26 : 29; + + for (int i = 0; i < 7; ++i) { + _alienRowAnims[i] = i; + _alienRowXOfs[i] = 0; + initAlienRowKind(i, _alienRowKind[i]); + insertAlienRow(i); + } +} + +void Scene52::initAlienRowKind(int rowNum, int alienKind) { + for (int i = 0; i < 5; ++i) + _items[rowNum][i] = alienKind; +} + +void Scene52::insertAlienRow(int rowNum) { + if (_alienRowKind[rowNum] >= 0) { + insertAlienRowAliens(rowNum); + _alienRowIds[rowNum] = 256; + _vm->_gameSys->setAnimation(_alienRowKind[rowNum], _alienRowIds[rowNum], _alienRowAnims[rowNum]); + ++_liveAlienRows; + } +} + +void Scene52::insertAlienRowAliens(int rowNum) { + int xOffs = _alienLeftX; + int yOffs = _alienTopY - 52 * rowNum - _alienHeight + 10; + for (int i = 0; i < 5; ++i) { + if (_items[rowNum][i] >= 0) { + _vm->_gameSys->insertSequence(_items[rowNum][i], i + 256, 0, 0, kSeqNone, 0, xOffs, yOffs); + ++_alienSpeed; + } + xOffs += _alienWidth; + } +} + +void Scene52::updateAlienRow(int rowNum) { + if (_alienRowKind[rowNum] != -1 && !checkAlienRow(rowNum)) { + updateAlienRowXOfs(); + _alienRowIds[rowNum] = -1; + int xOffs = _alienLeftX + _alienRowXOfs[rowNum]; + int yOffs = _alienTopY - 52 * rowNum - _alienHeight + 10; + for (int i = 0; i < 5; ++i) { + if (_items[rowNum][i] >= 0) { + _vm->_gameSys->insertSequence(_items[rowNum][i], i + 256, _items[rowNum][i], i + 256, kSeqSyncWait, 0, xOffs, yOffs); + if (_alienRowIds[rowNum] == -1) + _alienRowIds[rowNum] = i + 256; + } else if (_items[rowNum][i] == -2) { + _vm->_gameSys->removeSequence(_alienRowKind[rowNum], i + 256, true); + _items[rowNum][i] = -1; + --_alienSpeed; + } + xOffs += _alienWidth; + } + if (_alienRowIds[rowNum] == -1) { + _vm->_gameSys->setAnimation(0, 0, _alienRowAnims[rowNum]); + // MessageBoxA(0, "No live aliens!", "Error 3:", 0x30u); + } else { + _vm->_gameSys->setAnimation(_alienRowKind[rowNum], _alienRowIds[rowNum], _alienRowAnims[rowNum]); + } + if (rowNum == 1) { + for (int j = 0; j < 3; ++j) { + if (_shieldSpriteIds[j] != -1) { + _vm->_gameSys->fillSurface(nullptr, _shieldPosX[j], _arcadeScreenBottom - 44, 33, 44, 0, 0, 0); + _shieldSpriteIds[j] = -1; + } + } + } + if (rowNum == 0 && _bottomAlienFlag) + shipExplode(); + } +} + +void Scene52::moveDownAlienRow() { + int v2[5], v3, v1, v0, v4; + + for (int i = 0; i < 5; ++i) + v2[i] = _items[0][i]; + + v3 = _alienRowIds[0]; + v1 = _alienRowAnims[0]; + v0 = _alienRowKind[0]; + v4 = _alienRowXOfs[0]; + + for (int j = 0; j < 7; ++j) { + for (int i = 0; i < 5; ++i) + _items[j][i] = _items[j + 1][i]; + _alienRowIds[j] = _alienRowIds[j + 1]; + _alienRowAnims[j] = _alienRowAnims[j + 1]; + _alienRowKind[j] = _alienRowKind[j + 1]; + _alienRowXOfs[j] = _alienRowXOfs[j + 1]; + } + + for (int i = 0; i < 5; ++i) + _items[6][i] = v2[i]; + + _alienRowIds[6] = v3; + _alienRowAnims[6] = v1; + _alienRowKind[6] = v0; + _alienRowXOfs[6] = v4; + + updateAlien(6); + initAlienRowKind(6, _alienRowKind[6]); + insertAlienRow(6); + + _bottomAlienFlag = _alienRowKind[0] > -1; +} + +int Scene52::updateHitAlien() { + int result = 0, rowNum, ya; + + int y = _shipCannonTopY - _shipCannonPosY; + + if (y == 26) { + rowNum = 1; + ya = _shipCannonPosY + 26; + } else { + if (y % 52) + return 0; + rowNum = y / 52 + 1; + ya = _shipCannonPosY; + } + + if (rowNum < 7) { + int hitAlienNum = getHitAlienNum(rowNum); + if (hitAlienNum != -1 && _items[rowNum][hitAlienNum] >= 0) { + _gameScore = ((_items[rowNum][hitAlienNum] - 24) % 3 + _gameScore + 1) % 1000; + _items[rowNum][hitAlienNum] = -2; + _vm->playSound(0x2C, false); + _vm->_gameSys->insertSequence(0x21, 266, 0, 0, + kSeqNone, 0, _alienLeftX + hitAlienNum * _alienWidth + _alienRowXOfs[rowNum] - 10, ya - _alienHeight); + result = 1; + } + } + + return result; +} + +int Scene52::getHitAlienNum(int rowNum) { + int result = -1; + + int v3 = _alienLeftX + _alienRowXOfs[rowNum]; + + if (_shipCannonPosX >= v3) { + int v8 = _alienWidth / 2 - 15; + if (v3 + 5 * _alienWidth - v8 >= _shipCannonPosX) { + int v4 = v3 + _alienWidth; + if (_shipCannonPosX >= v4 - v8) { + int v5 = v4 + _alienWidth; + if (_shipCannonPosX >= v5 - v8) { + int v6 = v5 + _alienWidth; + if (_shipCannonPosX >= v6 - v8) { + int v7 = v6 + _alienWidth; + if (_shipCannonPosX >= v7 - v8) { + if (_shipCannonPosX >= v7 + _alienWidth - v8) + result = -1; + else + result = 4; + } else { + result = 3; + } + } else { + result = 2; + } + } else { + result = 1; + } + } else { + result = 0; + } + } else { + result = -1; + } + } else { + result = -1; + } + return result; +} + +int Scene52::alienCannonHitShip(int cannonNum) { + int result = 0; + + if (_aliensCount) { + result = 0; + } else { + int cannonY = _alienCannonPosY[cannonNum] - 13; + if (_arcadeScreenBottom <= cannonY) { + if (_shipMidY + _arcadeScreenBottom > cannonY) { + if (_alienCannonPosX[cannonNum] >= _shipPosX) + result = _alienCannonPosX[cannonNum] < _shipMidX + _shipPosX; + else + result = 0; + } else { + result = 0; + } + } else { + result = 0; + } + } + return result; +} + +int Scene52::alienCannonHitShield(int cannonNum) { + int result = 0; + + int v3 = _alienCannonPosY[cannonNum] + 39; + if (_arcadeScreenBottom - 44 > v3) + return 0; + + if (_arcadeScreenBottom <= v3) + return 0; + + if (_alienCannonPosX[cannonNum] < _shieldPosX[0]) + return 0; + + if (_alienCannonPosX[cannonNum] > _shieldPosX[2] + 33) + return 0; + + int shieldNum = -1; + if (_alienCannonPosX[cannonNum] < _shieldPosX[0] + 33) + shieldNum = 0; + + if (shieldNum < 0 && _alienCannonPosX[cannonNum] < _shieldPosX[1]) + return 0; + + if (shieldNum < 0 && _alienCannonPosX[cannonNum] < _shieldPosX[1] + 33) + shieldNum = 1; + + if (shieldNum < 0) { + if (_alienCannonPosX[cannonNum] < _shieldPosX[2]) + return 0; + shieldNum = 2; + } + + if (_shieldSpriteIds[shieldNum] == -1) { + result = 0; + } else { + ++_shieldSpriteIds[shieldNum]; + if (_shieldSpriteIds[shieldNum] <= 21) { + _vm->_gameSys->drawSpriteToBackground(_shieldPosX[shieldNum], _arcadeScreenBottom - 44, _shieldSpriteIds[shieldNum]); + } else { + _vm->_gameSys->fillSurface(nullptr, _shieldPosX[shieldNum], _arcadeScreenBottom - 44, 33, 44, 0, 0, 0); + _shieldSpriteIds[shieldNum] = -1; + } + _vm->_gameSys->setAnimation(0, 0, cannonNum + 9); + _vm->_gameSys->insertSequence(0x21, shieldNum + 257, 0, 0, kSeqNone, 0, _alienCannonPosX[cannonNum] - 18, _arcadeScreenBottom - 44); + _vm->playSound(0x2C, false); + result = 1; + } + + return result; +} + +bool Scene52::shipCannonHitShield(int cannonNum) { + bool result = false; + + if (_shipCannonPosX < _shieldPosX[0]) + return result; + + if (_shipCannonPosX > _shieldPosX[2] + 33) + return result; + + int shieldNum = -1; + if (_shipCannonPosX < _shieldPosX[0] + 33) + shieldNum = 0; + + if (shieldNum < 0 && _shipCannonPosX < _shieldPosX[1]) + return result; + + if (shieldNum < 0 && _shipCannonPosX < _shieldPosX[1] + 33) + shieldNum = 1; + + if (shieldNum < 0) { + if (_shipCannonPosX < _shieldPosX[2]) + return result; + shieldNum = 2; + } + + if (_shieldSpriteIds[shieldNum] == -1) { + result = false; + } else { + ++_shieldSpriteIds[shieldNum]; + if (_shieldSpriteIds[shieldNum] <= 21) { + _vm->_gameSys->drawSpriteToBackground(_shieldPosX[shieldNum], _arcadeScreenBottom - 44, _shieldSpriteIds[shieldNum]); + } else { + _vm->_gameSys->fillSurface(nullptr, _shieldPosX[shieldNum], _arcadeScreenBottom - 44, 33, 44, 0, 0, 0); + _shieldSpriteIds[shieldNum] = -1; + } + _vm->_gameSys->insertSequence(0x21, shieldNum + 257, 0, 0, kSeqNone, 0, _shipCannonPosX - 18, _arcadeScreenBottom - 44); + _vm->playSound(0x2C, false); + result = true; + } + + return result; +} + +bool Scene52::shipCannonHitAlien() { + bool result = false; + + if (_aliensCount || checkAlienRow(0)) + return false; + + int alienNextX = _alienLeftX + _alienRowXOfs[0]; + if (_shipMidX + _shipPosX >= alienNextX) { + int startX = _alienWidth / 2 - 15; + if (alienNextX + 5 * _alienWidth - startX >= _shipPosX) { + int alienNextDeltaX = alienNextX + _alienWidth; + if (_items[0][0] <= -1 || alienNextDeltaX - startX <= _shipPosX) { + alienNextDeltaX += _alienWidth; + if (_items[0][1] <= -1 || alienNextDeltaX - startX <= _shipPosX) { + alienNextDeltaX += _alienWidth; + if (_items[0][2] <= -1 || alienNextDeltaX - startX <= _shipPosX) { + alienNextDeltaX += _alienWidth; + if (_items[0][3] <= -1 || alienNextDeltaX - startX <= _shipPosX) { + alienNextDeltaX += _alienWidth; + result = _items[0][4] > -1 && alienNextDeltaX - startX > _shipPosX; + } else { + result = true; + } + } else { + result = true; + } + } else { + result = true; + } + } else { + result = true; + } + } else { + result = false; + } + } else { + result = false; + } + + return result; +} + +void Scene52::shipExplode() { + if (!_aliensCount) { + _vm->_gameSys->setAnimation(0, 0, 7); + _vm->_gameSys->removeSequence(_ufoSequenceId, 256, true); + _vm->playSound(0x2C, false); + _vm->_gameSys->insertSequence(0x21, 266, 0, 0, kSeqNone, 0, _shipPosX, _arcadeScreenBottom); + _aliensCount = 1; + _vm->playSound(0x31, false); + } +} + +bool Scene52::checkAlienRow(int rowNum) { + for (int i = 0; i < 5; ++i) { + if (_items[rowNum][i] >= 0) + return false; + } + + bool found = false; + for (int j = 0; j < 5; ++j) + if (_items[rowNum][j] == -2) { + _vm->_gameSys->removeSequence(_alienRowKind[rowNum], j + 256, true); + _items[rowNum][j] = -1; + --_alienSpeed; + found = true; + } + + if (found) { + _vm->_gameSys->setAnimation(0, 0, _alienRowAnims[rowNum]); + --_liveAlienRows; + } + + if (_liveAlienRows < 0) + _liveAlienRows = 0; + + return true; +} + +void Scene52::updateAlienRowXOfs() { + int amount = 2 * (3 - _liveAlienRows) + 1; + + if (_alienSpeed == 2) + amount *= 4; + else if (_alienSpeed == 1) + amount *= 10; + + if (_alienDirection) { + for (int i = 0; i < 7; ++i) { + _alienRowXOfs[i] -= amount; + if (_alienRowXOfs[i] <= -100) { + _alienRowXOfs[i] = -100; + _alienDirection = 0; + ++_alienRowDownCtr; + } + } + } else { + for (int j = 0; j < 7; ++j) { + _alienRowXOfs[j] += amount; + if (_alienRowXOfs[j] >= 100) { + _alienRowXOfs[j] = 100; + _alienDirection = 1; + ++_alienRowDownCtr; + } + } + } +} + +void Scene52::initAlienSize() { + _alienWidth = _vm->_gameSys->getSpriteWidthById(0); + if (_vm->_gameSys->getSpriteWidthById(1) > _alienWidth) + _alienWidth = _vm->_gameSys->getSpriteWidthById(1); + if (_vm->_gameSys->getSpriteWidthById(4) > _alienWidth) + _alienWidth = _vm->_gameSys->getSpriteWidthById(4); + if (_vm->_gameSys->getSpriteWidthById(5) > _alienWidth) + _alienWidth = _vm->_gameSys->getSpriteWidthById(5); + if (_vm->_gameSys->getSpriteWidthById(12) > _alienWidth) + _alienWidth = _vm->_gameSys->getSpriteWidthById(12); + if (_vm->_gameSys->getSpriteWidthById(13) > _alienWidth) + _alienWidth = _vm->_gameSys->getSpriteWidthById(13); + + _alienHeight = _vm->_gameSys->getSpriteHeightById(0); + if (_vm->_gameSys->getSpriteHeightById(1) > _alienHeight) + _alienHeight = _vm->_gameSys->getSpriteHeightById(1); + if (_vm->_gameSys->getSpriteHeightById(4) > _alienHeight) + _alienHeight = _vm->_gameSys->getSpriteHeightById(4); + if (_vm->_gameSys->getSpriteHeightById(5) > _alienHeight) + _alienHeight = _vm->_gameSys->getSpriteHeightById(5); + if (_vm->_gameSys->getSpriteHeightById(12) > _alienHeight) + _alienHeight = _vm->_gameSys->getSpriteHeightById(12); + if (_vm->_gameSys->getSpriteHeightById(13) > _alienHeight) + _alienHeight = _vm->_gameSys->getSpriteHeightById(13); + + _alienTopY = _shipCannonTopY + 52; + _alienLeftX = (800 - 5 * _alienWidth) / 2; +} + +void Scene52::playSound() { + if (_soundToggle) { + _vm->playSound(0x2F, false); + _soundToggle = false; + } else { + _vm->playSound(0x2E, false); + _soundToggle = true; + } +} + +void Scene52::updateAliens() { + for (int i = 0; i < 7; ++i) + updateAlien(i); +} + +void Scene52::updateAlien(int rowNum) { + if (_alienRowKind[rowNum] >= 0 && !checkAlienRow(rowNum)) { + for (int i = 0; i < 5; ++i) { + if (_items[rowNum][i] >= 0) + _items[rowNum][i] = -2; + } + checkAlienRow(rowNum); + } +} + +void Scene52::loseShip() { + --_shipsLeft; + if (_shipsLeft == 2) { + _vm->_gameSys->fillSurface(nullptr, 120, 140, _shipMidX, _shipMidY, 0, 0, 0); + } else if (_shipsLeft == 1) { + _vm->_gameSys->fillSurface(nullptr, 120, 185, _shipMidX, _shipMidY, 0, 0, 0); + } +} + +void Scene52::initShields() { + for (int i = 0; i < 3; ++i) { + _vm->_gameSys->drawSpriteToBackground(_shieldPosX[i], _arcadeScreenBottom - 44, 17); + _shieldSpriteIds[i] = 17; + } +} + +void Scene52::initAnims() { + for (int i = 0; i < 7; ++i) + _vm->_gameSys->setAnimation(0, 0, i); + _vm->_gameSys->setAnimation(0, 0, 7); + for (int j = 0; j < 1; ++j) + _vm->_gameSys->setAnimation(0, 0, j + 8); + for (int k = 0; k < 3; ++k) + _vm->_gameSys->setAnimation(0, 0, k + 9); +} + +void Scene52::drawScore(int score) { + char str[4]; + sprintf(str, "%03d", score); + _vm->_gameSys->fillSurface(nullptr, 420, 80, 48, 30, 0, 0, 0); + _vm->_gameSys->drawTextToSurface(nullptr, 420, 80, 255, 255, 255, str); +} + +void Scene52::run() { + _vm->_timers[1] = 0; + + _vm->hideCursor(); + + _gameScore = 0; + _vm->_gameSys->drawTextToSurface(nullptr, 300, 80, 255, 255, 255, "SCORE"); + _vm->_gameSys->drawTextToSurface(nullptr, 468, 80, 255, 255, 255, "0"); + + drawScore(0); + + _shipMidX = 33; + _shipMidY = _vm->_gameSys->getSpriteHeightById(15); + _shipPosX = (800 - _shipMidX) / 2; + _arcadeScreenBottom = 496; + int arcadeScreenRight = 595 - _shipMidX; + int arcadeScreenLeft = 210; + _shipsLeft = 3; + _alienCounter = 0; + + _shieldPosX[0] = 247; + _shieldPosX[1] = 387; + _shieldPosX[2] = 525; + + for (int i = 0; i < 3; ++i) + _shieldSpriteIds[i] = -1; + + _vm->_gameSys->drawSpriteToBackground(120, 140, 0xF); + _vm->_gameSys->drawSpriteToBackground(120, 185, 0xF); + + initShipCannon(_arcadeScreenBottom); + initAlienCannons(); + initAliens(); + + _nextUfoSequenceId = 0x22; + _vm->_gameSys->setAnimation(0x22, 256, 7); + _vm->_gameSys->insertSequence(_nextUfoSequenceId, 256, 0, 0, kSeqNone, 0, _shipPosX, _arcadeScreenBottom); + + _ufoSequenceId = _nextUfoSequenceId; + + _vm->clearKeyStatus1(Common::KEYCODE_RIGHT); + _vm->clearKeyStatus1(Common::KEYCODE_LEFT); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + _vm->clearKeyStatus1(Common::KEYCODE_UP); + _vm->clearKeyStatus1(Common::KEYCODE_ESCAPE); + + _vm->_timers[2] = 5; + _shipFlag = false; + + _vm->_timers[0] = 10; + _alienWave = true; + + while (!_vm->_sceneDone) { + _vm->gameUpdateTick(); + + while (_vm->isKeyStatus2(Common::KEYCODE_RIGHT)) { + update(); + if (_vm->_gameSys->getAnimationStatus(7) == 2) { + if (_shipPosX < arcadeScreenRight) { + _shipPosX += 15; + if (_shipPosX > arcadeScreenRight) + _shipPosX = arcadeScreenRight; + _vm->_gameSys->setAnimation(_nextUfoSequenceId, 256, 7); + _vm->_gameSys->insertSequence(_nextUfoSequenceId, 256, _ufoSequenceId, 256, kSeqSyncWait, 0, _shipPosX, _arcadeScreenBottom); + _ufoSequenceId = _nextUfoSequenceId; + if (_bottomAlienFlag && shipCannonHitAlien()) + shipExplode(); + } + break; + } + } + + while (_vm->isKeyStatus2(Common::KEYCODE_LEFT)) { + update(); + if (_vm->_gameSys->getAnimationStatus(7) == 2) { + if (_shipPosX > arcadeScreenLeft) { + _shipPosX -= 15; + if (_shipPosX < arcadeScreenLeft) + _shipPosX = arcadeScreenLeft; + _vm->_gameSys->setAnimation(_nextUfoSequenceId, 256, 7); + _vm->_gameSys->insertSequence(_nextUfoSequenceId, 256, _ufoSequenceId, 256, kSeqSyncWait, 0, _shipPosX, _arcadeScreenBottom); + _ufoSequenceId = _nextUfoSequenceId; + if (_bottomAlienFlag && shipCannonHitAlien()) + shipExplode(); + } + break; + } + } + + update(); + + if (clearKeyStatus()) { + _alienWave = false; + _vm->_gameSys->waitForUpdate(); + initAnims(); + _vm->clearKeyStatus1(Common::KEYCODE_SPACE); + _vm->_sceneDone = true; + } + } + _vm->_gameSys->waitForUpdate(); +} + +} // End of namespace Gnap |