Initial commit
This commit is contained in:
470
engines/agos/rooms.cpp
Normal file
470
engines/agos/rooms.cpp
Normal file
@@ -0,0 +1,470 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "common/file.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "agos/agos.h"
|
||||
#include "agos/intern.h"
|
||||
|
||||
namespace AGOS {
|
||||
|
||||
uint16 AGOSEngine::getBackExit(int n) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
return 2;
|
||||
case 1:
|
||||
return 3;
|
||||
case 2:
|
||||
return 0;
|
||||
case 3:
|
||||
return 1;
|
||||
case 4:
|
||||
return 5;
|
||||
case 5:
|
||||
return 4;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16 AGOSEngine::getDoorState(Item *item, uint16 d) {
|
||||
uint16 mask = 3;
|
||||
uint16 n;
|
||||
|
||||
SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
|
||||
if (subRoom == nullptr)
|
||||
return 0;
|
||||
|
||||
d <<= 1;
|
||||
mask <<= d;
|
||||
n = subRoom->roomExitStates & mask;
|
||||
n >>= d;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
uint16 AGOSEngine::getExitOf(Item *item, uint16 d) {
|
||||
SubRoom *subRoom;
|
||||
uint16 x;
|
||||
uint16 y = 0;
|
||||
|
||||
subRoom = (SubRoom *)findChildOfType(item, kRoomType);
|
||||
if (subRoom == nullptr)
|
||||
return 0;
|
||||
x = d;
|
||||
while (x > y) {
|
||||
if (getDoorState(item, y) == 0)
|
||||
d--;
|
||||
y++;
|
||||
}
|
||||
return subRoom->roomExit[d];
|
||||
}
|
||||
|
||||
void AGOSEngine::changeDoorState(SubRoom *r, uint16 d, uint16 n) {
|
||||
uint16 mask=3;
|
||||
d <<= 1;
|
||||
mask <<= d;
|
||||
n <<= d;
|
||||
r->roomExitStates &= ~mask;
|
||||
r->roomExitStates |= n;
|
||||
}
|
||||
|
||||
void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) {
|
||||
Item *j;
|
||||
SubRoom *r, *r1;
|
||||
uint16 d1;
|
||||
uint16 y = 0;
|
||||
|
||||
r = (SubRoom *)findChildOfType(i, kRoomType);
|
||||
if (r == nullptr)
|
||||
return;
|
||||
d1 = d;
|
||||
while (d > y) {
|
||||
if (getDoorState(i, y) == 0)
|
||||
d1--;
|
||||
y++;
|
||||
}
|
||||
changeDoorState(r, d, n);
|
||||
|
||||
j = derefItem(r->roomExit[d1]);
|
||||
if (j == nullptr)
|
||||
return;
|
||||
r1 = (SubRoom *)findChildOfType(j, kRoomType);
|
||||
if (r1 == nullptr)
|
||||
return;
|
||||
d = getBackExit(d);
|
||||
d1 = d;
|
||||
y = 0;
|
||||
while (d > y) {
|
||||
if (getDoorState(j, y) == 0)
|
||||
d1--;
|
||||
y++;
|
||||
}
|
||||
/* Check are a complete exit pair */
|
||||
if (derefItem(r1->roomExit[d1]) != i)
|
||||
return;
|
||||
/* Change state of exit coming back */
|
||||
changeDoorState(r1, d, n);
|
||||
}
|
||||
|
||||
// Elvira 1 specific
|
||||
Item *AGOSEngine::getDoorOf(Item *i, uint16 d) {
|
||||
SubGenExit *g;
|
||||
Item *x;
|
||||
|
||||
g = (SubGenExit *)findChildOfType(i, kGenExitType);
|
||||
if (g == nullptr)
|
||||
return nullptr;
|
||||
|
||||
x = derefItem(g->dest[d]);
|
||||
if (x == nullptr)
|
||||
return nullptr;
|
||||
if (isRoom(x))
|
||||
return nullptr;
|
||||
return x;
|
||||
}
|
||||
|
||||
Item *AGOSEngine::getExitOf_e1(Item *item, uint16 d) {
|
||||
SubGenExit *g;
|
||||
Item *x;
|
||||
|
||||
g = (SubGenExit *)findChildOfType(item, kGenExitType);
|
||||
if (g == nullptr)
|
||||
return nullptr;
|
||||
|
||||
x = derefItem(g->dest[d]);
|
||||
if (x == nullptr)
|
||||
return nullptr;
|
||||
if (isRoom(x))
|
||||
return x;
|
||||
if (x->state != 0)
|
||||
return nullptr;
|
||||
return derefItem(x->parent);
|
||||
}
|
||||
|
||||
void AGOSEngine_Waxworks::moveDirn(Item *i, uint x) {
|
||||
Item *d;
|
||||
uint16 n;
|
||||
|
||||
if (i->parent == 0)
|
||||
return;
|
||||
|
||||
n = getExitOf(derefItem(i->parent), x);
|
||||
if (derefItem(n) == nullptr) {
|
||||
loadRoomItems(n);
|
||||
n = getExitOf(derefItem(i->parent), x);
|
||||
}
|
||||
|
||||
d = derefItem(n);
|
||||
if (d) {
|
||||
n = getDoorState(derefItem(i->parent), x);
|
||||
if (n == 1) {
|
||||
if (!canPlace(i, d))
|
||||
setItemParent(i, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine_Elvira2::moveDirn(Item *i, uint x) {
|
||||
SubSuperRoom *sr;
|
||||
Item *d, *p;
|
||||
uint16 a, n;
|
||||
|
||||
if (i->parent == 0)
|
||||
return;
|
||||
|
||||
p = derefItem(i->parent);
|
||||
if (findChildOfType(p, kSuperRoomType)) {
|
||||
n = getExitState(p, _superRoomNumber,x);
|
||||
if (n == 1) {
|
||||
sr = (SubSuperRoom *)findChildOfType(p, kSuperRoomType);
|
||||
switch (x) {
|
||||
case 0: a = -(sr->roomX); break;
|
||||
case 1: a = 1; break;
|
||||
case 2: a = sr->roomX; break;
|
||||
case 3: a = 0xFFFF; break;
|
||||
case 4: a = -(sr->roomX * sr->roomY); break;
|
||||
case 5: a = (sr->roomX * sr->roomY); break;
|
||||
default: return;
|
||||
}
|
||||
_superRoomNumber += a;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
n = getExitOf(derefItem(i->parent), x);
|
||||
|
||||
d = derefItem(n);
|
||||
if (d) {
|
||||
n = getDoorState(derefItem(i->parent), x);
|
||||
if (n == 1) {
|
||||
if (!canPlace(i, d))
|
||||
setItemParent(i, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AGOSEngine::moveDirn(Item *i, uint x) {
|
||||
Item *d, *p;
|
||||
|
||||
p = derefItem(i->parent);
|
||||
if (p == nullptr)
|
||||
return;
|
||||
|
||||
|
||||
d = getExitOf_e1(p, x);
|
||||
if (d) {
|
||||
if (canPlace(i, d))
|
||||
return;
|
||||
|
||||
setItemParent(i, d);
|
||||
return;
|
||||
}
|
||||
|
||||
d = getDoorOf(p, x);
|
||||
if (d) {
|
||||
const byte *name = getStringPtrByID(d->itemName, true);
|
||||
if (d->state == 1)
|
||||
showMessageFormat("%s is closed.\n", name);
|
||||
else
|
||||
showMessageFormat("%s is locked.\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
showMessageFormat("You can't go that way.\n");
|
||||
}
|
||||
|
||||
// Elvira 2 specific
|
||||
int AGOSEngine_Elvira2::changeExitStates(SubSuperRoom *sr, int n, int d, uint16 s) {
|
||||
int b, bd;
|
||||
uint16 mask;
|
||||
|
||||
switch (d) {
|
||||
case 0:
|
||||
b = -(sr->roomX);
|
||||
bd = 2;
|
||||
if (((n % (sr->roomX * sr->roomY)) / sr->roomX) == 0)
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
case 1:
|
||||
b = 1;
|
||||
bd = 3;
|
||||
if (((n % (sr->roomX * sr->roomY)) % sr->roomX) == 0)
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
case 2:
|
||||
b = sr->roomX;
|
||||
bd = 0;
|
||||
if (((n % (sr->roomX * sr->roomY)) / sr->roomX) == (sr->roomY - 1))
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
case 3:
|
||||
b = -1;
|
||||
bd = 1;
|
||||
if (((n % (sr->roomX * sr->roomY)) % sr->roomX) == 1)
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
case 4:
|
||||
b = -(sr->roomX * sr->roomY);
|
||||
bd = 5;
|
||||
if (n < (sr->roomX * sr->roomY))
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
case 5:
|
||||
b = sr->roomX * sr->roomY;
|
||||
bd = 4;
|
||||
if (n > (sr->roomX * sr->roomY * (sr->roomZ - 1)))
|
||||
return 0;
|
||||
else
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
n--;
|
||||
d <<= 1;
|
||||
mask = (3 << d);
|
||||
sr->roomExitStates[n] &= ~mask;
|
||||
sr->roomExitStates[n] |= (s << d);
|
||||
|
||||
bd <<= 1;
|
||||
mask = (3 << bd);
|
||||
sr->roomExitStates[n + b] &= ~mask;
|
||||
sr->roomExitStates[n + b] |= (s << bd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) {
|
||||
SubSuperRoom *sr;
|
||||
uint16 mask = 3;
|
||||
uint16 n;
|
||||
|
||||
sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
|
||||
if (sr == nullptr)
|
||||
return 0;
|
||||
|
||||
d <<= 1;
|
||||
mask <<= d;
|
||||
n = sr->roomExitStates[x - 1] & mask;
|
||||
n >>= d;
|
||||
return n;
|
||||
}
|
||||
|
||||
void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) {
|
||||
SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
|
||||
if (sr)
|
||||
changeExitStates(sr, n, d, s);
|
||||
}
|
||||
|
||||
void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) {
|
||||
uint16 mask = 3;
|
||||
|
||||
SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType);
|
||||
if (sr) {
|
||||
n--;
|
||||
d <<= 1;
|
||||
mask <<= d;
|
||||
s <<= d;
|
||||
sr->roomExitStates[n] &= ~mask;
|
||||
sr->roomExitStates[n] |= s;
|
||||
}
|
||||
}
|
||||
|
||||
// Waxworks specific
|
||||
bool AGOSEngine::loadRoomItems(uint16 room) {
|
||||
byte *p;
|
||||
uint i, minNum, maxNum;
|
||||
char filename[30];
|
||||
Common::File in;
|
||||
Item *item, *itemTmp;
|
||||
|
||||
if (_roomsList == nullptr)
|
||||
return 0;
|
||||
|
||||
_currentRoom = room;
|
||||
room -= 2;
|
||||
|
||||
if (_roomsListPtr) {
|
||||
p = _roomsListPtr;
|
||||
for (;;) {
|
||||
minNum = READ_BE_UINT16(p); p += 2;
|
||||
if (minNum == 0)
|
||||
break;
|
||||
|
||||
maxNum = READ_BE_UINT16(p); p += 2;
|
||||
|
||||
for (uint16 z = minNum; z <= maxNum; z++) {
|
||||
uint16 itemNum = z + 2;
|
||||
item = derefItem(itemNum);
|
||||
_itemArrayPtr[itemNum] = nullptr;
|
||||
|
||||
uint16 num = (itemNum - _itemArrayInited);
|
||||
_roomStates[num].state = item->state;
|
||||
_roomStates[num].classFlags = item->classFlags;
|
||||
SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
|
||||
_roomStates[num].roomExitStates = subRoom->roomExitStates;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p = _roomsList;
|
||||
while (*p) {
|
||||
for (i = 0; *p; p++, i++)
|
||||
filename[i] = *p;
|
||||
filename[i] = 0;
|
||||
p++;
|
||||
|
||||
_roomsListPtr = p;
|
||||
|
||||
for (;;) {
|
||||
minNum = READ_BE_UINT16(p); p += 2;
|
||||
if (minNum == 0)
|
||||
break;
|
||||
|
||||
maxNum = READ_BE_UINT16(p); p += 2;
|
||||
|
||||
if (room >= minNum && room <= maxNum) {
|
||||
in.open(filename);
|
||||
if (in.isOpen() == false) {
|
||||
error("loadRoomItems: Can't load rooms file '%s'", filename);
|
||||
}
|
||||
|
||||
while ((i = in.readUint16BE()) != 0) {
|
||||
uint16 itemNum = i + 2;
|
||||
|
||||
_itemArrayPtr[itemNum] = (Item *)allocateItem(sizeof(Item));
|
||||
readItemFromGamePc(&in, _itemArrayPtr[itemNum]);
|
||||
|
||||
item = derefItem(itemNum);
|
||||
item->parent = 0;
|
||||
item->child = 0;
|
||||
|
||||
for (uint16 z = _itemArrayInited; z; z--) {
|
||||
itemTmp = derefItem(z);
|
||||
|
||||
if (!itemTmp)
|
||||
continue;
|
||||
if (itemTmp->parent != itemNum)
|
||||
continue;
|
||||
if (item->child == 0) {
|
||||
item->child = z;
|
||||
continue;
|
||||
}
|
||||
uint16 child = item->child;
|
||||
while (itemTmp->next != 0) {
|
||||
if (itemTmp->next == child) {
|
||||
item->child = z;
|
||||
break;
|
||||
}
|
||||
|
||||
itemTmp = derefItem(itemTmp->next);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 num = (itemNum - _itemArrayInited);
|
||||
item->state = _roomStates[num].state;
|
||||
item->classFlags = _roomStates[num].classFlags;
|
||||
SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType);
|
||||
subRoom->roomExitStates = _roomStates[num].roomExitStates;
|
||||
|
||||
}
|
||||
in.close();
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug(1,"loadRoomItems: didn't find %d", room);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // End of namespace AGOS
|
||||
Reference in New Issue
Block a user