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 \
scene.o \
services/archiveloader.o \
services/dialogplayer.o \
services/resourceprovider.o \
services/services.o \
services/stateprovider.o \

View file

@ -24,10 +24,13 @@
#include "engines/stark/debug.h"
#include "engines/stark/resources/bookmark.h"
#include "engines/stark/resources/dialog.h"
#include "engines/stark/resources/item.h"
#include "engines/stark/resources/knowledge.h"
#include "engines/stark/resources/script.h"
#include "engines/stark/resourcereference.h"
#include "engines/stark/services/services.h"
#include "engines/stark/services/dialogplayer.h"
#include "engines/stark/xrcreader.h"
namespace Stark {
@ -42,19 +45,21 @@ Command::Command(Resource *parent, byte subType, uint16 index, const Common::Str
Command *Command::execute(uint32 callMode, Script *script) {
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
case kPause:
opPause(script, _arguments[1].referenceValue);
return this;
case kScriptPause:
opScriptPause(script, _arguments[1].referenceValue);
return this; // Stay on this command while the script is suspended
case kItem3DPlaceOn:
op3DPlaceOn(_arguments[1].referenceValue, _arguments[2].referenceValue);
opItem3DPlaceOn(_arguments[1].referenceValue, _arguments[2].referenceValue);
return nextCommand();
case kItemEnable:
opItemEnable(_arguments[1].referenceValue, _arguments[2].intValue);
return nextCommand();
case kItemPlaceDirection:
opPlaceDirection(_arguments[1].referenceValue, _arguments[2].intValue);
opItemPlaceDirection(_arguments[1].referenceValue, _arguments[2].intValue);
return nextCommand();
default:
// warning("Unimplemented opcode %d", _subType);
@ -64,12 +69,26 @@ Command *Command::execute(uint32 callMode, Script *script) {
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>();
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>();
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>();
item->setDirection(abs(direction) % 360);

View file

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

View file

@ -24,6 +24,7 @@
#include "engines/stark/resources/command.h"
#include "engines/stark/resources/item.h"
#include "engines/stark/services/dialogplayer.h"
#include "engines/stark/services/global.h"
#include "engines/stark/services/services.h"
#include "engines/stark/xrcreader.h"
@ -42,7 +43,8 @@ Script::Script(Resource *parent, byte subType, uint16 index, const Common::Strin
_shouldResetGameSpeed(false),
_enabled(false),
_nextCommand(nullptr),
_pauseTimeLeft(-1) {
_pauseTimeLeft(-1),
_suspendingResource(nullptr) {
_type = TYPE;
}
@ -152,7 +154,7 @@ bool Script::shouldExecute(uint32 callMode) {
}
bool Script::isSuspended() {
return _pauseTimeLeft >= 0;
return _pauseTimeLeft >= 0 || _suspendingResource;
}
void Script::updateSuspended() {
@ -160,11 +162,28 @@ void Script::updateSuspended() {
// Decrease the remaining pause time
Global *global = StarkServices::instance().global;
_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
_pauseTimeLeft = -1;
_nextCommand = _nextCommand->nextCommand();
}
}
@ -173,6 +192,10 @@ void Script::pause(int32 msecs) {
_pauseTimeLeft = msecs;
}
void Script::suspend(Resource *cause) {
_suspendingResource = cause;
}
void Script::execute(uint32 callMode) {
if (!shouldExecute(callMode)) {
return;

View file

@ -82,6 +82,9 @@ public:
/** Pause the script for the specified time */
void pause(int32 msecs);
/** Suspend the script while the specified resource is running */
void suspend(Resource *cause);
protected:
void printData() override;
@ -98,7 +101,9 @@ protected:
bool _enabled;
Command *_nextCommand;
int32 _pauseTimeLeft;
Resource *_suspendingResource;
};
} // 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 {
class Scene;
class Global;
class ArchiveLoader;
class DialogPlayer;
class Global;
class ResourceProvider;
class Scene;
/**
* Public services available as a singleton
@ -42,15 +43,17 @@ class ResourceProvider;
class StarkServices : public Common::Singleton<StarkServices> {
public:
StarkServices() {
global = nullptr;
archiveLoader = nullptr;
dialogPlayer = nullptr;
global = nullptr;
resourceProvider = nullptr;
randomSource = nullptr;
scene = nullptr;
}
Global *global;
ArchiveLoader *archiveLoader;
DialogPlayer *dialogPlayer;
Global *global;
ResourceProvider *resourceProvider;
Common::RandomSource *randomSource;
Scene *scene;

View file

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

View file

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