diff --git a/apps/openmw/mwmp/LocalActor.cpp b/apps/openmw/mwmp/LocalActor.cpp index ebcf74dd8..4924b17ca 100644 --- a/apps/openmw/mwmp/LocalActor.cpp +++ b/apps/openmw/mwmp/LocalActor.cpp @@ -274,6 +274,7 @@ void LocalActor::updateAttackOrCast() { mwmp::Main::get().getNetworking()->getActorList()->addCastActor(*this); cast.shouldSend = false; + cast.hasProjectile = false; } } diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index de496bf97..7d8501d8e 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -589,6 +589,7 @@ void LocalPlayer::updateAttackOrCast() getNetworking()->getPlayerPacket(ID_PLAYER_CAST)->Send(); cast.shouldSend = false; + cast.hasProjectile = false; } } diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerCast.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerCast.hpp index ada670c95..69924146f 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerCast.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerCast.hpp @@ -17,8 +17,15 @@ namespace mwmp virtual void Do(PlayerPacket &packet, BasePlayer *player) { - if (player != 0) - MechanicsHelper::processCast(player->cast, static_cast(player)->getPtr()); + if (!isLocal() && player != 0) + { + DedicatedPlayer& dedicatedPlayer = static_cast(*player); + MWWorld::Ptr playerPtr = dedicatedPlayer.getPtr(); + MWBase::World* world = MWBase::Environment::get().getWorld(); + world->moveObject(playerPtr, dedicatedPlayer.position.pos[0], dedicatedPlayer.position.pos[1], dedicatedPlayer.position.pos[2]); + world->rotateObject(playerPtr, dedicatedPlayer.position.rot[0], 0, dedicatedPlayer.position.rot[2]); + MechanicsHelper::processCast(player->cast, playerPtr); + } } }; } diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 753ee69e8..df4b6e732 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -47,6 +47,16 @@ #include "../mwphysics/physicssystem.hpp" #include "../mwphysics/projectile.hpp" +/* + Start of tes3mp addition + + Include additional headers for multiplayer purposes +*/ +#include "../mwmp/MechanicsHelper.hpp" +/* + End of tes3mp addition +*/ + namespace { ESM::EffectList getMagicBoltData(std::vector& projectileIDs, std::set& sounds, float& speed, std::string& texture, std::string& sourceName, const std::string& id) @@ -278,6 +288,42 @@ namespace MWWorld else orient.makeRotate(osg::Vec3f(0,1,0), osg::Vec3f(fallbackDirection)); + /* + Start of tes3mp addition + + If the actor casting this is a LocalPlayer or LocalActor, track their projectile origin so it can be sent + in the next PlayerCast or ActorCast packet + + Otherwise, set the projectileOrigin for a DedicatedPlayer or DedicatedActor + */ + mwmp::Cast* localCast = MechanicsHelper::getLocalCast(caster); + + if (localCast) + { + localCast->hasProjectile = true; + localCast->projectileOrigin.origin[0] = pos.x(); + localCast->projectileOrigin.origin[1] = pos.y(); + localCast->projectileOrigin.origin[2] = pos.z(); + localCast->projectileOrigin.orientation[0] = orient.x(); + localCast->projectileOrigin.orientation[1] = orient.y(); + localCast->projectileOrigin.orientation[2] = orient.z(); + localCast->projectileOrigin.orientation[3] = orient.w(); + } + else + { + mwmp::Cast* dedicatedCast = MechanicsHelper::getDedicatedCast(caster); + + if (dedicatedCast) + { + pos = osg::Vec3f(dedicatedCast->projectileOrigin.origin[0], dedicatedCast->projectileOrigin.origin[1], dedicatedCast->projectileOrigin.origin[2]); + orient = osg::Quat(dedicatedCast->projectileOrigin.orientation[0], dedicatedCast->projectileOrigin.orientation[1], dedicatedCast->projectileOrigin.orientation[2], + dedicatedCast->projectileOrigin.orientation[3]); + } + } + /* + End of tes3mp addition + */ + MagicBoltState state; state.mSpellId = spellId; state.mCasterHandle = caster; diff --git a/components/openmw-mp/Base/BaseStructs.hpp b/components/openmw-mp/Base/BaseStructs.hpp index 970aeb80c..2c07fd11e 100644 --- a/components/openmw-mp/Base/BaseStructs.hpp +++ b/components/openmw-mp/Base/BaseStructs.hpp @@ -84,6 +84,12 @@ namespace mwmp enchantmentCharge == rhs.enchantmentCharge && soul == rhs.soul; } }; + + struct ProjectileOrigin + { + float origin[3]; + float orientation[4]; + }; struct Target { @@ -150,7 +156,8 @@ namespace mwmp std::string spellId; // id of spell (e.g. "fireball") std::string itemId; - ESM::Position hitPosition; + bool hasProjectile = false; + ProjectileOrigin projectileOrigin; bool isHit; bool success; diff --git a/components/openmw-mp/Packets/Actor/PacketActorCast.cpp b/components/openmw-mp/Packets/Actor/PacketActorCast.cpp index 4e3782ba1..aaf20cfca 100644 --- a/components/openmw-mp/Packets/Actor/PacketActorCast.cpp +++ b/components/openmw-mp/Packets/Actor/PacketActorCast.cpp @@ -36,4 +36,17 @@ void PacketActorCast::Actor(BaseActor &actor, bool send) RW(actor.cast.instant, send); RW(actor.cast.spellId, send, true); } + + RW(actor.cast.hasProjectile, send); + + if (actor.cast.hasProjectile) + { + RW(actor.cast.projectileOrigin.origin[0], send); + RW(actor.cast.projectileOrigin.origin[1], send); + RW(actor.cast.projectileOrigin.origin[2], send); + RW(actor.cast.projectileOrigin.orientation[0], send); + RW(actor.cast.projectileOrigin.orientation[1], send); + RW(actor.cast.projectileOrigin.orientation[2], send); + RW(actor.cast.projectileOrigin.orientation[3], send); + } } diff --git a/components/openmw-mp/Packets/Player/PacketPlayerCast.cpp b/components/openmw-mp/Packets/Player/PacketPlayerCast.cpp index 89b03f9ce..be44fe91f 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerCast.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerCast.cpp @@ -39,4 +39,19 @@ void PacketPlayerCast::Packet(RakNet::BitStream *newBitstream, bool send) RW(player->cast.instant, send); RW(player->cast.spellId, send, true); } + + RW(player->cast.hasProjectile, send); + + if (player->cast.hasProjectile) + { + RW(player->cast.projectileOrigin.origin[0], send); + RW(player->cast.projectileOrigin.origin[1], send); + RW(player->cast.projectileOrigin.origin[2], send); + RW(player->cast.projectileOrigin.orientation[0], send); + RW(player->cast.projectileOrigin.orientation[1], send); + RW(player->cast.projectileOrigin.orientation[2], send); + RW(player->cast.projectileOrigin.orientation[3], send); + RW(player->position, send); + RW(player->direction, send); + } }