diff --git a/apps/openmw-mp/NetActor.cpp b/apps/openmw-mp/NetActor.cpp index c3c14c0f4..09228a507 100644 --- a/apps/openmw-mp/NetActor.cpp +++ b/apps/openmw-mp/NetActor.cpp @@ -60,6 +60,17 @@ void NetActor::setRotation(float x, float z) positionChanged = true; } +void NetActor::setMomentum(float x, float y, float z) +{ + netCreature->momentum.pos[0] = x; + netCreature->momentum.pos[1] = y; + netCreature->momentum.pos[2] = z; + + if (!momentumChanged && isPlayer()) + toPlayer()->addToUpdateQueue(); + momentumChanged = true; +} + std::tuple NetActor::getHealth() const { return make_tuple(netCreature->creatureStats.mDynamic[0].mBase, netCreature->creatureStats.mDynamic[0].mCurrent); diff --git a/apps/openmw-mp/NetActor.hpp b/apps/openmw-mp/NetActor.hpp index bdef84ac3..ae92d05ce 100644 --- a/apps/openmw-mp/NetActor.hpp +++ b/apps/openmw-mp/NetActor.hpp @@ -39,6 +39,8 @@ public: std::tuple getRotation() const; void setRotation(float x, float z); + void setMomentum(float x, float y, float z); + /** * * @return base, current @@ -68,7 +70,7 @@ public: bool isPlayer() const { return isActorPlayer; } Player *toPlayer(); protected: - bool baseInfoChanged, shapeshiftChanged, levelChanged, statsChanged, positionChanged, attributesChanged, skillsChanged; + bool baseInfoChanged, shapeshiftChanged, levelChanged, statsChanged, positionChanged, momentumChanged, attributesChanged, skillsChanged; mwmp::BasePlayer *basePlayer; mwmp::BaseNetCreature *netCreature; diff --git a/apps/openmw-mp/Object.cpp b/apps/openmw-mp/Object.cpp index 631475364..e22c4be3c 100644 --- a/apps/openmw-mp/Object.cpp +++ b/apps/openmw-mp/Object.cpp @@ -26,8 +26,10 @@ void Object::Init(LuaState &lua) "goldValue", sol::property(&Object::getGoldValue, &Object::setGoldValue), "scale", sol::property(&Object::getScale, &Object::setScale), "state", sol::property(&Object::getState, &Object::setState), - "doorState", sol::property(&Object::getDoorState, &Object::setDoorState), "lockLevel", sol::property(&Object::getLockLevel, &Object::setLockLevel), + "doorState", sol::property(&Object::getDoorState, &Object::setDoorState), + "setTeleportState", &Object::setTeleportState, + "setDoorDestination", &Object::setDoorDestination, "setDisarmState", &Object::setDisarmState, "setMasterState", &Object::setMasterState ); @@ -215,6 +217,24 @@ void Object::setLockLevel(int locklevel) object.lockLevel = locklevel; } +void Object::setTeleportState(bool state) +{ + changedDoorDestination = true; + object.teleportState = state; +} + +void Object::setDoorDestination(const std::string &cellDescription, float posX, float posY, float posZ, float rotX, float rotY, float rotZ) +{ + changedDoorDestination = true; + object.destinationCell = Utils::getCellFromDescription(cellDescription); + object.destinationPosition.pos[0] = posX; + object.destinationPosition.pos[1] = posY; + object.destinationPosition.pos[2] = posZ; + object.destinationPosition.rot[0] = rotX; + object.destinationPosition.rot[1] = rotY; + object.destinationPosition.rot[2] = rotZ; +} + void Object::setDisarmState(bool state) { changedObjectTrap = true; @@ -344,6 +364,7 @@ void ObjectController::sendObjects(shared_ptr player, shared_ptr player, shared_ptrobject); } + if (object->changedDoorDestination && validNewObjOrCopy) + { + changed[Type::DOOR_DESTINATION] = true; + events[Type::DOOR_DESTINATION].worldObjects.push_back(object->object); + } if (object->changedObjectState && validNewObjOrCopy) { changed[Type::OBJECT_STATE] = true; @@ -424,6 +450,16 @@ void ObjectController::sendObjects(shared_ptr player, shared_ptrSend(true); } + if (changed[Type::DOOR_DESTINATION]) + { + auto packet = worldCtrl->GetPacket(ID_DOOR_DESTINATION); + auto &event = events[Type::DOOR_DESTINATION]; + packet->setEvent(&event); + packet->Send(false); + + if (broadcast) + packet->Send(true); + } if (changed[Type::OBJECT_STATE]) { auto packet = worldCtrl->GetPacket(ID_OBJECT_STATE); diff --git a/apps/openmw-mp/Object.hpp b/apps/openmw-mp/Object.hpp index d2f137d42..bd5c29b8c 100644 --- a/apps/openmw-mp/Object.hpp +++ b/apps/openmw-mp/Object.hpp @@ -84,10 +84,13 @@ public: int getLockLevel() const; void setLockLevel(int locklevel); + void setTeleportState(bool state); + void setDoorDestination(const std::string &cellDescription, float posX, float posY, float posZ, float rotX, float rotY, float rotZ); + void setDisarmState(bool state); void setMasterState(bool state); - bool changedDoorState, changedObjectState, changedObjectScale, changedObjectTrap, changedObjectLock, + bool changedDoorState, changedDoorDestination, changedObjectState, changedObjectScale, changedObjectTrap, changedObjectLock, changedObjectDelete, changedObjectSpawn, changedObjectPlace; }; diff --git a/apps/openmw-mp/Player.cpp b/apps/openmw-mp/Player.cpp index dd62dddfa..c3b4b51b3 100644 --- a/apps/openmw-mp/Player.cpp +++ b/apps/openmw-mp/Player.cpp @@ -21,6 +21,7 @@ void Player::Init(LuaState &lua) "setPosition", &NetActor::setPosition, "getRotation", &NetActor::getRotation, "setRotation", &NetActor::setRotation, + "setMomentum", &NetActor::setMomentum, "getHealth", &NetActor::getHealth, "setHealth", &NetActor::setHealth, @@ -184,6 +185,13 @@ void Player::update() packet->Send(false); } + if (momentumChanged) + { + auto packet = plPCtrl->GetPacket(ID_PLAYER_MOMENTUM); + packet->setPlayer(basePlayer); + packet->Send(false); + } + if (shapeshiftChanged) { auto packet = plPCtrl->GetPacket(ID_PLAYER_SHAPESHIFT); diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 5ce750edc..03a13b72c 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/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 3afdac766..70bf66034 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); @@ -1007,6 +1007,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 b17f6630a..868f07644 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/Main.cpp b/apps/openmw/mwmp/Main.cpp index ec298bc21..d62056def 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 diff --git a/apps/openmw/mwmp/WorldEvent.cpp b/apps/openmw/mwmp/WorldEvent.cpp index 3994277d0..1eb5596eb 100644 --- a/apps/openmw/mwmp/WorldEvent.cpp +++ b/apps/openmw/mwmp/WorldEvent.cpp @@ -557,6 +557,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().mIndex, 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 ec6c4ecbb..a14940fad 100644 --- a/apps/openmw/mwmp/WorldEvent.hpp +++ b/apps/openmw/mwmp/WorldEvent.hpp @@ -34,6 +34,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/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/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp b/apps/openmw/mwmp/processors/world/ProcessorDoorDestination.hpp index 9cfb268b0..819579a2c 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/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index f7219959a..faaa3799e 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -1,5 +1,6 @@ #include "characterpreview.hpp" +#include #include #include @@ -13,6 +14,7 @@ #include #include +#include #include #include "../mwbase/environment.hpp" @@ -158,14 +160,25 @@ 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); - /// \todo Read the fallback values from INIImporter (Inventory:Directional*) ? osg::ref_ptr light = new osg::Light; - 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)); + 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"); + 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)); light->setLightNum(0); light->setConstantAttenuation(1.f); diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 0dd4845aa..f7675afff 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 00aabf0da..b339a0069 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/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 diff --git a/components/openmw-mp/Base/BaseEvent.hpp b/components/openmw-mp/Base/BaseEvent.hpp index bf31f12f5..1fb136c49 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/Base/BaseNetCreature.hpp b/components/openmw-mp/Base/BaseNetCreature.hpp index 7db61eb1c..f757c4c5d 100644 --- a/components/openmw-mp/Base/BaseNetCreature.hpp +++ b/components/openmw-mp/Base/BaseNetCreature.hpp @@ -20,6 +20,7 @@ namespace mwmp public: ESM::Position position; ESM::Position direction; + ESM::Position momentum; ESM::CreatureStats creatureStats; ESM::Cell cell; diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index 03845791b..2f5ada423 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -319,6 +319,7 @@ namespace mwmp bool ignorePosPacket; ESM::Position previousCellPosition; + ESM::NPC npc; ESM::NpcStats npcStats; ESM::Creature creature; 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); } 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); + } }