refactor: Move RoutineManager to game namespace

This commit is contained in:
Vsevolod Kremianskii 2020-08-10 16:17:00 +07:00
parent 44a25851f7
commit d419c059cf
23 changed files with 1955 additions and 1831 deletions

View file

@ -75,8 +75,9 @@ set(HEADERS
src/game/object/trigger.h
src/game/object/waypoint.h
src/game/room.h
src/game/script/callbacks.h
src/game/script/routines.h
src/game/script/routines_common.h
src/game/script/util.h
src/game/templates.h
src/game/types.h
src/gui/control/button.h
@ -135,7 +136,6 @@ set(HEADERS
src/script/execution.h
src/script/program.h
src/script/routine.h
src/script/routines.h
src/script/types.h
src/script/variable.h)
@ -178,6 +178,7 @@ set(SOURCES
src/game/script/routines_common.cpp
src/game/script/routines_kotor.cpp
src/game/script/routines_tsl.cpp
src/game/script/util.cpp
src/game/templates.cpp
src/gui/control/button.cpp
src/gui/control/control.cpp
@ -232,7 +233,6 @@ set(SOURCES
src/script/execution.cpp
src/script/program.cpp
src/script/routine.cpp
src/script/routines.cpp
src/script/variable.cpp)
add_executable(reone ${HEADERS} ${SOURCES})

View file

@ -38,6 +38,8 @@
#include "object/placeable.h"
#include "object/trigger.h"
#include "object/waypoint.h"
#include "script/routines.h"
#include "script/util.h"
using namespace std;
@ -65,7 +67,7 @@ static const char kPartyLeaderTag[] = "party-leader";
static const char kPartyMember1Tag[] = "party-member-1";
static const char kPartyMember2Tag[] = "party-member-2";
Area::Area(resources::GameVersion version, const string &name) : _version(version), _name(name), _navMesh(new NavMesh()) {
Area::Area(GameVersion version, const string &name) : _version(version), _name(name), _navMesh(new NavMesh()) {
_objects.insert(make_pair(ObjectType::Creature, ObjectList()));
_objects.insert(make_pair(ObjectType::Door, ObjectList()));
_objects.insert(make_pair(ObjectType::Placeable, ObjectList()));
@ -192,10 +194,10 @@ void Area::loadCameraStyle(const GffStruct &are) {
}
void Area::loadScripts(const GffStruct &are) {
_scripts[ScriptType::OnEnter] = ResMan.findScript(are.getString("OnEnter"));
_scripts[ScriptType::OnExit] = ResMan.findScript(are.getString("OnExit"));
_scripts[ScriptType::OnHeartbeat] = ResMan.findScript(are.getString("OnHeartbeat"));
_scripts[ScriptType::OnUserDefined] = ResMan.findScript(are.getString("OnUserDefined"));
_scripts[ScriptType::OnEnter] = are.getString("OnEnter");
_scripts[ScriptType::OnExit] = are.getString("OnExit");
_scripts[ScriptType::OnHeartbeat] = are.getString("OnHeartbeat");
_scripts[ScriptType::OnUserDefined] = are.getString("OnUserDefined");
}
void Area::landObject(Object &object) {
@ -460,27 +462,16 @@ void Area::updateTriggers(const Creature &creature) {
}
}
void Area::delayAction(uint32_t timestamp, const ExecutionContext &ctx) {
DelayedAction action;
action.timestamp = timestamp;
action.context = ctx;
_delayed.push_back(action);
}
void Area::runOnEnterScript() {
if (_scriptsEnabled && _scripts[ScriptType::OnEnter]) {
ExecutionContext ctx;
if (_player) {
ctx.playerId = _player->id();
ctx.enteringObjectId = ctx.playerId;
ctx.delayCommand = [this](uint32_t timestamp, const ExecutionContext &ctx) {
_delayed.push_back(DelayedAction { timestamp, ctx });
};
ctx.getObjectByTag = [this](const string &tag) {
shared_ptr<Object> object(find(tag));
return object ? object->id() : 0;
};
ctx.startDialog = [this](int objectId, const string &resRef) {
shared_ptr<Object> object(find(objectId));
if (object && _onStartDialog) {
_onStartDialog(*object, resRef);
}
};
}
ScriptExecution(_scripts[ScriptType::OnEnter], ctx).run();
if (_scriptsEnabled && !_scripts[ScriptType::OnEnter].empty()) {
runScript(_scripts[ScriptType::OnEnter], kObjectArea, _player->id());
}
}

View file

@ -60,10 +60,13 @@ public:
void update(const UpdateContext &updateCtx, GuiContext &guiCtx);
bool moveCreatureTowards(Creature &creature, const glm::vec3 &point, float dt);
void updateTriggers(const Creature &creature);
void delayAction(uint32_t timestamp, const script::ExecutionContext &ctx);
// Rendering
void initGL();
void render() const;
// Load/save
void saveTo(GameState &state) const;
void loadState(const GameState &state);
@ -94,7 +97,7 @@ public:
void setOnStartDialog(const std::function<void(const Object &, const std::string &)> &fn);
protected:
uint32_t _idCounter { 2 };
uint32_t _idCounter { 1000 };
std::map<ObjectType, ObjectList> _objects;
bool _scriptsEnabled { true };
std::function<void()> _onPlayerChanged;
@ -135,7 +138,7 @@ private:
std::map<RenderListName, render::RenderList> _renderLists;
std::unique_ptr<NavMesh> _navMesh;
DebugMode _debugMode { DebugMode::None };
std::map<ScriptType, std::shared_ptr<script::ScriptProgram>> _scripts;
std::map<ScriptType, std::string> _scripts;
std::list<DelayedAction> _delayed;
// Callbacks

View file

@ -34,6 +34,7 @@ using namespace reone::audio;
using namespace reone::gui;
using namespace reone::render;
using namespace reone::resources;
using namespace reone::script;
namespace fs = boost::filesystem;
@ -55,15 +56,16 @@ int Game::run() {
ResMan.init(_version, _path);
TheAudioPlayer.init(_opts.audio);
initScriptRoutines(_version);
RoutineMan.init(_version, this);
configure();
_renderWindow.show();
runMainLoop();
TheJobExecutor.deinit();
ResMan.deinit();
RoutineMan.deinit();
TheAudioPlayer.deinit();
ResMan.deinit();
_renderWindow.deinit();
return 0;
@ -297,6 +299,26 @@ bool Game::handle(const SDL_Event &event) {
return false;
}
void Game::delayCommand(uint32_t timestamp, const ExecutionContext &ctx) {
_module->area().delayAction(timestamp, ctx);
}
shared_ptr<Object> Game::getObjectByTag(const string &tag) {
return _module->area().find(tag);
}
shared_ptr<Object> Game::getPlayer() {
return _module->area().player();
}
void Game::startDialog(uint32_t objectId, const std::string &resRef) {
std::shared_ptr<Object> object(_module->area().find(objectId));
if (!object) return;
_screen = Screen::Dialog;
_dialogGui->startDialog(*object, resRef);
}
void Game::renderWorld() {
switch (_screen) {
case Screen::InGame:

View file

@ -42,7 +42,7 @@ namespace game {
* @see reone::gui::GUI
* @see reone::render::RenderWindow
*/
class Game : public render::IEventHandler {
class Game : public render::IEventHandler, public IRoutineCallbacks {
public:
Game(
resources::GameVersion version,
@ -55,6 +55,11 @@ public:
bool handle(const SDL_Event &event) override;
void delayCommand(uint32_t timestamp, const script::ExecutionContext &ctx) override;
std::shared_ptr<Object> getObjectByTag(const std::string &tag) override;
std::shared_ptr<Object> getPlayer() override;
void startDialog(uint32_t objectId, const std::string &resRef) override;
protected:
resources::GameVersion _version { resources::GameVersion::KotOR };
Options _opts;

View file

@ -25,6 +25,8 @@
#include "../../resources/resources.h"
#include "../../script/execution.h"
#include "../script/routines.h"
#include "../script/util.h"
#include "../types.h"
using namespace std;
@ -190,8 +192,7 @@ void DialogGui::loadStartEntry() {
}
bool DialogGui::checkCondition(const string &script) {
shared_ptr<ScriptProgram> program(ResMan.findScript(script));
return ScriptExecution(program, ExecutionContext()).run() != 0;
return runScript(script, kObjectInvalid, kObjectInvalid) != 0;
}
void DialogGui::loadCurrentEntry() {
@ -230,7 +231,7 @@ void DialogGui::loadCurrentEntry() {
}
if (!_currentEntry->script.empty()) {
ScriptExecution(ResMan.findScript(_currentEntry->script), ExecutionContext()).run();
runScript(_currentEntry->script, kObjectInvalid, kObjectInvalid);
}
if (replyCount == 0 && _onDialogFinished) {
if (_onSpeakerChanged) {

View file

@ -40,7 +40,11 @@ namespace game {
static const float kDefaultFieldOfView = 75.0f;
Module::Module(const string &name, GameVersion version, const GraphicsOptions &opts) :
Module::Module(
const string &name,
GameVersion version,
const GraphicsOptions &opts
) :
_name(name),
_version(version),
_opts(opts),

View file

@ -27,6 +27,8 @@
#include "area.h"
#include "script/callbacks.h"
namespace reone {
namespace game {
@ -44,7 +46,10 @@ struct ModuleInfo {
*/
class Module : public render::IRenderRoot, public render::IEventHandler {
public:
Module(const std::string &name, resources::GameVersion version, const render::GraphicsOptions &opts);
Module(
const std::string &name,
resources::GameVersion version,
const render::GraphicsOptions &opts);
void load(const resources::GffStruct &ifo);
void loadParty(const PartyConfiguration &party, const std::string &entry = "");

View file

@ -26,8 +26,13 @@ namespace reone {
namespace game {
MultiplayerArea::MultiplayerArea(MultiplayerMode mode, resources::GameVersion version, const string &name, IMultiplayerCallbacks *callbacks) :
Area(version, name), _callbacks(callbacks) {
MultiplayerArea::MultiplayerArea(
MultiplayerMode mode,
resources::GameVersion version,
const string &name,
IMultiplayerCallbacks *mpCallbacks
) :
Area(version, name), _callbacks(mpCallbacks) {
_scriptsEnabled = mode == MultiplayerMode::Server;
}

View file

@ -27,7 +27,11 @@ namespace game {
class MultiplayerArea : public Area {
public:
MultiplayerArea(MultiplayerMode mode, resources::GameVersion version, const std::string &name, IMultiplayerCallbacks *callbacks);
MultiplayerArea(
MultiplayerMode mode,
resources::GameVersion version,
const std::string &name,
IMultiplayerCallbacks *callbacks);
void execute(const Command &cmd);

View file

@ -27,7 +27,12 @@ class IMultiplayerCallbacks;
class MultiplayerModule : public Module {
public:
MultiplayerModule(const std::string &name, MultiplayerMode mode, resources::GameVersion version, const render::GraphicsOptions &opts, IMultiplayerCallbacks *callbacks);
MultiplayerModule(
const std::string &name,
MultiplayerMode mode,
resources::GameVersion version,
const render::GraphicsOptions &opts,
IMultiplayerCallbacks *callbacks);
private:
MultiplayerMode _mode { MultiplayerMode::None };

View file

@ -17,39 +17,28 @@
#pragma once
#include <vector>
#include <memory>
#include <string>
#include "routine.h"
#include "../../script/types.h"
#include "../object/object.h"
namespace reone {
namespace script {
namespace game {
class RoutineManager {
class IRoutineCallbacks {
public:
static RoutineManager &instance();
virtual ~IRoutineCallbacks() {
}
void add(const std::string &name, VariableType retType, const std::vector<VariableType> &argTypes);
void add(
const std::string &name,
VariableType retType,
const std::vector<VariableType> &argTypes,
const std::function<Variable(const std::vector<Variable> &, ExecutionContext &ctx)> &fn);
const Routine &get(int index);
private:
std::vector<Routine> _routines;
RoutineManager() = default;
RoutineManager(const RoutineManager &) = delete;
RoutineManager &operator=(const RoutineManager &) = delete;
virtual void delayCommand(uint32_t timestamp, const script::ExecutionContext &ctx) = 0;
virtual std::shared_ptr<Object> getObjectByTag(const std::string &tag) = 0;
virtual std::shared_ptr<Object> getPlayer() = 0;
virtual void startDialog(uint32_t objectId, const std::string &resRef) = 0;
};
#define RoutineMan RoutineManager::instance()
} // namespace script
} // namespace game
} // namespace reone

View file

@ -17,26 +17,65 @@
#include "routines.h"
#include <cassert>
#include "../../core/log.h"
#include "../game.h"
using namespace std;
using namespace reone::resources;
using namespace reone::script;
namespace reone {
namespace game {
extern void initKotorRoutines();
extern void initTslRoutines();
RoutineManager &RoutineManager::instance() {
static RoutineManager instance;
return instance;
}
void RoutineManager::init(GameVersion version, IRoutineCallbacks *callbacks) {
_callbacks = callbacks;
void initScriptRoutines(GameVersion version) {
switch (version) {
case GameVersion::TheSithLords:
initTslRoutines();
case GameVersion::KotOR:
addKotorRoutines();
break;
default:
initKotorRoutines();
case GameVersion::TheSithLords:
addTslRoutines();
break;
}
}
RoutineManager::~RoutineManager() {
deinit();
}
void RoutineManager::deinit() {
_routines.clear();
}
void RoutineManager::add(const std::string &name, VariableType retType, const std::vector<VariableType> &argTypes) {
_routines.emplace_back(name, retType, argTypes);
}
void RoutineManager::add(
const std::string &name,
VariableType retType,
const std::vector<VariableType> &argTypes,
const std::function<Variable(const std::vector<Variable> &, ExecutionContext &ctx)> &fn) {
_routines.emplace_back(name, retType, argTypes, fn);
}
const Routine &RoutineManager::get(int index) {
assert(index >= 0 && index < _routines.size());
return _routines[index];
}
} // namespace game
} // namespace reone

View file

@ -15,13 +15,66 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <functional>
#include <string>
#include <vector>
#include "../../resources/types.h"
#include "../../script/routine.h"
#include "../../script/types.h"
#include "../../script/variable.h"
#include "callbacks.h"
namespace reone {
namespace game {
void initScriptRoutines(resources::GameVersion version);
class RoutineManager : public script::IRoutineProvider {
public:
static RoutineManager &instance();
void init(resources::GameVersion version, IRoutineCallbacks *callbacks);
void deinit();
const script::Routine &get(int index) override;
private:
IRoutineCallbacks *_callbacks { nullptr };
std::vector<script::Routine> _routines;
RoutineManager() = default;
RoutineManager(const RoutineManager &) = delete;
~RoutineManager();
RoutineManager &operator=(const RoutineManager &) = delete;
void addKotorRoutines();
void addTslRoutines();
void add(const std::string &name, script::VariableType retType, const std::vector<script::VariableType> &argTypes);
void add(
const std::string &name,
script::VariableType retType,
const std::vector<script::VariableType> &argTypes,
const std::function<script::Variable(const std::vector<script::Variable>&, script::ExecutionContext &ctx)> &fn);
script::Variable delayCommand(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable assignCommand(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getEnteringObject(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getIsPC(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getIsObjectValid(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getFirstPC(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getObjectByTag(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getLevelByClass(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getGender(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable actionStartConversation(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
};
#define RoutineMan RoutineManager::instance()
} // namespace game

View file

@ -15,10 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "routines_common.h"
#include <cassert>
#include <cstdint>
#include "routines.h"
#include "SDL2/SDL_timer.h"
@ -30,21 +27,19 @@ namespace reone {
namespace game {
Variable delayCommand(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::delayCommand(const vector<Variable> &args, ExecutionContext &ctx) {
assert(
args.size() == 2 &&
args[0].type == VariableType::Float &&
args[1].type == VariableType::Action);
if (ctx.delayCommand) {
uint32_t timestamp = SDL_GetTicks() + static_cast<int>(args[0].floatValue * 1000.0f);
ctx.delayCommand(timestamp, args[1].context);
}
uint32_t timestamp = SDL_GetTicks() + static_cast<int>(args[0].floatValue * 1000.0f);
_callbacks->delayCommand(timestamp, args[1].context);
return Variable();
}
Variable assignCommand(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::assignCommand(const vector<Variable> &args, ExecutionContext &ctx) {
assert(
args.size() == 2 &&
args[0].type == VariableType::Object &&
@ -52,44 +47,50 @@ Variable assignCommand(const vector<Variable> &args, ExecutionContext &ctx) {
ExecutionContext newCtx(args[1].context);
newCtx.callerId = args[0].objectId;
newCtx.triggererId = kObjectInvalid;
ctx.delayCommand(SDL_GetTicks(), newCtx);
_callbacks->delayCommand(SDL_GetTicks(), move(newCtx));
return Variable();
}
Variable getEnteringObject(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getEnteringObject(const vector<Variable> &args, ExecutionContext &ctx) {
Variable result(VariableType::Object);
result.objectId = ctx.enteringObjectId;
result.objectId = ctx.triggererId;
return move(result);
}
Variable getIsPC(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getIsPC(const vector<Variable> &args, ExecutionContext &ctx) {
assert(!args.empty() && args[0].type == VariableType::Object);
return Variable(args[0].objectId == ctx.playerId);
shared_ptr<Object> player(_callbacks->getPlayer());
return Variable(args[0].objectId == player->id());
}
Variable getIsObjectValid(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getIsObjectValid(const vector<Variable> &args, ExecutionContext &ctx) {
assert(!args.empty() && args[0].type == VariableType::Object);
return Variable(args[0].objectId != kObjectInvalid);
}
Variable getFirstPC(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getFirstPC(const vector<Variable> &args, ExecutionContext &ctx) {
shared_ptr<Object> player(_callbacks->getPlayer());
Variable result(VariableType::Object);
result.objectId = ctx.playerId;
result.objectId = player->id();
return move(result);
}
Variable getObjectByTag(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getObjectByTag(const vector<Variable> &args, ExecutionContext &ctx) {
assert(!args.empty() && args[0].type == VariableType::String);
Variable result(VariableType::Object);
result.objectId = ctx.getObjectByTag ? ctx.getObjectByTag(args[0].strValue) : 0;
result.objectId = _callbacks->getObjectByTag(args[0].strValue)->id();
return move(result);
}
Variable getLevelByClass(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getLevelByClass(const vector<Variable> &args, ExecutionContext &ctx) {
assert(
!args.empty() &&
args[0].type == VariableType::Int &&
@ -103,7 +104,7 @@ Variable getLevelByClass(const vector<Variable> &args, ExecutionContext &ctx) {
return Variable(1);
}
Variable getGender(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::getGender(const vector<Variable> &args, ExecutionContext &ctx) {
assert(!args.empty() && args[0].type == VariableType::Object);
int objectId = args[0].objectId;
@ -111,15 +112,13 @@ Variable getGender(const vector<Variable> &args, ExecutionContext &ctx) {
return Variable();
}
Variable actionStartConversation(const vector<Variable> &args, ExecutionContext &ctx) {
Variable RoutineManager::actionStartConversation(const vector<Variable> &args, ExecutionContext &ctx) {
assert(!args.empty() && args[0].type == VariableType::Object);
int objectId = args[0].objectId;
string resRef(args.size() >= 2 ? args[1].strValue : "");
if (ctx.startDialog) {
ctx.startDialog(objectId, resRef);
}
_callbacks->startDialog(objectId, resRef);
return Variable();
}

View file

@ -1,40 +0,0 @@
/*
* Copyright © 2020 Vsevolod Kremianskii
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*/
#include <vector>
#include "../../script/types.h"
#include "../../script/variable.h"
namespace reone {
namespace game {
script::Variable delayCommand(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable assignCommand(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getEnteringObject(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getIsPC(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getIsObjectValid(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getFirstPC(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getObjectByTag(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getLevelByClass(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable getGender(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
script::Variable actionStartConversation(const std::vector<script::Variable> &args, script::ExecutionContext &ctx);
} // namespace game
} // namespace reone

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,39 +15,35 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "util.h"
#include "../../resources/resources.h"
#include "../../script/execution.h"
#include "../../script/types.h"
#include "routines.h"
#include <cassert>
#include "../core/log.h"
using namespace std;
using namespace reone::resources;
using namespace reone::script;
namespace reone {
namespace script {
namespace game {
RoutineManager &RoutineManager::instance() {
static RoutineManager instance;
return instance;
int runScript(const string &resRef, uint32_t callerId, uint32_t triggererId) {
shared_ptr<ScriptProgram> program(ResMan.findScript(resRef));
return runScript(move(program), callerId, triggererId);
}
void RoutineManager::add(const std::string &name, VariableType retType, const std::vector<VariableType> &argTypes) {
_routines.emplace_back(name, retType, argTypes);
}
int runScript(const std::shared_ptr<ScriptProgram> &program, uint32_t callerId, uint32_t triggererId) {
ExecutionContext ctx;
ctx.routines = &RoutineMan;
ctx.callerId = callerId;
ctx.triggererId = triggererId;
void RoutineManager::add(
const std::string &name,
VariableType retType,
const std::vector<VariableType> &argTypes,
const std::function<Variable(const std::vector<Variable> &, ExecutionContext &ctx)> &fn) {
_routines.emplace_back(name, retType, argTypes, fn);
}
const Routine &RoutineManager::get(int index) {
assert(index >= 0 && index < _routines.size());
return _routines[index];
return ScriptExecution(program, move(ctx)).run();
}
} // namespace game

35
src/game/script/util.h Normal file
View file

@ -0,0 +1,35 @@
/*
* Copyright © 2020 Vsevolod Kremianskii
*
* 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 3 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, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include "../../script/program.h"
namespace reone {
namespace game {
int runScript(const std::string &resRef, uint32_t callerId, uint32_t triggererId);
int runScript(const std::shared_ptr<script::ScriptProgram> &program, uint32_t callerId, uint32_t triggererId);
} // namespace game
} // namespace reone

View file

@ -23,7 +23,7 @@
#include "../core/log.h"
#include "routines.h"
#include "routine.h"
using namespace std;
using namespace std::placeholders;
@ -196,7 +196,7 @@ void ScriptExecution::executePushConstant(const Instruction &ins) {
}
void ScriptExecution::executeCallRoutine(const Instruction &ins) {
const Routine &routine = RoutineMan.get(ins.routine);
const Routine &routine = _context.routines->get(ins.routine);
debug("Script: calling routine " + routine.name());
vector<Variable> args;

View file

@ -17,6 +17,7 @@
#pragma once
#include <functional>
#include <string>
#include "variable.h"

View file

@ -18,7 +18,6 @@
#pragma once
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <vector>
@ -29,9 +28,12 @@ namespace script {
const uint32_t kObjectSelf = 0;
const uint32_t kObjectInvalid = 1;
const uint32_t kObjectModule = 2;
const uint32_t kObjectArea = 3;
class ScriptProgram;
struct Variable;
class ScriptProgram;
class Routine;
struct ExecutionState {
std::shared_ptr<ScriptProgram> program;
@ -40,14 +42,19 @@ struct ExecutionState {
uint32_t insOffset { 0 };
};
class IRoutineProvider {
public:
virtual ~IRoutineProvider() {
}
virtual const Routine &get(int index) = 0;
};
struct ExecutionContext {
IRoutineProvider *routines { nullptr };
std::shared_ptr<ExecutionState> savedState;
uint32_t callerId { 0xffffffff };
uint32_t playerId { 0xffffffff };
uint32_t enteringObjectId { 0xffffffff };
std::function<void(uint32_t, const ExecutionContext &)> delayCommand;
std::function<uint32_t(const std::string &)> getObjectByTag;
std::function<void(int, const std::string &)> startDialog;
uint32_t callerId { kObjectInvalid };
uint32_t triggererId { kObjectInvalid };
};
} // namespace script