aboutsummaryrefslogtreecommitdiff
path: root/engines/bbvs/minigames/bbloogie.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/bbvs/minigames/bbloogie.cpp')
-rw-r--r--engines/bbvs/minigames/bbloogie.cpp1355
1 files changed, 1355 insertions, 0 deletions
diff --git a/engines/bbvs/minigames/bbloogie.cpp b/engines/bbvs/minigames/bbloogie.cpp
new file mode 100644
index 0000000000..df7fec3123
--- /dev/null
+++ b/engines/bbvs/minigames/bbloogie.cpp
@@ -0,0 +1,1355 @@
+/* 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 "bbvs/minigames/bbloogie.h"
+
+namespace Bbvs {
+
+static const int kLoogieOffY[16] = {
+ 0, 1, 1, 2, 2, 3, 3, 4,
+ 4, 5, 5, 6, 6, 7, 7, 0
+};
+
+static const int kSquirrelOffX[] = {
+ -43, -43, -38, -33, -33, -27, -23, -23,
+ -23, -23, -23, -23, -18, -14, -8, -4,
+ 2, 8, 12, 18, 20, 20, 26, 31,
+ 37, 37, 37, 37, 37, 37, 37, 32,
+ 29, 26, 21, 14, 10, 6, 6, 6,
+ 6, 6, 6, 6, 0, -6, -15, -20,
+ -27, -37, -41, -41, -41, -41
+};
+
+static const int kPlaneOffX[] = {
+ 0, -1, -1, -1, 0, 1, 1, 1
+};
+
+static const int kPlaneOffY[] = {
+ -1, -1, 0, 1, 1, 1, 0, -1
+};
+
+static const int kLevelScores[] = {
+ 20, 50, 90, 140, 200, 270, 350, 440, 540, 10000
+};
+
+static const int kLevelTimes[] = {
+ 120, 110, 100, 90, 80, 70, 60, 50, 40, 30
+};
+
+static const uint kBeavisSounds1[] = {
+ 14, 15, 19, 20, 22, 23, 24, 26
+};
+
+static const uint kButtheadSounds1[] = {
+ 16, 14, 15, 22, 23
+};
+
+static const uint kBeavisSounds2[] = {
+ 9, 3, 4, 5, 7, 14, 15, 19, 20, 22, 23, 24, 26
+};
+
+static const uint kButtheadSounds2[] = {
+ 9, 3, 4, 5, 7, 16, 14, 15, 22, 23
+};
+
+static const uint kPrincipalSounds[] = {
+ 3, 4, 5, 7
+};
+
+static const char * const kSoundFilenames[] = {
+ "loog1.aif", "loog2.aif", "loog3.aif", "loog4.aif", "loog5.aif",
+ "loog6.aif", "loog7.aif", "loog8.aif", "loog9.aif", "loog10.aif",
+ "loog11.aif", "loog12.aif", "loog13.aif", "loog14.aif", "loog15.aif",
+ "loog16.aif", "loog17.aif", "loog18.aif", "loog19.aif", "loog20.aif",
+ "loog21.aif", "loog22.aif", "loog23.aif", "loog24.aif", "loog25.aif",
+ "loog26.aif", "loog27.aif", "meghoker.aif", "spit1.aif", "megaloog.aif",
+ "megaspit.aif", "gamemuse.aif", "bing.aif", "carhit.aif", "bikehit.aif",
+ "squirhit.aif", "planehit.aif", "bing2.aif"
+};
+
+static const uint kSoundFilenamesCount = ARRAYSIZE(kSoundFilenames);
+
+void MinigameBbLoogie::buildDrawList(DrawList &drawList) {
+ switch (_gameState) {
+ case kGSTitleScreen:
+ buildDrawList0(drawList);
+ break;
+ case kGSMainGame:
+ buildDrawList1(drawList);
+ break;
+ case kGSStandaloneGame:
+ buildDrawList2(drawList);
+ break;
+ case kGSScoreCountUp:
+ buildDrawList3(drawList);
+ break;
+ }
+}
+
+void MinigameBbLoogie::buildDrawList0(DrawList &drawList) {
+ drawList.add(_objects[0].anim->frameIndices[_objects[0].frameIndex], _objects[0].x, _objects[0].y, 2000);
+ for (int i = 1; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->kind != 0)
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, obj->y + 16);
+ }
+ if (_titleScreenSpriteIndex)
+ drawList.add(_titleScreenSpriteIndex, 0, 0, 0);
+}
+
+void MinigameBbLoogie::buildDrawList1(DrawList &drawList) {
+
+ for (int i = 0; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ switch (obj->kind) {
+ case 0:
+ // Empty object
+ break;
+ case 2:
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, 400);
+ break;
+ case 3:
+ drawList.add(obj->anim->frameIndices[obj->frameIndex + obj->frameIndexAdd], obj->x, obj->y, 1000);
+ break;
+ case 7:
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, 390);
+ break;
+ case 8:
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, 1000);
+ break;
+ default:
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, obj->y + 16);
+ break;
+ }
+ }
+
+ if (_backgroundSpriteIndex)
+ drawList.add(_backgroundSpriteIndex, 0, 0, 0);
+
+ if (_fromMainGame) {
+ drawList.add(getAnimation(8)->frameIndices[0], 8, 2, 2000);
+ drawNumber(drawList, _numberOfHits, 56, 16);
+ } else {
+ drawList.add(getAnimation(10)->frameIndices[0], 230, 2, 2000);
+ drawNumber(drawList, _levelTimeLeft, 280, 16);
+ drawList.add(getAnimation(15)->frameIndices[0], 5, 2, 2000);
+ int numberX2 = drawNumber(drawList, _currScore, 68, 16);
+ drawList.add(getAnimation(9)->frameIndices[10], numberX2, 16, 2000);
+ drawNumber(drawList, _dispLevelScore, numberX2 + 10, 16);
+ }
+
+ for (int i = 0; i < _megaLoogieCount; ++i)
+ drawList.add(getAnimation(19)->frameIndices[0], 20 + i * 25, 236, 2000);
+
+}
+
+void MinigameBbLoogie::buildDrawList2(DrawList &drawList) {
+
+ buildDrawList1(drawList);
+
+ if (_level > 0 && (_bonusDisplayDelay1 > 0 || _bonusDisplayDelay2 > 0)) {
+ drawList.add(getAnimation(12)->frameIndices[0], 100, 80, 2000);
+ drawNumber(drawList, _timeBonusCtr, 212, 94);
+ }
+
+ if (_bonusDisplayDelay3 > 0) {
+ drawList.add(getAnimation(14)->frameIndices[0], 65, 80, 2000);
+ int numberX2 = drawNumber(drawList, _nextLevelScore, 170, 92);
+ drawList.add(getAnimation(11)->frameIndices[0], numberX2, 80, 2000);
+ }
+
+}
+
+void MinigameBbLoogie::buildDrawList3(DrawList &drawList) {
+
+ for (int i = 0; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->kind == 2)
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, 400);
+ else
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, obj->y + 16);
+ }
+
+ if (_backgroundSpriteIndex)
+ drawList.add(_backgroundSpriteIndex, 0, 0, 0);
+
+ drawList.add(getAnimation(10)->frameIndices[0], 230, 2, 2000);
+
+ drawNumber(drawList, _levelTimeLeft, 280, 16);
+
+ drawList.add(getAnimation(15)->frameIndices[0], 5, 2, 2000);
+
+ int numberX2 = drawNumber(drawList, _currScore, 68, 16);
+ drawList.add(getAnimation(9)->frameIndices[10], numberX2, 16, 2000);
+ drawNumber(drawList, _dispLevelScore, numberX2 + 10, 16);
+
+ drawList.add(getAnimation(20)->frameIndices[0], 120, 70, 2000);
+ drawList.add(getAnimation(13)->frameIndices[0], 95, 95, 2000);
+
+ drawNumber(drawList, _hiScore, 210, 109);
+
+}
+
+void MinigameBbLoogie::drawSprites() {
+ DrawList drawList;
+ buildDrawList(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ _vm->_screen->copyToScreen();
+}
+
+void MinigameBbLoogie::initObjs() {
+ for (int i = 0; i < kMaxObjectsCount; ++i)
+ _objects[i].kind = 0;
+}
+
+MinigameBbLoogie::Obj *MinigameBbLoogie::getFreeObject() {
+ for (int i = 0; i < kMaxObjectsCount; ++i)
+ if (_objects[i].kind == 0)
+ return &_objects[i];
+ return 0;
+}
+
+MinigameBbLoogie::Obj *MinigameBbLoogie::findLoogieObj(int startObjIndex) {
+ for (int i = startObjIndex; i < kMaxObjectsCount; ++i)
+ if (_objects[i].kind == 3)
+ return &_objects[i];
+ return 0;
+}
+
+bool MinigameBbLoogie::isHit(Obj *obj1, Obj *obj2) {
+ const BBRect &frameRect1 = obj1->anim->frameRects[obj1->frameIndex];
+ const BBRect &frameRect2 = obj2->anim->frameRects[obj2->frameIndex];
+ const int obj1X1 = obj1->x + frameRect1.x;
+ const int obj1Y1 = obj1->y + frameRect1.y;
+ const int obj1X2 = obj1X1 + frameRect1.width;
+ const int obj1Y2 = obj1Y1 + frameRect1.height;
+ const int obj2X1 = obj2->x + frameRect2.x;
+ const int obj2Y1 = obj2->y + frameRect2.y;
+ const int obj2X2 = obj2X1 + frameRect2.width;
+ const int obj2Y2 = obj2Y1 + frameRect2.height;
+ return obj1X1 <= obj2X2 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1;
+}
+
+bool MinigameBbLoogie::isCursorAtObj(int objIndex) {
+ return isHit(&_objects[0], &_objects[objIndex]);
+}
+
+void MinigameBbLoogie::initObjects() {
+ switch (_gameState) {
+ case kGSTitleScreen:
+ initObjects0();
+ break;
+ case kGSMainGame:
+ initObjects1();
+ break;
+ case kGSStandaloneGame:
+ // Nothing
+ break;
+ case kGSScoreCountUp:
+ initObjects3();
+ break;
+ }
+}
+
+void MinigameBbLoogie::initObjects0() {
+ initObjs();
+ _objects[0].anim = getAnimation(25);
+ _objects[0].frameIndex = 0;
+ _objects[0].ticks = getAnimation(25)->frameTicks[0];
+ _objects[0].x = 160;
+ _objects[0].y = 120;
+ _objects[0].kind = 1;
+ _objects[1].anim = getAnimation(21);
+ _objects[1].frameIndex = 0;
+ _objects[1].ticks = getAnimation(21)->frameTicks[0];
+ _objects[1].x = 40;
+ _objects[1].y = 240;
+ _objects[1].kind = 1;
+ _objects[2].anim = getAnimation(23);
+ _objects[2].frameIndex = 0;
+ _objects[2].ticks = getAnimation(23)->frameTicks[0];
+ _objects[2].x = 280;
+ _objects[2].y = 240;
+ _objects[2].kind = 1;
+ _objects[3].anim = getAnimation(22);
+ _objects[3].frameIndex = 0;
+ _objects[3].ticks = getAnimation(22)->frameTicks[0];
+ _objects[3].x = 40;
+ _objects[3].y = 240;
+ _objects[3].kind = 0;
+ _objects[4].anim = getAnimation(24);
+ _objects[4].frameIndex = 0;
+ _objects[4].ticks = getAnimation(24)->frameTicks[0];
+ _objects[4].x = 280;
+ _objects[4].y = 240;
+ _objects[4].kind = 0;
+}
+
+void MinigameBbLoogie::initObjects1() {
+ initObjs();
+ _objects[0].anim = _playerAnim;
+ _objects[0].frameIndex = 0;
+ _objects[0].ticks = _playerAnim->frameTicks[0];
+ _objects[0].status = 0;
+ _objects[0].x = 160;
+ _objects[0].y = 240;
+ _objects[0].kind = 1;
+ _objects[1].anim = getAnimation(4);
+ _objects[1].frameIndex = 0;
+ _objects[1].ticks = getAnimation(4)->frameTicks[0];
+ _objects[1].x = 248;
+ _objects[1].y = 24;
+ _objects[1].kind = 2;
+}
+
+void MinigameBbLoogie::initObjects3() {
+ initObjs();
+ _objects[0].anim = _playerAnim;
+ _objects[0].frameIndex = 0;
+ _objects[0].ticks = _playerAnim->frameTicks[0];
+ _objects[0].status = 0;
+ _objects[0].kind = 1;
+ _objects[1].anim = getAnimation(4);
+ _objects[1].frameIndex = 0;
+ _objects[1].ticks = getAnimation(4)->frameTicks[0];
+ _objects[1].x = 248;
+ _objects[1].y = 24;
+ _objects[1].kind = 2;
+}
+
+void MinigameBbLoogie::initVars() {
+ switch (_gameState) {
+ case kGSTitleScreen:
+ initVars0();
+ break;
+ case kGSMainGame:
+ initVars1();
+ break;
+ case kGSStandaloneGame:
+ initVars2();
+ break;
+ case kGSScoreCountUp:
+ initVars3();
+ break;
+ }
+}
+
+void MinigameBbLoogie::initVars0() {
+ _carDelay = 120;
+ _bikeDelay = 250;
+ _squirrelDelay = 40;
+ _paperPlaneDelay = 400; // Uninitialized in the original
+ _principalDelay = 1750;
+ _levelTimeDelay = 58;
+ _principalAngry = false;
+ _squirrelDirection = false;
+ _numberOfHits = 0;
+ _megaLoogieCount = 0;
+ _level = 0;
+ _levelTimeLeft = 0;
+ _currScore = 0;
+ _dispLevelScore = 0;
+}
+
+void MinigameBbLoogie::initVars1() {
+ _carDelay = 120;
+ _bikeDelay = 250;
+ _squirrelDelay = 40;
+ _paperPlaneDelay = 400; // Uninitialized in the original
+ _principalDelay = 1750;
+ _squirrelDirection = false;
+ _numberOfHits = 0;
+ _megaLoogieCount = 0;
+}
+
+void MinigameBbLoogie::initVars2() {
+ _timeBonusCtr = _levelTimeLeft;
+ _levelTimeDelay = 58;
+ _bonusDisplayDelay1 = 60;
+ _levelTimeLeft = kLevelTimes[_level];
+ _nextLevelScore = kLevelScores[_level] + _currScore;
+ _bonusDisplayDelay2 = 0;
+ _bonusDisplayDelay3 = 0;
+}
+
+void MinigameBbLoogie::initVars3() {
+ if (_currScore > _hiScore)
+ _hiScore = _currScore;
+ if (_playerKind) {
+ playSound(11);
+ } else {
+ playSound(21);
+ }
+}
+
+bool MinigameBbLoogie::updateStatus(int mouseX, int mouseY, uint mouseButtons) {
+ switch (_gameState) {
+ case kGSTitleScreen:
+ return updateStatus0(mouseX, mouseY, mouseButtons);
+ case kGSMainGame:
+ return updateStatus1(mouseX, mouseY, mouseButtons);
+ case kGSStandaloneGame:
+ return updateStatus2(mouseX, mouseY, mouseButtons);
+ case kGSScoreCountUp:
+ return updateStatus3(mouseX, mouseY, mouseButtons);
+ }
+ return false;
+}
+
+bool MinigameBbLoogie::updateStatus0(int mouseX, int mouseY, uint mouseButtons) {
+
+ _objects[0].x = mouseX;
+ _objects[0].y = mouseY;
+
+ if (_objects[1].kind != 0 && isCursorAtObj(1)) {
+ _objects[0].frameIndex = 1;
+ _objects[1].kind = 0;
+ _objects[3].kind = 11;
+ _objects[3].frameIndex = 0;
+ _objects[3].ticks = _objects[3].anim->frameTicks[0];
+ } else if (!isCursorAtObj(3)) {
+ if (_objects[4].kind == 0)
+ _objects[0].frameIndex = 0;
+ _objects[3].kind = 0;
+ _objects[1].kind = 1;
+ }
+
+ if (_objects[2].kind && isCursorAtObj(2)) {
+ _objects[0].frameIndex = 1;
+ _objects[2].kind = 0;
+ _objects[4].kind = 11;
+ _objects[4].frameIndex = 0;
+ _objects[4].ticks = _objects[4].anim->frameTicks[0];
+ } else if (!isCursorAtObj(4)) {
+ if (_objects[3].kind == 0)
+ _objects[0].frameIndex = 0;
+ _objects[4].kind = 0;
+ _objects[2].kind = 1;
+ }
+
+ for (int i = 0; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->kind == 11) {
+ if (--obj->ticks == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex >= obj->anim->frameCount)
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[obj->frameIndex];
+ }
+ }
+ }
+
+ if ((mouseButtons & kLeftButtonDown) &&
+ (_objects[3].kind != 0 || _objects[4].kind != 0)) {
+ if (_objects[4].kind != 0) {
+ // Beavis
+ _playerKind = 0;
+ _playerAnim = getAnimation(0);
+ _playerSounds1 = kBeavisSounds1;
+ _playerSounds1Count = 8;
+ _playerSounds2 = kBeavisSounds2;
+ _playerSounds2Count = 13;
+ playSound(15);
+ while (isSoundPlaying(15)) { }
+ } else {
+ // Butt-head
+ _playerKind = 1;
+ _playerAnim = getAnimation(1);
+ _playerSounds1 = kButtheadSounds1;
+ _playerSounds1Count = 5;
+ _playerSounds2 = kButtheadSounds2;
+ _playerSounds2Count = 10;
+ playSound(23);
+ while (isSoundPlaying(23)) { }
+ }
+ _gameState = _fromMainGame ? kGSMainGame : kGSStandaloneGame;
+ initObjects1();
+ initObjects();
+ initVars();
+ _gameTicks = 0;
+ }
+
+ return true;
+}
+
+bool MinigameBbLoogie::updateStatus1(int mouseX, int mouseY, uint mouseButtons) {
+
+ if (--_levelTimeDelay == 0) {
+ _levelTimeDelay = 58;
+ --_levelTimeLeft;
+ }
+
+ if (!_fromMainGame && _levelTimeLeft == 0) {
+ _gameState = kGSScoreCountUp;
+ initObjects();
+ initVars();
+ } else if (_fromMainGame || _currScore < _nextLevelScore) {
+ _objects->x = CLIP(mouseX, 0, 319);
+ _objects->y = 240;
+ if (!_principalAngry &&
+ ((mouseButtons & kLeftButtonDown) || ((mouseButtons & kRightButtonDown) && _megaLoogieCount)) &&
+ _objects[0].status == 0 && mouseX != 32512 && mouseY != 32512) {
+ _objects[0].ticks = _playerAnim->frameTicks[13];
+ _objects[0].frameIndex = 14;
+ _objects[0].status = 1;
+ _objects[0].unk2 = 0;
+ Obj *newObj = getFreeObject();
+ newObj->anim = getAnimation(17);
+ newObj->frameIndex = 0;
+ newObj->ticks = 1;
+ newObj->x = 0;
+ newObj->y = 140;
+ newObj->kind = 8;
+ if (mouseButtons & kLeftButtonDown) {
+ _doubleScore = 0;
+ playSound(28);
+ } else {
+ _doubleScore = 17;
+ playSound(30);
+ }
+ }
+ updateObjs(mouseButtons);
+ } else {
+ _gameState = kGSStandaloneGame;
+ ++_level;
+ initObjects();
+ initVars();
+ }
+ return true;
+}
+
+bool MinigameBbLoogie::updateStatus2(int mouseX, int mouseY, uint mouseButtons) {
+
+ _objects[0].x = mouseX;
+
+ if (_bonusDisplayDelay1 > 0) {
+ if (--_bonusDisplayDelay1 == 0) {
+ _bonusDisplayDelay2 = 60;
+ if (_timeBonusCtr)
+ playSound(33, true);
+ }
+ } else if (_bonusDisplayDelay2 > 0) {
+ if (--_bonusDisplayDelay2 == 0) {
+ _bonusDisplayDelay3 = 150;
+ playSound(38);
+ } else if (_timeBonusCtr > 0) {
+ ++_bonusDisplayDelay2;
+ ++_levelTimeLeft;
+ if (--_timeBonusCtr == 0)
+ stopSound(33);
+ }
+ } else if (_bonusDisplayDelay3 > 0) {
+ if ((mouseButtons & kAnyButtonDown) || (--_bonusDisplayDelay3 == 0)) {
+ _dispLevelScore = _nextLevelScore;
+ _gameState = kGSMainGame;
+ _gameTicks = 0;
+ }
+ }
+ return true;
+}
+
+bool MinigameBbLoogie::updateStatus3(int mouseX, int mouseY, uint mouseButtons) {
+
+ _objects[0].x = mouseX;
+
+ for (int i = 0; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->kind == 2) {
+ if (--obj->ticks == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex >= obj->anim->frameCount)
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[obj->frameIndex];
+ }
+ }
+ }
+
+ return true;
+}
+
+void MinigameBbLoogie::updateObjs(uint mouseButtons) {
+
+ for (int i = 0; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ switch (obj->kind) {
+ case 1:
+ updatePlayer(i, mouseButtons);
+ break;
+ case 2:
+ updateObjKind2(i);
+ break;
+ case 3:
+ updateLoogie(i);
+ break;
+ case 4:
+ updateCar(i);
+ break;
+ case 5:
+ updateBike(i);
+ break;
+ case 6:
+ updateSquirrel(i);
+ break;
+ case 7:
+ updatePaperPlane(i);
+ break;
+ case 8:
+ updateIndicator(i);
+ break;
+ case 9:
+ updatePrincipal(i);
+ break;
+ }
+ }
+
+ if (--_carDelay == 0) {
+ // Car
+ Obj *obj = getFreeObject();
+ obj->anim = getAnimation(2);
+ obj->kind = 4;
+ obj->frameIndex = 0;
+ obj->x = 379;
+ obj->y = 22;
+ obj->xIncr = -2;
+ obj->yIncr = 0;
+ _carDelay = _vm->getRandom(256) + 800;
+ }
+
+ if (--_bikeDelay == 0) {
+ // Bike
+ Obj *obj = getFreeObject();
+ obj->kind = 5;
+ obj->anim = getAnimation(3);
+ obj->frameIndex = 0;
+ obj->x = 360;
+ obj->y = _vm->getRandom(32) + 82;
+ obj->xIncr = -1;
+ obj->yIncr = 0;
+ _bikeDelay = _vm->getRandom(512) + 500;
+ }
+
+ if (--_squirrelDelay == 0) {
+ // Squirrel
+ Obj *obj = getFreeObject();
+ obj->kind = 6;
+ obj->anim = getAnimation(7);
+ obj->frameIndex = !_squirrelDirection ? 0 : 29;
+ obj->x = 160;
+ obj->y = 36;
+ obj->xIncr = 0;
+ obj->yIncr = 0;
+ _squirrelDirection = !_squirrelDirection;
+ if (_vm->getRandom(5) == 1 && !isAnySoundPlaying(_playerSounds2, _playerSounds2Count))
+ playSound(9);
+ _squirrelDelay = _vm->getRandom(512) + 300;
+ }
+
+ if (--_paperPlaneDelay == 0) {
+ // Paper plane
+ Obj *obj = getFreeObject();
+ obj->kind = 7;
+ obj->anim = getAnimation(16);
+ obj->frameIndex = 0;
+ obj->x = 86;
+ obj->y = 187;
+ obj->xIncr = 0;
+ obj->yIncr = -1;
+ switch (_vm->getRandom(3)) {
+ case 1:
+ obj->frameIndex = 1;
+ obj->xIncr = -1;
+ break;
+ case 2:
+ obj->frameIndex = 7;
+ obj->xIncr = 1;
+ break;
+ }
+ _paperPlaneDelay = 400;
+ }
+
+ if (_principalDelay >= 0 && --_principalDelay == 0) {
+ // Principal
+ Obj *obj = getFreeObject();
+ obj->kind = 9;
+ obj->anim = getAnimation(18);
+ obj->frameIndex = 11;
+ obj->x = -20;
+ obj->y = 130;
+ obj->xIncr = 1;
+ obj->yIncr = 0;
+ obj->status = 0;
+ obj->frameIndexAdd = 0;
+ obj->unk2 = _vm->getRandom(256) + 100;
+ _principalCtr = 0;
+ _principalFirstFrameIndex = 11;
+ _principalLastFrameIndex = 16;
+ }
+
+}
+
+void MinigameBbLoogie::updatePlayer(int objIndex, uint mouseButtons) {
+
+ Obj *obj = &_objects[0];
+
+ switch (obj->status) {
+
+ case 1:
+ if (obj->ticks-- == 0) {
+ if (obj->frameIndex != 15) {
+ ++obj->frameIndex;
+ obj->ticks = _playerAnim->frameTicks[obj->frameIndex];
+ }
+ }
+ if ((((mouseButtons & kLeftButtonDown) && _doubleScore == 0) ||
+ ((mouseButtons & kRightButtonDown) && _doubleScore == 17))
+ && obj->unk2 != 61) {
+ ++obj->unk2;
+ } else {
+ obj->status = 2;
+ obj->frameIndex = 16;
+ obj->ticks = _playerAnim->frameTicks[16];
+ if (obj->unk2 >= 30) {
+ obj->status = 3;
+ obj->frameIndex = 21;
+ obj->ticks = _playerAnim->frameTicks[21];
+ }
+ if (obj->unk2 < 30) {
+ Obj *newObj = getFreeObject();
+ newObj->kind = 3;
+ newObj->anim = getAnimation(5);
+ newObj->frameIndex = 0;
+ newObj->ticks = getAnimation(5)->frameTicks[0];
+ newObj->x = obj->x;
+ newObj->y = 172;
+ newObj->unk2 = obj->unk2;
+ newObj->frameIndexAdd = _doubleScore;
+ if (_doubleScore)
+ --_megaLoogieCount;
+ }
+ if (_doubleScore) {
+ stopSound(30);
+ playSound(31);
+ } else {
+ stopSound(28);
+ playSound(29);
+ }
+ }
+ break;
+
+ case 2:
+ if (obj->ticks-- == 0) {
+ if (obj->frameIndex == 17) {
+ obj->frameIndex = 0;
+ obj->status = 0;
+ } else {
+ ++obj->frameIndex;
+ obj->ticks = _playerAnim->frameTicks[obj->frameIndex];
+ }
+ }
+ break;
+
+ case 3:
+ if (obj->ticks-- == 0) {
+ if (obj->frameIndex == 23) {
+ obj->frameIndex = 0;
+ obj->status = 0;
+ } else {
+ ++obj->frameIndex;
+ obj->ticks = _playerAnim->frameTicks[obj->frameIndex];
+ if (obj->frameIndex == 22) {
+ Obj *newObj = getFreeObject();
+ newObj->kind = 3;
+ newObj->anim = getAnimation(5);
+ newObj->frameIndex = 0;
+ newObj->ticks = getAnimation(5)->frameTicks[0];
+ newObj->x = obj->x;
+ newObj->y = 154;
+ newObj->unk2 = obj->unk2;
+ newObj->frameIndexAdd = _doubleScore;
+ if (_doubleScore)
+ --_megaLoogieCount;
+ }
+ }
+ }
+ break;
+
+ }
+
+}
+
+void MinigameBbLoogie::updateObjKind2(int objIndex) {
+
+ Obj *obj = &_objects[objIndex];
+
+ if (obj->ticks-- == 0) {
+ obj->ticks = getAnimation(4)->frameTicks[0];
+ if (obj->frameIndex > 7)
+ obj->frameIndex = 1;
+ if (obj->frameIndex++ >= 7)
+ obj->frameIndex = 0;
+ }
+
+}
+
+void MinigameBbLoogie::updateLoogie(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ if (obj->unk2 > 0) {
+ obj->y -= kLoogieOffY[obj->unk2 / 8];
+ --obj->unk2;
+ }
+
+ if (obj->ticks-- == 0) {
+ obj->ticks = getAnimation(5)->frameTicks[0];
+ ++obj->frameIndex;
+ if (obj->frameIndex >= 17) {
+ obj->kind = 0;
+ obj->anim = getAnimation(6);
+ obj->frameIndex = 0;
+ }
+ }
+
+}
+
+void MinigameBbLoogie::updateCar(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->x += obj->xIncr;
+
+ if (obj->ticks-- == 0) {
+ if (obj->frameIndex++ == 3 || obj->frameIndex == 6)
+ obj->frameIndex = 0;
+ obj->ticks = getAnimation(2)->frameTicks[obj->frameIndex];
+ }
+
+ if (obj->x <= -60) {
+ obj->kind = 0;
+ obj->anim = getAnimation(6);
+ obj->frameIndex = 0;
+ } else if (!_principalAngry && obj->frameIndex <= 3) {
+ int loogieObjIndex = 0;
+ Obj *loogieObj = findLoogieObj(loogieObjIndex++);
+ while (loogieObj) {
+ if (loogieObj->frameIndex >= 8 && loogieObj->frameIndex <= 10 && isHit(obj, loogieObj)) {
+ incNumberOfHits();
+ incScore(7);
+ loogieObj->frameIndex = 13;
+ loogieObj->ticks = getAnimation(5)->frameTicks[12];
+ obj->frameIndex = 4;
+ obj->ticks = getAnimation(2)->frameTicks[4];
+ playSound(34);
+ playRndSound();
+ }
+ loogieObj = findLoogieObj(loogieObjIndex++);
+ }
+ }
+
+}
+
+void MinigameBbLoogie::updateBike(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->x += obj->xIncr;
+
+ if (obj->ticks-- == 0) {
+ if (obj->frameIndex++ == 3 || obj->frameIndex == 7)
+ obj->frameIndex = 0;
+ obj->ticks = getAnimation(3)->frameTicks[obj->frameIndex];
+ }
+
+ if (obj->x == -40) {
+ obj->kind = 0;
+ obj->anim = getAnimation(6);
+ obj->frameIndex = 0;
+ } else if (!_principalAngry && obj->frameIndex <= 3) {
+ int loogieObjIndex = 0;
+ Obj *loogieObj = findLoogieObj(loogieObjIndex++);
+ while (loogieObj) {
+ if (loogieObj->frameIndex >= 7 && loogieObj->frameIndex <= 11 && isHit(obj, loogieObj)) {
+ incNumberOfHits();
+ incScore(2);
+ loogieObj->frameIndex = 13;
+ loogieObj->ticks = getAnimation(5)->frameTicks[12];
+ obj->frameIndex = 4;
+ obj->ticks = getAnimation(3)->frameTicks[4];
+ playSound(35);
+ playRndSound();
+ }
+ loogieObj = findLoogieObj(loogieObjIndex++);
+ }
+ }
+
+}
+
+void MinigameBbLoogie::updateSquirrel(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ if (obj->ticks-- == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex == 29 || obj->frameIndex == 54 ||
+ obj->frameIndex == 58 || obj->frameIndex == 62) {
+ obj->kind = 0;
+ obj->anim = getAnimation(6);
+ obj->frameIndex = 0;
+ }
+ obj->ticks = getAnimation(7)->frameTicks[obj->frameIndex];
+ }
+
+ if (!_principalAngry && obj->frameIndex <= 53) {
+ int loogieObjIndex = 0;
+ Obj *loogieObj = findLoogieObj(loogieObjIndex++);
+ while (loogieObj) {
+ if (loogieObj->frameIndex >= 7 && loogieObj->frameIndex <= 9 && isHit(obj, loogieObj)) {
+ incNumberOfHits();
+ incScore(10);
+ loogieObj->frameIndex = 13;
+ loogieObj->ticks = getAnimation(5)->frameTicks[12];
+ obj->x += kSquirrelOffX[obj->frameIndex];
+ obj->frameIndex = obj->frameIndex < 29 ? 54 : 58;
+ obj->ticks = getAnimation(7)->frameTicks[obj->frameIndex];
+ playSound(36);
+ playRndSound();
+ }
+ loogieObj = findLoogieObj(loogieObjIndex++);
+ }
+ }
+
+}
+
+void MinigameBbLoogie::updatePaperPlane(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+
+ if (obj->x == -16 || obj->x == 336 || obj->y == -16) {
+ obj->kind = 0;
+ obj->anim = getAnimation(6);
+ obj->frameIndex = 0;
+ }
+
+ if (!_principalAngry && obj->frameIndex <= 53) {
+ int loogieObjIndex = 0;
+ Obj *loogieObj = findLoogieObj(loogieObjIndex++);
+ while (loogieObj) {
+ if (loogieObj->frameIndex >= 4 && loogieObj->frameIndex <= 7 && isHit(obj, loogieObj)) {
+ incNumberOfHits();
+ incScore(5);
+ loogieObj->frameIndex = 13;
+ loogieObj->ticks = getAnimation(5)->frameTicks[12];
+ obj->frameIndex = (obj->frameIndex + 1) % 8;
+ obj->xIncr = kPlaneOffX[obj->frameIndex];
+ obj->yIncr = kPlaneOffY[obj->frameIndex];
+ playSound(37);
+ playRndSound();
+ }
+ loogieObj = findLoogieObj(loogieObjIndex++);
+ }
+ }
+
+}
+
+void MinigameBbLoogie::updateIndicator(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+ Obj *loogieObj = &_objects[0];
+
+ if (obj->ticks-- == 0) {
+ obj->frameIndex = (obj->frameIndex + 1) % 2;
+ obj->ticks = getAnimation(17)->frameTicks[0];
+ }
+
+ if (loogieObj->status != 0) {
+ int unk2mod = loogieObj->unk2 / 8;
+ int unk2div = loogieObj->unk2 / 8 * 8;
+ int v6 = 0;
+ if (unk2div >= 8) {
+ int v7 = 1;
+ if (unk2div != 8) {
+ do {
+ v6 += 8 * kLoogieOffY[v7++];
+ } while (v7 != unk2mod);
+ }
+ }
+ int yOfs = (loogieObj->unk2 % 8 + 1) * kLoogieOffY[loogieObj->unk2 / 8] + v6;
+ if (loogieObj->unk2 >= 30)
+ yOfs += 18;
+ obj->y = 140 - yOfs;
+ } else {
+ obj->kind = 0;
+ obj->anim = getAnimation(6);
+ }
+
+}
+
+void MinigameBbLoogie::updatePrincipal(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ switch (obj->status) {
+
+ case 0:
+ if (obj->unk2--) {
+ if (obj->ticks-- == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex == _principalLastFrameIndex)
+ obj->frameIndex = _principalFirstFrameIndex;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ ++_principalCtr;
+ if (_principalCtr % 2 != 0) {
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+ if (obj->xIncr > 0 && obj->x == 340) {
+ obj->xIncr = -1;
+ _principalLastFrameIndex = 34;
+ _principalFirstFrameIndex = 29;
+ obj->frameIndex = 29;
+ obj->status = 2;
+ obj->ticks = _vm->getRandom(256) + 60;
+ }
+ if (obj->xIncr < 0 && obj->x == -20) {
+ obj->xIncr = 1;
+ _principalLastFrameIndex = 16;
+ _principalFirstFrameIndex = 11;
+ obj->frameIndex = 11;
+ obj->status = 2;
+ obj->ticks = _vm->getRandom(256) + 60;
+ }
+ }
+ } else {
+ obj->unk2 = _vm->getRandom(64) + 20;
+ ++obj->status;
+ if (_vm->getRandom(2) == 1) {
+ obj->frameIndex = _principalFirstFrameIndex < 11 ? 17 : 26;
+ _principalFirstFrameIndex = 19;
+ } else {
+ obj->frameIndex = _principalFirstFrameIndex < 11 ? 8 : 35;
+ _principalFirstFrameIndex = 1;
+ }
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ break;
+
+ case 1:
+ if (obj->unk2--) {
+ if (obj->ticks-- == 0)
+ obj->frameIndex = _principalFirstFrameIndex;
+ } else {
+ obj->unk2 = _vm->getRandom(256) + 100;
+ ++obj->status;
+ if (_vm->getRandom(2) == 1) {
+ _principalLastFrameIndex = 16;
+ _principalFirstFrameIndex = 11;
+ obj->frameIndex = obj->frameIndex < 1 ? 8 : 17;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ obj->xIncr = 1;
+ } else {
+ _principalLastFrameIndex = 34;
+ _principalFirstFrameIndex = 29;
+ obj->frameIndex = obj->frameIndex < 1 ? 35 : 26;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ obj->xIncr = -1;
+ }
+ }
+ break;
+
+ case 2:
+ if (obj->ticks-- == 0) {
+ obj->status = 0;
+ obj->frameIndex = _principalFirstFrameIndex;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ break;
+
+ case 3:
+ if (obj->ticks-- == 0) {
+ obj->status = _prevPrincipalStatus;
+ obj->frameIndex = _principalFirstFrameIndex;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ break;
+
+ case 4:
+ if (obj->ticks-- == 0) {
+ switch (obj->frameIndex) {
+ case 8:
+ obj->frameIndex = 36;
+ break;
+ case 26:
+ obj->frameIndex = 28;
+ break;
+ case 28:
+ obj->frameIndex = 35;
+ break;
+ case 35:
+ ++obj->frameIndex;
+ break;
+ case 36:
+ obj->status = 5;
+ ++obj->frameIndex;
+ break;
+ }
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ break;
+
+ case 5:
+ if (obj->ticks-- == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex == 48)
+ obj->frameIndex = 36;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ if (!isSoundPlaying(1)) {
+ _gameResult = 1;
+ if (_fromMainGame) {
+ _principalAngry = true;
+ if (obj->x <= 140 || obj->x >= 165) {
+ obj->status = 6;
+ if (obj->x >= 160) {
+ _principalLastFrameIndex = 34;
+ _principalFirstFrameIndex = 29;
+ obj->frameIndex = 29;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ obj->xIncr = -1;
+ } else {
+ _principalLastFrameIndex = 16;
+ _principalFirstFrameIndex = 11;
+ obj->frameIndex = 11;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ obj->xIncr = 1;
+ }
+ } else {
+ obj->status = 7;
+ _principalFirstFrameIndex = 2;
+ _principalLastFrameIndex = 7;
+ obj->frameIndex = 2;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ obj->xIncr = 0;
+ obj->yIncr = 1;
+ }
+ } else {
+ obj->status = _prevPrincipalStatus;
+ obj->frameIndex = _principalFirstFrameIndex;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ }
+ break;
+
+ case 6:
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+ if (obj->ticks-- == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex == _principalLastFrameIndex)
+ obj->frameIndex = _principalFirstFrameIndex;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ if (obj->x > 145 && obj->x < 160) {
+ obj->status = 7;
+ _principalFirstFrameIndex = 2;
+ _principalLastFrameIndex = 7;
+ obj->frameIndex = 2;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ obj->xIncr = 0;
+ obj->yIncr = 1;
+ }
+ break;
+
+ case 7:
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+ if (obj->ticks-- == 0) {
+ ++obj->frameIndex;
+ if (obj->frameIndex == _principalLastFrameIndex)
+ obj->frameIndex = _principalFirstFrameIndex;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ }
+ if (obj->y > 175) {
+ // Angry principal enters school, end the minigame
+ _gameDone = true;
+ }
+ break;
+
+ }
+
+ if (!_principalAngry) {
+ int loogieObjIndex = 0;
+ Obj *loogieObj = findLoogieObj(loogieObjIndex++);
+ while (loogieObj) {
+ if (loogieObj->frameIndex >= 7 && loogieObj->frameIndex <= 12 && isHit(obj, loogieObj)) {
+ incNumberOfHits();
+ incScore(1);
+ loogieObj->frameIndex = 13;
+ loogieObj->ticks = getAnimation(5)->frameTicks[12];
+ if (obj->status != 3 && obj->status != 4 && obj->status != 5) {
+ _prevPrincipalStatus = obj->status;
+ obj->status = 3;
+ if (_principalFirstFrameIndex == 1 || _principalFirstFrameIndex == 19)
+ obj->frameIndex = _principalFirstFrameIndex - 1;
+ else
+ obj->frameIndex = _principalFirstFrameIndex - 2;
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ if (loogieObj->frameIndexAdd > 0) {
+ obj->status = 4;
+ switch (obj->frameIndex) {
+ case 0:
+ obj->frameIndex = 36;
+ break;
+ case 9:
+ obj->frameIndex = 8;
+ break;
+ case 27:
+ obj->frameIndex = 35;
+ break;
+ case 18:
+ obj->frameIndex = 26;
+ break;
+ }
+ obj->ticks = getAnimation(18)->frameTicks[obj->frameIndex];
+ playSound(1);
+ } else {
+ if (!isAnySoundPlaying(_playerSounds2, _playerSounds2Count))
+ playSound(kPrincipalSounds[_vm->getRandom(4)]);
+ playRndSound();
+ }
+ }
+ }
+ loogieObj = findLoogieObj(loogieObjIndex++);
+ }
+ }
+
+}
+
+void MinigameBbLoogie::incNumberOfHits() {
+ ++_numberOfHits;
+ if (_numberOfHits == 1000)
+ _numberOfHits = 0;
+ if (_numberOfHits % 10 == 0) {
+ ++_megaLoogieCount;
+ if (_megaLoogieCount > 11)
+ _megaLoogieCount = 11;
+ }
+}
+
+void MinigameBbLoogie::incScore(int incrAmount) {
+ if (_doubleScore)
+ _currScore += 2 * incrAmount;
+ else
+ _currScore += incrAmount;
+}
+
+void MinigameBbLoogie::playRndSound() {
+ if (!isAnySoundPlaying(_playerSounds2, _playerSounds2Count))
+ playSound(_playerSounds1[_vm->getRandom(_playerSounds1Count)]);
+}
+
+int MinigameBbLoogie::run(bool fromMainGame) {
+
+ memset(_objects, 0, sizeof(_objects));
+
+ _numbersAnim = getAnimation(9);
+
+ _backgroundSpriteIndex = 210;
+ _titleScreenSpriteIndex = 211;
+
+ _fromMainGame = fromMainGame;
+
+ _hiScore = 0;
+ if (!_fromMainGame)
+ _hiScore = loadHiscore(kMinigameBbLoogie);
+
+ _gameState = kGSTitleScreen;
+ _gameTicks = 0;
+ _gameResult = 0;
+ _gameDone = false;
+ initObjects();
+ initVars();
+
+ _spriteModule = new SpriteModule();
+ _spriteModule->load("bbloogie/bbloogie.000");
+
+ Palette palette = _spriteModule->getPalette();
+ _vm->_screen->setPalette(palette);
+
+ loadSounds();
+
+ playSound(32, true);
+
+ while (!_vm->shouldQuit() &&!_gameDone) {
+ _vm->updateEvents();
+ update();
+ }
+
+ _vm->_sound->unloadSounds();
+
+ if (!_fromMainGame)
+ saveHiscore(kMinigameBbLoogie, _hiScore);
+
+ delete _spriteModule;
+
+ return _gameResult;
+}
+
+void MinigameBbLoogie::update() {
+
+ int currTicks, inputTicks;
+
+ if (_gameTicks > 0) {
+ currTicks = _vm->_system->getMillis();
+ inputTicks = (currTicks - _gameTicks) / 17;
+ _gameTicks = currTicks - (currTicks - _gameTicks) % 17;
+ } else {
+ inputTicks = 1;
+ _gameTicks = _vm->_system->getMillis();
+ }
+
+ if (_vm->_keyCode == Common::KEYCODE_ESCAPE) {
+ _gameDone = true;
+ return;
+ }
+
+ if (inputTicks == 0)
+ return;
+
+ bool done;
+
+ do {
+ done = !updateStatus(_vm->_mouseX, _vm->_mouseY, _vm->_mouseButtons);
+ _vm->_mouseButtons &= ~kLeftButtonClicked;
+ _vm->_mouseButtons &= ~kRightButtonClicked;
+ _vm->_keyCode = Common::KEYCODE_INVALID;
+ } while (--inputTicks && _gameTicks > 0 && !done);
+
+ drawSprites();
+
+ _vm->_system->delayMillis(10);
+
+}
+
+void MinigameBbLoogie::loadSounds() {
+ for (uint i = 0; i < kSoundFilenamesCount; ++i) {
+ Common::String filename = Common::String::format("bbloogie/%s", kSoundFilenames[i]);
+ _vm->_sound->loadSound(filename.c_str());
+ }
+}
+
+} // End of namespace Bbvs