diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 60d29dd8b..ad6987c21 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -493,56 +493,13 @@ void Entity::Initialize() { break; } case eReplicaComponentType::SCRIPT: { - /** - * This is a bit of a mess - * yep i aint touching this - */ - + // LWOScriptComponent's allocator: a script component for a registry entry, a character, or a custom script in + // the level config; the component picks its script CDScriptComponentTable* const scriptCompTable = CDClientManager::GetTable(); const int32_t scriptComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPT, -1); - - std::string scriptName = ""; - bool client = false; - if (scriptComponentID > 0 || m_Character) { - std::string clientScriptName; - if (!m_Character) { - CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID); - scriptName = scriptCompData.script_name; - clientScriptName = scriptCompData.client_script_name; - } else { - scriptName = ""; - } - - if (scriptName != "" || (scriptName == "" && m_Character)) { - - } else if (clientScriptName != "") { - client = true; - } else if (!m_Character) { - client = true; - } - } - - std::string customScriptServer; - bool hasCustomServerScript = false; - - const auto customScriptServerName = GetVarAsString(u"custom_script_server"); - const auto customScriptClientName = GetVarAsString(u"custom_script_client"); - - if (!customScriptServerName.empty()) { - customScriptServer = customScriptServerName; - hasCustomServerScript = true; - } - - if (!customScriptClientName.empty()) { - client = true; - } - - if (hasCustomServerScript && scriptName.empty()) { - scriptName = customScriptServer; - } - - if (!scriptName.empty() || client || m_Character || scriptComponentID >= 0) { - AddComponent(scriptComponentID, scriptName, true, client && scriptName.empty()); + const bool hasCustomScript = !GetVarAsString(u"custom_script_server").empty() || !GetVarAsString(u"custom_script_client").empty(); + if (scriptComponentID >= 0 || m_Character || hasCustomScript) { + AddComponent(scriptComponentID); addProximityAndPathfinding(); } diff --git a/dGame/dComponents/ScriptComponent.cpp b/dGame/dComponents/ScriptComponent.cpp index fbb79ca85..287b4cba0 100644 --- a/dGame/dComponents/ScriptComponent.cpp +++ b/dGame/dComponents/ScriptComponent.cpp @@ -5,6 +5,8 @@ #include "Entity.h" #include "ScriptComponent.h" +#include "CDClientManager.h" +#include "CDScriptComponentTable.h" #include "GameMessages.h" #include "Amf3.h" @@ -19,6 +21,38 @@ ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, cons Component::RegisterMsg(&ScriptComponent::OnGetObjectReportInfo); } +ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) { + m_Serialized = true; + m_Client = false; + m_FromObject = true; + m_Script = nullptr; + Component::RegisterMsg(&ScriptComponent::OnGetObjectReportInfo); +} + +// The ScriptComponent row's server and client scripts (a character has neither) +void ScriptComponent::LoadDataFromTemplate() { + if (!m_FromObject || m_ComponentID <= 0 || m_Parent->GetCharacter()) return; + const auto row = CDClientManager::GetTable()->GetByID(m_ComponentID); + m_ScriptName = row.script_name; + m_ClientScriptName = row.client_script_name; +} + +// custom_script_server replaces a missing server script; a client script (the row's or custom_script_client, or +// any object's without a server script) makes it a client script component +void ScriptComponent::LoadConfigData() { + if (!m_FromObject) return; + const bool isCharacter = m_Parent->GetCharacter() != nullptr; + bool client = false; + if ((m_ComponentID > 0 || isCharacter) && m_ScriptName.empty() && !isCharacter) client = true; + + const auto customScriptServer = m_Parent->GetVarAsString(u"custom_script_server"); + if (!m_Parent->GetVarAsString(u"custom_script_client").empty()) client = true; + if (!customScriptServer.empty() && m_ScriptName.empty()) m_ScriptName = customScriptServer; + + m_Client = client && m_ScriptName.empty(); + SetScript(m_ScriptName); +} + void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) { // A server-only script (the zone control object's) sends nothing: the client made no script component for it if (!m_Serialized) return; diff --git a/dGame/dComponents/ScriptComponent.h b/dGame/dComponents/ScriptComponent.h index 69f22268e..2fc16fa25 100644 --- a/dGame/dComponents/ScriptComponent.h +++ b/dGame/dComponents/ScriptComponent.h @@ -26,6 +26,13 @@ public: ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client = false); + // One the object's registry or level config gives (LWOScriptComponent's allocator): its script comes from the + // ScriptComponent row and custom_script_server / custom_script_client + ScriptComponent(Entity* parent, const int32_t componentID); + + void LoadDataFromTemplate() override; + void LoadConfigData() override; + void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override; /** @@ -79,6 +86,11 @@ private: bool m_Client; std::string m_ScriptName; + + // Made from the registry / level config: LoadDataFromTemplate and LoadConfigData pick the script + bool m_FromObject = false; + // The row's client script name (the client runs one when there is no server script) + std::string m_ClientScriptName; }; #endif // SCRIPTCOMPONENT_H