diff --git a/apps/openmw-mp/Script/Functions/World.cpp b/apps/openmw-mp/Script/Functions/World.cpp index ba7dba1a5..9147488b3 100644 --- a/apps/openmw-mp/Script/Functions/World.cpp +++ b/apps/openmw-mp/Script/Functions/World.cpp @@ -229,11 +229,6 @@ void WorldFunctions::SetObjectState(bool objectState) noexcept tempWorldObject.objectState = objectState; } -void WorldFunctions::SetObjectDoorState(int doorState) noexcept -{ - tempWorldObject.doorState = doorState; -} - void WorldFunctions::SetObjectLockLevel(int lockLevel) noexcept { tempWorldObject.lockLevel = lockLevel; @@ -263,6 +258,34 @@ void WorldFunctions::SetObjectRotation(double x, double y, double z) noexcept tempWorldObject.position.rot[2] = z; } +void WorldFunctions::SetObjectDoorState(int doorState) noexcept +{ + tempWorldObject.doorState = doorState; +} + +void WorldFunctions::SetObjectDoorTeleportState(bool teleportState) noexcept +{ + tempWorldObject.teleportState = teleportState; +} + +void WorldFunctions::SetObjectDoorDestinationCell(const char* cellDescription) noexcept +{ + tempWorldObject.destinationCell = Utils::getCellFromDescription(cellDescription); +} + +void WorldFunctions::SetObjectDoorDestinationPosition(double x, double y, double z) noexcept +{ + tempWorldObject.destinationPosition.pos[0] = x; + tempWorldObject.destinationPosition.pos[1] = y; + tempWorldObject.destinationPosition.pos[2] = z; +} + +void WorldFunctions::SetObjectDoorDestinationRotation(double x, double z) noexcept +{ + tempWorldObject.destinationPosition.rot[0] = x; + tempWorldObject.destinationPosition.rot[2] = z; +} + void WorldFunctions::SetPlayerAsObject(unsigned short pid) noexcept { Player *player; @@ -392,6 +415,16 @@ void WorldFunctions::SendDoorState(bool broadcast) noexcept packet->Send(true); } +void WorldFunctions::SendDoorDestination(bool broadcast) noexcept +{ + mwmp::WorldPacket *packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_DOOR_DESTINATION); + packet->setEvent(&writeEvent); + packet->Send(false); + + if (broadcast) + packet->Send(true); +} + void WorldFunctions::SendContainer(bool broadcast, bool useLastReadEvent) noexcept { mwmp::WorldPacket *packet = mwmp::Networking::get().getWorldPacketController()->GetPacket(ID_CONTAINER); diff --git a/apps/openmw-mp/Script/Functions/World.hpp b/apps/openmw-mp/Script/Functions/World.hpp index 95d8af7cd..2ba777dee 100644 --- a/apps/openmw-mp/Script/Functions/World.hpp +++ b/apps/openmw-mp/Script/Functions/World.hpp @@ -47,12 +47,18 @@ {"SetObjectGoldValue", WorldFunctions::SetObjectGoldValue},\ {"SetObjectScale", WorldFunctions::SetObjectScale},\ {"SetObjectState", WorldFunctions::SetObjectState},\ - {"SetObjectDoorState", WorldFunctions::SetObjectDoorState},\ {"SetObjectLockLevel", WorldFunctions::SetObjectLockLevel},\ {"SetObjectDisarmState", WorldFunctions::SetObjectDisarmState},\ {"SetObjectMasterState", WorldFunctions::SetObjectMasterState},\ {"SetObjectPosition", WorldFunctions::SetObjectPosition},\ {"SetObjectRotation", WorldFunctions::SetObjectRotation},\ + \ + {"SetObjectDoorState", WorldFunctions::SetObjectDoorState},\ + {"SetObjectDoorTeleportState", WorldFunctions::SetObjectDoorTeleportState},\ + {"SetObjectDoorDestinationCell", WorldFunctions::SetObjectDoorDestinationCell},\ + {"SetObjectDoorDestinationPosition", WorldFunctions::SetObjectDoorDestinationPosition},\ + {"SetObjectDoorDestinationRotation", WorldFunctions::SetObjectDoorDestinationRotation},\ + \ {"SetPlayerAsObject", WorldFunctions::SetPlayerAsObject},\ \ {"SetContainerItemRefId", WorldFunctions::SetContainerItemRefId},\ @@ -73,6 +79,7 @@ {"SendObjectScale", WorldFunctions::SendObjectScale},\ {"SendObjectState", WorldFunctions::SendObjectState},\ {"SendDoorState", WorldFunctions::SendDoorState},\ + {"SendDoorDestination", WorldFunctions::SendDoorDestination},\ {"SendContainer", WorldFunctions::SendContainer},\ {"SendConsoleCommand", WorldFunctions::SendConsoleCommand},\ \ @@ -80,7 +87,7 @@ {"SetMonth", WorldFunctions::SetMonth},\ {"SetDay", WorldFunctions::SetDay} -class WorldFunctions +class WorldFunctions { public: @@ -456,16 +463,6 @@ public: */ static void SetObjectState(bool objectState) noexcept; - /** - * \brief Set the door state of the temporary world object stored on the server. - * - * Doors are open or closed based on their door state. - * - * \param doorState The door state. - * \return void - */ - static void SetObjectDoorState(int doorState) noexcept; - /** * \brief Set the lock level of the temporary world object stored on the server. * @@ -513,6 +510,60 @@ public: */ static void SetObjectRotation(double x, double y, double z) noexcept; + /** + * \brief Set the door state of the temporary world object stored on the server. + * + * Doors are open or closed based on their door state. + * + * \param doorState The door state. + * \return void + */ + static void SetObjectDoorState(int doorState) noexcept; + + /** + * \brief Set the teleport state of the temporary world object stored on the server. + * + * If a door's teleport state is true, interacting with the door teleports a player to its + * destination. If it's false, it opens and closes like a regular door. + * + * \param teleportState The teleport state. + * \return void + */ + static void SetObjectDoorTeleportState(bool teleportState) noexcept; + + /** + * \brief Set the door destination cell of the temporary world object stored on the server. + * + * The cell is determined to be an exterior cell if it fits the pattern of a number followed + * by a comma followed by another number. + * + * \param cellDescription The description of the cell. + * \return void + */ + static void SetObjectDoorDestinationCell(const char* cellDescription) noexcept; + + /** + * \brief Set the door destination position of the temporary world object stored on the server. + * + * \param x The X position. + * \param y The Y position. + * \param z The Z position. + * \return void + */ + static void SetObjectDoorDestinationPosition(double x, double y, double z) noexcept; + + /** + * \brief Set the door destination rotation of the temporary world object stored on the server. + * + * Note: Because this sets the rotation a player will have upon using the door, and rotation + * on the Y axis has no effect on players, the Y value has been omitted as an argument. + * + * \param x The X rotation. + * \param z The Z rotation. + * \return void + */ + static void SetObjectDoorDestinationRotation(double x, double z) noexcept; + /** * \brief Set a player as the object in the temporary world object stored on the server. * Currently only used for ConsoleCommand packets. @@ -670,6 +721,16 @@ public: */ static void SendDoorState(bool broadcast = false) noexcept; + /** + * \brief Send a DoorDestination packet. + * + * \param broadcast Whether this packet should be sent only to the player for whom the current + * event was initialized or to everyone on the server. + * + * \return void + */ + static void SendDoorDestination(bool broadcast = false) noexcept; + /** * \brief Send a Container packet. * diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index a4e932eb5..ddd555a77 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -124,12 +124,12 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic ) -add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorState - ProcessorMusicPlay ProcessorVideoPlay ProcessorObjectAnimPlay ProcessorObjectAttach ProcessorObjectCollision - ProcessorObjectDelete ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace ProcessorObjectReset - ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSpawn ProcessorObjectState ProcessorObjectTrap - ProcessorScriptLocalShort ProcessorScriptLocalFloat ProcessorScriptMemberShort ProcessorScriptMemberFloat - ProcessorScriptGlobalShort ProcessorScriptGlobalFloat +add_openmw_dir (mwmp/processors/world BaseObjectProcessor ProcessorConsoleCommand ProcessorContainer ProcessorDoorDestination + ProcessorDoorState ProcessorMusicPlay ProcessorVideoPlay ProcessorObjectAnimPlay ProcessorObjectAttach + ProcessorObjectCollision ProcessorObjectDelete ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace + ProcessorObjectReset ProcessorObjectRotate ProcessorObjectScale ProcessorObjectSpawn ProcessorObjectState + ProcessorObjectTrap ProcessorScriptLocalShort ProcessorScriptLocalFloat ProcessorScriptMemberShort + ProcessorScriptMemberFloat ProcessorScriptGlobalShort ProcessorScriptGlobalFloat ) # Main executable diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp index 03afd6317..30443a244 100644 --- a/apps/openmw/mwmp/WorldEvent.cpp +++ b/apps/openmw/mwmp/WorldEvent.cpp @@ -566,6 +566,34 @@ void WorldEvent::activateDoors(MWWorld::CellStore* cellStore) } } +void WorldEvent::setDoorDestinations(MWWorld::CellStore* cellStore) +{ + for (const auto &worldObject : worldObjects) + { + LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i", worldObject.refId.c_str(), worldObject.refNumIndex, worldObject.mpNum); + + MWWorld::Ptr ptrFound = cellStore->searchExact(worldObject.refNumIndex, worldObject.mpNum); + + if (ptrFound) + { + LOG_APPEND(Log::LOG_VERBOSE, "-- Found %s, %i, %i", ptrFound.getCellRef().getRefId().c_str(), + ptrFound.getCellRef().getRefNum(), ptrFound.getCellRef().getMpNum()); + + ptrFound.getCellRef().setTeleport(worldObject.teleportState); + + if (worldObject.teleportState) + { + ptrFound.getCellRef().setDoorDest(worldObject.destinationPosition); + + if (worldObject.destinationCell.isExterior()) + ptrFound.getCellRef().setDestCell(""); + else + ptrFound.getCellRef().setDestCell(worldObject.destinationCell.getDescription()); + } + } + } +} + void WorldEvent::runConsoleCommands(MWWorld::CellStore* cellStore) { MWBase::WindowManager *windowManager = MWBase::Environment::get().getWindowManager(); diff --git a/apps/openmw/mwmp/WorldEvent.hpp b/apps/openmw/mwmp/WorldEvent.hpp index 7ef4e7dbf..a8e15313c 100644 --- a/apps/openmw/mwmp/WorldEvent.hpp +++ b/apps/openmw/mwmp/WorldEvent.hpp @@ -35,6 +35,7 @@ namespace mwmp void rotateObjects(MWWorld::CellStore* cellStore); void animateObjects(MWWorld::CellStore* cellStore); void activateDoors(MWWorld::CellStore* cellStore); + void setDoorDestinations(MWWorld::CellStore* cellStore); void runConsoleCommands(MWWorld::CellStore* cellStore); void setLocalShorts(MWWorld::CellStore* cellStore); diff --git a/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp b/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp index 8a671696d..5ecb4fc53 100644 --- a/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp +++ b/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp @@ -17,7 +17,7 @@ namespace mwmp { BaseObjectProcessor::Do(packet, event); - //event.setDoorDestinations(ptrCellStore); + event.setDoorDestinations(ptrCellStore); } }; } diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 952d1cde9..602248bb1 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -56,16 +56,55 @@ namespace MWWorld return mCellRef.mTeleport; } + /* + Start of tes3mp addition + + Make it possible to change the teleport state from elsewhere + */ + void CellRef::setTeleport(bool teleportState) + { + mCellRef.mTeleport = teleportState; + } + /* + End of tes3mp addition + */ + ESM::Position CellRef::getDoorDest() const { return mCellRef.mDoorDest; } + /* + Start of tes3mp addition + + Make it possible to change the destination position from elsewhere + */ + void CellRef::setDoorDest(const ESM::Position& position) + { + mCellRef.mDoorDest = position; + } + /* + End of tes3mp addition + */ + std::string CellRef::getDestCell() const { return mCellRef.mDestCell; } + /* + Start of tes3mp addition + + Make it possible to change the destination cell from elsewhere + */ + void CellRef::setDestCell(const std::string& cellDescription) + { + mCellRef.mDestCell = cellDescription; + } + /* + End of tes3mp addition + */ + float CellRef::getScale() const { return mCellRef.mScale; diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 790b589bc..18f8a7165 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -58,12 +58,42 @@ namespace MWWorld // if it should open through animation. bool getTeleport() const; + /* + Start of tes3mp addition + + Make it possible to change the teleport state from elsewhere + */ + void setTeleport(bool teleportState); + /* + End of tes3mp addition + */ + // Teleport location for the door, if this is a teleporting door. ESM::Position getDoorDest() const; + /* + Start of tes3mp addition + + Make it possible to change the destination position from elsewhere + */ + void setDoorDest(const ESM::Position& position); + /* + End of tes3mp addition + */ + // Destination cell for doors (optional) std::string getDestCell() const; + /* + Start of tes3mp addition + + Make it possible to change the destination cell from elsewhere + */ + void setDestCell(const std::string& cellDescription); + /* + End of tes3mp addition + */ + // Scale applied to mesh float getScale() const; void setScale(float scale); diff --git a/components/openmw-mp/Base/BaseEvent.hpp b/components/openmw-mp/Base/BaseEvent.hpp index b2a66c9fd..6229b94cc 100644 --- a/components/openmw-mp/Base/BaseEvent.hpp +++ b/components/openmw-mp/Base/BaseEvent.hpp @@ -35,10 +35,14 @@ namespace mwmp ESM::Position position; bool objectState; - int doorState; int lockLevel; float scale; + int doorState; + bool teleportState; + ESM::Cell destinationCell; + ESM::Position destinationPosition; + std::string filename; bool allowSkipping; diff --git a/components/openmw-mp/Packets/World/PacketDoorDestination.cpp b/components/openmw-mp/Packets/World/PacketDoorDestination.cpp index 41f3c2764..827d65e40 100644 --- a/components/openmw-mp/Packets/World/PacketDoorDestination.cpp +++ b/components/openmw-mp/Packets/World/PacketDoorDestination.cpp @@ -12,5 +12,16 @@ PacketDoorDestination::PacketDoorDestination(RakNet::RakPeerInterface *peer) : W void PacketDoorDestination::Object(WorldObject &worldObject, bool send) { WorldPacket::Object(worldObject, send); - // Placeholder + + RW(worldObject.teleportState, send); + + if (worldObject.teleportState) + { + RW(worldObject.destinationCell.mData, send, 1); + RW(worldObject.destinationCell.mName, send, 1); + + RW(worldObject.destinationPosition.pos, send, 1); + RW(worldObject.destinationPosition.rot[0], send, 1); + RW(worldObject.destinationPosition.rot[2], send, 1); + } }