diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 5184b378..c11764bd 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -386,6 +386,9 @@ void Entity::Initialize() { if (m_Character) { comp->LoadFromXml(m_Character->GetXMLDoc()); } else { + // extraInfo overrides. Client ORs the database smashable and the luz smashable. + comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable); + if (componentID > 0) { std::vector destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); @@ -420,9 +423,6 @@ void Entity::Initialize() { comp->SetMinCoins(currencyValues[0].minvalue); comp->SetMaxCoins(currencyValues[0].maxvalue); } - - // extraInfo overrides. Client ORs the database smashable and the luz smashable. - comp->SetIsSmashable(comp->GetIsSmashable() | isSmashable); } } else { comp->SetHealth(1); @@ -1565,7 +1565,7 @@ void Entity::Kill(Entity* murderer, const eKillType killType) { m_DieCallbacks.clear(); - //OMAI WA MOU, SHINDERIU + //お前はもう死んでいる GetScript()->OnDie(this, murderer); @@ -2208,7 +2208,7 @@ void Entity::SetRespawnRot(const NiQuaternion& rotation) { int32_t Entity::GetCollisionGroup() const { for (const auto* component : m_Components | std::views::values) { - auto* compToCheck = dynamic_cast(component); + auto* compToCheck = dynamic_cast(component); if (compToCheck) { return compToCheck->GetCollisionGroup(); } diff --git a/dGame/dComponents/QuickBuildComponent.cpp b/dGame/dComponents/QuickBuildComponent.cpp index e3aed82d..4e393fb0 100644 --- a/dGame/dComponents/QuickBuildComponent.cpp +++ b/dGame/dComponents/QuickBuildComponent.cpp @@ -65,14 +65,7 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni outBitStream.Write(false); } - // If build state is completed and we've already serialized once in the completed state, - // don't serializing this component anymore as this will cause the build to jump again. - // If state changes, serialization will begin again. - if (!m_StateDirty && m_State == eQuickBuildState::COMPLETED) { - outBitStream.Write0(); - outBitStream.Write0(); - return; - } + // BEGIN Scripted Activity outBitStream.Write1(); @@ -90,26 +83,27 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni } // END Scripted Activity - outBitStream.Write1(); + outBitStream.Write(m_StateDirty || bIsInitialUpdate); + if (m_StateDirty || bIsInitialUpdate) { + outBitStream.Write(m_State); - outBitStream.Write(m_State); + outBitStream.Write(m_ShowResetEffect); + outBitStream.Write(m_Activator != nullptr); - outBitStream.Write(m_ShowResetEffect); - outBitStream.Write(m_Activator != nullptr); + outBitStream.Write(m_Timer); + outBitStream.Write(m_TimerIncomplete); - outBitStream.Write(m_Timer); - outBitStream.Write(m_TimerIncomplete); - - if (bIsInitialUpdate) { - outBitStream.Write(false); - outBitStream.Write(m_ActivatorPosition); - outBitStream.Write(m_RepositionPlayer); + if (bIsInitialUpdate) { + outBitStream.Write(false); // IsChoiceBuild + outBitStream.Write(m_ActivatorPosition); + outBitStream.Write(m_RepositionPlayer); + } + m_StateDirty = false; } - m_StateDirty = false; } void QuickBuildComponent::Update(float deltaTime) { - m_Activator = GetActivator(); + SetActivator(GetActivator()); // Serialize the quickbuild every so often, fixes the odd bug where the quickbuild is not buildable /*if (m_SoftTimer > 0.0f) { @@ -130,12 +124,13 @@ void QuickBuildComponent::Update(float deltaTime) { const bool isSmashGroup = spawner != nullptr ? spawner->GetIsSpawnSmashGroup() : false; if (isSmashGroup) { - m_TimerIncomplete += deltaTime; + ModifyIncompleteTimer(deltaTime); + Game::entityManager->SerializeEntity(m_Parent); // For reset times < 0 this has to be handled manually if (m_TimeBeforeSmash > 0) { if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) { - m_ShowResetEffect = true; + SetShowResetEffect(true); Game::entityManager->SerializeEntity(m_Parent); } @@ -153,21 +148,20 @@ void QuickBuildComponent::Update(float deltaTime) { break; } case eQuickBuildState::COMPLETED: { - m_Timer += deltaTime; + ModifyTimer(deltaTime); + Game::entityManager->SerializeEntity(m_Parent); // For reset times < 0 this has to be handled manually if (m_ResetTime > 0) { if (m_Timer >= m_ResetTime - 4.0f) { - if (!m_ShowResetEffect) { - m_ShowResetEffect = true; + SetShowResetEffect(true); - Game::entityManager->SerializeEntity(m_Parent); - } + Game::entityManager->SerializeEntity(m_Parent); } if (m_Timer >= m_ResetTime) { - GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true); + GameMessages::SendDieNoImplCode(m_Parent, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 7.0f, false, true); ResetQuickBuild(false); } @@ -185,9 +179,9 @@ void QuickBuildComponent::Update(float deltaTime) { } m_TimeBeforeDrain -= deltaTime; - m_Timer += deltaTime; - m_TimerIncomplete = 0; - m_ShowResetEffect = false; + ModifyTimer(deltaTime); + SetIncompleteTimer(0.0f); + SetShowResetEffect(false); if (m_TimeBeforeDrain <= 0.0f) { m_TimeBeforeDrain = m_CompleteTime / static_cast(m_TakeImagination); @@ -215,12 +209,13 @@ void QuickBuildComponent::Update(float deltaTime) { break; } case eQuickBuildState::INCOMPLETE: { - m_TimerIncomplete += deltaTime; + ModifyIncompleteTimer(deltaTime); + Game::entityManager->SerializeEntity(m_Parent); // For reset times < 0 this has to be handled manually if (m_TimeBeforeSmash > 0) { if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) { - m_ShowResetEffect = true; + SetShowResetEffect(true); Game::entityManager->SerializeEntity(m_Parent); } @@ -260,7 +255,7 @@ void QuickBuildComponent::SpawnActivator() { info.spawnerID = m_Parent->GetObjectID(); info.pos = m_ActivatorPosition == NiPoint3Constant::ZERO ? m_Parent->GetPosition() : m_ActivatorPosition; - m_Activator = Game::entityManager->CreateEntity(info, nullptr, m_Parent); + SetActivator(Game::entityManager->CreateEntity(info, nullptr, m_Parent)); if (m_Activator) { m_ActivatorId = m_Activator->GetObjectID(); Game::entityManager->ConstructEntity(m_Activator); @@ -277,7 +272,7 @@ void QuickBuildComponent::DespawnActivator() { m_Activator->ScheduleKillAfterUpdate(); - m_Activator = nullptr; + SetActivator(nullptr); m_ActivatorId = LWOOBJID_EMPTY; } @@ -405,8 +400,7 @@ void QuickBuildComponent::StartQuickBuild(Entity* const user) { GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::BUILDING, user->GetObjectID()); GameMessages::SendEnableQuickBuild(m_Parent, true, false, false, eQuickBuildFailReason::NOT_GIVEN, 0.0f, user->GetObjectID()); - m_State = eQuickBuildState::BUILDING; - m_StateDirty = true; + SetState(eQuickBuildState::BUILDING); Game::entityManager->SerializeEntity(m_Parent); auto* movingPlatform = m_Parent->GetComponent(); @@ -444,9 +438,8 @@ void QuickBuildComponent::CompleteQuickBuild(Entity* const user) { GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); - m_State = eQuickBuildState::COMPLETED; - m_StateDirty = true; - m_Timer = 0.0f; + SetState(eQuickBuildState::COMPLETED); + SetTimer(0.0f); m_DrainedImagination = 0; Game::entityManager->SerializeEntity(m_Parent); @@ -526,11 +519,10 @@ void QuickBuildComponent::ResetQuickBuild(const bool failed) { GameMessages::SendQuickBuildNotifyState(m_Parent, m_State, eQuickBuildState::RESETTING, LWOOBJID_EMPTY); - m_State = eQuickBuildState::RESETTING; - m_StateDirty = true; - m_Timer = 0.0f; - m_TimerIncomplete = 0.0f; - m_ShowResetEffect = false; + SetState(eQuickBuildState::RESETTING); + SetTimer(0.0f); + SetIncompleteTimer(0.0f); + SetShowResetEffect(false); m_DrainedImagination = 0; Game::entityManager->SerializeEntity(m_Parent); @@ -563,8 +555,7 @@ void QuickBuildComponent::CancelQuickBuild(Entity* const entity, const eQuickBui GameMessages::SendTerminateInteraction(m_Parent->GetObjectID(), eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID()); // Now update the component itself - m_State = eQuickBuildState::INCOMPLETE; - m_StateDirty = true; + SetState(eQuickBuildState::INCOMPLETE); // Notify scripts and possible subscribers m_Parent->GetScript()->OnQuickBuildNotifyState(m_Parent, m_State); diff --git a/dGame/dComponents/QuickBuildComponent.h b/dGame/dComponents/QuickBuildComponent.h index 1cab8660..b220fecd 100644 --- a/dGame/dComponents/QuickBuildComponent.h +++ b/dGame/dComponents/QuickBuildComponent.h @@ -218,6 +218,48 @@ public: * @param skipChecks whether or not to skip the check for the quickbuild not being completed */ void CancelQuickBuild(Entity* const builder, const eQuickBuildFailReason failReason, const bool skipChecks = false); + + void SetState(const eQuickBuildState state) { + if (m_State == state) return; + m_State = state; + m_StateDirty = true; + } + + void SetShowResetEffect(const bool value) { + if (m_ShowResetEffect == value) return; + m_ShowResetEffect = value; + m_StateDirty = true; + } + + void SetActivator(Entity* const activator) { + if (m_Activator == activator) return; + m_Activator = activator; + m_StateDirty = true; + } + + void SetTimer(const float value) { + if (m_Timer == value) return; + m_Timer = value; + m_StateDirty = true; + } + + void ModifyTimer(const float value) { + if (value == 0.0f) return; + m_Timer += value; + m_StateDirty = true; + } + + void SetIncompleteTimer(const float value) { + if (m_TimerIncomplete == value) return; + m_TimerIncomplete = value; + m_StateDirty = true; + } + + void ModifyIncompleteTimer(const float value) { + if (value == 0.0f) return; + m_TimerIncomplete += value; + m_StateDirty = true; + } private: /** * Whether or not the quickbuild state has been changed since we last serialized it. diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index b91c1065..940eb549 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -843,8 +843,10 @@ void GameMessages::SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, c bitStream.Write(entity->GetObjectID()); bitStream.Write(MessageType::Game::DIE); + bitStream.Write(bClientDeath); bitStream.Write(bSpawnLoot); + bitStream.Write(deathType.size()); bitStream.Write(deathType); bitStream.Write(directionRelative_AngleXZ); bitStream.Write(directionRelative_AngleY); @@ -854,7 +856,10 @@ void GameMessages::SendDieNoImplCode(Entity* entity, const LWOOBJID& killerID, c if (killType != eKillType::VIOLENT) bitStream.Write(killType); bitStream.Write(killerID); - bitStream.Write(lootOwnerID); + bitStream.Write(lootOwnerID != LWOOBJID_EMPTY); + if (lootOwnerID != LWOOBJID_EMPTY) { + bitStream.Write(lootOwnerID); + } SEND_PACKET_BROADCAST; }