From 370c2610fa43eacfe9a3f6e9e0319d1c934e8994 Mon Sep 17 00:00:00 2001 From: Robbe Bryssinck Date: Fri, 8 Apr 2022 01:16:04 +0200 Subject: [PATCH] fix: awful fix for weapon draw sync not working --- Code/client/Games/References.cpp | 4 +- Code/client/Games/Skyrim/PlayerCharacter.cpp | 4 +- Code/client/Services/CharacterService.h | 8 ++-- .../Services/Generic/CharacterService.cpp | 42 +++++++++++++++---- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/Code/client/Games/References.cpp b/Code/client/Games/References.cpp index a65434720..5baa32b5b 100644 --- a/Code/client/Games/References.cpp +++ b/Code/client/Games/References.cpp @@ -528,13 +528,13 @@ extern thread_local bool g_forceAnimation; void Actor::SetWeaponDrawnEx(bool aDraw) noexcept { - spdlog::debug("Setting weapon drawn: {:X}:{}, current state: {}", formID, aDraw, actorState.IsWeaponDrawn()); + spdlog::info("Setting weapon drawn: {:X}:{}, current state: {}", formID, aDraw, actorState.IsWeaponDrawn()); if (actorState.IsWeaponDrawn() == aDraw) { actorState.SetWeaponDrawn(!aDraw); - spdlog::debug("Setting weapon drawn after update: {:X}:{}, current state: {}", formID, aDraw, actorState.IsWeaponDrawn()); + spdlog::info("Setting weapon drawn after update: {:X}:{}, current state: {}", formID, aDraw, actorState.IsWeaponDrawn()); } g_forceAnimation = true; diff --git a/Code/client/Games/Skyrim/PlayerCharacter.cpp b/Code/client/Games/Skyrim/PlayerCharacter.cpp index d58be9e29..f802733ad 100644 --- a/Code/client/Games/Skyrim/PlayerCharacter.cpp +++ b/Code/client/Games/Skyrim/PlayerCharacter.cpp @@ -36,7 +36,7 @@ void PlayerCharacter::AddSkillExperience(int32_t aSkill, float aExperience) noex float newExperience = GetSkillExperience(skill); float deltaExperience = newExperience - oldExperience; - spdlog::info("Added {} experience to skill {}", deltaExperience, aSkill); + spdlog::debug("Added {} experience to skill {}", deltaExperience, aSkill); } char TP_MAKE_THISCALL(HookPickUpObject, PlayerCharacter, TESObjectREFR* apObject, int32_t aCount, bool aUnk1, bool aUnk2) @@ -88,7 +88,7 @@ void TP_MAKE_THISCALL(HookAddSkillExperience, PlayerCharacter, int32_t aSkill, f float newExperience = apThis->GetSkillExperience(skill); float deltaExperience = newExperience - oldExperience; - spdlog::info("Skill (AVI): {}, experience: {}", aSkill, deltaExperience); + spdlog::debug("Skill (AVI): {}, experience: {}", aSkill, deltaExperience); if (combatSkills.contains(aSkill)) { diff --git a/Code/client/Services/CharacterService.h b/Code/client/Services/CharacterService.h index da42589e2..cb23e97d0 100644 --- a/Code/client/Services/CharacterService.h +++ b/Code/client/Services/CharacterService.h @@ -48,14 +48,14 @@ struct CharacterService void OnUpdate(const UpdateEvent& acUpdateEvent) noexcept; void OnConnected(const ConnectedEvent& acConnectedEvent) const noexcept; void OnDisconnected(const DisconnectedEvent& acDisconnectedEvent) const noexcept; - void OnAssignCharacter(const AssignCharacterResponse& acMessage) const noexcept; + void OnAssignCharacter(const AssignCharacterResponse& acMessage) noexcept; void OnCharacterSpawn(const CharacterSpawnRequest& acMessage) const noexcept; void OnReferencesMoveRequest(const ServerReferencesMoveRequest& acMessage) const noexcept; void OnActionEvent(const ActionEvent& acActionEvent) const noexcept; void OnFactionsChanges(const NotifyFactionsChanges& acEvent) const noexcept; void OnOwnershipTransfer(const NotifyOwnershipTransfer& acMessage) const noexcept; void OnRemoveCharacter(const NotifyRemoveCharacter& acMessage) const noexcept; - void OnRemoteSpawnDataReceived(const NotifySpawnData& acEvent) const noexcept; + void OnRemoteSpawnDataReceived(const NotifySpawnData& acEvent) noexcept; void OnProjectileLaunchedEvent(const ProjectileLaunchedEvent& acEvent) const noexcept; void OnNotifyProjectileLaunch(const NotifyProjectileLaunch& acMessage) const noexcept; void OnMountEvent(const MountEvent& acEvent) const noexcept; @@ -75,7 +75,7 @@ struct CharacterService Actor* CreateCharacterForEntity(entt::entity aEntity) const noexcept; void RunLocalUpdates() const noexcept; - void RunRemoteUpdates() const noexcept; + void RunRemoteUpdates() noexcept; void RunFactionsUpdates() const noexcept; void RunSpawnUpdates() const noexcept; void RunExperienceUpdates() noexcept; @@ -86,6 +86,8 @@ struct CharacterService float m_cachedExperience = 0.f; + Map> m_weaponDrawUpdates{}; + entt::scoped_connection m_formIdAddedConnection; entt::scoped_connection m_formIdRemovedConnection; entt::scoped_connection m_updateConnection; diff --git a/Code/client/Services/Generic/CharacterService.cpp b/Code/client/Services/Generic/CharacterService.cpp index f3775c7fe..d886c0613 100644 --- a/Code/client/Services/Generic/CharacterService.cpp +++ b/Code/client/Services/Generic/CharacterService.cpp @@ -159,6 +159,27 @@ void CharacterService::OnUpdate(const UpdateEvent& acUpdateEvent) noexcept RunFactionsUpdates(); RunRemoteUpdates(); RunExperienceUpdates(); + + std::vector toRemove{}; + + for (auto& [cId, cTimer] : m_weaponDrawUpdates) + { + double& timer = const_cast(cTimer.first); + timer += acUpdateEvent.Delta; + if (timer <= 0.5) + continue; + + Actor* pActor = RTTI_CAST(TESForm::GetById(cId), TESForm, Actor); + if (!pActor) + continue; + + pActor->SetWeaponDrawnEx(cTimer.second); + + toRemove.push_back(cId); + } + + for (auto id : toRemove) + m_weaponDrawUpdates.erase(id); } void CharacterService::OnConnected(const ConnectedEvent& acConnectedEvent) const noexcept @@ -191,7 +212,7 @@ void CharacterService::OnDisconnected(const DisconnectedEvent& acDisconnectedEve m_world.clear(); } -void CharacterService::OnAssignCharacter(const AssignCharacterResponse& acMessage) const noexcept +void CharacterService::OnAssignCharacter(const AssignCharacterResponse& acMessage) noexcept { spdlog::info("Received for cookie {:X}", acMessage.Cookie); @@ -231,7 +252,8 @@ void CharacterService::OnAssignCharacter(const AssignCharacterResponse& acMessag acMessage.IsDead ? pActor->Kill() : pActor->Respawn(); if (pActor->actorState.IsWeaponDrawn() != acMessage.IsWeaponDrawn) - pActor->SetWeaponDrawnEx(acMessage.IsWeaponDrawn); + m_weaponDrawUpdates[formIdComponent->Id] = {0, acMessage.IsWeaponDrawn}; + //pActor->SetWeaponDrawnEx(acMessage.IsWeaponDrawn); return; } @@ -270,7 +292,8 @@ void CharacterService::OnAssignCharacter(const AssignCharacterResponse& acMessag acMessage.IsDead ? pActor->Kill() : pActor->Respawn(); if (pActor->actorState.IsWeaponDrawn() != acMessage.IsWeaponDrawn) - pActor->SetWeaponDrawnEx(acMessage.IsWeaponDrawn); + m_weaponDrawUpdates[pActor->formID] = {0, acMessage.IsWeaponDrawn}; + //pActor->SetWeaponDrawnEx(acMessage.IsWeaponDrawn); const uint32_t cCellId = World::Get().GetModSystem().GetGameId(acMessage.CellId); const TESForm* const pCellForm = TESForm::GetById(cCellId); @@ -386,7 +409,7 @@ void CharacterService::OnCharacterSpawn(const CharacterSpawnRequest& acMessage) } // TODO: verify/simplify this spawn data stuff -void CharacterService::OnRemoteSpawnDataReceived(const NotifySpawnData& acMessage) const noexcept +void CharacterService::OnRemoteSpawnDataReceived(const NotifySpawnData& acMessage) noexcept { auto view = m_world.view(); @@ -404,6 +427,7 @@ void CharacterService::OnRemoteSpawnDataReceived(const NotifySpawnData& acMessag remoteComponent.SpawnRequest.InitialActorValues = acMessage.InitialActorValues; remoteComponent.SpawnRequest.InventoryContent = acMessage.InitialInventory; remoteComponent.SpawnRequest.IsDead = acMessage.IsDead; + remoteComponent.SpawnRequest.IsWeaponDrawn = acMessage.IsWeaponDrawn; auto& formIdComponent = view.get(*itor); auto* const pForm = TESForm::GetById(formIdComponent.Id); @@ -414,6 +438,8 @@ void CharacterService::OnRemoteSpawnDataReceived(const NotifySpawnData& acMessag pActor->SetActorValues(remoteComponent.SpawnRequest.InitialActorValues); pActor->SetActorInventory(remoteComponent.SpawnRequest.InventoryContent); + m_weaponDrawUpdates[pActor->formID] = {0, acMessage.IsWeaponDrawn}; + //pActor->SetWeaponDrawnEx(acMessage.IsWeaponDrawn); if (pActor->IsDead() != acMessage.IsDead) acMessage.IsDead ? pActor->Kill() : pActor->Respawn(); @@ -1228,7 +1254,7 @@ void CharacterService::RunLocalUpdates() const noexcept m_transport.Send(message); } -void CharacterService::RunRemoteUpdates() const noexcept +void CharacterService::RunRemoteUpdates() noexcept { // Delay by 120ms to let the interpolation system accumulate interpolation points const auto tick = m_transport.GetClock().GetCurrentTick() - 120; @@ -1301,7 +1327,8 @@ void CharacterService::RunRemoteUpdates() const noexcept pActor->SetActorInventory(remoteComponent.SpawnRequest.InventoryContent); pActor->SetFactions(remoteComponent.SpawnRequest.FactionsContent); pActor->LoadAnimationVariables(remoteComponent.SpawnRequest.LatestAction.Variables); - pActor->SetWeaponDrawnEx(remoteComponent.SpawnRequest.IsWeaponDrawn); + m_weaponDrawUpdates[pActor->formID] = {0, remoteComponent.SpawnRequest.IsWeaponDrawn}; + //pActor->SetWeaponDrawnEx(acMessage.IsWeaponDrawn); if (pActor->IsDead() != remoteComponent.SpawnRequest.IsDead) remoteComponent.SpawnRequest.IsDead ? pActor->Kill() : pActor->Respawn(); @@ -1414,5 +1441,6 @@ void CharacterService::RunExperienceUpdates() noexcept m_cachedExperience = 0.f; m_transport.Send(message); - spdlog::info("Sending over experience {}", message.Experience); + + spdlog::debug("Sending over experience {}", message.Experience); }