diff --git a/apps/openmw-mp/Script/Functions/Objects.cpp b/apps/openmw-mp/Script/Functions/Objects.cpp index 07094828d..73cc90cf8 100644 --- a/apps/openmw-mp/Script/Functions/Objects.cpp +++ b/apps/openmw-mp/Script/Functions/Objects.cpp @@ -184,6 +184,11 @@ const char *ObjectFunctions::GetObjectActivatingName(unsigned int index) noexcep return readObjectList->baseObjects.at(index).activatingActor.name.c_str(); } +bool ObjectFunctions::GetObjectHitSuccess(unsigned int index) noexcept +{ + return readObjectList->baseObjects.at(index).hitAttack.success; +} + bool ObjectFunctions::DoesObjectHavePlayerHitting(unsigned int index) noexcept { return readObjectList->baseObjects.at(index).hittingActor.isPlayer; diff --git a/apps/openmw-mp/Script/Functions/Objects.hpp b/apps/openmw-mp/Script/Functions/Objects.hpp index 38f3b15b0..66c656b3f 100644 --- a/apps/openmw-mp/Script/Functions/Objects.hpp +++ b/apps/openmw-mp/Script/Functions/Objects.hpp @@ -38,6 +38,7 @@ {"GetObjectActivatingMpNum", ObjectFunctions::GetObjectActivatingMpNum},\ {"GetObjectActivatingName", ObjectFunctions::GetObjectActivatingName},\ \ + {"GetObjectHitSuccess", ObjectFunctions::GetObjectHitSuccess},\ {"DoesObjectHavePlayerHitting", ObjectFunctions::DoesObjectHavePlayerHitting},\ {"GetObjectHittingPid", ObjectFunctions::GetObjectHittingPid},\ {"GetObjectHittingRefId", ObjectFunctions::GetObjectHittingRefId},\ @@ -417,6 +418,15 @@ public: */ static const char *GetObjectActivatingName(unsigned int index) noexcept; + /** + * \brief Check whether the object at a certain index in the read object list has been + * hit successfully. + * + * \param index The index of the object. + * \return The success state. + */ + static bool GetObjectHitSuccess(unsigned int index) noexcept; + /** * \brief Check whether the object at a certain index in the read object list has been * hit by a player. diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 833871b05..d5315ef47 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -13,8 +13,10 @@ */ #include #include "../mwmp/Main.hpp" +#include "../mwmp/Networking.hpp" #include "../mwmp/LocalPlayer.hpp" #include "../mwmp/PlayerList.hpp" +#include "../mwmp/ObjectList.hpp" #include "../mwmp/CellController.hpp" #include "../mwmp/MechanicsHelper.hpp" /* @@ -291,8 +293,23 @@ namespace MWClass MWWorld::Ptr victim = result.first; + /* + Start of tes3mp change (major) + + Send an ID_OBJECT_HIT packet when hitting non-actors instead of + just returning + */ if (!victim.getClass().isActor()) - return; // Can't hit non-actors + { + mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); + objectList->reset(); + objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY; + objectList->addObjectHit(victim, ptr); + objectList->sendObjectHit(); + } + /* + End of tes3mp change (major) + */ osg::Vec3f hitPosition (result.second); @@ -324,12 +341,20 @@ namespace MWClass If this was a failed attack by the LocalPlayer or LocalActor, send a packet about it + + Send an ID_OBJECT_HIT about it as well */ if (localAttack) { localAttack->pressed = false; localAttack->success = false; localAttack->shouldSend = true; + + mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); + objectList->reset(); + objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY; + objectList->addObjectHit(victim, ptr, *localAttack); + objectList->sendObjectHit(); } /* End of tes3mp addition @@ -553,8 +578,10 @@ namespace MWClass /* Start of tes3mp addition - If the attacker was the LocalPlayer or LocalActor, record their target and send a - packet with it + If the attacker was the LocalPlayer or LocalActor, record their target and send an + attack packet about it + + Send an ID_OBJECT_HIT about it as well If the victim was a LocalActor who died, record their attacker as the killer */ @@ -569,6 +596,12 @@ namespace MWClass MechanicsHelper::assignAttackTarget(localAttack, ptr); localAttack->shouldSend = true; + + mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); + objectList->reset(); + objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY; + objectList->addObjectHit(ptr, attacker, *localAttack); + objectList->sendObjectHit(); } if (mwmp::Main::get().getCellController()->isLocalActor(ptr)) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 67f9a41e4..c3fccd97c 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -670,12 +670,20 @@ namespace MWClass If this was a failed attack by the LocalPlayer or LocalActor, send a packet about it + + Send an ID_OBJECT_HIT about it as well */ if (localAttack) { localAttack->pressed = false; localAttack->success = false; localAttack->shouldSend = true; + + mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); + objectList->reset(); + objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY; + objectList->addObjectHit(victim, ptr, *localAttack); + objectList->sendObjectHit(); } /* End of tes3mp addition @@ -993,8 +1001,10 @@ namespace MWClass /* Start of tes3mp addition - If the attacker was the LocalPlayer or LocalActor, record their target and send a - packet with it + If the attacker was the LocalPlayer or LocalActor, record their target and send an + attack packet about it + + Send an ID_OBJECT_HIT about it as well If the victim was the LocalPlayer, check whether packets should be sent about their new dynamic stats and position @@ -1012,6 +1022,12 @@ namespace MWClass MechanicsHelper::assignAttackTarget(localAttack, ptr); localAttack->shouldSend = true; + + mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList(); + objectList->reset(); + objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY; + objectList->addObjectHit(ptr, attacker, *localAttack); + objectList->sendObjectHit(); } if (ptr == MWMechanics::getPlayer()) diff --git a/apps/openmw/mwmp/ObjectList.cpp b/apps/openmw/mwmp/ObjectList.cpp index def9db54a..ff36d470e 100644 --- a/apps/openmw/mwmp/ObjectList.cpp +++ b/apps/openmw/mwmp/ObjectList.cpp @@ -979,6 +979,18 @@ void ObjectList::addObjectHit(const MWWorld::Ptr& ptr, const MWWorld::Ptr& hitti mwmp::BaseObject baseObject = getObjectFromPtr(ptr); baseObject.hittingActor = MechanicsHelper::getTarget(hittingActor); + baseObject.hitAttack.success = false; + + addObject(baseObject); +} + +void ObjectList::addObjectHit(const MWWorld::Ptr& ptr, const MWWorld::Ptr& hittingActor, const Attack hitAttack) +{ + cell = *ptr.getCell()->getCell(); + + mwmp::BaseObject baseObject = getObjectFromPtr(ptr); + baseObject.hittingActor = MechanicsHelper::getTarget(hittingActor); + baseObject.hitAttack = hitAttack; addObject(baseObject); } diff --git a/apps/openmw/mwmp/ObjectList.hpp b/apps/openmw/mwmp/ObjectList.hpp index 987888ad9..d60e7ea96 100644 --- a/apps/openmw/mwmp/ObjectList.hpp +++ b/apps/openmw/mwmp/ObjectList.hpp @@ -54,6 +54,7 @@ namespace mwmp void addObjectActivate(const MWWorld::Ptr& ptr, const MWWorld::Ptr& activatingActor); void addObjectHit(const MWWorld::Ptr& ptr, const MWWorld::Ptr& hittingActor); + void addObjectHit(const MWWorld::Ptr& ptr, const MWWorld::Ptr& hittingActor, const Attack hitAttack); 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, std::string spellId, int effectId, float duration); diff --git a/components/openmw-mp/Base/BaseObject.hpp b/components/openmw-mp/Base/BaseObject.hpp index 9f794f793..204c5575c 100644 --- a/components/openmw-mp/Base/BaseObject.hpp +++ b/components/openmw-mp/Base/BaseObject.hpp @@ -64,6 +64,7 @@ namespace mwmp Target activatingActor; Target hittingActor; + Attack hitAttack; bool isSummon; int summonEffectId; diff --git a/components/openmw-mp/Packets/Object/PacketObjectHit.cpp b/components/openmw-mp/Packets/Object/PacketObjectHit.cpp index 903d42062..5a45082ac 100644 --- a/components/openmw-mp/Packets/Object/PacketObjectHit.cpp +++ b/components/openmw-mp/Packets/Object/PacketObjectHit.cpp @@ -42,6 +42,8 @@ void PacketObjectHit::Packet(RakNet::BitStream *newBitstream, bool send) RW(baseObject.hittingActor.name, send); } + RW(baseObject.hitAttack.success, send); + if (!send) objectList->baseObjects.push_back(baseObject); }