Revert to storing object id, not object pointer in scripts

- This is how vanilla does it
- It will supposedly be easier to save delayed actions this way
This commit is contained in:
Vsevolod Kremianskii 2021-04-22 17:49:15 +07:00
parent 533f6cf949
commit 25253405ce
51 changed files with 271 additions and 327 deletions

View file

@ -502,7 +502,7 @@ set(GAME_HEADERS
src/game/d20/skills.h
src/game/savedgame.h
src/game/script/routines.h
src/game/script/runner.h
src/game/script/runutil.h
src/game/soundsets.h
src/game/surface.h
src/game/surfaces.h
@ -631,7 +631,7 @@ set(GAME_SOURCES
src/game/script/routines_time.cpp
src/game/script/routines_tsl.cpp
src/game/script/routines_vars.cpp
src/game/script/runner.cpp
src/game/script/runutil.cpp
src/game/soundsets.cpp
src/game/surfaces.cpp)

View file

@ -162,7 +162,7 @@ void ActionExecutor::executeFollow(const shared_ptr<Object> &actor, FollowAction
void ActionExecutor::executeDoCommand(const shared_ptr<Object> &actor, CommandAction &action, float dt) {
auto context = make_unique<ExecutionContext>(*action.context());
context->caller = actor;
context->callerId = actor ? actor->id() : kObjectInvalid;
shared_ptr<ScriptProgram> program(action.context()->savedState->program);
ScriptExecution(program, move(context)).run();
@ -291,14 +291,14 @@ void ActionExecutor::executeOpenDoor(const shared_ptr<Object> &actor, ObjectActi
if (!isObjectSelf && door->isLocked()) {
string onFailToOpen(door->getOnFailToOpen());
if (!onFailToOpen.empty()) {
_game->scriptRunner().run(onFailToOpen, door->id(), actor->id());
runScript(onFailToOpen, door->id(), actor->id());
}
} else {
door->open(actor);
if (!isObjectSelf) {
string onOpen(door->getOnOpen());
if (!onOpen.empty()) {
_game->scriptRunner().run(onOpen, door->id(), actor->id(), -1);
runScript(onOpen, door->id(), actor->id(), -1);
}
}
}
@ -350,7 +350,7 @@ void ActionExecutor::executeOpenLock(const shared_ptr<Object> &actor, ObjectActi
string onOpen(door->getOnOpen());
if (!onOpen.empty()) {
_game->scriptRunner().run(onOpen, door->id(), actor->id());
runScript(onOpen, door->id(), actor->id());
}
}

View file

@ -79,7 +79,6 @@ Game::Game(const fs::path &path, const Options &opts) :
_worldPipeline(&_sceneGraph, opts.graphics),
_console(this),
_party(this),
_scriptRunner(this),
_profileOverlay(opts.graphics),
_combat(this),
_objectFactory(this, &_sceneGraph) {
@ -397,15 +396,8 @@ shared_ptr<Object> Game::getObjectById(uint32_t id) const {
case kObjectInvalid:
return nullptr;
default:
break;
return _objectFactory.getObjectById(id);
}
if (_module->id() == id) return _module;
auto area = _module->area();
if (area->id() == id) return area;
return area->getObjectById(id);
}
void Game::drawGUI() {

View file

@ -51,7 +51,7 @@
#include "options.h"
#include "party.h"
#include "savedgame.h"
#include "script/runner.h"
#include "script/runutil.h"
#include "types.h"
namespace reone {
@ -108,7 +108,6 @@ public:
Party &party() { return _party; }
CharacterGeneration &characterGeneration() { return *_charGen; }
CameraType cameraType() const { return _cameraType; }
ScriptRunner &scriptRunner() { return _scriptRunner; }
Conversation &conversation() { return *_conversation; }
const std::set<std::string> &moduleNames() const { return _moduleNames; }
Combat &combat() { return _combat; }
@ -201,7 +200,6 @@ private:
scene::WorldRenderPipeline _worldPipeline;
Console _console;
Party _party;
ScriptRunner _scriptRunner;
ProfileOverlay _profileOverlay;
Combat _combat;
GameID _gameId { GameID::KotOR };

View file

@ -372,7 +372,7 @@ void CharacterGeneration::reloadCharacterModel() {
shared_ptr<ModelSceneNode> CharacterGeneration::getCharacterModel(SceneGraph &sceneGraph) {
auto objectFactory = make_unique<ObjectFactory>(_game, &sceneGraph);
unique_ptr<Creature> creature(objectFactory->newCreature());
shared_ptr<Creature> creature(objectFactory->newCreature());
creature->setFacing(-glm::half_pi<float>());
creature->setAppearance(_character.appearance);
creature->equip("g_a_clothes01");

View file

@ -101,7 +101,7 @@ shared_ptr<ModelSceneNode> PortraitSelection::getCharacterModel(SceneGraph &scen
auto objectFactory = make_unique<ObjectFactory>(_game, &sceneGraph);
unique_ptr<Creature> creature(objectFactory->newCreature());
shared_ptr<Creature> creature(objectFactory->newCreature());
creature->setFacing(-glm::half_pi<float>());
creature->setAppearance(getAppearanceFromCurrentPortrait());
creature->equip("g_a_clothes01");

View file

@ -104,7 +104,7 @@ int Conversation::indexOfFirstActive(const vector<Dialog::EntryReplyLink> &links
}
bool Conversation::evaluateCondition(const string &scriptResRef) {
return _game->scriptRunner().run(scriptResRef, _owner->id()) != 0;
return runScript(scriptResRef, _owner->id()) != 0;
}
void Conversation::finish() {
@ -114,7 +114,7 @@ void Conversation::finish() {
// Run EndConversation script
if (!_dialog->endScript().empty()) {
_game->scriptRunner().run(_dialog->endScript(), _owner->id());
runScript(_dialog->endScript(), _owner->id());
}
}
@ -146,7 +146,7 @@ void Conversation::loadEntry(int index, bool start) {
// Run entry script
if (!_currentEntry->script.empty()) {
_game->scriptRunner().run(_currentEntry->script, _owner->id());
runScript(_currentEntry->script, _owner->id());
}
}
@ -244,7 +244,7 @@ void Conversation::pickReply(int index) {
// Run reply script
if (!reply.script.empty()) {
_game->scriptRunner().run(reply.script, _owner->id());
runScript(reply.script, _owner->id());
}
int entryIdx = indexOfFirstActive(reply.entries);

View file

@ -146,7 +146,7 @@ void PartySelection::onClick(const string &control) {
_game->openInGame();
if (!_context.exitScript.empty()) {
_game->scriptRunner().run(_context.exitScript);
runScript(_context.exitScript);
}
} else if (boost::starts_with(control, "BTN_NPC")) {
onNpcButtonClick(control);

View file

@ -265,7 +265,6 @@ bool Area::getCreatureObstacle(const Creature &creature, const glm::vec3 &dest)
void Area::add(const shared_ptr<SpatialObject> &object) {
_objects.push_back(object);
_objectsByType[object->type()].push_back(object);
_objectById[object->id()] = object;
_objectsByTag[object->tag()].push_back(object);
determineObjectRoom(*object);
@ -288,7 +287,7 @@ void Area::doDestroyObjects() {
}
void Area::doDestroyObject(uint32_t objectId) {
shared_ptr<SpatialObject> object(getObjectById(objectId));
shared_ptr<SpatialObject> object(dynamic_pointer_cast<SpatialObject>(_game->objectFactory().getObjectById(objectId)));
if (!object) return;
{
Room *room = object->room();
@ -308,7 +307,6 @@ void Area::doDestroyObject(uint32_t objectId) {
_objects.erase(maybeObject);
}
}
_objectById.erase(objectId);
{
auto maybeTagObjects = _objectsByTag.find(object->tag());
if (maybeTagObjects != _objectsByTag.end()) {
@ -331,11 +329,8 @@ void Area::doDestroyObject(uint32_t objectId) {
}
}
shared_ptr<SpatialObject> Area::getObjectById(uint32_t id) const {
auto object = _objectById.find(id);
if (object == _objectById.end()) return nullptr;
return object->second;
ObjectList &Area::getObjectsByType(ObjectType type) {
return _objectsByType.find(type)->second;
}
shared_ptr<SpatialObject> Area::getObjectByTag(const string &tag, int nth) const {
@ -346,10 +341,6 @@ shared_ptr<SpatialObject> Area::getObjectByTag(const string &tag, int nth) const
return objects->second[nth];
}
ObjectList &Area::getObjectsByType(ObjectType type) {
return _objectsByType.find(type)->second;
}
void Area::landObject(SpatialObject &object) {
glm::vec3 position(object.position());
Room *room = nullptr;
@ -585,7 +576,7 @@ void Area::runOnEnterScript() {
auto player = _game->party().player();
if (!player) return;
_game->scriptRunner().run(_onEnter, _id, player->id());
runScript(_onEnter, _id, player->id());
}
void Area::runOnExitScript() {
@ -594,7 +585,7 @@ void Area::runOnExitScript() {
auto player = _game->party().player();
if (!player) return;
_game->scriptRunner().run(_onExit, _id, player->id());
runScript(_onExit, _id, player->id());
}
shared_ptr<SpatialObject> Area::getObjectAt(int x, int y) const {
@ -896,7 +887,7 @@ void Area::checkTriggersIntersection(const shared_ptr<SpatialObject> &triggerrer
return;
}
if (!trigger->getOnEnter().empty()) {
_game->scriptRunner().run(trigger->getOnEnter(), trigger->id(), triggerrer->id());
runScript(trigger->getOnEnter(), trigger->id(), triggerrer->id());
}
}
}
@ -904,12 +895,12 @@ void Area::checkTriggersIntersection(const shared_ptr<SpatialObject> &triggerrer
void Area::updateHeartbeat(float dt) {
if (_heartbeatTimer.advance(dt)) {
if (!_onHeartbeat.empty()) {
_game->scriptRunner().run(_onHeartbeat, _id);
runScript(_onHeartbeat, _id);
}
for (auto &object : _objects) {
string heartbeat(object->getOnHeartbeat());
if (!heartbeat.empty()) {
_game->scriptRunner().run(heartbeat, object->id());
runScript(heartbeat, object->id());
}
}
_heartbeatTimer.reset(kHeartbeatInterval);

View file

@ -41,7 +41,7 @@
#include "../objectselect.h"
#include "../pathfinder.h"
#include "../perception.h"
#include "../script/runner.h"
#include "../script/runutil.h"
#include "../types.h"
#include "object.h"
@ -108,10 +108,8 @@ public:
std::shared_ptr<Object> createObject(ObjectType type, const std::string &blueprintResRef, const std::shared_ptr<Location> &location);
std::shared_ptr<SpatialObject> getObjectById(uint32_t id) const;
std::shared_ptr<SpatialObject> getObjectByTag(const std::string &tag, int nth = 0) const;
ObjectList &getObjectsByType(ObjectType type);
std::shared_ptr<SpatialObject> getObjectByTag(const std::string &tag, int nth = 0) const;
/**
* Find the nth nearest object for which the specified predicate returns true.
@ -220,7 +218,6 @@ private:
ObjectList _objects;
std::unordered_map<ObjectType, ObjectList> _objectsByType;
std::unordered_map<uint32_t, std::shared_ptr<SpatialObject>> _objectById;
std::unordered_map<std::string, ObjectList> _objectsByTag;
std::set<uint32_t> _objectsToDestroy;

View file

@ -59,10 +59,9 @@ static string g_talkDummyNode("talkdummy");
Creature::Creature(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(id, ObjectType::Creature, objectFactory, sceneGraph, scriptRunner) {
SpatialObject(id, ObjectType::Creature, objectFactory, sceneGraph) {
_drawDistance = 32.0f;
}
@ -448,13 +447,13 @@ int Creature::getNeededXP() const {
void Creature::runSpawnScript() {
if (!_onSpawn.empty()) {
_scriptRunner->run(_onSpawn, _id, kObjectInvalid);
runScript(_onSpawn, _id, kObjectInvalid);
}
}
void Creature::runEndRoundScript() {
if (!_onEndRound.empty()) {
_scriptRunner->run(_onEndRound, _id, kObjectInvalid);
runScript(_onEndRound, _id, kObjectInvalid);
}
}
@ -486,7 +485,7 @@ void Creature::die() {
void Creature::runDeathScript() {
if (!_onDeath.empty()) {
_scriptRunner->run(_onDeath, _id, kObjectInvalid);
runScript(_onDeath, _id, kObjectInvalid);
}
}
@ -542,7 +541,7 @@ void Creature::onObjectSeen(const shared_ptr<SpatialObject> &object) {
void Creature::runOnNoticeScript() {
if (!_onNotice.empty()) {
_scriptRunner->run(_onNotice, _id, _perception.lastPerceived->id());
runScript(_onNotice, _id, _perception.lastPerceived->id());
}
}

View file

@ -87,8 +87,7 @@ public:
Creature(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);
void loadFromBlueprint(const std::string &resRef);

View file

@ -42,10 +42,9 @@ namespace game {
Door::Door(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(id, ObjectType::Door, objectFactory, sceneGraph, scriptRunner) {
SpatialObject(id, ObjectType::Door, objectFactory, sceneGraph) {
_drawDistance = FLT_MAX;
}

View file

@ -30,8 +30,7 @@ public:
Door(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);
void loadFromBlueprint(const std::string &resRef);

View file

@ -33,14 +33,9 @@ namespace game {
Encounter::Encounter(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
) : SpatialObject(
id,
ObjectType::Encounter,
objectFactory,
sceneGraph,
scriptRunner) {
SceneGraph *sceneGraph
) :
SpatialObject(id, ObjectType::Encounter, objectFactory, sceneGraph) {
}
void Encounter::loadFromGIT(const GffStruct &gffs) {

View file

@ -30,8 +30,7 @@ public:
Encounter(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);

View file

@ -17,12 +17,10 @@
#include "objectfactory.h"
#include "../game.h"
#include "../../common/collectionutil.h"
using namespace std;
using namespace reone::render;
using namespace reone::resource;
using namespace reone::scene;
namespace reone {
@ -40,48 +38,52 @@ ObjectFactory::ObjectFactory(Game *game, SceneGraph *sceneGraph) :
}
}
unique_ptr<Module> ObjectFactory::newModule() {
return make_unique<Module>(_counter++, _game);
shared_ptr<Module> ObjectFactory::newModule() {
return newObject<Module>(_game);
}
unique_ptr<Area> ObjectFactory::newArea() {
return make_unique<Area>(_counter++, _game);
shared_ptr<Area> ObjectFactory::newArea() {
return newObject<Area>(_game);
}
unique_ptr<Creature> ObjectFactory::newCreature() {
return make_unique<Creature>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Creature> ObjectFactory::newCreature() {
return newObject<Creature>(this, _sceneGraph);
}
unique_ptr<Placeable> ObjectFactory::newPlaceable() {
return make_unique<Placeable>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Placeable> ObjectFactory::newPlaceable() {
return newObject<Placeable>(this, _sceneGraph);
}
unique_ptr<Door> ObjectFactory::newDoor() {
return make_unique<Door>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Door> ObjectFactory::newDoor() {
return newObject<Door>(this, _sceneGraph);
}
unique_ptr<Waypoint> ObjectFactory::newWaypoint() {
return make_unique<Waypoint>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Waypoint> ObjectFactory::newWaypoint() {
return newObject<Waypoint>(this, _sceneGraph);
}
unique_ptr<Trigger> ObjectFactory::newTrigger() {
return make_unique<Trigger>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Trigger> ObjectFactory::newTrigger() {
return newObject<Trigger>(this, _sceneGraph);
}
unique_ptr<Item> ObjectFactory::newItem() {
return make_unique<Item>(_counter++);
shared_ptr<Item> ObjectFactory::newItem() {
return newObject<Item>();
}
unique_ptr<Sound> ObjectFactory::newSound() {
return make_unique<Sound>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Sound> ObjectFactory::newSound() {
return newObject<Sound>(this, _sceneGraph);
}
unique_ptr<PlaceableCamera> ObjectFactory::newCamera() {
return make_unique<PlaceableCamera>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<PlaceableCamera> ObjectFactory::newCamera() {
return newObject<PlaceableCamera>(this, _sceneGraph);
}
unique_ptr<Encounter> ObjectFactory::newEncounter() {
return make_unique<Encounter>(_counter++, this, _sceneGraph, &_game->scriptRunner());
shared_ptr<Encounter> ObjectFactory::newEncounter() {
return newObject<Encounter>(this, _sceneGraph);
}
shared_ptr<Object> ObjectFactory::getObjectById(uint32_t id) const {
return getFromLookupOrNull(_objectById, id);
}
} // namespace game

View file

@ -19,6 +19,7 @@
#include <cstdint>
#include <memory>
#include <unordered_map>
#include <boost/noncopyable.hpp>
@ -49,23 +50,34 @@ class ObjectFactory {
public:
ObjectFactory(Game *game, scene::SceneGraph *sceneGraph);
std::unique_ptr<Module> newModule();
std::unique_ptr<Area> newArea();
std::unique_ptr<Creature> newCreature();
std::unique_ptr<Placeable> newPlaceable();
std::unique_ptr<Door> newDoor();
std::unique_ptr<Waypoint> newWaypoint();
std::unique_ptr<Trigger> newTrigger();
std::unique_ptr<Item> newItem();
std::unique_ptr<Sound> newSound();
std::unique_ptr<PlaceableCamera> newCamera();
std::unique_ptr<Encounter> newEncounter();
std::shared_ptr<Module> newModule();
std::shared_ptr<Area> newArea();
std::shared_ptr<Creature> newCreature();
std::shared_ptr<Placeable> newPlaceable();
std::shared_ptr<Door> newDoor();
std::shared_ptr<Waypoint> newWaypoint();
std::shared_ptr<Trigger> newTrigger();
std::shared_ptr<Item> newItem();
std::shared_ptr<Sound> newSound();
std::shared_ptr<PlaceableCamera> newCamera();
std::shared_ptr<Encounter> newEncounter();
std::shared_ptr<Object> getObjectById(uint32_t id) const;
private:
Game *_game;
scene::SceneGraph *_sceneGraph;
uint32_t _counter { 2 }; // ids 0 and 1 are reserved
std::unordered_map<uint32_t, std::shared_ptr<Object>> _objectById;
template <class T, class ...Args>
std::shared_ptr<T> newObject(Args &&... args) {
uint32_t id = _counter++;
std::shared_ptr<T> object(std::make_shared<T>(id, std::forward<Args>(args)...));
_objectById.insert(std::make_pair(id, object));
return move(object);
}
};
} // namespace game

View file

@ -25,7 +25,7 @@
#include "../../scene/node/modelscenenode.h"
#include "../../script/types.h"
#include "../script/runner.h"
#include "../script/runutil.h"
using namespace std;
@ -41,10 +41,9 @@ namespace game {
Placeable::Placeable(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(id, ObjectType::Placeable, objectFactory, sceneGraph, scriptRunner) {
SpatialObject(id, ObjectType::Placeable, objectFactory, sceneGraph) {
_drawDistance = 64.0f;
}
@ -91,13 +90,13 @@ shared_ptr<Walkmesh> Placeable::getWalkmesh() const {
void Placeable::runOnUsed(shared_ptr<SpatialObject> usedBy) {
if (!_onUsed.empty()) {
_scriptRunner->run(_onUsed, _id, usedBy ? usedBy->id() : kObjectInvalid);
runScript(_onUsed, _id, usedBy ? usedBy->id() : kObjectInvalid);
}
}
void Placeable::runOnInvDisturbed(shared_ptr<SpatialObject> triggerrer) {
if (!_onInvDisturbed.empty()) {
_scriptRunner->run(_onInvDisturbed, _id, triggerrer ? triggerrer->id() : kObjectInvalid);
runScript(_onInvDisturbed, _id, triggerrer ? triggerrer->id() : kObjectInvalid);
}
}

View file

@ -34,8 +34,7 @@ public:
Placeable(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);
void loadFromBlueprint(const std::string &resRef);

View file

@ -31,15 +31,13 @@ namespace game {
PlaceableCamera::PlaceableCamera(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(
id,
ObjectType::Camera,
objectFactory,
sceneGraph,
scriptRunner) {
sceneGraph) {
}
void PlaceableCamera::loadFromGIT(const GffStruct &gffs) {

View file

@ -32,8 +32,7 @@ public:
PlaceableCamera(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);

View file

@ -38,15 +38,13 @@ namespace game {
Sound::Sound(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(
id,
ObjectType::Sound,
objectFactory,
sceneGraph,
scriptRunner) {
sceneGraph) {
}
void Sound::loadFromGIT(const GffStruct &gffs) {

View file

@ -31,8 +31,7 @@ public:
Sound(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);
void loadFromBlueprint(const std::string &resRef);

View file

@ -37,13 +37,11 @@ SpatialObject::SpatialObject(
uint32_t id,
ObjectType type,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
Object(id, type),
_objectFactory(objectFactory),
_sceneGraph(sceneGraph),
_scriptRunner(scriptRunner) {
_sceneGraph(sceneGraph) {
}
shared_ptr<Item> SpatialObject::addItem(const string &resRef, int stackSize, bool dropable) {

View file

@ -42,7 +42,6 @@ constexpr float kDefaultDrawDistance = 1024.0f;
class Item;
class ObjectFactory;
class Room;
class ScriptRunner;
class SpatialObject : public Object {
public:
@ -139,7 +138,6 @@ protected:
ObjectFactory *_objectFactory;
scene::SceneGraph *_sceneGraph;
ScriptRunner *_scriptRunner;
glm::vec3 _position { 0.0f };
glm::quat _orientation { 1.0f, 0.0f, 0.0f, 0.0f };
glm::mat4 _transform { 1.0f };
@ -156,8 +154,7 @@ protected:
uint32_t id,
ObjectType type,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
virtual void updateTransform();

View file

@ -25,7 +25,7 @@
#include "../../resource/resources.h"
#include "../../resource/strings.h"
#include "../script/runner.h"
#include "../script/runutil.h"
using namespace std;
@ -40,15 +40,13 @@ namespace game {
Trigger::Trigger(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(
id,
ObjectType::Trigger,
objectFactory,
sceneGraph,
scriptRunner) {
sceneGraph) {
}
void Trigger::loadFromGIT(const GffStruct &gffs) {
@ -103,7 +101,7 @@ void Trigger::update(float dt) {
for (auto &tenant : tenantsToRemove) {
_tenants.erase(tenant);
if (!_onExit.empty()) {
_scriptRunner->run(_onExit, _id, tenant->id());
runScript(_onExit, _id, tenant->id());
}
}
}

View file

@ -32,8 +32,7 @@ public:
Trigger(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);
void loadFromBlueprint(const std::string &resRef);

View file

@ -37,15 +37,13 @@ namespace game {
Waypoint::Waypoint(
uint32_t id,
ObjectFactory *objectFactory,
SceneGraph *sceneGraph,
ScriptRunner *scriptRunner
SceneGraph *sceneGraph
) :
SpatialObject(
id,
ObjectType::Waypoint,
objectFactory,
sceneGraph,
scriptRunner) {
sceneGraph) {
}
void Waypoint::loadFromGIT(const GffStruct &gffs) {

View file

@ -30,8 +30,7 @@ public:
Waypoint(
uint32_t id,
ObjectFactory *objectFactory,
scene::SceneGraph *sceneGraph,
ScriptRunner *scriptRunner);
scene::SceneGraph *sceneGraph);
void loadFromGIT(const resource::GffStruct &gffs);
void loadFromBlueprint(const std::string &resRef);

View file

@ -92,55 +92,63 @@ glm::vec3 Routines::getVector(const VariablesList &args, int index, glm::vec3 de
}
shared_ptr<Object> Routines::getCaller(ExecutionContext &ctx) const {
return static_pointer_cast<Object>(ctx.caller);
return _game->getObjectById(ctx.callerId);
}
shared_ptr<SpatialObject> Routines::getCallerAsSpatial(ExecutionContext &ctx) const {
return dynamic_pointer_cast<SpatialObject>(ctx.caller);
return dynamic_pointer_cast<SpatialObject>(getCaller(ctx));
}
shared_ptr<Creature> Routines::getCallerAsCreature(ExecutionContext &ctx) const {
return dynamic_pointer_cast<Creature>(ctx.caller);
return dynamic_pointer_cast<Creature>(getCaller(ctx));
}
shared_ptr<Object> Routines::getTriggerrer(ExecutionContext &ctx) const {
return static_pointer_cast<Object>(ctx.triggerer);
return _game->getObjectById(ctx.triggererId);
}
shared_ptr<Object> Routines::getObject(const VariablesList &args, int index) const {
return static_pointer_cast<Object>(isOutOfRange(args, index) ? nullptr : args[index].object);
shared_ptr<Object> Routines::getObject(const VariablesList &args, int index, ExecutionContext &ctx) const {
uint32_t objectId = isOutOfRange(args, index) ? kObjectInvalid : args[index].objectId;
if (objectId == kObjectSelf) {
objectId = ctx.callerId;
}
return _game->getObjectById(objectId);
}
shared_ptr<Object> Routines::getObjectOrCaller(const VariablesList &args, int index, ExecutionContext &ctx) const {
return static_pointer_cast<Object>(isOutOfRange(args, index) ? ctx.caller : args[index].object);
uint32_t objectId = isOutOfRange(args, index) ? kObjectSelf : args[index].objectId;
if (objectId == kObjectSelf) {
objectId = ctx.callerId;
}
return _game->getObjectById(objectId);
}
shared_ptr<SpatialObject> Routines::getSpatialObject(const VariablesList &args, int index) const {
return dynamic_pointer_cast<SpatialObject>(isOutOfRange(args, index) ? nullptr : args[index].object);
shared_ptr<SpatialObject> Routines::getSpatialObject(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<SpatialObject>(getObject(args, index, ctx));
}
shared_ptr<SpatialObject> Routines::getSpatialObjectOrCaller(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<SpatialObject>(isOutOfRange(args, index) ? ctx.caller : args[index].object);
return dynamic_pointer_cast<SpatialObject>(getObjectOrCaller(args, index, ctx));
}
shared_ptr<Creature> Routines::getCreature(const VariablesList &args, int index) const {
return dynamic_pointer_cast<Creature>(isOutOfRange(args, index) ? nullptr : args[index].object);
shared_ptr<Creature> Routines::getCreature(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<Creature>(getObject(args, index, ctx));
}
shared_ptr<Creature> Routines::getCreatureOrCaller(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<Creature>(isOutOfRange(args, index) ? ctx.caller : args[index].object);
return dynamic_pointer_cast<Creature>(getObjectOrCaller(args, index, ctx));
}
shared_ptr<Door> Routines::getDoor(const VariablesList &args, int index) const {
return dynamic_pointer_cast<Door>(isOutOfRange(args, index) ? nullptr : args[index].object);
shared_ptr<Door> Routines::getDoor(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<Door>(getObject(args, index, ctx));
}
shared_ptr<Item> Routines::getItem(const VariablesList &args, int index) const {
return dynamic_pointer_cast<Item>(isOutOfRange(args, index) ? nullptr : args[index].object);
shared_ptr<Item> Routines::getItem(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<Item>(getObject(args, index, ctx));
}
shared_ptr<Sound> Routines::getSound(const VariablesList &args, int index) const {
return dynamic_pointer_cast<Sound>(isOutOfRange(args, index) ? nullptr : args[index].object);
shared_ptr<Sound> Routines::getSound(const VariablesList &args, int index, ExecutionContext &ctx) const {
return dynamic_pointer_cast<Sound>(getObject(args, index, ctx));
}
shared_ptr<Effect> Routines::getEffect(const VariablesList &args, int index) const {

View file

@ -94,15 +94,15 @@ private:
std::shared_ptr<SpatialObject> getCallerAsSpatial(script::ExecutionContext &ctx) const;
std::shared_ptr<Creature> getCallerAsCreature(script::ExecutionContext &ctx) const;
std::shared_ptr<Object> getTriggerrer(script::ExecutionContext &ctx) const;
std::shared_ptr<Object> getObject(const VariablesList &args, int index) const;
std::shared_ptr<Object> getObject(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Object> getObjectOrCaller(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<SpatialObject> getSpatialObject(const VariablesList &args, int index) const;
std::shared_ptr<SpatialObject> getSpatialObject(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<SpatialObject> getSpatialObjectOrCaller(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Creature> getCreature(const VariablesList &args, int index) const;
std::shared_ptr<Creature> getCreature(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Creature> getCreatureOrCaller(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Door> getDoor(const VariablesList &args, int index) const;
std::shared_ptr<Item> getItem(const VariablesList &args, int index) const;
std::shared_ptr<Sound> getSound(const VariablesList &args, int index) const;
std::shared_ptr<Door> getDoor(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Item> getItem(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Sound> getSound(const VariablesList &args, int index, script::ExecutionContext &ctx) const;
std::shared_ptr<Effect> getEffect(const VariablesList &args, int index) const;
std::shared_ptr<Event> getEvent(const VariablesList &args, int index) const;

View file

@ -52,7 +52,7 @@ Variable Routines::delayCommand(const VariablesList &args, ExecutionContext &ctx
}
Variable Routines::assignCommand(const VariablesList &args, ExecutionContext &ctx) {
auto subject = getObject(args, 0);
auto subject = getObject(args, 0, ctx);
auto action = getAction(args, 1);
if (subject) {
@ -68,14 +68,14 @@ Variable Routines::assignCommand(const VariablesList &args, ExecutionContext &ct
Variable Routines::actionDoCommand(const VariablesList &args, ExecutionContext &ctx) {
auto action = getAction(args, 0);
auto objectAction = make_unique<CommandAction>(move(action));
getCaller(ctx)->actionQueue().add(move(objectAction));
auto commandAction = make_unique<CommandAction>(move(action));
getCaller(ctx)->actionQueue().add(move(commandAction));
return Variable();
}
Variable Routines::actionMoveToObject(const VariablesList &args, ExecutionContext &ctx) {
auto moveTo = getObject(args, 0);
auto moveTo = getObject(args, 0, ctx);
bool run = getBool(args, 1, false);
float range = getFloat(args, 2, 1.0f);
@ -91,7 +91,7 @@ Variable Routines::actionMoveToObject(const VariablesList &args, ExecutionContex
Variable Routines::actionStartConversation(const VariablesList &args, ExecutionContext &ctx) {
// TODO: figure out all arguments
auto objectToConverse = getObject(args, 0);
auto objectToConverse = getObject(args, 0, ctx);
string dialogResRef(getString(args, 1, ""));
bool ignoreStartRange = getBool(args, 4, false);
@ -122,7 +122,7 @@ Variable Routines::actionResumeConversation(const VariablesList &args, Execution
}
Variable Routines::actionOpenDoor(const VariablesList &args, ExecutionContext &ctx) {
auto door = getObject(args, 0);
auto door = getObject(args, 0, ctx);
if (door) {
auto action = make_unique<ObjectAction>(ActionType::OpenDoor, door);
getCaller(ctx)->actionQueue().add(move(action));
@ -133,7 +133,7 @@ Variable Routines::actionOpenDoor(const VariablesList &args, ExecutionContext &c
}
Variable Routines::actionCloseDoor(const VariablesList &args, ExecutionContext &ctx) {
auto door = getObject(args, 0);
auto door = getObject(args, 0, ctx);
if (door) {
auto action = make_unique<ObjectAction>(ActionType::CloseDoor, door);
getCaller(ctx)->actionQueue().add(move(action));
@ -150,7 +150,7 @@ Variable Routines::clearAllActions(const VariablesList &args, ExecutionContext &
Variable Routines::actionJumpToObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto jumpTo = getObject(args, 0);
auto jumpTo = getObject(args, 0, ctx);
bool walkStraightLine = getBool(args, 1, true);
if (jumpTo) {
@ -176,7 +176,7 @@ Variable Routines::actionJumpToLocation(const VariablesList &args, ExecutionCont
Variable Routines::actionForceMoveToObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto moveTo = getObject(args, 0);
auto moveTo = getObject(args, 0, ctx);
bool run = getBool(args, 1, false);
float range = getFloat(args, 2, 1.0f);
float timeout = getFloat(args, 3, 30.0f);
@ -209,7 +209,7 @@ Variable Routines::actionForceMoveToLocation(const VariablesList &args, Executio
Variable Routines::jumpToObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto jumpTo = getObject(args, 0);
auto jumpTo = getObject(args, 0, ctx);
bool walkStraightLine = getBool(args, 1, true);
if (jumpTo) {
@ -255,7 +255,7 @@ Variable Routines::actionMoveToLocation(const VariablesList &args, ExecutionCont
Variable Routines::actionMoveAwayFromObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto fleeFrom = getObject(args, 0);
auto fleeFrom = getObject(args, 0, ctx);
bool run = getBool(args, 1, false);
float range = getFloat(args, 2, 40.0f);
@ -271,7 +271,7 @@ Variable Routines::actionMoveAwayFromObject(const VariablesList &args, Execution
Variable Routines::actionEquipItem(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
int inventorySlot = getInt(args, 1);
bool instant = getBool(args, 2, false);
@ -287,7 +287,7 @@ Variable Routines::actionEquipItem(const VariablesList &args, ExecutionContext &
Variable Routines::actionUnequipItem(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
bool instant = getBool(args, 1, false);
if (item) {
@ -302,7 +302,7 @@ Variable Routines::actionUnequipItem(const VariablesList &args, ExecutionContext
Variable Routines::actionPickUpItem(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
if (item) {
auto action = make_unique<Action>(ActionType::PickUpItem);
getCaller(ctx)->actionQueue().add(move(action));
@ -314,7 +314,7 @@ Variable Routines::actionPickUpItem(const VariablesList &args, ExecutionContext
Variable Routines::actionPutDownItem(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
if (item) {
auto action = make_unique<Action>(ActionType::DropItem);
getCaller(ctx)->actionQueue().add(move(action));
@ -327,7 +327,7 @@ Variable Routines::actionPutDownItem(const VariablesList &args, ExecutionContext
Variable Routines::actionAttack(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto caller = getCallerAsCreature(ctx);
auto attackee = getSpatialObject(args, 0);
auto attackee = getSpatialObject(args, 0, ctx);
bool passive = getBool(args, 1, false);
if (caller && attackee) {
@ -367,7 +367,7 @@ Variable Routines::actionPlayAnimation(const VariablesList &args, ExecutionConte
Variable Routines::actionCastSpellAtObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto spell = getEnum<ForcePower>(args, 0);
auto target = getObject(args, 1);
auto target = getObject(args, 1, ctx);
int metaMagic = getInt(args, 2, 0);
bool cheat = getBool(args, 3, false);
int domainLevel = getInt(args, 4, 0);
@ -382,8 +382,8 @@ Variable Routines::actionCastSpellAtObject(const VariablesList &args, ExecutionC
Variable Routines::actionGiveItem(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto item = getItem(args, 0);
auto giveTo = getObject(args, 1);
auto item = getItem(args, 0, ctx);
auto giveTo = getObject(args, 1, ctx);
if (item && giveTo) {
auto action = make_unique<Action>(ActionType::GiveItem);
@ -399,8 +399,8 @@ Variable Routines::actionGiveItem(const VariablesList &args, ExecutionContext &c
Variable Routines::actionTakeItem(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto item = getItem(args, 0);
auto takeFrom = getObject(args, 1);
auto item = getItem(args, 0, ctx);
auto takeFrom = getObject(args, 1, ctx);
if (item && takeFrom) {
auto action = make_unique<Action>(ActionType::TakeItem);
@ -416,7 +416,7 @@ Variable Routines::actionTakeItem(const VariablesList &args, ExecutionContext &c
Variable Routines::actionForceFollowObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto follow = getObject(args, 0);
auto follow = getObject(args, 0, ctx);
float followDistance = getFloat(args, 1, 0.0f);
if (follow) {
@ -471,7 +471,7 @@ Variable Routines::actionSpeakStringByStrRef(const VariablesList &args, Executio
Variable Routines::actionUseFeat(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto feat = getEnum<Feat>(args, 0);
auto target = getObject(args, 1);
auto target = getObject(args, 1, ctx);
if (target) {
auto action = make_unique<Action>(ActionType::UseFeat);
@ -486,9 +486,9 @@ Variable Routines::actionUseFeat(const VariablesList &args, ExecutionContext &ct
Variable Routines::actionUseSkill(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto skill = getEnum<Skill>(args, 0);
auto target = getObject(args, 1);
auto target = getObject(args, 1, ctx);
int subSkill = getInt(args, 2, 0);
auto itemUsed = getObject(args, 3);
auto itemUsed = getObject(args, 3, ctx);
if (target) {
auto action = make_unique<Action>(ActionType::UseSkill);
@ -503,7 +503,7 @@ Variable Routines::actionUseSkill(const VariablesList &args, ExecutionContext &c
Variable Routines::actionUseTalentOnObject(const VariablesList &args, ExecutionContext &ctx) {
// TODO: pass all arguments to an action
auto chosenTalen = getTalent(args, 0);
auto target = getObject(args, 1);
auto target = getObject(args, 1, ctx);
if (target) {
auto action = make_unique<Action>(ActionType::UseTalentOnObject);

View file

@ -38,7 +38,7 @@ namespace game {
Variable Routines::getNPCAIStyle(const VariablesList &args, ExecutionContext &ctx) {
auto result = NPCAIStyle::DefaultAttack;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->aiStyle();
} else {
@ -49,7 +49,7 @@ Variable Routines::getNPCAIStyle(const VariablesList &args, ExecutionContext &ct
}
Variable Routines::setNPCAIStyle(const VariablesList &args, ExecutionContext &ctx) {
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
auto style = getEnum<NPCAIStyle>(args, 1);
if (creature) {

View file

@ -103,11 +103,11 @@ Variable Routines::shipBuild(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::executeScript(const VariablesList &args, ExecutionContext &ctx) {
string script(getString(args, 0));
auto target = getObject(args, 1);
auto target = getObject(args, 1, ctx);
int scriptVar = getInt(args, 2, -1);
if (target) {
_game->scriptRunner().run(script, target->id(), kObjectInvalid, kObjectInvalid, scriptVar);
runScript(script, target->id(), kObjectInvalid, kObjectInvalid, scriptVar);
} else {
debug("Script: executeScript: target is invalid", 1, DebugChannels::script);
}
@ -167,7 +167,7 @@ Variable Routines::printInteger(const VariablesList &args, ExecutionContext &ctx
}
Variable Routines::printObject(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
info(to_string(object->id()));
return Variable();
}

View file

@ -137,7 +137,7 @@ Variable Routines::d100(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getGender(const VariablesList &args, ExecutionContext &ctx) {
auto result = Gender::None;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->gender();
} else {
@ -150,7 +150,7 @@ Variable Routines::getGender(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getHitDice(const VariablesList &args, ExecutionContext &ctx) {
int result = 0;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->attributes().getAggregateLevel();
} else {
@ -231,7 +231,7 @@ Variable Routines::getMaxHitPoints(const VariablesList &args, ExecutionContext &
Variable Routines::getMinOneHP(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
if (object) {
result = object->isMinOneHP();
} else {
@ -242,7 +242,7 @@ Variable Routines::getMinOneHP(const VariablesList &args, ExecutionContext &ctx)
}
Variable Routines::setMaxHitPoints(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
int maxHP = getInt(args, 1);
if (object) {
@ -254,7 +254,7 @@ Variable Routines::setMaxHitPoints(const VariablesList &args, ExecutionContext &
}
Variable Routines::setMinOneHP(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
bool minOneHP = getBool(args, 1);
if (object) {
@ -268,7 +268,7 @@ Variable Routines::setMinOneHP(const VariablesList &args, ExecutionContext &ctx)
Variable Routines::getAbilityScore(const VariablesList &args, ExecutionContext &ctx) {
int result = 0;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
auto type = getEnum<Ability>(args, 1);
if (creature) {
@ -311,7 +311,7 @@ Variable Routines::getSkillRank(const VariablesList &args, ExecutionContext &ctx
Variable Routines::getXP(const VariablesList &args, ExecutionContext &ctx) {
int result = 0;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->xp();
} else {
@ -322,7 +322,7 @@ Variable Routines::getXP(const VariablesList &args, ExecutionContext &ctx) {
}
Variable Routines::setXP(const VariablesList &args, ExecutionContext &ctx) {
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
int xpAmount = getInt(args, 1);
if (creature) {
@ -335,7 +335,7 @@ Variable Routines::setXP(const VariablesList &args, ExecutionContext &ctx) {
}
Variable Routines::giveXPToCreature(const VariablesList &args, ExecutionContext &ctx) {
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
int xpAmount = getInt(args, 1);
if (creature) {
@ -350,7 +350,7 @@ Variable Routines::giveXPToCreature(const VariablesList &args, ExecutionContext
Variable Routines::getRacialType(const VariablesList &args, ExecutionContext &ctx) {
auto result = RacialType::Invalid;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->racialType();
} else {
@ -363,7 +363,7 @@ Variable Routines::getRacialType(const VariablesList &args, ExecutionContext &ct
Variable Routines::getSubRace(const VariablesList &args, ExecutionContext &ctx) {
auto result = Subrace::None;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->subrace();
} else {

View file

@ -492,7 +492,7 @@ Variable Routines::clearAllEffects(const VariablesList &args, ExecutionContext &
Variable Routines::applyEffectToObject(const VariablesList &args, ExecutionContext &ctx) {
auto durationType = getEnum<DurationType>(args, 0);
auto effect = getEffect(args, 1);
auto target = getSpatialObject(args, 2);
auto target = getSpatialObject(args, 2, ctx);
float duration = getFloat(args, 3, 0.0f);
if (target) {

View file

@ -41,12 +41,12 @@ Variable Routines::eventUserDefined(const VariablesList &args, ExecutionContext
}
Variable Routines::signalEvent(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
auto toRun = getEvent(args, 1);
if (object && toRun) {
debug(boost::format("Event signalled: %s %s") % object->tag() % toRun->number(), 2);
_game->scriptRunner().run(object->getOnUserDefined(), object->id(), kObjectInvalid, toRun->number());
runScript(object->getOnUserDefined(), object->id(), kObjectInvalid, toRun->number());
} else if (!object) {
debug("Script: signalEvent: object is invalid", 1, DebugChannels::script);
} else if (!toRun) {

View file

@ -34,8 +34,8 @@ namespace reone {
namespace game {
Variable Routines::changeFaction(const VariablesList &args, ExecutionContext &ctx) {
auto objectToChangeFaction = getCreature(args, 0);
auto memberOfFactionToJoin = getCreature(args, 1);
auto objectToChangeFaction = getCreature(args, 0, ctx);
auto memberOfFactionToJoin = getCreature(args, 1, ctx);
if (objectToChangeFaction && memberOfFactionToJoin) {
objectToChangeFaction->setFaction(memberOfFactionToJoin->faction());
@ -49,7 +49,7 @@ Variable Routines::changeFaction(const VariablesList &args, ExecutionContext &ct
}
Variable Routines::changeToStandardFaction(const VariablesList &args, ExecutionContext &ctx) {
auto creatureToChange = getCreature(args, 0);
auto creatureToChange = getCreature(args, 0, ctx);
auto faction = getEnum<Faction>(args, 1);
if (creatureToChange) {
@ -63,7 +63,7 @@ Variable Routines::changeToStandardFaction(const VariablesList &args, ExecutionC
Variable Routines::getFactionEqual(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto firstObject = getCreature(args, 0);
auto firstObject = getCreature(args, 0, ctx);
auto secondObject = getCreatureOrCaller(args, 1, ctx);
if (firstObject && secondObject) {
@ -80,7 +80,7 @@ Variable Routines::getFactionEqual(const VariablesList &args, ExecutionContext &
Variable Routines::getStandardFaction(const VariablesList &args, ExecutionContext &ctx) {
auto result = Faction::Invalid;
auto object = getCreature(args, 0);
auto object = getCreature(args, 0, ctx);
if (object) {
result = object->faction();
} else {
@ -92,7 +92,7 @@ Variable Routines::getStandardFaction(const VariablesList &args, ExecutionContex
Variable Routines::getIsEnemy(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto target = getCreature(args, 0);
auto target = getCreature(args, 0, ctx);
auto source = getCreatureOrCaller(args, 1, ctx);
if (target && source) {
@ -108,7 +108,7 @@ Variable Routines::getIsEnemy(const VariablesList &args, ExecutionContext &ctx)
Variable Routines::getIsFriend(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto target = getCreature(args, 0);
auto target = getCreature(args, 0, ctx);
auto source = getCreatureOrCaller(args, 1, ctx);
if (target && source) {
@ -124,7 +124,7 @@ Variable Routines::getIsFriend(const VariablesList &args, ExecutionContext &ctx)
Variable Routines::getIsNeutral(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto target = getCreature(args, 0);
auto target = getCreature(args, 0, ctx);
auto source = getCreatureOrCaller(args, 1, ctx);
if (target && source) {

View file

@ -95,7 +95,7 @@ Variable Routines::getNextItemInInventory(const VariablesList &args, ExecutionCo
Variable Routines::getItemStackSize(const VariablesList &args, ExecutionContext &ctx) {
int result = 0;
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
if (item) {
result = item->stackSize();
} else {
@ -106,7 +106,7 @@ Variable Routines::getItemStackSize(const VariablesList &args, ExecutionContext
}
Variable Routines::setItemStackSize(const VariablesList &args, ExecutionContext &ctx) {
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
int stackSize = getInt(args, 1);
if (item) {
@ -121,7 +121,7 @@ Variable Routines::setItemStackSize(const VariablesList &args, ExecutionContext
Variable Routines::getIdentified(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
if (item) {
result = item->isIdentified();
} else {
@ -132,7 +132,7 @@ Variable Routines::getIdentified(const VariablesList &args, ExecutionContext &ct
}
Variable Routines::setIdentified(const VariablesList &args, ExecutionContext &ctx) {
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
bool identified = getBool(args, 1);
if (item) {
@ -146,7 +146,7 @@ Variable Routines::setIdentified(const VariablesList &args, ExecutionContext &ct
Variable Routines::getItemPossessedBy(const VariablesList &args, ExecutionContext &ctx) {
shared_ptr<Item> result;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
auto itemTag = boost::to_lower_copy(getString(args, 1));
if (creature && !itemTag.empty()) {
@ -163,7 +163,7 @@ Variable Routines::getItemPossessedBy(const VariablesList &args, ExecutionContex
Variable Routines::getBaseItemType(const VariablesList &args, ExecutionContext &ctx) {
int result = 0;
auto item = getItem(args, 0);
auto item = getItem(args, 0, ctx);
if (item) {
result = item->baseItemType();
} else {

View file

@ -52,7 +52,7 @@ Variable Routines::getFacingFromLocation(const VariablesList &args, ExecutionCon
Variable Routines::getLocation(const VariablesList &args, ExecutionContext &ctx) {
shared_ptr<Location> result;
auto object = getSpatialObject(args, 0);
auto object = getSpatialObject(args, 0, ctx);
if (object) {
glm::vec3 position(object->position());
float facing = object->getFacing();

View file

@ -38,7 +38,7 @@ namespace reone {
namespace game {
Variable Routines::destroyObject(const VariablesList &args, ExecutionContext &ctx) {
auto destroy = getSpatialObject(args, 0);
auto destroy = getSpatialObject(args, 0, ctx);
if (destroy) {
_game->module()->area()->destroyObject(*destroy);
} else {
@ -52,7 +52,7 @@ Variable Routines::getEnteringObject(const VariablesList &args, ExecutionContext
}
Variable Routines::getIsObjectValid(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
return Variable::ofInt(static_cast<int>(static_cast<bool>(object)));
}
@ -90,7 +90,7 @@ Variable Routines::getArea(const VariablesList &args, ExecutionContext &ctx) {
}
Variable Routines::setLocked(const VariablesList &args, ExecutionContext &ctx) {
auto target = getDoor(args, 0);
auto target = getDoor(args, 0, ctx);
bool locked = getBool(args, 1);
if (target) {
@ -105,7 +105,7 @@ Variable Routines::setLocked(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getLocked(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto target = getDoor(args, 0);
auto target = getDoor(args, 0, ctx);
if (target) {
result = target->isLocked();
} else {
@ -122,7 +122,7 @@ Variable Routines::getModule(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getTag(const VariablesList &args, ExecutionContext &ctx) {
string result;
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
if (object) {
result = object->tag();
} else {
@ -135,7 +135,7 @@ Variable Routines::getTag(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getDistanceToObject(const VariablesList &args, ExecutionContext &ctx) {
float result = -1.0f;
auto caller = getCallerAsSpatial(ctx);
auto object = getSpatialObject(args, 0);
auto object = getSpatialObject(args, 0, ctx);
if (caller && object) {
result = caller->getDistanceTo(*object);
@ -151,7 +151,7 @@ Variable Routines::getDistanceToObject(const VariablesList &args, ExecutionConte
Variable Routines::getDistanceToObject2D(const VariablesList &args, ExecutionContext &ctx) {
float result = -1.0f;
auto caller = getCallerAsSpatial(ctx);
auto object = getSpatialObject(args, 0);
auto object = getSpatialObject(args, 0, ctx);
if (caller && object) {
result = caller->getDistanceTo(glm::vec2(object->position()));
@ -171,7 +171,7 @@ Variable Routines::getExitingObject(const VariablesList &args, ExecutionContext
Variable Routines::getFacing(const VariablesList &args, ExecutionContext &ctx) {
float result = -1.0f;
auto target = getSpatialObject(args, 0);
auto target = getSpatialObject(args, 0, ctx);
if (target) {
result = glm::degrees(target->getFacing());
} else {
@ -184,7 +184,7 @@ Variable Routines::getFacing(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getPosition(const VariablesList &args, ExecutionContext &ctx) {
glm::vec3 result(0.0f);
auto target = getSpatialObject(args, 0);
auto target = getSpatialObject(args, 0, ctx);
if (target) {
result = target->position();
} else {
@ -196,7 +196,7 @@ Variable Routines::getPosition(const VariablesList &args, ExecutionContext &ctx)
}
Variable Routines::soundObjectPlay(const VariablesList &args, ExecutionContext &ctx) {
auto sound = getSound(args, 0);
auto sound = getSound(args, 0, ctx);
if (sound) {
sound->play();
} else {
@ -206,7 +206,7 @@ Variable Routines::soundObjectPlay(const VariablesList &args, ExecutionContext &
}
Variable Routines::soundObjectStop(const VariablesList &args, ExecutionContext &ctx) {
auto sound = getSound(args, 0);
auto sound = getSound(args, 0, ctx);
if (sound) {
sound->stop();
} else {
@ -217,8 +217,8 @@ Variable Routines::soundObjectStop(const VariablesList &args, ExecutionContext &
Variable Routines::getDistanceBetween(const VariablesList &args, ExecutionContext &ctx) {
float result = 0.0f;
auto objectA = getSpatialObject(args, 0);
auto objectB = getSpatialObject(args, 1);
auto objectA = getSpatialObject(args, 0, ctx);
auto objectB = getSpatialObject(args, 1, ctx);
if (objectA && objectB) {
result = objectA->getDistanceTo(*objectB);
@ -233,8 +233,8 @@ Variable Routines::getDistanceBetween(const VariablesList &args, ExecutionContex
Variable Routines::getDistanceBetween2D(const VariablesList &args, ExecutionContext &ctx) {
float result = 0.0f;
auto objectA = getSpatialObject(args, 0);
auto objectB = getSpatialObject(args, 1);
auto objectA = getSpatialObject(args, 0, ctx);
auto objectB = getSpatialObject(args, 1, ctx);
if (objectA && objectB) {
result = objectA->getDistanceTo(glm::vec2(objectB->position()));
@ -250,7 +250,7 @@ Variable Routines::getDistanceBetween2D(const VariablesList &args, ExecutionCont
Variable Routines::getIsDead(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature->isDead();
} else {
@ -276,7 +276,7 @@ Variable Routines::getIsInCombat(const VariablesList &args, ExecutionContext &ct
Variable Routines::getIsOpen(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto object = getSpatialObject(args, 0);
auto object = getSpatialObject(args, 0, ctx);
if (object) {
result = object->isOpen();
} else {
@ -313,7 +313,7 @@ Variable Routines::setFacingPoint(const VariablesList &args, ExecutionContext &c
Variable Routines::getName(const VariablesList &args, ExecutionContext &ctx) {
string result;
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
if (object) {
result = object->name();
} else {
@ -326,7 +326,7 @@ Variable Routines::getName(const VariablesList &args, ExecutionContext &ctx) {
Variable Routines::getObjectType(const VariablesList &args, ExecutionContext &ctx) {
auto result = ObjectType::Invalid;
auto target = getObject(args, 0);
auto target = getObject(args, 0, ctx);
if (target) {
result = target->type();
} else {
@ -350,7 +350,7 @@ Variable Routines::getPlotFlag(const VariablesList &args, ExecutionContext &ctx)
}
Variable Routines::setPlotFlag(const VariablesList &args, ExecutionContext &ctx) {
auto target = getObject(args, 0);
auto target = getObject(args, 0, ctx);
bool plotFlag = getBool(args, 1);
if (target) {
@ -363,8 +363,8 @@ Variable Routines::setPlotFlag(const VariablesList &args, ExecutionContext &ctx)
}
Variable Routines::faceObjectAwayFromObject(const VariablesList &args, ExecutionContext &ctx) {
auto facer = getSpatialObject(args, 0);
auto objectToFaceAwayFrom = getSpatialObject(args, 1);
auto facer = getSpatialObject(args, 0, ctx);
auto objectToFaceAwayFrom = getSpatialObject(args, 1, ctx);
if (facer && objectToFaceAwayFrom) {
facer->faceAwayFrom(*objectToFaceAwayFrom);
@ -436,7 +436,7 @@ Variable Routines::setAreaUnescapable(const VariablesList &args, ExecutionContex
Variable Routines::cutsceneAttack(const VariablesList &args, ExecutionContext &ctx) {
auto caller = getCallerAsCreature(ctx);
auto target = getSpatialObject(args, 0);
auto target = getSpatialObject(args, 0, ctx);
int animation = getInt(args, 1);
auto attackResult = getEnum<AttackResultType>(args, 2);
int damage = getInt(args, 3);
@ -546,7 +546,7 @@ Variable Routines::getNearestObjectByTag(const VariablesList &args, ExecutionCon
}
Variable Routines::objectToString(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
string result;
if (object) {

View file

@ -63,7 +63,7 @@ Variable Routines::showPartySelectionGUI(const VariablesList &args, ExecutionCon
Variable Routines::getIsPC(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = creature == _game->party().player();
} else {
@ -82,7 +82,7 @@ Variable Routines::isAvailableCreature(const VariablesList &args, ExecutionConte
Variable Routines::isObjectPartyMember(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto creature = getCreature(args, 0);
auto creature = getCreature(args, 0, ctx);
if (creature) {
result = _game->party().isMember(*creature);
} else {
@ -116,7 +116,7 @@ Variable Routines::setPartyLeader(const VariablesList &args, ExecutionContext &c
Variable Routines::addPartyMember(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
int npc = getInt(args, 0);
auto creature = getCreature(args, 1);
auto creature = getCreature(args, 1, ctx);
if (creature) {
_game->party().addAvailableMember(npc, creature->blueprintResRef());

View file

@ -101,7 +101,7 @@ Variable Routines::getLastPerceptionInaudible(const VariablesList &args, Executi
Variable Routines::getObjectSeen(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto target = getCreature(args, 0);
auto target = getCreature(args, 0, ctx);
auto source = getCreatureOrCaller(args, 1, ctx);
if (target && source) {
@ -117,7 +117,7 @@ Variable Routines::getObjectSeen(const VariablesList &args, ExecutionContext &ct
Variable Routines::getObjectHeard(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto target = getCreature(args, 0);
auto target = getCreature(args, 0, ctx);
auto source = getCreatureOrCaller(args, 1, ctx);
if (target && source) {

View file

@ -78,7 +78,7 @@ Variable Routines::setGlobalString(const VariablesList &args, ExecutionContext &
Variable Routines::getLocalBoolean(const VariablesList &args, ExecutionContext &ctx) {
bool result = false;
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
int index = getInt(args, 1);
if (object) {
@ -91,7 +91,7 @@ Variable Routines::getLocalBoolean(const VariablesList &args, ExecutionContext &
}
Variable Routines::setLocalBoolean(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
int index = getInt(args, 1);
bool value = getBool(args, 2);
@ -106,7 +106,7 @@ Variable Routines::setLocalBoolean(const VariablesList &args, ExecutionContext &
Variable Routines::getLocalNumber(const VariablesList &args, ExecutionContext &ctx) {
int result = 0;
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
int index = getInt(args, 1);
if (object) {
@ -119,7 +119,7 @@ Variable Routines::getLocalNumber(const VariablesList &args, ExecutionContext &c
}
Variable Routines::setLocalNumber(const VariablesList &args, ExecutionContext &ctx) {
auto object = getObject(args, 0);
auto object = getObject(args, 0, ctx);
int index = getInt(args, 1);
int value = getInt(args, 2);

View file

@ -15,15 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "runner.h"
#include "runutil.h"
#include <stdexcept>
#include "../../script/execution.h"
#include "../../script/scripts.h"
#include "../game.h"
#include "routines.h"
using namespace std;
@ -34,20 +32,21 @@ namespace reone {
namespace game {
ScriptRunner::ScriptRunner(Game *game) : _game(game) {
if (!game) {
throw invalid_argument("game must not be null");
int runScript(const string &resRef, uint32_t callerId, uint32_t triggerrerId, int userDefinedEventNumber, int scriptVar) {
if (callerId == kObjectSelf) {
throw invalid_argument("Invalid callerId");
}
if (triggerrerId == kObjectSelf) {
throw invalid_argument("Invalid triggerrerId");
}
int ScriptRunner::run(const string &resRef, uint32_t callerId, uint32_t triggerrerId, int userDefinedEventNumber, int scriptVar) {
auto program = Scripts::instance().get(resRef);
if (!program) return -1;
auto ctx = make_unique<ExecutionContext>();
ctx->routines = &Routines::instance();
ctx->caller = _game->getObjectById(callerId);
ctx->triggerer = _game->getObjectById(triggerrerId);
ctx->callerId = callerId;
ctx->triggererId = triggerrerId;
ctx->userDefinedEventNumber = userDefinedEventNumber;
ctx->scriptVar = scriptVar;

View file

@ -18,39 +18,21 @@
#pragma once
#include <cstdint>
#include <memory>
#include <string>
#include <boost/noncopyable.hpp>
#include "../../script/types.h"
namespace reone {
namespace game {
class Game;
class Object;
/**
* An interface for game objects to run their scripts. This is needed because
* runScript accepts smart pointers to game objects.
*/
class ScriptRunner : boost::noncopyable {
public:
ScriptRunner(Game *game);
int run(
int runScript(
const std::string &resRef,
uint32_t callerId = script::kObjectInvalid,
uint32_t triggerrerId = script::kObjectInvalid,
int userDefinedEventNumber = -1,
int scriptVar = -1);
private:
Game *_game;
};
} // namespace game
} // namespace reone

View file

@ -89,13 +89,7 @@ ScriptExecution::ScriptExecution(const shared_ptr<ScriptProgram> &program, uniqu
}
int ScriptExecution::run() {
string callerTag;
if (_context->caller) {
callerTag = _context->caller->tag();
} else {
callerTag = "[invalid]";
}
debug(boost::format("Script: run %s as %s") % _program->name() % callerTag, 1, DebugChannels::script);
debug(boost::format("Script: run %s as %u") % _program->name() % _context->callerId, 1, DebugChannels::script);
uint32_t insOff = kStartInstructionOffset;
if (_context->savedState) {
@ -196,17 +190,8 @@ void ScriptExecution::executePushConstant(const Instruction &ins) {
_stack.push_back(Variable::ofFloat(ins.floatValue));
break;
case InstructionType::Object: {
shared_ptr<ScriptObject> object;
switch (ins.objectId) {
case kObjectSelf:
object = _context->caller;
break;
case kObjectInvalid:
break;
default:
throw logic_error("Invalid object id");
}
_stack.push_back(Variable::ofObject(object));
uint32_t objectId = ins.objectId == kObjectSelf ? _context->callerId : ins.objectId;
_stack.push_back(Variable::ofObject(objectId));
break;
}
case InstructionType::String:

View file

@ -30,7 +30,6 @@ constexpr uint32_t kObjectInvalid = 1;
struct Variable;
class ScriptObject;
class ScriptProgram;
class Routine;
@ -52,8 +51,8 @@ public:
struct ExecutionContext {
IRoutineProvider *routines { nullptr };
std::shared_ptr<ExecutionState> savedState;
std::shared_ptr<ScriptObject> caller;
std::shared_ptr<ScriptObject> triggerer;
uint32_t callerId { kObjectInvalid };
uint32_t triggererId { kObjectInvalid };
int userDefinedEventNumber { -1 };
int scriptVar { -1 };
};

View file

@ -129,10 +129,17 @@ Variable Variable::ofVector(glm::vec3 value) {
return move(result);
}
Variable Variable::ofObject(uint32_t objectId) {
Variable result;
result.type = VariableType::Object;
result.objectId = objectId;
return move(result);
}
Variable Variable::ofObject(shared_ptr<ScriptObject> object) {
Variable result;
result.type = VariableType::Object;
result.object = move(object);
result.objectId = object ? object->id() : kObjectInvalid;
return move(result);
}
@ -182,7 +189,7 @@ bool Variable::operator==(const Variable &other) const {
case VariableType::String:
return strValue == other.strValue;
case VariableType::Object:
return object == other.object;
return objectId == other.objectId;
case VariableType::Effect:
case VariableType::Event:
case VariableType::Location:
@ -256,7 +263,7 @@ const string Variable::toString() const {
case VariableType::String:
return str(boost::format("\"%s\"") % strValue);
case VariableType::Object:
return to_string(object ? object->id() : kObjectInvalid);
return to_string(objectId);
case VariableType::Vector:
return str(boost::format("[%f,%f,%f]") % vecValue.x % vecValue.y % vecValue.z);
case VariableType::Effect:

View file

@ -49,12 +49,12 @@ struct Variable {
VariableType type { VariableType::Void };
std::string strValue;
glm::vec3 vecValue { 0.0f };
std::shared_ptr<ScriptObject> object;
std::shared_ptr<EngineType> engineType;
std::shared_ptr<ExecutionContext> context;
union {
int intValue { 0 };
int32_t intValue { 0 };
uint32_t objectId;
float floatValue;
};
@ -64,6 +64,7 @@ struct Variable {
static Variable ofFloat(float value);
static Variable ofString(std::string value);
static Variable ofVector(glm::vec3 value);
static Variable ofObject(uint32_t objectId);
static Variable ofObject(std::shared_ptr<ScriptObject> object);
static Variable ofEffect(std::shared_ptr<EngineType> engineType);
static Variable ofEvent(std::shared_ptr<EngineType> engineType);