1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-26 19:41:34 +00:00

Merge branch 'teleporting' into 'master'

A few Lua changes related to teleporting

See merge request OpenMW/openmw!3246
This commit is contained in:
psi29a 2023-07-27 09:32:28 +00:00
commit 3032b340a2
13 changed files with 55 additions and 12 deletions

View file

@ -47,6 +47,7 @@ namespace MWBase
virtual void gameLoaded() = 0; virtual void gameLoaded() = 0;
virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0; virtual void objectAddedToScene(const MWWorld::Ptr& ptr) = 0;
virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0; virtual void objectRemovedFromScene(const MWWorld::Ptr& ptr) = 0;
virtual void objectTeleported(const MWWorld::Ptr& ptr) = 0;
virtual void itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor) = 0; virtual void itemConsumed(const MWWorld::Ptr& consumable, const MWWorld::Ptr& actor) = 0;
virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0; virtual void objectActivated(const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;
virtual void exteriorCreated(MWWorld::CellStore& cell) = 0; virtual void exteriorCreated(MWWorld::CellStore& cell) = 0;

View file

@ -22,8 +22,6 @@ namespace MWLua
{ {
} }
void operator()(const OnNewGame&) const { mGlobalScripts.newGameStarted(); }
void operator()(const OnActive& event) const void operator()(const OnActive& event) const
{ {
MWWorld::Ptr ptr = getPtr(event.mObject); MWWorld::Ptr ptr = getPtr(event.mObject);
@ -50,6 +48,12 @@ namespace MWLua
scripts->setActive(false); scripts->setActive(false);
} }
void operator()(const OnTeleported& event) const
{
if (auto* scripts = getLocalScripts(event.mObject))
scripts->onTeleported();
}
void operator()(const OnActivate& event) const void operator()(const OnActivate& event) const
{ {
MWWorld::Ptr obj = getPtr(event.mObject); MWWorld::Ptr obj = getPtr(event.mObject);

View file

@ -19,9 +19,6 @@ namespace MWLua
{ {
} }
struct OnNewGame
{
};
struct OnActive struct OnActive
{ {
ESM::RefNum mObject; ESM::RefNum mObject;
@ -30,6 +27,10 @@ namespace MWLua
{ {
ESM::RefNum mObject; ESM::RefNum mObject;
}; };
struct OnTeleported
{
ESM::RefNum mObject;
};
struct OnActivate struct OnActivate
{ {
ESM::RefNum mActor; ESM::RefNum mActor;
@ -44,7 +45,7 @@ namespace MWLua
{ {
MWWorld::CellStore& mCell; MWWorld::CellStore& mCell;
}; };
using Event = std::variant<OnNewGame, OnActive, OnInactive, OnConsume, OnActivate, OnNewExterior>; using Event = std::variant<OnActive, OnInactive, OnConsume, OnActivate, OnNewExterior, OnTeleported>;
void clear() { mQueue.clear(); } void clear() { mQueue.clear(); }
void addToQueue(Event e) { mQueue.push_back(std::move(e)); } void addToQueue(Event e) { mQueue.push_back(std::move(e)); }

View file

@ -169,8 +169,8 @@ namespace MWLua
, mData(obj) , mData(obj)
{ {
this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData)); this->addPackage("openmw.self", sol::make_object(lua->sol(), &mData));
registerEngineHandlers( registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers,
{ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers }); &mOnTeleportedHandlers });
} }
void LocalScripts::setActive(bool active) void LocalScripts::setActive(bool active)

View file

@ -70,6 +70,7 @@ namespace MWLua
void setActive(bool active); void setActive(bool active);
void onConsume(const LObject& consumable) { callEngineHandlers(mOnConsumeHandlers, consumable); } void onConsume(const LObject& consumable) { callEngineHandlers(mOnConsumeHandlers, consumable); }
void onActivated(const LObject& actor) { callEngineHandlers(mOnActivatedHandlers, actor); } void onActivated(const LObject& actor) { callEngineHandlers(mOnActivatedHandlers, actor); }
void onTeleported() { callEngineHandlers(mOnTeleportedHandlers); }
void applyStatsCache(); void applyStatsCache();
@ -81,6 +82,7 @@ namespace MWLua
EngineHandlerList mOnInactiveHandlers{ "onInactive" }; EngineHandlerList mOnInactiveHandlers{ "onInactive" };
EngineHandlerList mOnConsumeHandlers{ "onConsume" }; EngineHandlerList mOnConsumeHandlers{ "onConsume" };
EngineHandlerList mOnActivatedHandlers{ "onActivated" }; EngineHandlerList mOnActivatedHandlers{ "onActivated" };
EngineHandlerList mOnTeleportedHandlers{ "onTeleported" };
}; };
} }

View file

@ -178,6 +178,20 @@ namespace MWLua
} }
} }
void LuaManager::objectTeleported(const MWWorld::Ptr& ptr)
{
if (ptr == mPlayer)
{
// For player run the onTeleported handler immediately,
// so it can adjust camera position after teleporting.
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
if (playerScripts)
playerScripts->onTeleported();
}
else
mEngineEvents.addToQueue(EngineEvents::OnTeleported{ getId(ptr) });
}
void LuaManager::questUpdated(const ESM::RefId& questId, int stage) void LuaManager::questUpdated(const ESM::RefId& questId, int stage)
{ {
if (mPlayer.isEmpty()) if (mPlayer.isEmpty())
@ -194,6 +208,14 @@ namespace MWLua
if (mPlayer.isEmpty()) if (mPlayer.isEmpty())
return; // The game is not started yet. return; // The game is not started yet.
if (mNewGameStarted)
{
mNewGameStarted = false;
// Run onNewGame handler in synchronizedUpdate (at the beginning of the frame), so it
// can teleport the player to the starting location before the first frame is rendered.
mGlobalScripts.newGameStarted();
}
// We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency. // We apply input events in `synchronizedUpdate` rather than in `update` in order to reduce input latency.
mProcessingInputEvents = true; mProcessingInputEvents = true;
PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts()); PlayerScripts* playerScripts = dynamic_cast<PlayerScripts*>(mPlayer.getRefData().getLuaScripts());
@ -237,6 +259,7 @@ namespace MWLua
mWorldView.clear(); mWorldView.clear();
mGlobalScripts.removeAllScripts(); mGlobalScripts.removeAllScripts();
mGlobalScriptsStarted = false; mGlobalScriptsStarted = false;
mNewGameStarted = false;
if (!mPlayer.isEmpty()) if (!mPlayer.isEmpty())
{ {
mPlayer.getCellRef().unsetRefNum(); mPlayer.getCellRef().unsetRefNum();
@ -273,7 +296,7 @@ namespace MWLua
mInputEvents.clear(); mInputEvents.clear();
mGlobalScripts.addAutoStartedScripts(); mGlobalScripts.addAutoStartedScripts();
mGlobalScriptsStarted = true; mGlobalScriptsStarted = true;
mEngineEvents.addToQueue(EngineEvents::OnNewGame{}); mNewGameStarted = true;
} }
void LuaManager::gameLoaded() void LuaManager::gameLoaded()

View file

@ -75,6 +75,7 @@ namespace MWLua
{ {
mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell }); mEngineEvents.addToQueue(EngineEvents::OnNewExterior{ cell });
} }
void objectTeleported(const MWWorld::Ptr& ptr) override;
void questUpdated(const ESM::RefId& questId, int stage) override; void questUpdated(const ESM::RefId& questId, int stage) override;
MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override; MWBase::LuaManager::ActorControls* getActorControls(const MWWorld::Ptr&) const override;
@ -141,6 +142,7 @@ namespace MWLua
bool mInitialized = false; bool mInitialized = false;
bool mGlobalScriptsStarted = false; bool mGlobalScriptsStarted = false;
bool mProcessingInputEvents = false; bool mProcessingInputEvents = false;
bool mNewGameStarted = false;
LuaUtil::ScriptsConfiguration mConfiguration; LuaUtil::ScriptsConfiguration mConfiguration;
LuaUtil::LuaState mLua; LuaUtil::LuaState mLua;
LuaUi::ResourceManager mUiResourceManager; LuaUi::ResourceManager mUiResourceManager;

View file

@ -95,6 +95,7 @@ namespace MWLua
world->rotateObject(newPtr, rot); world->rotateObject(newPtr, rot);
if (placeOnGround) if (placeOnGround)
world->adjustPosition(newPtr, true); world->adjustPosition(newPtr, true);
MWBase::Environment::get().getLuaManager()->objectTeleported(newPtr);
} }
void teleportNotPlayer(const MWWorld::Ptr& ptr, MWWorld::CellStore* destCell, const osg::Vec3f& pos, void teleportNotPlayer(const MWWorld::Ptr& ptr, MWWorld::CellStore* destCell, const osg::Vec3f& pos,
@ -119,6 +120,7 @@ namespace MWLua
} }
if (!newPtr.getRefData().isEnabled()) if (!newPtr.getRefData().isEnabled())
world->enable(newPtr); world->enable(newPtr);
MWBase::Environment::get().getLuaManager()->objectTeleported(newPtr);
} }
template <typename ObjT> template <typename ObjT>

View file

@ -11,6 +11,7 @@
#include <components/interpreter/runtime.hpp> #include <components/interpreter/runtime.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
#include "../mwworld/cellstore.hpp" #include "../mwworld/cellstore.hpp"
@ -436,6 +437,7 @@ namespace MWScript
bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell()); bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell());
ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive); ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive);
MWBase::Environment::get().getLuaManager()->objectTeleported(ptr);
} }
}; };
@ -492,6 +494,7 @@ namespace MWScript
world->rotateObject(ptr, rot); world->rotateObject(ptr, rot);
bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell()); bool cellActive = MWBase::Environment::get().getWorldScene()->isCellActive(*ptr.getCell());
ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive); ptr.getClass().adjustPosition(ptr, isPlayer || !cellActive);
MWBase::Environment::get().getLuaManager()->objectTeleported(ptr);
} }
}; };

View file

@ -4,6 +4,7 @@
#include <components/esm3/loadmgef.hpp> #include <components/esm3/loadmgef.hpp>
#include "../mwbase/environment.hpp" #include "../mwbase/environment.hpp"
#include "../mwbase/luamanager.hpp"
#include "../mwbase/mechanicsmanager.hpp" #include "../mwbase/mechanicsmanager.hpp"
#include "../mwbase/world.hpp" #include "../mwbase/world.hpp"
@ -65,7 +66,6 @@ namespace MWWorld
actor.getClass().getCreatureStats(actor).getAiSequence().stopCombat(); actor.getClass().getCreatureStats(actor).getAiSequence().stopCombat();
return; return;
} }
else else
teleported = world->moveObject(actor, &worldModel->getCell(mCellId), mPosition.asVec3(), true, true); teleported = world->moveObject(actor, &worldModel->getCell(mCellId), mPosition.asVec3(), true, true);
} }
@ -75,6 +75,8 @@ namespace MWWorld
.getCreatureStats(teleported) .getCreatureStats(teleported)
.getActiveSpells() .getActiveSpells()
.purgeEffect(actor, ESM::MagicEffect::WaterWalking); .purgeEffect(actor, ESM::MagicEffect::WaterWalking);
MWBase::Environment::get().getLuaManager()->objectTeleported(teleported);
} }
void ActionTeleport::getFollowers( void ActionTeleport::getFollowers(

View file

@ -974,7 +974,6 @@ namespace MWWorld
removeContainerScripts(getPlayerPtr()); removeContainerScripts(getPlayerPtr());
mWorldScene->changeToInteriorCell(cellName, position, adjustPlayerPos, changeEvent); mWorldScene->changeToInteriorCell(cellName, position, adjustPlayerPos, changeEvent);
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
mRendering->getCamera()->instantTransition();
} }
void World::changeToCell( void World::changeToCell(
@ -999,7 +998,6 @@ namespace MWWorld
else else
mWorldScene->changeToInteriorCell(destinationCell->getNameId(), position, adjustPlayerPos, changeEvent); mWorldScene->changeToInteriorCell(destinationCell->getNameId(), position, adjustPlayerPos, changeEvent);
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell()); addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
mRendering->getCamera()->instantTransition();
} }
float World::getMaxActivationDistance() const float World::getMaxActivationDistance() const

View file

@ -64,6 +64,8 @@ Engine handler is a function defined by a script, that can be called by the engi
- | Object became inactive. Since it is inactive the handler - | Object became inactive. Since it is inactive the handler
| can not access anything nearby, but it is possible to send | can not access anything nearby, but it is possible to send
| an event to global scripts. | an event to global scripts.
* - onTeleported()
- Object was teleported.
* - onActivated(actor) * - onActivated(actor)
- | Called on an object when an actor activates it. Note that picking - | Called on an object when an actor activates it. Note that picking
| up an item is also an activation and works this way: (1) a copy of | up an item is also an activation and works this way: (1) a copy of

View file

@ -281,6 +281,9 @@ return {
end end
move360.onInputAction(action) move360.onInputAction(action)
end, end,
onTeleported = function()
camera.instantTransition()
end,
onActive = init, onActive = init,
onLoad = function(data) onLoad = function(data)
if data and data.distance then third_person.baseDistance = data.distance end if data and data.distance then third_person.baseDistance = data.distance end