* Fix mismatched delete in create_image.cpp * Add shebangs to create_ms2_data.***.sh * Reduce scopes of some variables * Substitute bitwise and for logical and in GamaManager2::passageConstruction
1471 lines
41 KiB
C++
1471 lines
41 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 "common/system.h"
|
|
#include "graphics/cursorman.h"
|
|
#include "graphics/palette.h"
|
|
#include "gui/message.h"
|
|
|
|
#include "supernova/screen.h"
|
|
#include "supernova/supernova.h"
|
|
#include "supernova/supernova2/state.h"
|
|
#include "supernova/supernova2/stringid.h"
|
|
|
|
namespace Supernova {
|
|
|
|
bool GameManager2::serialize(Common::WriteStream *out) {
|
|
if (out->err())
|
|
return false;
|
|
|
|
// GameState
|
|
out->writeSint16LE(_state._money);
|
|
out->writeSint32LE(_state._startTime - g_system->getMillis());
|
|
out->writeByte(_state._addressKnown);
|
|
out->writeByte(_state._poleMagnet);
|
|
out->writeByte(_state._admission);
|
|
out->writeByte(_state._tipsy);
|
|
out->writeByte(_state._dark);
|
|
out->writeByte(_state._elevatorE);
|
|
out->writeByte(_state._elevatorNumber);
|
|
out->writeByte(_state._toMuseum);
|
|
out->writeSint16LE(_state._pyraE);
|
|
out->writeByte(_state._pyraS);
|
|
out->writeByte(_state._pyraZ);
|
|
out->writeByte(_state._alarmOn);
|
|
out->writeByte(_state._alarmCracked);
|
|
out->writeByte(_state._haste);
|
|
out->writeByte(_state._pressureCounter);
|
|
out->writeByte(_state._sirenOn);
|
|
out->writeSint16LE(_state._pyraDirection);
|
|
out->writeUint32LE(_state._eventTime - g_system->getMillis());
|
|
out->writeSint32LE(_state._eventCallback);
|
|
out->writeByte(_state._taxiPossibility);
|
|
for (int i = 0; i < 15; i++) {
|
|
out->writeSint16LE(_state._puzzleTab[i]);
|
|
}
|
|
|
|
// Inventory
|
|
out->writeSint32LE(_inventory.getSize());
|
|
out->writeSint32LE(_inventoryScroll);
|
|
for (int i = 0; i < _inventory.getSize(); ++i) {
|
|
Object *objectStateBegin = _rooms[_inventory.get(i)->_roomId]->getObject(0);
|
|
byte objectIndex = _inventory.get(i) - objectStateBegin;
|
|
out->writeSint32LE(_inventory.get(i)->_roomId);
|
|
out->writeSint32LE(objectIndex);
|
|
}
|
|
|
|
// Rooms
|
|
out->writeByte(_lastRoom->getId());
|
|
out->writeByte(_currentRoom->getId());
|
|
for (int i = 0; i < NUMROOMS2; ++i) {
|
|
_rooms[i]->serialize(out);
|
|
}
|
|
|
|
return !out->err();
|
|
}
|
|
|
|
|
|
bool GameManager2::deserialize(Common::ReadStream *in, int version) {
|
|
if (in->err())
|
|
return false;
|
|
|
|
// GameState
|
|
_state._money = in->readSint16LE();
|
|
_state._startTime = in->readSint32LE() + g_system->getMillis();
|
|
_state._addressKnown = in->readByte();
|
|
_state._poleMagnet = in->readByte();
|
|
_state._admission = in->readByte();
|
|
_state._tipsy = in->readByte();
|
|
_state._dark = in->readByte();
|
|
_state._elevatorE = in->readByte();
|
|
_state._elevatorNumber = in->readByte();
|
|
_state._toMuseum = in->readByte();
|
|
_state._pyraE = in->readSint16LE();
|
|
_state._pyraS = in->readByte();
|
|
_state._pyraZ = in->readByte();
|
|
_state._alarmOn = in->readByte();
|
|
_state._alarmCracked = in->readByte();
|
|
_state._haste = in->readByte();
|
|
_state._pressureCounter = in->readByte();
|
|
_state._sirenOn = in->readByte();
|
|
_state._pyraDirection = in->readSint16LE();
|
|
_state._eventTime = in->readUint32LE() + g_system->getMillis();
|
|
_state._eventCallback = (EventFunction)in->readSint32LE();
|
|
_state._taxiPossibility = in->readByte();
|
|
for (int i = 0; i < 15; i++)
|
|
_state._puzzleTab[i] = in->readSint16LE();
|
|
_vm->setGameString(kStringMoney, Common::String::format("%d Xa", _state._money));
|
|
|
|
_oldTime = g_system->getMillis();
|
|
|
|
// Inventory
|
|
int inventorySize = in->readSint32LE();
|
|
_inventoryScroll = in->readSint32LE();
|
|
_inventory.clear();
|
|
for (int i = 0; i < inventorySize; ++i) {
|
|
RoomId objectRoom = static_cast<RoomId>(in->readSint32LE());
|
|
int objectIndex = in->readSint32LE();
|
|
_inventory.add(*_rooms[objectRoom]->getObject(objectIndex));
|
|
}
|
|
|
|
// Rooms
|
|
RoomId lastRoomId = static_cast<RoomId>(in->readByte());
|
|
RoomId curRoomId = static_cast<RoomId>(in->readByte());
|
|
for (int i = 0; i < NUMROOMS2; ++i) {
|
|
_rooms[i]->deserialize(in, version);
|
|
}
|
|
_lastRoom = _rooms[lastRoomId];
|
|
changeRoom(curRoomId);
|
|
|
|
// Some additional variables
|
|
_state._previousRoom = _rooms[INTRO2];
|
|
_guiEnabled = true;
|
|
_animationEnabled = true;
|
|
|
|
return !in->err();
|
|
}
|
|
|
|
GameManager2::GameManager2(SupernovaEngine *vm, Sound *sound)
|
|
: GameManager(vm, sound) {
|
|
initRooms();
|
|
changeRoom(INTRO2);
|
|
initState();
|
|
}
|
|
|
|
GameManager2::~GameManager2() {
|
|
destroyRooms();
|
|
}
|
|
|
|
void GameManager2::destroyRooms() {
|
|
delete _rooms[INTRO2];
|
|
delete _rooms[AIRPORT];
|
|
delete _rooms[TAXISTAND];
|
|
delete _rooms[STREET];
|
|
delete _rooms[GAMES];
|
|
delete _rooms[CABIN2];
|
|
delete _rooms[KIOSK];
|
|
delete _rooms[CULTURE_PALACE];
|
|
delete _rooms[CHECKOUT];
|
|
delete _rooms[CITY1];
|
|
delete _rooms[CITY2];
|
|
delete _rooms[ELEVATOR2];
|
|
delete _rooms[APARTMENT];
|
|
delete _rooms[SHIP];
|
|
delete _rooms[PYRAMID];
|
|
delete _rooms[PYR_ENTRANCE];
|
|
delete _rooms[UPSTAIRS1];
|
|
delete _rooms[DOWNSTAIRS1];
|
|
delete _rooms[BOTTOM_RIGHT_DOOR];
|
|
delete _rooms[BOTTOM_LEFT_DOOR];
|
|
delete _rooms[UPSTAIRS2];
|
|
delete _rooms[DOWNSTAIRS2];
|
|
delete _rooms[UPPER_DOOR];
|
|
delete _rooms[PUZZLE_FRONT];
|
|
delete _rooms[PUZZLE_BEHIND];
|
|
delete _rooms[FORMULA1_F];
|
|
delete _rooms[FORMULA1_N];
|
|
delete _rooms[FORMULA2_F];
|
|
delete _rooms[FORMULA2_N];
|
|
delete _rooms[TOMATO_F];
|
|
delete _rooms[TOMATO_N];
|
|
delete _rooms[MONSTER_F];
|
|
delete _rooms[MONSTER1_N];
|
|
delete _rooms[MONSTER2_N];
|
|
delete _rooms[UPSTAIRS3];
|
|
delete _rooms[DOWNSTAIRS3];
|
|
delete _rooms[LCORRIDOR1];
|
|
delete _rooms[LCORRIDOR2];
|
|
delete _rooms[HOLE_ROOM];
|
|
delete _rooms[IN_HOLE];
|
|
delete _rooms[FLOORDOOR];
|
|
delete _rooms[FLOORDOOR_U];
|
|
delete _rooms[BST_DOOR];
|
|
delete _rooms[HALL2];
|
|
delete _rooms[COFFIN_ROOM];
|
|
delete _rooms[MASK];
|
|
delete _rooms[MUSEUM];
|
|
delete _rooms[MUS_ENTRANCE];
|
|
delete _rooms[MUS1];
|
|
delete _rooms[MUS2];
|
|
delete _rooms[MUS3];
|
|
delete _rooms[MUS4];
|
|
delete _rooms[MUS5];
|
|
delete _rooms[MUS6];
|
|
delete _rooms[MUS7];
|
|
delete _rooms[MUS8];
|
|
delete _rooms[MUS9];
|
|
delete _rooms[MUS10];
|
|
delete _rooms[MUS11];
|
|
delete _rooms[MUS_ROUND];
|
|
delete _rooms[MUS12];
|
|
delete _rooms[MUS13];
|
|
delete _rooms[MUS14];
|
|
delete _rooms[MUS15];
|
|
delete _rooms[MUS16];
|
|
delete _rooms[MUS17];
|
|
delete _rooms[MUS18];
|
|
delete _rooms[MUS19];
|
|
delete _rooms[MUS20];
|
|
delete _rooms[MUS21];
|
|
delete _rooms[MUS22];
|
|
}
|
|
|
|
void GameManager2::initState() {
|
|
GameManager::initState();
|
|
_mapOn = false;
|
|
_steps = false;
|
|
_cracking = false;
|
|
_alarmBefore = false;
|
|
RoomId startSecurityTab[10] = {MUS6, MUS7, MUS11, MUS10, MUS3, MUS2, MUS1, MUS8, MUS9, MUS5};
|
|
for (int i = 0; i < 10; i++)
|
|
_securityTab[i] = startSecurityTab[i];
|
|
|
|
_state._money = 20;
|
|
_state._startTime = 0;
|
|
_state._addressKnown = false;
|
|
_state._previousRoom = _currentRoom;
|
|
_lastRoom = _rooms[INTRO2];
|
|
_state._poleMagnet = false;
|
|
_state._admission = 0;
|
|
_state._tipsy = false;
|
|
_state._dark = false;
|
|
_state._elevatorE = 0;
|
|
_state._elevatorNumber = 0;
|
|
_state._toMuseum = false;
|
|
_state._pyraE = 0;
|
|
_state._pyraS = 4;
|
|
_state._pyraZ = 10;
|
|
_state._alarmOn = false;
|
|
_state._alarmCracked = false;
|
|
_state._haste = false;
|
|
_state._pressureCounter = 0;
|
|
_state._sirenOn = false;
|
|
_state._pyraDirection = 0;
|
|
_state._eventTime = kMaxTimerValue;
|
|
_state._eventCallback = kNoFn;
|
|
_state._taxiPossibility = 4;
|
|
int16 startPuzzleTab[15] = {12, 3, 14, 1, 11, 0, 2, 13, 9, 5, 4, 10, 7, 6, 8};
|
|
for (int i = 0; i < 15; i++)
|
|
_state._puzzleTab[i] = startPuzzleTab[i];
|
|
|
|
for (int i = 0 ; i < 6 ; ++i) {
|
|
_dials[i] = 1;
|
|
}
|
|
}
|
|
|
|
void GameManager2::initRooms() {
|
|
_rooms = new Room *[NUMROOMS2];
|
|
_rooms[INTRO2] = new Intro2(_vm, this);
|
|
_rooms[AIRPORT] = new Airport(_vm, this);
|
|
_rooms[TAXISTAND] = new TaxiStand(_vm, this);
|
|
_rooms[STREET] = new Street(_vm, this);
|
|
_rooms[GAMES] = new Games(_vm, this);
|
|
_rooms[CABIN2] = new Cabin2(_vm, this);
|
|
_rooms[KIOSK] = new Kiosk(_vm, this);
|
|
_rooms[CULTURE_PALACE] = new CulturePalace(_vm, this);
|
|
_rooms[CHECKOUT] = new Checkout(_vm, this);
|
|
_rooms[CITY1] = new City1(_vm, this);
|
|
_rooms[CITY2] = new City2(_vm, this);
|
|
_rooms[ELEVATOR2] = new Elevator2(_vm, this);
|
|
_rooms[APARTMENT] = new Apartment(_vm, this);
|
|
_rooms[SHIP] = new Ship(_vm, this);
|
|
_rooms[PYRAMID] = new Pyramid(_vm, this);
|
|
_rooms[PYR_ENTRANCE] = new PyrEntrance(_vm, this);
|
|
_rooms[UPSTAIRS1] = new Upstairs1(_vm, this);
|
|
_rooms[DOWNSTAIRS1] = new Downstairs1(_vm, this);
|
|
_rooms[BOTTOM_RIGHT_DOOR] = new BottomRightDoor(_vm, this);
|
|
_rooms[BOTTOM_LEFT_DOOR] = new BottomLeftDoor(_vm, this);
|
|
_rooms[UPSTAIRS2] = new Upstairs2(_vm, this);
|
|
_rooms[DOWNSTAIRS2] = new Downstairs2(_vm, this);
|
|
_rooms[UPPER_DOOR] = new UpperDoor(_vm, this);
|
|
_rooms[PUZZLE_FRONT] = new PuzzleFront(_vm, this);
|
|
_rooms[PUZZLE_BEHIND] = new PuzzleBehind(_vm, this);
|
|
_rooms[FORMULA1_F] = new Formula1F(_vm, this);
|
|
_rooms[FORMULA1_N] = new Formula1N(_vm, this);
|
|
_rooms[FORMULA2_F] = new Formula2F(_vm, this);
|
|
_rooms[FORMULA2_N] = new Formula2N(_vm, this);
|
|
_rooms[TOMATO_F] = new TomatoF(_vm, this);
|
|
_rooms[TOMATO_N] = new TomatoN(_vm, this);
|
|
_rooms[MONSTER_F] = new MonsterF(_vm, this);
|
|
_rooms[MONSTER1_N] = new Monster1N(_vm, this);
|
|
_rooms[MONSTER2_N] = new Monster2N(_vm, this);
|
|
_rooms[UPSTAIRS3] = new Upstairs3(_vm, this);
|
|
_rooms[DOWNSTAIRS3] = new Downstairs3(_vm, this);
|
|
_rooms[LCORRIDOR1] = new LCorridor1(_vm, this);
|
|
_rooms[LCORRIDOR2] = new LCorridor2(_vm, this);
|
|
_rooms[HOLE_ROOM] = new HoleRoom(_vm, this);
|
|
_rooms[IN_HOLE] = new InHole(_vm, this);
|
|
_rooms[FLOORDOOR] = new Floordoor(_vm, this);
|
|
_rooms[FLOORDOOR_U] = new FloordoorU(_vm, this);
|
|
_rooms[BST_DOOR] = new BstDoor(_vm, this);
|
|
_rooms[HALL2] = new Hall2(_vm, this);
|
|
_rooms[COFFIN_ROOM] = new CoffinRoom(_vm, this);
|
|
_rooms[MASK] = new Mask(_vm, this);
|
|
_rooms[MUSEUM] = new Museum(_vm, this);
|
|
_rooms[MUS_ENTRANCE] = new MusEntrance(_vm, this);
|
|
_rooms[MUS1] = new Mus1(_vm, this);
|
|
_rooms[MUS2] = new Mus2(_vm, this);
|
|
_rooms[MUS3] = new Mus3(_vm, this);
|
|
_rooms[MUS4] = new Mus4(_vm, this);
|
|
_rooms[MUS5] = new Mus5(_vm, this);
|
|
_rooms[MUS6] = new Mus6(_vm, this);
|
|
_rooms[MUS7] = new Mus7(_vm, this);
|
|
_rooms[MUS8] = new Mus8(_vm, this);
|
|
_rooms[MUS9] = new Mus9(_vm, this);
|
|
_rooms[MUS10] = new Mus10(_vm, this);
|
|
_rooms[MUS11] = new Mus11(_vm, this);
|
|
_rooms[MUS_ROUND] = new MusRound(_vm, this);
|
|
_rooms[MUS12] = new Mus12(_vm, this);
|
|
_rooms[MUS13] = new Mus13(_vm, this);
|
|
_rooms[MUS14] = new Mus14(_vm, this);
|
|
_rooms[MUS15] = new Mus15(_vm, this);
|
|
_rooms[MUS16] = new Mus16(_vm, this);
|
|
_rooms[MUS17] = new Mus17(_vm, this);
|
|
_rooms[MUS18] = new Mus18(_vm, this);
|
|
_rooms[MUS19] = new Mus19(_vm, this);
|
|
_rooms[MUS20] = new Mus20(_vm, this);
|
|
_rooms[MUS21] = new Mus21(_vm, this);
|
|
_rooms[MUS22] = new Mus22(_vm, this);
|
|
}
|
|
|
|
bool GameManager2::canSaveGameStateCurrently() {
|
|
return _animationEnabled && _guiEnabled && !_state._haste;
|
|
}
|
|
|
|
void GameManager2::updateEvents() {
|
|
handleTime();
|
|
if (_animationEnabled && !_vm->_screen->isMessageShown() && _animationTimer == 0)
|
|
_currentRoom->animation();
|
|
|
|
if (_state._eventCallback != kNoFn && g_system->getMillis() >= _state._eventTime) {
|
|
_vm->_allowLoadGame = false;
|
|
_vm->_allowSaveGame = false;
|
|
_state._eventTime = kMaxTimerValue;
|
|
EventFunction fn = _state._eventCallback;
|
|
_state._eventCallback = kNoFn;
|
|
switch (fn) {
|
|
case kNoFn:
|
|
break;
|
|
case kSoberFn:
|
|
sober();
|
|
break;
|
|
case kPyramidEndFn:
|
|
pyramidEnd();
|
|
break;
|
|
case kCaughtFn:
|
|
caught();
|
|
break;
|
|
default: //shouldn't happen
|
|
break;
|
|
}
|
|
_vm->_allowLoadGame = true;
|
|
_vm->_allowSaveGame = true;
|
|
return;
|
|
}
|
|
|
|
_mouseClicked = false;
|
|
_keyPressed = false;
|
|
Common::Event event;
|
|
while (g_system->getEventManager()->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_KEYDOWN:
|
|
_keyPressed = true;
|
|
processInput(event.kbd);
|
|
break;
|
|
case Common::EVENT_LBUTTONUP:
|
|
// fallthrough
|
|
case Common::EVENT_RBUTTONUP:
|
|
_mouseClicked = true;
|
|
// fallthrough
|
|
case Common::EVENT_MOUSEMOVE:
|
|
_mouseClickType = event.type;
|
|
_mouseX = event.mouse.x;
|
|
_mouseY = event.mouse.y;
|
|
if (_guiEnabled)
|
|
processInput();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameManager2::handleTime() {
|
|
if (_timerPaused)
|
|
return;
|
|
int32 newTime = g_system->getMillis();
|
|
int32 delta = newTime - _oldTime;
|
|
_time += delta;
|
|
|
|
if (_animationTimer > delta)
|
|
_animationTimer -= delta;
|
|
else
|
|
_animationTimer = 0;
|
|
|
|
_oldTime = newTime;
|
|
}
|
|
|
|
void GameManager2::drawMapExits() {
|
|
_vm->renderBox(281, 161, 39, 39, kColorWhite25);
|
|
|
|
if ((_currentRoom->getId() >= PYR_ENTRANCE && _currentRoom->getId() <= HOLE_ROOM) ||
|
|
(_currentRoom->getId() >= FLOORDOOR && _currentRoom->getId() <= BST_DOOR))
|
|
compass();
|
|
else {
|
|
for (int i = 0; i < 25; i++) {
|
|
int idx;
|
|
if ((idx = _exitList[i]) != -1) {
|
|
byte r = _currentRoom->getObject(idx)->_direction;
|
|
int x = 284 + 7 * (r % 5);
|
|
int y = 164 + 7 * (r / 5);
|
|
_vm->renderBox(x, y, 5, 5, kColorDarkRed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameManager2::takeMoney(int amount) {
|
|
_state._money += amount;
|
|
_vm->setGameString(kStringMoney, Common::String::format("%d Xa", _state._money));
|
|
}
|
|
|
|
bool GameManager2::genericInteract(Action verb, Object &obj1, Object &obj2) {
|
|
if (verb == ACTION_OPEN && obj1._id == WALLET) {
|
|
if (_rooms[TAXISTAND]->getObject(4)->_type & CARRIED)
|
|
_vm->renderMessage(kStringEmpty);
|
|
else {
|
|
_vm->renderMessage(kStringWalletOpen);
|
|
takeObject(*_rooms[TAXISTAND]->getObject(4));
|
|
takeObject(*_rooms[TAXISTAND]->getObject(5));
|
|
takeMoney(1);
|
|
_vm->playSound(kAudioSuccess2);
|
|
}
|
|
} else if (verb == ACTION_PRESS && obj1._id == TRANSMITTER) {
|
|
if (_currentRoom == _rooms[TAXISTAND]) {
|
|
if (_currentRoom->getObject(0)->_type != EXIT) {
|
|
_vm->renderImage(5);
|
|
wait(3);
|
|
_vm->renderImage(6);
|
|
_vm->playSound(kAudioTaxiOpen);
|
|
_currentRoom->getObject(0)->_type = EXIT;
|
|
drawMapExits();
|
|
}
|
|
} else if (_currentRoom == _rooms[STREET] ||
|
|
_currentRoom == _rooms[CULTURE_PALACE] ||
|
|
_currentRoom == _rooms[CITY1] ||
|
|
_currentRoom == _rooms[CITY2]) {
|
|
Common::String t = _vm->getGameString(kStringTaxiArrives);
|
|
_vm->renderMessage(t);
|
|
wait((t.size() + 20) * _vm->_textSpeed / 10, true);
|
|
_vm->removeMessage();
|
|
taxi();
|
|
} else
|
|
_vm->renderMessage(kStringNothingHappens);
|
|
} else if (verb == ACTION_USE && Object::combine(obj1, obj2, ROD, MAGNET)) {
|
|
Object *o1, *o2;
|
|
if (obj2._id == ROD) {
|
|
o1 = &obj2;
|
|
o2 = &obj1;
|
|
} else {
|
|
o1 = &obj1;
|
|
o2 = &obj2;
|
|
}
|
|
if (!(o1->_type & CARRIED))
|
|
return false;
|
|
|
|
if (!(o2->_type & CARRIED))
|
|
takeObject(*o2);
|
|
|
|
_vm->renderMessage(kStringAttachMagnet);
|
|
o1->_name = kStringPoleMagnet;
|
|
o1->_description = kStringCunning;
|
|
_inventory.remove(*o2);
|
|
_rooms[APARTMENT]->setSectionVisible(kMaxSection - 1, kShownTrue);
|
|
} else if (verb == ACTION_USE && Object::combine(obj1, obj2, CHIP, PLAYER)) {
|
|
Object *o1, *o2;
|
|
if (obj2._id == CHIP) {
|
|
o1 = &obj2;
|
|
o2 = &obj1;
|
|
} else {
|
|
o1 = &obj1;
|
|
o2 = &obj2;
|
|
}
|
|
if (!(o2->_type & CARRIED))
|
|
_vm->renderMessage(kStringMustBuyFirst);
|
|
else {
|
|
if (!(o1->_type & CARRIED))
|
|
{
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(2 + kSectionInvert);
|
|
_currentRoom->getObject(0)->_click = 255;
|
|
} else
|
|
_inventory.remove(*o1);
|
|
|
|
_vm->renderMessage(kStringInsertChip);
|
|
if (_state._admission)
|
|
_state._admission = 2;
|
|
else
|
|
_state._admission = 1;
|
|
}
|
|
} else if (verb == ACTION_USE && Object::combine(obj1, obj2, DISCMAN, PLAYER)) {
|
|
switch (_state._admission) {
|
|
case 1:
|
|
// fall through
|
|
case 2:
|
|
_vm->renderMessage(kStringTransferCD);
|
|
_state._admission = 2;
|
|
_vm->playSound(kAudioSuccess2);
|
|
break;
|
|
default:
|
|
_vm->renderMessage(kStringCDNotInserted);
|
|
}
|
|
} else if (verb == ACTION_OPEN && obj1._id == PLAYER) {
|
|
switch (_state._admission) {
|
|
case 1:
|
|
_state._admission = 0;
|
|
playerTakeOut();
|
|
break;
|
|
case 2:
|
|
_state._admission = 3;
|
|
playerTakeOut();
|
|
break;
|
|
default:
|
|
_vm->renderMessage(kStringChipNotInserted);
|
|
}
|
|
} else if (verb == ACTION_OPEN && obj1._id == DISCMAN) {
|
|
_vm->renderMessage(kStringWhatFor);
|
|
} else if (verb == ACTION_PRESS && obj1._id == DISCMAN) {
|
|
_vm->renderMessage(kStringMMCD);
|
|
playCD();
|
|
} else if (verb == ACTION_PRESS && obj1._id == PLAYER) {
|
|
switch (_state._admission) {
|
|
case 1:
|
|
_vm->renderMessage(kStringChipEmpty);
|
|
break;
|
|
case 2:
|
|
_vm->renderMessage(kStringListeningToCD);
|
|
playCD();
|
|
break;
|
|
default:
|
|
_vm->renderMessage(kStringNoChip);
|
|
}
|
|
} else if ((verb == ACTION_OPEN || verb == ACTION_USE) &&
|
|
obj1._id == BOTTLE && (obj1._type & CARRIED)) {
|
|
_vm->renderMessage(kStringTipsy);
|
|
_state._tipsy = true;
|
|
_state._eventTime = g_system->getMillis() + 60000;
|
|
_state._eventCallback = kSoberFn;
|
|
} else if (verb == ACTION_LOOK && obj1._id == MUSCARD) {
|
|
_vm->setCurrentImage(30);
|
|
_vm->renderImage(0);
|
|
//karte_an = true
|
|
wait(100000, true);
|
|
//karte_an = false
|
|
_vm->removeMessage();
|
|
_vm->renderRoom(*_currentRoom);
|
|
drawGUI();
|
|
} else
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void GameManager2::playCD() {
|
|
CursorMan.showMouse(false);
|
|
_vm->playSound(kMusicMadMonkeys);
|
|
Common::KeyCode k = Common::KEYCODE_INVALID;
|
|
while(_vm->_sound->isPlaying())
|
|
if (waitOnInput(1, k))
|
|
break;
|
|
_vm->_sound->stop();
|
|
_vm->removeMessage();
|
|
CursorMan.showMouse(true);
|
|
}
|
|
|
|
void GameManager2::handleInput() {
|
|
bool validCommand = genericInteract(_inputVerb, *_inputObject[0], *_inputObject[1]);
|
|
if (!validCommand)
|
|
validCommand = _currentRoom->interact(_inputVerb, *_inputObject[0], *_inputObject[1]);
|
|
if (!validCommand) {
|
|
switch (_inputVerb) {
|
|
case ACTION_LOOK:
|
|
_vm->renderMessage(_inputObject[0]->_description);
|
|
break;
|
|
|
|
case ACTION_WALK:
|
|
if (_inputObject[0]->hasProperty(CARRIED)) {
|
|
// You already carry this.
|
|
_vm->renderMessage(kStringGenericInteract1);
|
|
} else if (!_inputObject[0]->hasProperty(EXIT)) {
|
|
// You're already there.
|
|
_vm->renderMessage(kStringGenericInteract2);
|
|
} else if (_inputObject[0]->hasProperty(OPENABLE) && !_inputObject[0]->hasProperty(OPENED)) {
|
|
// This is closed
|
|
_vm->renderMessage(kStringGenericInteract3);
|
|
} else {
|
|
_lastRoom = _currentRoom;
|
|
changeRoom(_inputObject[0]->_exitRoom);
|
|
}
|
|
|
|
break;
|
|
|
|
case ACTION_TAKE:
|
|
if (_inputObject[0]->hasProperty(OPENED)) {
|
|
// You already have that
|
|
_vm->renderMessage(kStringGenericInteract4);
|
|
} else if (_inputObject[0]->hasProperty(UNNECESSARY)) {
|
|
// You do not need that.
|
|
_vm->renderMessage(kStringGenericInteract5);
|
|
} else if (!_inputObject[0]->hasProperty(TAKE)) {
|
|
// You can't take that.
|
|
_vm->renderMessage(kStringGenericInteract6);
|
|
} else
|
|
takeObject(*_inputObject[0]);
|
|
|
|
break;
|
|
|
|
case ACTION_OPEN:
|
|
if (!_inputObject[0]->hasProperty(OPENABLE)) {
|
|
// This can't be opened
|
|
_vm->renderMessage(kStringGenericInteract7);
|
|
} else if (_inputObject[0]->hasProperty(OPENED)) {
|
|
// This is already opened.
|
|
_vm->renderMessage(kStringGenericInteract8);
|
|
} else if (_inputObject[0]->hasProperty(CLOSED)) {
|
|
// This is locked.
|
|
_vm->renderMessage(kStringGenericInteract9);
|
|
} else {
|
|
_vm->renderImage(_inputObject[0]->_section);
|
|
_inputObject[0]->setProperty(OPENED);
|
|
byte i = _inputObject[0]->_click;
|
|
_inputObject[0]->_click = _inputObject[0]->_click2;
|
|
_inputObject[0]->_click2 = i;
|
|
_vm->_sound->play(kAudioTaxiOpen);
|
|
}
|
|
break;
|
|
|
|
case ACTION_CLOSE:
|
|
if (!_inputObject[0]->hasProperty(OPENABLE) ||
|
|
(_inputObject[0]->hasProperty(CLOSED) &&
|
|
_inputObject[0]->hasProperty(OPENED))) {
|
|
// This can't be closed.
|
|
_vm->renderMessage(kStringGenericInteract10);
|
|
} else if (!_inputObject[0]->hasProperty(OPENED)) {
|
|
// This is already closed.
|
|
_vm->renderMessage(kStringGenericInteract11);
|
|
} else {
|
|
_vm->renderImage(invertSection(_inputObject[0]->_section));
|
|
_inputObject[0]->disableProperty(OPENED);
|
|
byte i = _inputObject[0]->_click;
|
|
_inputObject[0]->_click = _inputObject[0]->_click2;
|
|
_inputObject[0]->_click2 = i;
|
|
_vm->_sound->play(kAudioElevator1);
|
|
}
|
|
break;
|
|
|
|
case ACTION_GIVE:
|
|
if (_inputObject[0]->hasProperty(CARRIED)) {
|
|
// Better keep it!
|
|
_vm->renderMessage(kStringGenericInteract12);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
// This is not possible.
|
|
_vm->renderMessage(kStringGenericInteract13);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameManager2::executeRoom() {
|
|
if (_currentRoom == _rooms[PUZZLE_FRONT])
|
|
puzzleConstruction();
|
|
if (_state._sirenOn && !_vm->_sound->isPlaying())
|
|
_vm->_sound->playSiren();
|
|
if (_processInput && !_vm->_screen->isMessageShown() && _guiEnabled) {
|
|
handleInput();
|
|
if (_dead) {
|
|
_dead = false;
|
|
return;
|
|
}
|
|
if (_mouseClicked) {
|
|
Common::Event event;
|
|
event.type = Common::EVENT_MOUSEMOVE;
|
|
event.mouse = Common::Point(0, 0);
|
|
_vm->getEventManager()->pushEvent(event);
|
|
event.type = Common::EVENT_MOUSEMOVE;
|
|
event.mouse = Common::Point(_mouseX, _mouseY);
|
|
_vm->getEventManager()->pushEvent(event);
|
|
}
|
|
|
|
resetInputState();
|
|
}
|
|
|
|
if (_guiEnabled) {
|
|
if (!_vm->_screen->isMessageShown()) {
|
|
g_system->fillScreen(kColorBlack);
|
|
_vm->renderRoom(*_currentRoom);
|
|
}
|
|
if (_currentRoom->getId() < MUSEUM)
|
|
drawMapExits();
|
|
else
|
|
drawClock();
|
|
if (_dead) {
|
|
_dead = false;
|
|
return;
|
|
}
|
|
drawInventory();
|
|
drawStatus();
|
|
drawCommandBox();
|
|
}
|
|
|
|
if (_vm->_screen->getViewportBrightness() == 0)
|
|
_vm->paletteFadeIn();
|
|
|
|
if (!_currentRoom->hasSeen() && _newRoom) {
|
|
_newRoom = false;
|
|
_currentRoom->onEntrance();
|
|
}
|
|
}
|
|
|
|
void GameManager2::leaveTaxi() {
|
|
_currentRoom = _state._previousRoom;
|
|
_vm->renderRoom(*_currentRoom);
|
|
_guiEnabled = true;
|
|
}
|
|
|
|
void GameManager2::taxiUnknownDestination() {
|
|
_vm->renderImage(invertSection(2));
|
|
_vm->renderImage(0);
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(4);
|
|
wait(_vm->_textSpeed * 3, true);
|
|
_vm->renderImage(invertSection(4));
|
|
_vm->renderImage(0);
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(2);
|
|
}
|
|
|
|
void GameManager2::taxiPayment(int price, int destination) {
|
|
static int answers[] = {
|
|
kStringPay,
|
|
kStringLeaveTaxi
|
|
};
|
|
if (dialog(2, _dials, answers, 0)) {
|
|
leaveTaxi();
|
|
} else if (_state._money < price) {
|
|
Common::String t = _vm->getGameString(kStringNotEnoughMoney);
|
|
_vm->renderMessage(t);
|
|
wait((t.size() + 20) * _vm->_textSpeed / 10, true);
|
|
_vm->removeMessage();
|
|
leaveTaxi();
|
|
} else {
|
|
takeMoney(-price);
|
|
_vm->renderImage(invertSection(5));
|
|
_vm->renderImage(invertSection(6));
|
|
_vm->renderImage(0);
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(3);
|
|
|
|
Common::String t = _vm->getGameString(kStringTaxiAccelerating);
|
|
_vm->renderMessage(t);
|
|
_vm->playSound(kAudioTaxiLeaving);
|
|
while(_vm->_sound->isPlaying())
|
|
wait(1);
|
|
wait((t.size() + 20) * _vm->_textSpeed / 10, true);
|
|
_vm->removeMessage();
|
|
|
|
_vm->paletteFadeOut();
|
|
_vm->_system->fillScreen(kColorBlack);
|
|
_vm->_screen->setViewportBrightness(255);
|
|
_vm->_screen->setGuiBrightness(255);
|
|
_vm->paletteBrightness();
|
|
|
|
Common::String t2 = _vm->getGameString(kString5MinutesLater);
|
|
_vm->renderMessage(t2);
|
|
_vm->playSound(kAudioTaxiArriving);
|
|
while(_vm->_sound->isPlaying())
|
|
wait(1);
|
|
wait((t2.size() + 20) * _vm->_textSpeed / 10, true);
|
|
_vm->removeMessage();
|
|
_vm->paletteFadeOut();
|
|
|
|
switch (destination) {
|
|
case 0:
|
|
changeRoom(TAXISTAND);
|
|
break;
|
|
case 1:
|
|
changeRoom(STREET);
|
|
break;
|
|
case 2:
|
|
changeRoom(CULTURE_PALACE);
|
|
break;
|
|
case 10:
|
|
changeRoom(CITY1);
|
|
break;
|
|
case 11:
|
|
changeRoom(CITY2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameManager2::taxi() {
|
|
_vm->_allowSaveGame = false;
|
|
static int dest[] = {
|
|
kStringAirport,
|
|
kStringDowntown,
|
|
kStringCulturePalace,
|
|
kStringEarth,
|
|
kStringPrivateApartment,
|
|
kStringLeaveTaxi
|
|
};
|
|
Common::String input;
|
|
int possibility = _state._taxiPossibility;
|
|
|
|
_state._previousRoom = _currentRoom;
|
|
_currentRoom = _rooms[INTRO2];
|
|
_vm->setCurrentImage(4);
|
|
_vm->renderImage(0);
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(2);
|
|
|
|
if (_state._previousRoom == _rooms[TAXISTAND]) possibility += 1;
|
|
else if (_state._previousRoom == _rooms[STREET]) possibility += 2;
|
|
else if (_state._previousRoom == _rooms[CULTURE_PALACE]) possibility += 4;
|
|
int answer;
|
|
do {
|
|
_currentRoom->removeSentenceByMask(possibility, 1);
|
|
switch (answer = dialog(6, _dials, dest, 1)) {
|
|
case 3:
|
|
_state._taxiPossibility += 8;
|
|
possibility += 8;
|
|
taxiUnknownDestination();
|
|
break;
|
|
case 5:
|
|
leaveTaxi();
|
|
break;
|
|
case 4:
|
|
_vm->renderMessage(kStringAddress);
|
|
do {
|
|
edit(input, 101, 70, 18);
|
|
} while ((_key.keycode != Common::KEYCODE_RETURN) && (_key.keycode != Common::KEYCODE_ESCAPE) && !_vm->shouldQuit());
|
|
|
|
_vm->removeMessage();
|
|
if (_key.keycode == Common::KEYCODE_ESCAPE) {
|
|
leaveTaxi();
|
|
break;
|
|
}
|
|
input.toUppercase();
|
|
if (input == "115AY2,96A" || input == "115AY2,96B")
|
|
answer = 10;
|
|
else if (input == "341,105A" || input == "341,105B") {
|
|
if (_state._addressKnown)
|
|
answer = 11;
|
|
else {
|
|
Common::String t = _vm->getGameString(kStringCheater);
|
|
_vm->renderMessage(t);
|
|
wait((t.size() + 20) * _vm->_textSpeed / 10, true);
|
|
_vm->removeMessage();
|
|
|
|
leaveTaxi();
|
|
break;
|
|
}
|
|
} else {
|
|
answer = 3;
|
|
input = "";
|
|
taxiUnknownDestination();
|
|
break;
|
|
}
|
|
_vm->renderImage(invertSection(2));
|
|
_vm->renderImage(0);
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(6);
|
|
_vm->playSound(kAudioSuccess2);
|
|
taxiPayment(14, answer);
|
|
break;
|
|
default:
|
|
_vm->renderImage(invertSection(2));
|
|
_vm->renderImage(0);
|
|
_vm->renderImage(1);
|
|
_vm->renderImage(5);
|
|
taxiPayment(8, answer);
|
|
break;
|
|
}
|
|
_rooms[INTRO2]->addAllSentences(1);
|
|
} while(answer == 3 && !_vm->shouldQuit());
|
|
_vm->_allowSaveGame = true;
|
|
|
|
}
|
|
|
|
void GameManager2::playerTakeOut() {
|
|
_vm->renderMessage(kStringRemoveChip);
|
|
Object *o = _rooms[APARTMENT]->getObject(0);
|
|
o->_section = 0;
|
|
takeObject(*o);
|
|
}
|
|
|
|
void GameManager2::sober() {
|
|
_state._tipsy = false;
|
|
}
|
|
|
|
bool GameManager2::talk(int mod1, int mod2, int rest, MessagePosition pos, int id) {
|
|
Common::KeyCode key = Common::KEYCODE_INVALID;
|
|
const Common::String& text = _vm->getGameString(id);
|
|
|
|
_vm->renderMessage(text, pos);
|
|
int animation_count = (text.size() + 20) * (10 - rest) * _vm->_textSpeed / 400;
|
|
_restTime = (text.size() + 20) * rest * _vm->_textSpeed / 400;
|
|
|
|
while (animation_count) {
|
|
if (mod1)
|
|
_vm->renderImage(mod1);
|
|
|
|
if (waitOnInput(2, key)) {
|
|
_vm->removeMessage();
|
|
return key != Common::KEYCODE_ESCAPE && !_vm->shouldQuit();
|
|
}
|
|
if (mod2)
|
|
_vm->renderImage(mod2);
|
|
|
|
if (waitOnInput(2, key)) {
|
|
_vm->removeMessage();
|
|
return key != Common::KEYCODE_ESCAPE && !_vm->shouldQuit();
|
|
}
|
|
animation_count--;
|
|
}
|
|
if (_restTime == 0)
|
|
_vm->removeMessage();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GameManager2::talkRest(int mod1, int mod2, int rest) {
|
|
Common::KeyCode key = Common::KEYCODE_INVALID;
|
|
while (rest) {
|
|
_vm->renderImage(mod1);
|
|
if (waitOnInput(2, key)) {
|
|
_vm->removeMessage();
|
|
return key != Common::KEYCODE_ESCAPE && !_vm->shouldQuit();
|
|
}
|
|
_vm->renderImage(mod2);
|
|
if (waitOnInput(2, key)) {
|
|
_vm->removeMessage();
|
|
return key != Common::KEYCODE_ESCAPE && !_vm->shouldQuit();
|
|
}
|
|
rest--;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void GameManager2::pyramidEnd() {
|
|
_vm->renderMessage(kStringPyramid0);
|
|
wait(_messageDuration, true);
|
|
_vm->removeMessage();
|
|
_vm->paletteFadeOut();
|
|
_vm->loadGame(kSleepAutosaveSlot);
|
|
changeRoom(CABIN2);
|
|
drawGUI();
|
|
_rooms[CABIN2]->setSectionVisible(kMaxSection - 1, kShownFalse);
|
|
_rooms[CABIN2]->setSectionVisible(kMaxSection - 2, kShownTrue);
|
|
_rooms[CABIN2]->setSectionVisible(1, kShownFalse);
|
|
}
|
|
|
|
void GameManager2::passageConstruction() {
|
|
static ConstructionEntry constructionTab[9] = {
|
|
{0, 4, 10, 2, 13},
|
|
{0, 4, 9, 2, 14},
|
|
{0, 4, 8, 3, 2},
|
|
{1, 4, 7, 3, 1},
|
|
{1, 5, 7, 3, 3},
|
|
{1, 6, 7, 3, 5},
|
|
{1, 4, 7, 1, 2},
|
|
{1, 2, 5, 1, 1},
|
|
{0, 4, 9, 2, 20}
|
|
};
|
|
|
|
changeRoom(PYR_ENTRANCE);
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(1,
|
|
!wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 0, -1));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(2,
|
|
!wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 0, 1));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(7,
|
|
wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 1, 0));
|
|
|
|
if (!_rooms[PYR_ENTRANCE]->isSectionVisible(7)) {
|
|
_rooms[PYR_ENTRANCE]->getObject(3)->_type = EXIT;
|
|
_rooms[PYR_ENTRANCE]->getObject(3)->_click = 0;
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(3,
|
|
!wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 1, -1));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(4,
|
|
!wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 1, 1));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(8,
|
|
wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 2, 0));
|
|
if (!_rooms[PYR_ENTRANCE]->isSectionVisible(8)) {
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(5,
|
|
!wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 2, -1));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(6,
|
|
!wall(_state._pyraS, _state._pyraZ, _state._pyraDirection, 2, 1));
|
|
} else {
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(5, kShownFalse);
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(6, kShownFalse);
|
|
}
|
|
} else {
|
|
_rooms[PYR_ENTRANCE]->getObject(3)->_type = NULLTYPE;
|
|
_rooms[PYR_ENTRANCE]->getObject(3)->_click = 255;
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(3, kShownFalse);
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(4, kShownFalse);
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(8, kShownFalse);
|
|
}
|
|
for (int i = 0; i < 9; i++) {
|
|
bool b = (_state._pyraE == constructionTab[i]._e &&
|
|
_state._pyraS == constructionTab[i]._s &&
|
|
_state._pyraZ == constructionTab[i]._z &&
|
|
_state._pyraDirection == constructionTab[i]._r);
|
|
if (constructionTab[i]._a > 12)
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(constructionTab[i]._a, b);
|
|
else if (b)
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(constructionTab[i]._a, kShownTrue);
|
|
}
|
|
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(18, kShownFalse);
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(19, kShownFalse);
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(21, kShownFalse);
|
|
_rooms[PYR_ENTRANCE]->getObject(0)->_click = 255;
|
|
|
|
if (_state._pyraE == 0 && _state._pyraS == 4 && _state._pyraZ == 10) {
|
|
switch (_state._pyraDirection) {
|
|
case 0:
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(19, kShownTrue);
|
|
_rooms[PYR_ENTRANCE]->getObject(0)->_click = 8;
|
|
break;
|
|
case 2:
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(18, kShownTrue);
|
|
_rooms[PYR_ENTRANCE]->getObject(0)->_click = 7;
|
|
break;
|
|
case 1:
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(21, kShownTrue);
|
|
_rooms[PYR_ENTRANCE]->getObject(0)->_click = 9;
|
|
break;
|
|
}
|
|
}
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(9,
|
|
_rooms[PYR_ENTRANCE]->isSectionVisible(7) &&
|
|
!_rooms[PYR_ENTRANCE]->isSectionVisible(1));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(10,
|
|
_rooms[PYR_ENTRANCE]->isSectionVisible(7) &&
|
|
!_rooms[PYR_ENTRANCE]->isSectionVisible(2));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(11,
|
|
_rooms[PYR_ENTRANCE]->isSectionVisible(8) &&
|
|
!_rooms[PYR_ENTRANCE]->isSectionVisible(3));
|
|
_rooms[PYR_ENTRANCE]->setSectionVisible(12,
|
|
_rooms[PYR_ENTRANCE]->isSectionVisible(8) &&
|
|
!_rooms[PYR_ENTRANCE]->isSectionVisible(4));
|
|
}
|
|
|
|
byte GameManager2::wall(int s, int z, int direction, int stepsForward, int stepsRight) {
|
|
static char vertical[2][12][11] = {
|
|
{
|
|
{0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,1,0,0,0,0,0,0,0,0,0},
|
|
{1,0,1,0,0,0,0,0,0,0,0},
|
|
{1,0,1,0,1,0,0,0,0,0,0},
|
|
{0,1,0,0,1,0,0,1,0,0,0},
|
|
{0,0,1,0,0,0,1,0,1,0,0},
|
|
{0,0,0,1,1,0,1,0,0,0,0},
|
|
{0,0,0,1,1,0,0,1,0,0,0},
|
|
{0,0,0,0,0,1,0,1,0,0,0},
|
|
{0,0,0,0,0,1,1,0,1,0,0},
|
|
{0,0,0,0,1,0,0,0,1,0,0},
|
|
{0,0,0,0,1,0,0,0,0,0,0}
|
|
},
|
|
{
|
|
{0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,0,0,0,1,0,0,0,0,0,0},
|
|
{0,0,0,0,1,0,0,0,0,0,0},
|
|
{0,1,0,1,0,0,0,0,0,0,0},
|
|
{0,1,0,1,1,0,0,0,0,0,0},
|
|
{1,0,0,0,1,0,0,0,0,0,0},
|
|
{0,0,0,0,0,1,0,0,1,0,0},
|
|
{0,0,0,0,0,0,1,1,0,0,1},
|
|
{0,0,0,0,0,1,0,1,0,0,1},
|
|
{0,0,0,0,1,0,1,0,1,1,0},
|
|
{0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,0,0,0,0,0,0,0,0,0,0}
|
|
}
|
|
};
|
|
|
|
static char horizontal[2][11][12] = {
|
|
{
|
|
{0,1,1,0,0,0,0,0,0,0,0,0},
|
|
{0,0,1,0,0,0,0,0,0,0,0,0},
|
|
{0,1,0,1,1,0,0,0,0,0,0,0},
|
|
{0,1,1,0,0,0,0,0,0,0,0,0},
|
|
{0,0,1,0,0,1,1,0,1,0,0,0},
|
|
{0,0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,0,0,0,0,0,0,1,0,0,0,0},
|
|
{0,0,0,0,1,1,0,0,0,0,0,0},
|
|
{0,0,0,0,0,1,0,1,1,0,0,0},
|
|
{0,0,0,0,0,1,1,0,0,0,0,0},
|
|
{0,0,0,0,0,0,0,0,0,0,0,0}
|
|
},
|
|
{
|
|
{0,0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,1,0,0,1,0,0,0,0,0,0,0},
|
|
{0,0,0,0,1,0,0,0,0,0,0,0},
|
|
{0,0,1,1,0,0,0,0,0,0,0,0},
|
|
{0,1,1,0,0,1,0,0,0,0,0,0},
|
|
{0,0,0,0,0,0,1,0,1,0,0,0},
|
|
{0,0,0,0,0,1,1,0,0,0,0,0},
|
|
{0,0,0,0,0,1,0,1,1,0,1,0},
|
|
{0,0,0,0,0,1,1,0,0,1,0,0},
|
|
{0,0,0,0,0,0,0,0,0,0,0,0}
|
|
}
|
|
};
|
|
if (stepsRight) {
|
|
int newR;
|
|
if (stepsRight > 0)
|
|
newR = (direction + 1) & 3;
|
|
else {
|
|
newR = (direction - 1) & 3;
|
|
stepsRight = -stepsRight;
|
|
}
|
|
switch (direction) {
|
|
case 0:
|
|
return wall(s, z - stepsForward, newR, stepsRight, 0);
|
|
case 2:
|
|
return wall(s, z + stepsForward, newR, stepsRight, 0);
|
|
case 1:
|
|
return wall(s + stepsForward, z, newR, stepsRight, 0);
|
|
case 3:
|
|
return wall(s - stepsForward, z, newR, stepsRight, 0);
|
|
}
|
|
}
|
|
switch (direction) {
|
|
case 0:
|
|
return vertical [_state._pyraE][z + 1 - stepsForward][s] == 0;
|
|
case 2:
|
|
return vertical [_state._pyraE][z + stepsForward][s] == 0;
|
|
case 1:
|
|
return horizontal[_state._pyraE][z][s + stepsForward] == 0;
|
|
case 3:
|
|
return horizontal[_state._pyraE][z][s + 1 - stepsForward] == 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool GameManager2::move(Action verb, Object &obj) {
|
|
if (verb == ACTION_WALK && obj._id == CORRIDOR) {
|
|
switch (_state._pyraDirection) {
|
|
case 0:
|
|
_state._pyraZ--;
|
|
break;
|
|
case 1:
|
|
_state._pyraS++;
|
|
break;
|
|
case 2:
|
|
_state._pyraZ++;
|
|
break;
|
|
case 3:
|
|
_state._pyraS--;
|
|
break;
|
|
}
|
|
} else if (verb == ACTION_WALK && obj._id == G_RIGHT) {
|
|
_state._pyraDirection++;
|
|
_state._pyraDirection &= 3;
|
|
} else if (verb == ACTION_WALK && obj._id == G_LEFT) {
|
|
_state._pyraDirection--;
|
|
_state._pyraDirection &= 3;
|
|
} else
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
void GameManager2::compass() {
|
|
static int dirs[7] = {
|
|
kStringDirection1,
|
|
kStringDirection2,
|
|
kStringDirection3,
|
|
kStringDirection4,
|
|
kStringDirection1,
|
|
kStringDirection2,
|
|
kStringDirection3
|
|
};
|
|
_vm->renderBox(281, 161, 39, 39, kColorWhite63);
|
|
_vm->renderBox(295, 180, 13, 3, kColorWhite44);
|
|
_vm->renderBox(300, 175, 3, 13, kColorWhite44);
|
|
_vm->renderText(dirs[_state._pyraDirection ], 299, 163, kColorBlack);
|
|
_vm->renderText(dirs[_state._pyraDirection + 1], 312, 179, kColorBlack);
|
|
_vm->renderText(dirs[_state._pyraDirection + 2], 299, 191, kColorBlack);
|
|
_vm->renderText(dirs[_state._pyraDirection + 3], 283, 179, kColorBlack);
|
|
}
|
|
|
|
void GameManager2::puzzleConstruction() {
|
|
_vm->setCurrentImage(12);
|
|
MSNImage *image = _vm->_screen->getCurrentImage();
|
|
for (int i = 0; i < 16; i ++) {
|
|
_puzzleField[i] = 255;
|
|
}
|
|
for (int i = 0; i < 15; i++) {
|
|
image->_section[i + 1].x1 = 95 + (_state._puzzleTab[i] % 4) * 33;
|
|
image->_section[i + 1].x2 = image->_section[i + 1].x1 + 31;
|
|
image->_section[i + 1].y1 = 24 + (_state._puzzleTab[i] / 4) * 25;
|
|
image->_section[i + 1].y2 = image->_section[i + 1].y1 + 23;
|
|
|
|
_puzzleField[_state._puzzleTab[i]] = i;
|
|
}
|
|
}
|
|
|
|
void GameManager2::alarm() {
|
|
_vm->_sound->playSiren();
|
|
_state._sirenOn = true;
|
|
if (_vm->_screen->isMessageShown())
|
|
_vm->removeMessage();
|
|
_vm->renderMessage(kStringMuseum7);
|
|
_state._eventTime = g_system->getMillis() + 16200;
|
|
_state._eventCallback = kCaughtFn;
|
|
_state._alarmOn = true;
|
|
}
|
|
|
|
void GameManager2::caught() {
|
|
if (_vm->_screen->isMessageShown())
|
|
_vm->removeMessage();
|
|
if (_currentRoom->getId() < MUS1) {
|
|
} else if (_currentRoom->getId() <= MUS2) {
|
|
_vm->renderImage( 8);
|
|
_vm->renderImage(18);
|
|
} else if (_currentRoom->getId() == MUS3) {
|
|
_vm->renderImage(12);
|
|
_vm->renderImage(30);
|
|
} else if (_currentRoom->getId() == MUS4) {
|
|
_vm->renderImage( 8);
|
|
_vm->renderImage(18);
|
|
} else if (_currentRoom->getId() == MUS5) {
|
|
_vm->renderImage( 9);
|
|
_vm->renderImage(29);
|
|
} else if (_currentRoom->getId() <= MUS7) {
|
|
_vm->renderImage( 7);
|
|
_vm->renderImage(17);
|
|
} else if (_currentRoom->getId() <= MUS9) {
|
|
_vm->renderImage( 1);
|
|
_vm->renderImage( 7);
|
|
} else if (_currentRoom->getId() <= MUS11) {
|
|
_vm->renderImage( 2);
|
|
_vm->renderImage( 8);
|
|
}
|
|
caught2();
|
|
}
|
|
|
|
void GameManager2::caught2() {
|
|
_vm->renderMessage(kStringMuseum8);
|
|
_vm->playSound(kAudioCaught);
|
|
wait(_messageDuration, true);
|
|
_vm->removeMessage();
|
|
_state._sirenOn = false;
|
|
_mapOn = false;
|
|
_state._haste = false;
|
|
dead(kStringMuseum9);
|
|
}
|
|
|
|
void GameManager2::drawClock() {
|
|
int time = (g_system->getMillis() - _state._startTime) / 600;
|
|
int second = time % 100;
|
|
Room *r;
|
|
if (!_mapOn) {
|
|
_vm->renderBox(281, 161, 39, 39, kColorWhite25);
|
|
char s[9] = "00";
|
|
s[1] = time % 10 + 48;
|
|
time /= 10;
|
|
s[0] = time % 10 + 48;
|
|
time /= 10;
|
|
_vm->renderText(s, 293, 180, kColorWhite99);
|
|
strcpy(s, " 0:00");
|
|
s[4] = time % 10 + 48;
|
|
time /= 10;
|
|
s[3] = time % 10 + 48;
|
|
time /= 10;
|
|
s[1] = time % 10 + 48;
|
|
time /= 10;
|
|
if (time)
|
|
s[0] = time % 10 + 48;
|
|
_vm->renderText(s, 285, 170, kColorWhite99);
|
|
}
|
|
if ((r = _rooms[_securityTab[second / 10]]) == _currentRoom) {
|
|
//arrow();
|
|
_state._alarmCracked = false;
|
|
caught();
|
|
return;
|
|
}
|
|
for (int i = 0; i < 3; i++) {
|
|
Object *o = r->getObject(i);
|
|
if ((o->_id == DOOR || o->_id == ENCRYPTED_DOOR || o->_id == SMALL_DOOR) &&
|
|
(o->_type & OPENED) && ! _state._alarmOn)
|
|
alarm();
|
|
}
|
|
if (!_state._alarmOn && _currentRoom == _rooms[MUS4] &&
|
|
second >= 21 && second <= 40)
|
|
alarm();
|
|
if (_currentRoom == _rooms[MUS_ENTRANCE] && second >= 22 && second <= 29) {
|
|
if (!_steps && !_state._alarmCracked) {
|
|
_steps = true;
|
|
_vm->renderMessage(kStringMuseum6);
|
|
}
|
|
} else _steps = false;
|
|
}
|
|
|
|
void GameManager2::crack(int time) {
|
|
_alarmBefore = _state._alarmOn;
|
|
_cracking = true;
|
|
_vm->_screen->changeCursor(ResourceManager::kCursorWait);
|
|
int t = 0;
|
|
int zv = 0;
|
|
do {
|
|
int z;
|
|
do {
|
|
wait(1);
|
|
} while ((z = (g_system->getMillis() - _state._startTime) / 600) == zv);
|
|
zv = z;
|
|
drawClock();
|
|
t++;
|
|
} while (t < time && _state._alarmOn == _alarmBefore && !_dead);
|
|
_cracking = false;
|
|
_vm->_screen->changeCursor(ResourceManager::kCursorNormal);
|
|
if (_state._alarmOn == _alarmBefore)
|
|
_vm->removeMessage();
|
|
}
|
|
|
|
bool GameManager2::crackDoor(int time) {
|
|
_vm->renderMessage(kStringMuseum15);
|
|
crack(time);
|
|
if (_dead)
|
|
return false;
|
|
if (_state._alarmOn != _alarmBefore) {
|
|
wait(_messageDuration, true);
|
|
_vm->removeMessage();
|
|
_vm->renderMessage(kStringMuseum16);
|
|
}
|
|
return !_state._alarmOn;
|
|
}
|
|
|
|
void GameManager2::museumDoorInteract(Action verb, Object &obj1, Object &obj2) {
|
|
static struct {
|
|
int _r1;
|
|
int _o1;
|
|
int _r2;
|
|
int _o2;
|
|
} doorTab[11] = {
|
|
{MUS1, 0, MUS2, 0},
|
|
{MUS2, 1, MUS3, 0},
|
|
{MUS3, 1, MUS10, 0},
|
|
{MUS10, 1, MUS11, 0},
|
|
{MUS11, 1, MUS7, 1},
|
|
{MUS7, 0, MUS6, 1},
|
|
{MUS6, 0, MUS5, 1},
|
|
{MUS5, 0, MUS4, 0},
|
|
{MUS5, 2, MUS9, 1},
|
|
{MUS9, 0, MUS8, 1},
|
|
{MUS8, 0, MUS1, 1}
|
|
};
|
|
Room *r;
|
|
if (verb == ACTION_OPEN && obj1._id == DOOR) {
|
|
for (int i = 0; i < 11; i++) {
|
|
if ((_currentRoom == _rooms[doorTab[i]._r1]) &&
|
|
&obj1 == _currentRoom->getObject(doorTab[i]._o1)) {
|
|
r = _rooms[doorTab[i]._r2];
|
|
r->getObject(doorTab[i]._o2)->_type |= OPENED;
|
|
r->setSectionVisible(r->getObject(doorTab[i]._o2)->_section, kShownTrue);
|
|
} else if ((_currentRoom == _rooms[doorTab[i]._r2]) &&
|
|
&obj1 == _currentRoom->getObject(doorTab[i]._o2)) {
|
|
r = _rooms[doorTab[i]._r1];
|
|
r->getObject(doorTab[i]._o1)->_type |= OPENED;
|
|
r->setSectionVisible(r->getObject(doorTab[i]._o1)->_section, kShownTrue);
|
|
}
|
|
}
|
|
} else if (verb == ACTION_CLOSE && obj1._id == DOOR) {
|
|
for (int i = 0; i < 11; i++) {
|
|
if ((_currentRoom == _rooms[doorTab[i]._r1]) &&
|
|
&obj1 == _currentRoom->getObject(doorTab[i]._o1)) {
|
|
r = _rooms[doorTab[i]._r2];
|
|
r->getObject(doorTab[i]._o2)->_type &= ~OPENED;
|
|
r->setSectionVisible(r->getObject(doorTab[i]._o2)->_section, kShownFalse);
|
|
} else if ((_currentRoom == _rooms[doorTab[i]._r2]) &&
|
|
&obj1 == _currentRoom->getObject(doorTab[i]._o2)) {
|
|
r = _rooms[doorTab[i]._r1];
|
|
r->getObject(doorTab[i]._o1)->_type &= ~OPENED;
|
|
r->setSectionVisible(r->getObject(doorTab[i]._o1)->_section, kShownFalse);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void GameManager2::securityEntrance() {
|
|
static struct {
|
|
RoomId _r;
|
|
int _a1;
|
|
int _a2;
|
|
} securityList[11] = {
|
|
{MUS1 ,11,31},
|
|
{MUS2 , 7,17},
|
|
{MUS3 , 7,17},
|
|
{MUS10, 1, 7},
|
|
{MUS11, 1, 7},
|
|
{MUS7 ,10,32},
|
|
{MUS6 , 8,18},
|
|
{MUS5 , 8,18},
|
|
{MUS9 , 2, 8},
|
|
{MUS8 , 2, 8},
|
|
{MUS1 , 0, 0}
|
|
};
|
|
|
|
int time = (g_system->getMillis() - _state._startTime) / 600;
|
|
int second = time % 100;
|
|
|
|
if (_rooms[_securityTab[second / 10]] == _currentRoom) {
|
|
int i;
|
|
for (i = 0; _currentRoom != _rooms[securityList[i]._r]; i++) {}
|
|
if (_lastRoom == _rooms[securityList[i + 1]._r]) {
|
|
_vm->renderImage(securityList[i]._a1);
|
|
_vm->renderImage(securityList[i]._a2);
|
|
caught2();
|
|
} else
|
|
caught();
|
|
}
|
|
}
|
|
|
|
void GameManager2::pressureAlarmEntrance() {
|
|
_state._pressureCounter = 0;
|
|
securityEntrance();
|
|
}
|
|
|
|
void GameManager2::pressureAlarmCount() {
|
|
if (!(_state._alarmOn ||
|
|
(_currentRoom == _rooms[MUS22] && _currentRoom->isSectionVisible(6)))) {
|
|
_state._pressureCounter++;
|
|
if ((_currentRoom->getId() >= MUS12 && _state._pressureCounter > 8) ||
|
|
_state._pressureCounter > 16)
|
|
alarm();
|
|
}
|
|
setAnimationTimer(11);
|
|
}
|
|
|
|
}
|
|
|