aboutsummaryrefslogtreecommitdiff
path: root/engines/bbvs/minigames/bbant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/bbvs/minigames/bbant.cpp')
-rw-r--r--engines/bbvs/minigames/bbant.cpp1317
1 files changed, 1317 insertions, 0 deletions
diff --git a/engines/bbvs/minigames/bbant.cpp b/engines/bbvs/minigames/bbant.cpp
new file mode 100644
index 0000000000..abecf22aff
--- /dev/null
+++ b/engines/bbvs/minigames/bbant.cpp
@@ -0,0 +1,1317 @@
+/* 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/bbant.h"
+
+namespace Bbvs {
+
+static const BBPoint kPosIncrTbl1[] = {
+ {0, -1}, {-1, -1}, {-1, 0}, {-1, 1},
+ { 0, 1}, { 1, 1}, { 1, 0}, { 1, -1}
+};
+
+static const BBPoint kPosIncrTbl2[] = {
+ {0, -2}, {-2, -2}, {-2, 0}, {-2, 2},
+ { 0, 2}, { 2, 2}, { 2, 0}, { 2, -2}
+};
+
+static const int kScoreTbl[] = {
+ 0, 1, 1, 3, 2, 4
+};
+
+static const char * const kSoundFilenames[] = {
+ "ant1.aif", "ant2.aif", "ant3.aif", "ant4.aif", "ant5.aif",
+ "ant6.aif", "ant7.aif", "ant8.aif", "ant9.aif", "ant10.aif",
+ "ant11.aif", "antmus1.aif", "fryant.aif", "stomp.aif", "bing.aif",
+ "bvyell.aif"
+};
+
+static const uint kSoundFilenamesCount = ARRAYSIZE(kSoundFilenames);
+
+static const uint kSoundTbl1[] = {
+ 2, 3, 4, 6
+};
+
+static const uint kSoundTbl2[] = {
+ 5, 7, 11
+};
+
+static const uint kSoundTbl3[] = {
+ 8, 10, 11
+};
+
+static const uint kSoundTbl4[] = {
+ 2, 3, 4, 6, 8, 10, 11, 5, 7, 16
+};
+
+void MinigameBbAnt::buildDrawList0(DrawList &drawList) {
+
+ if (_titleScreenSpriteIndex)
+ drawList.add(_titleScreenSpriteIndex, 0, 0, 0);
+
+ for (int i = 0; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->kind)
+ drawList.add(obj->anim->frameIndices[obj->frameIndex], obj->x, obj->y, obj->priority);
+ }
+
+}
+
+void MinigameBbAnt::buildDrawList1(DrawList &drawList) {
+
+ if (_backgroundSpriteIndex)
+ drawList.add(_backgroundSpriteIndex, _stompX, _stompY, 0);
+
+ for (int i = 1; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->kind) {
+ drawList.add(obj->anim->frameIndices[obj->frameIndex],
+ _stompX + (obj->x >> 16), _stompY + (obj->y >> 16),
+ obj->priority);
+ }
+ }
+
+ drawList.add(getAnimation(164)->frameIndices[0], 5, 2, 2000);
+ drawNumber(drawList, _score, 68, 16);
+ drawList.add(getAnimation(166)->frameIndices[0], 230, 2, 2000);
+ drawNumber(drawList, _levelTimeLeft, 280, 16);
+
+ for (int i = 0; i < _stompCount; ++i)
+ drawList.add(getAnimation(130)->frameIndices[0], 20 + i * 30, 230, 2000);
+
+}
+
+void MinigameBbAnt::buildDrawList2(DrawList &drawList) {
+ buildDrawList1(drawList);
+ drawList.add(getAnimation(168)->frameIndices[0], 40, 100, 2000);
+ drawNumber(drawList, _counter1, 190, 112);
+ drawNumber(drawList, _countdown5, 258, 112);
+ drawList.add(getAnimation(169)->frameIndices[0], 120, 120, 2000);
+ drawNumber(drawList, _counter4, 192, 132);
+}
+
+void MinigameBbAnt::buildDrawList3(DrawList &drawList) {
+ buildDrawList1(drawList);
+ drawList.add(getAnimation(163)->frameIndices[0], 120, 70, 2000);
+ drawList.add(getAnimation(165)->frameIndices[0], 95, 95, 2000);
+ drawNumber(drawList, _hiScore, 208, 107);
+}
+
+void MinigameBbAnt::drawMagnifyingGlass(DrawList &drawList) {
+ scale2x(_objects[0].x - 28, _objects[0].y - 27);
+ drawList.clear();
+ drawList.add(_objects[0].anim->frameIndices[0], _objects[0].x, _objects[0].y, _objects[0].priority);
+ drawList.add(_objects[0].anim->frameIndices[1], _objects[0].x, _objects[0].y, _objects[0].priority);
+ drawList.add(_objects[0].anim->frameIndices[2], _objects[0].x, _objects[0].y, _objects[0].priority);
+}
+
+void MinigameBbAnt::drawSprites() {
+ switch (_gameState) {
+ case 0:
+ drawSprites0();
+ break;
+ case 1:
+ drawSprites1();
+ break;
+ case 2:
+ drawSprites2();
+ break;
+ case 3:
+ drawSprites3();
+ break;
+ }
+}
+
+void MinigameBbAnt::drawSprites0() {
+ DrawList drawList;
+ buildDrawList0(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ _vm->_screen->copyToScreen();
+}
+
+void MinigameBbAnt::drawSprites1() {
+ DrawList drawList;
+ buildDrawList1(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ drawMagnifyingGlass(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ _vm->_screen->copyToScreen();
+}
+
+void MinigameBbAnt::drawSprites2() {
+ DrawList drawList;
+ buildDrawList2(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ drawMagnifyingGlass(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ _vm->_screen->copyToScreen();
+}
+
+void MinigameBbAnt::drawSprites3() {
+ DrawList drawList;
+ buildDrawList3(drawList);
+ _vm->_screen->drawDrawList(drawList, _spriteModule);
+ _vm->_screen->copyToScreen();
+}
+
+MinigameBbAnt::Obj *MinigameBbAnt::getFreeObject() {
+ for (int i = 12; i < kMaxObjectsCount; ++i)
+ if (_objects[i].kind == 0)
+ return &_objects[i];
+ return 0;
+}
+
+void MinigameBbAnt::initObjects() {
+ switch (_gameState) {
+ case 0:
+ initObjects0();
+ break;
+ case 1:
+ initObjects1();
+ break;
+ case 2:
+ case 3:
+ // Nothing
+ break;
+ }
+}
+
+void MinigameBbAnt::initObjects0() {
+ _objects[0].anim = getAnimation(172);
+ _objects[0].frameIndex = 0;
+ _objects[0].ticks = getAnimation(172)->frameTicks[0];
+ _objects[0].x = 160;
+ _objects[0].y = 120;
+ _objects[0].priority = 2000;
+ _objects[0].kind = 1;
+ _objects[1].anim = getAnimation(170);
+ _objects[1].frameIndex = 0;
+ _objects[1].ticks = getAnimation(170)->frameTicks[0];
+ _objects[1].x = 40;
+ _objects[1].y = 240;
+ _objects[1].priority = 100;
+ _objects[1].kind = 2;
+ _objects[2].anim = getAnimation(171);
+ _objects[2].frameIndex = 0;
+ _objects[2].ticks = getAnimation(171)->frameTicks[0];
+ _objects[2].x = 280;
+ _objects[2].y = 240;
+ _objects[2].priority = 100;
+ _objects[2].kind = 2;
+}
+
+void MinigameBbAnt::initObjects1() {
+ _objects[0].kind = 0;
+ _objects[0].x = 160;
+ _objects[0].y = 120;
+ _objects[0].xIncr = 0;
+ _objects[0].yIncr = 0;
+ _objects[0].anim = getAnimation(159);
+ _objects[0].frameIndex = 0;
+ _objects[0].ticks = _objects[0].anim->frameTicks[0];
+ _objects[0].priority = 1000;
+ _objects[1].kind = 8;
+ _objects[1].x = 0x1E0000;
+ _objects[1].y = 0x280000;
+ _objects[1].xIncr = 0;
+ _objects[1].yIncr = 0;
+ _objects[1].anim = getAnimation(160);
+ _objects[1].frameIndex = 0;
+ _objects[1].ticks = _objects[0].anim->frameTicks[0];
+ _objects[1].priority = 900;
+ _objects[1].smokeCtr = 0;
+ _objects[1].hasSmoke = false;
+ _objects[1].status = 0;
+ _objects[2].kind = 8;
+ _objects[2].x = 0x280000;
+ _objects[2].y = 0x4B0000;
+ _objects[2].xIncr = 0;
+ _objects[2].yIncr = 0;
+ _objects[2].anim = getAnimation(161);
+ _objects[2].frameIndex = 0;
+ _objects[2].ticks = _objects[0].anim->frameTicks[0];
+ _objects[2].priority = 900;
+ _objects[2].smokeCtr = 0;
+ _objects[2].hasSmoke = false;
+ _objects[2].status = 0;
+ for (int i = 3; i < 12; ++i) {
+ const ObjInit *objInit = getObjInit(i - 3);
+ _objects[i].kind = 6;
+ _objects[i].x = objInit->x << 16;
+ _objects[i].y = objInit->y << 16;
+ _objects[i].xIncr = 0;
+ _objects[i].yIncr = 0;
+ _objects[i].anim = objInit->anim1;
+ _objects[i].frameIndex = 0;
+ _objects[i].ticks = _objects[0].anim->frameTicks[0];
+ _objects[i].priority = 600;
+ _objects[i].status = 9;
+ _objects[i].damageCtr = 0;
+
+ }
+}
+
+void MinigameBbAnt::initVars() {
+ switch (_gameState) {
+ case 0:
+ // Nothing
+ break;
+ case 1:
+ initVars1();
+ break;
+ case 2:
+ initVars2();
+ break;
+ case 3:
+ initVars3();
+ break;
+ }
+}
+
+void MinigameBbAnt::initVars1() {
+ _stompX = 0;
+ _stompY = 0;
+ _stompDelay1 = 0;
+ _stompCount = 1;
+ _stompCounter1 = 80;
+ _stompCounter2 = 80;
+ _totalBugsCount = 0;
+ _hasLastStompObj = false;
+ _counter1 = 9;
+ _countdown10 = 140;
+ _score = 0;
+ _counter4 = 1;
+ _gameTicks = 0;
+ _skullBugCtr = 500;
+ _levelTimeDelay = 58;
+ _levelTimeLeft = 30;
+ _bugsChanceByKind[0] = 0;
+ _bugsChanceByKind[1] = 20;
+ _bugsChanceByKind[2] = 20;
+ _bugsChanceByKind[3] = 5;
+ _bugsChanceByKind[4] = 7;
+ _bugsCountByKind[0] = 0;
+ _bugsCountByKind[1] = 0;
+ _bugsCountByKind[2] = 0;
+ _bugsCountByKind[3] = 0;
+ _bugsCountByKind[4] = 0;
+ _bugsCountByKind[5] = 0;
+}
+
+void MinigameBbAnt::initVars2() {
+ _countdown4 = 0;
+ _countdown3 = 0;
+ _levelTimeDelay = 58;
+ _countdown6 = 60;
+ _countdown5 = 50 * _counter1;
+}
+
+void MinigameBbAnt::initVars3() {
+ if (_score > _hiScore)
+ _hiScore = _score;
+ playSound(9);
+}
+
+bool MinigameBbAnt::updateStatus(int mouseX, int mouseY, uint mouseButtons) {
+ switch (_gameState) {
+ case 0:
+ return updateStatus0(mouseX, mouseY, mouseButtons);
+ case 1:
+ return updateStatus1(mouseX, mouseY, mouseButtons);
+ case 2:
+ return updateStatus2(mouseX, mouseY, mouseButtons);
+ case 3:
+ return updateStatus3(mouseX, mouseY, mouseButtons);
+ }
+ return false;
+}
+
+bool MinigameBbAnt::updateStatus0(int mouseX, int mouseY, uint mouseButtons) {
+
+ _objects[0].x = mouseX;
+ _objects[0].y = mouseY;
+
+ if (_objects[0].x >= 320)
+ _objects[0].x = 320 - 1;
+ if (_objects[0].y >= 240)
+ _objects[0].y = 240 - 1;
+ if (_objects[0].x < 0)
+ _objects[0].x = 0;
+ if (_objects[0].y < 0)
+ _objects[0].y = 0;
+
+ if ((mouseButtons & kLeftButtonDown) || (mouseButtons & kRightButtonDown)) {
+ _gameState = 1;
+ initObjects();
+ initVars();
+ _gameTicks = 0;
+ playSound(1);
+ } else {
+ 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[0];
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool MinigameBbAnt::updateStatus1(int mouseX, int mouseY, uint mouseButtons) {
+ const int kMaxBugsCount = 52;
+
+ --_levelTimeDelay;
+ if (!_levelTimeDelay) {
+ _levelTimeDelay = 58;
+ --_levelTimeLeft;
+ }
+
+ _objects[0].x = mouseX;
+ _objects[0].y = mouseY;
+
+ if (_objects[0].x >= 320)
+ _objects[0].x = 320 - 1;
+ if (_objects[0].y >= 240)
+ _objects[0].y = 240 - 1;
+ if (_objects[0].x < 0)
+ _objects[0].x = 0;
+ if (_objects[0].y < 0)
+ _objects[0].y = 0;
+
+ if (!_levelTimeLeft) {
+ _gameState = 2;
+ initVars();
+ initObjects();
+ _gameTicks = 0;
+ return true;
+ }
+
+ if (_counter1 == 0) {
+ _gameState = 3;
+ initVars();
+ initObjects();
+ _gameTicks = 0;
+ return true;
+ }
+
+ if ((mouseButtons & kRightButtonClicked) && (_stompCount > 0|| _hasLastStompObj) && !_objects[2].status) {
+ if (_hasLastStompObj)
+ removeStompObj(_lastStompObj);
+ --_stompCount;
+ _objects[2].status = 1;
+ }
+
+ if ((mouseButtons & kLeftButtonClicked) && _objects[2].status == 0 && isMagGlassAtBeavisLeg(2)) {
+ if (_vm->getRandom(10) == 1 && !isAnySoundPlaying(kSoundTbl4, 10))
+ playSound(16);
+ insertSmokeObj(_objects[0].x << 16, _objects[0].y << 16);
+ }
+
+ if (_skullBugCtr > 0) {
+ if (--_skullBugCtr == 0) {
+ _skullBugCtr = _vm->getRandom(150) + 500;
+ insertRandomBugObj(5);
+ }
+ }
+
+ if (_stompCounter2 > 0)
+ --_stompCounter2;
+
+ if (_totalBugsCount < kMaxBugsCount && _vm->getRandom(_stompCounter2) == 0) {
+ int testTbl[4];
+ int maxKindCount = 0, objKind = 0;
+
+ _stompCounter2 = _stompCounter1;
+
+ for (int i = 0; i < 4; ++i)
+ testTbl[i] = _vm->getRandom(_bugsChanceByKind[i] - _bugsCountByKind[i]);
+
+ for (int i = 0; i < 4; ++i) {
+ if (testTbl[i] >= maxKindCount) {
+ maxKindCount = testTbl[i];
+ objKind = i + 1;
+ }
+ }
+
+ if (objKind)
+ insertRandomBugObj(objKind);
+
+ }
+
+ updateObjs(mouseButtons);
+ updateFootObj(2);
+
+ if (--_countdown10 == 0) {
+ _countdown10 = 140;
+ if (_stompCounter1 > 20)
+ --_stompCounter1;
+ }
+
+ return true;
+}
+
+bool MinigameBbAnt::updateStatus2(int mouseX, int mouseY, uint mouseButtons) {
+
+ _objects[0].x = mouseX;
+ _objects[0].y = mouseY;
+
+ if (_objects[0].x >= 320)
+ _objects[0].x = 320 - 1;
+ if (_objects[0].y >= 240)
+ _objects[0].y = 240 - 1;
+ if (_objects[0].x < 0)
+ _objects[0].x = 0;
+ if (_objects[0].y < 0)
+ _objects[0].y = 0;
+
+ if (_countdown6 > 0) {
+ if (--_countdown6 == 0) {
+ _countdown4 = 150;
+ playSound(15, true);
+ }
+ } else if (_countdown4 > 0) {
+ if (--_countdown4 == 0) {
+ _countdown3 = 150;
+ } else if (_countdown5 > 0) {
+ ++_countdown4;
+ ++_score;
+ if (--_countdown5 == 0) {
+ stopSound(15);
+ _bugsChanceByKind[5] = 10;
+ _countdown7 = 40;
+ _countdown4 = 10 * (13 - _counter1);
+ return true;
+ }
+ } else {
+ if (--_countdown7 == 0) {
+ bool flag1 = false;
+ _countdown7 = _bugsChanceByKind[5];
+ for (int i = 3; i < 12 && !flag1; ++i) {
+ Obj *obj = &_objects[i];
+ if (obj->status == 13) {
+ const ObjInit *objInit = getObjInit(i - 3);
+ obj->x = objInit->x << 16;
+ obj->y = objInit->y << 16;
+ obj->anim = objInit->anim3;
+ obj->frameIndex = 0;
+ obj->ticks = _objects[0].anim->frameTicks[0];
+ obj->status = 9;
+ obj->damageCtr = 0;
+ obj->priority = 600;
+ ++_counter1;
+ playSound(15);
+ flag1 = true;
+ }
+ }
+ }
+ }
+ } else if (_countdown3 > 0) {
+ if ((mouseButtons & kLeftButtonDown) || (mouseButtons & kRightButtonDown) || (--_countdown3 == 0)) {
+ _levelTimeDelay = 58;
+ _levelTimeLeft = 30;
+ _gameState = 1;
+ _gameTicks = 0;
+ ++_counter4;
+ }
+ }
+
+ return true;
+}
+
+bool MinigameBbAnt::updateStatus3(int mouseX, int mouseY, uint mouseButtons) {
+ if (!isSoundPlaying(9) && _fromMainGame) {
+ _vm->_system->delayMillis(1000);
+ _gameDone = true;
+ }
+ return true;
+}
+
+void MinigameBbAnt::getRandomBugObjValues(int &x, int &y, int &animIndexIncr, int &field30) {
+ field30 = _vm->getRandom(4);
+ switch (field30) {
+ case 0:
+ y = -5;
+ x = _vm->getRandom(190) + 120;
+ animIndexIncr = 4;
+ break;
+ case 1:
+ x = 325;
+ y = _vm->getRandom(220) + 10;
+ animIndexIncr = 2;
+ break;
+ case 2:
+ y = 245;
+ x = _vm->getRandom(300) + 10;
+ animIndexIncr = 0;
+ break;
+ case 3:
+ x = -5;
+ y = _vm->getRandom(190) + 120;
+ animIndexIncr = 6;
+ break;
+ }
+}
+
+void MinigameBbAnt::insertBugSmokeObj(int x, int y, int bugObjIndex) {
+ Obj *obj = getFreeObject();
+ if (obj) {
+ Obj *bugObj = &_objects[bugObjIndex];
+ bugObj->hasSmoke = true;
+ obj->kind = 7;
+ obj->x = x;
+ obj->y = y;
+ obj->priority = 950;
+ if (bugObj->status >= 4 && (bugObj->status <= 6 || bugObj->status == 8)) {
+ obj->xIncr = 0;
+ obj->yIncr = (-1 << 16);
+ } else {
+ obj->xIncr = bugObj->xIncr / 8;
+ obj->yIncr = bugObj->yIncr / 8;
+ }
+ obj->anim = getAnimation(158);
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ }
+}
+
+void MinigameBbAnt::insertSmokeObj(int x, int y) {
+ Obj *obj = getFreeObject();
+ if (obj) {
+ obj->kind = 7;
+ obj->x = x;
+ obj->y = y;
+ obj->priority = 950;
+ obj->xIncr = 0x2000;
+ obj->yIncr = -0xC000;
+ obj->anim = getAnimation(158);
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ }
+}
+
+void MinigameBbAnt::resetObj(int objIndex) {
+ _objects[objIndex].kind = 0;
+}
+
+void MinigameBbAnt::insertStompObj(int x, int y) {
+ Obj *obj = getFreeObject();
+ if (obj) {
+ obj->kind = 9;
+ obj->x = x;
+ obj->y = y;
+ obj->priority = 2000;
+ obj->xIncr = (0x1E0000 * _stompCount - x + 0x140000) / 15;
+ obj->yIncr = (0xE60000 - y) / 15;
+ obj->anim = getAnimation(130);
+ obj->frameIndex = 0;
+ obj->ticks = 15;
+ _lastStompObj = obj;
+ _hasLastStompObj = true;
+ }
+}
+
+void MinigameBbAnt::removeStompObj(Obj *obj) {
+ ++_stompCount;
+ _hasLastStompObj = false;
+ obj->kind = 0;
+}
+
+void MinigameBbAnt::insertBugObj(int kind, int animIndexIncr, int always0, int x, int y, int field30, int always1) {
+ Obj *obj = getFreeObject();
+ if (obj) {
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(kind);
+ obj->field30 = field30;
+ obj->animIndexIncr = animIndexIncr;
+ obj->kind = kind;
+ obj->x = x << 16;
+ obj->y = y << 16;
+ obj->priority = 610;
+ obj->xIncr = kPosIncrTbl1[0].x << 16;
+ obj->yIncr = kPosIncrTbl1[0].y << 16;
+ obj->anim = objKindAnimTable[0];
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ obj->animIndex = 0;
+ obj->status = 1;
+ obj->damageCtr = 0;
+ obj->hasSmoke = false;
+ obj->flag = 0;
+ ++_bugsCountByKind[kind];
+ ++_totalBugsCount;
+ }
+}
+
+void MinigameBbAnt::removeBugObj(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+ --_totalBugsCount;
+ --_bugsCountByKind[obj->kind];
+ obj->hasSmoke = false;
+ obj->kind = 0;
+}
+
+void MinigameBbAnt::updateBugObjAnim(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ switch (obj->field30) {
+ case 0:
+ obj->animIndexIncr = 4;
+ break;
+ case 1:
+ obj->animIndexIncr = 2;
+ break;
+ case 2:
+ obj->animIndexIncr = 0;
+ break;
+ case 3:
+ obj->animIndexIncr = 6;
+ break;
+ }
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind);
+ obj->xIncr = kPosIncrTbl1[obj->animIndexIncr].x << 16;
+ obj->yIncr = kPosIncrTbl1[obj->animIndexIncr].y << 16;
+ obj->anim = objKindAnimTable[obj->animIndexIncr];
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+}
+
+void MinigameBbAnt::updateObjAnim2(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->animIndexIncr += _vm->getRandom(3) - 1;
+ if (obj->animIndexIncr < 0)
+ obj->animIndexIncr = 7;
+ if (obj->animIndexIncr > 7)
+ obj->animIndexIncr = 0;
+ obj->animIndexIncr += 4;
+ if (obj->animIndexIncr >= 8)
+ obj->animIndexIncr %= 8;
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind);
+ obj->xIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].x << 16;
+ obj->yIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].y << 16;
+ obj->anim = objKindAnimTable[obj->animIndex + obj->animIndexIncr];
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+}
+
+void MinigameBbAnt::insertRandomBugObj(int kind) {
+ int x, y, animIndexIncr, field30;
+ getRandomBugObjValues(x, y, animIndexIncr, field30);
+ insertBugObj(kind, animIndexIncr, 0, x, y, field30, 1);
+}
+
+bool MinigameBbAnt::isBugOutOfScreen(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ return
+ obj->x < (-10 << 16) || obj->x > (330 << 16) ||
+ obj->y < (-10 << 16) || obj->y > (250 << 16);
+}
+
+void MinigameBbAnt::updateObjAnim3(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->animIndexIncr += _vm->getRandom(3) - 1;
+ if (obj->animIndexIncr < 0)
+ obj->animIndexIncr = 7;
+ if (obj->animIndexIncr > 7)
+ obj->animIndexIncr = 0;
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind);
+ obj->xIncr = kPosIncrTbl1[obj->animIndexIncr].x << 16;
+ obj->yIncr = kPosIncrTbl1[obj->animIndexIncr].y << 16;
+ obj->anim = objKindAnimTable[obj->animIndexIncr];
+}
+
+void MinigameBbAnt::updateBugObj1(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+ bool flag1 = false;
+ bool flag2 = false;
+
+ if (--obj->ticks == 0) {
+ ++obj->frameIndex;
+ if (obj->anim->frameCount == obj->frameIndex) {
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ flag1 = true;
+ } else {
+ obj->ticks = obj->anim->frameTicks[obj->frameIndex];
+ flag2 = true;
+ }
+ }
+
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+
+ if (obj->status != 7) {
+ if (obj->damageCtr <= 5) {
+ obj->hasSmoke = false;
+ } else if (!obj->hasSmoke) {
+ obj->smokeCtr = 6;
+ insertBugSmokeObj(obj->x, obj->y, objIndex);
+ } else if (obj->damageCtr > 200 && obj->status != 4 && obj->status != 6) {
+ _score += kScoreTbl[obj->kind];
+ if (obj->status == 3) {
+ _objects[obj->otherObjIndex].status = 9;
+ _objects[obj->otherObjIndex].priority = 600;
+ if (_vm->getRandom(3) == 1 && !isAnySoundPlaying(kSoundTbl4, 10))
+ playSound(kSoundTbl3[_vm->getRandom(3)]);
+ } else {
+ if (_vm->getRandom(3) == 1 && !isAnySoundPlaying(kSoundTbl4, 10))
+ playSound(kSoundTbl2[_vm->getRandom(3)]);
+ }
+ flag1 = false;
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind);
+ obj->hasSmoke = false;
+ obj->status = 4;
+ obj->xIncr = 0;
+ obj->yIncr = 0;
+ obj->anim = objKindAnimTable[16];
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ obj->priority = 605;
+ if (obj->kind == 5) {
+ // Skull Beetle
+ if (_stompCount < 10)
+ insertStompObj(obj->x, obj->y);
+ obj->kind = 4;
+ obj->anim = getObjAnim(70);
+ obj->ticks = obj->anim->frameTicks[0];
+ }
+ } else if (--obj->smokeCtr == 0) {
+ obj->smokeCtr = 6;
+ insertBugSmokeObj(obj->x, obj->y, objIndex);
+ }
+ }
+
+ switch (obj->status) {
+
+ case 1:
+ if (isBugOutOfScreen(objIndex))
+ removeBugObj(objIndex);
+ else if (flag1 && !obj->flag)
+ updateObjAnim3(objIndex);
+ break;
+
+ case 3:
+ // Bug carries candy
+ _objects[obj->otherObjIndex].x = obj->x;
+ _objects[obj->otherObjIndex].y = obj->y;
+ if (isBugOutOfScreen(objIndex)) {
+ _objects[obj->otherObjIndex].status = 13;
+ _objects[obj->otherObjIndex].x = (500 << 16);
+ _objects[obj->otherObjIndex].y = (500 << 16);
+ removeBugObj(objIndex);
+ --_counter1;
+ }
+ break;
+
+ case 4:
+ if (flag1) {
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind);
+ obj->status = 6;
+ obj->xIncr = 0;
+ obj->yIncr = 0;
+ obj->anim = objKindAnimTable[17];
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ }
+ break;
+
+ case 6:
+ if (flag1) {
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(obj->kind);
+ obj->status = 7;
+ obj->xIncr = kPosIncrTbl2[obj->animIndexIncr].x << 16;
+ obj->yIncr = kPosIncrTbl2[obj->animIndexIncr].y << 16;
+ obj->anim = objKindAnimTable[obj->animIndexIncr + 8];
+ obj->frameIndex = 0;
+ obj->ticks = obj->anim->frameTicks[0];
+ obj->animIndex = 8;
+ obj->priority = 610;
+ }
+ break;
+
+ case 7:
+ if (isBugOutOfScreen(objIndex))
+ removeBugObj(objIndex);
+ break;
+
+ case 8:
+ if (--obj->counter != 0) {
+ if (flag2 && obj->frameIndex == 13) {
+ obj->frameIndex = 4;
+ obj->ticks = obj->anim->frameTicks[4];
+ }
+ } else {
+ obj->status = obj->status2;
+ obj->anim = obj->anim2;
+ obj->frameIndex = obj->frameIndex2;
+ obj->ticks = obj->ticks2;
+ obj->xIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].x << 16;
+ obj->yIncr = kPosIncrTbl1[obj->animIndex + obj->animIndexIncr].y << 16;
+ obj->priority = 610;
+ }
+ break;
+
+ }
+
+}
+
+void MinigameBbAnt::updateObjKind2(int objIndex) {
+ updateBugObj1(objIndex);
+}
+
+void MinigameBbAnt::updateObjKind3(int objIndex) {
+ updateBugObj1(objIndex);
+}
+
+void MinigameBbAnt::updateObjKind4(int objIndex) {
+ updateBugObj1(objIndex);
+}
+
+void MinigameBbAnt::updateObjKind5(int objIndex) {
+ ++_skullBugCtr;
+ updateBugObj1(objIndex);
+}
+
+void MinigameBbAnt::updateStompObj(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+ if (--obj->ticks == 0)
+ removeStompObj(obj);
+}
+
+void MinigameBbAnt::updateSmokeObj(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+
+ if (--obj->ticks == 0) {
+ ++obj->frameIndex;
+ if (obj->anim->frameCount == obj->frameIndex)
+ resetObj(objIndex);
+ else
+ obj->ticks = obj->anim->frameTicks[obj->frameIndex];
+ }
+}
+
+void MinigameBbAnt::updateFootObj(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+
+ switch (obj->status) {
+
+ case 1:
+ obj->xIncr = -0x8000;
+ obj->yIncr = (-4 << 16);
+ obj->status = 2;
+ _stompCounter1 += 5;
+ _stompCounter2 = 100;
+ break;
+
+ case 2:
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+ obj->yIncr += 0x2000;
+ if (obj->y < (20 << 16)) {
+ obj->xIncr = 0x8000;
+ obj->yIncr = (7 << 16);
+ obj->status = 3;
+ }
+ break;
+
+ case 3:
+ obj->x += obj->xIncr;
+ obj->y += obj->yIncr;
+ obj->yIncr += 0x2000;
+ if (obj->y >= 0x4B0000) {
+ obj->x = (40 << 16);
+ obj->y = (75 << 16);
+ obj->status = 4;
+ _stompDelay1 = 6;
+ _stompY = 0;
+ playSound(14);
+ }
+ break;
+
+ case 4:
+ if (--_stompDelay1 == 0) {
+ _gameTicks = 0;
+ if (_stompDelay1 % 2)
+ _stompY = _stompY < 1 ? -8 : 0;
+ } else {
+ obj->status = 0;
+ _stompX = 0;
+ _stompY = 0;
+ // Stun all bugs
+ for (int i = 12; i < kMaxObjectsCount; ++i) {
+ Obj *bugObj = &_objects[i];
+ if (bugObj->kind >= 1 && bugObj->kind <= 5) {
+ bugObj->counter = _vm->getRandom(200) + 360;
+ const ObjAnimation * const *objKindAnimTable = getObjKindAnimTable(bugObj->kind);
+ if (bugObj->status == 8) {
+ bugObj->hasSmoke = false;
+ bugObj->xIncr = 0;
+ bugObj->yIncr = 0;
+ bugObj->status2 = 7;
+ bugObj->anim2 = objKindAnimTable[bugObj->animIndexIncr + 8];
+ bugObj->frameIndex2 = 0;
+ bugObj->ticks2 = obj->anim->frameTicks[0];
+ bugObj->anim = objKindAnimTable[17];
+ bugObj->frameIndex = 0;
+ bugObj->ticks = _vm->getRandom(4) + obj->anim->frameTicks[0];
+ bugObj->animIndex = 8;
+ } else {
+ if (bugObj->status == 3) {
+ bugObj->priority = 610;
+ _objects[bugObj->otherObjIndex].status = 9;
+ _objects[bugObj->otherObjIndex].priority = 600;
+ }
+ bugObj->hasSmoke = false;
+ bugObj->xIncr = 0;
+ bugObj->yIncr = 0;
+ bugObj->status2 = 1;
+ bugObj->anim2 = bugObj->anim;
+ bugObj->frameIndex2 = bugObj->frameIndex;
+ bugObj->ticks2 = bugObj->ticks;
+ bugObj->anim = objKindAnimTable[17];
+ bugObj->frameIndex = 0;
+ bugObj->ticks = _vm->getRandom(4) + obj->anim->frameTicks[0];
+ }
+ bugObj->status = 8;
+ bugObj->priority = 605;
+ }
+ }
+ }
+ break;
+
+ }
+
+}
+
+bool MinigameBbAnt::isBugAtCandy(int objIndex, int &candyObjIndex) {
+ Obj *obj = &_objects[objIndex];
+ bool result = false;
+
+ if (obj->kind >= 1 && obj->kind <= 4) {
+ const BBRect &frameRect1 = obj->anim->frameRects[obj->frameIndex];
+ const int obj1X1 = frameRect1.x + (obj->x >> 16);
+ const int obj1Y1 = frameRect1.y + (obj->y >> 16);
+ const int obj1X2 = obj1X1 + frameRect1.width;
+ const int obj1Y2 = obj1Y1 + frameRect1.height;
+ for (int i = 3; i < 12 && !result; ++i) {
+ Obj *obj2 = &_objects[i];
+ const BBRect &frameRect2 = obj->anim->frameRects[obj2->frameIndex]; // sic
+ const int obj2X1 = (obj2->x >> 16) + frameRect2.x;
+ const int obj2Y1 = (obj2->y >> 16) + frameRect2.y;
+ const int obj2X2 = obj2X1 + frameRect2.width;
+ const int obj2Y2 = obj2Y1 + frameRect2.height;
+ if (obj2->status == 9 && obj1X1 <= obj2X2 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1) {
+ result = true;
+ candyObjIndex = i;
+ }
+ }
+ }
+ return result;
+}
+
+bool MinigameBbAnt::isMagGlassAtBug(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+ Obj *obj0 = &_objects[0];
+ bool result = false;
+
+ if (obj->kind >= 1 && obj->kind <= 5) {
+ const BBRect &frameRect1 = obj0->anim->frameRects[0];
+ const int obj1X1 = obj0->x + frameRect1.x;
+ const int obj1Y1 = obj0->y + frameRect1.y;
+ const int obj1X2 = obj1X1 + frameRect1.width;
+ const int obj1Y2 = obj1Y1 + frameRect1.height;
+ const BBRect &frameRect2 = obj->anim->frameRects[obj->frameIndex];
+ const int obj2X1 = (obj->x >> 16) + frameRect2.x;
+ const int obj2Y1 = (obj->y >> 16) + frameRect2.y;
+ const int obj2X2 = obj2X1 + frameRect2.width;
+ const int obj2Y2 = obj2Y1 + frameRect2.height;
+ if (obj2X2 >= obj1X1 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1)
+ result = true;
+ }
+ return result;
+}
+
+bool MinigameBbAnt::isMagGlassAtBeavisLeg(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+ Obj *magGlassObj = &_objects[0];
+ bool result = false;
+
+ const BBRect &frameRect1 = magGlassObj->anim->frameRects[0];
+ const int obj1X1 = magGlassObj->x + frameRect1.x;
+ const int obj1Y1 = magGlassObj->y + frameRect1.y;
+ const int obj1X2 = obj1X1 + frameRect1.width;
+ const int obj1Y2 = obj1Y1 + frameRect1.height;
+ const BBRect &frameRect2 = obj->anim->frameRects[obj->frameIndex];
+ const int obj2X1 = (obj->x >> 16) + frameRect2.x;
+ const int obj2Y1 = (obj->y >> 16) + frameRect2.y;
+ const int obj2X2 = obj2X1 + frameRect2.width;
+ const int obj2Y2 = obj2Y1 + frameRect2.height;
+ if (obj2X2 >= obj1X1 && obj1X2 >= obj2X1 && obj1Y1 <= obj2Y2 && obj1Y2 >= obj2Y1)
+ result = true;
+ return result;
+}
+
+bool MinigameBbAnt::testObj5(int objIndex) {
+ Obj *obj = &_objects[objIndex];
+ bool result = false;
+ if (obj->kind >= 1 && obj->kind <= 5) {
+ const int x = obj->x >> 16;
+ const int y = obj->y >> 16;
+ if (x < 0 || x >= 110 || y < 0 || y >= 110) {
+ obj->flag = 0;
+ } else if (!obj->flag) {
+ obj->flag = 1;
+ result = true;
+ }
+ }
+ return result;
+}
+
+void MinigameBbAnt::updateObjs(uint mouseButtons) {
+
+ for (int i = 12; i < kMaxObjectsCount; ++i) {
+ Obj *obj = &_objects[i];
+
+ if (obj->kind) {
+
+ if ((mouseButtons & kLeftButtonClicked) && isMagGlassAtBug(i))
+ obj->damageCtr += 100;
+
+ if (obj->status == 1) {
+ int candyObjIndex;
+ if (isBugAtCandy(i, candyObjIndex)) {
+ obj->status = 3;
+ obj->otherObjIndex = candyObjIndex;
+ _objects[candyObjIndex].otherObjIndex = i;
+ _objects[candyObjIndex].status = 10;
+ _objects[candyObjIndex].priority = 620;
+ _objects[candyObjIndex].status = 11;
+ _objects[candyObjIndex].anim = getObjInit(candyObjIndex - 3)->anim3;
+ updateBugObjAnim(i);
+ if (_vm->getRandom(3) == 1 && !isAnySoundPlaying(kSoundTbl4, 10))
+ playSound(kSoundTbl1[_vm->getRandom(4)]);
+ }
+ }
+
+ if (testObj5(i)) {
+ updateObjAnim2(i);
+ }
+
+ if (obj->damageCtr) {
+ --obj->damageCtr;
+ if (!isSoundPlaying(13))
+ playSound(13);
+ }
+
+ switch (obj->kind) {
+ case 1:
+ updateBugObj1(i);
+ break;
+ case 2:
+ updateObjKind2(i);
+ break;
+ case 3:
+ updateObjKind3(i);
+ break;
+ case 4:
+ updateObjKind4(i);
+ break;
+ case 5:
+ updateObjKind5(i);
+ break;
+ case 7:
+ updateSmokeObj(i);
+ break;
+ case 9:
+ updateStompObj(i);
+ break;
+ }
+
+ }
+
+ }
+
+}
+
+int MinigameBbAnt::run(bool fromMainGame) {
+
+ memset(_objects, 0, sizeof(_objects));
+
+ _numbersAnim = getAnimation(167);
+
+ _backgroundSpriteIndex = 303;
+ _titleScreenSpriteIndex = 304;
+
+ _fromMainGame = fromMainGame;
+
+ _hiScore = 0;
+ if (!_fromMainGame)
+ _hiScore = loadHiscore(kMinigameBbAnt);
+
+ _gameState = 0;
+ _gameResult = 0;
+ _gameDone = false;
+ initObjects();
+ initVars();
+
+ _spriteModule = new SpriteModule();
+ _spriteModule->load("bbant/bbant.000");
+
+ Palette palette = _spriteModule->getPalette();
+ _vm->_screen->setPalette(palette);
+
+ loadSounds();
+
+ _gameTicks = 0;
+ playSound(12, true);
+
+ while (!_vm->shouldQuit() &&!_gameDone) {
+ _vm->updateEvents();
+ update();
+ }
+
+ _vm->_sound->unloadSounds();
+
+ if (!_fromMainGame)
+ saveHiscore(kMinigameBbAnt, _hiScore);
+
+ delete _spriteModule;
+
+ return _gameResult;
+}
+
+void MinigameBbAnt::update() {
+
+ int currTicks, inputTicks;
+
+ if (_gameTicks > 0) {
+ currTicks = _vm->_system->getMillis();
+ inputTicks = 3 * (currTicks - _gameTicks) / 50;
+ _gameTicks = currTicks - (currTicks - _gameTicks - 50 * inputTicks / 3);
+ } 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 MinigameBbAnt::scale2x(int x, int y) {
+ Graphics::Surface *surface = _vm->_screen->_surface;
+
+ int srcX = x + 14, srcY = y + 14;
+ int srcW = kScaleDim, srcH = kScaleDim;
+
+ if (srcX < 0) {
+ srcW += srcX;
+ srcX = 0;
+ }
+
+ if (srcY < 0) {
+ srcH += srcY;
+ srcY = 0;
+ }
+
+ if (srcX + srcW >= 320)
+ srcW = 320 - srcX - 1;
+
+ if (srcY + srcH >= 240)
+ srcH = 240 - srcY - 1;
+
+ for (int yc = 0; yc < srcH; ++yc) {
+ byte *src = (byte*)surface->getBasePtr(srcX, srcY + yc);
+ memcpy(&_scaleBuf[yc * kScaleDim], src, srcW);
+ }
+
+ int dstX = x, dstY = y;
+ int dstW = 2 * kScaleDim, dstH = 2 * kScaleDim;
+
+ if (dstX < 0) {
+ dstW += dstX;
+ dstX = 0;
+ }
+
+ if (dstY < 0) {
+ dstH += dstY;
+ dstY = 0;
+ }
+
+ if (dstX + dstW >= 320)
+ dstW = 320 - dstX - 1;
+
+ if (dstY + dstH >= 240)
+ dstH = 240 - dstY - 1;
+
+ int w = MIN(srcW * 2, dstW), h = MIN(srcH * 2, dstH);
+
+ for (int yc = 0; yc < h; ++yc) {
+ byte *src = _scaleBuf + kScaleDim * (yc / 2);
+ byte *dst = (byte*)surface->getBasePtr(dstX, dstY + yc);
+ for (int xc = 0; xc < w; ++xc)
+ dst[xc] = src[xc / 2];
+ }
+
+}
+
+void MinigameBbAnt::loadSounds() {
+ for (uint i = 0; i < kSoundFilenamesCount; ++i) {
+ Common::String filename = Common::String::format("bbant/%s", kSoundFilenames[i]);
+ _vm->_sound->loadSound(filename.c_str());
+ }
+}
+
+} // End of namespace Bbvs