refactor: Move RoutineManager to game namespace
This commit is contained in:
parent
44a25851f7
commit
d419c059cf
23 changed files with 1955 additions and 1831 deletions
|
@ -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})
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 = "");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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
35
src/game/script/util.h
Normal 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
|
|
@ -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;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "variable.h"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue