diff options
Diffstat (limited to 'engines/gnap/grid.cpp')
-rw-r--r-- | engines/gnap/grid.cpp | 1392 |
1 files changed, 1392 insertions, 0 deletions
diff --git a/engines/gnap/grid.cpp b/engines/gnap/grid.cpp new file mode 100644 index 0000000000..522c72c491 --- /dev/null +++ b/engines/gnap/grid.cpp @@ -0,0 +1,1392 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "gnap/gnap.h" +#include "gnap/datarchive.h" +#include "gnap/gamesys.h" +#include "gnap/resource.h" + +namespace Gnap { + +void GnapEngine::initSceneGrid(int gridMinX, int gridMinY, int gridMaxX, int gridMaxY) { + _gridMinX = gridMinX; + _gridMinY = gridMinY; + _gridMaxX = gridMaxX; + _gridMaxY = gridMaxY; + _gnapGridX = 410 - gridMinX; + _gnapGridY = 450 - gridMinY; + _platGridX = 396 - gridMinX; + _platGridY = 347 - gridMinY; +} + +int GnapEngine::getGnapWalkSequenceId(int deltaX, int deltaY) { + static const int _gnapWalkSequenceIds[9] = { + 0x7B2, 0x000, 0x7B4, + 0x7AD, 0x000, 0x7AE, + 0x7B1, 0x000, 0x7B3 + }; + // CHECKME This is a little weird + return _gnapWalkSequenceIds[3 * deltaX + 3 + 1 + deltaY]; +} + +int GnapEngine::getGnapWalkStopSequenceId(int deltaX, int deltaY) { + static const int _gnapWalkStopSequenceIds[9] = { + 0x7BC, 0x7BA, 0x7BA, + 0x7BC, 0x000, 0x7BA, + 0x7BB, 0x7B9, 0x7B9 + }; + // CHECKME This is a little weird + return _gnapWalkStopSequenceIds[3 * deltaX + 3 + 1 + deltaY]; +} + +int GnapEngine::getGnapWalkFacing(int deltaX, int deltaY) { + static const int _gnapWalkFacings[9] = { + 5, 3, 3, + 5, 0, 3, + 7, 1, 1 + }; + // CHECKME This is a little weird + return _gnapWalkFacings[3 * deltaX + 3 + 1 + deltaY]; +} + +bool GnapEngine::isPointBlocked(int gridX, int gridY) { + + if (gridX < 0 || gridX >= _gridMaxX || gridY < 0 || gridY >= _gridMaxY) + return true; + + if ((gridX == _gnapX && gridY == _gnapY) || (gridX == _platX && gridY == _platY)) + return true; + + const int x = _gridMinX + 75 * gridX; + const int y = _gridMinY + 48 * gridY; + + for (int i = 0; i < _hotspotsCount; ++i) { + if (x >= _hotspots[i].x1 && x <= _hotspots[i].x2 && + y >= _hotspots[i].y1 && y <= _hotspots[i].y2 && + !(_hotspots[i].flags & SF_WALKABLE)) + return true; + } + + return false; + +} + +bool GnapEngine::gridSub41F08B(int gridX, int gridY) { + bool result = false; + + _gnapWalkNodesCount = 0; + _gnapWalkDirXIncr = 0; + _gnapWalkDirYIncr = 0; + _gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX); + _gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY); + + if (_gnapWalkDeltaX) + _gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX; + else + _gnapWalkDirX = 0; + + if (_gnapWalkDeltaY) + _gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY; + else + _gnapWalkDirY = 0; + + while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirXIncr; + ++_gnapWalkDirYIncr; + } else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) { + if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + } else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + } else { + _gnapWalkDeltaX = _gnapWalkDirXIncr; + _gnapWalkDeltaY = _gnapWalkDirYIncr; + --_gnapWalkNodesCount; + } + } else { + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + } else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + } else { + _gnapWalkDeltaX = _gnapWalkDirXIncr; + _gnapWalkDeltaY = _gnapWalkDirYIncr; + --_gnapWalkNodesCount; + } + } + ++_gnapWalkNodesCount; + } + + while (_gnapWalkDirXIncr < _gnapWalkDeltaX) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + ++_gnapWalkNodesCount; + } else { + _gnapWalkDeltaX = _gnapWalkDirXIncr; + } + } + + while (_gnapWalkDirYIncr < _gnapWalkDeltaY) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + ++_gnapWalkNodesCount; + } else { + _gnapWalkDeltaY = _gnapWalkDirYIncr; + } + } + + if (gridX + _gnapWalkDirX * _gnapWalkDirXIncr != _gnapWalkDestX || gridY + _gnapWalkDirY * _gnapWalkDirYIncr != _gnapWalkDestY) { + _gnapWalkDestX = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkDestY = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + result = false; + } else { + result = true; + } + + return result; +} + +bool GnapEngine::gridSub41F5FC(int gridX, int gridY, int index) { + _gnapWalkNodesCount = index; + _gnapWalkDirXIncr = 0; + _gnapWalkDirYIncr = 0; + _gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX); + _gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY); + + if (_gnapWalkDeltaX) + _gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX; + else + _gnapWalkDirX = 0; + + if (_gnapWalkDeltaY) + _gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY; + else + _gnapWalkDirY = 0; + + while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirXIncr; + ++_gnapWalkDirYIncr; + } else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) { + if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + } else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + } else + return false; + } else { + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + } else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + } else + return false; + } + ++_gnapWalkNodesCount; + } + + while (_gnapWalkDirXIncr < _gnapWalkDeltaX) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + ++_gnapWalkNodesCount; + } else + return false; + } + + while (_gnapWalkDirYIncr < _gnapWalkDeltaY) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + ++_gnapWalkNodesCount; + } else + return false; + } + + return true; +} + +bool GnapEngine::gridSub41FAD5(int gridX, int gridY, int index) { + _gnapWalkNodesCount = index; + _gnapWalkDirXIncr = 0; + _gnapWalkDirYIncr = 0; + _gnapWalkDeltaX = ABS(_gnapWalkDestX - gridX); + _gnapWalkDeltaY = ABS(_gnapWalkDestY - gridY); + + if (_gnapWalkDeltaX) + _gnapWalkDirX = (_gnapWalkDestX - gridX) / _gnapWalkDeltaX; + else + _gnapWalkDirX = 0; + + if (_gnapWalkDeltaY) + _gnapWalkDirY = (_gnapWalkDestY - gridY) / _gnapWalkDeltaY; + else + _gnapWalkDirY = 0; + + while (_gnapWalkDeltaY < _gnapWalkDeltaX - _gnapWalkDirXIncr) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, gridY)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + ++_gnapWalkNodesCount; + } else + return false; + } + + while (_gnapWalkDeltaX < _gnapWalkDeltaY - _gnapWalkDirYIncr) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(gridX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + ++_gnapWalkNodesCount; + } else + return false; + } + + while (_gnapWalkDirXIncr < _gnapWalkDeltaX && _gnapWalkDirYIncr < _gnapWalkDeltaY) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirXIncr; + ++_gnapWalkDirYIncr; + } else if (_gnapWalkDeltaY - _gnapWalkDirYIncr > _gnapWalkDeltaX - _gnapWalkDirXIncr) { + if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + } else if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + } else + return false; + } else { + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + } else if (!isPointBlocked(_gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + } else + return false; + } + ++_gnapWalkNodesCount; + } + + while (_gnapWalkDirXIncr < _gnapWalkDeltaX) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = gridX + _gnapWalkDirX * _gnapWalkDirXIncr; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = _gnapWalkDestY; + if (!isPointBlocked(_gnapWalkDirX + _gnapWalkNodes[_gnapWalkNodesCount].gridX1, _gnapWalkDestY)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = _gnapWalkDirX; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = 0; + ++_gnapWalkDirXIncr; + ++_gnapWalkNodesCount; + } else + return false; + } + + while (_gnapWalkDirYIncr < _gnapWalkDeltaY) { + _gnapWalkNodes[_gnapWalkNodesCount].gridX1 = _gnapWalkDestX; + _gnapWalkNodes[_gnapWalkNodesCount].gridY1 = gridY + _gnapWalkDirY * _gnapWalkDirYIncr; + if (!isPointBlocked(_gnapWalkDestX, _gnapWalkDirY + _gnapWalkNodes[_gnapWalkNodesCount].gridY1)) { + _gnapWalkNodes[_gnapWalkNodesCount].deltaX = 0; + _gnapWalkNodes[_gnapWalkNodesCount].deltaY = _gnapWalkDirY; + ++_gnapWalkDirYIncr; + ++_gnapWalkNodesCount; + } else + return false; + } + + return true; +} + +bool GnapEngine::gnapFindPath3(int gridX, int gridY) { + int gridIncr = 1; + bool done = false; + + while (!done && gridIncr < _gridMaxX) { + if (!isPointBlocked(gridX + gridIncr, gridY) && gridSub41F5FC(gridX + gridIncr, gridY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX + i; + _gnapWalkNodes[i].gridY1 = gridY; + _gnapWalkNodes[i].deltaX = 1; + _gnapWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(gridX - gridIncr, gridY) && gridSub41F5FC(gridX - gridIncr, gridY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX - i; + _gnapWalkNodes[i].gridY1 = gridY; + _gnapWalkNodes[i].deltaX = -1; + _gnapWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(gridX, gridY + gridIncr) && gridSub41F5FC(gridX, gridY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX; + _gnapWalkNodes[i].gridY1 = gridY + i; + _gnapWalkNodes[i].deltaX = 0; + _gnapWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(gridX, gridY - gridIncr) && gridSub41F5FC(gridX, gridY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX; + _gnapWalkNodes[i].gridY1 = gridY - i; + _gnapWalkNodes[i].deltaX = 0; + _gnapWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(gridX + gridIncr, gridY + gridIncr) && gridSub41F5FC(gridX + gridIncr, gridY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX + i; + _gnapWalkNodes[i].gridY1 = gridY + i; + _gnapWalkNodes[i].deltaX = 1; + _gnapWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(gridX - gridIncr, gridY + gridIncr) && gridSub41F5FC(gridX - gridIncr, gridY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX - i; + _gnapWalkNodes[i].gridY1 = gridY + i; + _gnapWalkNodes[i].deltaX = -1; + _gnapWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(gridX + gridIncr, gridY - gridIncr) && gridSub41F5FC(gridX + gridIncr, gridY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX + i; + _gnapWalkNodes[i].gridY1 = gridY - i; + _gnapWalkNodes[i].deltaX = 1; + _gnapWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(gridX - gridIncr, gridY - gridIncr) && gridSub41F5FC(gridX - gridIncr, gridY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX - i; + _gnapWalkNodes[i].gridY1 = gridY - i; + _gnapWalkNodes[i].deltaX = -1; + _gnapWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(gridX + gridIncr, gridY) && gridSub41FAD5(gridX + gridIncr, gridY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX + i; + _gnapWalkNodes[i].gridY1 = gridY; + _gnapWalkNodes[i].deltaX = 1; + _gnapWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(gridX - gridIncr, gridY) && gridSub41FAD5(gridX - gridIncr, gridY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX - i; + _gnapWalkNodes[i].gridY1 = gridY; + _gnapWalkNodes[i].deltaX = -1; + _gnapWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(gridX, gridY + gridIncr) && gridSub41FAD5(gridX, gridY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX; + _gnapWalkNodes[i].gridY1 = gridY + i; + _gnapWalkNodes[i].deltaX = 0; + _gnapWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(gridX, gridY - gridIncr) && gridSub41FAD5(gridX, gridY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX; + _gnapWalkNodes[i].gridY1 = gridY - i; + _gnapWalkNodes[i].deltaX = 0; + _gnapWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(gridX + gridIncr, gridY + gridIncr) && gridSub41FAD5(gridX + gridIncr, gridY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX + i; + _gnapWalkNodes[i].gridY1 = gridY + i; + _gnapWalkNodes[i].deltaX = 1; + _gnapWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(gridX - gridIncr, gridY + gridIncr) && gridSub41FAD5(gridX - gridIncr, gridY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX - i; + _gnapWalkNodes[i].gridY1 = gridY + i; + _gnapWalkNodes[i].deltaX = -1; + _gnapWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(gridX + gridIncr, gridY - gridIncr) && gridSub41FAD5(gridX + gridIncr, gridY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX + i; + _gnapWalkNodes[i].gridY1 = gridY - i; + _gnapWalkNodes[i].deltaX = 1; + _gnapWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(gridX - gridIncr, gridY - gridIncr) && gridSub41FAD5(gridX - gridIncr, gridY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _gnapWalkNodes[i].gridX1 = gridX - i; + _gnapWalkNodes[i].gridY1 = gridY - i; + _gnapWalkNodes[i].deltaX = -1; + _gnapWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + ++gridIncr; + } + + return done; +} + +bool GnapEngine::gnapWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags) { + + int datNum = flags & 3; + bool done = false; + + _timers[2] = 200; + _timers[3] = 300; + + if (gridX < 0) + gridX = (_leftClickMouseX - _gridMinX + 37) / 75; + + if (gridY < 0) + gridY = (_leftClickMouseY - _gridMinY + 24) / 48; + + _gnapWalkDestX = CLIP(gridX, 0, _gridMaxX - 1); + _gnapWalkDestY = CLIP(gridY, 0, _gridMaxY - 1); + + if (animationIndex >= 0 && _gnapWalkDestX == _platX && _gnapWalkDestY == _platY) + beaverMakeRoom(); + + if (gridSub41F5FC(_gnapX, _gnapY, 0)) + done = true; + + if (!done && gridSub41FAD5(_gnapX, _gnapY, 0)) + done = true; + + if (!done && gnapFindPath3(_gnapX, _gnapY)) + done = true; + + if (!done && gridSub41F08B(_gnapX, _gnapY)) + done = true; + + gnapIdle(); + + int gnapSequenceId = _gnapSequenceId; + int gnapId = _gnapId; + int gnapSequenceDatNum = _gnapSequenceDatNum; + + debug(0, "_gnapWalkNodesCount: %d", _gnapWalkNodesCount); + + for (int index = 0; index < _gnapWalkNodesCount; ++index) { + _gnapWalkNodes[index].id = index + 20 * _gnapWalkNodes[index].gridY1; + if (_gnapWalkNodes[index].deltaX == 1 && _gnapWalkNodes[index].deltaY == 0) { + if (index % 2) { + _gameSys->insertSequence(makeRid(datNum, 0x7AB), _gnapWalkNodes[index].id, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); + _gnapWalkNodes[index].sequenceId = 0x7AB; + gnapSequenceId = 0x7AB; + } else { + _gameSys->insertSequence(makeRid(datNum, 0x7AC), _gnapWalkNodes[index].id, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); + _gnapWalkNodes[index].sequenceId = 0x7AC; + gnapSequenceId = 0x7AC; + } + } else if (_gnapWalkNodes[index].deltaX == -1 && _gnapWalkNodes[index].deltaY == 0) { + if (index % 2) { + _gameSys->insertSequence(makeRid(datNum, 0x7AF), _gnapWalkNodes[index].id, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); + _gnapWalkNodes[index].sequenceId = 0x7AF; + gnapSequenceId = 0x7AF; + } else { + _gameSys->insertSequence(makeRid(datNum, 0x7B0), _gnapWalkNodes[index].id, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); + _gnapWalkNodes[index].sequenceId = 0x7B0; + gnapSequenceId = 0x7B0; + } + } else { + if (_gnapWalkNodes[index].deltaY == -1) + _gnapWalkNodes[index].id -= 10; + else + _gnapWalkNodes[index].id += 10; + int newSequenceId = getGnapWalkSequenceId(_gnapWalkNodes[index].deltaX, _gnapWalkNodes[index].deltaY); + _gameSys->insertSequence(makeRid(datNum, newSequenceId), _gnapWalkNodes[index].id, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 75 * _gnapWalkNodes[index].gridX1 - _gnapGridX, 48 * _gnapWalkNodes[index].gridY1 - _gnapGridY); + _gnapWalkNodes[index].sequenceId = newSequenceId; + gnapSequenceId = newSequenceId; + } + gnapId = _gnapWalkNodes[index].id; + gnapSequenceDatNum = datNum; + } + + if (flags & 8) { + if (_gnapWalkNodesCount > 0) { + _gnapSequenceId = gnapSequenceId; + _gnapId = gnapId; + _gnapIdleFacing = getGnapWalkFacing(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY); + _gnapSequenceDatNum = datNum; + if (animationIndex >= 0) + _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, animationIndex); + } else if (animationIndex >= 0) { + _gameSys->setAnimation(0x107D3, 1, animationIndex); + _gameSys->insertSequence(0x107D3, 1, 0, 0, 0, 0, 0, 0); + } + } else { + if (sequenceId >= 0 && sequenceId != -1) { + _gnapSequenceId = ridToEntryIndex(sequenceId); + _gnapSequenceDatNum = ridToDatIndex(sequenceId); + if (_gnapSequenceId == 0x7B9) { + _gnapIdleFacing = 1; + } else { + switch (_gnapSequenceId) { + case 0x7BA: + _gnapIdleFacing = 3; + break; + case 0x7BB: + _gnapIdleFacing = 7; + break; + case 0x7BC: + _gnapIdleFacing = 5; + break; + } + } + } else { + if (_gnapWalkNodesCount > 0) { + _gnapSequenceId = getGnapWalkStopSequenceId(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY); + _gnapIdleFacing = getGnapWalkFacing(_gnapWalkNodes[_gnapWalkNodesCount - 1].deltaX, _gnapWalkNodes[_gnapWalkNodesCount - 1].deltaY); + } else if (gridX >= 0 || gridY >= 0) { + switch (_gnapIdleFacing) { + case 1: + _gnapSequenceId = 0x7B9; + break; + case 3: + _gnapSequenceId = 0x7BA; + break; + case 7: + _gnapSequenceId = 0x7BB; + break; + default: + _gnapSequenceId = 0x7BC; + break; + } + } else { + int v10 = _leftClickMouseX - (_gridMinX + 75 * _gnapX); + int v11 = _leftClickMouseY - (_gridMinY + 48 * _gnapY); + if (_leftClickMouseX == _gridMinX + 75 * _gnapX) + ++v10; + if (_leftClickMouseY == _gridMinY + 48 * _gnapY) + v11 = 1; + _gnapSequenceId = getGnapWalkStopSequenceId(v10 / abs(v10), v11 / abs(v11)); + _gnapIdleFacing = getGnapWalkFacing(v10 / abs(v10), v11 / abs(v11)); + } + _gnapSequenceDatNum = datNum; + } + + if (animationIndex < 0) { + _gnapId = 20 * _gnapWalkDestY + 1; + } else { + _gnapId = _gnapWalkNodesCount + animationIndex + 20 * _gnapWalkDestY; + _gameSys->setAnimation(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapWalkNodesCount + animationIndex + 20 * _gnapWalkDestY, animationIndex); + } + + if (flags & 4) { + _gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 0, 0); + } else { + _gameSys->insertSequence(makeRid(_gnapSequenceDatNum, _gnapSequenceId), _gnapId, + makeRid(gnapSequenceDatNum, gnapSequenceId), gnapId, + 9, 0, 75 * _gnapWalkDestX - _gnapGridX, 48 * _gnapWalkDestY - _gnapGridY); + } + + } + + _gnapX = _gnapWalkDestX; + _gnapY = _gnapWalkDestY; + + return done; +} + +void GnapEngine::gnapWalkStep() { + bool done = false; + for (int i = 1; i < _gridMaxX && !done; ++i) { + done = true; + if (!isPointBlocked(_gnapX + i, _gnapY)) + gnapWalkTo(_gnapX + i, _gnapY, -1, -1, 1); + else if (!isPointBlocked(_gnapX - i, _gnapY)) + gnapWalkTo(_gnapX - i, _gnapY, -1, -1, 1); + else if (!isPointBlocked(_gnapX, _gnapY + 1)) + gnapWalkTo(_gnapX, _gnapY + 1, -1, -1, 1); + else if (!isPointBlocked(_gnapX, _gnapY - 1)) + gnapWalkTo(_gnapX, _gnapY - 1, -1, -1, 1); + else if (!isPointBlocked(_gnapX + 1, _gnapY + 1)) + gnapWalkTo(_gnapX + 1, _gnapY + 1, -1, -1, 1); + else if (!isPointBlocked(_gnapX - 1, _gnapY + 1)) + gnapWalkTo(_gnapX - 1, _gnapY + 1, -1, -1, 1); + else if (!isPointBlocked(_gnapX + 1, _gnapY - 1)) + gnapWalkTo(_gnapX + 1, _gnapY - 1, -1, -1, 1); + else if (!isPointBlocked(_gnapX - 1, _gnapY - 1)) + gnapWalkTo(_gnapX - 1, _gnapY - 1, -1, -1, 1); + else + done = false; + } +} + +//////////////////////////////////////////////////////////////////////////////// + +int GnapEngine::getBeaverWalkSequenceId(int deltaX, int deltaY) { + static const int _beaverWalkSequenceIds[9] = { + 0x7C5, 0x000, 0x7C8, + 0x7C4, 0x000, 0x7C7, + 0x7C3, 0x000, 0x7C6 + }; + // CHECKME This is a little weird + return _beaverWalkSequenceIds[3 * deltaX + 3 + 1 + deltaY]; +} + +bool GnapEngine::gridSub423750(int gridX, int gridY) { + bool result = false; + + _platWalkNodesCount = 0; + _platWalkDirXIncr = 0; + _platWalkDirYIncr = 0; + _platWalkDeltaX = ABS(_platWalkDestX - gridX); + _platWalkDeltaY = ABS(_platWalkDestY - gridY); + + if (_platWalkDeltaX) + _platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX; + else + _platWalkDirX = 0; + + if (_platWalkDeltaY) + _platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY; + else + _platWalkDirY = 0; + + while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirXIncr; + ++_platWalkDirYIncr; + } else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) { + if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + } else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + } else { + _platWalkDeltaX = _platWalkDirXIncr; + _platWalkDeltaY = _platWalkDirYIncr; + --_platWalkNodesCount; + } + } else { + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + } else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + } else { + _platWalkDeltaX = _platWalkDirXIncr; + _platWalkDeltaY = _platWalkDirYIncr; + --_platWalkNodesCount; + } + } + ++_platWalkNodesCount; + } + + while (_platWalkDirXIncr < _platWalkDeltaX) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + ++_platWalkNodesCount; + } else { + _platWalkDeltaX = _platWalkDirXIncr; + } + } + + while (_platWalkDirYIncr < _platWalkDeltaY) { + _platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + ++_platWalkNodesCount; + } else { + _platWalkDeltaY = _platWalkDirYIncr; + } + } + + if (gridX + _platWalkDirX * _platWalkDirXIncr != _platWalkDestX || gridY + _platWalkDirY * _platWalkDirYIncr != _platWalkDestY) { + _platWalkDestX = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkDestY = gridY + _platWalkDirY * _platWalkDirYIncr; + result = false; + } else { + result = true; + } + + return result; +} + +bool GnapEngine::gridSub423CC1(int gridX, int gridY, int index) { + _platWalkNodesCount = index; + _platWalkDirXIncr = 0; + _platWalkDirYIncr = 0; + _platWalkDeltaX = ABS(_platWalkDestX - gridX); + _platWalkDeltaY = ABS(_platWalkDestY - gridY); + + if (_platWalkDeltaX) + _platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX; + else + _platWalkDirX = 0; + + if (_platWalkDeltaY) + _platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY; + else + _platWalkDirY = 0; + + while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirXIncr; + ++_platWalkDirYIncr; + } else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) { + if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + } else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + } else + return false; + } else { + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + } else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + } else + return false; + } + ++_platWalkNodesCount; + } + + while (_platWalkDirXIncr < _platWalkDeltaX) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + ++_platWalkNodesCount; + } else + return false; + } + + while (_platWalkDirYIncr < _platWalkDeltaY) { + _platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + ++_platWalkNodesCount; + } else + return false; + } + + return true; +} + +bool GnapEngine::gridSub42419A(int gridX, int gridY, int index) { + _platWalkNodesCount = index; + _platWalkDirXIncr = 0; + _platWalkDirYIncr = 0; + _platWalkDeltaX = ABS(_platWalkDestX - gridX); + _platWalkDeltaY = ABS(_platWalkDestY - gridY); + + if (_platWalkDeltaX) + _platWalkDirX = (_platWalkDestX - gridX) / _platWalkDeltaX; + else + _platWalkDirX = 0; + + if (_platWalkDeltaY) + _platWalkDirY = (_platWalkDestY - gridY) / _platWalkDeltaY; + else + _platWalkDirY = 0; + + while (_platWalkDeltaY < _platWalkDeltaX - _platWalkDirXIncr) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, gridY)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + ++_platWalkNodesCount; + } else + return false; + } + + while (_platWalkDeltaX < _platWalkDeltaY - _platWalkDirYIncr) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(gridX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + ++_platWalkNodesCount; + } else + return false; + } + + while (_platWalkDirXIncr < _platWalkDeltaX && _platWalkDirYIncr < _platWalkDeltaY) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirXIncr; + ++_platWalkDirYIncr; + } else if (_platWalkDeltaY - _platWalkDirYIncr > _platWalkDeltaX - _platWalkDirXIncr) { + if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + } else if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + } else + return false; + } else { + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + } else if (!isPointBlocked(_platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + } else + return false; + } + ++_platWalkNodesCount; + } + + while (_platWalkDirXIncr < _platWalkDeltaX) { + _platWalkNodes[_platWalkNodesCount].gridX1 = gridX + _platWalkDirX * _platWalkDirXIncr; + _platWalkNodes[_platWalkNodesCount].gridY1 = _platWalkDestY; + if (!isPointBlocked(_platWalkDirX + _platWalkNodes[_platWalkNodesCount].gridX1, _platWalkDestY)) { + _platWalkNodes[_platWalkNodesCount].deltaX = _platWalkDirX; + _platWalkNodes[_platWalkNodesCount].deltaY = 0; + ++_platWalkDirXIncr; + ++_platWalkNodesCount; + } else + return false; + } + + while (_platWalkDirYIncr < _platWalkDeltaY) { + _platWalkNodes[_platWalkNodesCount].gridX1 = _platWalkDestX; + _platWalkNodes[_platWalkNodesCount].gridY1 = gridY + _platWalkDirY * _platWalkDirYIncr; + if (!isPointBlocked(_platWalkDestX, _platWalkDirY + _platWalkNodes[_platWalkNodesCount].gridY1)) { + _platWalkNodes[_platWalkNodesCount].deltaX = 0; + _platWalkNodes[_platWalkNodesCount].deltaY = _platWalkDirY; + ++_platWalkDirYIncr; + ++_platWalkNodesCount; + } else + return false; + } + + return true; +} + +bool GnapEngine::platFindPath3(int gridX, int gridY) { + int gridIncr = 1; + bool done = false; + + while (!done && gridIncr < _gridMaxX) { + if (!isPointBlocked(_platX + gridIncr, _platY) && gridSub423CC1(_platX + gridIncr, _platY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX + i; + _platWalkNodes[i].gridY1 = _platY; + _platWalkNodes[i].deltaX = 1; + _platWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(_platX - gridIncr, _platY) && gridSub423CC1(_platX - gridIncr, _platY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX - i; + _platWalkNodes[i].gridY1 = _platY; + _platWalkNodes[i].deltaX = -1; + _platWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(_platX, _platY + gridIncr) && gridSub423CC1(_platX, _platY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX; + _platWalkNodes[i].gridY1 = _platY + i; + _platWalkNodes[i].deltaX = 0; + _platWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(_platX, _platY - gridIncr) && gridSub423CC1(_platX, _platY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX; + _platWalkNodes[i].gridY1 = _platY - i; + _platWalkNodes[i].deltaX = 0; + _platWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(_platX + gridIncr, _platY + gridIncr) && gridSub423CC1(_platX + gridIncr, _platY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX + i; + _platWalkNodes[i].gridY1 = _platY + i; + _platWalkNodes[i].deltaX = 1; + _platWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(_platX - gridIncr, _platY + gridIncr) && gridSub423CC1(_platX - gridIncr, _platY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX - i; + _platWalkNodes[i].gridY1 = _platY + i; + _platWalkNodes[i].deltaX = -1; + _platWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(_platX + gridIncr, _platY - gridIncr) && gridSub423CC1(_platX + gridIncr, _platY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX + i; + _platWalkNodes[i].gridY1 = _platY - i; + _platWalkNodes[i].deltaX = 1; + _platWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(_platX - gridIncr, _platY - gridIncr) && gridSub423CC1(_platX - gridIncr, _platY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX - i; + _platWalkNodes[i].gridY1 = _platY - i; + _platWalkNodes[i].deltaX = -1; + _platWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(_platX + gridIncr, _platY) && gridSub42419A(_platX + gridIncr, _platY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX + i; + _platWalkNodes[i].gridY1 = _platY; + _platWalkNodes[i].deltaX = 1; + _platWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(_platX - gridIncr, _platY) && gridSub42419A(_platX - gridIncr, _platY, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX - i; + _platWalkNodes[i].gridY1 = _platY; + _platWalkNodes[i].deltaX = -1; + _platWalkNodes[i].deltaY = 0; + } + done = true; + break; + } + if (!isPointBlocked(_platX, _platY + gridIncr) && gridSub42419A(_platX, _platY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX; + _platWalkNodes[i].gridY1 = _platY + i; + _platWalkNodes[i].deltaX = 0; + _platWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(_platX, _platY - gridIncr) && gridSub42419A(_platX, _platY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX; + _platWalkNodes[i].gridY1 = _platY - i; + _platWalkNodes[i].deltaX = 0; + _platWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(_platX + gridIncr, _platY + gridIncr) && gridSub42419A(_platX + gridIncr, _platY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX + i; + _platWalkNodes[i].gridY1 = _platY + i; + _platWalkNodes[i].deltaX = 1; + _platWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(_platX - gridIncr, _platY + gridIncr) && gridSub42419A(_platX - gridIncr, _platY + gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX - i; + _platWalkNodes[i].gridY1 = _platY + i; + _platWalkNodes[i].deltaX = -1; + _platWalkNodes[i].deltaY = 1; + } + done = true; + break; + } + if (!isPointBlocked(_platX + gridIncr, _platY - gridIncr) && gridSub42419A(_platX + gridIncr, _platY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX + i; + _platWalkNodes[i].gridY1 = _platY - i; + _platWalkNodes[i].deltaX = 1; + _platWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + if (!isPointBlocked(_platX - gridIncr, _platY - gridIncr) && gridSub42419A(_platX - gridIncr, _platY - gridIncr, gridIncr)) { + for (int i = 0; i < gridIncr; ++i) { + _platWalkNodes[i].gridX1 = _platX - i; + _platWalkNodes[i].gridY1 = _platY - i; + _platWalkNodes[i].deltaX = -1; + _platWalkNodes[i].deltaY = -1; + } + done = true; + break; + } + ++gridIncr; + } + + return done; +} + +bool GnapEngine::platypusWalkTo(int gridX, int gridY, int animationIndex, int sequenceId, int flags) { + + int datNum = flags & 3; + bool done = false; + + _timers[1] = 60; + + if (gridX < 0) + gridX = (_leftClickMouseX - _gridMinX + 37) / 75; + + if (gridY < 0) + gridY = (_leftClickMouseY - _gridMinY + 24) / 48; + + _platWalkDestX = CLIP(gridX, 0, _gridMaxX - 1); + _platWalkDestY = CLIP(gridY, 0, _gridMaxY - 1); + + if (animationIndex >= 0 && _platWalkDestX == _gnapX && _platWalkDestY == _gnapY) + gnapWalkStep(); + + if (gridSub423CC1(_platX, _platY, 0)) + done = true; + + if (!done && gridSub42419A(_platX, _platY, 0)) + done = true; + + if (!done && platFindPath3(_platX, _platY)) + done = true; + + if (!done) + gridSub423750(_platX, _platY); + + int platSequenceId = _beaverSequenceId; + int platId = _beaverId; + int platSequenceDatNum = _beaverSequenceDatNum; + + for (int index = 0; index < _platWalkNodesCount; ++index) { + _platWalkNodes[index].id = index + 20 * _platWalkNodes[index].gridY1; + if (_platWalkNodes[index].deltaX == 1 && _platWalkNodes[index].deltaY == 0) { + if (index % 2) { + _gameSys->insertSequence(makeRid(datNum, 0x7CD), _platWalkNodes[index].id, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); + _platWalkNodes[index].sequenceId = 0x7CD; + platSequenceId = 0x7CD; + } else { + _gameSys->insertSequence(makeRid(datNum, 0x7CE), _platWalkNodes[index].id, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); + _platWalkNodes[index].sequenceId = 0x7CE; + platSequenceId = 0x7CE; + } + } else if (_platWalkNodes[index].deltaX == -1 && _platWalkNodes[index].deltaY == 0) { + if (index % 2) { + _gameSys->insertSequence(makeRid(datNum, 0x7CF), _platWalkNodes[index].id, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); + _platWalkNodes[index].sequenceId = 0x7CF; + platSequenceId = 0x7CF; + } else { + _gameSys->insertSequence(makeRid(datNum, 0x7D0), _platWalkNodes[index].id, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); + _platWalkNodes[index].sequenceId = 0x7D0; + platSequenceId = 0x7D0; + } + } else { + if (_platWalkNodes[index].deltaY == -1) + _platWalkNodes[index].id -= 10; + else + _platWalkNodes[index].id += 10; + int newSequenceId = getBeaverWalkSequenceId(_platWalkNodes[index].deltaX, _platWalkNodes[index].deltaY); + _gameSys->insertSequence(makeRid(datNum, newSequenceId), _platWalkNodes[index].id, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 75 * _platWalkNodes[index].gridX1 - _platGridX, 48 * _platWalkNodes[index].gridY1 - _platGridY); + _platWalkNodes[index].sequenceId = newSequenceId; + platSequenceId = newSequenceId; + } + platId = _platWalkNodes[index].id; + platSequenceDatNum = datNum; + } + + if (flags & 8) { + if (_platWalkNodesCount > 0) { + _beaverSequenceId = platSequenceId; + _beaverId = platId; + _beaverSequenceDatNum = datNum; + // CHECKME Not sure if this is correct... + if (_platWalkNodes[_platWalkNodesCount - 1].deltaX > 0) + _beaverFacing = 0; + else if (_platWalkNodes[_platWalkNodesCount - 1].deltaX < 0) + _beaverFacing = 4; + else if (_platWalkNodes[_platWalkNodesCount - 1].gridX1 % 2) + _beaverFacing = 4; + else + _beaverFacing = 0; + if (animationIndex >= 0) + _gameSys->setAnimation(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, animationIndex); + } else if (animationIndex >= 0) { + _gameSys->setAnimation(0x107D3, 1, animationIndex); + _gameSys->insertSequence(0x107D3, 1, 0, 0, 0, 0, 0, 0); + } + } else { + if (sequenceId >= 0 && sequenceId != -1) { + _beaverSequenceId = ridToEntryIndex(sequenceId); + _beaverSequenceDatNum = ridToDatIndex(sequenceId); + if (_beaverSequenceId == 0x7C2) { + _beaverFacing = 0; + } else if (_beaverSequenceId == 0x7D2) { + _beaverFacing = 4; + } + } else { + if (_platWalkNodesCount > 0) { + if (_platWalkNodes[_platWalkNodesCount - 1].deltaX > 0) { + _beaverSequenceId = 0x7C2; + _beaverFacing = 0; + } else if (_platWalkNodes[_platWalkNodesCount - 1].deltaX < 0) { + _beaverSequenceId = 0x7D2; + _beaverFacing = 4; + } else if (_platWalkNodes[0].deltaX > 0) { + _beaverSequenceId = 0x7C2; + _beaverFacing = 0; + } else if (_platWalkNodes[0].deltaX < 0) { + _beaverSequenceId = 0x7D2; + _beaverFacing = 4; + } else { + _beaverSequenceId = 0x7D2; + _beaverFacing = 4; + } + } else if (_beaverFacing > 0) { + _beaverSequenceId = 0x7D2; + } else { + _beaverSequenceId = 0x7C2; + } + _beaverSequenceDatNum = datNum; + } + + if (animationIndex < 0) { + _beaverId = 20 * _platWalkDestY; + } else { + _beaverId = animationIndex + 20 * _platWalkDestY; + _gameSys->setAnimation(makeRid(_beaverSequenceDatNum, _beaverSequenceId), animationIndex + 20 * _platWalkDestY, animationIndex); + } + + if (flags & 4) + _gameSys->insertSequence(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 0, 0); + else + _gameSys->insertSequence(makeRid(_beaverSequenceDatNum, _beaverSequenceId), _beaverId, + makeRid(platSequenceDatNum, platSequenceId), platId, + 9, 0, 75 * _platWalkDestX - _platGridX, 48 * _platWalkDestY - _platGridY); + } + + _platX = _platWalkDestX; + _platY = _platWalkDestY; + + return done; +} + +void GnapEngine::platypusWalkStep() { + bool done = false; + for (int i = 1; !done && i < _gridMaxX; ++i) { + done = true; + if (!isPointBlocked(_platX + i, _platY)) + platypusWalkTo(_platX + i, _platY, -1, -1, 1); + else if (!isPointBlocked(_platX - i, _platY)) + platypusWalkTo(_platX - i, _platY, -1, -1, 1); + else if (!isPointBlocked(_platX, _platY + 1)) + platypusWalkTo(_platX, _platY + 1, -1, -1, 1); + else if (!isPointBlocked(_platX, _platY - 1)) + platypusWalkTo(_platX, _platY - 1, -1, -1, 1); + else if (!isPointBlocked(_platX + 1, _platY + 1)) + platypusWalkTo(_platX + 1, _platY + 1, -1, -1, 1); + else if (!isPointBlocked(_platX - 1, _platY + 1)) + platypusWalkTo(_platX - 1, _platY + 1, -1, -1, 1); + else if (!isPointBlocked(_platX + 1, _platY - 1)) + platypusWalkTo(_platX + 1, _platY - 1, -1, -1, 1); + else if (!isPointBlocked(_platX - 1, _platY - 1)) + platypusWalkTo(_platX - 1, _platY - 1, -1, -1, 1); + else + done = false; + } +} + +void GnapEngine::beaverMakeRoom() { + int rndGridX, rndGridY; + do { + rndGridY = getRandom(_gridMaxY); + rndGridX = getRandom(_gridMaxX); + } while (ABS(rndGridX - _platX) > 4 || ABS(rndGridY - _platY) > 3 || + isPointBlocked(rndGridX, rndGridY)); + platypusWalkTo(rndGridX, rndGridY, -1, -1, 1); +} + +} // End of namespace Gnap |