STARK: Add support for calling dialogs

This commit is contained in:
Bastien Bouclet 2015-01-11 15:25:43 +01:00
parent c93098e7af
commit a75de69533
10 changed files with 175 additions and 29 deletions

View file

@ -36,6 +36,7 @@ MODULE_OBJS := \
resourcereference.o \ resourcereference.o \
scene.o \ scene.o \
services/archiveloader.o \ services/archiveloader.o \
services/dialogplayer.o \
services/resourceprovider.o \ services/resourceprovider.o \
services/services.o \ services/services.o \
services/stateprovider.o \ services/stateprovider.o \

View file

@ -24,10 +24,13 @@
#include "engines/stark/debug.h" #include "engines/stark/debug.h"
#include "engines/stark/resources/bookmark.h" #include "engines/stark/resources/bookmark.h"
#include "engines/stark/resources/dialog.h"
#include "engines/stark/resources/item.h" #include "engines/stark/resources/item.h"
#include "engines/stark/resources/knowledge.h" #include "engines/stark/resources/knowledge.h"
#include "engines/stark/resources/script.h" #include "engines/stark/resources/script.h"
#include "engines/stark/resourcereference.h" #include "engines/stark/resourcereference.h"
#include "engines/stark/services/services.h"
#include "engines/stark/services/dialogplayer.h"
#include "engines/stark/xrcreader.h" #include "engines/stark/xrcreader.h"
namespace Stark { namespace Stark {
@ -42,19 +45,21 @@ Command::Command(Resource *parent, byte subType, uint16 index, const Common::Str
Command *Command::execute(uint32 callMode, Script *script) { Command *Command::execute(uint32 callMode, Script *script) {
switch (_subType) { switch (_subType) {
case kGoTo: case kDialogCall:
return opDialogCall(script, _arguments[1].referenceValue, _arguments[2].intValue);
case kLocationGoTo:
return nullptr; // TODO, just end the script for now return nullptr; // TODO, just end the script for now
case kPause: case kScriptPause:
opPause(script, _arguments[1].referenceValue); opScriptPause(script, _arguments[1].referenceValue);
return this; return this; // Stay on this command while the script is suspended
case kItem3DPlaceOn: case kItem3DPlaceOn:
op3DPlaceOn(_arguments[1].referenceValue, _arguments[2].referenceValue); opItem3DPlaceOn(_arguments[1].referenceValue, _arguments[2].referenceValue);
return nextCommand(); return nextCommand();
case kItemEnable: case kItemEnable:
opItemEnable(_arguments[1].referenceValue, _arguments[2].intValue); opItemEnable(_arguments[1].referenceValue, _arguments[2].intValue);
return nextCommand(); return nextCommand();
case kItemPlaceDirection: case kItemPlaceDirection:
opPlaceDirection(_arguments[1].referenceValue, _arguments[2].intValue); opItemPlaceDirection(_arguments[1].referenceValue, _arguments[2].intValue);
return nextCommand(); return nextCommand();
default: default:
// warning("Unimplemented opcode %d", _subType); // warning("Unimplemented opcode %d", _subType);
@ -64,12 +69,26 @@ Command *Command::execute(uint32 callMode, Script *script) {
return nextCommand(); return nextCommand();
} }
void Command::opPause(Script *script, const ResourceReference &durationRef) { Command *Command::opDialogCall(Script *script, const ResourceReference &dialogRef, int32 suspend) {
DialogPlayer *dialogPlayer = StarkServices::instance().dialogPlayer;
Dialog *dialog = dialogRef.resolve<Dialog>();
dialogPlayer->run(dialog);
if (suspend) {
script->suspend(dialog);
return this; // Stay on the same command while suspended
} else {
return nextCommand();
}
}
void Command::opScriptPause(Script *script, const ResourceReference &durationRef) {
Knowledge *duration = durationRef.resolve<Knowledge>(); Knowledge *duration = durationRef.resolve<Knowledge>();
script->pause(duration->getIntegerValue()); script->pause(duration->getIntegerValue());
} }
void Command::op3DPlaceOn(const ResourceReference &itemRef, const ResourceReference &targetRef) { void Command::opItem3DPlaceOn(const ResourceReference &itemRef, const ResourceReference &targetRef) {
ItemSub5610 *item = itemRef.resolve<ItemSub5610>(); ItemSub5610 *item = itemRef.resolve<ItemSub5610>();
Resource *target = targetRef.resolve<Resource>(); Resource *target = targetRef.resolve<Resource>();
@ -102,7 +121,7 @@ void Command::opItemEnable(const ResourceReference &itemRef, int32 enable) {
} }
} }
void Command::opPlaceDirection(const ResourceReference &itemRef, int32 direction) { void Command::opItemPlaceDirection(const ResourceReference &itemRef, int32 direction) {
ItemSub5610 *item = itemRef.resolve<ItemSub5610>(); ItemSub5610 *item = itemRef.resolve<ItemSub5610>();
item->setDirection(abs(direction) % 360); item->setDirection(abs(direction) % 360);

View file

@ -46,9 +46,11 @@ public:
kCommandBegin = 0, kCommandBegin = 0,
kCommandEnd = 1, kCommandEnd = 1,
kGoTo = 5, kDialogCall = 3,
kPause = 9, kLocationGoTo = 5,
kScriptPause = 9,
kItem3DPlaceOn = 81, kItem3DPlaceOn = 81,
@ -87,10 +89,11 @@ protected:
Command *resolveArgumentSiblingReference(const Argument &argument); Command *resolveArgumentSiblingReference(const Argument &argument);
void op3DPlaceOn(const ResourceReference &itemRef, const ResourceReference &targetRef); Command *opDialogCall(Script *script, const ResourceReference &dialogRef, int32 suspend);
void opPause(Script *script, const ResourceReference &durationRef); void opScriptPause(Script *script, const ResourceReference &durationRef);
void opItem3DPlaceOn(const ResourceReference &itemRef, const ResourceReference &targetRef);
void opItemEnable(const ResourceReference &itemRef, int32 enable); void opItemEnable(const ResourceReference &itemRef, int32 enable);
void opPlaceDirection(const ResourceReference &itemRef, int32 direction); void opItemPlaceDirection(const ResourceReference &itemRef, int32 direction);
Common::Array<Argument> _arguments; Common::Array<Argument> _arguments;
}; };

View file

@ -24,6 +24,7 @@
#include "engines/stark/resources/command.h" #include "engines/stark/resources/command.h"
#include "engines/stark/resources/item.h" #include "engines/stark/resources/item.h"
#include "engines/stark/services/dialogplayer.h"
#include "engines/stark/services/global.h" #include "engines/stark/services/global.h"
#include "engines/stark/services/services.h" #include "engines/stark/services/services.h"
#include "engines/stark/xrcreader.h" #include "engines/stark/xrcreader.h"
@ -42,7 +43,8 @@ Script::Script(Resource *parent, byte subType, uint16 index, const Common::Strin
_shouldResetGameSpeed(false), _shouldResetGameSpeed(false),
_enabled(false), _enabled(false),
_nextCommand(nullptr), _nextCommand(nullptr),
_pauseTimeLeft(-1) { _pauseTimeLeft(-1),
_suspendingResource(nullptr) {
_type = TYPE; _type = TYPE;
} }
@ -152,7 +154,7 @@ bool Script::shouldExecute(uint32 callMode) {
} }
bool Script::isSuspended() { bool Script::isSuspended() {
return _pauseTimeLeft >= 0; return _pauseTimeLeft >= 0 || _suspendingResource;
} }
void Script::updateSuspended() { void Script::updateSuspended() {
@ -160,11 +162,28 @@ void Script::updateSuspended() {
// Decrease the remaining pause time // Decrease the remaining pause time
Global *global = StarkServices::instance().global; Global *global = StarkServices::instance().global;
_pauseTimeLeft -= global->getMillisecondsPerGameloop(); _pauseTimeLeft -= global->getMillisecondsPerGameloop();
} else {
_pauseTimeLeft = -1;
} }
if (_pauseTimeLeft < 0) { if (_suspendingResource) {
// Check if the suspending resource is still active
switch (_suspendingResource->getType().get()) {
case ResourceType::kDialog: {
DialogPlayer *dialogPlayer = StarkServices::instance().dialogPlayer;
if (!dialogPlayer->isRunning()) {
// Resume the script execution if the dialog is complete
_suspendingResource = nullptr;
}
break;
}
default:
error("Unhandled suspending resource type %s", _suspendingResource->getType().getName());
}
}
if (!isSuspended()) {
// Resume to the next command // Resume to the next command
_pauseTimeLeft = -1;
_nextCommand = _nextCommand->nextCommand(); _nextCommand = _nextCommand->nextCommand();
} }
} }
@ -173,6 +192,10 @@ void Script::pause(int32 msecs) {
_pauseTimeLeft = msecs; _pauseTimeLeft = msecs;
} }
void Script::suspend(Resource *cause) {
_suspendingResource = cause;
}
void Script::execute(uint32 callMode) { void Script::execute(uint32 callMode) {
if (!shouldExecute(callMode)) { if (!shouldExecute(callMode)) {
return; return;

View file

@ -82,6 +82,9 @@ public:
/** Pause the script for the specified time */ /** Pause the script for the specified time */
void pause(int32 msecs); void pause(int32 msecs);
/** Suspend the script while the specified resource is running */
void suspend(Resource *cause);
protected: protected:
void printData() override; void printData() override;
@ -98,7 +101,9 @@ protected:
bool _enabled; bool _enabled;
Command *_nextCommand; Command *_nextCommand;
int32 _pauseTimeLeft; int32 _pauseTimeLeft;
Resource *_suspendingResource;
}; };
} // End of namespace Stark } // End of namespace Stark

View file

@ -0,0 +1,41 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 "engines/stark/services/dialogplayer.h"
#include "engines/stark/resources/dialog.h"
namespace Stark {
DialogPlayer::~DialogPlayer() {
}
void DialogPlayer::run(Dialog *dialog) {
}
bool DialogPlayer::isRunning() {
return false;
}
} // End of namespace Stark

View file

@ -0,0 +1,43 @@
/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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.
*
*/
#ifndef STARK_SERVICES_DIALOG_PLAYER_H
#define STARK_SERVICES_DIALOG_PLAYER_H
namespace Stark {
class Dialog;
class DialogPlayer {
public:
virtual ~DialogPlayer();
void run(Dialog *dialog);
bool isRunning();
protected:
};
} // End of namespace Stark
#endif // STARK_SERVICES_DIALOG_PLAYER_H

View file

@ -31,10 +31,11 @@ class RandomSource;
namespace Stark { namespace Stark {
class Scene;
class Global;
class ArchiveLoader; class ArchiveLoader;
class DialogPlayer;
class Global;
class ResourceProvider; class ResourceProvider;
class Scene;
/** /**
* Public services available as a singleton * Public services available as a singleton
@ -42,15 +43,17 @@ class ResourceProvider;
class StarkServices : public Common::Singleton<StarkServices> { class StarkServices : public Common::Singleton<StarkServices> {
public: public:
StarkServices() { StarkServices() {
global = nullptr;
archiveLoader = nullptr; archiveLoader = nullptr;
dialogPlayer = nullptr;
global = nullptr;
resourceProvider = nullptr; resourceProvider = nullptr;
randomSource = nullptr; randomSource = nullptr;
scene = nullptr; scene = nullptr;
} }
Global *global;
ArchiveLoader *archiveLoader; ArchiveLoader *archiveLoader;
DialogPlayer *dialogPlayer;
Global *global;
ResourceProvider *resourceProvider; ResourceProvider *resourceProvider;
Common::RandomSource *randomSource; Common::RandomSource *randomSource;
Scene *scene; Scene *scene;

View file

@ -28,6 +28,7 @@
#include "engines/stark/resources/location.h" #include "engines/stark/resources/location.h"
#include "engines/stark/scene.h" #include "engines/stark/scene.h"
#include "engines/stark/services/archiveloader.h" #include "engines/stark/services/archiveloader.h"
#include "engines/stark/services/dialogplayer.h"
#include "engines/stark/services/global.h" #include "engines/stark/services/global.h"
#include "engines/stark/services/resourceprovider.h" #include "engines/stark/services/resourceprovider.h"
#include "engines/stark/services/services.h" #include "engines/stark/services/services.h"
@ -54,7 +55,8 @@ StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) :
_archiveLoader(nullptr), _archiveLoader(nullptr),
_stateProvider(nullptr), _stateProvider(nullptr),
_resourceProvider(nullptr), _resourceProvider(nullptr),
_randomSource(nullptr) { _randomSource(nullptr),
_dialogPlayer(nullptr) {
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127); _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127);
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
@ -68,6 +70,7 @@ StarkEngine::StarkEngine(OSystem *syst, const ADGameDescription *gameDesc) :
} }
StarkEngine::~StarkEngine() { StarkEngine::~StarkEngine() {
delete _dialogPlayer;
delete _randomSource; delete _randomSource;
delete _scene; delete _scene;
delete _console; delete _console;
@ -93,12 +96,14 @@ Common::Error StarkEngine::run() {
_resourceProvider = new ResourceProvider(_archiveLoader, _stateProvider, _global); _resourceProvider = new ResourceProvider(_archiveLoader, _stateProvider, _global);
_randomSource = new Common::RandomSource("stark"); _randomSource = new Common::RandomSource("stark");
_scene = new Scene(_gfx); _scene = new Scene(_gfx);
_dialogPlayer = new DialogPlayer();
// Setup the public services // Setup the public services
StarkServices &services = StarkServices::instance(); StarkServices &services = StarkServices::instance();
services.archiveLoader = _archiveLoader; services.archiveLoader = _archiveLoader;
services.resourceProvider = _resourceProvider; services.dialogPlayer = _dialogPlayer;
services.global = _global; services.global = _global;
services.resourceProvider = _resourceProvider;
services.randomSource = _randomSource; services.randomSource = _randomSource;
services.scene = _scene; services.scene = _scene;

View file

@ -43,11 +43,12 @@ enum StarkGameFeatures {
GF_DVD = (1 << 1) GF_DVD = (1 << 1)
}; };
class Console;
class GfxDriver;
class Scene;
class Global;
class ArchiveLoader; class ArchiveLoader;
class Console;
class DialogPlayer;
class GfxDriver;
class Global;
class Scene;
class StateProvider; class StateProvider;
class ResourceProvider; class ResourceProvider;
@ -73,8 +74,10 @@ private:
GfxDriver *_gfx; GfxDriver *_gfx;
Console *_console; Console *_console;
Global *_global; // Services
ArchiveLoader *_archiveLoader; ArchiveLoader *_archiveLoader;
DialogPlayer *_dialogPlayer;
Global *_global;
StateProvider *_stateProvider; StateProvider *_stateProvider;
ResourceProvider *_resourceProvider; ResourceProvider *_resourceProvider;
Common::RandomSource *_randomSource; Common::RandomSource *_randomSource;