2023-06-09 22:12:57 +00:00
|
|
|
#include "QuickBuildComponent.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
#include "Entity.h"
|
|
|
|
#include "DestroyableComponent.h"
|
|
|
|
#include "GameMessages.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "Game.h"
|
|
|
|
#include "dLogger.h"
|
|
|
|
#include "CharacterComponent.h"
|
2022-07-05 06:00:10 +00:00
|
|
|
#include "MissionComponent.h"
|
|
|
|
#include "eMissionTaskType.h"
|
2023-03-25 10:26:39 +00:00
|
|
|
#include "eTriggerEventType.h"
|
2023-05-02 22:39:21 +00:00
|
|
|
#include "eQuickBuildFailReason.h"
|
|
|
|
#include "eTerminateType.h"
|
|
|
|
#include "eGameActivity.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
#include "dServer.h"
|
|
|
|
#include "PacketUtils.h"
|
|
|
|
#include "Spawner.h"
|
|
|
|
#include "MovingPlatformComponent.h"
|
|
|
|
#include "Preconditions.h"
|
2023-01-07 05:17:05 +00:00
|
|
|
#include "Loot.h"
|
2022-12-22 13:24:59 +00:00
|
|
|
#include "TeamManager.h"
|
2023-03-20 13:10:52 +00:00
|
|
|
#include "RenderComponent.h"
|
2023-06-11 11:37:53 +00:00
|
|
|
#include "CDRebuildComponentTable.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
#include "CppScripts.h"
|
|
|
|
|
2023-06-26 20:06:33 +00:00
|
|
|
QuickBuildComponent::QuickBuildComponent(Entity* entity) : ActivityComponent(entity) {
|
2023-06-11 11:37:53 +00:00
|
|
|
m_ComponentId = componentId;
|
2021-12-05 17:54:36 +00:00
|
|
|
std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition");
|
|
|
|
|
|
|
|
if (!checkPreconditions.empty()) {
|
|
|
|
m_Precondition = new PreconditionExpression(GeneralUtils::UTF16ToWTF8(checkPreconditions));
|
|
|
|
}
|
2022-06-16 05:59:30 +00:00
|
|
|
|
2022-06-16 06:04:03 +00:00
|
|
|
// Should a setting that has the build activator position exist, fetch that setting here and parse it for position.
|
2022-06-16 15:38:38 +00:00
|
|
|
// It is assumed that the user who sets this setting uses the correct character delimiter (character 31 or in hex 0x1F)
|
2023-06-09 09:46:01 +00:00
|
|
|
auto positionAsVector = GeneralUtils::SplitString(m_ParentEntity->GetVarAsString(u"rebuild_activators"), 0x1F);
|
2022-07-25 02:26:51 +00:00
|
|
|
if (positionAsVector.size() == 3 &&
|
2022-06-16 15:38:38 +00:00
|
|
|
GeneralUtils::TryParse(positionAsVector[0], m_ActivatorPosition.x) &&
|
2022-07-25 02:26:51 +00:00
|
|
|
GeneralUtils::TryParse(positionAsVector[1], m_ActivatorPosition.y) &&
|
2022-06-16 15:38:38 +00:00
|
|
|
GeneralUtils::TryParse(positionAsVector[2], m_ActivatorPosition.z)) {
|
2022-06-16 05:59:30 +00:00
|
|
|
} else {
|
2023-06-09 22:12:57 +00:00
|
|
|
Game::logger->Log("QuickBuildComponent", "Failed to find activator position for lot %i. Defaulting to parents position.", m_ParentEntity->GetLOT());
|
2023-06-09 09:46:01 +00:00
|
|
|
m_ActivatorPosition = m_ParentEntity->GetPosition();
|
2022-06-16 05:59:30 +00:00
|
|
|
}
|
2022-06-16 15:38:38 +00:00
|
|
|
|
2022-06-16 05:59:30 +00:00
|
|
|
SpawnActivator();
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
QuickBuildComponent::~QuickBuildComponent() {
|
2021-12-05 17:54:36 +00:00
|
|
|
delete m_Precondition;
|
|
|
|
|
|
|
|
Entity* builder = GetBuilder();
|
|
|
|
if (builder) {
|
2023-05-02 22:39:21 +00:00
|
|
|
CancelRebuild(builder, eQuickBuildFailReason::BUILD_ENDED, true);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
DespawnActivator();
|
|
|
|
}
|
|
|
|
|
2023-06-11 11:37:53 +00:00
|
|
|
void QuickBuildComponent::LoadConfigData() {
|
|
|
|
const auto rebuildResetTime = m_ParentEntity->GetVar<float>(u"rebuild_reset_time");
|
|
|
|
|
|
|
|
if (rebuildResetTime != 0.0f) {
|
|
|
|
SetResetTime(rebuildResetTime);
|
2023-06-11 11:40:19 +00:00
|
|
|
if (m_ParentEntity->GetLOT() == 9483) // TODO: Fix the moving platform in Forbidden valley spawning at the end.
|
2023-06-11 11:37:53 +00:00
|
|
|
{
|
|
|
|
SetResetTime(GetResetTime() + 25);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto activityID = m_ParentEntity->GetVar<int32_t>(u"activityID");
|
|
|
|
if (activityID > 0) SetActivityId(activityID);
|
|
|
|
|
|
|
|
const auto compTime = m_ParentEntity->GetVar<float>(u"compTime");
|
|
|
|
if (compTime > 0) SetCompleteTime(compTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QuickBuildComponent::LoadTemplateData() {
|
|
|
|
auto* rebCompTable = CDClientManager::Instance().GetTable<CDRebuildComponentTable>();
|
|
|
|
std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([this](CDRebuildComponent entry) { return (entry.id == this->m_ComponentId); });
|
|
|
|
if (rebCompData.empty()) return;
|
|
|
|
const auto& quickbuildData = rebCompData.at(0);
|
|
|
|
SetResetTime(quickbuildData.reset_time);
|
|
|
|
SetCompleteTime(quickbuildData.complete_time);
|
|
|
|
SetTakeImagination(quickbuildData.take_imagination);
|
|
|
|
SetInterruptible(quickbuildData.interruptible);
|
|
|
|
SetSelfActivator(quickbuildData.self_activator);
|
|
|
|
SetActivityId(quickbuildData.activityID);
|
|
|
|
SetPostImaginationCost(quickbuildData.post_imagination_cost);
|
|
|
|
SetTimeBeforeSmash(quickbuildData.time_before_smash);
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
2023-06-09 09:46:01 +00:00
|
|
|
if (!m_ParentEntity->GetComponent<DestroyableComponent>()) {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (bIsInitialUpdate) {
|
|
|
|
outBitStream->Write(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
outBitStream->Write(false);
|
|
|
|
|
|
|
|
outBitStream->Write(false);
|
|
|
|
}
|
2022-07-25 02:26:51 +00:00
|
|
|
// If build state is completed and we've already serialized once in the completed state,
|
2022-05-03 05:32:00 +00:00
|
|
|
// don't serializing this component anymore as this will cause the build to jump again.
|
|
|
|
// If state changes, serialization will begin again.
|
2023-05-02 22:39:21 +00:00
|
|
|
if (!m_StateDirty && m_State == eRebuildState::COMPLETED) {
|
2022-05-03 05:32:00 +00:00
|
|
|
outBitStream->Write0();
|
|
|
|
outBitStream->Write0();
|
|
|
|
return;
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
// BEGIN Scripted Activity
|
|
|
|
outBitStream->Write1();
|
|
|
|
|
|
|
|
Entity* builder = GetBuilder();
|
|
|
|
|
|
|
|
if (builder) {
|
|
|
|
outBitStream->Write((uint32_t)1);
|
|
|
|
outBitStream->Write(builder->GetObjectID());
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
outBitStream->Write(0.0f);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
outBitStream->Write((uint32_t)0);
|
|
|
|
}
|
|
|
|
// END Scripted Activity
|
|
|
|
|
|
|
|
outBitStream->Write1();
|
|
|
|
|
2023-05-02 22:39:21 +00:00
|
|
|
outBitStream->Write(m_State);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
outBitStream->Write(m_ShowResetEffect);
|
|
|
|
outBitStream->Write(m_Activator != nullptr);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
outBitStream->Write(m_Timer);
|
|
|
|
outBitStream->Write(m_TimerIncomplete);
|
|
|
|
|
|
|
|
if (bIsInitialUpdate) {
|
|
|
|
outBitStream->Write(false);
|
|
|
|
outBitStream->Write(m_ActivatorPosition);
|
|
|
|
outBitStream->Write(m_RepositionPlayer);
|
|
|
|
}
|
2022-05-03 05:32:00 +00:00
|
|
|
m_StateDirty = false;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::Update(float deltaTime) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Activator = GetActivator();
|
|
|
|
|
|
|
|
// Serialize the quickbuild every so often, fixes the odd bug where the quickbuild is not buildable
|
|
|
|
/*if (m_SoftTimer > 0.0f) {
|
|
|
|
m_SoftTimer -= deltaTime;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_SoftTimer = 5.0f;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}*/
|
|
|
|
|
|
|
|
switch (m_State) {
|
2023-05-02 22:39:21 +00:00
|
|
|
case eRebuildState::OPEN: {
|
2021-12-05 17:54:36 +00:00
|
|
|
SpawnActivator();
|
|
|
|
m_TimeBeforeDrain = 0;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
auto* spawner = m_ParentEntity->GetSpawner();
|
2021-12-05 17:54:36 +00:00
|
|
|
const bool isSmashGroup = spawner != nullptr ? spawner->GetIsSpawnSmashGroup() : false;
|
|
|
|
|
|
|
|
if (isSmashGroup) {
|
|
|
|
m_TimerIncomplete += deltaTime;
|
|
|
|
|
|
|
|
// For reset times < 0 this has to be handled manually
|
|
|
|
if (m_TimeBeforeSmash > 0) {
|
|
|
|
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
|
|
|
|
m_ShowResetEffect = true;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (m_TimerIncomplete >= m_TimeBeforeSmash) {
|
|
|
|
m_Builder = LWOOBJID_EMPTY;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendDieNoImplCode(m_ParentEntity, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
ResetRebuild(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
break;
|
|
|
|
}
|
2023-05-02 22:39:21 +00:00
|
|
|
case eRebuildState::COMPLETED: {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Timer += deltaTime;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Timer >= m_ResetTime) {
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendDieNoImplCode(m_ParentEntity, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
ResetRebuild(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-05-02 22:39:21 +00:00
|
|
|
case eRebuildState::BUILDING:
|
2021-12-05 17:54:36 +00:00
|
|
|
{
|
|
|
|
Entity* builder = GetBuilder();
|
|
|
|
|
|
|
|
if (builder == nullptr) {
|
|
|
|
ResetRebuild(false);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_TimeBeforeDrain -= deltaTime;
|
|
|
|
m_Timer += deltaTime;
|
|
|
|
m_TimerIncomplete = 0;
|
|
|
|
m_ShowResetEffect = false;
|
|
|
|
|
|
|
|
if (m_TimeBeforeDrain <= 0.0f) {
|
|
|
|
m_TimeBeforeDrain = m_CompleteTime / static_cast<float>(m_TakeImagination);
|
|
|
|
|
2023-06-09 08:27:05 +00:00
|
|
|
auto* destComp = builder->GetComponent<DestroyableComponent>();
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!destComp) break;
|
|
|
|
|
2023-05-11 11:37:02 +00:00
|
|
|
int newImagination = destComp->GetImagination();
|
|
|
|
if (newImagination <= 0) {
|
|
|
|
CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true);
|
|
|
|
break;
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-05-11 11:37:02 +00:00
|
|
|
++m_DrainedImagination;
|
|
|
|
--newImagination;
|
2021-12-05 17:54:36 +00:00
|
|
|
destComp->SetImagination(newImagination);
|
|
|
|
EntityManager::Instance()->SerializeEntity(builder);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Timer >= m_CompleteTime && m_DrainedImagination >= m_TakeImagination) {
|
|
|
|
CompleteRebuild(builder);
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
2023-05-02 22:39:21 +00:00
|
|
|
case eRebuildState::INCOMPLETE: {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_TimerIncomplete += deltaTime;
|
|
|
|
|
|
|
|
// For reset times < 0 this has to be handled manually
|
|
|
|
if (m_TimeBeforeSmash > 0) {
|
|
|
|
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
|
|
|
|
m_ShowResetEffect = true;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (m_TimerIncomplete >= m_TimeBeforeSmash) {
|
|
|
|
m_Builder = LWOOBJID_EMPTY;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendDieNoImplCode(m_ParentEntity, LWOOBJID_EMPTY, LWOOBJID_EMPTY, eKillType::VIOLENT, u"", 0.0f, 0.0f, 0.0f, false, true);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
ResetRebuild(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2023-05-02 22:39:21 +00:00
|
|
|
case eRebuildState::RESETTING: break;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::OnUse(Entity* originator) {
|
2023-05-02 22:39:21 +00:00
|
|
|
if (GetBuilder() != nullptr || m_State == eRebuildState::COMPLETED) {
|
2021-12-05 17:54:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_Precondition != nullptr && !m_Precondition->Check(originator)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
StartRebuild(originator);
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SpawnActivator() {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (!m_SelfActivator || m_ActivatorPosition != NiPoint3::ZERO) {
|
|
|
|
if (!m_Activator) {
|
|
|
|
EntityInfo info;
|
|
|
|
|
|
|
|
info.lot = 6604;
|
2023-06-09 09:46:01 +00:00
|
|
|
info.spawnerID = m_ParentEntity->GetObjectID();
|
|
|
|
info.pos = m_ActivatorPosition == NiPoint3::ZERO ? m_ParentEntity->GetPosition() : m_ActivatorPosition;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
m_Activator = EntityManager::Instance()->CreateEntity(info, nullptr, m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Activator) {
|
|
|
|
m_ActivatorId = m_Activator->GetObjectID();
|
|
|
|
EntityManager::Instance()->ConstructEntity(m_Activator);
|
|
|
|
}
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::DespawnActivator() {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Activator) {
|
|
|
|
EntityManager::Instance()->DestructEntity(m_Activator);
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Activator->ScheduleKillAfterUpdate();
|
|
|
|
|
|
|
|
m_Activator = nullptr;
|
|
|
|
|
|
|
|
m_ActivatorId = LWOOBJID_EMPTY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
Entity* QuickBuildComponent::GetActivator() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return EntityManager::Instance()->GetEntity(m_ActivatorId);
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
NiPoint3 QuickBuildComponent::GetActivatorPosition() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_ActivatorPosition;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
float QuickBuildComponent::GetResetTime() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_ResetTime;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
float QuickBuildComponent::GetCompleteTime() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_CompleteTime;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
int QuickBuildComponent::GetTakeImagination() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_TakeImagination;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
bool QuickBuildComponent::GetInterruptible() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_Interruptible;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
bool QuickBuildComponent::GetSelfActivator() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_SelfActivator;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
std::vector<int> QuickBuildComponent::GetCustomModules() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_CustomModules;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
int QuickBuildComponent::GetActivityId() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_ActivityId;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
int QuickBuildComponent::GetPostImaginationCost() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_PostImaginationCost;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
float QuickBuildComponent::GetTimeBeforeSmash() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_TimeBeforeSmash;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
eRebuildState QuickBuildComponent::GetState() {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_State;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
Entity* QuickBuildComponent::GetBuilder() const {
|
2021-12-05 17:54:36 +00:00
|
|
|
auto* builder = EntityManager::Instance()->GetEntity(m_Builder);
|
|
|
|
|
|
|
|
return builder;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
bool QuickBuildComponent::GetRepositionPlayer() const {
|
2021-12-05 17:54:36 +00:00
|
|
|
return m_RepositionPlayer;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetActivatorPosition(NiPoint3 value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_ActivatorPosition = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetResetTime(float value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_ResetTime = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetCompleteTime(float value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (value < 0) {
|
|
|
|
m_CompleteTime = 4.5f;
|
|
|
|
} else {
|
|
|
|
m_CompleteTime = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetTakeImagination(int value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_TakeImagination = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetInterruptible(bool value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Interruptible = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetSelfActivator(bool value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_SelfActivator = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetCustomModules(std::vector<int> value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_CustomModules = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetActivityId(int value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_ActivityId = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetPostImaginationCost(int value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_PostImaginationCost = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetTimeBeforeSmash(float value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (value < 0) {
|
|
|
|
m_TimeBeforeSmash = 10.0f;
|
|
|
|
} else {
|
|
|
|
m_TimeBeforeSmash = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::SetRepositionPlayer(bool value) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_RepositionPlayer = value;
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::StartRebuild(Entity* user) {
|
2023-05-02 22:39:21 +00:00
|
|
|
if (m_State == eRebuildState::OPEN || m_State == eRebuildState::COMPLETED || m_State == eRebuildState::INCOMPLETE) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Builder = user->GetObjectID();
|
|
|
|
|
2023-06-09 08:27:05 +00:00
|
|
|
auto* character = user->GetComponent<CharacterComponent>();
|
2023-05-02 22:39:21 +00:00
|
|
|
character->SetCurrentActivity(eGameActivity::QUICKBUILDING);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
EntityManager::Instance()->SerializeEntity(user);
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendRebuildNotifyState(m_ParentEntity, m_State, eRebuildState::BUILDING, user->GetObjectID());
|
|
|
|
GameMessages::SendEnableRebuild(m_ParentEntity, true, false, false, eQuickBuildFailReason::NOT_GIVEN, 0.0f, user->GetObjectID());
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-05-02 22:39:21 +00:00
|
|
|
m_State = eRebuildState::BUILDING;
|
2022-05-03 05:32:00 +00:00
|
|
|
m_StateDirty = true;
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
auto* movingPlatform = m_ParentEntity->GetComponent<MovingPlatformComponent>();
|
2021-12-05 17:54:36 +00:00
|
|
|
if (movingPlatform != nullptr) {
|
|
|
|
movingPlatform->OnRebuildInitilized();
|
|
|
|
}
|
|
|
|
|
2023-06-14 03:01:51 +00:00
|
|
|
m_ParentEntity->GetScript()->OnRebuildStart(m_ParentEntity, user);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Notify scripts and possible subscribers
|
2023-06-14 03:01:51 +00:00
|
|
|
m_ParentEntity->GetScript()->OnRebuildNotifyState(m_ParentEntity, m_State);
|
|
|
|
for (const auto& cb : m_RebuildStateCallbacks) cb(m_State);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::CompleteRebuild(Entity* user) {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (user == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2023-06-09 08:27:05 +00:00
|
|
|
auto* characterComponent = user->GetComponent<CharacterComponent>();
|
2021-12-05 17:54:36 +00:00
|
|
|
if (characterComponent != nullptr) {
|
2023-05-02 22:39:21 +00:00
|
|
|
characterComponent->SetCurrentActivity(eGameActivity::NONE);
|
2021-12-05 17:54:36 +00:00
|
|
|
characterComponent->TrackRebuildComplete();
|
|
|
|
} else {
|
2023-06-09 22:12:57 +00:00
|
|
|
Game::logger->Log("QuickBuildComponent", "Some user tried to finish the rebuild but they didn't have a character somehow.");
|
2021-12-05 17:54:36 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
EntityManager::Instance()->SerializeEntity(user);
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendRebuildNotifyState(m_ParentEntity, m_State, eRebuildState::COMPLETED, user->GetObjectID());
|
|
|
|
GameMessages::SendPlayFXEffect(m_ParentEntity, 507, u"create", "BrickFadeUpVisCompleteEffect", LWOOBJID_EMPTY, 0.4f, 1.0f, true);
|
|
|
|
GameMessages::SendEnableRebuild(m_ParentEntity, false, false, true, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, user->GetObjectID());
|
|
|
|
GameMessages::SendTerminateInteraction(user->GetObjectID(), eTerminateType::FROM_INTERACTION, m_ParentEntity->GetObjectID());
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-05-02 22:39:21 +00:00
|
|
|
m_State = eRebuildState::COMPLETED;
|
2022-05-03 05:32:00 +00:00
|
|
|
m_StateDirty = true;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Timer = 0.0f;
|
|
|
|
m_DrainedImagination = 0;
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Removes extra item requirements, isn't live accurate.
|
|
|
|
// In live, all items were removed at the start of the quickbuild, then returned if it was cancelled.
|
|
|
|
// TODO: fix?
|
|
|
|
if (m_Precondition != nullptr) {
|
|
|
|
m_Precondition->Check(user, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
DespawnActivator();
|
|
|
|
|
|
|
|
// Set owner override so that entities smashed by this quickbuild will result in the builder getting rewards.
|
2023-06-09 09:46:01 +00:00
|
|
|
m_ParentEntity->SetOwnerOverride(user->GetObjectID());
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
auto* builder = GetBuilder();
|
|
|
|
|
2022-12-22 13:24:59 +00:00
|
|
|
if (builder) {
|
|
|
|
auto* team = TeamManager::Instance()->GetTeam(builder->GetObjectID());
|
|
|
|
if (team) {
|
|
|
|
for (const auto memberId : team->members) { // progress missions for all team members
|
|
|
|
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
|
|
|
if (member) {
|
2023-06-09 08:27:05 +00:00
|
|
|
auto* missionComponent = member->GetComponent<MissionComponent>();
|
2022-12-22 13:24:59 +00:00
|
|
|
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
|
|
|
|
}
|
|
|
|
}
|
2023-06-11 11:37:53 +00:00
|
|
|
} else {
|
2023-06-09 08:27:05 +00:00
|
|
|
auto* missionComponent = builder->GetComponent<MissionComponent>();
|
2022-12-22 13:24:59 +00:00
|
|
|
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
2023-06-09 09:46:01 +00:00
|
|
|
LootGenerator::Instance().DropActivityLoot(builder, m_ParentEntity, m_ActivityId, 1);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Notify scripts
|
2023-06-14 03:01:51 +00:00
|
|
|
m_ParentEntity->GetScript()->OnRebuildComplete(m_ParentEntity, user);
|
|
|
|
m_ParentEntity->GetScript()->OnRebuildNotifyState(m_ParentEntity, m_State);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Notify subscribers
|
|
|
|
for (const auto& callback : m_RebuildStateCallbacks)
|
|
|
|
callback(m_State);
|
|
|
|
for (const auto& callback : m_RebuildCompleteCallbacks)
|
|
|
|
callback(user);
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
m_ParentEntity->TriggerEvent(eTriggerEventType::REBUILD_COMPLETE, user);
|
2023-03-25 10:26:39 +00:00
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
auto* movingPlatform = m_ParentEntity->GetComponent<MovingPlatformComponent>();
|
2021-12-05 17:54:36 +00:00
|
|
|
if (movingPlatform != nullptr) {
|
|
|
|
movingPlatform->OnCompleteRebuild();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set flag
|
|
|
|
auto* character = user->GetCharacter();
|
|
|
|
|
|
|
|
if (character != nullptr) {
|
2023-06-09 09:46:01 +00:00
|
|
|
const auto flagNumber = m_ParentEntity->GetVar<int32_t>(u"quickbuild_single_build_player_flag");
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (flagNumber != 0) {
|
|
|
|
character->SetPlayerFlag(flagNumber, true);
|
|
|
|
}
|
|
|
|
}
|
2023-03-20 13:10:52 +00:00
|
|
|
RenderComponent::PlayAnimation(user, u"rebuild-celebrate", 1.09f);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::ResetRebuild(bool failed) {
|
2021-12-05 17:54:36 +00:00
|
|
|
Entity* builder = GetBuilder();
|
|
|
|
|
2023-05-02 22:39:21 +00:00
|
|
|
if (m_State == eRebuildState::BUILDING && builder) {
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendEnableRebuild(m_ParentEntity, false, false, failed, eQuickBuildFailReason::NOT_GIVEN, m_ResetTime, builder->GetObjectID());
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (failed) {
|
2023-03-20 13:10:52 +00:00
|
|
|
RenderComponent::PlayAnimation(builder, u"rebuild-fail");
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendRebuildNotifyState(m_ParentEntity, m_State, eRebuildState::RESETTING, LWOOBJID_EMPTY);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-05-02 22:39:21 +00:00
|
|
|
m_State = eRebuildState::RESETTING;
|
2022-05-03 05:32:00 +00:00
|
|
|
m_StateDirty = true;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Timer = 0.0f;
|
|
|
|
m_TimerIncomplete = 0.0f;
|
|
|
|
m_ShowResetEffect = false;
|
|
|
|
m_DrainedImagination = 0;
|
2022-07-25 02:26:51 +00:00
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Notify scripts and possible subscribers
|
2023-06-14 03:01:51 +00:00
|
|
|
m_ParentEntity->GetScript()->OnRebuildNotifyState(m_ParentEntity, m_State);
|
|
|
|
for (const auto& cb : m_RebuildStateCallbacks) cb(m_State);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
m_ParentEntity->ScheduleKillAfterUpdate();
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (m_Activator) {
|
|
|
|
m_Activator->ScheduleKillAfterUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::CancelRebuild(Entity* entity, eQuickBuildFailReason failReason, bool skipChecks) {
|
2023-05-02 22:39:21 +00:00
|
|
|
if (m_State != eRebuildState::COMPLETED || skipChecks) {
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
m_Builder = LWOOBJID_EMPTY;
|
|
|
|
|
|
|
|
const auto entityID = entity != nullptr ? entity->GetObjectID() : LWOOBJID_EMPTY;
|
|
|
|
|
|
|
|
// Notify the client that a state has changed
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendRebuildNotifyState(m_ParentEntity, m_State, eRebuildState::INCOMPLETE, entityID);
|
|
|
|
GameMessages::SendEnableRebuild(m_ParentEntity, false, true, false, failReason, m_Timer, entityID);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Now terminate any interaction with the rebuild
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendTerminateInteraction(entityID, eTerminateType::FROM_INTERACTION, m_ParentEntity->GetObjectID());
|
|
|
|
GameMessages::SendTerminateInteraction(m_ParentEntity->GetObjectID(), eTerminateType::FROM_INTERACTION, m_ParentEntity->GetObjectID());
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Now update the component itself
|
2023-05-02 22:39:21 +00:00
|
|
|
m_State = eRebuildState::INCOMPLETE;
|
2022-05-03 05:32:00 +00:00
|
|
|
m_StateDirty = true;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Notify scripts and possible subscribers
|
2023-06-14 03:01:51 +00:00
|
|
|
m_ParentEntity->GetScript()->OnRebuildNotifyState(m_ParentEntity, m_State);
|
|
|
|
for (const auto& cb : m_RebuildStateCallbacks) cb(m_State);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-06-09 09:46:01 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (entity == nullptr) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-09 08:27:05 +00:00
|
|
|
auto* characterComponent = entity->GetComponent<CharacterComponent>();
|
2021-12-05 17:54:36 +00:00
|
|
|
if (characterComponent) {
|
2023-05-02 22:39:21 +00:00
|
|
|
characterComponent->SetCurrentActivity(eGameActivity::NONE);
|
2021-12-05 17:54:36 +00:00
|
|
|
EntityManager::Instance()->SerializeEntity(entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::AddRebuildCompleteCallback(const std::function<void(Entity* user)>& callback) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_RebuildCompleteCallbacks.push_back(callback);
|
|
|
|
}
|
|
|
|
|
2023-06-09 22:12:57 +00:00
|
|
|
void QuickBuildComponent::AddRebuildStateCallback(const std::function<void(eRebuildState state)>& callback) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_RebuildStateCallbacks.push_back(callback);
|
|
|
|
}
|