[General] Track objects directly placed by players in ObjectPlace

This allows the OnPCDrop variable to get set correctly even when object placements have to go through the server first in order to gain a unique multiplayer index (mpNum).

Among other things, this makes it possible to roll marijuana joints in the popular mod "Tribunal Code Patch".
pull/376/head
David Cernat 7 years ago
parent 595bc5a152
commit 420dab10e1

@ -289,6 +289,7 @@ void WorldFunctions::SetContainerItemEnchantmentCharge(double enchantmentCharge)
void WorldFunctions::AddWorldObject() noexcept
{
tempWorldObject.droppedByPlayer = false;
writeEvent.worldObjects.push_back(tempWorldObject);
tempWorldObject = emptyWorldObject;

@ -249,6 +249,17 @@ namespace MWBase
virtual MWWorld::Ptr getFacedObject() = 0;
///< Return pointer to the object the player is looking at, if it is within activation range
/*
Start of tes3mp addition
This has been declared here so it can be accessed from places
other than MWWorld::World
*/
virtual void PCDropped(const MWWorld::Ptr& item) = 0;
/*
End of tes3mp addition
*/
virtual float getDistanceToFacedObject() = 0;
virtual float getMaxActivationDistance() = 0;

@ -74,7 +74,7 @@ namespace MWGui
*/
mwmp::WorldEvent *worldEvent = mwmp::Main::get().getNetworking()->getWorldEvent();
worldEvent->reset();
worldEvent->addObjectPlace(dropped);
worldEvent->addObjectPlace(dropped, true);
worldEvent->sendObjectPlace();
/*
End of tes3mp addition

@ -158,6 +158,8 @@ void WorldEvent::editContainers(MWWorld::CellStore* cellStore)
void WorldEvent::placeObjects(MWWorld::CellStore* cellStore)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
for (const auto &worldObject : worldObjects)
{
LOG_APPEND(Log::LOG_VERBOSE, "- cellRef: %s, %i, %i, count: %i, charge: %i, enchantmentCharge: %i", worldObject.refId.c_str(),
@ -172,7 +174,7 @@ void WorldEvent::placeObjects(MWWorld::CellStore* cellStore)
// Only create this object if it doesn't already exist
if (!ptrFound)
{
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), worldObject.refId, 1);
MWWorld::ManualRef ref(world->getStore(), worldObject.refId, 1);
MWWorld::Ptr newPtr = ref.getPtr();
if (worldObject.count > 1)
@ -185,10 +187,13 @@ void WorldEvent::placeObjects(MWWorld::CellStore* cellStore)
newPtr.getCellRef().setEnchantmentCharge(worldObject.enchantmentCharge);
newPtr.getCellRef().setGoldValue(worldObject.goldValue);
newPtr = MWBase::Environment::get().getWorld()->placeObject(newPtr, cellStore, worldObject.position);
newPtr = world->placeObject(newPtr, cellStore, worldObject.position);
// Because gold automatically gets replaced with a new object, make sure we set the mpNum at the end
newPtr.getCellRef().setMpNum(worldObject.mpNum);
if (guid == Main::get().getLocalPlayer()->guid && worldObject.droppedByPlayer)
world->PCDropped(newPtr);
}
else
LOG_APPEND(Log::LOG_VERBOSE, "-- Object already existed!");
@ -608,7 +613,7 @@ void WorldEvent::playVideo()
}
}
void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr)
void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer)
{
if (ptr.getCellRef().getRefId().find("$dynamic") != string::npos)
{
@ -624,6 +629,7 @@ void WorldEvent::addObjectPlace(const MWWorld::Ptr& ptr)
worldObject.mpNum = 0;
worldObject.charge = ptr.getCellRef().getCharge();
worldObject.enchantmentCharge = ptr.getCellRef().getEnchantmentCharge();
worldObject.droppedByPlayer = droppedByPlayer;
// Make sure we send the RefData position instead of the CellRef one, because that's what
// we actually see on this client

@ -41,7 +41,7 @@ namespace mwmp
void playMusic();
void playVideo();
void addObjectPlace(const MWWorld::Ptr& ptr);
void addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer = false);
void addObjectSpawn(const MWWorld::Ptr& ptr);
void addObjectSpawn(const MWWorld::Ptr& ptr, const MWWorld::Ptr& master);
void addObjectDelete(const MWWorld::Ptr& ptr);

@ -136,11 +136,21 @@ namespace MWWorld
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
/*
Start of tes3mp change (major)
This has been turned into a public method so it can be used in
multiplayer's different approach to placing items
*/
void PCDropped(const Ptr& item);
/*
End of tes3mp change (major)
*/
public: // FIXME
void removeContainerScripts(const Ptr& reference) override;
private:
void addContainerScripts(const Ptr& reference, CellStore* cell);
void PCDropped (const Ptr& item);
void processDoors(float duration);
///< Run physics simulation and modify \a world accordingly.

@ -51,6 +51,7 @@ namespace mwmp
std::string varName;
bool isDisarmed;
bool droppedByPlayer;
Target master;
bool hasMaster;

@ -17,4 +17,5 @@ void PacketObjectPlace::Object(WorldObject &worldObject, bool send)
RW(worldObject.enchantmentCharge, send);
RW(worldObject.goldValue, send);
RW(worldObject.position, send);
RW(worldObject.droppedByPlayer, send);
}

Loading…
Cancel
Save