/* 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 *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