scummvm/engines/hopkins/lines.cpp

2917 lines
92 KiB
C++
Raw Normal View History

/* 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 "hopkins/lines.h"
2013-02-15 21:20:24 +00:00
#include "hopkins/graphics.h"
#include "hopkins/hopkins.h"
2013-02-15 21:20:24 +00:00
#include "common/system.h"
#include "common/textconsole.h"
namespace Hopkins {
LinesManager::LinesManager(HopkinsEngine *vm) {
_vm = vm;
2013-04-20 22:40:09 +00:00
for (int i = 0; i < MAX_LINES + 1; ++i)
Common::fill((byte *)&_zoneLine[i], (byte *)&_zoneLine[i] + sizeof(LigneZoneItem), 0);
2013-04-20 22:40:09 +00:00
for (int i = 0; i < MAX_LINES; ++i)
2013-02-20 07:30:16 +00:00
Common::fill((byte *)&_lineItem[i], (byte *)&_lineItem[i] + sizeof(LigneItem), 0);
for (int i = 0; i < 4000; ++i)
Common::fill((byte *)&_smoothRoute[i], (byte *)&_smoothRoute[i] + sizeof(SmoothItem), 0);
for (int i = 0; i < 8001; ++i)
2013-02-20 07:30:16 +00:00
_bestRoute[i].set(0, 0, DIR_NONE);
for (int i = 0; i < 101; ++i) {
Common::fill((byte *)&_segment[i], (byte *)&_segment[i] + sizeof(SegmentItem), 0);
Common::fill((byte *)&_squareZone[i], (byte *)&_squareZone[i] + sizeof(SquareZoneItem), 0);
}
for (int i = 0; i < 105; ++i) {
_bobZone[i] = 0;
_bobZoneFl[i] = false;
}
for (int i = 0; i < 106; ++i)
Common::fill((byte *)&_zone[i], (byte *)&_zone[i] + sizeof(ZoneItem), 0);
_linesNumb = 0;
2013-02-20 07:30:16 +00:00
_newLineIdx = 0;
_newLineDataIdx = 0;
_newRouteIdx = 0;
_newPosX = 0;
_newPosY = 0;
2013-02-18 00:19:41 +00:00
_smoothMoveDirection = DIR_NONE;
_lastLine = 0;
_maxLineIdx = 0;
_pathFindingMaxDepth = 0;
_testRoute0 = NULL;
_testRoute1 = NULL;
_testRoute2 = NULL;
_lineBuf = NULL;
_route = NULL;
_currentSegmentId = 0;
2013-04-04 05:54:45 +00:00
_largeBuf = NULL;
_zoneSkipCount = 0;
_hotspotTextColor = 0;
_forceHideText = false;
2013-03-24 21:11:52 +00:00
_oldMouseZoneId = 0;
_oldMouseX = 0;
_oldMouseY = 0;
_oldRouteFromX = 0;
_oldRouteFromY = 0;
_oldRouteDestX = 0;
_oldRouteDestY = 0;
_oldZoneNum = 0;
}
LinesManager::~LinesManager() {
_vm->_globals->freeMemory(_largeBuf);
2013-04-04 23:43:10 +00:00
if (_testRoute0)
delete[] _testRoute0;
2013-04-04 23:43:10 +00:00
if (_testRoute1)
delete[] _testRoute1;
2013-04-04 23:43:10 +00:00
if (_testRoute2)
delete[] _testRoute2;
}
int LigneItem::appendToRouteInc(int from, int to, RouteItem *route, int index) {
if (to == -1)
to = _lineDataEndIdx;
for (int i = from; i < to; ++i)
route[index++].set(_lineData[2*i], _lineData[2*i+1], _directionRouteInc);
return index;
}
int LigneItem::appendToRouteDec(int from, int to, RouteItem *route, int index) {
if (from == -1)
from = _lineDataEndIdx - 1;
for (int i = from; i > to; --i)
route[index++].set(_lineData[2*i], _lineData[2*i+1], _directionRouteDec);
return index;
}
/**
* Load lines
*/
void LinesManager::loadLines(const Common::String &file) {
resetLines();
_linesNumb = 0;
_lastLine = 0;
byte *ptr = _vm->_fileIO->loadFile(file);
for (int idx = 0; READ_LE_INT16((uint16 *)ptr + (idx * 5)) != -1; idx++) {
addLine(idx,
(Directions)READ_LE_INT16((uint16 *)ptr + (idx * 5)),
READ_LE_INT16((uint16 *)ptr + (idx * 5) + 1),
READ_LE_INT16((uint16 *)ptr + (idx * 5) + 2),
READ_LE_INT16((uint16 *)ptr + (idx * 5) + 3),
READ_LE_INT16((uint16 *)ptr + (idx * 5) + 4));
}
initRoute();
_vm->_globals->freeMemory(ptr);
}
/**
2013-01-10 22:15:52 +00:00
* Check Hotspots in Inventory screen
* Returns the ID of the hotspot under mouse
*/
int LinesManager::checkInventoryHotspots(int posX, int posY) {
int hotspotId = 0;
if (posY >= 120 && posY <= 153)
hotspotId = checkInventoryHotspotsRow(posX, 1, false);
2013-01-10 22:15:52 +00:00
if (posY >= 154 && posY <= 191)
hotspotId = checkInventoryHotspotsRow(posX, 7, false);
2013-01-10 22:15:52 +00:00
if (posY >= 192 && posY <= 229)
hotspotId = checkInventoryHotspotsRow(posX, 13, false);
2013-01-10 22:15:52 +00:00
if (posY >= 230 && posY <= 267)
hotspotId = checkInventoryHotspotsRow(posX, 19, false);
2013-01-10 22:15:52 +00:00
if (posY >= 268 && posY <= 306)
hotspotId = checkInventoryHotspotsRow(posX, 25, true);
if (posY >= 268 && posY <= 288 && posX >= _vm->_graphicsMan->_scrollOffset + 424 && posX <= _vm->_graphicsMan->_scrollOffset + 478)
2013-01-10 22:15:52 +00:00
hotspotId = 30;
if (posY >= 290 && posY <= 306 && posX >= _vm->_graphicsMan->_scrollOffset + 424 && posX <= _vm->_graphicsMan->_scrollOffset + 478)
2013-01-10 22:15:52 +00:00
hotspotId = 31;
if (posY < 114 || posY > 306 || posX < _vm->_graphicsMan->_scrollOffset + 152 || posX > _vm->_graphicsMan->_scrollOffset + 484)
2013-01-10 22:15:52 +00:00
hotspotId = 32;
return hotspotId;
}
2013-01-10 22:15:52 +00:00
/**
* Check the hotspots in an inventory line
* Returns the hotspot Id under the mouse, if any.
*/
int LinesManager::checkInventoryHotspotsRow(int posX, int minZoneNum, bool lastRow) {
int result = minZoneNum;
if (posX >= _vm->_graphicsMan->_scrollOffset + 158 && posX < _vm->_graphicsMan->_scrollOffset + 208)
return result;
if (posX >= _vm->_graphicsMan->_scrollOffset + 208 && posX < _vm->_graphicsMan->_scrollOffset + 266) {
result += 1;
return result;
}
if (posX >= _vm->_graphicsMan->_scrollOffset + 266 && posX < _vm->_graphicsMan->_scrollOffset + 320) {
result += 2;
return result;
}
if (posX >= _vm->_graphicsMan->_scrollOffset + 320 && posX < _vm->_graphicsMan->_scrollOffset + 370) {
result += 3;
return result;
}
if (posX >= _vm->_graphicsMan->_scrollOffset + 370 && posX < _vm->_graphicsMan->_scrollOffset + 424) {
result += 4;
return result;
}
if (!lastRow && posX >= _vm->_graphicsMan->_scrollOffset + 424 && posX <= _vm->_graphicsMan->_scrollOffset + 478) {
result += 5;
return result;
}
return 0;
}
/**
* Add Zone Line
*/
void LinesManager::addZoneLine(int idx, int fromX, int fromY, int destX, int destY, int bobZoneIdx) {
int16 *zoneData;
if (fromX == fromY && fromY == destX && fromY == destY) {
_bobZoneFl[bobZoneIdx] = true;
_bobZone[bobZoneIdx] = fromY;
} else {
2013-04-21 05:13:02 +00:00
assert(idx < MAX_LINES + 1);
_zoneLine[idx]._zoneData = (int16 *)_vm->_globals->freeMemory((byte *)_zoneLine[idx]._zoneData);
int distX = abs(fromX - destX);
int distY = abs(fromY - destY);
int maxDist = 1;
if (distX <= distY)
maxDist += distY;
else
maxDist += distX;
zoneData = (int16 *)_vm->_globals->allocMemory(2 * sizeof(int16) * maxDist + (4 * sizeof(int16)));
2013-04-04 23:43:10 +00:00
assert(zoneData);
_zoneLine[idx]._zoneData = zoneData;
2012-11-23 23:16:44 +00:00
int16 *dataP = zoneData;
int stepX = 1000 * distX / maxDist;
int stepY = 1000 * distY / maxDist;
if (destX < fromX)
stepX = -stepX;
if (destY < fromY)
stepY = -stepY;
int smoothPosX = 1000 * fromX;
int smoothPosY = 1000 * fromY;
for (int i = 0; i < maxDist; i++) {
*dataP++ = smoothPosX / 1000;
*dataP++ = smoothPosY / 1000;
smoothPosX += stepX;
smoothPosY += stepY;
}
*dataP++ = -1;
*dataP++ = -1;
_zoneLine[idx]._count = maxDist;
_zoneLine[idx]._bobZoneIdx = bobZoneIdx;
}
}
2013-01-11 00:50:29 +00:00
/**
* Add Line
*/
void LinesManager::addLine(int lineIdx, Directions direction, int fromX, int fromY, int destX, int destY) {
2013-04-21 05:13:02 +00:00
assert(lineIdx < MAX_LINES);
2013-02-26 22:27:55 +00:00
if (_linesNumb < lineIdx)
_linesNumb = lineIdx;
_lineItem[lineIdx]._lineData = (int16 *)_vm->_globals->freeMemory((byte *)_lineItem[lineIdx]._lineData);
int distX = abs(fromX - destX) + 1;
int distY = abs(fromY - destY) + 1;
int maxDist = distY;
if (distX > maxDist)
maxDist = distX;
byte *zoneData = _vm->_globals->allocMemory(4 * maxDist + 8);
2013-04-21 05:13:02 +00:00
assert(zoneData);
Common::fill(zoneData, zoneData + 4 * maxDist + 8, 0);
_lineItem[lineIdx]._lineData = (int16 *)zoneData;
2013-02-26 22:27:55 +00:00
int16 *curLineData = _lineItem[lineIdx]._lineData;
int stepX = 1000 * distX / (maxDist - 1);
int stepY = 1000 * distY / (maxDist - 1);
if (destX < fromX)
stepX = -stepX;
if (destY < fromY)
stepY = -stepY;
int dirX = (int)stepX / 1000; // -1: Left, 0: None, 1: Right
int dirY = (int)stepY / 1000; // -1: Up, 0: None, 1: Right
2013-02-26 07:06:08 +00:00
if (!dirX) {
if (dirY == -1) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_UP;
_lineItem[lineIdx]._directionRouteDec = DIR_DOWN;
2013-02-26 07:06:08 +00:00
} else if (dirY == 1) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_DOWN;
_lineItem[lineIdx]._directionRouteDec = DIR_UP;
}
2013-02-26 07:06:08 +00:00
// If dirY == 0, no move
} else if (dirX == 1) {
if (dirY == -1) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_UP_RIGHT;
_lineItem[lineIdx]._directionRouteDec = DIR_DOWN_LEFT;
2013-02-26 07:06:08 +00:00
} else if (!dirY) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_RIGHT;
_lineItem[lineIdx]._directionRouteDec = DIR_LEFT;
2013-02-26 07:06:08 +00:00
} else if (dirY == 1) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_DOWN_RIGHT;
_lineItem[lineIdx]._directionRouteDec = DIR_UP_LEFT;
}
2013-02-26 07:06:08 +00:00
} else if (dirX == -1) {
if (dirY == 1) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_DOWN_LEFT;
_lineItem[lineIdx]._directionRouteDec = DIR_UP_RIGHT;
2013-02-26 07:06:08 +00:00
} else if (!dirY) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_LEFT;
_lineItem[lineIdx]._directionRouteDec = DIR_RIGHT;
2013-02-26 07:06:08 +00:00
} else if (dirY == -1) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_UP_LEFT;
_lineItem[lineIdx]._directionRouteDec = DIR_DOWN_RIGHT;
}
}
2013-02-26 07:06:08 +00:00
// Second pass to soften cases where dirY == 0
if (dirX == 1) {
if (stepY > 250 && stepY <= 999) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_DOWN_RIGHT;
_lineItem[lineIdx]._directionRouteDec = DIR_UP_LEFT;
} else if (stepY < -250 && stepY > -1000) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_UP_RIGHT;
_lineItem[lineIdx]._directionRouteDec = DIR_DOWN_LEFT;
2013-02-26 07:06:08 +00:00
}
} else if (dirX == -1) {
if (stepY > 250 && stepY <= 999) {
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_DOWN_LEFT;
_lineItem[lineIdx]._directionRouteDec = DIR_UP_RIGHT;
} else if (stepY < -250 && stepY > -1000) {
// In the original code, the test was on positive values and
// was impossible to meet.
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._directionRouteInc = DIR_UP_LEFT;
_lineItem[lineIdx]._directionRouteDec = DIR_DOWN_RIGHT;
2013-02-26 07:06:08 +00:00
}
}
2013-02-26 07:06:08 +00:00
stepX = 1000 * distX / maxDist;
stepY = 1000 * distY / maxDist;
if (destX < fromX)
stepX = -stepX;
if (destY < fromY)
stepY = -stepY;
int smoothPosX = 1000 * fromX;
int smoothPosY = 1000 * fromY;
for (int i = 0; i < maxDist - 1; i++) {
curLineData[0] = smoothPosX / 1000;
curLineData[1] = smoothPosY / 1000;
2013-02-26 07:06:08 +00:00
curLineData += 2;
2012-12-22 00:28:31 +00:00
smoothPosX += stepX;
smoothPosY += stepY;
}
curLineData[0] = destX;
curLineData[1] = destY;
2013-02-26 07:06:08 +00:00
curLineData += 2;
curLineData[0] = -1;
curLineData[1] = -1;
_lineItem[lineIdx]._lineDataEndIdx = maxDist;
2013-02-26 22:27:55 +00:00
_lineItem[lineIdx]._direction = direction;
++_linesNumb;
}
2013-01-10 07:28:15 +00:00
/**
* Check collision line
*/
bool LinesManager::checkCollisionLine(int xp, int yp, int *foundDataIdx, int *foundLineIdx, int startLineIdx, int endLineIdx) {
int16 *lineData;
int left = xp + 4;
int right = xp - 4;
int top = yp + 4;
int bottom = yp - 4;
*foundDataIdx = -1;
*foundLineIdx = -1;
for (int curLineIdx = startLineIdx; curLineIdx <= endLineIdx; curLineIdx++) {
2013-02-20 07:30:16 +00:00
lineData = _lineItem[curLineIdx]._lineData;
2013-01-10 07:28:15 +00:00
if (lineData == NULL)
2013-01-10 07:28:15 +00:00
continue;
bool collisionFl = true;
int lineStartX = lineData[0];
int lineStartY = lineData[1];
2013-02-20 07:30:16 +00:00
int lineDataIdx = 2 * _lineItem[curLineIdx]._lineDataEndIdx;
2013-01-10 07:28:15 +00:00
int lineEndX = lineData[lineDataIdx - 2];
int lineEndY = lineData[lineDataIdx - 1];
if (lineStartX >= lineEndX) {
if (right > lineStartX || left < lineEndX)
collisionFl = false;
} else { // lineStartX < lineEndX
if (left < lineStartX || right > lineEndX)
collisionFl = false;
}
if (lineStartY >= lineEndY) {
if (bottom > lineStartY || top < lineEndY)
collisionFl = false;
} else { // lineStartY < lineEndY
if (top < lineStartY || bottom > lineEndY)
collisionFl = false;
}
if (!collisionFl)
continue;
2013-02-20 07:30:16 +00:00
for (int idx = 0; idx < _lineItem[curLineIdx]._lineDataEndIdx; idx++) {
2013-01-10 07:28:15 +00:00
int lineX = lineData[0];
int lineY = lineData[1];
lineData += 2;
if ((xp == lineX || xp + 1 == lineX) && (yp == lineY || yp + 1 == lineY)) {
*foundDataIdx = idx;
*foundLineIdx = curLineIdx;
return true;
}
}
}
2013-01-10 07:28:15 +00:00
return false;
}
/**
* Init route
*/
void LinesManager::initRoute() {
2013-02-20 07:30:16 +00:00
int lineX = _lineItem[0]._lineData[0];
int lineY = _lineItem[0]._lineData[1];
int lineIdx = 1;
for (;;) {
2013-02-20 07:30:16 +00:00
int curDataIdx = _lineItem[lineIdx]._lineDataEndIdx;
int16 *curLineData = _lineItem[lineIdx]._lineData;
int curLineX = curLineData[2 * curDataIdx - 2];
int curLineY = curLineData[2 * curDataIdx - 1];
if (_vm->_graphicsMan->_maxX == curLineX || _vm->_graphicsMan->_maxY == curLineY ||
_vm->_graphicsMan->_minX == curLineX || _vm->_graphicsMan->_minY == curLineY ||
(lineX == curLineX && lineY == curLineY))
break;
if (lineIdx == MAX_LINES)
error("ERROR - LAST LINE NOT FOUND");
2012-12-31 00:09:06 +00:00
2013-02-20 07:30:16 +00:00
int16 *nextLineData = _lineItem[lineIdx + 1]._lineData;
2013-04-04 05:54:45 +00:00
if (!nextLineData)
break;
if (nextLineData[0] != curLineX && nextLineData[1] != curLineY)
break;
++lineIdx;
}
_lastLine = lineIdx;
for (int idx = 1; idx < MAX_LINES; idx++) {
2013-02-20 07:30:16 +00:00
if ((_lineItem[idx]._lineDataEndIdx < _maxLineIdx) && (idx != _lastLine + 1)) {
_lineItem[idx]._directionRouteInc = _lineItem[idx - 1]._directionRouteInc;
_lineItem[idx]._directionRouteDec = _lineItem[idx - 1]._directionRouteDec;
}
}
}
2013-03-28 16:59:34 +00:00
// Avoid obstacle
int LinesManager::avoidObstacle(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route) {
int curLineIdx = lineIdx;
int curLineDataIdx = lineDataIdx;
int curRouteIdx = routeIdx;
if (lineIdx < destLineIdx) {
curRouteIdx = _lineItem[lineIdx].appendToRouteInc(lineDataIdx, -1, route, curRouteIdx);
for (int i = lineIdx + 1; i < destLineIdx; i++)
curRouteIdx = _lineItem[i].appendToRouteInc(0, -1, route, curRouteIdx);
curLineDataIdx = 0;
curLineIdx = destLineIdx;
}
if (curLineIdx > destLineIdx) {
curRouteIdx = _lineItem[curLineIdx].appendToRouteDec(curLineDataIdx, 0, route, curRouteIdx);
for (int i = curLineIdx - 1; i > destLineIdx; i--)
curRouteIdx = _lineItem[i].appendToRouteDec(-1, 0, route, curRouteIdx);
curLineDataIdx = _lineItem[destLineIdx]._lineDataEndIdx - 1;
curLineIdx = destLineIdx;
}
if (curLineIdx == destLineIdx) {
if (destLineDataIdx >= curLineDataIdx) {
curRouteIdx = _lineItem[destLineIdx].appendToRouteInc(curLineDataIdx, destLineDataIdx, route, curRouteIdx);
} else {
curRouteIdx = _lineItem[destLineIdx].appendToRouteDec(curLineDataIdx, destLineDataIdx, route, curRouteIdx);
}
}
return curRouteIdx;
}
2013-03-28 16:59:34 +00:00
// Avoid Obstacle, taking into account start/End lind Idx
int LinesManager::avoidObstacleOnSegment(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route, int startLineIdx, int endLineIdx) {
int curLineIdx = lineIdx;
int curLineDataIdx = lineDataIdx;
int curRouteIdx = routeIdx;
if (destLineIdx < lineIdx) {
curRouteIdx = _lineItem[lineIdx].appendToRouteInc(lineDataIdx, -1, route, curRouteIdx);
int wrkLineIdx = lineIdx + 1;
2013-03-28 16:59:34 +00:00
if (wrkLineIdx == endLineIdx + 1)
wrkLineIdx = startLineIdx;
while (destLineIdx != wrkLineIdx) {
curRouteIdx = _lineItem[wrkLineIdx].appendToRouteInc(0, -1, route, curRouteIdx);
++wrkLineIdx;
2013-03-28 16:59:34 +00:00
if (endLineIdx + 1 == wrkLineIdx)
wrkLineIdx = startLineIdx;
}
curLineDataIdx = 0;
curLineIdx = destLineIdx;
}
if (destLineIdx > curLineIdx) {
curRouteIdx = _lineItem[curLineIdx].appendToRouteDec(curLineDataIdx, 0, route, curRouteIdx);
int wrkLineIdx = curLineIdx - 1;
2013-03-28 16:59:34 +00:00
if (wrkLineIdx == startLineIdx - 1)
wrkLineIdx = endLineIdx;
while (destLineIdx != wrkLineIdx) {
curRouteIdx = _lineItem[wrkLineIdx].appendToRouteDec(-1, 0, route, curRouteIdx);
--wrkLineIdx;
2013-03-28 16:59:34 +00:00
if (startLineIdx - 1 == wrkLineIdx)
wrkLineIdx = endLineIdx;
}
curLineDataIdx = _lineItem[destLineIdx]._lineDataEndIdx - 1;
curLineIdx = destLineIdx;
}
if (destLineIdx == curLineIdx) {
if (destLineDataIdx >= curLineDataIdx) {
curRouteIdx = _lineItem[destLineIdx].appendToRouteInc(curLineDataIdx, destLineDataIdx, route, curRouteIdx);
} else {
curRouteIdx = _lineItem[destLineIdx].appendToRouteDec(curLineDataIdx, destLineDataIdx, route, curRouteIdx);
}
}
return curRouteIdx;
}
2013-02-26 22:27:55 +00:00
bool LinesManager::MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, int routeIdx) {
int newLinesDataIdx = 0;
int newLinesIdx = 0;
int lineIdxLeft = 0;
int lineDataIdxLeft = 0;
int lineIdxRight = 0;
int lineDataIdxRight = 0;
int linesIdxUp = 0;
int linesDataIdxUp = 0;
int lineIdxDown = 0;
int lineDataIdxDown = 0;
int curX = fromX;
int curY = fromY;
2013-02-26 22:27:55 +00:00
int curLineIdx = lineIdx;
int tmpRouteIdx = routeIdx;
2013-02-26 22:27:55 +00:00
int dummyDataIdx;
if (checkCollisionLine(fromX, fromY, &dummyDataIdx, &curLineIdx, 0, _linesNumb)) {
switch (_lineItem[curLineIdx]._direction) {
2013-02-18 00:19:41 +00:00
case DIR_UP:
curY -= 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_UP_RIGHT:
curY -= 2;
curX += 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_RIGHT:
curX += 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN_RIGHT:
curY += 2;
curX += 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN:
curY += 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN_LEFT:
curY += 2;
curX -= 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_LEFT:
curX -= 2;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_UP_LEFT:
curY -= 2;
curX -= 2;
2013-01-27 11:04:24 +00:00
break;
default:
break;
}
}
int stepVertIncCount = 0;
for (int i = curY; curY + 200 > i; i++) {
if (checkCollisionLine(curX, i, &lineDataIdxDown, &lineIdxDown, 0, _lastLine) == 1 && lineIdxDown <= _lastLine)
break;
lineDataIdxDown = 0;
lineIdxDown = -1;
++stepVertIncCount;
}
int stepVertDecCount = 0;
for (int i = curY; curY - 200 < i; i--) {
if (checkCollisionLine(curX, i, &linesDataIdxUp, &linesIdxUp, 0, _lastLine) == 1 && linesIdxUp <= _lastLine)
break;
linesDataIdxUp = 0;
linesIdxUp = -1;
++stepVertDecCount;
}
int stepHoriIncCount = 0;
for (int i = curX; curX + 200 > i; i++) {
if (checkCollisionLine(i, curY, &lineDataIdxRight, &lineIdxRight, 0, _lastLine) == 1 && lineIdxRight <= _lastLine)
break;
lineDataIdxRight = 0;
lineIdxRight = -1;
++stepHoriIncCount;
}
int stepHoriDecCount = 0;
for (int i = curX; curX - 200 < i; i--) {
if (checkCollisionLine(i, curY, &lineDataIdxLeft, &lineIdxLeft, 0, _lastLine) == 1 && lineIdxLeft <= _lastLine)
break;
lineDataIdxLeft = 0;
lineIdxLeft = -1;
++stepHoriDecCount;
}
2013-02-26 22:27:55 +00:00
if (destLineIdx > curLineIdx) {
if (linesIdxUp != -1 && linesIdxUp <= curLineIdx)
linesIdxUp = -1;
if (lineIdxRight != -1 && curLineIdx >= lineIdxRight)
lineIdxRight = -1;
if (lineIdxDown != -1 && curLineIdx >= lineIdxDown)
lineIdxDown = -1;
if (lineIdxLeft != -1 && curLineIdx >= lineIdxLeft)
lineIdxLeft = -1;
if (linesIdxUp != -1 && destLineIdx < linesIdxUp)
linesIdxUp = -1;
if (lineIdxRight != -1 && destLineIdx < lineIdxRight)
lineIdxRight = -1;
if (lineIdxDown != -1 && destLineIdx < lineIdxDown)
lineIdxDown = -1;
if (lineIdxLeft != -1 && destLineIdx < lineIdxLeft)
lineIdxLeft = -1;
2013-02-26 22:27:55 +00:00
} else if (destLineIdx < curLineIdx) {
if (linesIdxUp != -1 && linesIdxUp >= curLineIdx)
linesIdxUp = -1;
if (lineIdxRight != -1 && curLineIdx <= lineIdxRight)
lineIdxRight = -1;
if (lineIdxDown != -1 && curLineIdx <= lineIdxDown)
lineIdxDown = -1;
if (lineIdxLeft != -1 && curLineIdx <= lineIdxLeft)
lineIdxLeft = -1;
if (linesIdxUp != -1 && destLineIdx > linesIdxUp)
linesIdxUp = -1;
if (lineIdxRight != -1 && destLineIdx > lineIdxRight)
lineIdxRight = -1;
if (lineIdxDown != -1 && destLineIdx > lineIdxDown)
lineIdxDown = -1;
if (lineIdxLeft != -1 && destLineIdx > lineIdxLeft)
lineIdxLeft = -1;
}
if (linesIdxUp != -1 || lineIdxRight != -1 || lineIdxDown != -1 || lineIdxLeft != -1) {
2013-02-18 00:19:41 +00:00
Directions newDir = DIR_NONE;
2013-02-26 22:27:55 +00:00
if (destLineIdx > curLineIdx) {
if (lineIdxDown <= linesIdxUp && lineIdxRight <= linesIdxUp && lineIdxLeft <= linesIdxUp && linesIdxUp > curLineIdx)
2013-02-18 00:19:41 +00:00
newDir = DIR_UP;
if (lineIdxDown <= lineIdxRight && linesIdxUp <= lineIdxRight && lineIdxLeft <= lineIdxRight && curLineIdx < lineIdxRight)
2013-02-18 00:19:41 +00:00
newDir = DIR_RIGHT;
if (linesIdxUp <= lineIdxDown && lineIdxRight <= lineIdxDown && lineIdxLeft <= lineIdxDown && curLineIdx < lineIdxDown)
2013-02-18 00:19:41 +00:00
newDir = DIR_DOWN;
if (lineIdxDown <= lineIdxLeft && lineIdxRight <= lineIdxLeft && linesIdxUp <= lineIdxLeft && curLineIdx < lineIdxLeft)
2013-02-18 00:19:41 +00:00
newDir = DIR_LEFT;
2013-02-26 22:27:55 +00:00
} else if (destLineIdx < curLineIdx) {
if (linesIdxUp == -1)
linesIdxUp = INVALID_LINE_VALUE;
if (lineIdxRight == -1)
lineIdxRight = INVALID_LINE_VALUE;
if (lineIdxDown == -1)
lineIdxDown = INVALID_LINE_VALUE;
if (lineIdxLeft == -1)
lineIdxLeft = INVALID_LINE_VALUE;
if (linesIdxUp != INVALID_LINE_VALUE && lineIdxDown >= linesIdxUp && lineIdxRight >= linesIdxUp && lineIdxLeft >= linesIdxUp && linesIdxUp < curLineIdx)
2013-02-18 00:19:41 +00:00
newDir = DIR_UP;
if (lineIdxRight != INVALID_LINE_VALUE && lineIdxDown >= lineIdxRight && linesIdxUp >= lineIdxRight && lineIdxLeft >= lineIdxRight && curLineIdx > lineIdxRight)
2013-02-18 00:19:41 +00:00
newDir = DIR_RIGHT;
if (lineIdxDown != INVALID_LINE_VALUE && linesIdxUp >= lineIdxDown && lineIdxRight >= lineIdxDown && lineIdxLeft >= lineIdxDown && curLineIdx > lineIdxDown)
2013-02-18 00:19:41 +00:00
newDir = DIR_DOWN;
if (lineIdxLeft != INVALID_LINE_VALUE && lineIdxDown >= lineIdxLeft && lineIdxRight >= lineIdxLeft && linesIdxUp >= lineIdxLeft && curLineIdx > lineIdxLeft)
2013-02-18 00:19:41 +00:00
newDir = DIR_LEFT;
}
2013-02-15 22:41:05 +00:00
2013-02-18 00:19:41 +00:00
switch(newDir) {
case DIR_UP:
newLinesIdx = linesIdxUp;
newLinesDataIdx = linesDataIdxUp;
for (int i = 0; i < stepVertDecCount; i++) {
if (checkCollisionLine(curX, curY - i, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdxUp = computeRouteIdx(linesIdxUp, linesDataIdxUp, curX, curY - i, curX, curY - stepVertDecCount, tmpRouteIdx, &_bestRoute[0]);
if (tmpRouteIdxUp == -1)
2013-02-15 22:41:05 +00:00
return false;
tmpRouteIdx = tmpRouteIdxUp;
2013-02-20 07:30:16 +00:00
if (_newPosY != -1)
i = _newPosY - curY;
}
_bestRoute[tmpRouteIdx].set(curX, curY - i, DIR_UP);
tmpRouteIdx++;
}
_newLineIdx = newLinesIdx;
_newLineDataIdx = newLinesDataIdx;
_newRouteIdx = tmpRouteIdx;
2013-02-15 22:41:05 +00:00
return true;
break;
2013-02-18 00:19:41 +00:00
case DIR_RIGHT:
newLinesIdx = lineIdxRight;
newLinesDataIdx = lineDataIdxRight;
for (int i = 0; i < stepHoriIncCount; i++) {
if (checkCollisionLine(i + curX, curY, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdxRight = computeRouteIdx(linesIdxUp, linesDataIdxUp, i + curX, curY, stepHoriIncCount + curX, curY, tmpRouteIdx, &_bestRoute[0]);
if (tmpRouteIdxRight == -1)
2013-02-15 22:41:05 +00:00
return false;
tmpRouteIdx = tmpRouteIdxRight;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1)
i = _newPosX - curX;
}
_bestRoute[tmpRouteIdx].set(i + curX, curY, DIR_RIGHT);
tmpRouteIdx++;
}
_newLineIdx = newLinesIdx;
_newLineDataIdx = newLinesDataIdx;
_newRouteIdx = tmpRouteIdx;
2013-02-15 22:41:05 +00:00
return true;
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN:
newLinesIdx = lineIdxDown;
newLinesDataIdx = lineDataIdxDown;
for (int i = 0; i < stepVertIncCount; i++) {
if (checkCollisionLine(curX, i + curY, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdxDown = computeRouteIdx(linesIdxUp, linesDataIdxUp, curX, i + curY, curX, stepVertIncCount + curY, tmpRouteIdx, &_bestRoute[0]);
if (tmpRouteIdxDown == -1)
2013-02-15 22:41:05 +00:00
return false;
tmpRouteIdx = tmpRouteIdxDown;
2013-02-20 07:30:16 +00:00
if (_newPosY != -1)
i = curY - _newPosY;
}
_bestRoute[tmpRouteIdx].set(curX, i + curY, DIR_DOWN);
tmpRouteIdx++;
}
_newLineIdx = newLinesIdx;
_newLineDataIdx = newLinesDataIdx;
_newRouteIdx = tmpRouteIdx;
2013-02-15 22:41:05 +00:00
return true;
break;
2013-02-18 00:19:41 +00:00
case DIR_LEFT:
newLinesIdx = lineIdxLeft;
newLinesDataIdx = lineDataIdxLeft;
for (int i = 0; i < stepHoriDecCount; i++) {
if (checkCollisionLine(curX - i, curY, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdxLeft = computeRouteIdx(linesIdxUp, linesDataIdxUp, curX - i, curY, curX - stepHoriDecCount, curY, tmpRouteIdx, &_bestRoute[0]);
if (tmpRouteIdxLeft == -1)
2013-02-15 22:41:05 +00:00
return false;
tmpRouteIdx = tmpRouteIdxLeft;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1)
i = curX - _newPosX;
}
_bestRoute[tmpRouteIdx].set(curX - i, curY, DIR_LEFT);
tmpRouteIdx++;
}
_newLineIdx = newLinesIdx;
_newLineDataIdx = newLinesDataIdx;
_newRouteIdx = tmpRouteIdx;
2013-02-15 22:41:05 +00:00
return true;
break;
default:
break;
}
}
2013-01-11 00:50:29 +00:00
return false;
}
2013-03-28 16:59:34 +00:00
int LinesManager::computeRouteIdx(int lineIdx, int dataIdx, int fromX, int fromY, int destX, int destY, int routerIdx, RouteItem *route) {
int result = routerIdx;
++_pathFindingMaxDepth;
if (_pathFindingMaxDepth > 10) {
warning("PathFinding - Max depth reached");
route[routerIdx].invalidate();
return -1;
}
2013-03-12 22:22:56 +00:00
int lineX = _lineItem[lineIdx]._lineData[0];
int lineY = _lineItem[lineIdx]._lineData[1];
int startLineIdx = lineIdx;
2013-03-12 22:22:56 +00:00
int curLineDataEndIdx;
bool loopCond = false;
for (;;) {
int curLineIdx = startLineIdx - 1;
int endLineIdx = 2 * _lineItem[startLineIdx - 1]._lineDataEndIdx;
2013-03-12 22:22:56 +00:00
int16 *lineData = _lineItem[startLineIdx - 1]._lineData;
if (lineData == NULL)
break;
while (lineData[endLineIdx - 2] != lineX || lineY != lineData[endLineIdx - 1]) {
--curLineIdx;
if (_lastLine - 1 != curLineIdx) {
endLineIdx = 2 * _lineItem[curLineIdx]._lineDataEndIdx;
lineData = _lineItem[curLineIdx]._lineData;
2013-04-04 23:43:10 +00:00
if (lineData)
continue;
}
loopCond = true;
break;
}
if (loopCond)
break;
startLineIdx = curLineIdx;
2013-03-12 22:22:56 +00:00
lineX = lineData[0];
lineY = lineData[1];
}
2013-03-12 22:22:56 +00:00
int lastIdx = _lineItem[lineIdx]._lineDataEndIdx - 1;
int lastPosX = _lineItem[lineIdx]._lineData[(2 * lastIdx)];
int lastPosY = _lineItem[lineIdx]._lineData[(2 * lastIdx) + 1];
int endLineIdx = lineIdx;
2013-01-27 11:04:24 +00:00
int foundLineIdx, foundDataIdx;
loopCond = false;
for (;;) {
2013-03-12 22:22:56 +00:00
int curLineIdx = endLineIdx + 1;
int nextLineDataEndIdx = 2 * _lineItem[curLineIdx]._lineDataEndIdx;
int16 *lineData = _lineItem[curLineIdx]._lineData;
if (lineData == NULL)
break;
for (;;) {
2013-03-12 22:22:56 +00:00
curLineDataEndIdx = nextLineDataEndIdx;
if (lineData[0] == lastPosX && lastPosY == lineData[1])
break;
2013-03-12 22:22:56 +00:00
++curLineIdx;
if (curLineIdx != _linesNumb + 1) {
nextLineDataEndIdx = 2 * _lineItem[curLineIdx]._lineDataEndIdx;
lineData = _lineItem[curLineIdx]._lineData;
2013-04-04 23:43:10 +00:00
if (lineData)
continue;
}
loopCond = true;
break;
}
if (loopCond)
break;
2013-03-12 22:22:56 +00:00
endLineIdx = curLineIdx;
lastPosX = lineData[curLineDataEndIdx - 2];
lastPosY = lineData[curLineDataEndIdx - 1];
}
int distX = abs(fromX - destX) + 1;
int distY = abs(fromY - destY) + 1;
int maxDist = distY;
if (distX > distY)
maxDist = distX;
int stepX = 1000 * distX / maxDist;
int stepY = 1000 * distY / maxDist;
int smoothPosX = 1000 * fromX;
int smoothPosY = 1000 * fromY;
2013-02-26 22:27:55 +00:00
if (destX < fromX)
stepX = -stepX;
2013-02-26 22:27:55 +00:00
if (destY < fromY)
stepY = -stepY;
if (maxDist > 800)
maxDist = 800;
2013-02-20 07:30:16 +00:00
Common::fill(&_lineBuf[0], &_lineBuf[1000], 0);
int bugLigIdx = 0;
for (int i = 0; i < maxDist + 1; i++) {
_lineBuf[bugLigIdx] = smoothPosX / 1000;
_lineBuf[bugLigIdx + 1] = smoothPosY / 1000;
smoothPosX += stepX;
smoothPosY += stepY;
bugLigIdx += 2;
}
bugLigIdx -= 2;
int destDataIdx = 0;
int destLineIdx = -1;
2013-03-14 07:05:09 +00:00
int bufX = 0;
int bufY = 0;
for (int i = maxDist + 1; i > 0; i--) {
2013-03-12 22:22:56 +00:00
if (checkCollisionLine(_lineBuf[bugLigIdx], _lineBuf[bugLigIdx + 1], &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx) && _lastLine < foundLineIdx) {
destLineIdx = foundLineIdx;
destDataIdx = foundDataIdx;
2013-03-14 07:05:09 +00:00
bufX = _lineBuf[bugLigIdx];
bufY = _lineBuf[bugLigIdx + 1];
2012-12-22 00:28:31 +00:00
break;
}
bugLigIdx -= 2;
}
int maxLineX = 0;
int minLineX = 0;
int maxLineY = 0;
int minLineY = 0;
2013-03-12 22:22:56 +00:00
for (int i = startLineIdx; i <= endLineIdx; ++i) {
2013-02-20 07:30:16 +00:00
int16 *lineData = _lineItem[i]._lineData;
if (lineData == NULL)
error("error in genial routine");
2013-03-12 22:22:56 +00:00
if (i == startLineIdx) {
minLineY = MIN(lineData[1], lineData[2 * _lineItem[i]._lineDataEndIdx - 1]);
maxLineY = MAX(lineData[1], lineData[2 * _lineItem[i]._lineDataEndIdx - 1]);
minLineX = MIN(lineData[0], lineData[2 * _lineItem[i]._lineDataEndIdx - 2]);
maxLineX = MAX(lineData[0], lineData[2 * _lineItem[i]._lineDataEndIdx - 2]);
} else {
if (lineData[1] < lineData[2 * _lineItem[i]._lineDataEndIdx - 1] && lineData[1] < minLineY)
minLineY = lineData[1];
if (lineData[2 * _lineItem[i]._lineDataEndIdx - 1] < lineData[1] && lineData[2 * _lineItem[i]._lineDataEndIdx - 1] < minLineY)
minLineY = lineData[2 * _lineItem[i]._lineDataEndIdx - 1];
if (lineData[1] > lineData[2 * _lineItem[i]._lineDataEndIdx - 1] && lineData[1] > maxLineY)
maxLineY = lineData[1];
if (lineData[2 * _lineItem[i]._lineDataEndIdx - 1] > lineData[1] && lineData[2 * _lineItem[i]._lineDataEndIdx - 1] > maxLineY)
maxLineY = lineData[2 * _lineItem[i]._lineDataEndIdx - 1];
if (lineData[0] < lineData[2 * _lineItem[i]._lineDataEndIdx - 2] && minLineX > lineData[0])
minLineX = lineData[0];
if (lineData[2 * _lineItem[i]._lineDataEndIdx - 2] < lineData[0] && minLineX > lineData[2 * _lineItem[i]._lineDataEndIdx - 2])
minLineX = lineData[2 * _lineItem[i]._lineDataEndIdx - 2];
if (lineData[0] > lineData[2 * _lineItem[i]._lineDataEndIdx - 2] && maxLineX < lineData[0])
maxLineX = lineData[0];
if (lineData[2 * _lineItem[i]._lineDataEndIdx - 2] > lineData[0] && maxLineX < lineData[2 * _lineItem[i]._lineDataEndIdx - 2])
maxLineX = lineData[2 * _lineItem[i]._lineDataEndIdx - 2];
}
}
minLineX -= 2;
minLineY -= 2;
maxLineX += 2;
maxLineY += 2;
if (destX >= minLineX && destX <= maxLineX && destY >= minLineY && destY <= maxLineY) {
2013-03-14 07:05:09 +00:00
int curY = destY;
int linesIdxUp = -1;
for (;;) {
2013-03-14 07:05:09 +00:00
--curY;
if (!checkCollisionLine(destX, curY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx))
break;
2013-03-14 07:05:09 +00:00
linesIdxUp = foundLineIdx;
if (!curY || minLineY > curY)
break;
}
2013-03-14 07:05:09 +00:00
curY = destY;
int lineIdxDown = -1;
for (;;) {
2013-03-14 07:05:09 +00:00
++curY;
if (!checkCollisionLine(destX, curY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx))
break;
2013-03-14 07:05:09 +00:00
lineIdxDown = foundLineIdx;
if (_vm->_globals->_characterMaxPosY <= curY || maxLineY <= curY)
break;
}
2013-03-14 07:05:09 +00:00
int curX = destX;
int lineIdxRight = -1;
for (;;) {
2013-03-14 07:05:09 +00:00
++curX;
if (!checkCollisionLine(curX, destY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx))
break;
2013-03-14 07:05:09 +00:00
lineIdxRight = foundLineIdx;
if (_vm->_graphicsMan->_maxX <= curX || maxLineX <= curX)
break;
}
2013-03-14 07:05:09 +00:00
curX = destX;
int lineIdxLeft = -1;
for(;;) {
2013-03-14 07:05:09 +00:00
--curX;
if (!checkCollisionLine(curX, destY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx))
break;
2013-03-14 07:05:09 +00:00
lineIdxLeft = foundLineIdx;
if (curX <= 0 || minLineX >= curX)
break;
}
2013-03-14 07:05:09 +00:00
if (lineIdxRight != -1 && lineIdxLeft != -1 && linesIdxUp != -1 && lineIdxDown != -1) {
route[routerIdx].invalidate();
2013-01-11 00:50:29 +00:00
return -1;
}
}
2013-03-14 07:05:09 +00:00
if (bufX < fromX - 1 || bufX > fromX + 1 || bufY < fromY - 1 || bufY > fromY + 1) {
_newPosX = bufX;
_newPosY = bufY;
if (lineIdx < destLineIdx) {
int stepCount = 0;
int curLineIdx = lineIdx;
do {
if (curLineIdx == startLineIdx - 1)
curLineIdx = endLineIdx;
++stepCount;
--curLineIdx;
if (curLineIdx == startLineIdx - 1)
curLineIdx = endLineIdx;
} while (destLineIdx != curLineIdx);
if (abs(destLineIdx - lineIdx) == stepCount) {
2013-02-20 07:30:16 +00:00
if (dataIdx > abs(_lineItem[lineIdx]._lineDataEndIdx / 2)) {
2013-03-28 16:59:34 +00:00
result = avoidObstacle(lineIdx, dataIdx, routerIdx, destLineIdx, destDataIdx, route);
} else {
2013-03-28 16:59:34 +00:00
result = avoidObstacleOnSegment(lineIdx, dataIdx, routerIdx, destLineIdx, destDataIdx, route, startLineIdx, endLineIdx);
}
}
if (abs(destLineIdx - lineIdx) < stepCount)
2013-03-28 16:59:34 +00:00
result = avoidObstacle(lineIdx, dataIdx, result, destLineIdx, destDataIdx, route);
if (stepCount < abs(destLineIdx - lineIdx))
2013-03-28 16:59:34 +00:00
result = avoidObstacleOnSegment(lineIdx, dataIdx, result, destLineIdx, destDataIdx, route, startLineIdx, endLineIdx);
}
if (lineIdx > destLineIdx) {
int destStepCount = abs(lineIdx - destLineIdx);
int curLineIdx = lineIdx;
int curStepCount = 0;
do {
if (curLineIdx == endLineIdx + 1)
curLineIdx = startLineIdx;
++curStepCount;
++curLineIdx;
if (curLineIdx == endLineIdx + 1)
curLineIdx = startLineIdx;
} while (destLineIdx != curLineIdx);
if (destStepCount == curStepCount) {
2013-02-20 07:30:16 +00:00
if (dataIdx > abs(_lineItem[lineIdx]._lineDataEndIdx / 2)) {
2013-03-28 16:59:34 +00:00
result = avoidObstacleOnSegment(lineIdx, dataIdx, result, destLineIdx, destDataIdx, route, startLineIdx, endLineIdx);
} else {
2013-03-28 16:59:34 +00:00
result = avoidObstacle(lineIdx, dataIdx, result, destLineIdx, destDataIdx, route);
}
}
if (destStepCount < curStepCount)
2013-03-28 16:59:34 +00:00
result = avoidObstacle(lineIdx, dataIdx, result, destLineIdx, destDataIdx, route);
if (curStepCount < destStepCount)
2013-03-28 16:59:34 +00:00
result = avoidObstacleOnSegment(lineIdx, dataIdx, result, destLineIdx, destDataIdx, route, startLineIdx, endLineIdx);
}
if (lineIdx == destLineIdx)
2013-03-28 16:59:34 +00:00
result = avoidObstacle(lineIdx, dataIdx, result, lineIdx, destDataIdx, route);
for(;;) {
2013-02-20 07:30:16 +00:00
if (!checkCollisionLine(_newPosX, _newPosY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb))
break;
2013-02-20 07:30:16 +00:00
switch (_lineItem[foundLineIdx]._direction) {
2013-02-18 00:19:41 +00:00
case DIR_UP:
2013-02-20 07:30:16 +00:00
--_newPosY;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_UP_RIGHT:
2013-02-20 07:30:16 +00:00
--_newPosY;
++_newPosX;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_RIGHT:
2013-02-20 07:30:16 +00:00
++_newPosX;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN_RIGHT:
2013-02-20 07:30:16 +00:00
++_newPosY;
++_newPosX;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN:
2013-02-20 07:30:16 +00:00
++_newPosY;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN_LEFT:
2013-02-20 07:30:16 +00:00
++_newPosY;
--_newPosX;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_LEFT:
2013-02-20 07:30:16 +00:00
--_newPosX;
2013-01-27 11:04:24 +00:00
break;
2013-02-18 00:19:41 +00:00
case DIR_UP_LEFT:
2013-02-20 07:30:16 +00:00
--_newPosY;
--_newPosX;
2013-01-27 11:04:24 +00:00
break;
default:
break;
}
}
} else {
2013-02-20 07:30:16 +00:00
_newPosX = -1;
_newPosY = -1;
}
return result;
}
2013-03-28 09:25:42 +00:00
// Find Route from a point to the other
RouteItem *LinesManager::findRoute(int fromX, int fromY, int destX, int destY) {
2013-01-27 11:04:24 +00:00
int foundLineIdx;
int foundDataIdx;
int curLineY = 0;
int curLineX = 0;
int stepArr[9];
int deltaArr[9];
int collLineDataIdxArr[9];
int collLineIdxArr[9];
2013-01-24 19:50:48 +00:00
int clipDestX = destX;
int clipDestY = destY;
int curLineIdx = 0;
int curLineDataIdx = 0;
int lineIdx = 0;
int lineDataIdx = 0;
2013-02-18 00:19:41 +00:00
Directions newDir = DIR_NONE;
if (destY <= 24)
clipDestY = 25;
if (!_vm->_globals->_checkDistanceFl) {
if (abs(fromX - _oldRouteFromX) <= 4 && abs(fromY - _oldRouteFromY) <= 4 &&
abs(_oldRouteDestX - destX) <= 4 && abs(_oldRouteDestY - clipDestY) <= 4)
return NULL;
2013-01-27 11:04:24 +00:00
if (abs(fromX - destX) <= 4 && abs(fromY - clipDestY) <= 4)
return NULL;
if (_oldZoneNum > 0 && _vm->_objectsMan->_zoneNum > 0 && _oldZoneNum == _vm->_objectsMan->_zoneNum)
return NULL;
}
_vm->_globals->_checkDistanceFl = false;
_oldZoneNum = _vm->_objectsMan->_zoneNum;
_oldRouteFromX = fromX;
_oldRouteDestX = destX;
_oldRouteFromY = fromY;
_oldRouteDestY = clipDestY;
_pathFindingMaxDepth = 0;
int routeIdx = 0;
if (destX <= 19)
clipDestX = 20;
if (clipDestY <= 19)
clipDestY = 20;
if (clipDestX > _vm->_graphicsMan->_maxX - 10)
clipDestX = _vm->_graphicsMan->_maxX - 10;
if (clipDestY > _vm->_globals->_characterMaxPosY)
clipDestY = _vm->_globals->_characterMaxPosY;
2013-01-27 11:04:24 +00:00
if (abs(fromX - clipDestX) <= 3 && abs(fromY - clipDestY) <= 3)
return NULL;
2013-01-24 19:50:48 +00:00
for (int i = 0; i <= 8; ++i) {
collLineIdxArr[i] = -1;
collLineDataIdxArr[i] = 0;
deltaArr[i] = INVALID_LINE_VALUE;
stepArr[i] = INVALID_LINE_VALUE;
}
if (characterRoute(fromX, fromY, clipDestX, clipDestY, -1, -1, 0) == 1)
2013-02-20 07:30:16 +00:00
return _bestRoute;
2013-01-24 07:34:35 +00:00
int tmpDelta = 0;
for (int tmpY = clipDestY; tmpY < _vm->_graphicsMan->_maxY; tmpY++, tmpDelta++) {
if (checkCollisionLine(clipDestX, tmpY, &collLineDataIdxArr[DIR_DOWN], &collLineIdxArr[DIR_DOWN], 0, _lastLine) && collLineIdxArr[DIR_DOWN] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_DOWN] = 0;
collLineIdxArr[DIR_DOWN] = -1;
2013-01-24 19:50:48 +00:00
}
deltaArr[DIR_DOWN] = tmpDelta;
2013-01-24 07:34:35 +00:00
tmpDelta = 0;
for (int tmpY = clipDestY; tmpY > _vm->_graphicsMan->_minY; tmpY--, tmpDelta++) {
if (checkCollisionLine(clipDestX, tmpY, &collLineDataIdxArr[DIR_UP], &collLineIdxArr[DIR_UP], 0, _lastLine) && collLineIdxArr[DIR_UP] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_UP] = 0;
collLineIdxArr[DIR_UP] = -1;
if (deltaArr[DIR_DOWN] < tmpDelta && collLineIdxArr[DIR_DOWN] != -1)
2013-01-24 19:50:48 +00:00
break;
}
deltaArr[DIR_UP] = tmpDelta;
2013-01-24 07:34:35 +00:00
tmpDelta = 0;
for (int tmpX = clipDestX; tmpX < _vm->_graphicsMan->_maxX; tmpX++) {
if (checkCollisionLine(tmpX, clipDestY, &collLineDataIdxArr[DIR_RIGHT], &collLineIdxArr[DIR_RIGHT], 0, _lastLine) && collLineIdxArr[DIR_RIGHT] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_RIGHT] = 0;
collLineIdxArr[DIR_RIGHT] = -1;
++tmpDelta;
if (deltaArr[DIR_UP] < tmpDelta && collLineIdxArr[DIR_UP] != -1)
2013-01-24 07:34:35 +00:00
break;
if (deltaArr[DIR_DOWN] < tmpDelta && collLineIdxArr[DIR_DOWN] != -1)
2013-01-24 19:50:48 +00:00
break;
}
deltaArr[DIR_RIGHT] = tmpDelta;
2013-01-24 07:34:35 +00:00
tmpDelta = 0;
for (int tmpX = clipDestX; tmpX > _vm->_graphicsMan->_minX; tmpX--) {
if (checkCollisionLine(tmpX, clipDestY, &collLineDataIdxArr[DIR_LEFT], &collLineIdxArr[DIR_LEFT], 0, _lastLine) && collLineIdxArr[DIR_LEFT] <= _lastLine)
break;
collLineDataIdxArr[DIR_LEFT] = 0;
collLineIdxArr[DIR_LEFT] = -1;
++tmpDelta;
if (deltaArr[DIR_UP] < tmpDelta && collLineIdxArr[DIR_UP] != -1)
break;
if (deltaArr[DIR_DOWN] < tmpDelta && collLineIdxArr[DIR_DOWN] != -1)
break;
if (deltaArr[DIR_RIGHT] < tmpDelta && collLineIdxArr[DIR_RIGHT] != -1)
break;
}
deltaArr[DIR_LEFT] = tmpDelta;
if (collLineIdxArr[DIR_UP] < 0 || _lastLine < collLineIdxArr[DIR_UP])
collLineIdxArr[DIR_UP] = -1;
if (collLineIdxArr[DIR_RIGHT] < 0 || _lastLine < collLineIdxArr[DIR_RIGHT])
collLineIdxArr[DIR_RIGHT] = -1;
if (collLineIdxArr[DIR_DOWN] < 0 || _lastLine < collLineIdxArr[DIR_DOWN])
collLineIdxArr[DIR_DOWN] = -1;
if (collLineIdxArr[DIR_LEFT] < 0 || _lastLine < collLineIdxArr[DIR_LEFT])
collLineIdxArr[DIR_LEFT] = -1;
if (collLineIdxArr[DIR_UP] < 0)
deltaArr[DIR_UP] = INVALID_LINE_VALUE;
if (collLineIdxArr[DIR_RIGHT] < 0)
deltaArr[DIR_RIGHT] = INVALID_LINE_VALUE;
if (collLineIdxArr[DIR_DOWN] < 0)
deltaArr[DIR_DOWN] = INVALID_LINE_VALUE;
if (collLineIdxArr[DIR_LEFT] < 0)
deltaArr[DIR_LEFT] = INVALID_LINE_VALUE;
if (collLineIdxArr[DIR_UP] == -1 && collLineIdxArr[DIR_RIGHT] == -1 && collLineIdxArr[DIR_DOWN] == -1 && collLineIdxArr[DIR_LEFT] == -1)
return NULL;
if (collLineIdxArr[DIR_DOWN] != -1 && deltaArr[DIR_UP] >= deltaArr[DIR_DOWN] && deltaArr[DIR_RIGHT] >= deltaArr[DIR_DOWN] && deltaArr[DIR_LEFT] >= deltaArr[DIR_DOWN]) {
curLineIdx = collLineIdxArr[DIR_DOWN];
curLineDataIdx = collLineDataIdxArr[DIR_DOWN];
} else if (collLineIdxArr[DIR_UP] != -1 && deltaArr[DIR_DOWN] >= deltaArr[DIR_UP] && deltaArr[DIR_RIGHT] >= deltaArr[DIR_UP] && deltaArr[DIR_LEFT] >= deltaArr[DIR_UP]) {
curLineIdx = collLineIdxArr[DIR_UP];
curLineDataIdx = collLineDataIdxArr[DIR_UP];
} else if (collLineIdxArr[DIR_RIGHT] != -1 && deltaArr[DIR_UP] >= deltaArr[DIR_RIGHT] && deltaArr[DIR_DOWN] >= deltaArr[DIR_RIGHT] && deltaArr[DIR_LEFT] >= deltaArr[DIR_RIGHT]) {
curLineIdx = collLineIdxArr[DIR_RIGHT];
curLineDataIdx = collLineDataIdxArr[DIR_RIGHT];
} else if (collLineIdxArr[DIR_LEFT] != -1 && deltaArr[DIR_DOWN] >= deltaArr[DIR_LEFT] && deltaArr[DIR_RIGHT] >= deltaArr[DIR_LEFT] && deltaArr[DIR_UP] >= deltaArr[DIR_LEFT]) {
curLineIdx = collLineIdxArr[DIR_LEFT];
curLineDataIdx = collLineDataIdxArr[DIR_LEFT];
2013-01-24 19:50:48 +00:00
}
2013-01-24 19:50:48 +00:00
for (int i = 0; i <= 8; ++i) {
collLineIdxArr[i] = -1;
collLineDataIdxArr[i] = 0;
deltaArr[i] = INVALID_LINE_VALUE;
stepArr[i] = INVALID_LINE_VALUE;
2013-01-24 19:50:48 +00:00
}
2013-01-24 07:34:35 +00:00
tmpDelta = 0;
for (int tmpY = fromY; tmpY < _vm->_graphicsMan->_maxY; tmpY++, tmpDelta++) {
if (checkCollisionLine(fromX, tmpY, &collLineDataIdxArr[DIR_DOWN], &collLineIdxArr[DIR_DOWN], 0, _lastLine) && collLineIdxArr[DIR_DOWN] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_DOWN] = 0;
collLineIdxArr[DIR_DOWN] = -1;
2013-01-24 19:50:48 +00:00
}
deltaArr[DIR_DOWN] = tmpDelta + 1;
2013-01-24 07:34:35 +00:00
tmpDelta = 0;
for (int tmpY = fromY; tmpY > _vm->_graphicsMan->_minY; tmpY--) {
if (checkCollisionLine(fromX, tmpY, &collLineDataIdxArr[DIR_UP], &collLineIdxArr[DIR_UP], 0, _lastLine) && collLineIdxArr[DIR_UP] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_UP] = 0;
collLineIdxArr[DIR_UP] = -1;
++tmpDelta;
if (collLineIdxArr[DIR_DOWN] != -1 && tmpDelta > 80)
2013-01-24 19:50:48 +00:00
break;
}
deltaArr[DIR_UP] = tmpDelta + 1;
2013-01-24 07:34:35 +00:00
tmpDelta = 0;
for (int tmpX = fromX; tmpX < _vm->_graphicsMan->_maxX; tmpX++) {
if (checkCollisionLine(tmpX, fromY, &collLineDataIdxArr[DIR_RIGHT], &collLineIdxArr[DIR_RIGHT], 0, _lastLine) && collLineIdxArr[DIR_RIGHT] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_RIGHT] = 0;
collLineIdxArr[DIR_RIGHT] = -1;
++tmpDelta;
if ((collLineIdxArr[DIR_DOWN] != -1 || collLineIdxArr[DIR_UP] != -1) && (tmpDelta > 100))
2013-01-24 19:50:48 +00:00
break;
}
deltaArr[DIR_RIGHT] = tmpDelta + 1;
2013-01-24 19:50:48 +00:00
tmpDelta = 0;
for (int tmpX = fromX; tmpX > _vm->_graphicsMan->_minX; tmpX--) {
if (checkCollisionLine(tmpX, fromY, &collLineDataIdxArr[DIR_LEFT], &collLineIdxArr[DIR_LEFT], 0, _lastLine) && collLineIdxArr[DIR_LEFT] <= _lastLine)
2013-01-24 19:50:48 +00:00
break;
collLineDataIdxArr[DIR_LEFT] = 0;
collLineIdxArr[DIR_LEFT] = -1;
++tmpDelta;
if ((collLineIdxArr[DIR_DOWN] != -1 || collLineIdxArr[DIR_UP] != -1 || collLineIdxArr[DIR_RIGHT] != -1) && (tmpDelta > 100))
2013-01-24 19:50:48 +00:00
break;
}
deltaArr[DIR_LEFT] = tmpDelta + 1;
2013-01-24 19:50:48 +00:00
if (collLineIdxArr[DIR_UP] != -1)
stepArr[DIR_UP] = abs(collLineIdxArr[DIR_UP] - curLineIdx);
2013-01-24 19:50:48 +00:00
if (collLineIdxArr[DIR_RIGHT] != -1)
stepArr[DIR_RIGHT] = abs(collLineIdxArr[DIR_RIGHT] - curLineIdx);
2013-01-24 19:50:48 +00:00
if (collLineIdxArr[DIR_DOWN] != -1)
stepArr[DIR_DOWN] = abs(collLineIdxArr[DIR_DOWN] - curLineIdx);
2013-01-24 19:50:48 +00:00
if (collLineIdxArr[DIR_LEFT] != -1)
stepArr[DIR_LEFT] = abs(collLineIdxArr[DIR_LEFT] - curLineIdx);
2013-01-24 19:50:48 +00:00
if (collLineIdxArr[DIR_UP] == -1 && collLineIdxArr[DIR_RIGHT] == -1 && collLineIdxArr[DIR_DOWN] == -1 && collLineIdxArr[DIR_LEFT] == -1)
2013-01-24 19:50:48 +00:00
error("Nearest point not found");
int delta = 0;
if (collLineIdxArr[DIR_UP] != -1 && stepArr[DIR_RIGHT] >= stepArr[DIR_UP] && stepArr[DIR_DOWN] >= stepArr[DIR_UP] && stepArr[DIR_LEFT] >= stepArr[DIR_UP]) {
lineIdx = collLineIdxArr[DIR_UP];
delta = deltaArr[DIR_UP];
2013-02-18 00:19:41 +00:00
newDir = DIR_UP;
lineDataIdx = collLineDataIdxArr[DIR_UP];
} else if (collLineIdxArr[DIR_DOWN] != -1 && stepArr[DIR_RIGHT] >= stepArr[DIR_DOWN] && stepArr[DIR_UP] >= stepArr[DIR_DOWN] && stepArr[DIR_LEFT] >= stepArr[DIR_DOWN]) {
lineIdx = collLineIdxArr[DIR_DOWN];
delta = deltaArr[DIR_DOWN];
2013-02-18 00:19:41 +00:00
newDir = DIR_DOWN;
lineDataIdx = collLineDataIdxArr[DIR_DOWN];
} else if (collLineIdxArr[DIR_RIGHT] != -1 && stepArr[DIR_UP] >= stepArr[DIR_RIGHT] && stepArr[DIR_DOWN] >= stepArr[DIR_RIGHT] && stepArr[DIR_LEFT] >= stepArr[DIR_RIGHT]) {
lineIdx = collLineIdxArr[DIR_RIGHT];
delta = deltaArr[DIR_RIGHT];
2013-02-18 00:19:41 +00:00
newDir = DIR_RIGHT;
lineDataIdx = collLineDataIdxArr[DIR_RIGHT];
} else if (collLineIdxArr[DIR_LEFT] != -1 && stepArr[DIR_UP] >= stepArr[DIR_LEFT] && stepArr[DIR_DOWN] >= stepArr[DIR_LEFT] && stepArr[DIR_RIGHT] >= stepArr[DIR_LEFT]) {
lineIdx = collLineIdxArr[DIR_LEFT];
delta = deltaArr[DIR_LEFT];
2013-02-18 00:19:41 +00:00
newDir = DIR_LEFT;
lineDataIdx = collLineDataIdxArr[DIR_LEFT];
2013-01-24 19:50:48 +00:00
}
2013-01-24 07:34:35 +00:00
int bestRouteNum = characterRoute(fromX, fromY, clipDestX, clipDestY, lineIdx, curLineIdx, 0);
if (bestRouteNum == 1)
2013-02-20 07:30:16 +00:00
return _bestRoute;
if (bestRouteNum == 2) {
lineIdx = _newLineIdx;
lineDataIdx = _newLineDataIdx;
routeIdx = _newRouteIdx;
} else {
switch (newDir) {
case DIR_UP:
for (int deltaY = 0; deltaY < delta; deltaY++) {
if (checkCollisionLine(fromX, fromY - deltaY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(foundLineIdx, foundDataIdx, fromX, fromY - deltaY, fromX, fromY - delta, routeIdx, _bestRoute);
if (tmpRouteIdx == -1) {
_bestRoute[routeIdx].invalidate();
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
}
routeIdx = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosY != -1)
deltaY = fromY - _newPosY;
}
_bestRoute[routeIdx].set(fromX, fromY - deltaY, DIR_UP);
routeIdx++;
}
break;
case DIR_DOWN:
for (int deltaY = 0; deltaY < delta; deltaY++) {
if (checkCollisionLine(fromX, deltaY + fromY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb)
&& _lastLine < foundLineIdx) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(foundLineIdx, foundDataIdx, fromX, deltaY + fromY, fromX, delta + fromY, routeIdx, &_bestRoute[0]);
if (tmpRouteIdx == -1) {
_bestRoute[routeIdx].invalidate();
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
}
routeIdx = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosY != -1)
deltaY = _newPosY - fromY;
}
_bestRoute[routeIdx].set(fromX, fromY + deltaY, DIR_DOWN);
routeIdx++;
}
break;
case DIR_LEFT:
for (int deltaX = 0; deltaX < delta; deltaX++) {
if (checkCollisionLine(fromX - deltaX, fromY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(foundLineIdx, foundDataIdx, fromX - deltaX, fromY, fromX - delta, fromY, routeIdx, &_bestRoute[0]);
if (tmpRouteIdx == -1) {
_bestRoute[routeIdx].invalidate();
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
}
routeIdx = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1)
deltaX = fromX - _newPosX;
}
_bestRoute[routeIdx].set(fromX - deltaX, fromY, DIR_LEFT);
routeIdx++;
}
break;
case DIR_RIGHT:
for (int deltaX = 0; deltaX < delta; deltaX++) {
if (checkCollisionLine(deltaX + fromX, fromY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) {
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(foundLineIdx, foundDataIdx, deltaX + fromX, fromY, delta + fromX, fromY, routeIdx, &_bestRoute[0]);
if (tmpRouteIdx == -1) {
_bestRoute[routeIdx].invalidate();
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
}
routeIdx = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1)
deltaX = _newPosX - fromX;
}
_bestRoute[routeIdx].set(fromX + deltaX, fromY, DIR_RIGHT);
routeIdx++;
}
break;
default:
break;
2013-01-24 19:50:48 +00:00
}
}
bool loopCond;
do {
loopCond = false;
if (lineIdx < curLineIdx) {
for (int i = lineDataIdx; _lineItem[lineIdx]._lineDataEndIdx > i; ++i) {
curLineX = _lineItem[lineIdx]._lineData[2 * i];
curLineY = _lineItem[lineIdx]._lineData[2 * i + 1];
_bestRoute[routeIdx].set(_lineItem[lineIdx]._lineData[2 * i], _lineItem[lineIdx]._lineData[2 * i + 1], _lineItem[lineIdx]._directionRouteInc);
routeIdx++;
}
for (int idx = lineIdx + 1; idx < curLineIdx; idx++) {
for (int dataIdx = 0; _lineItem[idx]._lineDataEndIdx > dataIdx; dataIdx++) {
curLineX = _lineItem[idx]._lineData[2 * dataIdx];
curLineY = _lineItem[idx]._lineData[2 * dataIdx + 1];
_bestRoute[routeIdx].set(_lineItem[idx]._lineData[2 * dataIdx], _lineItem[idx]._lineData[2 * dataIdx + 1], _lineItem[idx]._directionRouteInc);
routeIdx++;
if (_lineItem[idx]._lineDataEndIdx > 30 && dataIdx == _lineItem[idx]._lineDataEndIdx / 2) {
bestRouteNum = characterRoute(_lineItem[idx]._lineData[2 * dataIdx], _lineItem[idx]._lineData[2 * dataIdx + 1], clipDestX, clipDestY, idx, curLineIdx, routeIdx);
if (bestRouteNum == 1)
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, idx, curLineIdx, routeIdx)) {
lineIdx = _newLineIdx;
lineDataIdx = _newLineDataIdx;
routeIdx = _newRouteIdx;
loopCond = true;
break;
}
2013-01-24 19:50:48 +00:00
}
}
if (loopCond)
break;
bestRouteNum = characterRoute(curLineX, curLineY, clipDestX, clipDestY, idx, curLineIdx, routeIdx);
if (bestRouteNum == 1)
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, idx, curLineIdx, routeIdx)) {
lineIdx = _newLineIdx;
lineDataIdx = _newLineDataIdx;
routeIdx = _newRouteIdx;
loopCond = true;
break;
}
}
if (loopCond)
continue;
lineDataIdx = 0;
lineIdx = curLineIdx;
}
if (lineIdx > curLineIdx) {
for (int dataIdx = lineDataIdx; dataIdx > 0; dataIdx--) {
curLineX = _lineItem[lineIdx]._lineData[2 * dataIdx];
curLineY = _lineItem[lineIdx]._lineData[2 * dataIdx + 1];
_bestRoute[routeIdx].set(_lineItem[lineIdx]._lineData[2 * dataIdx], _lineItem[lineIdx]._lineData[2 * dataIdx + 1], _lineItem[lineIdx]._directionRouteDec);
routeIdx++;
}
for (int i = lineIdx - 1; i > curLineIdx; i--) {
for (int dataIdx = _lineItem[i]._lineDataEndIdx - 1; dataIdx > -1; dataIdx--) {
curLineX = _lineItem[i]._lineData[2 * dataIdx];
curLineY = _lineItem[i]._lineData[2 * dataIdx + 1];
_bestRoute[routeIdx].set(_lineItem[i]._lineData[2 * dataIdx], _lineItem[i]._lineData[2 * dataIdx + 1], _lineItem[i]._directionRouteDec);
routeIdx++;
if (_lineItem[i]._lineDataEndIdx > 30 && dataIdx == _lineItem[i]._lineDataEndIdx / 2) {
bestRouteNum = characterRoute(curLineX, curLineY, clipDestX, clipDestY, i, curLineIdx, routeIdx);
if (bestRouteNum == 1)
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, i, curLineIdx, routeIdx)) {
lineIdx = _newLineIdx;
lineDataIdx = _newLineDataIdx;
routeIdx = _newRouteIdx;
loopCond = true;
break;
}
}
}
if (loopCond)
break;
bestRouteNum = characterRoute(curLineX, curLineY, clipDestX, clipDestY, i, curLineIdx, routeIdx);
if (bestRouteNum == 1)
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, i, curLineIdx, routeIdx)) {
lineIdx = _newLineIdx;
lineDataIdx = _newLineDataIdx;
routeIdx = _newRouteIdx;
loopCond = true;
break;
}
}
if (!loopCond) {
lineDataIdx = _lineItem[curLineIdx]._lineDataEndIdx - 1;
lineIdx = curLineIdx;
}
}
} while (loopCond);
if (lineIdx == curLineIdx) {
if (lineDataIdx <= curLineDataIdx)
routeIdx = _lineItem[curLineIdx].appendToRouteInc(lineDataIdx, curLineDataIdx, _bestRoute, routeIdx);
else
routeIdx = _lineItem[curLineIdx].appendToRouteDec(lineDataIdx, curLineDataIdx, _bestRoute, routeIdx);
}
if (characterRoute(_bestRoute[routeIdx - 1]._x, _bestRoute[routeIdx - 1]._y, clipDestX, clipDestY, -1, -1, routeIdx) != 1) {
_bestRoute[routeIdx].invalidate();
}
2013-02-20 07:30:16 +00:00
return &_bestRoute[0];
}
2013-03-28 09:25:42 +00:00
void LinesManager::useRoute0(int idx, int curRouteIdx) {
2013-03-05 07:26:51 +00:00
if (idx) {
int i = 0;
do {
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute0[i++];
} while (_testRoute0[i].isValid());
}
_bestRoute[curRouteIdx].invalidate();
}
void LinesManager::useRoute1(int idx, int curRouteIdx) {
if (idx) {
int i = 0;
do {
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute1[i++];
} while (_testRoute1[i].isValid());
2013-03-05 07:26:51 +00:00
}
_bestRoute[curRouteIdx].invalidate();
}
void LinesManager::useRoute2(int idx, int curRouteIdx) {
if (idx) {
int i = 0;
do {
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute2[i++];
} while (_testRoute2[i].isValid());
2013-03-05 07:26:51 +00:00
}
_bestRoute[curRouteIdx].invalidate();
}
2013-02-26 22:27:55 +00:00
int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int startLineIdx, int endLineIdx, int routeIdx) {
2013-03-06 22:47:33 +00:00
int collDataIdxRoute2 = 0;
bool colResult = false;
2013-01-27 11:04:24 +00:00
int curX = fromX;
int curY = fromY;
2013-02-26 22:27:55 +00:00
int curRouteIdx = routeIdx;
2013-03-06 22:47:33 +00:00
bool dummyLineFl = false;
2013-02-26 22:27:55 +00:00
if (startLineIdx == -1 && endLineIdx == -1)
2013-03-06 22:47:33 +00:00
dummyLineFl = true;
2013-01-27 11:04:24 +00:00
int foundDataIdx;
2013-02-26 22:27:55 +00:00
int foundLineIdx = startLineIdx;
2013-01-27 11:04:24 +00:00
if (checkCollisionLine(fromX, fromY, &foundDataIdx, &foundLineIdx, 0, _linesNumb)) {
2013-02-20 07:30:16 +00:00
switch (_lineItem[foundLineIdx]._direction) {
2013-02-18 00:19:41 +00:00
case DIR_UP:
2013-01-27 11:04:24 +00:00
curY -= 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_UP_RIGHT:
2013-01-27 11:04:24 +00:00
curY -= 2;
curX += 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_RIGHT:
2013-01-27 11:04:24 +00:00
curX += 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN_RIGHT:
2013-01-27 11:04:24 +00:00
curY += 2;
curX += 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN:
2013-01-27 11:04:24 +00:00
curY += 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_DOWN_LEFT:
2013-01-27 11:04:24 +00:00
curY += 2;
curX -= 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_LEFT:
2013-01-27 11:04:24 +00:00
curX -= 2;
break;
2013-02-18 00:19:41 +00:00
case DIR_UP_LEFT:
2013-01-27 11:04:24 +00:00
curY -= 2;
curX -= 2;
break;
default:
break;
}
}
2013-03-12 22:22:56 +00:00
int oldX = curX;
int oldY = curY;
2013-03-06 22:47:33 +00:00
int idxRoute0 = 0;
int collLineIdxRoute0 = -1;
int collLineIdxRoute1 = -1;
int collLineIdxRoute2 = -1;
2013-03-10 10:39:58 +00:00
int distX, distY;
int repeatFlag = 0;
2013-03-06 22:47:33 +00:00
int collDataIdxRoute0 = 0;
int collDataIdxRoute1 = 0;
for (;;) {
2013-03-06 22:47:33 +00:00
int newX = curX;
int newY = curY;
2013-01-27 11:04:24 +00:00
if (destX >= curX - 2 && destX <= curX + 2 && destY >= curY - 2 && destY <= curY + 2) {
2013-03-05 07:26:51 +00:00
_testRoute0[idxRoute0].invalidate();
2013-03-28 09:25:42 +00:00
useRoute0(idxRoute0, curRouteIdx);
2013-03-05 07:26:51 +00:00
return 1;
}
2013-03-06 22:47:33 +00:00
distX = abs(curX - destX) + 1;
distY = abs(curY - destY) + 1;
int maxDist;
if (distX > distY)
maxDist = distX;
else
2013-03-06 22:47:33 +00:00
maxDist = distY;
maxDist--;
assert(maxDist != 0);
int stepX = 1000 * distX / maxDist;
int stepY = 1000 * distY / maxDist;
2013-01-27 11:04:24 +00:00
if (destX < curX)
stepX = -stepX;
2013-01-27 11:04:24 +00:00
if (destY < curY)
stepY = -stepY;
int vertDirection = (int16)stepX / 1000;
int horzDirection = (int16)stepY / 1000;
2013-03-06 22:47:33 +00:00
Directions newDirection = DIR_NONE;
if (horzDirection == -1 && (stepX >= 0 && stepX <= 150))
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP;
if (vertDirection == 1 && (stepY >= -1 && stepY <= 150))
2013-02-18 00:19:41 +00:00
newDirection = DIR_RIGHT;
if (horzDirection == 1 && (stepX >= -150 && stepX <= 150))
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN;
if (vertDirection == -1 && (stepY >= -150 && stepY <= 150))
2013-02-18 00:19:41 +00:00
newDirection = DIR_LEFT;
if (horzDirection == -1 && (stepX >= -150 && stepX <= 0))
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP;
2013-03-06 22:47:33 +00:00
if (newDirection == DIR_NONE && !checkSmoothMove(curX, newY, destX, destY) && !makeSmoothMove(curX, newY, destX, destY)) {
newDirection = _smoothMoveDirection;
2013-03-10 10:39:58 +00:00
int smoothRouteIdx = 0;
for (smoothRouteIdx = 0; _smoothRoute[smoothRouteIdx]._posX != -1 && _smoothRoute[smoothRouteIdx]._posY != -1; ++smoothRouteIdx) {
if (checkCollisionLine(_smoothRoute[smoothRouteIdx]._posX, _smoothRoute[smoothRouteIdx]._posY, &collDataIdxRoute0, &collLineIdxRoute0, 0, _linesNumb)) {
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute0 > _lastLine)
collLineIdxRoute0 = -1;
break;
}
2013-03-10 10:39:58 +00:00
_testRoute0[idxRoute0].set(_smoothRoute[smoothRouteIdx]._posX, _smoothRoute[smoothRouteIdx]._posY, newDirection);
2013-03-05 07:26:51 +00:00
idxRoute0++;
if (repeatFlag == 1) {
repeatFlag = 2;
break;
}
}
2013-03-10 10:39:58 +00:00
if (repeatFlag != 2 && _smoothRoute[smoothRouteIdx]._posX != -1 && _smoothRoute[smoothRouteIdx]._posY != -1)
break;
repeatFlag = 1;
2013-03-10 10:39:58 +00:00
newX = _smoothRoute[smoothRouteIdx - 1]._posX;
newY = _smoothRoute[smoothRouteIdx - 1]._posY;
}
int newDistX = abs(newX - destX) + 1;
int newDistY = abs(newY - destY) + 1;
int newMaxDist = newDistY;
if (newDistX > newDistY)
newMaxDist = newDistX;
if (newMaxDist <= 10) {
2013-03-05 07:26:51 +00:00
_testRoute0[idxRoute0].invalidate();
2013-03-28 09:25:42 +00:00
useRoute0(idxRoute0, curRouteIdx);
2013-03-05 07:26:51 +00:00
return 1;
}
2013-03-10 10:39:58 +00:00
int newStepX = 1000 * newDistX / (newMaxDist - 1);
int newStepY = 1000 * newDistY / (newMaxDist - 1);
2013-03-06 22:47:33 +00:00
if (destX < newX)
newStepX = -newStepX;
2013-03-06 22:47:33 +00:00
if (destY < newY)
newStepY = -newStepY;
int newVertDirection = newStepX / 1000;
int newHorzDirection = newStepY / 1000;
2013-03-10 10:39:58 +00:00
int newSmoothX = 1000 * newX;
int newSmoothY = 1000 * newY;
int curPosX = newSmoothX / 1000;
int curPosY = newSmoothY / 1000;
if (!(newStepX / 1000) && newHorzDirection == -1)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP;
if (newVertDirection == 1) {
if (newHorzDirection == -1)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP_RIGHT;
if (!newHorzDirection)
2013-02-18 00:19:41 +00:00
newDirection = DIR_RIGHT;
if (newHorzDirection == 1)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN_RIGHT;
}
if (!newVertDirection && newHorzDirection == 1)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN;
if ((newVertDirection != -1) && (newHorzDirection == -1)) {
if (newStepX >= 0 && newStepX < 510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP;
else if (newStepX >= 510 && newStepX <= 1000)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP_RIGHT;
} else {
if (newHorzDirection == 1)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN_LEFT;
else if (!newHorzDirection)
2013-02-18 00:19:41 +00:00
newDirection = DIR_LEFT;
else if (newHorzDirection == -1) {
if (newStepX >= 0 && newStepX < 510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP;
else if (newStepX >= 510 && newStepX <= 1000)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP_RIGHT;
else
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP_LEFT;
}
}
if (newVertDirection == 1) {
if (newStepY >= -1000 && newStepY <= -510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP_RIGHT;
if (newStepY >= -510 && newStepY <= 510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_RIGHT;
if (newStepY >= 510 && newStepY <= 1000)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN_RIGHT;
}
if (newHorzDirection == 1) {
if (newStepX >= 510 && newStepX <= 1000)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN_RIGHT;
if (newStepX >= -510 && newStepX <= 510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN;
if (newStepX >= -1000 && newStepX <= -510)
newDirection = DIR_DOWN_LEFT;
}
if (newVertDirection == -1) {
if (newStepY >= 510 && newStepY <= 1000)
2013-02-18 00:19:41 +00:00
newDirection = DIR_DOWN_LEFT;
if (newStepY >= -510 && newStepY <= 510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_LEFT;
if (newStepY >= -1000 && newStepY <= -510)
newDirection = DIR_UP_LEFT;
}
if (newHorzDirection == -1) {
if (newStepX >= -1000 && newStepX <= -510)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP_LEFT;
if (newStepX >= -510 && newStepX <= 0)
2013-02-18 00:19:41 +00:00
newDirection = DIR_UP;
}
if (newMaxDist + 1 <= 0) {
2013-03-05 07:26:51 +00:00
_testRoute0[idxRoute0].invalidate();
2013-03-28 09:25:42 +00:00
useRoute0(idxRoute0, curRouteIdx);
2013-03-05 07:26:51 +00:00
return 1;
}
2013-03-10 10:39:58 +00:00
int curDist = 0;
while (!checkCollisionLine(curPosX, curPosY, &collDataIdxRoute0, &collLineIdxRoute0, 0, _linesNumb)) {
_testRoute0[idxRoute0].set(curPosX, curPosY, newDirection);
newSmoothX += newStepX;
newSmoothY += newStepY;
curPosX = newSmoothX / 1000;
curPosY = newSmoothY / 1000;
2013-03-05 07:26:51 +00:00
idxRoute0++;
2013-03-10 10:39:58 +00:00
++curDist;
if (curDist >= newMaxDist + 1) {
2013-03-05 07:26:51 +00:00
_testRoute0[idxRoute0].invalidate();
2013-03-28 09:25:42 +00:00
useRoute0(idxRoute0, curRouteIdx);
2013-03-05 07:26:51 +00:00
return 1;
}
}
2013-03-06 22:47:33 +00:00
if (_lastLine >= collLineIdxRoute0)
break;
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(collLineIdxRoute0, collDataIdxRoute0, curPosX, curPosY, destX, destY, idxRoute0, _testRoute0);
if (tmpRouteIdx == -1) {
2013-03-28 09:25:42 +00:00
useRoute0(idxRoute0, curRouteIdx);
2013-03-05 07:26:51 +00:00
return 1;
}
idxRoute0 = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1 || _newPosY != -1) {
2013-03-06 22:47:33 +00:00
collLineIdxRoute0 = -1;
break;
}
2013-01-27 11:04:24 +00:00
curX = -1;
curY = -1;
}
2013-03-05 07:26:51 +00:00
_testRoute0[idxRoute0].invalidate();
2013-03-06 22:47:33 +00:00
int idxRoute1 = 0;
2013-03-10 10:39:58 +00:00
int posXRoute1 = oldX;
int posYRoute1 = oldY;
while (true) {
2013-03-06 22:47:33 +00:00
if (destX >= posXRoute1 - 2 && destX <= posXRoute1 + 2 && destY >= posYRoute1 - 2 && destY <= posYRoute1 + 2) {
_testRoute1[idxRoute1].invalidate();
2013-03-05 07:26:51 +00:00
useRoute1(idxRoute1, curRouteIdx);
return 1;
}
2013-03-06 22:47:33 +00:00
while (posXRoute1 != destX) {
if (checkCollisionLine(posXRoute1, posYRoute1, &collDataIdxRoute1, &collLineIdxRoute1, 0, _linesNumb)) {
if (collLineIdxRoute1 > _lastLine)
collLineIdxRoute1 = -1;
break;
}
2013-03-06 22:47:33 +00:00
if (posXRoute1 < destX)
_testRoute1[idxRoute1++].set(posXRoute1++, posYRoute1, DIR_RIGHT);
else
2013-03-06 22:47:33 +00:00
_testRoute1[idxRoute1++].set(posXRoute1--, posYRoute1, DIR_LEFT);
}
2013-03-06 22:47:33 +00:00
if (posXRoute1 != destX)
break;
2013-03-06 22:47:33 +00:00
int curPosY = posYRoute1;
while (curPosY != destY) {
2013-03-06 22:47:33 +00:00
if (checkCollisionLine(destX, curPosY, &collDataIdxRoute1, &collLineIdxRoute1, 0, _linesNumb)) {
if (collLineIdxRoute1 <= _lastLine)
break;
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(collLineIdxRoute1, collDataIdxRoute1, destX, curPosY, destX, destY, idxRoute1, _testRoute1);
if (tmpRouteIdx == -1) {
2013-03-05 07:26:51 +00:00
useRoute1(idxRoute1, curRouteIdx);
return 1;
}
idxRoute1 = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1 && _newPosY != -1)
break;
}
if (curPosY < destY)
_testRoute1[idxRoute1++].set(destX, curPosY++, DIR_DOWN);
else
_testRoute1[idxRoute1++].set(destX, curPosY--, DIR_UP);
}
if (curPosY == destY) {
_testRoute1[idxRoute1].invalidate();
2013-03-05 07:26:51 +00:00
useRoute1(idxRoute1, curRouteIdx);
return 1;
}
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute1 <= _lastLine)
break;
2013-03-06 22:47:33 +00:00
posXRoute1 = _newPosX;
posYRoute1 = _newPosY;
bool colRes = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute1, &collLineIdxRoute1, 0, _lastLine);
if (colRes && collLineIdxRoute1 <= _lastLine)
break;
}
_testRoute1[idxRoute1].invalidate();
2013-03-05 07:26:51 +00:00
idxRoute1 = 0;
2013-03-10 10:39:58 +00:00
int posXRoute2 = oldX;
int posYRoute2 = oldY;
while (true) {
int curPosX;
2013-03-06 22:47:33 +00:00
if (destX >= posXRoute2 - 2 && destX <= posXRoute2 + 2 && destY >= posYRoute2 - 2 && destY <= posYRoute2 + 2) {
_testRoute2[idxRoute1].invalidate();
2013-03-05 07:26:51 +00:00
useRoute2(idxRoute1, curRouteIdx);
return 1;
}
2013-03-10 10:39:58 +00:00
int curPosYRoute2 = posYRoute2;
while (curPosYRoute2 != destY) {
if (checkCollisionLine(posXRoute2, curPosYRoute2, &collDataIdxRoute2, &collLineIdxRoute2, 0, _linesNumb)) {
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute2 > _lastLine)
collLineIdxRoute2 = -1;
break;
}
2013-03-10 10:39:58 +00:00
if (curPosYRoute2 < destY)
_testRoute2[idxRoute1++].set(posXRoute2, curPosYRoute2++, DIR_DOWN);
else
2013-03-10 10:39:58 +00:00
_testRoute2[idxRoute1++].set(posXRoute2, curPosYRoute2--, DIR_UP);
}
2013-03-10 10:39:58 +00:00
if (curPosYRoute2 != destY)
break;
2013-03-10 10:39:58 +00:00
curPosX = posXRoute2;
while (curPosX != destX) {
2013-03-06 22:47:33 +00:00
if (checkCollisionLine(curPosX, destY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _linesNumb)) {
if (collLineIdxRoute2 <= _lastLine)
break;
2013-03-28 16:59:34 +00:00
int tmpRouteIdx = computeRouteIdx(collLineIdxRoute2, collDataIdxRoute2, curPosX, destY, destX, destY, idxRoute1, _testRoute2);
if (tmpRouteIdx == -1) {
2013-03-05 07:26:51 +00:00
useRoute2(idxRoute1, curRouteIdx);
return 1;
}
idxRoute1 = tmpRouteIdx;
2013-02-20 07:30:16 +00:00
if (_newPosX != -1 && _newPosY != -1)
break;
}
if (curPosX < destX)
_testRoute2[idxRoute1++].set(curPosX++, destY, DIR_RIGHT);
else
_testRoute2[idxRoute1++].set(curPosX--, destY, DIR_LEFT);
}
if (curPosX == destX) {
2013-03-06 22:47:33 +00:00
collLineIdxRoute2 = -1;
_testRoute2[idxRoute1].invalidate();
2013-03-05 07:26:51 +00:00
useRoute2(idxRoute1, curRouteIdx);
return 1;
}
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute2 <= _lastLine)
break;
2013-03-06 22:47:33 +00:00
posXRoute2 = _newPosX;
posYRoute2 = _newPosY;
colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _lastLine);
if (colResult && collLineIdxRoute2 <= _lastLine)
break;
}
_testRoute2[idxRoute1].invalidate();
2013-03-06 22:47:33 +00:00
if (!dummyLineFl) {
2013-02-26 22:27:55 +00:00
if (endLineIdx > foundLineIdx) {
2013-03-06 22:47:33 +00:00
if (_testRoute0[0]._x != -1 && collLineIdxRoute0 > foundLineIdx && collLineIdxRoute1 <= collLineIdxRoute0 && collLineIdxRoute2 <= collLineIdxRoute0 && endLineIdx >= collLineIdxRoute0) {
_newLineIdx = collLineIdxRoute0;
_newLineDataIdx = collDataIdxRoute0;
int i = 0;
do {
2013-02-26 22:27:55 +00:00
assert(curRouteIdx <= 8000);
2013-03-05 07:26:51 +00:00
_bestRoute[curRouteIdx++] = _testRoute0[i++];
} while (_testRoute0[i].isValid());
2013-02-26 22:27:55 +00:00
_newRouteIdx = curRouteIdx;
return 2;
}
2013-03-06 22:47:33 +00:00
if (_testRoute1[0]._x != -1 && foundLineIdx < collLineIdxRoute1 && collLineIdxRoute2 <= collLineIdxRoute1 && collLineIdxRoute0 <= collLineIdxRoute1 && endLineIdx >= collLineIdxRoute1) {
_newLineIdx = collLineIdxRoute1;
_newLineDataIdx = collDataIdxRoute1;
int i = 0;
do {
2013-02-26 22:27:55 +00:00
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute1[i++];
} while (_testRoute1[i].isValid());
2013-02-26 22:27:55 +00:00
_newRouteIdx = curRouteIdx;
return 2;
}
2013-03-06 22:47:33 +00:00
if (_testRoute2[0]._x != -1 && foundLineIdx < collLineIdxRoute2 && collLineIdxRoute1 < collLineIdxRoute2 && collLineIdxRoute0 < collLineIdxRoute2 && endLineIdx >= collLineIdxRoute2) {
_newLineIdx = collLineIdxRoute2;
_newLineDataIdx = collDataIdxRoute2;
int i = 0;
do {
2013-02-26 22:27:55 +00:00
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute2[i++];
} while (_testRoute2[i].isValid());
2013-02-26 22:27:55 +00:00
_newRouteIdx = curRouteIdx;
return 2;
}
}
2013-02-26 22:27:55 +00:00
if (endLineIdx < foundLineIdx) {
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute0 == -1)
collLineIdxRoute0 = INVALID_LINE_VALUE;
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute1 == -1)
collLineIdxRoute0 = INVALID_LINE_VALUE;
2013-03-06 22:47:33 +00:00
if (collLineIdxRoute2 == -1)
collLineIdxRoute0 = INVALID_LINE_VALUE;
2013-03-06 22:47:33 +00:00
if (_testRoute1[0]._x != -1 && collLineIdxRoute1 < foundLineIdx && collLineIdxRoute2 >= collLineIdxRoute1 && collLineIdxRoute0 >= collLineIdxRoute1 && endLineIdx <= collLineIdxRoute1) {
_newLineIdx = collLineIdxRoute1;
_newLineDataIdx = collDataIdxRoute1;
int i = 0;
do {
2013-02-26 22:27:55 +00:00
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute1[i++];
} while (_testRoute1[i].isValid());
2013-02-26 22:27:55 +00:00
_newRouteIdx = curRouteIdx;
return 2;
}
2013-03-06 22:47:33 +00:00
if (_testRoute2[0]._x != -1 && foundLineIdx > collLineIdxRoute2 && collLineIdxRoute1 >= collLineIdxRoute2 && collLineIdxRoute0 >= collLineIdxRoute2 && endLineIdx <= collLineIdxRoute2) {
_newLineIdx = collLineIdxRoute2;
_newLineDataIdx = collDataIdxRoute2;
int i = 0;
do {
2013-02-26 22:27:55 +00:00
assert(curRouteIdx <= 8000);
_bestRoute[curRouteIdx++] = _testRoute2[i++];
} while (_testRoute2[i].isValid());
2013-02-26 22:27:55 +00:00
_newRouteIdx = curRouteIdx;
return 2;
}
// CHECKME: Checking essai0[0]._x might make more sense here?
2013-03-06 22:47:33 +00:00
if (_testRoute1[0]._x != -1 && foundLineIdx > collLineIdxRoute0 && collLineIdxRoute1 >= collLineIdxRoute0 && collLineIdxRoute2 >= collLineIdxRoute0 && endLineIdx <= collLineIdxRoute0) {
_newLineIdx = collLineIdxRoute0;
_newLineDataIdx = collDataIdxRoute0;
int i = 0;
do {
2013-02-26 22:27:55 +00:00
assert(curRouteIdx <= 8000);
2013-03-05 07:26:51 +00:00
_bestRoute[curRouteIdx++] = _testRoute0[i++];
} while (_testRoute0[i].isValid());
2013-02-26 22:27:55 +00:00
_newRouteIdx = curRouteIdx;
return 2;
}
}
}
return 0;
}
RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) {
RouteItem *result;
int arrDelta[10];
int arrDataIdx[10];
int arrLineIdx[10];
int clipX2 = x2;
int clipY2 = y2;
if (x2 <= 14)
clipX2 = 15;
if (y2 <= 14)
clipY2 = 15;
if (clipX2 > _vm->_graphicsMan->_maxX - 10)
clipX2 = _vm->_graphicsMan->_maxX - 10;
if (clipY2 > 445)
clipY2 = 440;
int delta = 0;
for (delta = 0; clipY2 + delta < _vm->_graphicsMan->_maxY; delta++) {
if (checkCollisionLine(clipX2, clipY2 + delta, &arrDataIdx[DIR_DOWN], &arrLineIdx[DIR_DOWN], 0, _lastLine) && arrLineIdx[DIR_DOWN] <= _lastLine)
break;
arrDataIdx[DIR_DOWN] = 0;
arrLineIdx[DIR_DOWN] = -1;
}
arrDelta[DIR_DOWN] = delta;
for (delta = 0; clipY2 - delta > _vm->_graphicsMan->_minY; delta++) {
if (checkCollisionLine(clipX2, clipY2 - delta , &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine) && arrLineIdx[DIR_UP] <= _lastLine)
break;
arrDataIdx[DIR_UP] = 0;
arrLineIdx[DIR_UP] = -1;
if (arrDelta[DIR_DOWN] < delta && arrLineIdx[DIR_DOWN] != -1)
break;
}
arrDelta[DIR_UP] = delta;
for (delta = 0; clipX2 + delta < _vm->_graphicsMan->_maxX; delta++) {
if (checkCollisionLine(clipX2 + delta, clipY2, &arrDataIdx[DIR_RIGHT], &arrLineIdx[DIR_RIGHT], 0, _lastLine) && arrLineIdx[DIR_RIGHT] <= _lastLine)
break;
arrDataIdx[DIR_RIGHT] = 0;
arrLineIdx[DIR_RIGHT] = -1;
if ((arrDelta[DIR_UP] <= delta && arrLineIdx[DIR_UP] != -1) || (arrDelta[DIR_DOWN] <= delta && arrLineIdx[DIR_DOWN] != -1))
break;
}
arrDelta[DIR_RIGHT] = delta;
for (delta = 0; clipX2 - delta > _vm->_graphicsMan->_minX; delta++) {
if (checkCollisionLine(clipX2 - delta, clipY2, &arrDataIdx[DIR_LEFT], &arrLineIdx[DIR_LEFT], 0, _lastLine) && arrLineIdx[DIR_LEFT] <= _lastLine)
break;
arrDataIdx[DIR_LEFT] = 0;
arrLineIdx[DIR_LEFT] = -1;
if ((arrDelta[DIR_UP] <= delta && arrLineIdx[DIR_UP] != -1) || (arrDelta[DIR_RIGHT] <= delta && arrLineIdx[DIR_RIGHT] != -1) || (arrDelta[DIR_DOWN] <= delta && arrLineIdx[DIR_DOWN] != -1))
break;
}
arrDelta[DIR_LEFT] = delta;
if (arrLineIdx[DIR_UP] == -1)
arrDelta[DIR_UP] = INVALID_LINE_VALUE;
if (arrLineIdx[DIR_RIGHT] == -1)
arrDelta[DIR_RIGHT] = INVALID_LINE_VALUE;
if (arrLineIdx[DIR_DOWN] == -1)
arrDelta[DIR_DOWN] = INVALID_LINE_VALUE;
if (arrLineIdx[DIR_LEFT] == -1)
arrDelta[DIR_LEFT] = INVALID_LINE_VALUE;
if (arrLineIdx[DIR_UP] != -1 || arrLineIdx[DIR_RIGHT] != -1 || arrLineIdx[DIR_DOWN] != -1 || arrLineIdx[DIR_LEFT] != -1) {
2013-03-26 23:51:35 +00:00
int curLineDataIdx = 0;
int curLineIdx = 0;
if (arrLineIdx[DIR_DOWN] != -1 && arrDelta[DIR_UP] >= arrDelta[DIR_DOWN] && arrDelta[DIR_RIGHT] >= arrDelta[DIR_DOWN] && arrDelta[DIR_LEFT] >= arrDelta[DIR_DOWN]) {
curLineIdx = arrLineIdx[DIR_DOWN];
curLineDataIdx = arrDataIdx[DIR_DOWN];
} else if (arrLineIdx[DIR_UP] != -1 && arrDelta[DIR_DOWN] >= arrDelta[DIR_UP] && arrDelta[DIR_RIGHT] >= arrDelta[DIR_UP] && arrDelta[DIR_LEFT] >= arrDelta[DIR_UP]) {
curLineIdx = arrLineIdx[DIR_UP];
curLineDataIdx = arrDataIdx[DIR_UP];
} else if (arrLineIdx[DIR_RIGHT] != -1 && arrDelta[DIR_UP] >= arrDelta[DIR_RIGHT] && arrDelta[DIR_DOWN] >= arrDelta[DIR_RIGHT] && arrDelta[DIR_LEFT] >= arrDelta[DIR_RIGHT]) {
curLineIdx = arrLineIdx[DIR_RIGHT];
curLineDataIdx = arrDataIdx[DIR_RIGHT];
} else if (arrLineIdx[DIR_LEFT] != -1 && arrDelta[DIR_DOWN] >= arrDelta[DIR_LEFT] && arrDelta[DIR_RIGHT] >= arrDelta[DIR_LEFT] && arrDelta[DIR_UP] >= arrDelta[DIR_LEFT]) {
curLineIdx = arrLineIdx[DIR_LEFT];
curLineDataIdx = arrDataIdx[DIR_LEFT];
}
for (int i = 0; i <= 8; i++) {
arrLineIdx[i] = -1;
arrDataIdx[i] = 0;
arrDelta[i] = INVALID_LINE_VALUE;
}
2013-03-26 23:51:35 +00:00
int superRouteIdx = 0;
int curRouteDataIdx = 0;
int curRouteLineIdx = 0;
if (checkCollisionLine(x1, y1, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine)) {
2013-03-12 22:22:56 +00:00
curRouteLineIdx = arrLineIdx[DIR_UP];
curRouteDataIdx = arrDataIdx[DIR_UP];
} else if (checkCollisionLine(x1, y1, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _linesNumb)) {
int curRouteIdx = 0;
int curRouteX;
for (;;) {
curRouteX = _testRoute2[curRouteIdx]._x;
int curRouteY = _testRoute2[curRouteIdx]._y;
2013-03-21 06:18:38 +00:00
Directions curRouteDir = _testRoute2[curRouteIdx]._dir;
curRouteIdx++;
if (checkCollisionLine(curRouteX, curRouteY, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine))
break;
2013-03-21 06:18:38 +00:00
_bestRoute[superRouteIdx].set(curRouteX, curRouteY, curRouteDir);
2013-03-21 06:18:38 +00:00
_testRoute0[superRouteIdx].set(curRouteX, curRouteY, curRouteDir);
superRouteIdx++;
if (curRouteX == -1)
break;;
}
if (curRouteX != -1) {
2013-03-12 22:22:56 +00:00
curRouteLineIdx = arrLineIdx[DIR_UP];
curRouteDataIdx = arrDataIdx[DIR_UP];
}
} else {
2013-03-12 22:22:56 +00:00
curRouteLineIdx = 1;
curRouteDataIdx = 1;
superRouteIdx = 0;
}
bool loopFl = true;
while (loopFl) {
loopFl = false;
2013-03-12 22:22:56 +00:00
if (curRouteLineIdx < curLineIdx) {
superRouteIdx = _lineItem[curRouteLineIdx].appendToRouteInc(curRouteDataIdx, _lineItem[curRouteLineIdx]._lineDataEndIdx - 2, _bestRoute, superRouteIdx);
for (int j = curRouteLineIdx + 1; j < curLineIdx; ++j) {
if (PLAN_TEST(_lineItem[j]._lineData[0], _lineItem[j]._lineData[1], superRouteIdx, j, curLineIdx)) {
2013-03-12 22:22:56 +00:00
curRouteLineIdx = _newLineIdx;
curRouteDataIdx = _newLineDataIdx;
2013-02-20 07:30:16 +00:00
superRouteIdx = _newRouteIdx;
loopFl = true;
break;
}
2013-02-20 07:30:16 +00:00
if (_lineItem[j]._lineDataEndIdx - 2 > 0) {
superRouteIdx = _lineItem[j].appendToRouteInc(0, _lineItem[j]._lineDataEndIdx - 2, _bestRoute, superRouteIdx);
}
}
if (loopFl)
continue;
2013-03-12 22:22:56 +00:00
curRouteDataIdx = 0;
curRouteLineIdx = curLineIdx;
}
2013-03-12 22:22:56 +00:00
if (curRouteLineIdx > curLineIdx) {
superRouteIdx = _lineItem[curRouteLineIdx].appendToRouteDec(curRouteDataIdx, 0, _bestRoute, superRouteIdx);
for (int l = curRouteLineIdx - 1; l > curLineIdx; --l) {
if (PLAN_TEST(_lineItem[l]._lineData[2 * _lineItem[l]._lineDataEndIdx - 2], _lineItem[l]._lineData[2 * _lineItem[l]._lineDataEndIdx - 1], superRouteIdx, l, curLineIdx)) {
2013-03-12 22:22:56 +00:00
curRouteLineIdx = _newLineIdx;
curRouteDataIdx = _newLineDataIdx;
superRouteIdx = _newRouteIdx;
loopFl = true;
break;
}
2013-02-20 07:30:16 +00:00
superRouteIdx = _lineItem[l].appendToRouteDec(_lineItem[l]._lineDataEndIdx - 2, 0, _bestRoute, superRouteIdx);
}
if (loopFl)
continue;
2013-03-12 22:22:56 +00:00
curRouteDataIdx = _lineItem[curLineIdx]._lineDataEndIdx - 1;
curRouteLineIdx = curLineIdx;
}
2013-03-12 22:22:56 +00:00
if (curRouteLineIdx == curLineIdx) {
if (curRouteDataIdx <= curLineDataIdx) {
superRouteIdx = _lineItem[curLineIdx].appendToRouteInc(curRouteDataIdx, curLineDataIdx, _bestRoute, superRouteIdx);
} else {
2013-03-12 22:22:56 +00:00
superRouteIdx = _lineItem[curLineIdx].appendToRouteDec(curRouteDataIdx, curLineDataIdx, _bestRoute, superRouteIdx);
}
}
}
2013-02-20 07:30:16 +00:00
_bestRoute[superRouteIdx].invalidate();
result = &_bestRoute[0];
} else {
result = NULL;
}
return result;
}
bool LinesManager::checkSmoothMove(int fromX, int fromY, int destX, int destY) {
int distX = abs(fromX - destX) + 1;
int distY = abs(fromY - destY) + 1;
if (distX > distY)
distY = distX;
if (distY <= 10)
return true;
int stepX = 1000 * distX / (distY - 1);
int stepY = 1000 * distY / (distY - 1);
if (destX < fromX)
stepX = -stepX;
if (destY < fromY)
stepY = -stepY;
int smoothPosX = 1000 * fromX;
int smoothPosY = 1000 * fromY;
int newPosX = fromX;
int newPosY = fromY;
if (distY + 1 > 0) {
int stepCount = 0;
int foundLineIdx;
int foundDataIdx;
while (!checkCollisionLine(newPosX, newPosY, &foundDataIdx, &foundLineIdx, 0, _linesNumb) || foundLineIdx > _lastLine) {
smoothPosX += stepX;
smoothPosY += stepY;
newPosX = smoothPosX / 1000;
newPosY = smoothPosY / 1000;
++stepCount;
if (stepCount >= distY + 1)
return false;
}
return true;
}
return false;
}
bool LinesManager::makeSmoothMove(int fromX, int fromY, int destX, int destY) {
int curX = fromX;
int curY = fromY;
if (fromX > destX && destY > fromY) {
int hopkinsIdx = 36;
int smoothIdx = 0;
int stepCount = 0;
while (curX > destX && destY > curY) {
int realSpeedX = _vm->_globals->_hopkinsItem[hopkinsIdx]._speedX;
int realSpeedY = _vm->_globals->_hopkinsItem[hopkinsIdx]._speedY;
int spriteSize = _vm->_globals->_spriteSize[curY];
if (spriteSize < 0) {
realSpeedX = _vm->_graphicsMan->zoomOut(realSpeedX, -spriteSize);
realSpeedY = _vm->_graphicsMan->zoomOut(realSpeedY, -spriteSize);
} else if (spriteSize > 0) {
realSpeedX = _vm->_graphicsMan->zoomIn(realSpeedX, spriteSize);
realSpeedY = _vm->_graphicsMan->zoomIn(realSpeedY, spriteSize);
}
2013-03-08 06:56:53 +00:00
for (int i = 0; i < realSpeedX; i++) {
--curX;
_smoothRoute[smoothIdx]._posX = curX;
2013-03-08 06:56:53 +00:00
if (curY != curY + realSpeedY)
curY++;
_smoothRoute[smoothIdx]._posY = curY;
smoothIdx++;
}
++hopkinsIdx;
if (hopkinsIdx == 48)
hopkinsIdx = 36;
++stepCount;
}
if (stepCount > 5) {
_smoothRoute[smoothIdx]._posX = -1;
_smoothRoute[smoothIdx]._posY = -1;
2013-02-18 00:19:41 +00:00
_smoothMoveDirection = DIR_DOWN_LEFT;
return false;
}
} else if (fromX < destX && destY > fromY) {
int hopkinsIdx = 36;
int smoothIdx = 0;
int stepCount = 0;
while (curX < destX && destY > curY) {
int realSpeedX = _vm->_globals->_hopkinsItem[hopkinsIdx]._speedX;
int realSpeedY = _vm->_globals->_hopkinsItem[hopkinsIdx]._speedY;
int spriteSize = _vm->_globals->_spriteSize[curY];
if (spriteSize < 0) {
realSpeedX = _vm->_graphicsMan->zoomOut(realSpeedX, -spriteSize);
realSpeedY = _vm->_graphicsMan->zoomOut(realSpeedY, -spriteSize);
} else if (spriteSize > 0) {
realSpeedX = _vm->_graphicsMan->zoomIn(realSpeedX, spriteSize);
realSpeedY = _vm->_graphicsMan->zoomIn(realSpeedY, spriteSize);
}
2013-03-08 06:56:53 +00:00
for (int i = 0; i < realSpeedX; i++) {
++curX;
_smoothRoute[smoothIdx]._posX = curX;
2013-03-08 06:56:53 +00:00
if (curY != curY + realSpeedY)
curY++;
_smoothRoute[smoothIdx]._posY = curY;
smoothIdx++;
}
++hopkinsIdx;
if (hopkinsIdx == 48)
hopkinsIdx = 36;
++stepCount;
}
if (stepCount > 5) {
_smoothRoute[smoothIdx]._posX = -1;
_smoothRoute[smoothIdx]._posY = -1;
2013-02-18 00:19:41 +00:00
_smoothMoveDirection = DIR_DOWN_RIGHT;
return false;
}
} else if (fromX > destX && destY < fromY) {
int hopkinsIdx = 12;
int smoothIdx = 0;
int stepCount = 0;
while (curX > destX && destY < curY) {
int realSpeedX = _vm->_graphicsMan->zoomOut(_vm->_globals->_hopkinsItem[hopkinsIdx]._speedX, 25);
int realSpeedY = _vm->_graphicsMan->zoomOut(_vm->_globals->_hopkinsItem[hopkinsIdx]._speedY, 25);
int oldY = curY;
2013-03-08 06:56:53 +00:00
for (int i = 0; i < realSpeedX; i++) {
--curX;
_smoothRoute[smoothIdx]._posX = curX;
2013-03-08 06:56:53 +00:00
if ((uint16)curY != (uint16)oldY + realSpeedY)
curY--;
_smoothRoute[smoothIdx]._posY = curY;
smoothIdx++;
}
++hopkinsIdx;
if (hopkinsIdx == 24)
hopkinsIdx = 12;
++stepCount;
}
if (stepCount > 5) {
_smoothRoute[smoothIdx]._posX = -1;
_smoothRoute[smoothIdx]._posY = -1;
2013-02-18 00:19:41 +00:00
_smoothMoveDirection = DIR_UP_LEFT;
return false;
}
} else if (fromX < destX && destY < fromY) {
int hopkinsIdx = 12;
int smoothIdx = 0;
int stepCount = 0;
while (curX < destX && destY < curY) {
int oldY = curY;
int realSpeedX = _vm->_graphicsMan->zoomOut(_vm->_globals->_hopkinsItem[hopkinsIdx]._speedX, 25);
int realSpeedY = _vm->_graphicsMan->zoomOut(_vm->_globals->_hopkinsItem[hopkinsIdx]._speedY, 25);
2013-03-12 22:22:56 +00:00
for (int i = 0; i < realSpeedX; i++) {
++curX;
_smoothRoute[smoothIdx]._posX = curX;
2013-03-12 22:22:56 +00:00
if ((uint16)curY != (uint16)oldY + realSpeedY)
curY--;
_smoothRoute[smoothIdx]._posY = curY;
smoothIdx++;
}
++hopkinsIdx;
if (hopkinsIdx == 24)
hopkinsIdx = 12;
++stepCount;
}
if (stepCount > 5) {
_smoothRoute[smoothIdx]._posX = -1;
_smoothRoute[smoothIdx]._posY = -1;
2013-02-18 00:19:41 +00:00
_smoothMoveDirection = DIR_UP_RIGHT;
return false;
}
}
return true;
}
bool LinesManager::PLAN_TEST(int paramX, int paramY, int superRouteIdx, int paramStartLineIdx, int paramEndLineIdx) {
2013-03-08 06:56:53 +00:00
int sideTestUp;
int sideTestDown;
int sideTestLeft;
int sideTestRight;
2013-01-11 18:19:49 +00:00
int lineIdxTestUp;
int lineIdxTestDown;
int lineIdxTestLeft;
int lineIdxTestRight;
int dataIdxTestUp;
int dataIdxTestDown;
int dataIdxTestLeft;
int dataIdxTestRight;
2013-01-11 18:19:49 +00:00
2013-03-08 06:56:53 +00:00
int idxTestUp = testLine(paramX, paramY - 2, &sideTestUp, &lineIdxTestUp, &dataIdxTestUp);
int idxTestDown = testLine(paramX, paramY + 2, &sideTestDown, &lineIdxTestDown, &dataIdxTestDown);
int idxTestLeft = testLine(paramX - 2, paramY, &sideTestLeft, &lineIdxTestLeft, &dataIdxTestLeft);
int idxTestRight = testLine(paramX + 2, paramY, &sideTestRight, &lineIdxTestRight, &dataIdxTestRight);
2013-01-11 18:19:49 +00:00
if (idxTestUp == -1 && idxTestDown == -1 && idxTestLeft == -1 && idxTestRight == -1)
2013-01-11 00:50:29 +00:00
return false;
2013-01-11 18:19:49 +00:00
// Direction: 1 = Up, 2 = Down, 3 = Left, 4 = Right
int direction;
if (paramStartLineIdx == -1 || paramEndLineIdx == -1) {
2013-01-11 18:19:49 +00:00
if (idxTestUp != -1)
direction = 1;
2013-01-11 18:19:49 +00:00
else if (idxTestDown != -1)
direction = 2;
2013-01-11 18:19:49 +00:00
else if (idxTestLeft != -1)
direction = 3;
2013-01-11 18:19:49 +00:00
else if (idxTestRight != -1)
direction = 4;
else
2013-01-11 18:19:49 +00:00
return false;
} else {
int stepCountUp = 100;
int stepCountDown = 100;
int stepCountLeft = 100;
int stepCountRight = 100;
int paramStepCount = abs(paramStartLineIdx - paramEndLineIdx);
2013-01-11 18:19:49 +00:00
if (idxTestUp != -1) {
stepCountUp = abs(lineIdxTestUp - paramEndLineIdx);
2013-01-11 18:19:49 +00:00
}
if (idxTestDown != -1) {
stepCountDown = abs(lineIdxTestDown - paramEndLineIdx);
2013-01-11 18:19:49 +00:00
}
if (idxTestLeft != -1) {
stepCountLeft = abs(lineIdxTestLeft - paramEndLineIdx);
2013-01-11 18:19:49 +00:00
}
if (idxTestRight != -1) {
stepCountRight = abs(lineIdxTestRight - paramEndLineIdx);
2013-01-11 18:19:49 +00:00
}
if (stepCountUp < paramStepCount && stepCountUp <= stepCountDown && stepCountUp <= stepCountLeft && stepCountUp <= stepCountRight)
direction = 1;
else if (paramStepCount > stepCountDown && stepCountUp >= stepCountDown && stepCountLeft >= stepCountDown && stepCountRight >= stepCountDown)
direction = 2;
else if (stepCountLeft < paramStepCount && stepCountLeft <= stepCountUp && stepCountLeft <= stepCountDown && stepCountLeft <= stepCountRight)
direction = 3;
else if (stepCountRight < paramStepCount && stepCountRight <= stepCountUp && stepCountRight <= stepCountDown && stepCountRight <= stepCountLeft)
direction = 4;
2013-01-11 18:19:49 +00:00
else
return false;
}
2013-01-11 18:19:49 +00:00
2013-03-08 06:56:53 +00:00
int sideTest = 0;
2013-01-11 18:19:49 +00:00
int idxTest = 0;
if (direction == 1) {
2013-01-11 18:19:49 +00:00
idxTest = idxTestUp;
2013-03-08 06:56:53 +00:00
sideTest = sideTestUp;
2013-02-20 07:30:16 +00:00
_newLineIdx = lineIdxTestUp;
_newLineDataIdx = dataIdxTestUp;
} else if (direction == 2) {
2013-01-11 18:19:49 +00:00
idxTest = idxTestDown;
2013-03-08 06:56:53 +00:00
sideTest = sideTestDown;
2013-02-20 07:30:16 +00:00
_newLineIdx = lineIdxTestDown;
_newLineDataIdx = dataIdxTestDown;
} else if (direction == 3) {
2013-01-11 18:19:49 +00:00
idxTest = idxTestLeft;
2013-03-08 06:56:53 +00:00
sideTest = sideTestLeft;
2013-02-20 07:30:16 +00:00
_newLineIdx = lineIdxTestLeft;
_newLineDataIdx = dataIdxTestLeft;
} else if (direction == 4) {
2013-01-11 18:19:49 +00:00
idxTest = idxTestRight;
2013-03-08 06:56:53 +00:00
sideTest = sideTestRight;
2013-02-20 07:30:16 +00:00
_newLineIdx = lineIdxTestRight;
_newLineDataIdx = dataIdxTestRight;
}
2013-01-11 18:19:49 +00:00
2013-02-26 22:27:55 +00:00
int routeIdx = superRouteIdx;
2013-03-08 06:56:53 +00:00
if (sideTest == 1) {
2013-02-26 22:27:55 +00:00
routeIdx = _lineItem[idxTest].appendToRouteInc(0, -1, _bestRoute, routeIdx);
2013-03-08 06:56:53 +00:00
} else if (sideTest == 2) {
2013-02-26 22:27:55 +00:00
routeIdx = _lineItem[idxTest].appendToRouteDec(-1, -1, _bestRoute, routeIdx);
}
2013-02-26 22:27:55 +00:00
_newRouteIdx = routeIdx;
2013-01-11 00:50:29 +00:00
return true;
}
// Test line
int LinesManager::testLine(int paramX, int paramY, int *testValue, int *foundLineIdx, int *foundDataIdx) {
2013-01-11 07:16:47 +00:00
int16 *lineData;
int lineDataEndIdx;
int collLineIdx;
int collDataIdx;
for (int idx = _lastLine + 1; idx < _linesNumb + 1; idx++) {
2013-02-20 07:30:16 +00:00
lineData = _lineItem[idx]._lineData;
lineDataEndIdx = _lineItem[idx]._lineDataEndIdx;
if (!lineData)
continue;
if (lineData[0] == paramX && lineData[1] == paramY) {
*testValue = 1;
int posX = lineData[2 * (lineDataEndIdx - 1)];
int posY = lineData[2 * (lineDataEndIdx - 1) + 1];
if (_lineItem[idx]._directionRouteInc == DIR_DOWN || _lineItem[idx]._directionRouteInc == DIR_UP)
posY += 2;
if (_lineItem[idx]._directionRouteInc == DIR_RIGHT || _lineItem[idx]._directionRouteDec == DIR_LEFT)
posX += 2;
if (!checkCollisionLine(posX, posY, &collDataIdx, &collLineIdx, 0, _lastLine))
error("Error in test line");
*foundLineIdx = collLineIdx;
*foundDataIdx = collDataIdx;
return idx;
2013-01-11 07:16:47 +00:00
}
if (lineDataEndIdx > 0) {
if (lineData[2 * (lineDataEndIdx - 1)] == paramX && lineData[2 * (lineDataEndIdx - 1) + 1] == paramY) {
*testValue = 2;
int posX = lineData[0];
int posY = lineData[1];
if (_lineItem[idx]._directionRouteInc == DIR_DOWN || _lineItem[idx]._directionRouteInc == DIR_UP)
posY -= 2;
if (_lineItem[idx]._directionRouteInc == DIR_RIGHT || _lineItem[idx]._directionRouteDec == DIR_LEFT)
posX -= 2;
if (!checkCollisionLine(posX, posY, &collDataIdx, &collLineIdx, 0, _lastLine))
error("Error in test line");
*foundLineIdx = collLineIdx;
*foundDataIdx = collDataIdx;
return idx;
}
}
2013-01-11 07:16:47 +00:00
}
return -1;
}
2013-03-28 09:25:42 +00:00
int LinesManager::computeYSteps(int idx) {
int zoomPct = _vm->_globals->_spriteSize[idx];
if (_vm->_globals->_characterType == 1) {
2013-03-28 09:25:42 +00:00
if (zoomPct < 0)
zoomPct = -zoomPct;
zoomPct = 20 * (5 * zoomPct - 100) / -80;
} else if (_vm->_globals->_characterType == 2) {
2013-03-28 09:25:42 +00:00
if (zoomPct < 0)
zoomPct = -zoomPct;
zoomPct = 20 * (5 * zoomPct - 165) / -67;
}
2013-02-19 20:12:57 +00:00
int retVal = 25;
2013-03-28 09:25:42 +00:00
if (zoomPct < 0)
retVal = _vm->_graphicsMan->zoomOut(25, -zoomPct);
2013-03-28 09:25:42 +00:00
else if (zoomPct > 0)
retVal = _vm->_graphicsMan->zoomIn(25, zoomPct);
return retVal;
}
2013-03-28 09:25:42 +00:00
void LinesManager::optimizeRoute(RouteItem *route) {
if (route[0]._x == -1 && route[0]._y == -1)
return;
2013-02-19 17:06:05 +00:00
int routeIdx = 0;
Directions oldDir = DIR_NONE;
int route0Y = route[0]._y;
Directions curDir = route[0]._dir;
for (;;) {
2013-02-19 17:06:05 +00:00
if (oldDir != DIR_NONE && curDir != oldDir) {
int oldRouteIdx = routeIdx;
int routeCount = 0;
2013-03-28 09:25:42 +00:00
int yStep = computeYSteps(route0Y);
2013-02-19 17:06:05 +00:00
int curRouteX = route[routeIdx]._x;
int curRouteY = route[routeIdx]._y;
while (curRouteX != -1 || curRouteY != -1) {
int idx = routeIdx;
++routeIdx;
++routeCount;
if (route[idx]._dir != curDir)
break;
2013-02-19 17:06:05 +00:00
curRouteX = route[routeIdx]._x;
curRouteY = route[routeIdx]._y;
}
2013-03-28 09:25:42 +00:00
if (routeCount < yStep) {
2013-02-19 17:06:05 +00:00
int idx = oldRouteIdx;
for (int i = 0; i < routeCount; i++) {
route[idx]._dir = oldDir;
idx++;
}
2013-02-19 17:06:05 +00:00
curDir = oldDir;
}
2013-02-19 17:06:05 +00:00
routeIdx = oldRouteIdx;
if (curRouteX == -1 && curRouteY == -1)
break;
}
2013-02-19 17:06:05 +00:00
routeIdx++;
oldDir = curDir;
route0Y = route[routeIdx]._y;
curDir = route[routeIdx]._dir;
if (route[routeIdx]._x == -1 && route0Y == -1)
break;
}
}
int LinesManager::getMouseZone() {
int result;
int xp = _vm->_events->_mousePos.x + _vm->_events->_mouseOffset.x;
int yp = _vm->_events->_mousePos.y + _vm->_events->_mouseOffset.y;
if ((_vm->_events->_mousePos.y + _vm->_events->_mouseOffset.y) > 19) {
for (int bobZoneId = 0; bobZoneId <= 48; bobZoneId++) {
int bobId = _bobZone[bobZoneId];
if (bobId && _bobZoneFl[bobZoneId] && _vm->_objectsMan->_bob[bobId]._bobMode && _vm->_objectsMan->_bob[bobId]._frameIndex != 250 &&
!_vm->_objectsMan->_bob[bobId]._disabledAnimationFl && xp > _vm->_objectsMan->_bob[bobId]._oldX &&
xp < _vm->_objectsMan->_bob[bobId]._oldWidth + _vm->_objectsMan->_bob[bobId]._oldX && yp > _vm->_objectsMan->_bob[bobId]._oldY) {
if (yp < _vm->_objectsMan->_bob[bobId]._oldHeight + _vm->_objectsMan->_bob[bobId]._oldY) {
if (_zone[bobZoneId]._spriteIndex == -1) {
_zone[bobZoneId]._destX = 0;
_zone[bobZoneId]._destY = 0;
}
if (!_zone[bobZoneId]._destX && !_zone[bobZoneId]._destY) {
_zone[bobZoneId]._destX = _vm->_objectsMan->_bob[bobId]._oldWidth + _vm->_objectsMan->_bob[bobId]._oldX;
_zone[bobZoneId]._destY = _vm->_objectsMan->_bob[bobId]._oldHeight + _vm->_objectsMan->_bob[bobId]._oldY + 6;
_zone[bobZoneId]._spriteIndex = -1;
}
return bobZoneId;
}
}
}
_currentSegmentId = 0;
for (int squareZoneId = 0; squareZoneId <= 99; squareZoneId++) {
if (_zone[squareZoneId]._enabledFl && _squareZone[squareZoneId]._enabledFl
&& _squareZone[squareZoneId]._left <= xp && _squareZone[squareZoneId]._right >= xp
&& _squareZone[squareZoneId]._top <= yp && _squareZone[squareZoneId]._bottom >= yp) {
if (_squareZone[squareZoneId]._squareZoneFl)
return _zoneLine[_squareZone[squareZoneId]._minZoneLineIdx]._bobZoneIdx;
_segment[_currentSegmentId]._minZoneLineIdx = _squareZone[squareZoneId]._minZoneLineIdx;
_segment[_currentSegmentId]._maxZoneLineIdx = _squareZone[squareZoneId]._maxZoneLineIdx;
++_currentSegmentId;
}
}
if (!_currentSegmentId)
return -1;
int colRes1 = 0;
for (int yCurrent = yp; yCurrent >= 0; --yCurrent) {
colRes1 = checkCollision(xp, yCurrent);
if (colRes1 != -1 && _zone[colRes1]._enabledFl)
break;
}
if (colRes1 == -1)
return -1;
int colRes2 = 0;
for (int j = yp; j < _vm->_graphicsMan->_maxY; ++j) {
colRes2 = checkCollision(xp, j);
if (colRes2 != -1 && _zone[colRes1]._enabledFl)
break;
}
if (colRes2 == -1)
return -1;
int colRes3 = 0;
for (int k = xp; k >= 0; --k) {
colRes3 = checkCollision(k, yp);
if (colRes3 != -1 && _zone[colRes1]._enabledFl)
break;
}
if (colRes3 == -1)
return -1;
int colRes4 = 0;
for (int xCurrent = xp; _vm->_graphicsMan->_maxX > xCurrent; ++xCurrent) {
colRes4 = checkCollision(xCurrent, yp);
if (colRes4 != -1 && _zone[colRes1]._enabledFl)
break;
}
if (colRes1 == colRes2 && colRes1 == colRes3 && colRes1 == colRes4)
result = colRes1;
else
result = -1;
} else {
result = 0;
}
return result;
}
int LinesManager::checkCollision(int xp, int yp) {
if (_currentSegmentId <= 0)
return -1;
int xMax = xp + 4;
int xMin = xp - 4;
for (int idx = 0; idx <= _currentSegmentId; ++idx) {
int curZoneLineIdx = _segment[idx]._minZoneLineIdx;
if (_segment[idx]._maxZoneLineIdx < curZoneLineIdx)
continue;
int yMax = yp + 4;
int yMin = yp - 4;
do {
LigneZoneItem *curZoneLine = &_zoneLine[curZoneLineIdx];
int16 *dataP = curZoneLine->_zoneData;
2013-04-04 23:43:10 +00:00
if (dataP) {
int count = curZoneLine->_count;
int startX = dataP[0];
int startY = dataP[1];
int destX = dataP[count * 2 - 2];
int destY = dataP[count * 2 - 1];
bool flag = true;
if ((startX < destX && (xMax < startX || xMin > destX)) ||
(startX >= destX && (xMin > startX || xMax < destX)) ||
(startY < destY && (yMax < startY || yMin > destY)) ||
(startY >= destY && (yMin > startY || yMax < destY)))
flag = false;
if (flag && curZoneLine->_count > 0) {
for (int i = 0; i < count; ++i) {
int xCheck = *dataP++;
int yCheck = *dataP++;
if ((xp == xCheck || (xp + 1) == xCheck) && (yp == yCheck))
return curZoneLine->_bobZoneIdx;
}
}
}
} while (++curZoneLineIdx <= _segment[idx]._maxZoneLineIdx);
}
return -1;
}
// Square Zone
2013-03-28 09:25:42 +00:00
void LinesManager::initSquareZones() {
for (int idx = 0; idx < 100; ++idx) {
SquareZoneItem *curZone = &_squareZone[idx];
curZone->_enabledFl = false;
curZone->_squareZoneFl = false;
curZone->_left = 1280;
curZone->_right = 0;
curZone->_top = 460;
curZone->_bottom = 0;
curZone->_minZoneLineIdx = 401;
curZone->_maxZoneLineIdx = 0;
}
2013-04-20 22:40:09 +00:00
for (int idx = 0; idx < MAX_LINES + 1; ++idx) {
int16 *dataP = _zoneLine[idx]._zoneData;
if (dataP == NULL)
continue;
SquareZoneItem *curZone = &_squareZone[_zoneLine[idx]._bobZoneIdx];
curZone->_enabledFl = true;
2013-03-28 09:25:42 +00:00
curZone->_maxZoneLineIdx = MAX(curZone->_maxZoneLineIdx, idx);
curZone->_minZoneLineIdx = MIN(curZone->_minZoneLineIdx, idx);
for (int i = 0; i < _zoneLine[idx]._count; i++) {
int zoneX = *dataP++;
int zoneY = *dataP++;
curZone->_left = MIN(curZone->_left, zoneX);
curZone->_right = MAX(curZone->_right, zoneX);
curZone->_top = MIN(curZone->_top, zoneY);
curZone->_bottom = MAX(curZone->_bottom, zoneY);
}
}
for (int idx = 0; idx < 100; idx++) {
int zoneWidth = abs(_squareZone[idx]._left - _squareZone[idx]._right);
int zoneHeight = abs(_squareZone[idx]._top - _squareZone[idx]._bottom);
if (zoneWidth == zoneHeight)
_squareZone[idx]._squareZoneFl = true;
}
}
void LinesManager::clearAll() {
for (int idx = 0; idx < 105; ++idx) {
_zone[idx]._destX = 0;
_zone[idx]._destY = 0;
_zone[idx]._spriteIndex = 0;
}
_testRoute0 = NULL;
_testRoute1 = NULL;
_testRoute2 = NULL;
_lineBuf = NULL;
_route = NULL;
for (int idx = 0; idx < MAX_LINES; ++idx) {
2013-02-20 07:30:16 +00:00
_lineItem[idx]._lineDataEndIdx = 0;
_lineItem[idx]._direction = DIR_NONE;
_lineItem[idx]._directionRouteInc = DIR_NONE;
_lineItem[idx]._directionRouteDec = DIR_NONE;
_lineItem[idx]._lineData = NULL;
_zoneLine[idx]._count = 0;
_zoneLine[idx]._bobZoneIdx = 0;
_zoneLine[idx]._zoneData = NULL;
}
for (int idx = 0; idx < 100; ++idx)
_squareZone[idx]._enabledFl = false;
_testRoute0 = new RouteItem[8334];
_testRoute1 = new RouteItem[8334];
_testRoute2 = new RouteItem[8334];
if (!_testRoute0)
_testRoute0 = NULL;
if (!_testRoute1)
_testRoute1 = NULL;
if (!_testRoute2)
_testRoute2 = NULL;
_largeBuf = _vm->_globals->allocMemory(10000);
_lineBuf = (int16 *)(_largeBuf);
}
/**
* Clear all zones and reset nextLine
*/
void LinesManager::clearAllZones() {
for (int idx = 0; idx < MAX_LINES; ++idx)
removeZoneLine(idx);
}
/**
* Remove Zone Line
*/
void LinesManager::removeZoneLine(int idx) {
2013-04-21 05:13:02 +00:00
assert(idx < MAX_LINES + 1);
_zoneLine[idx]._zoneData = (int16 *)_vm->_globals->freeMemory((byte *)_zoneLine[idx]._zoneData);
}
void LinesManager::resetLines() {
for (int idx = 0; idx < MAX_LINES; ++idx) {
removeLine(idx);
2013-02-20 07:30:16 +00:00
_lineItem[idx]._lineDataEndIdx = 0;
_lineItem[idx]._lineData = NULL;
}
}
// Remove Line
void LinesManager::removeLine(int idx) {
2013-04-21 05:13:02 +00:00
assert(idx < MAX_LINES);
_lineItem[idx]._lineData = (int16 *)_vm->_globals->freeMemory((byte *)_lineItem[idx]._lineData);
}
void LinesManager::setMaxLineIdx(int idx) {
_maxLineIdx = idx;
}
void LinesManager::resetLastLine() {
_lastLine = 0;
}
void LinesManager::resetLinesNumb() {
_linesNumb = 0;
}
void LinesManager::enableZone(int idx) {
if (_bobZone[idx]) {
_bobZoneFl[idx] = true;
} else {
_zone[idx]._enabledFl = true;
}
}
void LinesManager::disableZone(int idx) {
if (_bobZone[idx]) {
_bobZoneFl[idx] = false;
} else {
_zone[idx]._enabledFl = false;
}
}
void LinesManager::checkZone() {
int mouseX = _vm->_events->getMouseX();
int mouseY = _vm->_events->getMouseY();
int oldMouseY = mouseY;
if (_vm->_globals->_cityMapEnabledFl
|| _vm->_events->_startPos.x >= mouseX
|| (mouseY = _vm->_graphicsMan->_scrollOffset + 54, mouseX >= mouseY)
|| (mouseY = oldMouseY - 1, mouseY < 0 || mouseY > 59)) {
if (_vm->_objectsMan->_visibleFl)
_vm->_objectsMan->_eraseVisibleCounter = 4;
_vm->_objectsMan->_visibleFl = false;
} else {
_vm->_objectsMan->_visibleFl = true;
}
if (_vm->_objectsMan->_forceZoneFl) {
_zoneSkipCount = 100;
2013-03-24 21:11:52 +00:00
_oldMouseZoneId = -1;
_oldMouseX = -200;
_oldMouseY = -220;
_vm->_objectsMan->_forceZoneFl = false;
}
_zoneSkipCount++;
if (_zoneSkipCount <= 1)
return;
if (_vm->_globals->_freezeCharacterFl || (_route == NULL) || _zoneSkipCount > 4) {
_zoneSkipCount = 0;
int zoneId;
2013-03-24 21:11:52 +00:00
if (_oldMouseX != mouseX || _oldMouseY != oldMouseY) {
zoneId = getMouseZone();
} else {
2013-03-24 21:11:52 +00:00
zoneId = _oldMouseZoneId;
}
2013-03-24 21:11:52 +00:00
if (_oldMouseZoneId != zoneId) {
_vm->_graphicsMan->setColorPercentage2(251, 100, 100, 100);
_vm->_events->_mouseCursorId = 4;
_vm->_events->changeMouseCursor(4);
if (_forceHideText) {
_vm->_fontMan->hideText(5);
_forceHideText = false;
return;
}
}
if (zoneId != -1) {
if (_zone[zoneId]._verbFl1 || _zone[zoneId]._verbFl2 ||
_zone[zoneId]._verbFl3 || _zone[zoneId]._verbFl4 ||
_zone[zoneId]._verbFl5 || _zone[zoneId]._verbFl6 ||
_zone[zoneId]._verbFl7 || _zone[zoneId]._verbFl8 ||
_zone[zoneId]._verbFl9 || _zone[zoneId]._verbFl10) {
2013-03-24 21:11:52 +00:00
if (_oldMouseZoneId != zoneId) {
_vm->_fontMan->initTextBuffers(5, _zone[zoneId]._messageId, _vm->_globals->_zoneFilename, 0, 430, 0, 0, 252);
_vm->_fontMan->showText(5);
_forceHideText = true;
}
_hotspotTextColor += 25;
if (_hotspotTextColor > 100)
_hotspotTextColor = 0;
_vm->_graphicsMan->setColorPercentage2(251, _hotspotTextColor, _hotspotTextColor, _hotspotTextColor);
if (_vm->_events->_mouseCursorId == 4) {
if (_zone[zoneId]._verbFl1 == 2) {
_vm->_events->changeMouseCursor(16);
_vm->_events->_mouseCursorId = 16;
_vm->_objectsMan->setVerb(16);
}
}
} else {
_vm->_graphicsMan->setColorPercentage2(251, 100, 100, 100);
_vm->_events->_mouseCursorId = 4;
_vm->_events->changeMouseCursor(4);
}
}
_vm->_objectsMan->_zoneNum = zoneId;
2013-03-24 21:11:52 +00:00
_oldMouseX = mouseX;
_oldMouseY = oldMouseY;
_oldMouseZoneId = zoneId;
if (_vm->_globals->_freezeCharacterFl && (_vm->_events->_mouseCursorId == 4)) {
if (zoneId != -1 && zoneId != 0)
_vm->_objectsMan->handleRightButton();
}
if ((_vm->_globals->_cityMapEnabledFl && zoneId == -1) || !zoneId) {
_vm->_objectsMan->setVerb(0);
_vm->_events->_mouseCursorId = 0;
_vm->_events->changeMouseCursor(0);
}
}
}
} // End of namespace Hopkins