[General] Implement ObjectActivate packet & associated script functions

fix/skillcap
David Cernat 7 years ago
parent 81b160cae8
commit 6ebe09375f

@ -58,6 +58,21 @@ unsigned char ObjectFunctions::GetObjectListContainerSubAction() noexcept
return readObjectList->containerSubAction;
}
bool ObjectFunctions::IsObjectPlayer(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).isPlayer;
}
int ObjectFunctions::GetObjectPid(unsigned int i) noexcept
{
Player *player = Players::getPlayer(readObjectList->baseObjects.at(i).guid);
if (player != nullptr)
return player->getId();
return -1;
}
const char *ObjectFunctions::GetObjectRefId(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).refId.c_str();
@ -113,6 +128,41 @@ int ObjectFunctions::GetObjectLockLevel(unsigned int i) noexcept
return readObjectList->baseObjects.at(i).lockLevel;
}
bool ObjectFunctions::DoesObjectHavePlayerActivating(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).activatingActor.isPlayer;
}
int ObjectFunctions::GetObjectActivatingPid(unsigned int i) noexcept
{
Player *player = Players::getPlayer(readObjectList->baseObjects.at(i).activatingActor.guid);
if (player != nullptr)
return player->getId();
return -1;
}
const char *ObjectFunctions::GetObjectActivatingRefId(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).activatingActor.refId.c_str();
}
unsigned int ObjectFunctions::GetObjectActivatingRefNum(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).activatingActor.refNum;
}
unsigned int ObjectFunctions::GetObjectActivatingMpNum(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).activatingActor.mpNum;
}
const char *ObjectFunctions::GetObjectActivatingName(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).activatingActor.name.c_str();
}
bool ObjectFunctions::GetObjectSummonState(unsigned int i) noexcept
{
return readObjectList->baseObjects.at(i).isSummon;
@ -399,6 +449,17 @@ void ObjectFunctions::AddContainerItem() noexcept
tempContainerItem = emptyContainerItem;
}
void ObjectFunctions::SendObjectActivate(bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept
{
mwmp::ObjectPacket *packet = mwmp::Networking::get().getObjectPacketController()->GetPacket(ID_OBJECT_ACTIVATE);
packet->setObjectList(&writeObjectList);
if (!skipAttachedPlayer)
packet->Send(false);
if (sendToOtherPlayers)
packet->Send(true);
}
void ObjectFunctions::SendObjectPlace(bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept
{
mwmp::ObjectPacket *packet = mwmp::Networking::get().getObjectPacketController()->GetPacket(ID_OBJECT_PLACE);

@ -13,6 +13,8 @@
{"GetObjectListAction", ObjectFunctions::GetObjectListAction},\
{"GetObjectListContainerSubAction", ObjectFunctions::GetObjectListContainerSubAction},\
\
{"IsObjectPlayer", ObjectFunctions::IsObjectPlayer},\
{"GetObjectPid", ObjectFunctions::GetObjectPid},\
{"GetObjectRefId", ObjectFunctions::GetObjectRefId},\
{"GetObjectRefNum", ObjectFunctions::GetObjectRefNum},\
{"GetObjectMpNum", ObjectFunctions::GetObjectMpNum},\
@ -25,6 +27,13 @@
{"GetObjectDoorState", ObjectFunctions::GetObjectDoorState},\
{"GetObjectLockLevel", ObjectFunctions::GetObjectLockLevel},\
\
{"DoesObjectHavePlayerActivating", ObjectFunctions::DoesObjectHavePlayerActivating},\
{"GetObjectActivatingPid", ObjectFunctions::GetObjectActivatingPid},\
{"GetObjectActivatingRefId", ObjectFunctions::GetObjectActivatingRefId},\
{"GetObjectActivatingRefNum", ObjectFunctions::GetObjectActivatingRefNum},\
{"GetObjectActivatingMpNum", ObjectFunctions::GetObjectActivatingMpNum},\
{"GetObjectActivatingName", ObjectFunctions::GetObjectActivatingName},\
\
{"GetObjectSummonState", ObjectFunctions::GetObjectSummonState},\
{"GetObjectSummonDuration", ObjectFunctions::GetObjectSummonDuration},\
{"DoesObjectHavePlayerSummoner", ObjectFunctions::DoesObjectHavePlayerSummoner},\
@ -89,6 +98,7 @@
{"AddObject", ObjectFunctions::AddObject},\
{"AddContainerItem", ObjectFunctions::AddContainerItem},\
\
{"SendObjectActivate", ObjectFunctions::SendObjectActivate},\
{"SendObjectPlace", ObjectFunctions::SendObjectPlace},\
{"SendObjectSpawn", ObjectFunctions::SendObjectSpawn},\
{"SendObjectDelete", ObjectFunctions::SendObjectDelete},\
@ -174,9 +184,35 @@ public:
*/
static unsigned char GetObjectListContainerSubAction() noexcept;
/**
* \brief Check whether the object at a certain index in the read object list is a
* player.
*
* Note: Although most player data and events are dealt with in Player packets,
* object activation is general enough for players themselves to be included
* as objects in ObjectActivate packets.
*
* \param i The index of the object.
* \return Whether the object is a player.
*/
static bool IsObjectPlayer(unsigned int i) noexcept;
/**
* \brief Get the player ID of the object at a certain index in the read object list,
* only valid if the object is a player.
*
* Note: Currently, players can only be objects in ObjectActivate and ConsoleCommand
* packets.
*
* \param i The index of the object.
* \return The player ID of the object.
*/
static int GetObjectPid(unsigned int i) noexcept;
/**
* \brief Get the refId of the object at a certain index in the read object list.
*
* \param i The index of the object.
* \return The refId.
*/
static const char *GetObjectRefId(unsigned int i) noexcept;
@ -263,6 +299,60 @@ public:
*/
static int GetObjectLockLevel(unsigned int i) noexcept;
/**
* \brief Check whether the object at a certain index in the read object list has been
* activated by a player.
*
* \param i The index of the object.
* \return Whether the object has been activated by a player.
*/
static bool DoesObjectHavePlayerActivating(unsigned int i) noexcept;
/**
* \brief Get the player ID of the player activating the object at a certain index in the
* read object list.
*
* \param i The index of the object.
* \return The player ID of the activating player.
*/
static int GetObjectActivatingPid(unsigned int i) noexcept;
/**
* \brief Get the refId of the actor activating the object at a certain index in the read
* object list.
*
* \param i The index of the object.
* \return The refId of the activating actor.
*/
static const char *GetObjectActivatingRefId(unsigned int i) noexcept;
/**
* \brief Get the refNum of the actor activating the object at a certain index in the read
* object list.
*
* \param i The index of the object.
* \return The refNum of the activating actor.
*/
static unsigned int GetObjectActivatingRefNum(unsigned int i) noexcept;
/**
* \brief Get the mpNum of the actor activating the object at a certain index in the read
* object list.
*
* \param i The index of the object.
* \return The mpNum of the activating actor.
*/
static unsigned int GetObjectActivatingMpNum(unsigned int i) noexcept;
/**
* \brief Get the name of the actor activating the object at a certain index in the read
* object list.
*
* \param i The index of the object.
* \return The name of the activating actor.
*/
static const char *GetObjectActivatingName(unsigned int i) noexcept;
/**
* \brief Check whether the object at a certain index in the read object list is a
* summon.
@ -767,6 +857,17 @@ public:
*/
static void AddContainerItem() noexcept;
/**
* \brief Send an ObjectActivate packet.
*
* \param sendToOtherPlayers Whether this packet should be sent to players other than the
* player attached to the packet (false by default).
* \param skipAttachedPlayer Whether the packet should skip being sent to the player attached
* to the packet (false by default).
* \return void
*/
static void SendObjectActivate(bool sendToOtherPlayers, bool skipAttachedPlayer) noexcept;
/**
* \brief Send an ObjectPlace packet.
*

@ -122,12 +122,16 @@ add_openmw_dir (mwmp/processors/player ProcessorChatMessage ProcessorGUIMessageB
ProcessorPlayerSpellbook ProcessorPlayerStatsDynamic ProcessorPlayerTopic
)
add_openmw_dir (mwmp/processors/object 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
add_openmw_dir (mwmp/processors/object BaseObjectProcessor
ProcessorConsoleCommand ProcessorContainer ProcessorDoorDestination ProcessorDoorState ProcessorMusicPlay
ProcessorVideoPlay
ProcessorObjectActivate ProcessorObjectAnimPlay ProcessorObjectAttach ProcessorObjectCollision ProcessorObjectDelete
ProcessorObjectLock ProcessorObjectMove ProcessorObjectPlace ProcessorObjectReset ProcessorObjectRotate
ProcessorObjectScale ProcessorObjectSpawn ProcessorObjectState ProcessorObjectTrap ProcessorScriptLocalShort
ProcessorScriptLocalFloat ProcessorScriptMemberShort ProcessorScriptMemberFloat ProcessorScriptGlobalShort
ProcessorScriptGlobalFloat
)
add_openmw_dir (mwmp/processors/worldstate ProcessorCellCreate ProcessorCellReplace ProcessorRecordDynamic

@ -2,6 +2,18 @@
#include <components/esm/aisequence.hpp>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/Networking.hpp"
#include "../mwmp/ObjectList.hpp"
/*
End of tes3mp addition
*/
#include "../mwbase/world.hpp"
#include "../mwbase/environment.hpp"
@ -63,7 +75,31 @@ namespace MWMechanics
if (pathTo(actor, dest, duration, MWBase::Environment::get().getWorld()->getMaxActivationDistance())) //Stop when you get in activation range
{
// activate when reached
MWBase::Environment::get().getWorld()->activate(target, actor);
/*
Start of tes3mp change (major)
Disable unilateral activation on this client and expect the server's reply to our
packet to do it instead
*/
//MWBase::Environment::get().getWorld()->activate(target, actor);
/*
End of tes3mp change (major)
*/
/*
Start of tes3mp addition
Send an ID_OBJECT_ACTIVATE packet every time an object is activated here
*/
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->addObjectActivate(target, actor);
objectList->sendObjectActivate();
/*
End of tes3mp addition
*/
return true;
}

@ -262,6 +262,58 @@ void ObjectList::editContainers(MWWorld::CellStore* cellStore)
}
}
void ObjectList::activateObjects(MWWorld::CellStore* cellStore)
{
for (const auto &baseObject : baseObjects)
{
MWWorld::Ptr ptrFound;
if (baseObject.isPlayer)
{
if (baseObject.guid == Main::get().getLocalPlayer()->guid)
{
LOG_APPEND(Log::LOG_VERBOSE, "-- Running on local player");
ptrFound = Main::get().getLocalPlayer()->getPlayerPtr();
}
else
{
DedicatedPlayer *player = PlayerList::getPlayer(baseObject.guid);
if (player != 0)
{
LOG_APPEND(Log::LOG_VERBOSE, "-- Running on player %s", player->npc.mName.c_str());
ptrFound = player->getPtr();
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "-- Could not find target player!");
}
}
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "-- Running on cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
}
if (ptrFound)
{
MWWorld::Ptr activatingActorPtr;
if (baseObject.activatingActor.isPlayer)
activatingActorPtr = MechanicsHelper::getPlayerPtr(baseObject.activatingActor);
else
activatingActorPtr = cellStore->searchExact(baseObject.activatingActor.refNum, baseObject.activatingActor.mpNum);
if (activatingActorPtr)
{
LOG_APPEND(Log::LOG_VERBOSE, "-- Object has activating actor: %s", activatingActorPtr.getCellRef().getRefId().c_str());
MWBase::Environment::get().getWorld()->activate(ptrFound, activatingActorPtr);
}
}
}
}
void ObjectList::placeObjects(MWWorld::CellStore* cellStore)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
@ -621,7 +673,7 @@ void ObjectList::runConsoleCommands(MWWorld::CellStore* cellStore)
{
if (baseObject.guid == Main::get().getLocalPlayer()->guid)
{
LOG_APPEND(Log::LOG_VERBOSE, "-- running on local player");
LOG_APPEND(Log::LOG_VERBOSE, "-- Running on local player");
windowManager->setConsolePtr(Main::get().getLocalPlayer()->getPlayerPtr());
windowManager->executeCommandInConsole(consoleCommand);
}
@ -631,7 +683,7 @@ void ObjectList::runConsoleCommands(MWWorld::CellStore* cellStore)
if (player != 0)
{
LOG_APPEND(Log::LOG_VERBOSE, "-- running on player %s", player->npc.mName.c_str());
LOG_APPEND(Log::LOG_VERBOSE, "-- Running on player %s", player->npc.mName.c_str());
windowManager->setConsolePtr(player->getPtr());
windowManager->executeCommandInConsole(consoleCommand);
}
@ -639,7 +691,7 @@ void ObjectList::runConsoleCommands(MWWorld::CellStore* cellStore)
}
else
{
LOG_APPEND(Log::LOG_VERBOSE, "-- running on cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
LOG_APPEND(Log::LOG_VERBOSE, "-- Running on cellRef: %s %i-%i", baseObject.refId.c_str(), baseObject.refNum, baseObject.mpNum);
MWWorld::Ptr ptrFound = cellStore->searchExact(baseObject.refNum, baseObject.mpNum);
@ -792,6 +844,35 @@ void ObjectList::addRequestedContainers(MWWorld::CellStore* cellStore, const std
}
}
void ObjectList::addObjectActivate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& activatingActor)
{
cell = *ptr.getCell()->getCell();
mwmp::BaseObject baseObject;
if (ptr == MWBase::Environment::get().getWorld()->getPlayerPtr())
{
baseObject.isPlayer = true;
baseObject.guid = mwmp::Main::get().getLocalPlayer()->guid;
}
else if (mwmp::PlayerList::isDedicatedPlayer(ptr))
{
baseObject.isPlayer = true;
baseObject.guid = mwmp::PlayerList::getPlayer(ptr)->guid;
}
else
{
baseObject.isPlayer = false;
baseObject.refId = ptr.getCellRef().getRefId();
baseObject.refNum = ptr.getCellRef().getRefNum().mIndex;
baseObject.mpNum = ptr.getCellRef().getMpNum();
}
baseObject.activatingActor = MechanicsHelper::getTarget(activatingActor);
addObject(baseObject);
}
void ObjectList::addObjectPlace(const MWWorld::Ptr& ptr, bool droppedByPlayer)
{
if (ptr.getCellRef().getRefId().find("$dynamic") != string::npos)
@ -1011,6 +1092,12 @@ void ObjectList::addScriptGlobalShort(std::string varName, int shortVal)
addObject(baseObject);
}
void ObjectList::sendObjectActivate()
{
mwmp::Main::get().getNetworking()->getObjectPacket(ID_OBJECT_ACTIVATE)->setObjectList(this);
mwmp::Main::get().getNetworking()->getObjectPacket(ID_OBJECT_ACTIVATE)->Send();
}
void ObjectList::sendObjectPlace()
{
if (baseObjects.size() == 0)

@ -24,6 +24,7 @@ namespace mwmp
void editContainers(MWWorld::CellStore* cellStore);
void activateObjects(MWWorld::CellStore* cellStore);
void placeObjects(MWWorld::CellStore* cellStore);
void spawnObjects(MWWorld::CellStore* cellStore);
void deleteObjects(MWWorld::CellStore* cellStore);
@ -49,6 +50,7 @@ namespace mwmp
void addAllContainers(MWWorld::CellStore* cellStore);
void addRequestedContainers(MWWorld::CellStore* cellStore, const std::vector<BaseObject>& requestObjects);
void addObjectActivate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& activatingActor);
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, float spawnDuration);
@ -67,6 +69,7 @@ namespace mwmp
void addScriptMemberShort(std::string refId, int index, int shortVal);
void addScriptGlobalShort(std::string varName, int shortVal);
void sendObjectActivate();
void sendObjectPlace();
void sendObjectSpawn();
void sendObjectDelete();

@ -17,7 +17,7 @@ namespace mwmp
{
BaseObjectProcessor::Do(packet, objectList);
//objectList.activateObjects(ptrCellStore);
objectList.activateObjects(ptrCellStore);
}
};

@ -3,6 +3,18 @@
#include <stdexcept>
#include <iostream>
/*
Start of tes3mp addition
Include additional headers for multiplayer purposes
*/
#include "../mwmp/Main.hpp"
#include "../mwmp/Networking.hpp"
#include "../mwmp/ObjectList.hpp"
/*
End of tes3mp addition
*/
#include <components/esm/esmreader.hpp>
#include <components/esm/esmwriter.hpp>
#include <components/esm/player.hpp>
@ -231,7 +243,29 @@ namespace MWWorld
if (!toActivate.getClass().canBeActivated(toActivate))
return;
MWBase::Environment::get().getWorld()->activate(toActivate, player);
/*
Start of tes3mp change (major)
Disable unilateral activation on this client and expect the server's reply to our
packet to do it instead
*/
//MWBase::Environment::get().getWorld()->activate(toActivate, player);
/*
End of tes3mp change (major)
*/
/*
Start of tes3mp addition
Send an ID_OBJECT_ACTIVATE packet every time an object is activated here
*/
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
objectList->reset();
objectList->addObjectActivate(toActivate, player);
objectList->sendObjectActivate();
/*
End of tes3mp addition
*/
}
bool Player::wasTeleported() const

@ -59,6 +59,8 @@ namespace mwmp
bool isDisarmed;
bool droppedByPlayer;
Target activatingActor;
bool isSummon;
float summonDuration;
Target master;

@ -9,7 +9,40 @@ PacketObjectActivate::PacketObjectActivate(RakNet::RakPeerInterface *peer) : Obj
hasCellData = true;
}
void PacketObjectActivate::Object(BaseObject &baseObject, bool send)
void PacketObjectActivate::Packet(RakNet::BitStream *bs, bool send)
{
ObjectPacket::Object(baseObject, send);
if (!PacketHeader(bs, send))
return;
BaseObject baseObject;
for (unsigned int i = 0; i < objectList->baseObjectCount; i++)
{
if (send)
baseObject = objectList->baseObjects.at(i);
RW(baseObject.isPlayer, send);
if (baseObject.isPlayer)
RW(baseObject.guid, send);
else
Object(baseObject, send);
RW(baseObject.activatingActor.isPlayer, send);
if (baseObject.activatingActor.isPlayer)
{
RW(baseObject.activatingActor.guid, send);
}
else
{
RW(baseObject.activatingActor.refId, send, true);
RW(baseObject.activatingActor.refNum, send);
RW(baseObject.activatingActor.mpNum, send);
RW(baseObject.activatingActor.name, send);
}
if (!send)
objectList->baseObjects.push_back(baseObject);
}
}

@ -10,7 +10,7 @@ namespace mwmp
public:
PacketObjectActivate(RakNet::RakPeerInterface *peer);
virtual void Object(BaseObject &baseObject, bool send);
virtual void Packet(RakNet::BitStream *bs, bool send);
};
}

Loading…
Cancel
Save