mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-15 06:08:35 +00:00
607 lines
15 KiB
C++
607 lines
15 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 "mohawk/cstime.h"
|
|
#include "mohawk/cstime_cases.h"
|
|
#include "mohawk/cstime_game.h"
|
|
#include "mohawk/cstime_ui.h"
|
|
#include "mohawk/cstime_view.h"
|
|
#include "mohawk/resource.h"
|
|
#include "mohawk/cursors.h"
|
|
#include "mohawk/video.h"
|
|
|
|
#include "common/config-manager.h"
|
|
#include "common/error.h"
|
|
#include "common/events.h"
|
|
#include "common/fs.h"
|
|
#include "common/textconsole.h"
|
|
#include "common/system.h"
|
|
|
|
namespace Mohawk {
|
|
|
|
MohawkEngine_CSTime::MohawkEngine_CSTime(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) {
|
|
_rnd = new Common::RandomSource("cstime");
|
|
|
|
// If the user just copied the CD contents, the fonts are in a subdirectory.
|
|
const Common::FSNode gameDataDir(ConfMan.get("path"));
|
|
// They're in setup/data32 for 'Where in Time is Carmen Sandiego?'.
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "setup/data32");
|
|
// They're in 95instal for 'Carmen Sandiego's Great Chase Through Time'.
|
|
SearchMan.addSubDirectoryMatching(gameDataDir, "95instal");
|
|
|
|
_state = kCSTStateStartup;
|
|
|
|
reset();
|
|
|
|
_console = 0;
|
|
_gfx = 0;
|
|
_cursor = 0;
|
|
_interface = 0;
|
|
_view = 0;
|
|
_needsUpdate = false;
|
|
_case = 0;
|
|
_nextSceneId = 1;
|
|
}
|
|
|
|
MohawkEngine_CSTime::~MohawkEngine_CSTime() {
|
|
delete _interface;
|
|
delete _view;
|
|
delete _console;
|
|
delete _gfx;
|
|
delete _rnd;
|
|
}
|
|
|
|
Common::Error MohawkEngine_CSTime::run() {
|
|
MohawkEngine::run();
|
|
|
|
_console = new CSTimeConsole(this);
|
|
_gfx = new CSTimeGraphics(this);
|
|
_cursor = new DefaultCursorManager(this, ID_CURS);
|
|
|
|
_interface = new CSTimeInterface(this);
|
|
|
|
_view = new CSTimeView(this);
|
|
_view->setupView();
|
|
_view->setModule(new CSTimeModule(this));
|
|
|
|
while (!shouldQuit()) {
|
|
switch (_state) {
|
|
case kCSTStateStartup:
|
|
// We just jump straight to the case for now.
|
|
_state = kCSTStateNewCase;
|
|
break;
|
|
|
|
case kCSTStateNewCase:
|
|
initCase();
|
|
_state = kCSTStateNewScene;
|
|
break;
|
|
|
|
case kCSTStateNewScene:
|
|
nextScene();
|
|
_state = kCSTStateNormal;
|
|
break;
|
|
|
|
case kCSTStateNormal:
|
|
update();
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
void MohawkEngine_CSTime::update() {
|
|
Common::Event event;
|
|
while (_eventMan->pollEvent(event)) {
|
|
switch (event.type) {
|
|
case Common::EVENT_MOUSEMOVE:
|
|
_interface->mouseMove(event.mouse);
|
|
_needsUpdate = true;
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONUP:
|
|
_interface->mouseUp(event.mouse);
|
|
break;
|
|
|
|
case Common::EVENT_LBUTTONDOWN:
|
|
_interface->mouseDown(event.mouse);
|
|
break;
|
|
|
|
case Common::EVENT_RBUTTONDOWN:
|
|
// (All of this case is only run if the relevant option is enabled.)
|
|
|
|
// FIXME: Don't do these if the options are open.
|
|
if (_case->getCurrScene()->_activeChar->_flappingState != 0xffff)
|
|
_case->getCurrScene()->_activeChar->interruptFlapping();
|
|
if (getCurrentEventType() == kCSTimeEventWaitForClick)
|
|
mouseClicked();
|
|
|
|
// TODO: This is always run, even if not in-game.
|
|
//pauseCurrentNIS();
|
|
//stopSound();
|
|
// FIXME: There's some more stuff here.
|
|
break;
|
|
|
|
case Common::EVENT_KEYDOWN:
|
|
switch (event.kbd.keycode) {
|
|
case Common::KEYCODE_d:
|
|
if (event.kbd.flags & Common::KBD_CTRL) {
|
|
_console->attach();
|
|
_console->onFrame();
|
|
}
|
|
break;
|
|
|
|
case Common::KEYCODE_SPACE:
|
|
pauseGame();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
_needsUpdate = true;
|
|
|
|
if (_video->updateMovies())
|
|
_needsUpdate = true;
|
|
|
|
if (_needsUpdate) {
|
|
_view->_needsUpdate = true;
|
|
_needsUpdate = false;
|
|
}
|
|
|
|
eventIdle();
|
|
_interface->idle();
|
|
|
|
// Cut down on CPU usage
|
|
_system->delayMillis(10);
|
|
}
|
|
|
|
void MohawkEngine_CSTime::initCase() {
|
|
_interface->openResFile();
|
|
_interface->install();
|
|
_interface->cursorInstall();
|
|
// TODO: _interface->paletteOff(true);
|
|
_interface->cursorActivate(true);
|
|
_interface->cursorSetShape(1, false);
|
|
for (uint i = 0; i < 19; i++)
|
|
_haveInvItem[i] = 0;
|
|
_interface->getInventoryDisplay()->clearDisplay();
|
|
_interface->getCarmenNote()->clearPieces();
|
|
// TODO: fixup book rect for case 20
|
|
for (uint i = 0; i < 20; i++)
|
|
_caseVariable[i] = 0;
|
|
_case = new CSTimeCase1(this); // TODO
|
|
_interface->getInventoryDisplay()->install();
|
|
_nextSceneId = 1;
|
|
}
|
|
|
|
void MohawkEngine_CSTime::nextScene() {
|
|
_case->setCurrScene(_nextSceneId);
|
|
CSTimeScene *scene = _case->getCurrScene();
|
|
// TODO: scene->setState(1);
|
|
scene->_visitCount++;
|
|
scene->installGroup();
|
|
|
|
_interface->draw();
|
|
scene->buildScene();
|
|
scene->setupAmbientAnims();
|
|
_interface->cursorSetShape(1, false);
|
|
|
|
addEvent(CSTimeEvent(kCSTimeEventWait, 0xffff, 500));
|
|
scene->idleAmbientAnims();
|
|
// TODO: startEnvironmentSound();
|
|
if (scene->_visitCount == 1) {
|
|
addEventList(scene->getEvents(false));
|
|
} else {
|
|
addEventList(scene->getEvents(true));
|
|
}
|
|
_view->idleView();
|
|
// TODO: maybe startMusic();
|
|
}
|
|
|
|
void MohawkEngine_CSTime::loadResourceFile(Common::String name) {
|
|
MohawkArchive *archive = new MohawkArchive();
|
|
if (!archive->openFile(name + ".mhk"))
|
|
error("failed to open %s.mhk", name.c_str());
|
|
_mhk.push_back(archive);
|
|
}
|
|
|
|
void MohawkEngine_CSTime::addEvent(const CSTimeEvent &event) {
|
|
_events.push_back(event);
|
|
}
|
|
|
|
void MohawkEngine_CSTime::addEventList(const Common::Array<CSTimeEvent> &list) {
|
|
for (uint i = 0; i < list.size(); i++)
|
|
addEvent(list[i]);
|
|
}
|
|
|
|
void MohawkEngine_CSTime::insertEventAtFront(const CSTimeEvent &event) {
|
|
if (_events.empty())
|
|
_events.push_front(event);
|
|
else
|
|
_events.insert(++_events.begin(), event);
|
|
}
|
|
|
|
uint16 MohawkEngine_CSTime::getCurrentEventType() {
|
|
if (_events.empty())
|
|
return 0xffff;
|
|
else
|
|
return _events.front().type;
|
|
}
|
|
|
|
void MohawkEngine_CSTime::eventIdle() {
|
|
bool done = false;
|
|
while (_events.size() && !done && true /* TODO: !_options->getState() */) {
|
|
_lastTimeout = 0xffffffff;
|
|
|
|
bool advanceQueue = true;
|
|
bool processEvent = true;
|
|
CSTimeEvent &event = _events.front();
|
|
|
|
switch (event.type) {
|
|
case kCSTimeEventCharPlayNIS:
|
|
if (_NISRunning) {
|
|
CSTimeChar *chr = _case->getCurrScene()->getChar(event.param1);
|
|
if (chr->NISIsDone()) {
|
|
chr->removeNIS();
|
|
_NISRunning = false;
|
|
chr->setupAmbientAnims(true);
|
|
_events.pop_front();
|
|
processEvent = false;
|
|
} else {
|
|
done = true;
|
|
}
|
|
} else {
|
|
advanceQueue = false;
|
|
}
|
|
break;
|
|
|
|
case kCSTimeEventNewScene:
|
|
if (_processingEvent) {
|
|
processEvent = false;
|
|
_events.pop_front();
|
|
_processingEvent = false;
|
|
// FIXME: check skip global, if set:
|
|
// stopMusic(), stopEnvironmentSound(), set scene to _nextSceneId,
|
|
// set scene state to 1, set state to idle loop
|
|
} else {
|
|
triggerEvent(event);
|
|
done = true;
|
|
_processingEvent = true;
|
|
}
|
|
break;
|
|
|
|
case kCSTimeEventCharStartFlapping:
|
|
assert(_case->getCurrScene()->_activeChar);
|
|
switch (_case->getCurrScene()->_activeChar->_flappingState) {
|
|
case 0xffff:
|
|
// FIXME: check skip global, if set, processEvent = false and pop event
|
|
advanceQueue = false;
|
|
break;
|
|
case 0:
|
|
_case->getCurrScene()->_activeChar->_flappingState = 0xffff;
|
|
_events.pop_front();
|
|
processEvent = false;
|
|
break;
|
|
default:
|
|
done = true;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kCSTimeEventCharSomeNIS55:
|
|
// This is like kCSTimeEventCharPlayNIS, only using a different flag variable.
|
|
if (_processingNIS55) {
|
|
CSTimeChar *chr = _case->getCurrScene()->getChar(event.param1);
|
|
if (chr->NISIsDone()) {
|
|
chr->removeNIS();
|
|
_processingNIS55 = false;
|
|
chr->setupAmbientAnims(true);
|
|
_events.pop_front();
|
|
processEvent = false;
|
|
} else {
|
|
done = true;
|
|
}
|
|
} else {
|
|
advanceQueue = false;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!done && processEvent) {
|
|
_interface->cursorSetWaitCursor();
|
|
triggerEvent(event);
|
|
if (advanceQueue)
|
|
_events.pop_front();
|
|
}
|
|
|
|
if (!_events.size()) {
|
|
Common::Point pos = _system->getEventManager()->getMousePos();
|
|
if (_interface->_sceneRect.contains(pos))
|
|
_case->getCurrScene()->setCursorForCurrentPoint();
|
|
else
|
|
_interface->setCursorForCurrentPoint();
|
|
_interface->mouseMove(pos);
|
|
resetTimeout();
|
|
}
|
|
}
|
|
}
|
|
|
|
void MohawkEngine_CSTime::resetTimeout() {
|
|
_lastTimeout = _system->getMillis();
|
|
}
|
|
|
|
void MohawkEngine_CSTime::mouseClicked() {
|
|
// TODO
|
|
}
|
|
|
|
bool MohawkEngine_CSTime::NISIsRunning() {
|
|
if (_NISRunning || (!_events.empty() && _events.front().type == kCSTimeEventUnused63))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
void MohawkEngine_CSTime::reset() {
|
|
_NISRunning = false;
|
|
_processingNIS55 = false;
|
|
_lastTimeout = 0xffffffff;
|
|
_processingEvent = false;
|
|
}
|
|
|
|
void MohawkEngine_CSTime::triggerEvent(CSTimeEvent &event) {
|
|
debug("triggerEvent: type %d, param1 %d, param2 %d", event.type, event.param1, event.param2);
|
|
|
|
switch (event.type) {
|
|
case kCSTimeEventNothing:
|
|
case kCSTimeEventUnused8:
|
|
case kCSTimeEventUnused21:
|
|
case kCSTimeEventUnused63:
|
|
break;
|
|
|
|
case kCSTimeEventCondition:
|
|
_case->handleConditionalEvent(event);
|
|
break;
|
|
|
|
case kCSTimeEventCharPlayNIS:
|
|
_case->getCurrScene()->getChar(event.param1)->playNIS(event.param2);
|
|
_NISRunning = true;
|
|
break;
|
|
|
|
case kCSTimeEventStartConversation:
|
|
_case->setConversation(event.param2);
|
|
_case->getCurrConversation()->setSourceChar(event.param1);
|
|
_case->getCurrConversation()->incrementTalkCount();
|
|
_case->getCurrConversation()->start();
|
|
break;
|
|
|
|
case kCSTimeEventNewScene:
|
|
if (_case->getCurrConversation()->getState() != (uint)~0)
|
|
_case->getCurrConversation()->end(false);
|
|
_interface->clearTextLine();
|
|
// TODO: _interface->fadeDown();
|
|
_interface->cursorSetShape(1);
|
|
// TODO: swap cursor
|
|
// TODO: unloadPreloadedSounds?
|
|
if (_interface->getInventoryDisplay()->getState() == 4) {
|
|
_interface->getInventoryDisplay()->hide();
|
|
_interface->getInventoryDisplay()->setState(0);
|
|
}
|
|
// TODO: stupid case 20 handling
|
|
_case->getCurrScene()->leave();
|
|
// TODO: set dim palette(true)
|
|
_view->_needsUpdate = true;
|
|
_view->idleView();
|
|
// TODO: set dim palette(false)
|
|
_nextSceneId = event.param2;
|
|
_state = kCSTStateNewScene;
|
|
break;
|
|
|
|
case kCSTimeEventCharStartFlapping:
|
|
{
|
|
CSTimeChar *chr = _case->getCurrScene()->getChar(event.param1);
|
|
if (!chr->_unknown2) {
|
|
_case->getCurrScene()->_activeChar->_flappingState = 0;
|
|
break;
|
|
}
|
|
|
|
chr->startFlapping(event.param2);
|
|
if (event.param2)
|
|
_interface->drawTextIdToBubble(event.param2);
|
|
|
|
CSTimeEvent newEvent;
|
|
newEvent.param1 = 0xffff;
|
|
newEvent.param2 = 0xffff;
|
|
|
|
newEvent.type = kCSTimeEventUnknown70;
|
|
insertEventAtFront(newEvent);
|
|
|
|
newEvent.type = kCSTimeEventUpdateBubble;
|
|
insertEventAtFront(newEvent);
|
|
|
|
newEvent.type = kCSTimeEventUnknown69;
|
|
insertEventAtFront(newEvent);
|
|
}
|
|
break;
|
|
|
|
case kCSTimeEventDropItemInInventory:
|
|
_interface->dropItemInInventory(event.param2);
|
|
break;
|
|
|
|
case kCSTimeEventRemoveItemFromInventory:
|
|
if (!_interface->getInventoryDisplay()->isItemDisplayed(event.param2))
|
|
break;
|
|
_haveInvItem[event.param2] = 0;
|
|
_interface->getInventoryDisplay()->removeItem(event.param2);
|
|
break;
|
|
|
|
case kCSTimeEventAddNotePiece:
|
|
_interface->clearTextLine();
|
|
_interface->getCarmenNote()->addPiece(event.param2, event.param1);
|
|
break;
|
|
|
|
case kCSTimeEventDisableHotspot:
|
|
_case->getCurrScene()->getHotspot(event.param2).state = 0;
|
|
break;
|
|
|
|
case kCSTimeEventDisableFeature:
|
|
if (!_case->getCurrScene()->_objectFeatures[event.param2])
|
|
break;
|
|
_view->removeFeature(_case->getCurrScene()->_objectFeatures[event.param2], true);
|
|
_case->getCurrScene()->_objectFeatures[event.param2] = NULL;
|
|
break;
|
|
|
|
case kCSTimeEventAddFeature:
|
|
// TODO: merge this with buildScene somehow?
|
|
if (_case->getCurrScene()->_objectFeatures[event.param2]) {
|
|
_case->getCurrScene()->_objectFeatures[event.param2]->resetFeatureScript(1, 0);
|
|
break;
|
|
}
|
|
{
|
|
uint32 flags = kFeatureSortStatic | kFeatureNewNoLoop | kFeatureNewDisableOnReset;
|
|
_case->getCurrScene()->_objectFeatures[event.param2] = _view->installViewFeature(_case->getCurrScene()->getSceneId() + event.param2, flags, NULL);
|
|
// FIXME: a mess of priority stuff
|
|
}
|
|
break;
|
|
|
|
case kCSTimeEventEnableHotspot:
|
|
_case->getCurrScene()->getHotspot(event.param2).state = 1;
|
|
break;
|
|
|
|
case kCSTimeEventSetAsked:
|
|
uint qar, entry;
|
|
qar = event.param2 / 5;
|
|
entry = event.param2 % 5;
|
|
if (qar > 7)
|
|
error("SetAsked event out of range");
|
|
_case->getCurrConversation()->setAsked(qar, entry);
|
|
break;
|
|
|
|
case kCSTimeEventStartHelp:
|
|
_interface->getHelp()->start();
|
|
break;
|
|
|
|
case kCSTimeEventShowBigNote:
|
|
_interface->getCarmenNote()->drawBigNote();
|
|
break;
|
|
|
|
case kCSTimeEventActivateCuffs:
|
|
_interface->getInventoryDisplay()->activateCuffs(true);
|
|
break;
|
|
|
|
case kCSTimeEventHelperSetupRestPos:
|
|
_case->getCurrScene()->getChar(_case->getCurrScene()->getHelperId())->setupRestPos();
|
|
break;
|
|
|
|
case kCSTimeEventUnknown25:
|
|
_case->getCurrScene()->getChar(event.param1)->_unknown2 = 1;
|
|
break;
|
|
|
|
case kCSTimeEventUnknown26:
|
|
_case->getCurrScene()->getChar(event.param1)->_unknown2 = 0;
|
|
break;
|
|
|
|
case kCSTimeEventWait:
|
|
warning("ignoring wait");
|
|
// FIXME
|
|
break;
|
|
|
|
case kCSTimeEventCharSetState:
|
|
_case->getCurrScene()->getChar(event.param1)->_enabled = event.param2;
|
|
break;
|
|
|
|
case kCSTimeEventCharSetupRestPos:
|
|
_case->getCurrScene()->getChar(event.param1)->setupRestPos();
|
|
break;
|
|
|
|
case kCSTimeEventStopEnvironmentSound:
|
|
warning("ignoring stop environment sound");
|
|
// FIXME
|
|
break;
|
|
|
|
case kCSTimeEventSetMusic:
|
|
warning("ignoring set music");
|
|
// FIXME
|
|
break;
|
|
|
|
case kCSTimeEventSetInsertBefore:
|
|
warning("ignoring insert before");
|
|
// FIXME
|
|
break;
|
|
|
|
case kCSTimeEventCharSomeNIS55:
|
|
_processingNIS55 = true;
|
|
_case->getCurrScene()->getChar(event.param1)->playNIS(event.param2);
|
|
break;
|
|
|
|
case kCSTimeEventUpdateBubble:
|
|
switch (event.param2) {
|
|
case 0:
|
|
// FIXME
|
|
warning("ignoring bubble update (queue events)");
|
|
break;
|
|
case 1:
|
|
// FIXME
|
|
warning("ignoring bubble update (install)");
|
|
break;
|
|
default:
|
|
_interface->closeBubble();
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case kCSTimeEventInitScene:
|
|
_interface->displayTextLine("");
|
|
|
|
// FIXME: install palette
|
|
|
|
// FIXME: swapCursor(true)
|
|
break;
|
|
|
|
case kCSTimeEventUnknown69:
|
|
// TODO: if persistent text, insert a kCSTimeEventWaitForClick in front of the queue
|
|
break;
|
|
|
|
case kCSTimeEventUnknown70:
|
|
if (_case->getCurrConversation()->getState() != (uint)~0 && _case->getCurrConversation()->getState()) {
|
|
_case->getCurrConversation()->finishProcessingQaR();
|
|
} else if (_interface->getHelp()->getState() != (uint)~0 && _interface->getHelp()->getState()) {
|
|
_interface->getHelp()->cleanupAfterFlapping();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
error("unknown scene event type %d", event.type);
|
|
}
|
|
}
|
|
|
|
} // End of namespace Mohawk
|