From b69e812a52827d5e6e24af9fcd76335abff505f8 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 22 Apr 2018 22:31:56 +0300 Subject: [PATCH 01/10] Utilize inventory character preview lighting color fallback settings --- apps/openmw/mwrender/characterpreview.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index f7219959a..622728c22 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include "../mwbase/environment.hpp" @@ -161,11 +162,18 @@ namespace MWRender lightmodel->setAmbientIntensity(osg::Vec4(0.25, 0.25, 0.25, 1.0)); stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON); - /// \todo Read the fallback values from INIImporter (Inventory:Directional*) ? osg::ref_ptr light = new osg::Light; + const Fallback::Map* fallback = MWBase::Environment::get().getWorld()->getFallback(); + float diffuseR = fallback->getFallbackFloat("Inventory_DirectionalDiffuseR"); + float diffuseG = fallback->getFallbackFloat("Inventory_DirectionalDiffuseG"); + float diffuseB = fallback->getFallbackFloat("Inventory_DirectionalDiffuseB"); + float ambientR = fallback->getFallbackFloat("Inventory_DirectionalAmbientR"); + float ambientG = fallback->getFallbackFloat("Inventory_DirectionalAmbientG"); + float ambientB = fallback->getFallbackFloat("Inventory_DirectionalAmbientB"); + /// \todo Read DirectionalRotationX/DirectionalRotationY light->setPosition(osg::Vec4(-0.3,0.3,0.7, 0.0)); - light->setDiffuse(osg::Vec4(1,1,1,1)); - light->setAmbient(osg::Vec4(0,0,0,1)); + light->setDiffuse(osg::Vec4(diffuseR,diffuseG,diffuseB,1)); + light->setAmbient(osg::Vec4(ambientR,ambientG,ambientB,1)); light->setSpecular(osg::Vec4(0,0,0,0)); light->setLightNum(0); light->setConstantAttenuation(1.f); From bfcdf660f2052dc40dacd9f50a61d64ce14e22d0 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 23 Apr 2018 21:17:25 +0300 Subject: [PATCH 02/10] Utilize inventory character preview lighting rotation fallback settings --- apps/openmw/mwrender/characterpreview.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 622728c22..b3f672f31 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -1,5 +1,6 @@ #include "characterpreview.hpp" +#include #include #include @@ -170,8 +171,12 @@ namespace MWRender float ambientR = fallback->getFallbackFloat("Inventory_DirectionalAmbientR"); float ambientG = fallback->getFallbackFloat("Inventory_DirectionalAmbientG"); float ambientB = fallback->getFallbackFloat("Inventory_DirectionalAmbientB"); - /// \todo Read DirectionalRotationX/DirectionalRotationY - light->setPosition(osg::Vec4(-0.3,0.3,0.7, 0.0)); + float azimuth = osg::DegreesToRadians(180.f - fallback->getFallbackFloat("Inventory_DirectionalRotationX")); + float altitude = osg::DegreesToRadians(fallback->getFallbackFloat("Inventory_DirectionalRotationY")); + float positionX = std::cos(azimuth) * std::sin(altitude); + float positionY = std::sin(azimuth) * std::sin(altitude); + float positionZ = std::cos(altitude); + light->setPosition(osg::Vec4(positionX,positionY,positionZ, 0.0)); light->setDiffuse(osg::Vec4(diffuseR,diffuseG,diffuseB,1)); light->setAmbient(osg::Vec4(ambientR,ambientG,ambientB,1)); light->setSpecular(osg::Vec4(0,0,0,0)); From 6b47f729591d01e9d6bd7d0f1fa1f31fda46863b Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 25 Apr 2018 15:31:49 +0300 Subject: [PATCH 03/10] Set character preview scene ambient to 0, 0, 0 --- apps/openmw/mwrender/characterpreview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index b3f672f31..faaa3799e 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -160,7 +160,7 @@ namespace MWRender stateset->setAttributeAndModes(fog, osg::StateAttribute::OFF|osg::StateAttribute::OVERRIDE); osg::ref_ptr lightmodel = new osg::LightModel; - lightmodel->setAmbientIntensity(osg::Vec4(0.25, 0.25, 0.25, 1.0)); + lightmodel->setAmbientIntensity(osg::Vec4(0.0, 0.0, 0.0, 1.0)); stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON); osg::ref_ptr light = new osg::Light; From 5afcc5686062a7c2cab90186a25cc5e9dbfada29 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 29 Apr 2018 09:24:13 +0400 Subject: [PATCH 04/10] Handle NiLookAtController (feature #4407) --- components/nif/controller.cpp | 12 ++++++++++++ components/nif/controller.hpp | 9 +++++++++ components/nif/niffile.cpp | 1 + components/nif/record.hpp | 3 ++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/components/nif/controller.cpp b/components/nif/controller.cpp index f39132543..ddfa02a09 100644 --- a/components/nif/controller.cpp +++ b/components/nif/controller.cpp @@ -101,6 +101,18 @@ namespace Nif data.post(nif); } + void NiLookAtController::read(NIFStream *nif) + { + Controller::read(nif); + data.read(nif); + } + + void NiLookAtController::post(NIFFile *nif) + { + Controller::post(nif); + data.post(nif); + } + void NiPathController::read(NIFStream *nif) { Controller::read(nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 527bb74af..ce8bff041 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -99,6 +99,15 @@ public: void post(NIFFile *nif); }; +class NiLookAtController : public Controller +{ +public: + NiKeyframeDataPtr data; + + void read(NIFStream *nif); + void post(NIFFile *nif); +}; + class NiUVController : public Controller { public: diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index b4b1caefc..4061247b5 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -108,6 +108,7 @@ static std::map makeFactory() newFactory.insert(makeEntry("NiSequenceStreamHelper", &construct , RC_NiSequenceStreamHelper )); newFactory.insert(makeEntry("NiSourceTexture", &construct , RC_NiSourceTexture )); newFactory.insert(makeEntry("NiSkinInstance", &construct , RC_NiSkinInstance )); + newFactory.insert(makeEntry("NiLookAtController", &construct , RC_NiLookAtController )); return newFactory; } diff --git a/components/nif/record.hpp b/components/nif/record.hpp index b8597f7d1..ee4d508ab 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -93,7 +93,8 @@ enum RecordType RC_NiSourceTexture, RC_NiSkinInstance, RC_RootCollisionNode, - RC_NiSphericalCollider + RC_NiSphericalCollider, + RC_NiLookAtController }; /// Base class for all records From d47b06fe7a7df845c7f58a7df7f9bf87449e774a Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 29 Apr 2018 19:50:39 +0300 Subject: [PATCH 05/10] [Server] Prevent SetGameMode() and SetHostname() from crashing server Previously, turning off communication with the MasterServer from the server config and then attempting to use SetGameMode() or SetHostname() led to a server crash. --- apps/openmw-mp/Script/ScriptFunctions.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/openmw-mp/Script/ScriptFunctions.cpp b/apps/openmw-mp/Script/ScriptFunctions.cpp index edc4cd91b..56ec7b6ef 100644 --- a/apps/openmw-mp/Script/ScriptFunctions.cpp +++ b/apps/openmw-mp/Script/ScriptFunctions.cpp @@ -146,12 +146,14 @@ const char *ScriptFunctions::GetIP(unsigned short pid) noexcept void ScriptFunctions::SetGameMode(const char *gameMode) noexcept { - mwmp::Networking::getPtr()->getMasterClient()->SetModname(gameMode); + if (mwmp::Networking::getPtr()->getMasterClient()) + mwmp::Networking::getPtr()->getMasterClient()->SetModname(gameMode); } void ScriptFunctions::SetHostname(const char *name) noexcept { - mwmp::Networking::getPtr()->getMasterClient()->SetHostname(name); + if (mwmp::Networking::getPtr()->getMasterClient()) + mwmp::Networking::getPtr()->getMasterClient()->SetHostname(name); } void ScriptFunctions::SetServerPassword(const char *password) noexcept From 4b501a39f4f241ea772e00cd92050e2bb2822c08 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 29 Apr 2018 22:32:22 +0300 Subject: [PATCH 06/10] [General] Implement DoorDestination packet & associated script functions --- apps/openmw-mp/Script/Functions/World.cpp | 43 ++++++++-- apps/openmw-mp/Script/Functions/World.hpp | 85 ++++++++++++++++--- apps/openmw/CMakeLists.txt | 12 +-- apps/openmw/mwmp/WorldEvent.cpp | 28 ++++++ apps/openmw/mwmp/WorldEvent.hpp | 1 + .../world/ProcessorDoorDestination.hpp | 2 +- apps/openmw/mwworld/cellref.cpp | 39 +++++++++ apps/openmw/mwworld/cellref.hpp | 30 +++++++ components/openmw-mp/Base/BaseEvent.hpp | 6 +- .../Packets/World/PacketDoorDestination.cpp | 13 ++- 10 files changed, 233 insertions(+), 26 deletions(-) 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); + } } From 099f85be0a31fc80d0ff9d8d3b121177de93d6d3 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Sun, 29 Apr 2018 23:47:17 +0300 Subject: [PATCH 07/10] [General] Implement PlayerMomentum packet & associated script functions --- apps/openmw-mp/Script/Functions/Positions.cpp | 19 +++++++++++++ apps/openmw-mp/Script/Functions/Positions.hpp | 28 ++++++++++++++++++- apps/openmw/mwmp/LocalPlayer.cpp | 7 +++++ apps/openmw/mwmp/LocalPlayer.hpp | 1 + .../player/ProcessorPlayerMomentum.hpp | 2 +- components/openmw-mp/Base/BasePlayer.hpp | 1 + .../Packets/Player/PacketPlayerMomentum.cpp | 3 +- 7 files changed, 58 insertions(+), 3 deletions(-) diff --git a/apps/openmw-mp/Script/Functions/Positions.cpp b/apps/openmw-mp/Script/Functions/Positions.cpp index 11c5d4f40..58a569bc1 100644 --- a/apps/openmw-mp/Script/Functions/Positions.cpp +++ b/apps/openmw-mp/Script/Functions/Positions.cpp @@ -118,6 +118,16 @@ void PositionFunctions::SetRot(unsigned short pid, double x, double z) noexcept player->position.rot[2] = z; } +void PositionFunctions::SetMomentum(unsigned short pid, double x, double y, double z) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + player->momentum.pos[0] = x; + player->momentum.pos[1] = y; + player->momentum.pos[2] = z; +} + void PositionFunctions::SendPos(unsigned short pid) noexcept { Player *player; @@ -126,3 +136,12 @@ void PositionFunctions::SendPos(unsigned short pid) noexcept mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_POSITION)->setPlayer(player); mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_POSITION)->Send(false); } + +void PositionFunctions::SendMomentum(unsigned short pid) noexcept +{ + Player *player; + GET_PLAYER(pid, player, ); + + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MOMENTUM)->setPlayer(player); + mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_MOMENTUM)->Send(false); +} diff --git a/apps/openmw-mp/Script/Functions/Positions.hpp b/apps/openmw-mp/Script/Functions/Positions.hpp index 49cb9f863..071dd6ee4 100644 --- a/apps/openmw-mp/Script/Functions/Positions.hpp +++ b/apps/openmw-mp/Script/Functions/Positions.hpp @@ -19,8 +19,10 @@ \ {"SetPos", PositionFunctions::SetPos},\ {"SetRot", PositionFunctions::SetRot},\ + {"SetMomentum", PositionFunctions::SetMomentum},\ \ - {"SendPos", PositionFunctions::SendPos} + {"SendPos", PositionFunctions::SendPos},\ + {"SendMomentum", PositionFunctions::SendMomentum} class PositionFunctions @@ -144,6 +146,20 @@ public: */ static void SetRot(unsigned short pid, double x, double z) noexcept; + /** + * \brief Set the momentum of a player. + * + * This changes the coordinates recorded for that player's momentum in the server memory, but + * does not by itself send a packet. + * + * \param pid The player ID. + * \param x The X momentum. + * \param y The Y momentum. + * \param z The Z momentum. + * \return void + */ + static void SetMomentum(unsigned short pid, double x, double y, double z) noexcept; + /** * \brief Send a PlayerPosition packet about a player. * @@ -153,6 +169,16 @@ public: * \return void */ static void SendPos(unsigned short pid) noexcept; + + /** + * \brief Send a PlayerMomentum packet about a player. + * + * It is only sent to the affected player. + * + * \param pid The player ID. + * \return void + */ + static void SendMomentum(unsigned short pid) noexcept; }; #endif //OPENMW_POSITIONAPI_HPP diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 1e07fc203..8d329e1b6 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -1002,6 +1002,13 @@ void LocalPlayer::setPosition() updateAnimFlags(true); } +void LocalPlayer::setMomentum() +{ + MWBase::World *world = MWBase::Environment::get().getWorld(); + MWWorld::Ptr ptrPlayer = world->getPlayerPtr(); + world->setInertialForce(ptrPlayer, momentum.asVec3()); +} + void LocalPlayer::setCell() { MWBase::World *world = MWBase::Environment::get().getWorld(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index 0c25f374e..741c9279f 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -54,6 +54,7 @@ namespace mwmp void setBounty(); void setReputation(); void setPosition(); + void setMomentum(); void setCell(); void setClass(); void setEquipment(); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerMomentum.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerMomentum.hpp index 6d1aa4820..87e1a9d2a 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerMomentum.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerMomentum.hpp @@ -23,7 +23,7 @@ namespace mwmp if (!isRequest()) { LocalPlayer &localPlayer = static_cast(*player); - //localPlayer.setMomentum(); + localPlayer.setMomentum(); } } }; diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 65aebb05e..9484ff9f0 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -294,6 +294,7 @@ namespace mwmp ESM::Position position; ESM::Position direction; ESM::Position previousCellPosition; + ESM::Position momentum; ESM::Cell cell; ESM::NPC npc; ESM::NpcStats npcStats; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerMomentum.cpp b/components/openmw-mp/Packets/Player/PacketPlayerMomentum.cpp index ceaebc0be..00eb49e9d 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerMomentum.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerMomentum.cpp @@ -12,5 +12,6 @@ PacketPlayerMomentum::PacketPlayerMomentum(RakNet::RakPeerInterface *peer) : Pla void PacketPlayerMomentum::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); - // Placeholder + + RW(player->momentum.pos, send, 1); } From 1b1e5e86d12e0026b212c2645c6d2f278fc18d6c Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 1 May 2018 18:19:52 +0300 Subject: [PATCH 08/10] [Client] Avoid sending CellStates to server after initialization Although b4e8560698fbe9ef30e1c5e004bf7f928e85c6a8 made players instantly able to see each other on minimalist servers that did not change their cells from the default, it created problems with the default CoreScripts where players need to be logged in before receipt of a CellStates packet from them is taken into account, with the result being that a player was recorded as having loaded their initial cells on the server's C++ side but not on the Lua side. It may simply be best to expect servers to set player cells. --- apps/openmw/mwmp/Main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwmp/Main.cpp b/apps/openmw/mwmp/Main.cpp index c62d297e0..42ff33970 100644 --- a/apps/openmw/mwmp/Main.cpp +++ b/apps/openmw/mwmp/Main.cpp @@ -227,7 +227,6 @@ void Main::updateWorld(float dt) const mNetworking->getPlayerPacket(ID_PLAYER_BASEINFO)->Send(); mNetworking->getPlayerPacket(ID_LOADED)->Send(); mLocalPlayer->updateStatsDynamic(true); - mLocalPlayer->sendCellStates(); get().getGUIController()->setChatVisible(true); } else From df0f9b0f5ec540c2c863b14b28b1e55359f50bdb Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 1 May 2018 19:34:21 +0300 Subject: [PATCH 09/10] [Client] Require a certain Skill progress amount before sending packet --- apps/openmw/mwmp/LocalPlayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 8d329e1b6..94e88018d 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -290,7 +290,7 @@ void LocalPlayer::updateSkills(bool forceUpdate) // Update a skill if its base value has changed at all or its progress has changed enough if (ptrNpcStats.getSkill(i).getBase() != npcStats.mSkills[i].mBase || ptrNpcStats.getSkill(i).getModifier() != npcStats.mSkills[i].mMod || - ptrNpcStats.getSkill(i).getProgress() != npcStats.mSkills[i].mProgress || + abs(ptrNpcStats.getSkill(i).getProgress() - npcStats.mSkills[i].mProgress) > 0.75 || forceUpdate) { skillIndexChanges.push_back(i); From 51fd9372508e65f17591cacaef6edd0fc2896829 Mon Sep 17 00:00:00 2001 From: David Cernat Date: Tue, 1 May 2018 20:39:43 +0300 Subject: [PATCH 10/10] [Server] Remove hardcoded debug messages when using script callbacks --- apps/openmw-mp/Script/Script.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/openmw-mp/Script/Script.hpp b/apps/openmw-mp/Script/Script.hpp index 7b446e0b2..9076baea6 100644 --- a/apps/openmw-mp/Script/Script.hpp +++ b/apps/openmw-mp/Script/Script.hpp @@ -91,9 +91,6 @@ public: if (!callback) continue; - - LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Called function \"%s\"", data.name); - if (script->script_type == SCRIPT_CPP) result = reinterpret_cast>>(callback)(std::forward(args)...); #if defined (ENABLE_PAWN) @@ -134,8 +131,6 @@ public: if (!callback) continue; - LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Called function \"%s\"", data.name); - if (script->script_type == SCRIPT_CPP) reinterpret_cast>>(callback)(std::forward(args)...); #if defined (ENABLE_PAWN)