From 16662d772be26d939edfe5eab7cff9050970729e Mon Sep 17 00:00:00 2001 From: David Cernat Date: Fri, 29 Nov 2019 12:52:47 +0200 Subject: [PATCH] [General] Synchronize death animations for players --- apps/openmw/mwmechanics/character.cpp | 31 +++++++++++++++++-- apps/openmw/mwmp/LocalPlayer.cpp | 30 +++++++++--------- apps/openmw/mwmp/LocalPlayer.hpp | 1 + .../player/ProcessorPlayerDeath.hpp | 1 - components/openmw-mp/Base/BasePlayer.hpp | 1 + .../Packets/Player/PacketPlayerDeath.cpp | 1 + 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 96f565a58..b419f962e 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -37,6 +37,7 @@ #include "../mwmp/LocalPlayer.hpp" #include "../mwmp/LocalActor.hpp" #include "../mwmp/PlayerList.hpp" +#include "../mwmp/DedicatedPlayer.hpp" #include "../mwmp/CellController.hpp" #include "../mwmp/MechanicsHelper.hpp" /* @@ -792,7 +793,8 @@ void CharacterController::playRandomDeath(float startpoint) If this is a LocalActor or DedicatedActor whose death animation is supposed to be finished, set the startpoint to the animation's end */ - if (mPtr.getClass().getCreatureStats(mPtr).isDeathAnimationFinished() && (mwmp::Main::get().getCellController()->isLocalActor(mPtr) || mwmp::Main::get().getCellController()->isDedicatedActor(mPtr))) + if (mPtr.getClass().getCreatureStats(mPtr).isDeathAnimationFinished() && + (mwmp::Main::get().getCellController()->isLocalActor(mPtr) || mwmp::Main::get().getCellController()->isDedicatedActor(mPtr))) { startpoint = 1.F; } @@ -807,7 +809,19 @@ void CharacterController::playRandomDeath(float startpoint) MWBase::Environment::get().getWorld()->useDeathCamera(); } - if(mHitState == CharState_SwimKnockDown && mAnimation->hasAnimation("swimdeathknockdown")) + /* + Start tes3mp change (major) + + If this is a DedicatedPlayer, use the deathState received from their PlayerDeath packet + */ + if (mwmp::PlayerList::isDedicatedPlayer(mPtr)) + { + mDeathState = static_cast(mwmp::PlayerList::getPlayer(mPtr)->deathState); + } + else if(mHitState == CharState_SwimKnockDown && mAnimation->hasAnimation("swimdeathknockdown")) + /* + End of tes3mp change (major) + */ { mDeathState = CharState_SwimDeathKnockDown; } @@ -832,6 +846,19 @@ void CharacterController::playRandomDeath(float startpoint) mDeathState = chooseRandomDeathState(); } + /* + Start of tes3mp addition + + Send a PlayerDeath packet with the decided-upon death animation + */ + if (mPtr == getPlayer()) + { + mwmp::Main::get().getLocalPlayer()->sendDeath(mDeathState); + } + /* + End of tes3mp addition + */ + // Do not interrupt scripted animation by death if (isPersistentAnimPlaying()) return; diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp index 944b06b84..57c126db1 100644 --- a/apps/openmw/mwmp/LocalPlayer.cpp +++ b/apps/openmw/mwmp/LocalPlayer.cpp @@ -256,22 +256,6 @@ void LocalPlayer::updateStatsDynamic(bool forceUpdate) exchangeFullInfo = false; getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(this); getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->Send(); - - static bool wasDead = false; - - if (creatureStats.mDead && !wasDead) - { - if (MechanicsHelper::isEmptyTarget(killer)) - killer = MechanicsHelper::getTarget(getPlayerPtr()); - - LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Sending ID_PLAYER_DEATH about myself to server"); - getNetworking()->getPlayerPacket(ID_PLAYER_DEATH)->setPlayer(this); - getNetworking()->getPlayerPacket(ID_PLAYER_DEATH)->Send(); - - MechanicsHelper::clearTarget(killer); - } - - wasDead = creatureStats.mDead; } } @@ -1361,6 +1345,20 @@ void LocalPlayer::setSelectedSpell() int(MWMechanics::getSpellSuccessChance(selectedSpellId, ptrPlayer))); } +void LocalPlayer::sendDeath(char deathState) +{ + if (MechanicsHelper::isEmptyTarget(killer)) + killer = MechanicsHelper::getTarget(getPlayerPtr()); + + this->deathState = deathState; + + LOG_MESSAGE_SIMPLE(TimedLog::LOG_INFO, "Sending ID_PLAYER_DEATH about myself to server\n- deathState: %d", deathState); + getNetworking()->getPlayerPacket(ID_PLAYER_DEATH)->setPlayer(this); + getNetworking()->getPlayerPacket(ID_PLAYER_DEATH)->Send(); + + MechanicsHelper::clearTarget(killer); +} + void LocalPlayer::sendClass() { MWBase::World *world = MWBase::Environment::get().getWorld(); diff --git a/apps/openmw/mwmp/LocalPlayer.hpp b/apps/openmw/mwmp/LocalPlayer.hpp index f06e524e2..bc6557377 100644 --- a/apps/openmw/mwmp/LocalPlayer.hpp +++ b/apps/openmw/mwmp/LocalPlayer.hpp @@ -75,6 +75,7 @@ namespace mwmp void setMarkLocation(); void setSelectedSpell(); + void sendDeath(char deathState); void sendClass(); void sendInventory(); void sendItemChange(const mwmp::Item& item, unsigned int action); diff --git a/apps/openmw/mwmp/processors/player/ProcessorPlayerDeath.hpp b/apps/openmw/mwmp/processors/player/ProcessorPlayerDeath.hpp index 4a635d6fb..e3fd9ad05 100644 --- a/apps/openmw/mwmp/processors/player/ProcessorPlayerDeath.hpp +++ b/apps/openmw/mwmp/processors/player/ProcessorPlayerDeath.hpp @@ -12,7 +12,6 @@ namespace mwmp ProcessorPlayerDeath() { BPP_INIT(ID_PLAYER_DEATH) - avoidReading = true; } virtual void Do(PlayerPacket &packet, BasePlayer *player) diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp index bf7554977..61441dc74 100644 --- a/components/openmw-mp/Base/BasePlayer.hpp +++ b/components/openmw-mp/Base/BasePlayer.hpp @@ -252,6 +252,7 @@ namespace mwmp std::string sound; Animation animation; + char deathState; bool resetStats; float scale; diff --git a/components/openmw-mp/Packets/Player/PacketPlayerDeath.cpp b/components/openmw-mp/Packets/Player/PacketPlayerDeath.cpp index 989b7a603..94d8d6b0b 100644 --- a/components/openmw-mp/Packets/Player/PacketPlayerDeath.cpp +++ b/components/openmw-mp/Packets/Player/PacketPlayerDeath.cpp @@ -12,6 +12,7 @@ void PacketPlayerDeath::Packet(RakNet::BitStream *bs, bool send) { PlayerPacket::Packet(bs, send); + RW(player->deathState, send); RW(player->killer.isPlayer, send); if (player->killer.isPlayer)