From 541250176c8c5d203480e53de4e58ea598740656 Mon Sep 17 00:00:00 2001 From: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> Date: Wed, 5 Apr 2023 06:57:47 -0700 Subject: [PATCH] Resolve many issues with invisible enemies and End Behavior nodes not firing (#1044) * Finall fix invisible enemies * Add garbage collection * Add comment * Add constexpr for lagFrames --- dGame/dBehaviors/AirMovementBehavior.cpp | 3 ++- dGame/dBehaviors/AirMovementBehavior.h | 10 +++------- dGame/dBehaviors/AttackDelayBehavior.cpp | 2 +- dGame/dBehaviors/BehaviorContext.cpp | 20 +++++++++++++++++++- dGame/dBehaviors/BehaviorContext.h | 4 +++- dGame/dBehaviors/ChargeUpBehavior.cpp | 3 ++- dGame/dBehaviors/ChargeUpBehavior.h | 12 ++++-------- dGame/dBehaviors/ForceMovementBehavior.cpp | 2 +- dGame/dComponents/SkillComponent.cpp | 18 +++++++++++++++--- vanity/NPC.xml | 1 + 10 files changed, 51 insertions(+), 24 deletions(-) diff --git a/dGame/dBehaviors/AirMovementBehavior.cpp b/dGame/dBehaviors/AirMovementBehavior.cpp index 932297b9..dbfde465 100644 --- a/dGame/dBehaviors/AirMovementBehavior.cpp +++ b/dGame/dBehaviors/AirMovementBehavior.cpp @@ -13,7 +13,7 @@ void AirMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi return; } - context->RegisterSyncBehavior(handle, this, branch); + context->RegisterSyncBehavior(handle, this, branch, this->m_Timeout); } void AirMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { @@ -47,4 +47,5 @@ void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitS } void AirMovementBehavior::Load() { + this->m_Timeout = (GetFloat("timeout_ms") / 1000.0f); } diff --git a/dGame/dBehaviors/AirMovementBehavior.h b/dGame/dBehaviors/AirMovementBehavior.h index 89dc1e05..9d51ef03 100644 --- a/dGame/dBehaviors/AirMovementBehavior.h +++ b/dGame/dBehaviors/AirMovementBehavior.h @@ -4,13 +4,7 @@ class AirMovementBehavior final : public Behavior { public: - - /* - * Inherited - */ - - explicit AirMovementBehavior(const uint32_t behavior_id) : Behavior(behavior_id) { - } + explicit AirMovementBehavior(const uint32_t behavior_id) : Behavior(behavior_id) {} void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; @@ -19,4 +13,6 @@ public: void Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Load() override; +private: + float m_Timeout; }; diff --git a/dGame/dBehaviors/AttackDelayBehavior.cpp b/dGame/dBehaviors/AttackDelayBehavior.cpp index ccea5fd9..af33aadd 100644 --- a/dGame/dBehaviors/AttackDelayBehavior.cpp +++ b/dGame/dBehaviors/AttackDelayBehavior.cpp @@ -13,7 +13,7 @@ void AttackDelayBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi }; for (auto i = 0u; i < this->m_numIntervals; ++i) { - context->RegisterSyncBehavior(handle, this, branch, m_ignoreInterrupts); + context->RegisterSyncBehavior(handle, this, branch, m_ignoreInterrupts, this->m_delay * i); } } diff --git a/dGame/dBehaviors/BehaviorContext.cpp b/dGame/dBehaviors/BehaviorContext.cpp index 397e0c72..d0cb68e4 100644 --- a/dGame/dBehaviors/BehaviorContext.cpp +++ b/dGame/dBehaviors/BehaviorContext.cpp @@ -47,7 +47,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const { } -void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext, bool ignoreInterrupts) { +void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext, const float duration, bool ignoreInterrupts) { auto entry = BehaviorSyncEntry(); entry.handle = syncId; @@ -55,6 +55,9 @@ void BehaviorContext::RegisterSyncBehavior(const uint32_t syncId, Behavior* beha entry.branchContext = branchContext; entry.branchContext.isSync = true; entry.ignoreInterrupts = ignoreInterrupts; + // Add 10 seconds + duration time to account for lag and give clients time to send their syncs to the server. + constexpr float lagTime = 10.0f; + entry.time = lagTime + duration; this->syncEntries.push_back(entry); } @@ -183,6 +186,21 @@ void BehaviorContext::SyncCalculation(const uint32_t syncId, const float time, B this->syncEntries.push_back(entry); } +void BehaviorContext::UpdatePlayerSyncs(float deltaTime) { + uint32_t i = 0; + while (i < this->syncEntries.size()) { + auto& entry = this->syncEntries.at(i); + + entry.time -= deltaTime; + + if (entry.time >= 0.0f) { + i++; + continue; + } + this->syncEntries.erase(this->syncEntries.begin() + i); + } +} + void BehaviorContext::InvokeEnd(const uint32_t id) { std::vector entries; diff --git a/dGame/dBehaviors/BehaviorContext.h b/dGame/dBehaviors/BehaviorContext.h index dbba4d91..117f328d 100644 --- a/dGame/dBehaviors/BehaviorContext.h +++ b/dGame/dBehaviors/BehaviorContext.h @@ -80,7 +80,9 @@ struct BehaviorContext uint32_t GetUniqueSkillId() const; - void RegisterSyncBehavior(uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext, bool ignoreInterrupts = false); + void UpdatePlayerSyncs(float deltaTime); + + void RegisterSyncBehavior(uint32_t syncId, Behavior* behavior, const BehaviorBranchContext& branchContext, const float duration, bool ignoreInterrupts = false); void RegisterTimerBehavior(Behavior* behavior, const BehaviorBranchContext& branchContext, LWOOBJID second = LWOOBJID_EMPTY); diff --git a/dGame/dBehaviors/ChargeUpBehavior.cpp b/dGame/dBehaviors/ChargeUpBehavior.cpp index 1b9ba433..4c7c3dac 100644 --- a/dGame/dBehaviors/ChargeUpBehavior.cpp +++ b/dGame/dBehaviors/ChargeUpBehavior.cpp @@ -12,7 +12,7 @@ void ChargeUpBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitSt return; }; - context->RegisterSyncBehavior(handle, this, branch); + context->RegisterSyncBehavior(handle, this, branch, this->m_MaxDuration); } void ChargeUpBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { @@ -24,4 +24,5 @@ void ChargeUpBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStre void ChargeUpBehavior::Load() { this->m_action = GetAction("action"); + this->m_MaxDuration = GetFloat("max_duration"); } diff --git a/dGame/dBehaviors/ChargeUpBehavior.h b/dGame/dBehaviors/ChargeUpBehavior.h index d753895e..ceb40f6c 100644 --- a/dGame/dBehaviors/ChargeUpBehavior.h +++ b/dGame/dBehaviors/ChargeUpBehavior.h @@ -4,14 +4,7 @@ class ChargeUpBehavior final : public Behavior { public: - Behavior* m_action; - - /* - * Inherited - */ - - explicit ChargeUpBehavior(const uint32_t behaviorId) : Behavior(behaviorId) { - } + explicit ChargeUpBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {} void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; @@ -20,4 +13,7 @@ public: void Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override; void Load() override; +private: + Behavior* m_action; + float m_MaxDuration; }; diff --git a/dGame/dBehaviors/ForceMovementBehavior.cpp b/dGame/dBehaviors/ForceMovementBehavior.cpp index e095447c..52359cf7 100644 --- a/dGame/dBehaviors/ForceMovementBehavior.cpp +++ b/dGame/dBehaviors/ForceMovementBehavior.cpp @@ -16,7 +16,7 @@ void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream* Game::logger->Log("ForceMovementBehavior", "Unable to read handle from bitStream, aborting Handle! %i", bitStream->GetNumberOfUnreadBits()); return; } - context->RegisterSyncBehavior(handle, this, branch); + context->RegisterSyncBehavior(handle, this, branch, this->m_Duration); } void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { diff --git a/dGame/dComponents/SkillComponent.cpp b/dGame/dComponents/SkillComponent.cpp index 23ef1bee..ae0e82f0 100644 --- a/dGame/dComponents/SkillComponent.cpp +++ b/dGame/dComponents/SkillComponent.cpp @@ -134,6 +134,10 @@ void SkillComponent::Update(const float deltaTime) { CalculateUpdate(deltaTime); } + if (m_Parent->IsPlayer()) { + for (const auto& pair : this->m_managedBehaviors) pair.second->UpdatePlayerSyncs(deltaTime); + } + std::map keep{}; for (const auto& pair : this->m_managedBehaviors) { @@ -192,7 +196,15 @@ void SkillComponent::Interrupt() { auto* combat = m_Parent->GetComponent(); if (combat != nullptr && combat->GetStunImmune()) return; - for (const auto& behavior : this->m_managedBehaviors) behavior.second->Interrupt(); + for (const auto& behavior : this->m_managedBehaviors) { + for (const auto& behaviorEndEntry : behavior.second->endEntries) { + behaviorEndEntry.behavior->End(behavior.second, behaviorEndEntry.branchContext, behaviorEndEntry.second); + } + behavior.second->endEntries.clear(); + if (m_Parent->IsPlayer()) continue; + behavior.second->Interrupt(); + } + } void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, BehaviorContext* context, const BehaviorBranchContext& branch, const LOT lot, const float maxTime, @@ -215,7 +227,7 @@ void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, B this->m_managedProjectiles.push_back(entry); } -bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID){ +bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID) { uint32_t behaviorId = -1; // try to find it via the cache const auto& pair = m_skillBehaviorCache.find(skillId); @@ -463,7 +475,7 @@ void SkillComponent::HandleUnCast(const uint32_t behaviorId, const LWOOBJID targ delete context; } -SkillComponent::SkillComponent(Entity* parent) : Component(parent) { +SkillComponent::SkillComponent(Entity* parent): Component(parent) { this->m_skillUid = 0; } diff --git a/vanity/NPC.xml b/vanity/NPC.xml index dfe324c3..2311ab46 100644 --- a/vanity/NPC.xml +++ b/vanity/NPC.xml @@ -22,6 +22,7 @@ I hope quickbulds are still working! Be careful crossing the gap! + Have The Maelstrom stopped going invisible?