diff options
author | Travis Howell | 2006-02-11 12:54:56 +0000 |
---|---|---|
committer | Travis Howell | 2006-02-11 12:54:56 +0000 |
commit | 6703dc7fa1cd517a96d4f1955ca1794967d2a920 (patch) | |
tree | cd3e2ee3053e8a7ffc6ac05c1109bcb5ac1040c5 /lure/game.cpp | |
parent | cbb2ca005c8385a25fcf7195319ca909d0f7124b (diff) | |
download | scummvm-rg350-6703dc7fa1cd517a96d4f1955ca1794967d2a920.tar.gz scummvm-rg350-6703dc7fa1cd517a96d4f1955ca1794967d2a920.tar.bz2 scummvm-rg350-6703dc7fa1cd517a96d4f1955ca1794967d2a920.zip |
Add patch #1374870 - New Lure of the Temptress module
svn-id: r20536
Diffstat (limited to 'lure/game.cpp')
-rw-r--r-- | lure/game.cpp | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/lure/game.cpp b/lure/game.cpp new file mode 100644 index 0000000000..d86b4a7bb3 --- /dev/null +++ b/lure/game.cpp @@ -0,0 +1,420 @@ +/* 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/debug-input.h" +#include "lure/debug-methods.h" +#include "lure/scripts.h" +#include "lure/res_struct.h" + +namespace Lure { + +static Game *int_game = NULL; + +Game &Game::getReference() { + return *int_game; +} + +Game::Game() { + int_game = this; + _slowSpeedFlag = true; + _soundFlag = true; + _remoteView = false; +} + +void Game::nextFrame() { + Resources &r = Resources::getReference(); + HotspotList::iterator i = r.activeHotspots().begin(); + HotspotList::iterator iTemp; + + // Note the somewhat more complicated loop style as a hotspot tick handler may + // unload the hotspot and accompanying record + for (; i != r.activeHotspots().end(); i = iTemp) { + iTemp = i; + ++iTemp; + Hotspot &h = *i.operator*(); + h.tick(); + } +} + +void Game::execute() { + OSystem &system = System::getReference(); + Room &r = Room::getReference(); + Resources &res = Resources::getReference(); + Events &events = Events::getReference(); + Mouse &mouse = Mouse::getReference(); + Screen &screen = Screen::getReference(); + Menu &menu = Menu::getReference(); + ValueTableData &fields = res.fieldList(); + + uint32 timerVal = system.getMillis(); + + screen.empty(); + //_screen.resetPalette(); + screen.setPaletteEmpty(); + + Script::execute(STARTUP_SCRIPT); + + // Load the first room + r.setRoomNumber(1); + + // Set the player direction + res.getActiveHotspot(PLAYER_ID)->setDirection(UP); + + r.update(); + mouse.setCursorNum(CURSOR_ARROW); + mouse.cursorOn(); + + while (!events.quitFlag) { + // If time for next frame, allow everything to update + if (system.getMillis() > timerVal + GAME_FRAME_DELAY) { + timerVal = system.getMillis(); + nextFrame(); + } + res.delayList().tick(); + r.update(); + + if (events.pollEvent()) { + if (events.type() == OSystem::EVENT_KEYDOWN) { + uint16 roomNum = r.roomNumber(); + +#ifdef LURE_DEBUG + if (events.event().kbd.keycode == 282) { + doDebugMenu(); + continue; + } +#endif + + switch (events.event().kbd.ascii) { + case 27: + events.quitFlag = true; + break; + +#ifdef LURE_DEBUG + case '+': + while (++roomNum <= 51) + if (res.getRoom(roomNum) != NULL) break; + if (roomNum == 52) roomNum = 1; + + r.leaveRoom(); + r.setRoomNumber(roomNum); + break; + + case '-': + if (roomNum == 1) roomNum = 55; + while (res.getRoom(--roomNum) == NULL) ; + + r.leaveRoom(); + r.setRoomNumber(roomNum); + break; + + case '*': + res.getActiveHotspot(PLAYER_ID)->setRoomNumber( + r.roomNumber()); + break; +#endif + default: + break; + } + } + + if (mouse.y() < MENUBAR_Y_SIZE) + { + if (mouse.getCursorNum() != CURSOR_MENUBAR) mouse.setCursorNum(CURSOR_MENUBAR); + if ((mouse.getCursorNum() == CURSOR_MENUBAR) && mouse.lButton()) + { + uint8 responseId = menu.execute(); + mouse.setCursorNum((mouse.y() < MENUBAR_Y_SIZE) ? CURSOR_MENUBAR : CURSOR_ARROW); + if (responseId != MENUITEM_NONE) + handleMenuResponse(responseId); + } + } else { + if (mouse.getCursorNum() == CURSOR_MENUBAR) mouse.setCursorNum(CURSOR_ARROW); + + if (events.type() == OSystem::EVENT_MOUSEMOVE) + r.cursorMoved(); + + if (mouse.rButton()) handleRightClickMenu(); + else if (mouse.lButton()) handleLeftClick(); + } + } + + uint16 destRoom = fields.getField(NEW_ROOM_NUMBER); + if (_remoteView && (destRoom != 0)) { + // Show a remote view of the specified room + uint16 currentRoom = r.roomNumber(); + r.setRoomNumber(destRoom, true); + + // This code eventually needs to be moved into the main loop so that, + // amongst other things, the tick handlers controlling animation can work + while (!events.quitFlag && !mouse.lButton() && !mouse.rButton()) { + if (events.pollEvent()) { + if ((events.type() == OSystem::EVENT_KEYDOWN) && + (events.event().kbd.ascii == 27)) + events.quitFlag = true; + if (events.type() == OSystem::EVENT_MOUSEMOVE) + r.cursorMoved(); + } + + if (system.getMillis() > timerVal + GAME_FRAME_DELAY) { + timerVal = system.getMillis(); + nextFrame(); + } + res.delayList().tick(); + r.update(); + } + + fields.setField(NEW_ROOM_NUMBER, 0); + Hotspot *player = res.getActiveHotspot(PLAYER_ID); + player->setTickProc(0x5e44); // reattach player handler + _remoteView = false; + r.setRoomNumber(currentRoom); + } + } + + r.leaveRoom(); +} + +#ifdef LURE_DEBUG + +#define NUM_DEBUG_ITEMS 4 +const char *debugItems[NUM_DEBUG_ITEMS] = + {"Toggle Info", "Set Room", "Show Active HS", "Show Room HS"}; + +void Game::doDebugMenu() { + uint16 index = PopupMenu::Show(NUM_DEBUG_ITEMS, debugItems); + Room &r = Room::getReference(); + Resources &res = Resources::getReference(); + + switch (index) { + case 0: + // Toggle co-ordinates + r.setShowInfo(!r.showInfo()); + break; + + case 1: + // Set room number: + uint32 roomNumber; + if (!input_integer("Enter room number:", roomNumber)) return; + if (res.getRoom(roomNumber)) + r.setRoomNumber(roomNumber); + else + Dialog::show("The room does not exist"); + break; + + case 2: + // Show active hotspots + showActiveHotspots(); + break; + + case 3: + // Show hotspots in room + showRoomHotspots(); + break; + + default: + break; + } +} + +#endif + +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(); + } +} + +void Game::handleRightClickMenu() { + Room &r = Room::getReference(); + Resources &res = Resources::getReference(); + ValueTableData &fields = Resources::getReference().fieldList(); + Hotspot *player = res.getActiveHotspot(PLAYER_ID); + HotspotData *hotspot; + Action action; + uint32 actions; + uint16 itemId; + + if (r.hotspotId() != 0) { + // Get hotspot actions + actions = r.hotspotActions(); + } else { + // Standard actions - drink, examine, look, status + actions = 0x1184000; + } + + // If no inventory items remove entries that require them + if (res.numInventoryItems() == 0) + actions &= 0xFEF3F9FD; + + action = NONE; + hotspot = NULL; + + bool breakFlag = false; + while (!breakFlag) { + action = PopupMenu::Show(actions); + + switch (action) { + case LOOK: + case STATUS: + breakFlag = true; + break; + + case GIVE: + case USE: + case EXAMINE: + case DRINK: + if (action != DRINK) + hotspot = res.getHotspot(r.hotspotId()); + itemId = PopupMenu::ShowInventory(); + breakFlag = (itemId != 0xffff); + if (breakFlag) + fields.setField(USE_HOTSPOT_ID, itemId); + break; + + default: + hotspot = res.getHotspot(r.hotspotId()); + breakFlag = true; + break; + } + } + + // Set fields used by the script interpreter + fields.setField(CHARACTER_HOTSPOT_ID, PLAYER_ID); + if (hotspot) { + fields.setField(ACTIVE_HOTSPOT_ID, hotspot->hotspotId); + if ((action != USE) && (action != GIVE)) { + fields.setField(USE_HOTSPOT_ID, hotspot->hotspotId); + } + } + + if (action != NONE) + player->doAction(action, hotspot); +} + +void Game::handleLeftClick() { + Room &room = Room::getReference(); + Mouse &mouse = Mouse::getReference(); + Resources &resources = Resources::getReference(); + + if (room.hotspotId()) { + // Handle look at hotspot + HotspotData *hs = resources.getHotspot(room.hotspotId()); + Hotspot *player = resources.getActiveHotspot(PLAYER_ID); + room.setAction(LOOK_AT); + room.update(); + player->doAction(LOOK_AT, hs); + room.setAction(NONE); + } else { + // Walk to mouse click. TODO: still need to recognise other actions, + // such as to room exits or closing an on-screen floating dialog + Hotspot *hs = resources.getActiveHotspot(PLAYER_ID); + hs->walkTo(mouse.x(), mouse.y(), 0); + } +} + +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); +} + +} // end of namespace Lure |