From bc093c8596dda6891f3b890ef2236ad2176af97c Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 13 Dec 2019 14:00:51 +0200 Subject: [PATCH] [General] Implement OnObjectHit packet, part 2 ObjectHit is now also sent when local actors succeed or fail in hitting other actors with melee attacks, with the packet including the success state of their attack. It is also sent when creatures hit a non-actor object. --- apps/openmw-mp/Script/Functions/Objects.cpp | 5 +++ apps/openmw-mp/Script/Functions/Objects.hpp | 10 +++++ apps/openmw/mwclass/creature.cpp | 39 +++++++++++++++++-- apps/openmw/mwclass/npc.cpp | 20 +++++++++- apps/openmw/mwmp/ObjectList.cpp | 12 ++++++ apps/openmw/mwmp/ObjectList.hpp | 1 + components/openmw-mp/Base/BaseObject.hpp | 1 + .../Packets/Object/PacketObjectHit.cpp | 2 + 8 files changed, 85 insertions(+), 5 deletions(-) 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); }