diff --git a/dGame/dComponents/BaseCombatAIComponent.cpp b/dGame/dComponents/BaseCombatAIComponent.cpp index 478058a7..081496a4 100644 --- a/dGame/dComponents/BaseCombatAIComponent.cpp +++ b/dGame/dComponents/BaseCombatAIComponent.cpp @@ -23,9 +23,9 @@ #include "RebuildComponent.h" #include "DestroyableComponent.h" -BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) : Component(parent) { +BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) { m_Target = LWOOBJID_EMPTY; - m_State = AiState::spawn; + SetAiState(AiState::spawn); m_Timer = 1.0f; m_StartPosition = parent->GetPosition(); m_MovementAI = nullptr; @@ -206,7 +206,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) { switch (m_State) { case AiState::spawn: Stun(2.0f); - m_State = AiState::idle; + SetAiState(AiState::idle); break; case AiState::idle: @@ -320,9 +320,9 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { m_Timer = 0; } - m_State = AiState::aggro; + SetAiState(AiState::aggro); } else { - m_State = AiState::idle; + SetAiState(AiState::idle); } for (auto i = 0; i < m_SkillEntries.size(); ++i) { @@ -348,7 +348,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { } if (m_Target == LWOOBJID_EMPTY) { - m_State = AiState::idle; + SetAiState(AiState::idle); return; } @@ -375,7 +375,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) { m_MovementAI->Stop(); } - m_State = AiState::aggro; + SetAiState(AiState::aggro); m_Timer = 0; @@ -532,11 +532,20 @@ bool BaseCombatAIComponent::IsMech() { void BaseCombatAIComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - outBitStream->Write1(); - outBitStream->Write(uint32_t(m_State)); - outBitStream->Write(m_Target); + outBitStream->Write(m_DirtyStateOrTarget || bIsInitialUpdate); + if (m_DirtyStateOrTarget || bIsInitialUpdate) { + outBitStream->Write(uint32_t(m_State)); + outBitStream->Write(m_Target); + m_DirtyStateOrTarget = false; + } } +void BaseCombatAIComponent::SetAiState(AiState newState) { + if (newState == this->m_State) return; + this->m_State = newState; + m_DirtyStateOrTarget = true; + EntityManager::Instance()->SerializeEntity(m_Parent); +} bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const { auto* entity = EntityManager::Instance()->GetEntity(target); @@ -585,7 +594,10 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const { } void BaseCombatAIComponent::SetTarget(const LWOOBJID target) { + if (this->m_Target == target) return; m_Target = target; + m_DirtyStateOrTarget = true; + EntityManager::Instance()->SerializeEntity(m_Parent); } Entity* BaseCombatAIComponent::GetTargetEntity() const { @@ -700,7 +712,7 @@ void BaseCombatAIComponent::OnAggro() { m_MovementAI->SetDestination(targetPos); - m_State = AiState::tether; + SetAiState(AiState::tether); } m_Timer += 0.5f; @@ -726,7 +738,7 @@ void BaseCombatAIComponent::OnTether() { m_MovementAI->SetDestination(m_StartPosition); - m_State = AiState::aggro; + SetAiState(AiState::aggro); } else { if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return; diff --git a/dGame/dComponents/BaseCombatAIComponent.h b/dGame/dComponents/BaseCombatAIComponent.h index 70a88a42..1f17d562 100644 --- a/dGame/dComponents/BaseCombatAIComponent.h +++ b/dGame/dComponents/BaseCombatAIComponent.h @@ -243,6 +243,12 @@ private: */ std::vector GetTargetWithinAggroRange() const; + /** + * @brief Sets the AiState and prepares the entity for serialization next frame. + * + */ + void SetAiState(AiState newState); + /** * The current state of the AI */ @@ -374,6 +380,12 @@ private: */ bool m_DirtyThreat = false; + /** + * Whether or not the Component has dirty information and should update next frame + * + */ + bool m_DirtyStateOrTarget = false; + /** * Whether the current entity is a mech enemy, needed as mechs tether radius works differently * @return whether this entity is a mech diff --git a/dGame/dComponents/PetComponent.cpp b/dGame/dComponents/PetComponent.cpp index 0b136a5c..d11331e7 100644 --- a/dGame/dComponents/PetComponent.cpp +++ b/dGame/dComponents/PetComponent.cpp @@ -59,7 +59,7 @@ std::map PetComponent::petFlags = { { 13067, 838 }, // Skeleton dragon }; -PetComponent::PetComponent(Entity* parent, uint32_t componentId) : Component(parent) { +PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(parent) { m_ComponentId = componentId; m_Interaction = LWOOBJID_EMPTY; @@ -118,21 +118,23 @@ void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpd outBitStream->Write(m_Owner); } - outBitStream->Write(tamed); - if (tamed) { - outBitStream->Write(m_ModerationStatus); + if (bIsInitialUpdate) { + outBitStream->Write(tamed); + if (tamed) { + outBitStream->Write(m_ModerationStatus); - const auto nameData = GeneralUtils::UTF8ToUTF16(m_Name); - const auto ownerNameData = GeneralUtils::UTF8ToUTF16(m_OwnerName); + const auto nameData = GeneralUtils::UTF8ToUTF16(m_Name); + const auto ownerNameData = GeneralUtils::UTF8ToUTF16(m_OwnerName); - outBitStream->Write(static_cast(nameData.size())); - for (const auto c : nameData) { - outBitStream->Write(c); - } + outBitStream->Write(static_cast(nameData.size())); + for (const auto c : nameData) { + outBitStream->Write(c); + } - outBitStream->Write(static_cast(ownerNameData.size())); - for (const auto c : ownerNameData) { - outBitStream->Write(c); + outBitStream->Write(static_cast(ownerNameData.size())); + for (const auto c : ownerNameData) { + outBitStream->Write(c); + } } } } @@ -916,16 +918,16 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) { return; } - // If we are out of imagination despawn the pet. - if (playerDestroyableComponent->GetImagination() == 0) { - this->Deactivate(); - auto playerEntity = playerDestroyableComponent->GetParent(); - if (!playerEntity) return; + // If we are out of imagination despawn the pet. + if (playerDestroyableComponent->GetImagination() == 0) { + this->Deactivate(); + auto playerEntity = playerDestroyableComponent->GetParent(); + if (!playerEntity) return; - GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), UseItemResponse::NoImaginationForPet); - } + GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), UseItemResponse::NoImaginationForPet); + } - this->AddDrainImaginationTimer(item); + this->AddDrainImaginationTimer(item); }); } diff --git a/dGame/dComponents/PlayerForcedMovementComponent.cpp b/dGame/dComponents/PlayerForcedMovementComponent.cpp index 3bcad677..76993507 100644 --- a/dGame/dComponents/PlayerForcedMovementComponent.cpp +++ b/dGame/dComponents/PlayerForcedMovementComponent.cpp @@ -7,8 +7,8 @@ PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent) : C PlayerForcedMovementComponent::~PlayerForcedMovementComponent() {} void PlayerForcedMovementComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { - outBitStream->Write(m_DirtyInfo); - if (m_DirtyInfo) { + outBitStream->Write(m_DirtyInfo || bIsInitialUpdate); + if (m_DirtyInfo || bIsInitialUpdate) { outBitStream->Write(m_PlayerOnRail); outBitStream->Write(m_ShowBillboard); }