aboutsummaryrefslogtreecommitdiff
path: root/lure/game.cpp
diff options
context:
space:
mode:
authorTravis Howell2006-02-11 12:54:56 +0000
committerTravis Howell2006-02-11 12:54:56 +0000
commit6703dc7fa1cd517a96d4f1955ca1794967d2a920 (patch)
treecd3e2ee3053e8a7ffc6ac05c1109bcb5ac1040c5 /lure/game.cpp
parentcbb2ca005c8385a25fcf7195319ca909d0f7124b (diff)
downloadscummvm-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.cpp420
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