/* 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 3 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, see . * */ #include "got/game/shot_movement.h" #include "got/events.h" #include "got/game/move.h" #include "got/game/move_patterns.h" #include "got/game/object.h" #include "got/vars.h" namespace Got { int shotMovementNone(Actor *actor); int shotMovementOne(Actor *actor); int shotMovementTwo(Actor *actor); int shotMovementThree(Actor *actor); int shotMovementFour(Actor *actor); int shotMovementFive(Actor *actor); int shotMovementSix(Actor *actor); int shotMovementSeven(Actor *actor); int shotMovementEight(Actor *actor); int shotMovementNine(Actor *actor); int shotMovementTen(Actor *actor); int shotMovementEleven(Actor *actor); int shotMovementTwelve(Actor *actor); int shotMovementThirteen(Actor *actor); int (*const shotMovementFunc[])(Actor *actor) = { shotMovementNone, shotMovementOne, shotMovementTwo, shotMovementThree, shotMovementFour, shotMovementFive, shotMovementSix, shotMovementSeven, shotMovementEight, shotMovementNine, shotMovementTen, shotMovementEleven, shotMovementTwelve, shotMovementThirteen }; void next_shot_frame(Actor *actor) { if (actor->_directions == 4 && actor->_framesPerDirection == 1) { actor->_nextFrame = actor->_lastDir; actor->_dir = 0; } else { const int fcount = actor->_frameCount - 1; if (fcount <= 0) { actor->_nextFrame++; if (actor->_nextFrame > 3) actor->_nextFrame = 0; actor->_frameCount = actor->_frameSpeed; } else actor->_frameCount = fcount; } } // Boss - snake int shotMovementNone(Actor *actor) { actor->_temp3--; if (!actor->_temp3) { actorDestroyed(actor); if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; } next_shot_frame(actor); if (actor->_directions == 1) return 0; return actor->_lastDir; } int shotMovementOne(Actor *actor) { int x1 = 0, y1 = 0; const int d = actor->_lastDir; switch (d) { case 0: x1 = actor->_x; y1 = actor->_y - 2; break; case 1: x1 = actor->_x; y1 = actor->_y + 2; break; case 2: x1 = actor->_x - 2; y1 = actor->_y; break; case 3: x1 = actor->_x + 2; y1 = actor->_y; break; default: break; } if (!checkMove3(x1, y1, actor)) { actorDestroyed(actor); if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; } else { next_shot_frame(actor); actor->_lastDir = d; } if (actor->_directions == 1) return 0; if (actor->_directions == 4 && actor->_framesPerDirection == 1) return 0; return d; } int shotMovementTwo(Actor *actor) { int x1 = 0, y1 = 0; const int d = actor->_lastDir; switch (d) { case 0: x1 = actor->_x; y1 = actor->_y - 2; break; case 1: x1 = actor->_x; y1 = actor->_y + 2; break; case 2: x1 = actor->_x - 2; y1 = actor->_y; break; case 3: x1 = actor->_x + 2; y1 = actor->_y; break; default: break; } if (!checkMove4(x1, y1, actor)) { actorDestroyed(actor); if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; } else { next_shot_frame(actor); actor->_lastDir = d; } if (actor->_directions == 1) return 0; if (actor->_directions == 4 && actor->_framesPerDirection == 1) return 0; return d; } // Serpent fire int shotMovementThree(Actor *actor) { const int d = actor->_lastDir; actor->_x -= 2; actor->_temp3--; actor->_temp4--; if (overlap(_G(thorX1) - 1, _G(thorY1) - 1, _G(thorX2) + 1, _G(thorY2) + 1, actor->_x, actor->_y, actor->_x + 15, actor->_y + 15)) { actor->_moveType = 0; actor->_speed = 6; thorDamaged(actor); actor->_x += 2; } if (!actor->_temp4) { actor->_temp4 = actor->_temp5; actor->_speed++; if (actor->_speed > 6) actor->_moveType = 0; } if (!actor->_temp3) { actorDestroyed(actor); if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; } else { next_shot_frame(actor); actor->_lastDir = d; } if (actor->_directions == 1) return 0; return d; } // Wraith balls int shotMovementFour(Actor *actor) { if (actor->_temp1) { actor->_temp1--; if (!actor->_temp1) { actorDestroyed(actor); _G(appleDropCounter++); if (_G(appleDropCounter) == 4) { if (dropObject(actor, 5)) _G(appleDropCounter) = 0; else _G(appleDropCounter) = 3; } else dropObject(actor, 3); return 0; } } if (overlap(_G(thor)->_x - 1, _G(thor)->_y - 1, _G(thorX2) + 1, _G(thorY2) + 1, actor->_x, actor->_y, actor->_x + 15, actor->_y + 15)) { thorDamaged(actor); actorDestroyed(actor); return 0; } int x1 = actor->_x; int y1 = actor->_y; int yd = 0; int xd = 0; int d = actor->_lastDir; if ((x1 > (_G(thorX1)) + 1)) xd = -2; else if ((x1 < (_G(thorX1)) - 1)) xd = 2; if (actor->_actorNum == 1) { if (y1 < (_G(thorY1) - 6)) yd = 2; else if (y1 > (_G(thorY1) - 6)) yd = -2; } else { if (y1 < (_G(thorRealY1) - 1)) yd = 2; else if (y1 > (_G(thorRealY1) + 1)) yd = -2; } if (xd && yd) { if (xd == -2 && ABS(yd) == 2) d = 2; else if (xd == 2 && ABS(yd) == 2) d = 3; x1 += xd; y1 += yd; if (checkMove3(x1, y1, actor)) { nextFrame(actor); actor->_lastDir = d; if (actor->_directions == 1) return 0; return d; } } else if (xd == 0 && yd == 2) d = 1; else if (xd == 0 && yd == -2) d = 0; else if (xd == 2 && yd == 0) d = 3; else if (xd == -2 && yd == 0) d = 2; x1 = actor->_x; y1 = actor->_y; actor->_toggle ^= 1; if (actor->_toggle) { if (xd) { x1 += xd; if (checkMove3(x1, y1, actor)) { if (xd > 0) d = 3; else d = 2; nextFrame(actor); actor->_lastDir = d; if (actor->_directions == 1) return 0; return d; } x1 = actor->_x; } if (yd) { y1 += yd; if (checkMove3(x1, y1, actor)) { if (yd > 0) d = 1; else d = 0; nextFrame(actor); actor->_lastDir = d; if (actor->_directions == 1) return 0; return d; } } } else { if (yd) { y1 += yd; if (checkMove3(x1, y1, actor)) { if (yd > 0) d = 1; else d = 0; nextFrame(actor); actor->_lastDir = d; if (actor->_directions == 1) return 0; return d; } y1 = actor->_y; } if (xd) { x1 += xd; if (checkMove3(x1, y1, actor)) { if (xd > 0) d = 3; else d = 2; nextFrame(actor); actor->_lastDir = d; if (actor->_directions == 1) return 0; return d; } } } checkMove3(actor->_x, actor->_y, actor); nextFrame(actor); actor->_lastDir = d; if (actor->_directions == 1) return 0; return d; } // No move, frame cycle int shotMovementFive(Actor *actor) { next_shot_frame(actor); if (actor->_directions == 1) return 0; return actor->_lastDir; } // Wraith spots int shotMovementSix(Actor *actor) { actor->_temp1--; if (!actor->_temp1) { actorDestroyed(actor); if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; } else next_shot_frame(actor); if (actor->_directions == 1) return 0; return actor->_lastDir; } #define YV actor->_i1 #define YC actor->_i2 #define BC actor->_i3 #define YD actor->_i4 #define XD actor->_i5 #define XC actor->_i6 #define IV 100 #define IC 50 // Skull drop int shotMovementSeven(Actor *actor) { if (actor->_temp3) { actor->_temp3--; goto done; } if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY, _G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15)) thorDamaged(actor); actor->_temp2++; if (actor->_temp2 > 2) { if (actor->_temp4) actor->_temp4--; actor->_temp2 = 0; } actor->_temp3 = actor->_temp4; actor->_y += 2; if (actor->_y > 160 - 36) { actor->_x += (4 - g_events->getRandomNumber(8)); actor->_moveType = 8; YV = IV; YC = 0; BC = IC; YD = 0; XC = 3; if (actor->_x < 150) XD = 1; else XD = 0; } done: next_shot_frame(actor); if (actor->_directions == 1) return 0; return actor->_lastDir; } // Skull bounce int shotMovementEight(Actor *actor) { int x = actor->_x; int y = actor->_y; XC--; if (!XC) { XC = 3; if (XD) x += 2; else x -= 2; } YC += YV; if (YC > (IV - 1)) { if (!YD) { YV -= 8; YC -= IV; y -= 2; } else { YV += 8; YC -= IV; y += 2; } } if (YV < 0) { YV = 0; BC = 1; } if (YV > IV) { YV = IV; BC = 1; } BC--; if (!BC) { BC = IC; if (YD) YV = IV; YD ^= 1; } if (y > 164) y = 164; // 8 311 if (x < 1 || x > (319 - actor->_sizeX)) { if (!actor->_dead) if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; actorDestroyed(actor); } if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY, _G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15)) thorDamaged(actor); actor->_x = x; actor->_y = y; //done: next_shot_frame(actor); if (actor->_directions == 1) return 0; return actor->_lastDir; } // Skull explode int shotMovementNine(Actor *actor) { actor->_nextFrame++; if (actor->_nextFrame == 3) { _G(actor[actor->_creator])._currNumShots--; actorDestroyed(actor); return 0; } if (actor->_directions == 1) return 0; return actor->_lastDir; } // Skull - stalagtites int shotMovementTen(Actor *actor) { bool check = false; actor->_y += 2; if (overlap(actor->_x, actor->_y, actor->_x + actor->_sizeX, actor->_y + actor->_sizeY, _G(thor)->_x, _G(thor)->_y + 4, _G(thor)->_x + 15, _G(thor)->_y + 15)) { thorDamaged(actor); check = true; } if (actor->_y > 160 || check) { if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; actorDestroyed(actor); } return 0; } #undef YD #undef XD #define YA actor->_i1 #define XA actor->_i2 #define YD actor->_i3 #define XD actor->_i4 #define DIR actor->_i5 #define CNT actor->_i6 void calc_angle(const int x1, const int y1, const int x2, const int y2, Actor *actor) { if (x1 < x2) { XA = -2; XD = x2 - x1; } else if (x1 > x2) { XA = 2; XD = x1 - x2; } else { XA = 0; XD = 0; } if (y1 < y2) { YA = -2; YD = y2 - y1; } else if (y1 > y2) { YA = 2; YD = y1 - y2; } else { YA = 0; YD = 0; } if (YD >= XD) DIR = 1; else DIR = 0; CNT = 0; } // Angle throw int shotMovementEleven(Actor *actor) { int x1 = actor->_x; int y1 = actor->_y; if (!actor->_temp1) { calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor); actor->_temp1 = 1; } if (DIR) { y1 += YA; CNT += XD; if (CNT >= YD) { x1 += XA; CNT -= YD; } } else { x1 += XA; CNT += YD; if (CNT >= XD) { y1 += YA; CNT -= XD; } } if (!checkMove3(x1, y1, actor)) { if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; actorDestroyed(actor); } else nextFrame(actor); if (actor->_directions == 1) return 0; return actor->_lastDir; } // Angle throw Loki int shotMovementTwelve(Actor *actor) { int x1 = actor->_x; int y1 = actor->_y; if (!actor->_temp5) { calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor); actor->_temp5 = 1; } if (DIR) { y1 += YA; CNT += XD; if (CNT >= YD) { x1 += XA; CNT -= YD; } } else { x1 += XA; CNT += YD; if (CNT >= XD) { y1 += YA; CNT -= XD; } } if (x1 < 16 || x1 > 287 || y1 < 16 || y1 > 159) { calc_angle(g_events->getRandomNumber(319), g_events->getRandomNumber(191), x1, y1, actor); actor->_moveType = 13; actor->_temp4 = 240; actor->_nextFrame = 2; } else { if (overlap(x1 + 2, y1 + 2, x1 + 14, y1 + 14, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2))) { thorDamaged(actor); } actor->_x = x1; actor->_y = y1; } const int fcount = actor->_frameCount - 1; if (fcount <= 0) { actor->_nextFrame++; if (actor->_nextFrame > 1) actor->_nextFrame = 0; actor->_frameCount = actor->_frameSpeed; } else actor->_frameCount = fcount; if (actor->_directions == 1) return 0; return actor->_lastDir; } // Angle throw Loki-2 int shotMovementThirteen(Actor *actor) { int x1 = actor->_x; int y1 = actor->_y; if (!actor->_temp5) { calc_angle(_G(thorX1), _G(thorRealY1), x1, y1, actor); actor->_temp5 = 1; } if (DIR) { y1 += YA; CNT += XD; if (CNT >= YD) { x1 += XA; CNT -= YD; } } else { x1 += XA; CNT += YD; if (CNT >= XD) { y1 += YA; CNT -= XD; } } if (actor->_temp4) actor->_temp4--; if (!actor->_temp4) { if (_G(actor[actor->_creator])._currNumShots) _G(actor[actor->_creator])._currNumShots--; actorDestroyed(actor); _G(appleDropCounter++); if (_G(appleDropCounter) > 4) { if (dropObject(actor, 5)) _G(appleDropCounter) = 0; else _G(appleDropCounter) = 4; } else dropObject(actor, 4); return 0; } if (x1 < 16 || x1 > 287 || y1 < 16 || y1 > 159) { if (x1 < 16 || x1 > 287) XA = 0 - XA; else YA = 0 - YA; } else { if (overlap(x1 + 4, y1 + 4, x1 + 12, y1 + 12, _G(thorX1), _G(thorY1), _G(thorX2), _G(thorY2))) { thorDamaged(actor); } actor->_x = x1; actor->_y = y1; } const int fcount = actor->_frameCount - 1; if (fcount <= 0) { actor->_nextFrame++; if (actor->_nextFrame > 3) actor->_nextFrame = 2; actor->_frameCount = actor->_frameSpeed; } else actor->_frameCount = fcount; if (actor->_directions == 1) return 0; return actor->_lastDir; } } // namespace Got