2006-02-11 12:54:56 +00:00
|
|
|
/* ScummVM - Scumm Interpreter
|
|
|
|
* Copyright (C) 2005-2006 The ScummVM project
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "lure/game.h"
|
|
|
|
#include "lure/strings.h"
|
|
|
|
#include "lure/room.h"
|
|
|
|
#include "lure/system.h"
|
|
|
|
#include "lure/scripts.h"
|
|
|
|
#include "lure/res_struct.h"
|
2006-05-23 12:41:28 +00:00
|
|
|
#include "lure/animseq.h"
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
#include "common/config-manager.h"
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
namespace Lure {
|
|
|
|
|
|
|
|
static Game *int_game = NULL;
|
|
|
|
|
|
|
|
Game &Game::getReference() {
|
|
|
|
return *int_game;
|
|
|
|
}
|
|
|
|
|
|
|
|
Game::Game() {
|
|
|
|
int_game = this;
|
2006-07-08 08:39:42 +00:00
|
|
|
_debugger = new Debugger();
|
2006-02-11 12:54:56 +00:00
|
|
|
_slowSpeedFlag = true;
|
|
|
|
_soundFlag = true;
|
|
|
|
}
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
Game::~Game() {
|
|
|
|
delete _debugger;
|
|
|
|
}
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
void Game::nextFrame() {
|
2006-02-19 04:29:26 +00:00
|
|
|
Resources &res = Resources::getReference();
|
2006-05-23 12:41:28 +00:00
|
|
|
ValueTableData &fields = res.fieldList();
|
2006-02-19 04:29:26 +00:00
|
|
|
Room &room = Room::getReference();
|
|
|
|
HotspotList::iterator i;
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
res.pausedList().countdown();
|
2006-02-19 04:29:26 +00:00
|
|
|
room.checkCursor();
|
|
|
|
room.update();
|
2006-05-23 12:41:28 +00:00
|
|
|
|
2006-02-19 04:29:26 +00:00
|
|
|
// Call the tick method for each hotspot - this is somewaht complicated
|
|
|
|
// by the fact that a tick proc can unload both itself and/or others,
|
|
|
|
// so we first get a list of the Ids, and call the tick proc for each
|
|
|
|
// id in sequence if it's still active
|
|
|
|
|
|
|
|
uint16 *idList = new uint16[res.activeHotspots().size()];
|
|
|
|
int idSize = 0;
|
|
|
|
for (i = res.activeHotspots().begin(); i != res.activeHotspots().end(); ++i) {
|
|
|
|
Hotspot *hotspot = *i;
|
|
|
|
idList[idSize++] = hotspot->hotspotId();
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
2006-02-19 04:29:26 +00:00
|
|
|
|
|
|
|
for (int idCtr = 0; idCtr < idSize; ++idCtr) {
|
|
|
|
Hotspot *hotspot = res.getActiveHotspot(idList[idCtr]);
|
2006-05-23 12:41:28 +00:00
|
|
|
if (hotspot) {
|
|
|
|
fields.setField(CHARACTER_HOTSPOT_ID, hotspot->hotspotId());
|
2006-02-19 04:29:26 +00:00
|
|
|
hotspot->tick();
|
2006-05-23 12:41:28 +00:00
|
|
|
}
|
2006-02-19 04:29:26 +00:00
|
|
|
}
|
|
|
|
|
2006-03-13 11:52:16 +00:00
|
|
|
delete[] idList;
|
2006-02-19 04:29:26 +00:00
|
|
|
Screen::getReference().update();
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Game::execute() {
|
|
|
|
OSystem &system = System::getReference();
|
2006-07-08 08:39:42 +00:00
|
|
|
Room &room = Room::getReference();
|
2006-02-11 12:54:56 +00:00
|
|
|
Resources &res = Resources::getReference();
|
|
|
|
Events &events = Events::getReference();
|
|
|
|
Mouse &mouse = Mouse::getReference();
|
|
|
|
Screen &screen = Screen::getReference();
|
|
|
|
ValueTableData &fields = res.fieldList();
|
|
|
|
|
|
|
|
uint32 timerVal = system.getMillis();
|
|
|
|
|
|
|
|
screen.empty();
|
|
|
|
//_screen.resetPalette();
|
|
|
|
screen.setPaletteEmpty();
|
|
|
|
|
2006-05-31 13:36:01 +00:00
|
|
|
setState(0);
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
Script::execute(STARTUP_SCRIPT);
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
int bootParam = ConfMan.getInt("boot_param");
|
|
|
|
handleBootParam(bootParam);
|
2006-02-11 12:54:56 +00:00
|
|
|
|
|
|
|
// Set the player direction
|
|
|
|
res.getActiveHotspot(PLAYER_ID)->setDirection(UP);
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
room.update();
|
2006-02-11 12:54:56 +00:00
|
|
|
mouse.setCursorNum(CURSOR_ARROW);
|
|
|
|
mouse.cursorOn();
|
|
|
|
|
|
|
|
while (!events.quitFlag) {
|
2006-05-23 12:41:28 +00:00
|
|
|
while (!events.quitFlag && (_state == 0)) {
|
|
|
|
// If time for next frame, allow everything to update
|
|
|
|
if (system.getMillis() > timerVal + GAME_FRAME_DELAY) {
|
|
|
|
timerVal = system.getMillis();
|
2006-07-08 08:39:42 +00:00
|
|
|
nextFrame();
|
2006-05-23 12:41:28 +00:00
|
|
|
}
|
|
|
|
res.delayList().tick();
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
while (events.pollEvent()) {
|
|
|
|
if (events.type() == OSystem::EVENT_KEYDOWN) {
|
2006-07-08 08:39:42 +00:00
|
|
|
uint16 roomNum = room.roomNumber();
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
if ((events.event().kbd.flags == OSystem::KBD_CTRL) &&
|
|
|
|
(events.event().kbd.keycode == 'd')) {
|
|
|
|
// Activate the debugger
|
|
|
|
_debugger->attach();
|
|
|
|
break;
|
2006-05-23 12:41:28 +00:00
|
|
|
}
|
2006-07-08 08:39:42 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
switch (events.event().kbd.ascii) {
|
|
|
|
case 27:
|
|
|
|
events.quitFlag = true;
|
|
|
|
break;
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
case '+':
|
|
|
|
while (++roomNum <= 51)
|
|
|
|
if (res.getRoom(roomNum) != NULL) break;
|
|
|
|
if (roomNum == 52) roomNum = 1;
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
room.leaveRoom();
|
|
|
|
room.setRoomNumber(roomNum);
|
2006-05-23 12:41:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
if (roomNum == 1) roomNum = 55;
|
|
|
|
while (res.getRoom(--roomNum) == NULL) ;
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
room.leaveRoom();
|
|
|
|
room.setRoomNumber(roomNum);
|
2006-05-23 12:41:28 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
res.getActiveHotspot(PLAYER_ID)->setRoomNumber(
|
2006-07-08 08:39:42 +00:00
|
|
|
room.roomNumber());
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 267: // keypad '/'
|
|
|
|
room.setShowInfo(!room.showInfo());
|
2006-05-23 12:41:28 +00:00
|
|
|
break;
|
2006-07-08 08:39:42 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
2006-05-23 12:41:28 +00:00
|
|
|
|
|
|
|
if ((events.type() == OSystem::EVENT_LBUTTONDOWN) ||
|
|
|
|
(events.type() == OSystem::EVENT_RBUTTONDOWN))
|
|
|
|
handleClick();
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
uint16 destRoom;
|
|
|
|
destRoom = fields.getField(NEW_ROOM_NUMBER);
|
|
|
|
if (destRoom != 0) {
|
|
|
|
// Need to change the current room
|
2006-07-08 08:39:42 +00:00
|
|
|
strcpy(room.statusLine(), "");
|
2006-05-23 12:41:28 +00:00
|
|
|
bool remoteFlag = fields.getField(OLD_ROOM_NUMBER) != 0;
|
2006-07-08 08:39:42 +00:00
|
|
|
room.setRoomNumber(destRoom, remoteFlag);
|
2006-05-23 12:41:28 +00:00
|
|
|
fields.setField(NEW_ROOM_NUMBER, 0);
|
|
|
|
}
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
destRoom = fields.playerNewPos().roomNumber;
|
|
|
|
if (destRoom != 0) {
|
|
|
|
playerChangeRoom();
|
|
|
|
}
|
|
|
|
|
|
|
|
system.updateScreen();
|
|
|
|
system.delayMillis(10);
|
2006-07-08 08:39:42 +00:00
|
|
|
|
|
|
|
if (_debugger->isAttached())
|
|
|
|
_debugger->onFrame();
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
2006-04-11 10:48:28 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
// If Skorl catches player, show the catching animation
|
|
|
|
if ((_state & GS_CAUGHT) != 0) {
|
|
|
|
Palette palette(SKORL_CATCH_PALETTE_ID);
|
|
|
|
AnimationSequence *anim = new AnimationSequence(screen, system,
|
|
|
|
SKORL_CATCH_ANIM_ID, palette, false);
|
|
|
|
mouse.cursorOff();
|
|
|
|
anim->show();
|
|
|
|
mouse.cursorOn();
|
2006-04-11 10:48:28 +00:00
|
|
|
}
|
2006-04-11 11:55:27 +00:00
|
|
|
|
2006-05-23 12:41:28 +00:00
|
|
|
// If the Restart/Restore dialog is needed, show it
|
|
|
|
if ((_state & GS_RESTORE_RESTART) != 0) {
|
|
|
|
// TODO: Restore/Restart dialog - for now, simply flag for exit
|
|
|
|
events.quitFlag = true;
|
|
|
|
}
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
room.leaveRoom();
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Game::handleMenuResponse(uint8 selection) {
|
|
|
|
switch (selection) {
|
|
|
|
case MENUITEM_CREDITS:
|
|
|
|
doShowCredits();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MENUITEM_RESTART_GAME:
|
|
|
|
case MENUITEM_SAVE_GAME:
|
|
|
|
case MENUITEM_RESTORE_GAME:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MENUITEM_QUIT:
|
|
|
|
doQuit();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MENUITEM_TEXT_SPEED:
|
|
|
|
doTextSpeed();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MENUITEM_SOUND:
|
|
|
|
doSound();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-11 10:48:28 +00:00
|
|
|
void Game::playerChangeRoom() {
|
|
|
|
Resources &res = Resources::getReference();
|
|
|
|
Room &room = Room::getReference();
|
|
|
|
ValueTableData &fields = res.fieldList();
|
2006-07-08 08:39:42 +00:00
|
|
|
SequenceDelayList &delayList = Resources::getReference().delayList();
|
|
|
|
|
2006-04-11 10:48:28 +00:00
|
|
|
uint16 roomNum = fields.playerNewPos().roomNumber;
|
|
|
|
fields.playerNewPos().roomNumber = 0;
|
|
|
|
Point &newPos = fields.playerNewPos().position;
|
2006-07-08 08:39:42 +00:00
|
|
|
delayList.clear();
|
2006-04-11 10:48:28 +00:00
|
|
|
|
|
|
|
Hotspot *player = res.getActiveHotspot(PLAYER_ID);
|
|
|
|
player->currentActions().clear();
|
|
|
|
player->setRoomNumber(roomNum);
|
|
|
|
//player->setPosition((newPos.x & 0xfff8) || 5, newPos.y & 0xfff8);
|
|
|
|
player->setPosition(newPos.x, newPos.y);
|
|
|
|
room.setRoomNumber(roomNum, false);
|
|
|
|
}
|
|
|
|
|
2006-02-19 04:29:26 +00:00
|
|
|
void Game::handleClick() {
|
|
|
|
Resources &res = Resources::getReference();
|
|
|
|
Room &room = Room::getReference();
|
|
|
|
ValueTableData &fields = res.fieldList();
|
|
|
|
Mouse &mouse = Mouse::getReference();
|
|
|
|
uint16 oldRoomNumber = fields.getField(OLD_ROOM_NUMBER);
|
|
|
|
|
|
|
|
if (room.checkInTalkDialog()) {
|
|
|
|
// Close the active talk dialog
|
2006-08-07 13:23:30 +00:00
|
|
|
room.setTalkDialog(0, 0, 0, 0);
|
2006-02-19 04:29:26 +00:00
|
|
|
} else if (oldRoomNumber != 0) {
|
|
|
|
// Viewing a room remotely - handle returning to prior room
|
2006-04-11 10:48:28 +00:00
|
|
|
if ((room.roomNumber() != 35) || (fields.getField(87) == 0)) {
|
|
|
|
// Reset player tick proc and signal to change back to the old room
|
|
|
|
res.getActiveHotspot(PLAYER_ID)->setTickProc(PLAYER_TICK_PROC_ID);
|
|
|
|
fields.setField(NEW_ROOM_NUMBER, oldRoomNumber);
|
|
|
|
fields.setField(OLD_ROOM_NUMBER, 0);
|
|
|
|
}
|
2006-04-29 11:22:05 +00:00
|
|
|
} else if ((room.cursorState() == CS_TALKING) ||
|
|
|
|
(res.getTalkState() != TALK_NONE)) {
|
2006-05-11 08:04:41 +00:00
|
|
|
// Currently talking, so let its tick proc handle it
|
2006-02-19 04:29:26 +00:00
|
|
|
} else if (mouse.y() < MENUBAR_Y_SIZE) {
|
|
|
|
uint8 response = Menu::getReference().execute();
|
|
|
|
if (response != MENUITEM_NONE)
|
|
|
|
handleMenuResponse(response);
|
2006-04-29 11:22:05 +00:00
|
|
|
} else if ((room.cursorState() == CS_SEQUENCE) ||
|
2006-05-29 08:12:07 +00:00
|
|
|
(room.cursorState() == CS_BUMPED)) {
|
2006-04-29 11:22:05 +00:00
|
|
|
// No action necessary
|
2006-02-19 04:29:26 +00:00
|
|
|
} else {
|
|
|
|
if (mouse.lButton())
|
|
|
|
handleLeftClick();
|
|
|
|
else
|
|
|
|
handleRightClickMenu();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
void Game::handleRightClickMenu() {
|
2006-02-19 04:29:26 +00:00
|
|
|
Room &room = Room::getReference();
|
2006-02-11 12:54:56 +00:00
|
|
|
Resources &res = Resources::getReference();
|
2006-07-08 08:39:42 +00:00
|
|
|
Screen &screen = Screen::getReference();
|
2006-02-19 04:29:26 +00:00
|
|
|
ValueTableData &fields = res.fieldList();
|
2006-07-08 08:39:42 +00:00
|
|
|
StringData &strings = StringData::getReference();
|
|
|
|
Mouse &mouse = Mouse::getReference();
|
|
|
|
char *statusLine = room.statusLine();
|
2006-02-11 12:54:56 +00:00
|
|
|
Hotspot *player = res.getActiveHotspot(PLAYER_ID);
|
2006-07-08 08:39:42 +00:00
|
|
|
HotspotData *hotspot, *useHotspot;
|
2006-02-11 12:54:56 +00:00
|
|
|
Action action;
|
|
|
|
uint32 actions;
|
2006-04-29 11:22:05 +00:00
|
|
|
uint16 itemId = 0xffff;
|
2006-07-08 08:39:42 +00:00
|
|
|
bool hasItems;
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-02-19 04:29:26 +00:00
|
|
|
if (room.hotspotId() != 0) {
|
2006-02-11 12:54:56 +00:00
|
|
|
// Get hotspot actions
|
2006-02-19 04:29:26 +00:00
|
|
|
actions = room.hotspotActions();
|
2006-02-11 12:54:56 +00:00
|
|
|
} else {
|
|
|
|
// Standard actions - drink, examine, look, status
|
|
|
|
actions = 0x1184000;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If no inventory items remove entries that require them
|
|
|
|
if (res.numInventoryItems() == 0)
|
|
|
|
actions &= 0xFEF3F9FD;
|
|
|
|
|
2006-02-19 04:29:26 +00:00
|
|
|
// If the player hasn't any money, remove any bribe entry
|
|
|
|
if (res.fieldList().numGroats() == 0)
|
|
|
|
actions &= 0xFF7FFFFF;
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
action = NONE;
|
|
|
|
hotspot = NULL;
|
|
|
|
|
|
|
|
bool breakFlag = false;
|
|
|
|
while (!breakFlag) {
|
2006-07-08 08:39:42 +00:00
|
|
|
statusLine = room.statusLine();
|
|
|
|
strcpy(statusLine, "");
|
|
|
|
room.update();
|
|
|
|
screen.update();
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
action = PopupMenu::Show(actions);
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
if (action != NONE) {
|
|
|
|
sprintf(statusLine, "%s ", actionList[action]);
|
|
|
|
statusLine += strlen(statusLine);
|
|
|
|
}
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
switch (action) {
|
|
|
|
case LOOK:
|
|
|
|
case STATUS:
|
|
|
|
breakFlag = true;
|
|
|
|
break;
|
|
|
|
|
2006-07-30 12:15:52 +00:00
|
|
|
case ASK:
|
|
|
|
hotspot = res.getHotspot(room.hotspotId());
|
2006-08-27 11:47:03 +00:00
|
|
|
assert(hotspot);
|
2006-07-30 12:15:52 +00:00
|
|
|
strings.getString(hotspot->nameId, statusLine);
|
|
|
|
strcat(statusLine, " for ");
|
|
|
|
statusLine += strlen(statusLine);
|
|
|
|
|
|
|
|
itemId = PopupMenu::ShowItems(GET);
|
|
|
|
breakFlag = ((itemId != 0xffff) && (itemId != 0xfffe));
|
|
|
|
break;
|
|
|
|
|
2006-08-27 11:47:03 +00:00
|
|
|
case TELL:
|
|
|
|
hotspot = res.getHotspot(room.hotspotId());
|
|
|
|
assert(hotspot);
|
|
|
|
strings.getString(hotspot->nameId, statusLine);
|
|
|
|
strcat(statusLine, " to ");
|
|
|
|
breakFlag = GetTellActions();
|
|
|
|
break;
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
case GIVE:
|
|
|
|
case USE:
|
|
|
|
case EXAMINE:
|
|
|
|
case DRINK:
|
2006-07-08 08:39:42 +00:00
|
|
|
hasItems = (res.numInventoryItems() != 0);
|
|
|
|
if (!hasItems)
|
|
|
|
strcat(statusLine, "(nothing)");
|
|
|
|
statusLine += strlen(statusLine);
|
|
|
|
|
|
|
|
room.update();
|
|
|
|
screen.update();
|
|
|
|
mouse.waitForRelease();
|
|
|
|
|
|
|
|
if (hasItems) {
|
|
|
|
if (action != DRINK)
|
|
|
|
hotspot = res.getHotspot(room.hotspotId());
|
|
|
|
itemId = PopupMenu::ShowInventory();
|
|
|
|
breakFlag = (itemId != 0xffff);
|
|
|
|
if (breakFlag) {
|
|
|
|
fields.setField(USE_HOTSPOT_ID, itemId);
|
|
|
|
if ((action == GIVE) || (action == USE)) {
|
|
|
|
// Add in the "X to " or "X on " section of give/use action
|
|
|
|
useHotspot = res.getHotspot(itemId);
|
|
|
|
assert(useHotspot);
|
|
|
|
strings.getString(useHotspot->nameId, statusLine);
|
|
|
|
if (action == GIVE)
|
|
|
|
strcat(statusLine, " to ");
|
|
|
|
else
|
|
|
|
strcat(statusLine, " on ");
|
|
|
|
statusLine += strlen(statusLine);
|
|
|
|
}
|
|
|
|
else if ((action == DRINK) || (action == EXAMINE))
|
|
|
|
hotspot = res.getHotspot(itemId);
|
|
|
|
}
|
|
|
|
}
|
2006-02-11 12:54:56 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2006-02-19 04:29:26 +00:00
|
|
|
hotspot = res.getHotspot(room.hotspotId());
|
2006-02-11 12:54:56 +00:00
|
|
|
breakFlag = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-19 04:29:26 +00:00
|
|
|
if (action != NONE) {
|
2006-04-29 11:22:05 +00:00
|
|
|
player->stopWalking();
|
2006-07-08 08:39:42 +00:00
|
|
|
|
|
|
|
if (hotspot == NULL) {
|
|
|
|
doAction(action, 0, itemId);
|
|
|
|
} else {
|
|
|
|
// Add the hotspot name to the status line and then go do the action
|
|
|
|
strings.getString(hotspot->nameId, statusLine);
|
|
|
|
doAction(action, hotspot->hotspotId, itemId);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Clear the status line
|
|
|
|
strcpy(room.statusLine(), "");
|
2006-02-19 04:29:26 +00:00
|
|
|
}
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Game::handleLeftClick() {
|
|
|
|
Room &room = Room::getReference();
|
|
|
|
Mouse &mouse = Mouse::getReference();
|
2006-02-19 04:29:26 +00:00
|
|
|
Resources &res = Resources::getReference();
|
2006-07-08 08:39:42 +00:00
|
|
|
StringData &strings = StringData::getReference();
|
2006-04-11 10:48:28 +00:00
|
|
|
Hotspot *player = res.getActiveHotspot(PLAYER_ID);
|
2006-02-11 12:54:56 +00:00
|
|
|
|
2006-04-29 11:22:05 +00:00
|
|
|
room.setCursorState(CS_NONE);
|
|
|
|
player->stopWalking();
|
|
|
|
player->setDestHotspot(0);
|
|
|
|
player->setActionCtr(0);
|
2006-07-08 08:39:42 +00:00
|
|
|
strcpy(room.statusLine(), "");
|
2006-04-29 11:22:05 +00:00
|
|
|
|
2006-04-11 10:48:28 +00:00
|
|
|
if ((room.destRoomNumber() == 0) && (room.hotspotId() != 0)) {
|
2006-02-11 12:54:56 +00:00
|
|
|
// Handle look at hotspot
|
2006-07-08 08:39:42 +00:00
|
|
|
sprintf(room.statusLine(), "%s ", actionList[LOOK_AT]);
|
|
|
|
HotspotData *hotspot = res.getHotspot(room.hotspotId());
|
|
|
|
assert(hotspot);
|
|
|
|
strings.getString(hotspot->nameId, room.statusLine() + strlen(room.statusLine()));
|
2006-04-29 11:22:05 +00:00
|
|
|
doAction(LOOK_AT, room.hotspotId(), 0xffff);
|
2006-02-19 04:29:26 +00:00
|
|
|
|
2006-04-11 10:48:28 +00:00
|
|
|
} else if (room.destRoomNumber() != 0) {
|
|
|
|
// Walk to another room
|
|
|
|
RoomExitCoordinateData &exitData =
|
|
|
|
res.coordinateList().getEntry(room.roomNumber()).getData(room.destRoomNumber());
|
|
|
|
|
|
|
|
player->walkTo((exitData.x & 0xfff8) | 5, (exitData.y & 0xfff8),
|
|
|
|
room.hotspotId() == 0 ? 0xffff : room.hotspotId());
|
2006-02-11 12:54:56 +00:00
|
|
|
} else {
|
2006-04-11 10:48:28 +00:00
|
|
|
// Walking within room
|
|
|
|
player->walkTo(mouse.x(), mouse.y(), 0);
|
2006-02-11 12:54:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-27 11:47:03 +00:00
|
|
|
const char *continueStrsList[] = {"and then", "finish"};
|
|
|
|
|
|
|
|
bool Game::GetTellActions() {
|
|
|
|
Resources &res = Resources::getReference();
|
|
|
|
Screen &screen = Screen::getReference();
|
|
|
|
Room &room = Room::getReference();
|
|
|
|
StringData &strings = StringData::getReference();
|
|
|
|
char *statusLine = room.statusLine();
|
|
|
|
uint16 fullCommands[MAX_TELL_COMMANDS * 3 + 1];
|
|
|
|
uint16 *commands = &fullCommands[1];
|
|
|
|
char *statusLinePos[MAX_TELL_COMMANDS][4];
|
|
|
|
int commandIndex = 0;
|
|
|
|
int paramIndex = 0;
|
|
|
|
uint16 selectionId;
|
|
|
|
char selectionName[MAX_DESC_SIZE];
|
|
|
|
HotspotData *hotspot;
|
|
|
|
Action action;
|
|
|
|
|
|
|
|
// First word will be the destination character
|
|
|
|
fullCommands[0] = room.hotspotId();
|
|
|
|
|
|
|
|
// Loop for getting tell commands
|
|
|
|
|
|
|
|
while ((commandIndex >= 0) && (commandIndex < MAX_TELL_COMMANDS)) {
|
|
|
|
|
|
|
|
// Loop for each sub-part of commands: Action, up to two params, and
|
|
|
|
// a "and then" selection to allow for more commands
|
|
|
|
|
|
|
|
while ((paramIndex >= 0) && (paramIndex <= 4)) {
|
|
|
|
// Update status line
|
|
|
|
statusLine += strlen(statusLine);
|
|
|
|
statusLinePos[commandIndex][paramIndex] = statusLine;
|
|
|
|
room.update();
|
|
|
|
screen.update();
|
|
|
|
|
|
|
|
switch (paramIndex) {
|
|
|
|
case 0:
|
|
|
|
// Prompt for selection of action to perform
|
|
|
|
action = PopupMenu::Show(0x6A07FD);
|
|
|
|
if (action == NONE) {
|
|
|
|
// Move backwards to prior specified action
|
|
|
|
--commandIndex;
|
|
|
|
if (commandIndex < 0)
|
|
|
|
paramIndex = -1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
paramIndex = 3;
|
|
|
|
statusLine = statusLinePos[commandIndex][paramIndex];
|
|
|
|
*statusLine = '\0';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the action to the status line
|
|
|
|
sprintf(statusLine + strlen(statusLine), "%s ", actionList[action]);
|
|
|
|
|
|
|
|
// Handle any processing for the action
|
|
|
|
commands[commandIndex * 3] = (uint16) action;
|
|
|
|
commands[commandIndex * 3 + 1] = 0;
|
|
|
|
commands[commandIndex * 3 + 2] = 0;
|
|
|
|
++paramIndex;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
// First parameter
|
|
|
|
action = (Action) commands[commandIndex * 3];
|
|
|
|
if (action != RETURN) {
|
|
|
|
// Prompt for selection
|
|
|
|
if ((action != USE) && (action != DRINK) && (action != GIVE))
|
|
|
|
selectionId = PopupMenu::ShowItems(action);
|
|
|
|
else
|
|
|
|
selectionId = PopupMenu::ShowItems(GET);
|
|
|
|
|
|
|
|
if ((selectionId == 0xffff) || (selectionId == 0xfffe)) {
|
|
|
|
// Move back to prompting for action
|
|
|
|
--paramIndex;
|
|
|
|
statusLine = statusLinePos[commandIndex][paramIndex];
|
|
|
|
*statusLine = '\0';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (selectionId < NOONE_ID) {
|
|
|
|
// Must be a room selection
|
|
|
|
strings.getString(selectionId, selectionName);
|
|
|
|
} else {
|
|
|
|
hotspot = res.getHotspot(selectionId);
|
|
|
|
assert(hotspot);
|
|
|
|
strings.getString(hotspot->nameId, selectionName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store selected entry
|
|
|
|
commands[commandIndex * 3 + 1] = selectionId;
|
|
|
|
strcat(statusLine, selectionName);
|
|
|
|
}
|
|
|
|
|
|
|
|
++paramIndex;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
// Second parameter
|
|
|
|
action = (Action) commands[commandIndex * 3];
|
|
|
|
if (action == ASK)
|
|
|
|
strcat(statusLine, " for ");
|
|
|
|
else if (action == GIVE)
|
|
|
|
strcat(statusLine, " to ");
|
|
|
|
else if (action == USE)
|
|
|
|
strcat(statusLine, " on ");
|
|
|
|
else {
|
|
|
|
// All other commads don't need a second parameter
|
|
|
|
++paramIndex;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the second parameter
|
|
|
|
selectionId = PopupMenu::ShowItems(GET);
|
|
|
|
if ((selectionId == 0xfffe) || (selectionId == 0xffff)) {
|
|
|
|
--paramIndex;
|
|
|
|
statusLine = statusLinePos[commandIndex][paramIndex];
|
|
|
|
*statusLine = '\0';
|
|
|
|
} else {
|
|
|
|
// Display the second parameter
|
|
|
|
hotspot = res.getHotspot(selectionId);
|
|
|
|
assert(hotspot);
|
|
|
|
strings.getString(hotspot->nameId, selectionName);
|
|
|
|
strcat(statusLine, selectionName);
|
|
|
|
|
|
|
|
commands[commandIndex * 3 + 2] = selectionId;
|
|
|
|
++paramIndex;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
// Prompting for "and then" for more commands
|
|
|
|
if (commandIndex == MAX_TELL_COMMANDS - 1) {
|
|
|
|
// No more commands allowed
|
|
|
|
++commandIndex;
|
|
|
|
paramIndex = -1;
|
|
|
|
} else {
|
|
|
|
// Only prompt if less than 8 commands entered
|
|
|
|
selectionId = PopupMenu::Show(2, continueStrsList);
|
|
|
|
|
|
|
|
switch (selectionId) {
|
|
|
|
case 0:
|
|
|
|
// Get ready for next command
|
|
|
|
sprintf(statusLine + strlen(statusLine), " %s ", continueStrsList[0]);
|
|
|
|
++commandIndex;
|
|
|
|
paramIndex = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
// Increment for just selected command, and add a large amount
|
|
|
|
// to signal that the command sequence is complete
|
|
|
|
commandIndex += 1 + 0x100;
|
|
|
|
paramIndex = -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Move to end of just completed command
|
|
|
|
action = (Action) commands[commandIndex * 3];
|
|
|
|
if (action == RETURN)
|
|
|
|
paramIndex = 0;
|
|
|
|
else if ((action == ASK) || (action == GIVE) || (action == USE))
|
|
|
|
paramIndex = 2;
|
|
|
|
else
|
|
|
|
paramIndex = 1;
|
|
|
|
|
|
|
|
statusLine = statusLinePos[commandIndex][paramIndex];
|
|
|
|
*statusLine = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool result = (commandIndex != -1);
|
|
|
|
if (result) {
|
|
|
|
commandIndex &= 0xff;
|
|
|
|
assert((commandIndex > 0) && (commandIndex <= MAX_TELL_COMMANDS));
|
|
|
|
strcpy(statusLinePos[0][0], "..");
|
|
|
|
room.update();
|
|
|
|
screen.update();
|
|
|
|
|
|
|
|
CharacterScheduleEntry *playerRec = res.playerSupportRecord();
|
|
|
|
playerRec->setDetails2(TELL, commandIndex * 3 + 1, &fullCommands[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2006-04-29 11:22:05 +00:00
|
|
|
void Game::doAction(Action action, uint16 hotspotId, uint16 usedId) {
|
|
|
|
Resources &res = Resources::getReference();
|
|
|
|
Room &room = Room::getReference();
|
|
|
|
ValueTableData &fields = res.fieldList();
|
|
|
|
Hotspot *player = res.getActiveHotspot(PLAYER_ID);
|
|
|
|
|
|
|
|
fields.setField(CHARACTER_HOTSPOT_ID, PLAYER_ID);
|
|
|
|
fields.setField(ACTIVE_HOTSPOT_ID, hotspotId);
|
|
|
|
|
|
|
|
res.setCurrentAction(action);
|
|
|
|
room.setCursorState(CS_ACTION);
|
2006-05-23 12:41:28 +00:00
|
|
|
|
|
|
|
// Set the action
|
|
|
|
CharacterScheduleEntry *rec = res.playerSupportRecord();
|
2006-08-27 11:47:03 +00:00
|
|
|
if (action != TELL)
|
|
|
|
rec->setDetails(action, hotspotId, usedId);
|
2006-05-23 12:41:28 +00:00
|
|
|
player->currentActions().addFront(DISPATCH_ACTION, rec, player->roomNumber());
|
2006-04-29 11:22:05 +00:00
|
|
|
}
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
void Game::doShowCredits() {
|
|
|
|
Events &events = Events::getReference();
|
|
|
|
Mouse &mouse = Mouse::getReference();
|
|
|
|
Screen &screen = Screen::getReference();
|
|
|
|
|
|
|
|
mouse.cursorOff();
|
|
|
|
Palette p(CREDITS_RESOURCE_ID - 1);
|
|
|
|
Surface *s = Surface::getScreen(CREDITS_RESOURCE_ID);
|
|
|
|
screen.setPalette(&p);
|
|
|
|
s->copyToScreen(0, 0);
|
|
|
|
delete s;
|
|
|
|
|
|
|
|
events.waitForPress();
|
|
|
|
|
|
|
|
screen.resetPalette();
|
|
|
|
screen.update();
|
|
|
|
mouse.cursorOn();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Game::doQuit() {
|
|
|
|
Mouse &mouse = Mouse::getReference();
|
|
|
|
Events &events = Events::getReference();
|
|
|
|
Screen &screen = Screen::getReference();
|
|
|
|
|
|
|
|
mouse.cursorOff();
|
|
|
|
Surface *s = Surface::newDialog(190, "Are you sure (y/n)?");
|
|
|
|
s->centerOnScreen();
|
|
|
|
delete s;
|
|
|
|
|
|
|
|
char key = '\0';
|
|
|
|
do {
|
|
|
|
if (events.pollEvent()) {
|
|
|
|
if (events.event().type == OSystem::EVENT_KEYDOWN) {
|
|
|
|
key = events.event().kbd.ascii;
|
|
|
|
if ((key >= 'A') && (key <= 'Z')) key += 'a' - 'A';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (((uint8) key != 27) && (key != 'y') && (key != 'n'));
|
|
|
|
|
|
|
|
events.quitFlag = key == 'y';
|
|
|
|
if (!events.quitFlag) {
|
|
|
|
screen.update();
|
|
|
|
mouse.cursorOn();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Game::doTextSpeed() {
|
|
|
|
Menu &menu = Menu::getReference();
|
|
|
|
|
|
|
|
_slowSpeedFlag = !_slowSpeedFlag;
|
|
|
|
const char *pSrc = _slowSpeedFlag ? "Slow" : "Fast";
|
|
|
|
char *pDest = menu.getMenu(2).getEntry(1);
|
|
|
|
memcpy(pDest, pSrc, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Game::doSound() {
|
|
|
|
Menu &menu = Menu::getReference();
|
|
|
|
|
|
|
|
_soundFlag = !_soundFlag;
|
|
|
|
const char *pSrc = _soundFlag ? "on " : "off";
|
|
|
|
char *pDest = menu.getMenu(2).getEntry(2) + 6;
|
|
|
|
memcpy(pDest, pSrc, 3);
|
|
|
|
}
|
|
|
|
|
2006-07-08 08:39:42 +00:00
|
|
|
void Game::handleBootParam(int value) {
|
|
|
|
Resources &res = Resources::getReference();
|
|
|
|
ValueTableData &fields = res.fieldList();
|
|
|
|
Room &room = Room::getReference();
|
|
|
|
Hotspot *h;
|
|
|
|
|
|
|
|
switch (value) {
|
|
|
|
case 0:
|
|
|
|
// No parameter - load the first room
|
|
|
|
room.setRoomNumber(1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
// Set player to be in rack room with a few items
|
|
|
|
// Setup Skorl in cell room
|
|
|
|
h = res.getActiveHotspot(SKORL_ID);
|
|
|
|
h->setRoomNumber(1);
|
|
|
|
h->setPosition(140, 120);
|
|
|
|
h->currentActions().top().setSupportData(0x1400);
|
|
|
|
fields.setField(11, 1);
|
|
|
|
|
|
|
|
// Set up player
|
|
|
|
h = res.getActiveHotspot(PLAYER_ID);
|
|
|
|
h->setRoomNumber(4);
|
|
|
|
h->setPosition(150, 110);
|
|
|
|
res.getHotspot(0x2710)->roomNumber = PLAYER_ID; // Bottle
|
|
|
|
res.getHotspot(0x2713)->roomNumber = PLAYER_ID; // Knife
|
|
|
|
|
|
|
|
room.setRoomNumber(4);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
// Set the player up in the outer cell with a full bottle & knife
|
|
|
|
h = res.getActiveHotspot(PLAYER_ID);
|
|
|
|
h->setRoomNumber(2);
|
|
|
|
h->setPosition(100, 110);
|
|
|
|
res.getHotspot(0x2710)->roomNumber = PLAYER_ID; // Bottle
|
|
|
|
fields.setField(BOTTLE_FILLED, 1);
|
|
|
|
res.getHotspot(0x2713)->roomNumber = PLAYER_ID; // Knife
|
|
|
|
|
|
|
|
room.setRoomNumber(2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
room.setRoomNumber(value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-11 12:54:56 +00:00
|
|
|
} // end of namespace Lure
|