diff --git a/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp b/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp index a6224ccf..8d3445b1 100644 --- a/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp +++ b/LEGO1/lego/legoomni/src/audio/lego3dsound.cpp @@ -186,6 +186,12 @@ void Lego3DSound::FUN_10011a60(ma_sound* p_sound, const char* p_name) } } else { + // Reset ownership flags before reassigning. Reset() only clears m_roi + // but not these flags, so stale values from a previous actor-backed play + // would cause an incorrect ReleaseActor call for non-actor ROIs + m_isActor = FALSE; + m_enabled = FALSE; + if (CharacterManager()->IsActor(p_name)) { m_roi = CharacterManager()->GetActorROI(p_name, TRUE); m_enabled = m_isActor = TRUE; diff --git a/extensions/src/multiplayer/networkmanager.cpp b/extensions/src/multiplayer/networkmanager.cpp index e54c657e..8aa397dc 100644 --- a/extensions/src/multiplayer/networkmanager.cpp +++ b/extensions/src/multiplayer/networkmanager.cpp @@ -1,5 +1,6 @@ #include "extensions/multiplayer/networkmanager.h" +#include "extensions/multiplayer/animdata.h" #include "extensions/multiplayer/charactercloner.h" #include "extensions/multiplayer/charactercustomizer.h" #include "legoanimationmanager.h" @@ -552,6 +553,12 @@ void NetworkManager::SendEmote(uint8_t p_emoteId) return; } + // Multi-part emotes require 3rd person camera to be active (they need the display clone). + // In 1st person mode, skip them entirely to avoid broadcasting an emote the local player can't play. + if (!m_thirdPersonCamera.IsActive() && IsMultiPartEmote(p_emoteId)) { + return; + } + m_thirdPersonCamera.TriggerEmote(p_emoteId); EmoteMsg msg{}; diff --git a/extensions/src/multiplayer/remoteplayer.cpp b/extensions/src/multiplayer/remoteplayer.cpp index 11b5cfe0..e35098a9 100644 --- a/extensions/src/multiplayer/remoteplayer.cpp +++ b/extensions/src/multiplayer/remoteplayer.cpp @@ -11,7 +11,6 @@ #include "realtime/realtime.h" #include "roi/legoroi.h" -#include #include #include #include @@ -141,13 +140,6 @@ void RemotePlayer::UpdateFromNetwork(const PlayerStateMsg& p_msg) SDL_memcpy(newName, p_msg.name, sizeof(newName)); newName[sizeof(newName) - 1] = '\0'; if (SDL_strcmp(m_displayName, newName) != 0) { - SDL_Log( - "RemotePlayer[%u] name changed: '%s' -> '%s' (spawned=%d)", - m_peerId, - m_displayName, - newName, - m_spawned - ); SDL_memcpy(m_displayName, newName, sizeof(m_displayName)); // Recreate bubble with new name (or create for the first time) diff --git a/extensions/src/multiplayer/thirdpersoncamera.cpp b/extensions/src/multiplayer/thirdpersoncamera.cpp index 7ee33732..64dffe5b 100644 --- a/extensions/src/multiplayer/thirdpersoncamera.cpp +++ b/extensions/src/multiplayer/thirdpersoncamera.cpp @@ -664,6 +664,13 @@ MxBool ThirdPersonCamera::HandleCameraRelativeMovement( // Normalize movement direction float moveDirLen = SDL_sqrtf(moveDirX * moveDirX + moveDirZ * moveDirZ); bool hasInput = moveDirLen > 0.001f; + + // Block translation during multi-part emotes (rotation/pan/zoom handled separately) + if (m_animator.IsInMultiPartEmote()) { + hasInput = false; + m_smoothedSpeed = 0.0f; + } + if (hasInput) { moveDirX /= moveDirLen; moveDirZ /= moveDirLen;