STARK: Add support for calling dialogs
This commit is contained in:
parent
c93098e7af
commit
a75de69533
10 changed files with 175 additions and 29 deletions
|
@ -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 \
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
41
engines/stark/services/dialogplayer.cpp
Normal file
41
engines/stark/services/dialogplayer.cpp
Normal 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
|
43
engines/stark/services/dialogplayer.h
Normal file
43
engines/stark/services/dialogplayer.h
Normal 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
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue