scummvm/engines/kyra/engine/scene_v1.cpp
athrxx 1dfdcc7252 KYRA: cleanup dir
Reorganize all files in sub directories. The file placement isn't as intuitive as it might be for other engines, which is probably the reason why this hasn't been done before.
2019-03-06 20:48:15 +01:00

360 lines
8.6 KiB
C++

/* 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 "kyra/kyra_v1.h"
namespace Kyra {
int KyraEngine_v1::findWay(int x, int y, int toX, int toY, int *moveTable, int moveTableSize) {
x &= 0xFFFC; toX &= 0xFFFC;
y &= 0xFFFE; toY &= 0xFFFE;
x = (int16)x; y = (int16)y; toX = (int16)toX; toY = (int16)toY;
if (x == toY && y == toY) {
moveTable[0] = 8;
return 0;
}
int curX = x;
int curY = y;
int tempValue = 0;
int lastUsedEntry = 0;
int *pathTable1 = new int[0x7D0];
int *pathTable2 = new int[0x7D0];
assert(pathTable1 && pathTable2);
while (true) {
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
changePosTowardsFacing(curX, curY, newFacing);
if (curX == toX && curY == toY) {
if (!lineIsPassable(curX, curY))
break;
moveTable[lastUsedEntry++] = newFacing;
break;
}
if (lineIsPassable(curX, curY)) {
if (lastUsedEntry == moveTableSize) {
delete[] pathTable1;
delete[] pathTable2;
return 0x7D00;
}
// debug drawing
/*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
screen()->setPagePixel(0, curX, curY, 11);
screen()->updateScreen();
delayWithTicks(5);
}*/
moveTable[lastUsedEntry++] = newFacing;
x = curX;
y = curY;
continue;
}
int temp = 0;
while (true) {
newFacing = getFacingFromPointToPoint(curX, curY, toX, toY);
changePosTowardsFacing(curX, curY, newFacing);
// debug drawing
/*if (curX >= 0 && curY >= 0 && curX < 320 && curY < 200) {
screen()->setPagePixel(0, curX, curY, 8);
screen()->updateScreen();
delayWithTicks(5);
}*/
if (!lineIsPassable(curX, curY)) {
if (curX != toX || curY != toY)
continue;
}
if (curX == toX && curY == toY) {
if (!lineIsPassable(curX, curY)) {
tempValue = 0;
temp = 0;
break;
}
}
temp = findSubPath(x, y, curX, curY, pathTable1, 1, 0x7D0);
tempValue = findSubPath(x, y, curX, curY, pathTable2, 0, 0x7D0);
if (curX == toX && curY == toY) {
if (temp == 0x7D00 && tempValue == 0x7D00) {
delete[] pathTable1;
delete[] pathTable2;
return 0x7D00;
}
}
if (temp != 0x7D00 || tempValue != 0x7D00)
break;
}
if (temp < tempValue) {
if (lastUsedEntry + temp > moveTableSize) {
delete[] pathTable1;
delete[] pathTable2;
return 0x7D00;
}
memcpy(&moveTable[lastUsedEntry], pathTable1, temp * sizeof(int));
lastUsedEntry += temp;
} else {
if (lastUsedEntry + tempValue > moveTableSize) {
delete[] pathTable1;
delete[] pathTable2;
return 0x7D00;
}
memcpy(&moveTable[lastUsedEntry], pathTable2, tempValue * sizeof(int));
lastUsedEntry += tempValue;
}
x = curX;
y = curY;
if (curX == toX && curY == toY)
break;
}
delete[] pathTable1;
delete[] pathTable2;
moveTable[lastUsedEntry] = 8;
return lastUsedEntry;
}
int KyraEngine_v1::findSubPath(int x, int y, int toX, int toY, int *moveTable, int start, int end) {
// only used for debug specific code
//static uint16 unkTable[] = { 8, 5 };
static const int8 facingTable1[] = { 7, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 0 };
static const int8 facingTable2[] = { -1, 0, -1, 2, -1, 4, -1, 6, -1, 2, -1, 4, -1, 6, -1, 0 };
static const int8 facingTable3[] = { 2, 4, 4, 6, 6, 0, 0, 2, 6, 6, 0, 0, 2, 2, 4, 4 };
static const int8 addPosTableX[] = { -1, 0, -1, 4, -1, 0, -1, -4, -1, -4, -1, 0, -1, 4, -1, 0 };
static const int8 addPosTableY[] = { -1, 2, -1, 0, -1, -2, -1, 0, -1, 0, -1, 2, -1, 0, -1, -2 };
// debug specific
/*++unkTable[start];
while (screen()->getPalette(0)[unkTable[start]] != 0x0F) {
++unkTable[start];
}*/
int xpos1 = x, xpos2 = x;
int ypos1 = y, ypos2 = y;
int newFacing = getFacingFromPointToPoint(x, y, toX, toY);
int position = 0;
while (position != end) {
int newFacing2 = newFacing;
while (true) {
changePosTowardsFacing(xpos1, ypos1, facingTable1[start * 8 + newFacing2]);
if (!lineIsPassable(xpos1, ypos1)) {
if (facingTable1[start * 8 + newFacing2] == newFacing)
return 0x7D00;
newFacing2 = facingTable1[start * 8 + newFacing2];
xpos1 = x;
ypos1 = y;
continue;
}
newFacing = facingTable1[start * 8 + newFacing2];
break;
}
// debug drawing
/*if (xpos1 >= 0 && ypos1 >= 0 && xpos1 < 320 && ypos1 < 200) {
screen()->setPagePixel(0, xpos1, ypos1, unkTable[start]);
screen()->updateScreen();
delayWithTicks(5);
}*/
if (newFacing & 1) {
int temp = xpos1 + addPosTableX[newFacing + start * 8];
if (toX == temp) {
temp = ypos1 + addPosTableY[newFacing + start * 8];
if (toY == temp) {
moveTable[position++] = facingTable2[newFacing + start * 8];
return position;
}
}
}
moveTable[position++] = newFacing;
x = xpos1;
y = ypos1;
if (x == toX && y == toY)
return position;
if (xpos1 == xpos2 && ypos1 == ypos2)
break;
newFacing = facingTable3[start * 8 + newFacing];
}
return 0x7D00;
}
int KyraEngine_v1::getFacingFromPointToPoint(int x, int y, int toX, int toY) {
static const int facingTable[] = {
1, 0, 1, 2, 3, 4, 3, 2, 7, 0, 7, 6, 5, 4, 5, 6
};
int facingEntry = 0;
int ydiff = y - toY;
if (ydiff < 0) {
++facingEntry;
ydiff = -ydiff;
}
facingEntry <<= 1;
int xdiff = toX - x;
if (xdiff < 0) {
++facingEntry;
xdiff = -xdiff;
}
if (xdiff >= ydiff) {
int temp = ydiff;
ydiff = xdiff;
xdiff = temp;
facingEntry <<= 1;
} else {
facingEntry <<= 1;
facingEntry += 1;
}
int temp = (ydiff + 1) >> 1;
if (xdiff < temp) {
facingEntry <<= 1;
facingEntry += 1;
} else {
facingEntry <<= 1;
}
assert(facingEntry < ARRAYSIZE(facingTable));
return facingTable[facingEntry];
}
int KyraEngine_v1::getOppositeFacingDirection(int dir) {
switch (dir) {
case 0:
return 2;
case 1:
return 1;
case 3:
return 7;
case 4:
return 6;
case 5:
return 5;
case 6:
return 4;
case 7:
return 3;
default:
break;
}
return 0;
}
void KyraEngine_v1::changePosTowardsFacing(int &x, int &y, int facing) {
x += _addXPosTable[facing];
y += _addYPosTable[facing];
}
int KyraEngine_v1::getMoveTableSize(int *moveTable) {
int tableSize = 0;
if (moveTable[0] == 8)
return 0;
static const int facingTable[] = {
4, 5, 6, 7, 0, 1, 2, 3
};
static const int unkTable[] = {
-1, -1, 1, 2, -1, 6, 7, -1,
-1, -1, -1, -1, 2, -1, 0, -1,
1, -1, -1, -1, 3, 4, -1, 0,
2, -1, -1, -1, -1, -1, 4, -1,
-1, 2, 3, -1, -1, -1, 5, 6,
6, -1, 4, -1, -1, -1, -1, -1,
7, 0, -1, 4, 5, -1, -1, -1,
-1, -1, 0, -1, 6, -1, -1, -1
};
int *oldPosition = moveTable;
int *tempPosition = moveTable;
int *curPosition = moveTable + 1;
tableSize = 1;
while (*curPosition != 8) {
if (*oldPosition == facingTable[*curPosition]) {
tableSize -= 2;
*oldPosition = 9;
*curPosition = 9;
while (tempPosition != moveTable) {
--tempPosition;
if (*tempPosition != 9)
break;
}
if (tempPosition == moveTable && *tempPosition == 9) {
while (*tempPosition == 9)
++tempPosition;
if (*tempPosition == 8)
return 0;
}
oldPosition = tempPosition;
curPosition = oldPosition + 1;
while (*curPosition == 9)
++curPosition;
} else if (unkTable[*curPosition + *oldPosition * 8] != -1) {
--tableSize;
*oldPosition = unkTable[*curPosition + *oldPosition * 8];
*curPosition = 9;
if (tempPosition != oldPosition) {
curPosition = oldPosition;
oldPosition = tempPosition;
while (tempPosition != moveTable) {
--tempPosition;
if (*tempPosition != 9)
break;
}
} else {
do {
++curPosition;
} while (*curPosition == 9);
}
} else {
tempPosition = oldPosition;
oldPosition = curPosition;
++tableSize;
do {
++curPosition;
} while (*curPosition == 9);
}
}
return tableSize;
}
} // End of namespace Kyra