diff --git a/dCommon/dEnums/eReplicaComponentType.h b/dCommon/dEnums/eReplicaComponentType.h index 2d24c19e..39f91eff 100644 --- a/dCommon/dEnums/eReplicaComponentType.h +++ b/dCommon/dEnums/eReplicaComponentType.h @@ -121,6 +121,7 @@ enum class eReplicaComponentType : uint32_t { BUILD_BORDER, UNKNOWN_115, CULLING_PLANE, + NUMBER_OF_COMPONENTS, DESTROYABLE = 1000 // Actually 7 }; diff --git a/dDatabase/Tables/CDComponentsRegistryTable.cpp b/dDatabase/Tables/CDComponentsRegistryTable.cpp index 32012f6c..c053de91 100644 --- a/dDatabase/Tables/CDComponentsRegistryTable.cpp +++ b/dDatabase/Tables/CDComponentsRegistryTable.cpp @@ -90,4 +90,11 @@ int32_t CDComponentsRegistryTable::GetByIDAndType(uint32_t id, eReplicaComponent return defaultValue; #endif } - +std::vector> CDComponentsRegistryTable::GetTemplateComponents(LOT templateId) { + std::vector> components; + for (int8_t i = 0; static_cast(i) < eReplicaComponentType::NUMBER_OF_COMPONENTS; i++) { + auto compId = GetByIDAndType(templateId, static_cast(i), -1); + if (compId != -1) components.push_back(std::make_pair(static_cast(i), compId)); + } + return components; +} diff --git a/dDatabase/Tables/CDComponentsRegistryTable.h b/dDatabase/Tables/CDComponentsRegistryTable.h index 990072c9..855679d5 100644 --- a/dDatabase/Tables/CDComponentsRegistryTable.h +++ b/dDatabase/Tables/CDComponentsRegistryTable.h @@ -2,6 +2,7 @@ // Custom Classes #include "CDTable.h" +#include "dCommonVars.h" enum class eReplicaComponentType : uint32_t; struct CDComponentsRegistry { @@ -18,4 +19,5 @@ private: public: CDComponentsRegistryTable(); int32_t GetByIDAndType(uint32_t id, eReplicaComponentType componentType, int32_t defaultValue = 0); + std::vector> GetTemplateComponents(LOT templateId); }; diff --git a/dGame/Character.cpp b/dGame/Character.cpp index 319b9376..f06416c1 100644 --- a/dGame/Character.cpp +++ b/dGame/Character.cpp @@ -427,7 +427,7 @@ void Character::SetPlayerFlag(const int32_t flagId, const bool value) { auto* player = EntityManager::Instance()->GetEntity(m_ObjectID); if (player != nullptr) { - auto* missionComponent = player->GetComponent(); + auto missionComponent = player->GetComponent(); if (missionComponent != nullptr) { missionComponent->Progress(eMissionTaskType::PLAYER_FLAG, flagId); @@ -538,7 +538,7 @@ void Character::OnZoneLoad() { return; } - auto* missionComponent = m_OurEntity->GetComponent(); + auto missionComponent = m_OurEntity->GetComponent(); if (missionComponent != nullptr) { // Fix the monument race flag @@ -563,7 +563,7 @@ void Character::OnZoneLoad() { } } - auto* inventoryComponent = m_OurEntity->GetComponent(); + auto inventoryComponent = m_OurEntity->GetComponent(); if (inventoryComponent == nullptr) { return; diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 6de6ba62..3377e8cd 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -120,667 +120,261 @@ Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity) } Entity::~Entity() { - if (m_Character) { - m_Character->SaveXMLToDatabase(); - } + if (m_Character) m_Character->SaveXMLToDatabase(); CancelAllTimers(); CancelCallbackTimers(); - const auto components = m_Components; + for (auto child : m_ChildEntities) if (child) child->RemoveParent(); - for (const auto& pair : components) { - delete pair.second; - - m_Components.erase(pair.first); - } - - for (auto child : m_ChildEntities) { - if (child) child->RemoveParent(); - } - - if (m_ParentEntity) { - m_ParentEntity->RemoveChild(this); - } + if (m_ParentEntity) m_ParentEntity->RemoveChild(this); } void Entity::Initialize() { - /** - * Setup trigger - */ - - const auto triggerInfo = GetVarAsString(u"trigger_id"); - - if (!triggerInfo.empty()) m_Components.emplace(eReplicaComponentType::TRIGGER, new TriggerComponent(this, triggerInfo)); - - /** - * Setup groups - */ - - const auto groupIDs = GetVarAsString(u"groupID"); - - if (!groupIDs.empty()) { - m_Groups = GeneralUtils::SplitString(groupIDs, ';'); - m_Groups.erase(m_Groups.end() - 1); - } - - /** - * Set ourselves as a child of our parent - */ - - if (m_ParentEntity != nullptr) { - m_ParentEntity->AddChild(this); - } - - // Get the registry table - CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); - - /** - * Special case for BBB models. They have components not corresponding to the registry. - */ - - if (m_TemplateID == 14) { - const auto simplePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SIMPLE_PHYSICS); - - SimplePhysicsComponent* comp = new SimplePhysicsComponent(simplePhysicsComponentID, this); - m_Components.insert(std::make_pair(eReplicaComponentType::SIMPLE_PHYSICS, comp)); - - ModelComponent* modelcomp = new ModelComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::MODEL, modelcomp)); - - RenderComponent* render = new RenderComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render)); - - auto destroyableComponent = new DestroyableComponent(this); - destroyableComponent->SetHealth(1); - destroyableComponent->SetMaxHealth(1.0f); - destroyableComponent->SetFaction(-1, true); - destroyableComponent->SetIsSmashable(true); - m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, destroyableComponent)); - // We have all our components. - return; - } - - /** - * Go through all the components and check if this entity has them. - * - * Not all components are implemented. Some are represented by a nullptr, as they hold no data. - */ - - if (GetParentUser()) { - auto missions = new MissionComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::MISSION, missions)); - missions->LoadFromXml(m_Character->GetXMLDoc()); - } - - uint32_t petComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET); - if (petComponentId > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::PET, new PetComponent(this, petComponentId))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ZONE_CONTROL) > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::ZONE_CONTROL, nullptr)); - } - - uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE); - if (possessableComponentId > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::POSSESSABLE, new PossessableComponent(this, possessableComponentId))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY) > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::MODULE_ASSEMBLY, new ModuleAssemblyComponent(this))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS) > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::RACING_STATS, nullptr)); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1) >= 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::LUP_EXHIBIT, new LUPExhibitComponent(this))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL) > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::RACING_CONTROL, new RacingControlComponent(this))); - } - - const auto propertyEntranceComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_ENTRANCE); - if (propertyEntranceComponentID > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::PROPERTY_ENTRANCE, - new PropertyEntranceComponent(propertyEntranceComponentID, this))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS) > 0) { - ControllablePhysicsComponent* controllablePhysics = new ControllablePhysicsComponent(this); - - if (m_Character) { - controllablePhysics->LoadFromXml(m_Character->GetXMLDoc()); - - const auto mapID = Game::server->GetZoneID(); - - //If we came from another zone, put us in the starting loc - if (m_Character->GetZoneID() != Game::server->GetZoneID() || mapID == 1603) { // Exception for Moon Base as you tend to spawn on the roof. - NiPoint3 pos; - NiQuaternion rot; - - const auto& targetSceneName = m_Character->GetTargetScene(); - auto* targetScene = EntityManager::Instance()->GetSpawnPointEntity(targetSceneName); - - if (m_Character->HasBeenToWorld(mapID) && targetSceneName.empty()) { - pos = m_Character->GetRespawnPoint(mapID); - rot = dZoneManager::Instance()->GetZone()->GetSpawnRot(); - } else if (targetScene != nullptr) { - pos = targetScene->GetPosition(); - rot = targetScene->GetRotation(); - } else { - pos = dZoneManager::Instance()->GetZone()->GetSpawnPos(); - rot = dZoneManager::Instance()->GetZone()->GetSpawnRot(); - } - - controllablePhysics->SetPosition(pos); - controllablePhysics->SetRotation(rot); - } - } else { - controllablePhysics->SetPosition(m_DefaultPosition); - controllablePhysics->SetRotation(m_DefaultRotation); - } - - m_Components.insert(std::make_pair(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysics)); - } - - // If an entity is marked a phantom, simple physics is made into phantom phyics. - bool markedAsPhantom = GetVar(u"markedAsPhantom"); - - const auto simplePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SIMPLE_PHYSICS); - if (!markedAsPhantom && simplePhysicsComponentID > 0) { - SimplePhysicsComponent* comp = new SimplePhysicsComponent(simplePhysicsComponentID, this); - m_Components.insert(std::make_pair(eReplicaComponentType::SIMPLE_PHYSICS, comp)); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS) > 0) { - RigidbodyPhantomPhysicsComponent* comp = new RigidbodyPhantomPhysicsComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, comp)); - } - - if (markedAsPhantom || compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS) > 0) { - PhantomPhysicsComponent* phantomPhysics = new PhantomPhysicsComponent(this); - phantomPhysics->SetPhysicsEffectActive(false); - m_Components.insert(std::make_pair(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysics)); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VEHICLE_PHYSICS) > 0) { - VehiclePhysicsComponent* vehiclePhysicsComponent = new VehiclePhysicsComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)); - vehiclePhysicsComponent->SetPosition(m_DefaultPosition); - vehiclePhysicsComponent->SetRotation(m_DefaultRotation); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) { - auto* comp = new SoundTriggerComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp)); - } - - //Also check for the collectible id: - m_CollectibleID = GetVarAs(u"collectible_id"); - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF) > 0) { - BuffComponent* comp = new BuffComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::BUFF, comp)); - } - - int collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE); - - if (collectibleComponentID > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::COLLECTIBLE, nullptr)); - } - - /** - * Multiple components require the destructible component. - */ - - int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF); - int rebuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD); - - int componentID = 0; - if (collectibleComponentID > 0) componentID = collectibleComponentID; - if (rebuildComponentID > 0) componentID = rebuildComponentID; - if (buffComponentID > 0) componentID = buffComponentID; - - CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable(); - std::vector destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); - - if (buffComponentID > 0 || collectibleComponentID > 0) { - DestroyableComponent* comp = new DestroyableComponent(this); - if (m_Character) { - comp->LoadFromXml(m_Character->GetXMLDoc()); - } else { - if (componentID > 0) { - std::vector destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); - - if (destCompData.size() > 0) { - if (HasComponent(eReplicaComponentType::RACING_STATS)) { - destCompData[0].imagination = 60; - } - - comp->SetHealth(destCompData[0].life); - comp->SetImagination(destCompData[0].imagination); - comp->SetArmor(destCompData[0].armor); - - comp->SetMaxHealth(destCompData[0].life); - comp->SetMaxImagination(destCompData[0].imagination); - comp->SetMaxArmor(destCompData[0].armor); - - comp->SetIsSmashable(destCompData[0].isSmashable); - - comp->SetLootMatrixID(destCompData[0].LootMatrixIndex); - - // Now get currency information - uint32_t npcMinLevel = destCompData[0].level; - uint32_t currencyIndex = destCompData[0].CurrencyIndex; - - CDCurrencyTableTable* currencyTable = CDClientManager::Instance().GetTable(); - std::vector currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); }); - - if (currencyValues.size() > 0) { - // Set the coins - comp->SetMinCoins(currencyValues[0].minvalue); - comp->SetMaxCoins(currencyValues[0].maxvalue); - } - - // extraInfo overrides - comp->SetIsSmashable(GetVarAs(u"is_smashable") != 0); - } - } else { - comp->SetHealth(1); - comp->SetArmor(0); - - comp->SetMaxHealth(1); - comp->SetMaxArmor(0); - - comp->SetIsSmashable(true); - comp->AddFaction(-1); - comp->AddFaction(6); //Smashables - - // A race car has 60 imagination, other entities defaults to 0. - comp->SetImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0); - comp->SetMaxImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0); - } - } - - if (destCompData.size() > 0) { - comp->AddFaction(destCompData[0].faction); - std::stringstream ss(destCompData[0].factionList); - std::string token; - - while (std::getline(ss, token, ',')) { - if (std::stoi(token) == destCompData[0].faction) continue; - - if (token != "") { - comp->AddFaction(std::stoi(token)); - } - } - } - - m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp)); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER) > 0 || m_Character) { - // Character Component always has a possessor, level, and forced movement components - m_Components.insert(std::make_pair(eReplicaComponentType::POSSESSOR, new PossessorComponent(this))); - - // load in the xml for the level - auto* levelComp = new LevelProgressionComponent(this); - levelComp->LoadFromXml(m_Character->GetXMLDoc()); - m_Components.insert(std::make_pair(eReplicaComponentType::LEVEL_PROGRESSION, levelComp)); - - m_Components.insert(std::make_pair(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, new PlayerForcedMovementComponent(this))); - - CharacterComponent* charComp = new CharacterComponent(this, m_Character); - charComp->LoadFromXml(m_Character->GetXMLDoc()); - m_Components.insert(std::make_pair(eReplicaComponentType::CHARACTER, charComp)); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) { - InventoryComponent* comp = nullptr; - if (m_Character) comp = new InventoryComponent(this, m_Character->GetXMLDoc()); - else comp = new InventoryComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp)); - } - // if this component exists, then we initialize it. it's value is always 0 - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH_LUP, -1) != -1) { - auto comp = new RocketLaunchLupComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH_LUP, comp)); - } - - /** - * This is a bit of a mess - */ - - CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable(); - 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) { - m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, new ScriptComponent(this, scriptName, true, client && scriptName.empty()))); - } - - // ZoneControl script - if (m_TemplateID == 2365) { - CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable(); - const auto zoneID = dZoneManager::Instance()->GetZoneID(); - const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID()); - - if (zoneData != nullptr) { - int zoneScriptID = zoneData->scriptID; - CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID); - - ScriptComponent* comp = new ScriptComponent(this, zoneScriptData.script_name, true); - m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, comp)); - } - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1) != -1 || m_Character) { - SkillComponent* comp = new SkillComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::SKILL, comp)); - } - - const auto combatAiId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI); - if (combatAiId > 0) { - BaseCombatAIComponent* comp = new BaseCombatAIComponent(this, combatAiId); - m_Components.insert(std::make_pair(eReplicaComponentType::BASE_COMBAT_AI, comp)); - } - - if (int componentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD) > 0) { - RebuildComponent* comp = new RebuildComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::QUICK_BUILD, comp)); - - CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable(); - std::vector rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == rebuildComponentID); }); - - if (rebCompData.size() > 0) { - comp->SetResetTime(rebCompData[0].reset_time); - comp->SetCompleteTime(rebCompData[0].complete_time); - comp->SetTakeImagination(rebCompData[0].take_imagination); - comp->SetInterruptible(rebCompData[0].interruptible); - comp->SetSelfActivator(rebCompData[0].self_activator); - comp->SetActivityId(rebCompData[0].activityID); - comp->SetPostImaginationCost(rebCompData[0].post_imagination_cost); - comp->SetTimeBeforeSmash(rebCompData[0].time_before_smash); - - const auto rebuildResetTime = GetVar(u"rebuild_reset_time"); - - if (rebuildResetTime != 0.0f) { - comp->SetResetTime(rebuildResetTime); - - if (m_TemplateID == 9483) // Look away! - { - comp->SetResetTime(comp->GetResetTime() + 25); - } - } - - const auto activityID = GetVar(u"activityID"); - - if (activityID > 0) { - comp->SetActivityId(activityID); - } - - const auto compTime = GetVar(u"compTime"); - - if (compTime > 0) { - comp->SetCompleteTime(compTime); - } - } - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1) != -1) { - SwitchComponent* comp = new SwitchComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::SWITCH, comp)); - } - - if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) { - VendorComponent* comp = new VendorComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp)); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) { - auto* component = new PropertyVendorComponent(this); - m_Components.insert_or_assign(eReplicaComponentType::PROPERTY_VENDOR, component); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1) != -1) { - auto* component = new PropertyManagementComponent(this); - m_Components.insert_or_assign(eReplicaComponentType::PROPERTY_MANAGEMENT, component); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1) != -1) { // you have to determine it like this because all bouncers have a componentID of 0 - BouncerComponent* comp = new BouncerComponent(this); - m_Components.insert(std::make_pair(eReplicaComponentType::BOUNCER, comp)); - } - - int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER); - if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) { - RenderComponent* render = new RenderComponent(this, renderComponentId); - m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render)); - } - - if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER) > 0) || m_Character) { - m_Components.insert(std::make_pair(eReplicaComponentType::MISSION_OFFER, new MissionOfferComponent(this, m_TemplateID))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1) != -1) { - m_Components.insert(std::make_pair(eReplicaComponentType::BUILD_BORDER, new BuildBorderComponent(this))); - } - - // Scripted activity component - int scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY); - if ((scriptedActivityID > 0)) { - m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPTED_ACTIVITY, new ScriptedActivityComponent(this, scriptedActivityID))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent()) { - m_Components.insert(std::make_pair(eReplicaComponentType::MODEL, new ModelComponent(this))); - if (m_Components.find(eReplicaComponentType::DESTROYABLE) == m_Components.end()) { - auto destroyableComponent = new DestroyableComponent(this); - destroyableComponent->SetHealth(1); - destroyableComponent->SetMaxHealth(1.0f); - destroyableComponent->SetFaction(-1, true); - destroyableComponent->SetIsSmashable(true); - m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, destroyableComponent)); - } - } - - PetComponent* petComponent; - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) { - m_Components.insert(std::make_pair(eReplicaComponentType::ITEM, nullptr)); - } - - // Shooting gallery component - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SHOOTING_GALLERY) > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::SHOOTING_GALLERY, new ShootingGalleryComponent(this))); - } - - if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1) != -1) { - m_Components.insert(std::make_pair(eReplicaComponentType::PROPERTY, new PropertyComponent(this))); - } - - const int rocketId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH); - if ((rocketId > 0)) { - m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH, new RocketLaunchpadControlComponent(this, rocketId))); - } - - const int32_t railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR); - if (railComponentID > 0) { - m_Components.insert(std::make_pair(eReplicaComponentType::RAIL_ACTIVATOR, new RailActivatorComponent(this, railComponentID))); - } - - int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI); - if (movementAIID > 0) { - CDMovementAIComponentTable* moveAITable = CDClientManager::Instance().GetTable(); - std::vector moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); }); - - if (moveAIComp.size() > 0) { - MovementAIInfo moveInfo = MovementAIInfo(); - - moveInfo.movementType = moveAIComp[0].MovementType; - moveInfo.wanderChance = moveAIComp[0].WanderChance; - moveInfo.wanderRadius = moveAIComp[0].WanderRadius; - moveInfo.wanderSpeed = moveAIComp[0].WanderSpeed; - moveInfo.wanderDelayMax = moveAIComp[0].WanderDelayMax; - moveInfo.wanderDelayMin = moveAIComp[0].WanderDelayMin; - - bool useWanderDB = GetVar(u"usewanderdb"); - - if (!useWanderDB) { - const auto wanderOverride = GetVarAs(u"wanderRadius"); - - if (wanderOverride != 0.0f) { - moveInfo.wanderRadius = wanderOverride; - } - } - - m_Components.insert(std::make_pair(eReplicaComponentType::MOVEMENT_AI, new MovementAIComponent(this, moveInfo))); - } - } else if (petComponentId > 0 || combatAiId > 0 && GetComponent()->GetTetherSpeed() > 0) { - MovementAIInfo moveInfo = MovementAIInfo(); - moveInfo.movementType = ""; - moveInfo.wanderChance = 0; - moveInfo.wanderRadius = 16; - moveInfo.wanderSpeed = 2.5f; - moveInfo.wanderDelayMax = 5; - moveInfo.wanderDelayMin = 2; - - m_Components.insert(std::make_pair(eReplicaComponentType::MOVEMENT_AI, new MovementAIComponent(this, moveInfo))); - } - - std::string pathName = GetVarAsString(u"attached_path"); - const Path* path = dZoneManager::Instance()->GetZone()->GetPath(pathName); - - //Check to see if we have an attached path and add the appropiate component to handle it: - if (path){ - // if we have a moving platform path, then we need a moving platform component - if (path->pathType == PathType::MovingPlatform) { - MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName); - m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat)); - // else if we are a movement path - } /*else if (path->pathType == PathType::Movement) { - auto movementAIcomp = GetComponent(); - if (movementAIcomp){ - // TODO: set path in existing movementAIComp - } else { - // TODO: create movementAIcomp and set path - } - }*/ - } else { - // else we still need to setup moving platform if it has a moving platform comp but no path - int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1); - if (movingPlatformComponentId >= 0) { - MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName); - m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat)); - } - } - - int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR); - if (proximityMonitorID > 0) { - CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance().GetTable(); - std::vector proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); }); - if (proxCompData.size() > 0) { - std::vector proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ','); - ProximityMonitorComponent* comp = new ProximityMonitorComponent(this, std::stoi(proximityStr[0]), std::stoi(proximityStr[1])); - m_Components.insert(std::make_pair(eReplicaComponentType::PROXIMITY_MONITOR, comp)); - } - } - - // Hacky way to trigger these when the object has had a chance to get constructed - AddCallbackTimer(0, [this]() { - for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { - script->OnStartup(this); - } - }); - - if (!m_Character && EntityManager::Instance()->GetGhostingEnabled()) { - // Don't ghost what is likely large scene elements - if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) { - goto no_ghosting; - } - - /* Filter for ghosting candidates. - * - * Don't ghost moving platforms, until we've got proper syncing for those. - * Don't ghost big phantom physics triggers, as putting those to sleep might prevent interactions. - * Don't ghost property related objects, as the client expects those to always be loaded. - */ - if ( - !EntityManager::IsExcludedFromGhosting(GetLOT()) && - !HasComponent(eReplicaComponentType::SCRIPTED_ACTIVITY) && - !HasComponent(eReplicaComponentType::MOVING_PLATFORM) && - !HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) && - !HasComponent(eReplicaComponentType::PROPERTY) && - !HasComponent(eReplicaComponentType::RACING_CONTROL) && - !HasComponent(eReplicaComponentType::VEHICLE_PHYSICS) - ) - //if (HasComponent(eReplicaComponentType::BASE_COMBAT_AI)) - { - m_IsGhostingCandidate = true; - } - - if (GetLOT() == 6368) { - m_IsGhostingCandidate = true; - } - - // Special case for collectibles in Ninjago - if (HasComponent(eReplicaComponentType::COLLECTIBLE) && Game::server->GetZoneID() == 2000) { - m_IsGhostingCandidate = true; - } - } - -no_ghosting: - - TriggerEvent(eTriggerEventType::CREATE, this); - - if (m_Character) { - auto* controllablePhysicsComponent = GetComponent(); - auto* levelComponent = GetComponent(); - - if (controllablePhysicsComponent && levelComponent) { - controllablePhysicsComponent->SetSpeedMultiplier(levelComponent->GetSpeedBase() / 500.0f); + auto* componentsRegistry = CDClientManager::Instance().GetTable(); + auto components = componentsRegistry->GetTemplateComponents(m_TemplateID); + for (const auto& [componentTemplate, componentId] : components) { + switch (componentTemplate) { + case eReplicaComponentType::CONTROLLABLE_PHYSICS: + AddComponent(this); + break; + case eReplicaComponentType::RENDER: + break; + case eReplicaComponentType::SIMPLE_PHYSICS: + break; + case eReplicaComponentType::CHARACTER: + break; + case eReplicaComponentType::SCRIPT: + break; + case eReplicaComponentType::BOUNCER: + break; + case eReplicaComponentType::BUFF: + break; + case eReplicaComponentType::GHOST: + break; + case eReplicaComponentType::SKILL: + break; + case eReplicaComponentType::SPAWNER: + break; + case eReplicaComponentType::ITEM: + break; + case eReplicaComponentType::REBUILD: + break; + case eReplicaComponentType::REBUILD_START: + break; + case eReplicaComponentType::REBUILD_ACTIVATOR: + break; + case eReplicaComponentType::ICON_ONLY: + break; + case eReplicaComponentType::VENDOR: + break; + case eReplicaComponentType::INVENTORY: + break; + case eReplicaComponentType::PROJECTILE_PHYSICS: + break; + case eReplicaComponentType::SHOOTING_GALLERY: + break; + case eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS: + break; + case eReplicaComponentType::DROP_EFFECT: + break; + case eReplicaComponentType::CHEST: + break; + case eReplicaComponentType::COLLECTIBLE: + break; + case eReplicaComponentType::BLUEPRINT: + break; + case eReplicaComponentType::MOVING_PLATFORM: + break; + case eReplicaComponentType::PET: + break; + case eReplicaComponentType::PLATFORM_BOUNDARY: + break; + case eReplicaComponentType::MODULE: + break; + case eReplicaComponentType::ARCADE: + break; + case eReplicaComponentType::VEHICLE_PHYSICS: + break; + case eReplicaComponentType::MOVEMENT_AI: + break; + case eReplicaComponentType::EXHIBIT: + break; + case eReplicaComponentType::OVERHEAD_ICON: + break; + case eReplicaComponentType::PET_CONTROL: + break; + case eReplicaComponentType::MINIFIG: + break; + case eReplicaComponentType::PROPERTY: + break; + case eReplicaComponentType::PET_CREATOR: + break; + case eReplicaComponentType::MODEL_BUILDER: + break; + case eReplicaComponentType::SCRIPTED_ACTIVITY: + break; + case eReplicaComponentType::PHANTOM_PHYSICS: + break; + case eReplicaComponentType::SPRINGPAD: + break; + case eReplicaComponentType::MODEL: + break; + case eReplicaComponentType::PROPERTY_ENTRANCE: + break; + case eReplicaComponentType::FX: + break; + case eReplicaComponentType::PROPERTY_MANAGEMENT: + break; + case eReplicaComponentType::VEHICLE_PHYSICS_NEW: + break; + case eReplicaComponentType::PHYSICS_SYSTEM: + break; + case eReplicaComponentType::QUICK_BUILD: + break; + case eReplicaComponentType::SWITCH: + break; + case eReplicaComponentType::ZONE_CONTROL: + break; + case eReplicaComponentType::CHANGLING: + break; + case eReplicaComponentType::CHOICE_BUILD: + break; + case eReplicaComponentType::PACKAGE: + break; + case eReplicaComponentType::SOUND_REPEATER: + break; + case eReplicaComponentType::SOUND_AMBIENT_2D: + break; + case eReplicaComponentType::SOUND_AMBIENT_3D: + break; + case eReplicaComponentType::PRECONDITION: + break; + case eReplicaComponentType::PLAYER_FLAG: + break; + case eReplicaComponentType::CUSTOM_BUILD_ASSEMBLY: + break; + case eReplicaComponentType::BASE_COMBAT_AI: + break; + case eReplicaComponentType::MODULE_ASSEMBLY: + break; + case eReplicaComponentType::SHOWCASE_MODEL_HANDLER: + break; + case eReplicaComponentType::RACING_MODULE: + break; + case eReplicaComponentType::GENERIC_ACTIVATOR: + break; + case eReplicaComponentType::PROPERTY_VENDOR: + break; + case eReplicaComponentType::HF_LIGHT_DIRECTION_GADGET: + break; + case eReplicaComponentType::ROCKET_LAUNCH: + break; + case eReplicaComponentType::ROCKET_LANDING: + break; + case eReplicaComponentType::TRIGGER: + break; + case eReplicaComponentType::DROPPED_LOOT: + break; + case eReplicaComponentType::RACING_CONTROL: + break; + case eReplicaComponentType::FACTION_TRIGGER: + break; + case eReplicaComponentType::MISSION_OFFER: + break; + case eReplicaComponentType::RACING_STATS: + break; + case eReplicaComponentType::LUP_EXHIBIT: + break; + case eReplicaComponentType::BBB: + break; + case eReplicaComponentType::SOUND_TRIGGER: + break; + case eReplicaComponentType::PROXIMITY_MONITOR: + break; + case eReplicaComponentType::RACING_SOUND_TRIGGER: + break; + case eReplicaComponentType::CHAT: + break; + case eReplicaComponentType::FRIENDS_LIST: + break; + case eReplicaComponentType::GUILD: + break; + case eReplicaComponentType::LOCAL_SYSTEM: + break; + case eReplicaComponentType::MISSION: + break; + case eReplicaComponentType::MUTABLE_MODEL_BEHAVIORS: + break; + case eReplicaComponentType::PATHFINDING: + break; + case eReplicaComponentType::PET_TAMING_CONTROL: + break; + case eReplicaComponentType::PROPERTY_EDITOR: + break; + case eReplicaComponentType::SKINNED_RENDER: + break; + case eReplicaComponentType::SLASH_COMMAND: + break; + case eReplicaComponentType::STATUS_EFFECT: + break; + case eReplicaComponentType::TEAMS: + break; + case eReplicaComponentType::TEXT_EFFECT: + break; + case eReplicaComponentType::TRADE: + break; + case eReplicaComponentType::USER_CONTROL: + break; + case eReplicaComponentType::IGNORE_LIST: + break; + case eReplicaComponentType::ROCKET_LAUNCH_LUP: + break; + case eReplicaComponentType::BUFF_REAL: + break; + case eReplicaComponentType::INTERACTION_MANAGER: + break; + case eReplicaComponentType::DONATION_VENDOR: + break; + case eReplicaComponentType::COMBAT_MEDIATOR: + break; + case eReplicaComponentType::COMMENDATION_VENDOR: + break; + case eReplicaComponentType::GATE_RUSH_CONTROL: + break; + case eReplicaComponentType::RAIL_ACTIVATOR: + break; + case eReplicaComponentType::ROLLER: + break; + case eReplicaComponentType::PLAYER_FORCED_MOVEMENT: + break; + case eReplicaComponentType::CRAFTING: + break; + case eReplicaComponentType::POSSESSABLE: + break; + case eReplicaComponentType::LEVEL_PROGRESSION: + break; + case eReplicaComponentType::POSSESSOR: + break; + case eReplicaComponentType::MOUNT_CONTROL: + break; + case eReplicaComponentType::UNKNOWN_112: + break; + case eReplicaComponentType::PROPERTY_PLAQUE: + break; + case eReplicaComponentType::BUILD_BORDER: + break; + case eReplicaComponentType::UNKNOWN_115: + break; + case eReplicaComponentType::CULLING_PLANE: + break; + case eReplicaComponentType::NUMBER_OF_COMPONENTS: + break; + case eReplicaComponentType::DESTROYABLE: + break; + case eReplicaComponentType::INVALID: + default: + Game::logger->Log("Entity", "blah %i %i", componentId, m_TemplateID); } } } @@ -801,33 +395,20 @@ User* Entity::GetParentUser() const { return static_cast(this)->GetParentUser(); } -Component* Entity::GetComponent(eReplicaComponentType componentID) const { +const ComponentPtr Entity::GetComponent(eReplicaComponentType componentID) const { const auto& index = m_Components.find(componentID); - - if (index == m_Components.end()) { - return nullptr; - } - - return index->second; + return index != m_Components.end() ? index->second : nullptr; } bool Entity::HasComponent(const eReplicaComponentType componentId) const { return m_Components.find(componentId) != m_Components.end(); } -void Entity::AddComponent(const eReplicaComponentType componentId, Component* component) { - if (HasComponent(componentId)) { - return; - } - - m_Components.insert_or_assign(componentId, component); -} - -std::vector Entity::GetScriptComponents() { - std::vector comps; - for (std::pair p : m_Components) { - if (p.first == eReplicaComponentType::SCRIPT) { - comps.push_back(static_cast(p.second)); +std::vector> Entity::GetScriptComponents() { + std::vector> comps; + for (const auto&[componentType, component] : m_Components) { + if (componentType == eReplicaComponentType::SCRIPT) { + comps.push_back(std::dynamic_pointer_cast(component)); } } @@ -836,7 +417,7 @@ std::vector Entity::GetScriptComponents() { void Entity::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, const std::string& notificationName) { if (notificationName == "HitOrHealResult" || notificationName == "Hit") { - auto* destroyableComponent = GetComponent(); + auto destroyableComponent = GetComponent(); if (!destroyableComponent) return; destroyableComponent->Subscribe(scriptObjId, scriptToAdd); } @@ -844,28 +425,20 @@ void Entity::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, co void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationName) { if (notificationName == "HitOrHealResult" || notificationName == "Hit") { - auto* destroyableComponent = GetComponent(); + auto destroyableComponent = GetComponent(); if (!destroyableComponent) return; destroyableComponent->Unsubscribe(scriptObjId); } } void Entity::SetProximityRadius(float proxRadius, std::string name) { - ProximityMonitorComponent* proxMon = GetComponent(); - if (!proxMon) { - proxMon = new ProximityMonitorComponent(this); - m_Components.insert_or_assign(eReplicaComponentType::PROXIMITY_MONITOR, proxMon); - } - proxMon->SetProximityRadius(proxRadius, name); + auto proximityMonitorComponent = AddComponent(this); + if (proximityMonitorComponent) proximityMonitorComponent->SetProximityRadius(proxRadius, name); } void Entity::SetProximityRadius(dpEntity* entity, std::string name) { - ProximityMonitorComponent* proxMon = GetComponent(); - if (!proxMon) { - proxMon = new ProximityMonitorComponent(this); - m_Components.insert_or_assign(eReplicaComponentType::PROXIMITY_MONITOR, proxMon); - } - proxMon->SetProximityRadius(entity, name); + auto proximityMonitorComponent = AddComponent(this); + if (proximityMonitorComponent) proximityMonitorComponent->SetProximityRadius(entity, name); } void Entity::SetGMLevel(eGameMasterLevel value) { @@ -878,7 +451,7 @@ void Entity::SetGMLevel(eGameMasterLevel value) { } } - CharacterComponent* character = GetComponent(); + auto character = GetComponent(); if (character) character->SetGMLevel(value); GameMessages::SendGMLevelBroadcast(m_ObjectID, value); @@ -950,8 +523,8 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacke outBitStream->Write0(); //No ldf data } - TriggerComponent* triggerComponent; - if (TryGetComponent(eReplicaComponentType::TRIGGER, triggerComponent)) { + auto triggerComponent = GetComponent(); + if (triggerComponent) { // has trigger component, check to see if we have events to handle auto* trigger = triggerComponent->GetTrigger(); outBitStream->Write(trigger && trigger->events.size() > 0); @@ -1007,210 +580,6 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacke void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType) { - /** - * This has to be done in a specific order. - */ - - bool destroyableSerialized = false; - bool bIsInitialUpdate = false; - if (packetType == eReplicaPacketType::CONSTRUCTION) bIsInitialUpdate = true; - unsigned int flags = 0; - - PossessableComponent* possessableComponent; - if (TryGetComponent(eReplicaComponentType::POSSESSABLE, possessableComponent)) { - possessableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - ModuleAssemblyComponent* moduleAssemblyComponent; - if (TryGetComponent(eReplicaComponentType::MODULE_ASSEMBLY, moduleAssemblyComponent)) { - moduleAssemblyComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - ControllablePhysicsComponent* controllablePhysicsComponent; - if (TryGetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysicsComponent)) { - controllablePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - SimplePhysicsComponent* simplePhysicsComponent; - if (TryGetComponent(eReplicaComponentType::SIMPLE_PHYSICS, simplePhysicsComponent)) { - simplePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - RigidbodyPhantomPhysicsComponent* rigidbodyPhantomPhysics; - if (TryGetComponent(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, rigidbodyPhantomPhysics)) { - rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - VehiclePhysicsComponent* vehiclePhysicsComponent; - if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) { - vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - PhantomPhysicsComponent* phantomPhysicsComponent; - if (TryGetComponent(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysicsComponent)) { - phantomPhysicsComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - SoundTriggerComponent* soundTriggerComponent; - if (TryGetComponent(eReplicaComponentType::SOUND_TRIGGER, soundTriggerComponent)) { - soundTriggerComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - BuffComponent* buffComponent; - if (TryGetComponent(eReplicaComponentType::BUFF, buffComponent)) { - buffComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - - DestroyableComponent* destroyableComponent; - if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - destroyableSerialized = true; - } - - if (HasComponent(eReplicaComponentType::COLLECTIBLE)) { - DestroyableComponent* destroyableComponent; - if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - destroyableSerialized = true; - outBitStream->Write(m_CollectibleID); // Collectable component - } - - PetComponent* petComponent; - if (TryGetComponent(eReplicaComponentType::PET, petComponent)) { - petComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - CharacterComponent* characterComponent; - if (TryGetComponent(eReplicaComponentType::CHARACTER, characterComponent)) { - - PossessorComponent* possessorComponent; - if (TryGetComponent(eReplicaComponentType::POSSESSOR, possessorComponent)) { - possessorComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } else { - // Should never happen, but just to be safe - outBitStream->Write0(); - } - - LevelProgressionComponent* levelProgressionComponent; - if (TryGetComponent(eReplicaComponentType::LEVEL_PROGRESSION, levelProgressionComponent)) { - levelProgressionComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } else { - // Should never happen, but just to be safe - outBitStream->Write0(); - } - - PlayerForcedMovementComponent* playerForcedMovementComponent; - if (TryGetComponent(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, playerForcedMovementComponent)) { - playerForcedMovementComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } else { - // Should never happen, but just to be safe - outBitStream->Write0(); - } - - characterComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - if (HasComponent(eReplicaComponentType::ITEM)) { - outBitStream->Write0(); - } - - InventoryComponent* inventoryComponent; - if (TryGetComponent(eReplicaComponentType::INVENTORY, inventoryComponent)) { - inventoryComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - ScriptComponent* scriptComponent; - if (TryGetComponent(eReplicaComponentType::SCRIPT, scriptComponent)) { - scriptComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - SkillComponent* skillComponent; - if (TryGetComponent(eReplicaComponentType::SKILL, skillComponent)) { - skillComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - BaseCombatAIComponent* baseCombatAiComponent; - if (TryGetComponent(eReplicaComponentType::BASE_COMBAT_AI, baseCombatAiComponent)) { - baseCombatAiComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - RebuildComponent* rebuildComponent; - if (TryGetComponent(eReplicaComponentType::QUICK_BUILD, rebuildComponent)) { - DestroyableComponent* destroyableComponent; - if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - destroyableSerialized = true; - rebuildComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - MovingPlatformComponent* movingPlatformComponent; - if (TryGetComponent(eReplicaComponentType::MOVING_PLATFORM, movingPlatformComponent)) { - movingPlatformComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - SwitchComponent* switchComponent; - if (TryGetComponent(eReplicaComponentType::SWITCH, switchComponent)) { - switchComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - VendorComponent* vendorComponent; - if (TryGetComponent(eReplicaComponentType::VENDOR, vendorComponent)) { - vendorComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - BouncerComponent* bouncerComponent; - if (TryGetComponent(eReplicaComponentType::BOUNCER, bouncerComponent)) { - bouncerComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - ScriptedActivityComponent* scriptedActivityComponent; - if (TryGetComponent(eReplicaComponentType::SCRIPTED_ACTIVITY, scriptedActivityComponent)) { - scriptedActivityComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - ShootingGalleryComponent* shootingGalleryComponent; - if (TryGetComponent(eReplicaComponentType::SHOOTING_GALLERY, shootingGalleryComponent)) { - shootingGalleryComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - RacingControlComponent* racingControlComponent; - if (TryGetComponent(eReplicaComponentType::RACING_CONTROL, racingControlComponent)) { - racingControlComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - LUPExhibitComponent* lupExhibitComponent; - if (TryGetComponent(eReplicaComponentType::LUP_EXHIBIT, lupExhibitComponent)) { - lupExhibitComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - ModelComponent* modelComponent; - if (TryGetComponent(eReplicaComponentType::MODEL, modelComponent)) { - modelComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - RenderComponent* renderComponent; - if (TryGetComponent(eReplicaComponentType::RENDER, renderComponent)) { - renderComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - } - - if (modelComponent) { - DestroyableComponent* destroyableComponent; - if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) { - destroyableComponent->Serialize(outBitStream, bIsInitialUpdate, flags); - destroyableSerialized = true; - } - } - - if (HasComponent(eReplicaComponentType::ZONE_CONTROL)) { - outBitStream->Write(0x40000000); - } - - // BBB Component, unused currently - // Need to to write0 so that is serialized correctly - // TODO: Implement BBB Component - outBitStream->Write0(); } void Entity::ResetFlags() { @@ -1296,7 +665,7 @@ void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxN script->OnProximityUpdate(this, other, proxName, status); } - RocketLaunchpadControlComponent* rocketComp = GetComponent(); + auto rocketComp = GetComponent(); if (!rocketComp) return; rocketComp->OnProximityUpdate(other, proxName, status); @@ -1314,7 +683,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) { callback(other); } - SwitchComponent* switchComp = GetComponent(); + auto switchComp = GetComponent(); if (switchComp) { switchComp->EntityEnter(other); } @@ -1325,7 +694,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) { const auto& poi = GetVar(u"POI"); if (!poi.empty()) { - auto* missionComponent = other->GetComponent(); + auto missionComponent = other->GetComponent(); if (missionComponent != nullptr) { missionComponent->Progress(eMissionTaskType::EXPLORE, 0, 0, GeneralUtils::UTF16ToWTF8(poi)); @@ -1333,7 +702,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) { } if (!other->GetIsDead()) { - auto* combat = GetComponent(); + auto combat = GetComponent(); if (combat != nullptr) { const auto index = std::find(m_TargetsInPhantom.begin(), m_TargetsInPhantom.end(), otherEntity); @@ -1359,7 +728,7 @@ void Entity::OnCollisionLeavePhantom(const LWOOBJID otherEntity) { TriggerEvent(eTriggerEventType::EXIT, other); - SwitchComponent* switchComp = GetComponent(); + auto switchComp = GetComponent(); if (switchComp) { switchComp->EntityLeave(other); } @@ -1502,12 +871,12 @@ void Entity::RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled) void Entity::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType) { if (!m_PlayerIsReadyForUpdates) return; - auto* destroyableComponent = GetComponent(); + auto destroyableComponent = GetComponent(); if (destroyableComponent == nullptr) { Kill(EntityManager::Instance()->GetEntity(source)); return; } - auto* possessorComponent = GetComponent(); + auto possessorComponent = GetComponent(); if (possessorComponent) { if (possessorComponent->GetPossessable() != LWOOBJID_EMPTY) { auto* mount = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable()); @@ -1564,14 +933,14 @@ void Entity::Kill(Entity* murderer) { } // Track a player being smashed - auto* characterComponent = GetComponent(); + auto characterComponent = GetComponent(); if (characterComponent != nullptr) { characterComponent->UpdatePlayerStatistic(TimesSmashed); } // Track a player smashing something else if (murderer != nullptr) { - auto* murdererCharacterComponent = murderer->GetComponent(); + auto murdererCharacterComponent = murderer->GetComponent(); if (murdererCharacterComponent != nullptr) { murdererCharacterComponent->UpdatePlayerStatistic(SmashablesSmashed); } @@ -1587,14 +956,14 @@ void Entity::AddCollisionPhantomCallback(const std::function& callback) const { - auto* rebuildComponent = GetComponent(); + auto rebuildComponent = GetComponent(); if (rebuildComponent != nullptr) { rebuildComponent->AddRebuildCompleteCallback(callback); } } bool Entity::GetIsDead() const { - DestroyableComponent* dest = GetComponent(); + auto dest = GetComponent(); if (dest && dest->GetArmor() == 0 && dest->GetHealth() == 0) return true; return false; @@ -1608,7 +977,7 @@ void Entity::AddLootItem(const Loot::Info& info) { void Entity::PickupItem(const LWOOBJID& objectID) { if (!IsPlayer()) return; - InventoryComponent* inv = GetComponent(); + auto inv = GetComponent(); if (!inv) return; CDObjectsTable* objectsTable = CDClientManager::Instance().GetTable(); @@ -1617,7 +986,7 @@ void Entity::PickupItem(const LWOOBJID& objectID) { for (const auto& p : droppedLoot) { if (p.first == objectID) { - auto* characterComponent = GetComponent(); + auto characterComponent = GetComponent(); if (characterComponent != nullptr) { characterComponent->TrackLOTCollection(p.second.lot); } @@ -1632,7 +1001,7 @@ void Entity::PickupItem(const LWOOBJID& objectID) { SkillComponent::HandleUnmanaged(behaviorData.behaviorID, GetObjectID()); - auto* missionComponent = GetComponent(); + auto missionComponent = GetComponent(); if (missionComponent != nullptr) { missionComponent->Progress(eMissionTaskType::POWERUP, skill.skillID); @@ -1757,7 +1126,7 @@ bool Entity::IsPlayer() const { } void Entity::TriggerEvent(eTriggerEventType event, Entity* optionalTarget) { - auto* triggerComponent = GetComponent(); + auto triggerComponent = GetComponent(); if (triggerComponent) triggerComponent->TriggerEvent(event, optionalTarget); } @@ -1806,7 +1175,7 @@ void Entity::SetObservers(int8_t value) { } void Entity::Sleep() { - auto* baseCombatAIComponent = GetComponent(); + auto baseCombatAIComponent = GetComponent(); if (baseCombatAIComponent != nullptr) { baseCombatAIComponent->Sleep(); @@ -1814,7 +1183,7 @@ void Entity::Sleep() { } void Entity::Wake() { - auto* baseCombatAIComponent = GetComponent(); + auto baseCombatAIComponent = GetComponent(); if (baseCombatAIComponent != nullptr) { baseCombatAIComponent->Wake(); @@ -1829,112 +1198,112 @@ bool Entity::IsSleeping() const { const NiPoint3& Entity::GetPosition() const { if (!this) return NiPoint3::ZERO; - auto* controllable = GetComponent(); + auto controllable = GetComponent(); if (controllable != nullptr) { return controllable->GetPosition(); } - auto* phantom = GetComponent(); + auto phantom = GetComponent(); if (phantom != nullptr) { return phantom->GetPosition(); } - auto* simple = GetComponent(); + auto simple = GetComponent(); if (simple != nullptr) { return simple->GetPosition(); } - auto* vehicel = GetComponent(); + auto vehicle = GetComponent(); - if (vehicel != nullptr) { - return vehicel->GetPosition(); + if (vehicle != nullptr) { + return vehicle->GetPosition(); } return NiPoint3::ZERO; } const NiQuaternion& Entity::GetRotation() const { - auto* controllable = GetComponent(); + auto controllable = GetComponent(); if (controllable != nullptr) { return controllable->GetRotation(); } - auto* phantom = GetComponent(); + auto phantom = GetComponent(); if (phantom != nullptr) { return phantom->GetRotation(); } - auto* simple = GetComponent(); + auto simple = GetComponent(); if (simple != nullptr) { return simple->GetRotation(); } - auto* vehicel = GetComponent(); + auto vehicle = GetComponent(); - if (vehicel != nullptr) { - return vehicel->GetRotation(); + if (vehicle != nullptr) { + return vehicle->GetRotation(); } return NiQuaternion::IDENTITY; } void Entity::SetPosition(NiPoint3 position) { - auto* controllable = GetComponent(); + auto controllable = GetComponent(); if (controllable != nullptr) { controllable->SetPosition(position); } - auto* phantom = GetComponent(); + auto phantom = GetComponent(); if (phantom != nullptr) { phantom->SetPosition(position); } - auto* simple = GetComponent(); + auto simple = GetComponent(); if (simple != nullptr) { simple->SetPosition(position); } - auto* vehicel = GetComponent(); + auto vehicle = GetComponent(); - if (vehicel != nullptr) { - vehicel->SetPosition(position); + if (vehicle != nullptr) { + vehicle->SetPosition(position); } EntityManager::Instance()->SerializeEntity(this); } void Entity::SetRotation(NiQuaternion rotation) { - auto* controllable = GetComponent(); + auto controllable = GetComponent(); if (controllable != nullptr) { controllable->SetRotation(rotation); } - auto* phantom = GetComponent(); + auto phantom = GetComponent(); if (phantom != nullptr) { phantom->SetRotation(rotation); } - auto* simple = GetComponent(); + auto simple = GetComponent(); if (simple != nullptr) { simple->SetRotation(rotation); } - auto* vehicel = GetComponent(); + auto vehicle = GetComponent(); - if (vehicel != nullptr) { - vehicel->SetRotation(rotation); + if (vehicle != nullptr) { + vehicle->SetRotation(rotation); } EntityManager::Instance()->SerializeEntity(this); diff --git a/dGame/Entity.h b/dGame/Entity.h index 90f2a34f..9f3198a6 100644 --- a/dGame/Entity.h +++ b/dGame/Entity.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "NiPoint3.h" #include "NiQuaternion.h" @@ -44,6 +45,8 @@ namespace CppScripts { /** * An entity in the world. Has multiple components. */ + +using ComponentPtr = std::shared_ptr; class Entity { public: explicit Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity = nullptr); @@ -136,19 +139,17 @@ public: * Component management */ - Component* GetComponent(eReplicaComponentType componentID) const; + const ComponentPtr GetComponent(eReplicaComponentType componentID) const; template - T* GetComponent() const; - - template - bool TryGetComponent(eReplicaComponentType componentId, T*& component) const; + std::shared_ptr GetComponent() const; bool HasComponent(eReplicaComponentType componentId) const; - void AddComponent(eReplicaComponentType componentId, Component* component); + template + std::shared_ptr AddComponent(ConstructorValues... arguments); - std::vector GetScriptComponents(); + std::vector> GetScriptComponents(); void Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd, const std::string& notificationName); void Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationName); @@ -169,8 +170,6 @@ public: void AddToGroup(const std::string& group); bool IsPlayer() const; - std::unordered_map& GetComponents() { return m_Components; } // TODO: Remove - void WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType); void WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType packetType); void ResetFlags(); @@ -320,7 +319,7 @@ protected: std::vector> m_DieCallbacks; std::vector> m_PhantomCollisionCallbacks; - std::unordered_map m_Components; + std::unordered_map m_Components; std::vector m_Timers; std::vector m_PendingTimers; std::vector m_CallbackTimers; @@ -345,31 +344,11 @@ protected: std::vector m_TargetsInPhantom; }; -/** - * Template definitions. - */ - -template -bool Entity::TryGetComponent(const eReplicaComponentType componentId, T*& component) const { - const auto& index = m_Components.find(componentId); - - if (index == m_Components.end()) { - component = nullptr; - - return false; - } - - component = dynamic_cast(index->second); - - return true; -} - template -T* Entity::GetComponent() const { - return dynamic_cast(GetComponent(T::ComponentType)); +std::shared_ptr Entity::GetComponent() const { + return std::dynamic_pointer_cast(GetComponent(T::ComponentType)); } - template const T& Entity::GetVar(const std::u16string& name) const { auto* data = GetVarData(name); @@ -501,3 +480,10 @@ T Entity::GetNetworkVar(const std::u16string& name) { return LDFData::Default; } + +template +std::shared_ptr Entity::AddComponent(ConstructorValues...arguments) { + if (GetComponent()) return nullptr; + + m_Components.insert_or_assign(ComponentType::ComponentType, std::make_shared(arguments...)); +} diff --git a/dGame/EntityInitializeOld.cc b/dGame/EntityInitializeOld.cc new file mode 100644 index 00000000..321b220c --- /dev/null +++ b/dGame/EntityInitializeOld.cc @@ -0,0 +1,640 @@ +Entity::Initialize() { + /** + * Setup trigger + */ + + const auto triggerInfo = GetVarAsString(u"trigger_id"); + + if (!triggerInfo.empty()) m_Components.emplace(eReplicaComponentType::TRIGGER, new TriggerComponent(this, triggerInfo)); + + /** + * Setup groups + */ + + const auto groupIDs = GetVarAsString(u"groupID"); + + if (!groupIDs.empty()) { + m_Groups = GeneralUtils::SplitString(groupIDs, ';'); + m_Groups.erase(m_Groups.end() - 1); + } + + /** + * Set ourselves as a child of our parent + */ + + if (m_ParentEntity != nullptr) { + m_ParentEntity->AddChild(this); + } + + // Get the registry table + CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable(); + + /** + * Special case for BBB models. They have components not corresponding to the registry. + */ + + if (m_TemplateID == 14) { + const auto simplePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SIMPLE_PHYSICS); + + SimplePhysicsComponent* comp = new SimplePhysicsComponent(simplePhysicsComponentID, this); + m_Components.insert(std::make_pair(eReplicaComponentType::SIMPLE_PHYSICS, comp)); + + ModelComponent* modelcomp = new ModelComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::MODEL, modelcomp)); + + RenderComponent* render = new RenderComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render)); + + auto destroyableComponent = new DestroyableComponent(this); + destroyableComponent->SetHealth(1); + destroyableComponent->SetMaxHealth(1.0f); + destroyableComponent->SetFaction(-1, true); + destroyableComponent->SetIsSmashable(true); + m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, destroyableComponent)); + // We have all our components. + return; + } + + /** + * Go through all the components and check if this entity has them. + * + * Not all components are implemented. Some are represented by a nullptr, as they hold no data. + */ + + if (GetParentUser()) { + auto missions = new MissionComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::MISSION, missions)); + missions->LoadFromXml(m_Character->GetXMLDoc()); + } + + uint32_t petComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET); + if (petComponentId > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::PET, new PetComponent(this, petComponentId))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ZONE_CONTROL) > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::ZONE_CONTROL, nullptr)); + } + + uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE); + if (possessableComponentId > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::POSSESSABLE, new PossessableComponent(this, possessableComponentId))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY) > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::MODULE_ASSEMBLY, new ModuleAssemblyComponent(this))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS) > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::RACING_STATS, nullptr)); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1) >= 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::LUP_EXHIBIT, new LUPExhibitComponent(this))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL) > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::RACING_CONTROL, new RacingControlComponent(this))); + } + + const auto propertyEntranceComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_ENTRANCE); + if (propertyEntranceComponentID > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::PROPERTY_ENTRANCE, + new PropertyEntranceComponent(propertyEntranceComponentID, this))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS) > 0) { + ControllablePhysicsComponent* controllablePhysics = new ControllablePhysicsComponent(this); + + if (m_Character) { + controllablePhysics->LoadFromXml(m_Character->GetXMLDoc()); + + const auto mapID = Game::server->GetZoneID(); + + //If we came from another zone, put us in the starting loc + if (m_Character->GetZoneID() != Game::server->GetZoneID() || mapID == 1603) { // Exception for Moon Base as you tend to spawn on the roof. + NiPoint3 pos; + NiQuaternion rot; + + const auto& targetSceneName = m_Character->GetTargetScene(); + auto* targetScene = EntityManager::Instance()->GetSpawnPointEntity(targetSceneName); + + if (m_Character->HasBeenToWorld(mapID) && targetSceneName.empty()) { + pos = m_Character->GetRespawnPoint(mapID); + rot = dZoneManager::Instance()->GetZone()->GetSpawnRot(); + } else if (targetScene != nullptr) { + pos = targetScene->GetPosition(); + rot = targetScene->GetRotation(); + } else { + pos = dZoneManager::Instance()->GetZone()->GetSpawnPos(); + rot = dZoneManager::Instance()->GetZone()->GetSpawnRot(); + } + + controllablePhysics->SetPosition(pos); + controllablePhysics->SetRotation(rot); + } + } else { + controllablePhysics->SetPosition(m_DefaultPosition); + controllablePhysics->SetRotation(m_DefaultRotation); + } + + m_Components.insert(std::make_pair(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysics)); + } + + // If an entity is marked a phantom, simple physics is made into phantom phyics. + bool markedAsPhantom = GetVar(u"markedAsPhantom"); + + const auto simplePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SIMPLE_PHYSICS); + if (!markedAsPhantom && simplePhysicsComponentID > 0) { + SimplePhysicsComponent* comp = new SimplePhysicsComponent(simplePhysicsComponentID, this); + m_Components.insert(std::make_pair(eReplicaComponentType::SIMPLE_PHYSICS, comp)); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS) > 0) { + RigidbodyPhantomPhysicsComponent* comp = new RigidbodyPhantomPhysicsComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, comp)); + } + + if (markedAsPhantom || compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS) > 0) { + PhantomPhysicsComponent* phantomPhysics = new PhantomPhysicsComponent(this); + phantomPhysics->SetPhysicsEffectActive(false); + m_Components.insert(std::make_pair(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysics)); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VEHICLE_PHYSICS) > 0) { + VehiclePhysicsComponent* vehiclePhysicsComponent = new VehiclePhysicsComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)); + vehiclePhysicsComponent->SetPosition(m_DefaultPosition); + vehiclePhysicsComponent->SetRotation(m_DefaultRotation); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) { + auto* comp = new SoundTriggerComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp)); + } + + //Also check for the collectible id: + m_CollectibleID = GetVarAs(u"collectible_id"); + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF) > 0) { + BuffComponent* comp = new BuffComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::BUFF, comp)); + } + + int collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE); + + if (collectibleComponentID > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::COLLECTIBLE, nullptr)); + } + + /** + * Multiple components require the destructible component. + */ + + int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF); + int rebuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD); + + int componentID = 0; + if (collectibleComponentID > 0) componentID = collectibleComponentID; + if (rebuildComponentID > 0) componentID = rebuildComponentID; + if (buffComponentID > 0) componentID = buffComponentID; + + CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable(); + std::vector destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); + + if (buffComponentID > 0 || collectibleComponentID > 0) { + DestroyableComponent* comp = new DestroyableComponent(this); + if (m_Character) { + comp->LoadFromXml(m_Character->GetXMLDoc()); + } else { + if (componentID > 0) { + std::vector destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); + + if (destCompData.size() > 0) { + if (HasComponent(eReplicaComponentType::RACING_STATS)) { + destCompData[0].imagination = 60; + } + + comp->SetHealth(destCompData[0].life); + comp->SetImagination(destCompData[0].imagination); + comp->SetArmor(destCompData[0].armor); + + comp->SetMaxHealth(destCompData[0].life); + comp->SetMaxImagination(destCompData[0].imagination); + comp->SetMaxArmor(destCompData[0].armor); + + comp->SetIsSmashable(destCompData[0].isSmashable); + + comp->SetLootMatrixID(destCompData[0].LootMatrixIndex); + + // Now get currency information + uint32_t npcMinLevel = destCompData[0].level; + uint32_t currencyIndex = destCompData[0].CurrencyIndex; + + CDCurrencyTableTable* currencyTable = CDClientManager::Instance().GetTable(); + std::vector currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); }); + + if (currencyValues.size() > 0) { + // Set the coins + comp->SetMinCoins(currencyValues[0].minvalue); + comp->SetMaxCoins(currencyValues[0].maxvalue); + } + + // extraInfo overrides + comp->SetIsSmashable(GetVarAs(u"is_smashable") != 0); + } + } else { + comp->SetHealth(1); + comp->SetArmor(0); + + comp->SetMaxHealth(1); + comp->SetMaxArmor(0); + + comp->SetIsSmashable(true); + comp->AddFaction(-1); + comp->AddFaction(6); //Smashables + + // A race car has 60 imagination, other entities defaults to 0. + comp->SetImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0); + comp->SetMaxImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0); + } + } + + if (destCompData.size() > 0) { + comp->AddFaction(destCompData[0].faction); + std::stringstream ss(destCompData[0].factionList); + std::string token; + + while (std::getline(ss, token, ',')) { + if (std::stoi(token) == destCompData[0].faction) continue; + + if (token != "") { + comp->AddFaction(std::stoi(token)); + } + } + } + + m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp)); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER) > 0 || m_Character) { + // Character Component always has a possessor, level, and forced movement components + m_Components.insert(std::make_pair(eReplicaComponentType::POSSESSOR, new PossessorComponent(this))); + + // load in the xml for the level + auto* levelComp = new LevelProgressionComponent(this); + levelComp->LoadFromXml(m_Character->GetXMLDoc()); + m_Components.insert(std::make_pair(eReplicaComponentType::LEVEL_PROGRESSION, levelComp)); + + m_Components.insert(std::make_pair(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, new PlayerForcedMovementComponent(this))); + + CharacterComponent* charComp = new CharacterComponent(this, m_Character); + charComp->LoadFromXml(m_Character->GetXMLDoc()); + m_Components.insert(std::make_pair(eReplicaComponentType::CHARACTER, charComp)); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) { + InventoryComponent* comp = nullptr; + if (m_Character) comp = new InventoryComponent(this, m_Character->GetXMLDoc()); + else comp = new InventoryComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp)); + } + // if this component exists, then we initialize it. it's value is always 0 + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH_LUP, -1) != -1) { + auto comp = new RocketLaunchLupComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH_LUP, comp)); + } + + /** + * This is a bit of a mess + */ + + CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable(); + 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) { + m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, new ScriptComponent(this, scriptName, true, client && scriptName.empty()))); + } + + // ZoneControl script + if (m_TemplateID == 2365) { + CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable(); + const auto zoneID = dZoneManager::Instance()->GetZoneID(); + const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID()); + + if (zoneData != nullptr) { + int zoneScriptID = zoneData->scriptID; + CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID); + + ScriptComponent* comp = new ScriptComponent(this, zoneScriptData.script_name, true); + m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, comp)); + } + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1) != -1 || m_Character) { + SkillComponent* comp = new SkillComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::SKILL, comp)); + } + + const auto combatAiId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI); + if (combatAiId > 0) { + BaseCombatAIComponent* comp = new BaseCombatAIComponent(this, combatAiId); + m_Components.insert(std::make_pair(eReplicaComponentType::BASE_COMBAT_AI, comp)); + } + + if (int componentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD) > 0) { + RebuildComponent* comp = new RebuildComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::QUICK_BUILD, comp)); + + CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable(); + std::vector rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == rebuildComponentID); }); + + if (rebCompData.size() > 0) { + comp->SetResetTime(rebCompData[0].reset_time); + comp->SetCompleteTime(rebCompData[0].complete_time); + comp->SetTakeImagination(rebCompData[0].take_imagination); + comp->SetInterruptible(rebCompData[0].interruptible); + comp->SetSelfActivator(rebCompData[0].self_activator); + comp->SetActivityId(rebCompData[0].activityID); + comp->SetPostImaginationCost(rebCompData[0].post_imagination_cost); + comp->SetTimeBeforeSmash(rebCompData[0].time_before_smash); + + const auto rebuildResetTime = GetVar(u"rebuild_reset_time"); + + if (rebuildResetTime != 0.0f) { + comp->SetResetTime(rebuildResetTime); + + if (m_TemplateID == 9483) // Look away! + { + comp->SetResetTime(comp->GetResetTime() + 25); + } + } + + const auto activityID = GetVar(u"activityID"); + + if (activityID > 0) { + comp->SetActivityId(activityID); + } + + const auto compTime = GetVar(u"compTime"); + + if (compTime > 0) { + comp->SetCompleteTime(compTime); + } + } + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1) != -1) { + SwitchComponent* comp = new SwitchComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::SWITCH, comp)); + } + + if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) { + VendorComponent* comp = new VendorComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp)); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) { + auto* component = new PropertyVendorComponent(this); + m_Components.insert_or_assign(eReplicaComponentType::PROPERTY_VENDOR, component); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1) != -1) { + auto* component = new PropertyManagementComponent(this); + m_Components.insert_or_assign(eReplicaComponentType::PROPERTY_MANAGEMENT, component); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1) != -1) { // you have to determine it like this because all bouncers have a componentID of 0 + BouncerComponent* comp = new BouncerComponent(this); + m_Components.insert(std::make_pair(eReplicaComponentType::BOUNCER, comp)); + } + + int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER); + if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) { + RenderComponent* render = new RenderComponent(this, renderComponentId); + m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render)); + } + + if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER) > 0) || m_Character) { + m_Components.insert(std::make_pair(eReplicaComponentType::MISSION_OFFER, new MissionOfferComponent(this, m_TemplateID))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1) != -1) { + m_Components.insert(std::make_pair(eReplicaComponentType::BUILD_BORDER, new BuildBorderComponent(this))); + } + + // Scripted activity component + int scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY); + if ((scriptedActivityID > 0)) { + m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPTED_ACTIVITY, new ScriptedActivityComponent(this, scriptedActivityID))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent()) { + m_Components.insert(std::make_pair(eReplicaComponentType::MODEL, new ModelComponent(this))); + if (m_Components.find(eReplicaComponentType::DESTROYABLE) == m_Components.end()) { + auto destroyableComponent = new DestroyableComponent(this); + destroyableComponent->SetHealth(1); + destroyableComponent->SetMaxHealth(1.0f); + destroyableComponent->SetFaction(-1, true); + destroyableComponent->SetIsSmashable(true); + m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, destroyableComponent)); + } + } + + PetComponent* petComponent; + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) { + m_Components.insert(std::make_pair(eReplicaComponentType::ITEM, nullptr)); + } + + // Shooting gallery component + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SHOOTING_GALLERY) > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::SHOOTING_GALLERY, new ShootingGalleryComponent(this))); + } + + if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1) != -1) { + m_Components.insert(std::make_pair(eReplicaComponentType::PROPERTY, new PropertyComponent(this))); + } + + const int rocketId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH); + if ((rocketId > 0)) { + m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH, new RocketLaunchpadControlComponent(this, rocketId))); + } + + const int32_t railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR); + if (railComponentID > 0) { + m_Components.insert(std::make_pair(eReplicaComponentType::RAIL_ACTIVATOR, new RailActivatorComponent(this, railComponentID))); + } + + int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI); + if (movementAIID > 0) { + CDMovementAIComponentTable* moveAITable = CDClientManager::Instance().GetTable(); + std::vector moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); }); + + if (moveAIComp.size() > 0) { + MovementAIInfo moveInfo = MovementAIInfo(); + + moveInfo.movementType = moveAIComp[0].MovementType; + moveInfo.wanderChance = moveAIComp[0].WanderChance; + moveInfo.wanderRadius = moveAIComp[0].WanderRadius; + moveInfo.wanderSpeed = moveAIComp[0].WanderSpeed; + moveInfo.wanderDelayMax = moveAIComp[0].WanderDelayMax; + moveInfo.wanderDelayMin = moveAIComp[0].WanderDelayMin; + + bool useWanderDB = GetVar(u"usewanderdb"); + + if (!useWanderDB) { + const auto wanderOverride = GetVarAs(u"wanderRadius"); + + if (wanderOverride != 0.0f) { + moveInfo.wanderRadius = wanderOverride; + } + } + + m_Components.insert(std::make_pair(eReplicaComponentType::MOVEMENT_AI, new MovementAIComponent(this, moveInfo))); + } + } else if (petComponentId > 0 || combatAiId > 0 && GetComponent()->GetTetherSpeed() > 0) { + MovementAIInfo moveInfo = MovementAIInfo(); + moveInfo.movementType = ""; + moveInfo.wanderChance = 0; + moveInfo.wanderRadius = 16; + moveInfo.wanderSpeed = 2.5f; + moveInfo.wanderDelayMax = 5; + moveInfo.wanderDelayMin = 2; + + m_Components.insert(std::make_pair(eReplicaComponentType::MOVEMENT_AI, new MovementAIComponent(this, moveInfo))); + } + + std::string pathName = GetVarAsString(u"attached_path"); + const Path* path = dZoneManager::Instance()->GetZone()->GetPath(pathName); + + //Check to see if we have an attached path and add the appropiate component to handle it: + if (path){ + // if we have a moving platform path, then we need a moving platform component + if (path->pathType == PathType::MovingPlatform) { + MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName); + m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat)); + // else if we are a movement path + } /*else if (path->pathType == PathType::Movement) { + auto movementAIcomp = GetComponent(); + if (movementAIcomp){ + // TODO: set path in existing movementAIComp + } else { + // TODO: create movementAIcomp and set path + } + }*/ + } else { + // else we still need to setup moving platform if it has a moving platform comp but no path + int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1); + if (movingPlatformComponentId >= 0) { + MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName); + m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat)); + } + } + + int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR); + if (proximityMonitorID > 0) { + CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance().GetTable(); + std::vector proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); }); + if (proxCompData.size() > 0) { + std::vector proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ','); + ProximityMonitorComponent* comp = new ProximityMonitorComponent(this, std::stoi(proximityStr[0]), std::stoi(proximityStr[1])); + m_Components.insert(std::make_pair(eReplicaComponentType::PROXIMITY_MONITOR, comp)); + } + } + + // Hacky way to trigger these when the object has had a chance to get constructed + AddCallbackTimer(0, [this]() { + for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { + script->OnStartup(this); + } + }); + + if (!m_Character && EntityManager::Instance()->GetGhostingEnabled()) { + // Don't ghost what is likely large scene elements + if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) { + goto no_ghosting; + } + + /* Filter for ghosting candidates. + * + * Don't ghost moving platforms, until we've got proper syncing for those. + * Don't ghost big phantom physics triggers, as putting those to sleep might prevent interactions. + * Don't ghost property related objects, as the client expects those to always be loaded. + */ + if ( + !EntityManager::IsExcludedFromGhosting(GetLOT()) && + !HasComponent(eReplicaComponentType::SCRIPTED_ACTIVITY) && + !HasComponent(eReplicaComponentType::MOVING_PLATFORM) && + !HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) && + !HasComponent(eReplicaComponentType::PROPERTY) && + !HasComponent(eReplicaComponentType::RACING_CONTROL) && + !HasComponent(eReplicaComponentType::VEHICLE_PHYSICS) + ) + //if (HasComponent(eReplicaComponentType::BASE_COMBAT_AI)) + { + m_IsGhostingCandidate = true; + } + + if (GetLOT() == 6368) { + m_IsGhostingCandidate = true; + } + + // Special case for collectibles in Ninjago + if (HasComponent(eReplicaComponentType::COLLECTIBLE) && Game::server->GetZoneID() == 2000) { + m_IsGhostingCandidate = true; + } + } + +no_ghosting: + + TriggerEvent(eTriggerEventType::CREATE, this); + + if (m_Character) { + auto* controllablePhysicsComponent = GetComponent(); + auto* levelComponent = GetComponent(); + + if (controllablePhysicsComponent && levelComponent) { + controllablePhysicsComponent->SetSpeedMultiplier(levelComponent->GetSpeedBase() / 500.0f); + } + } +} diff --git a/dGame/EntityManager.cpp b/dGame/EntityManager.cpp index 0fc859bd..c4ccbcdb 100644 --- a/dGame/EntityManager.cpp +++ b/dGame/EntityManager.cpp @@ -483,7 +483,7 @@ void EntityManager::UpdateGhosting(Player* player) { return; } - auto* missionComponent = player->GetComponent(); + auto missionComponent = player->GetComponent(); if (missionComponent == nullptr) { return; @@ -599,7 +599,7 @@ void EntityManager::ScheduleForKill(Entity* entity) { if (!entity) return; - SwitchComponent* switchComp = entity->GetComponent(); + auto switchComp = entity->GetComponent(); if (switchComp) { entity->TriggerEvent(eTriggerEventType::DEACTIVATED, entity); } diff --git a/dGame/Player.cpp b/dGame/Player.cpp index 2e194e6a..c8e35c58 100644 --- a/dGame/Player.cpp +++ b/dGame/Player.cpp @@ -94,7 +94,7 @@ void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) { const auto sysAddr = entity->GetSystemAddress(); auto* character = entity->GetCharacter(); - auto* characterComponent = entity->GetComponent(); + auto characterComponent = entity->GetComponent(); if (character != nullptr && characterComponent != nullptr) { character->SetZoneID(zoneID); diff --git a/dGame/TradingManager.cpp b/dGame/TradingManager.cpp index 281c003d..638e98f8 100644 --- a/dGame/TradingManager.cpp +++ b/dGame/TradingManager.cpp @@ -114,10 +114,10 @@ void Trade::Complete() { if (entityA == nullptr || entityB == nullptr) return; - auto* inventoryA = entityA->GetComponent(); - auto* inventoryB = entityB->GetComponent(); - auto* missionsA = entityA->GetComponent(); - auto* missionsB = entityB->GetComponent(); + auto inventoryA = entityA->GetComponent(); + auto inventoryB = entityB->GetComponent(); + auto missionsA = entityA->GetComponent(); + auto missionsB = entityB->GetComponent(); auto* characterA = entityA->GetCharacter(); auto* characterB = entityB->GetCharacter(); @@ -214,12 +214,12 @@ void Trade::SendUpdateToOther(LWOOBJID participant) { std::vector items{}; - auto* inventoryComponent = self->GetComponent(); + auto inventoryComponent = self->GetComponent(); if (inventoryComponent == nullptr) return; for (const auto tradeItem : itemIds) { - auto* item = inventoryComponent->FindItemById(tradeItem.itemId); + auto item = inventoryComponent->FindItemById(tradeItem.itemId); if (item == nullptr) return; diff --git a/dGame/UserManager.cpp b/dGame/UserManager.cpp index 0161395c..1d58b783 100644 --- a/dGame/UserManager.cpp +++ b/dGame/UserManager.cpp @@ -214,7 +214,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) { continue; } - auto* skillComponent = chars[i]->GetEntity()->GetComponent(); + auto skillComponent = chars[i]->GetEntity()->GetComponent(); if (skillComponent != nullptr) { skillComponent->Reset(); diff --git a/dGame/dBehaviors/ApplyBuffBehavior.cpp b/dGame/dBehaviors/ApplyBuffBehavior.cpp index 35b0f269..e162b5e4 100644 --- a/dGame/dBehaviors/ApplyBuffBehavior.cpp +++ b/dGame/dBehaviors/ApplyBuffBehavior.cpp @@ -4,13 +4,12 @@ #include "BehaviorBranchContext.h" #include "BuffComponent.h" - void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) { auto* entity = EntityManager::Instance()->GetEntity(branch.target == LWOOBJID_EMPTY ? context->originator : branch.target); if (entity == nullptr) return; - auto* buffComponent = entity->GetComponent(); + auto buffComponent = entity->GetComponent(); if (buffComponent == nullptr) return; @@ -23,7 +22,7 @@ void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext b if (entity == nullptr) return; - auto* buffComponent = entity->GetComponent(); + auto buffComponent = entity->GetComponent(); if (buffComponent == nullptr) return; diff --git a/dGame/dBehaviors/AreaOfEffectBehavior.cpp b/dGame/dBehaviors/AreaOfEffectBehavior.cpp index dedede2a..e2f1921d 100644 --- a/dGame/dBehaviors/AreaOfEffectBehavior.cpp +++ b/dGame/dBehaviors/AreaOfEffectBehavior.cpp @@ -87,7 +87,7 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream continue; } - auto* destroyableComponent = entity->GetComponent(); + auto destroyableComponent = entity->GetComponent(); if (destroyableComponent == nullptr) { continue; diff --git a/dGame/dBehaviors/BasicAttackBehavior.cpp b/dGame/dBehaviors/BasicAttackBehavior.cpp index 08d468ef..c0269e36 100644 --- a/dGame/dBehaviors/BasicAttackBehavior.cpp +++ b/dGame/dBehaviors/BasicAttackBehavior.cpp @@ -11,7 +11,7 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi if (context->unmanaged) { auto* entity = EntityManager::Instance()->GetEntity(branch.target); - auto* destroyableComponent = entity->GetComponent(); + auto destroyableComponent = entity->GetComponent(); if (destroyableComponent != nullptr) { PlayFx(u"onhit", entity->GetObjectID()); destroyableComponent->Damage(this->m_MaxDamage, context->originator, context->skillID); @@ -44,7 +44,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit return; } - auto* destroyableComponent = targetEntity->GetComponent(); + auto destroyableComponent = targetEntity->GetComponent(); if (!destroyableComponent) { Game::logger->Log("BasicAttackBehavior", "No destroyable found on the obj/lot %llu/%i", branch.target, targetEntity->GetLOT()); return; @@ -161,7 +161,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet return; } - auto* destroyableComponent = targetEntity->GetComponent(); + auto destroyableComponent = targetEntity->GetComponent(); if (!destroyableComponent || !destroyableComponent->GetOwningEntity()) { Game::logger->Log("BasicAttackBehavior", "No destroyable component on %llu", branch.target); return; diff --git a/dGame/dBehaviors/Behavior.cpp b/dGame/dBehaviors/Behavior.cpp index 8b34507a..cd33da29 100644 --- a/dGame/dBehaviors/Behavior.cpp +++ b/dGame/dBehaviors/Behavior.cpp @@ -328,7 +328,7 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID return; } - auto* renderComponent = targetEntity->GetComponent(); + auto renderComponent = targetEntity->GetComponent(); const auto typeString = GeneralUtils::UTF16ToWTF8(type); diff --git a/dGame/dBehaviors/BehaviorContext.cpp b/dGame/dBehaviors/BehaviorContext.cpp index c7db4208..09920939 100644 --- a/dGame/dBehaviors/BehaviorContext.cpp +++ b/dGame/dBehaviors/BehaviorContext.cpp @@ -35,7 +35,7 @@ uint32_t BehaviorContext::GetUniqueSkillId() const { return 0; } - auto* component = entity->GetComponent(); + auto component = entity->GetComponent(); if (component == nullptr) { Game::logger->Log("BehaviorContext", "No skill component attached to (%llu)!", this->originator);; @@ -331,8 +331,8 @@ std::vector BehaviorContext::GetValidTargets(int32_t ignoreFaction, in } if (ignoreFaction || includeFaction || (!entity->HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) && targets.empty())) { - DestroyableComponent* destroyableComponent; - if (!entity->TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent)) { + auto destroyableComponent = entity->GetComponent(); + if (!destroyableComponent) { return targets; } diff --git a/dGame/dBehaviors/BlockBehavior.cpp b/dGame/dBehaviors/BlockBehavior.cpp index cdbb3d80..bc8e3c3f 100644 --- a/dGame/dBehaviors/BlockBehavior.cpp +++ b/dGame/dBehaviors/BlockBehavior.cpp @@ -18,7 +18,7 @@ void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStrea return; } - auto* destroyableComponent = entity->GetComponent(); + auto destroyableComponent = entity->GetComponent(); if (destroyableComponent == nullptr) { return; @@ -48,7 +48,7 @@ void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branc return; } - auto* destroyableComponent = entity->GetComponent(); + auto destroyableComponent = entity->GetComponent(); destroyableComponent->SetAttacksToBlock(this->m_numAttacksCanBlock); diff --git a/dGame/dBehaviors/BuffBehavior.cpp b/dGame/dBehaviors/BuffBehavior.cpp index a39fd165..552ca160 100644 --- a/dGame/dBehaviors/BuffBehavior.cpp +++ b/dGame/dBehaviors/BuffBehavior.cpp @@ -18,7 +18,7 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream return; } - auto* component = entity->GetComponent(); + auto component = entity->GetComponent(); if (component == nullptr) { Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!", target); @@ -52,7 +52,7 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch return; } - auto* component = entity->GetComponent(); + auto component = entity->GetComponent(); if (component == nullptr) { Game::logger->Log("BuffBehavior", "Invalid target, no destroyable component (%llu)!", target); diff --git a/dGame/dBehaviors/CarBoostBehavior.cpp b/dGame/dBehaviors/CarBoostBehavior.cpp index 1ab0af95..1ed64735 100644 --- a/dGame/dBehaviors/CarBoostBehavior.cpp +++ b/dGame/dBehaviors/CarBoostBehavior.cpp @@ -19,13 +19,13 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitSt Game::logger->Log("Car boost", "Activating car boost!"); - auto* possessableComponent = entity->GetComponent(); + auto possessableComponent = entity->GetComponent(); if (possessableComponent != nullptr) { auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor()); if (possessor != nullptr) { - auto* characterComponent = possessor->GetComponent(); + auto characterComponent = possessor->GetComponent(); if (characterComponent != nullptr) { Game::logger->Log("Car boost", "Tracking car boost!"); characterComponent->UpdatePlayerStatistic(RacingCarBoostsActivated); diff --git a/dGame/dBehaviors/DamageAbsorptionBehavior.cpp b/dGame/dBehaviors/DamageAbsorptionBehavior.cpp index 48dbf705..799641c4 100644 --- a/dGame/dBehaviors/DamageAbsorptionBehavior.cpp +++ b/dGame/dBehaviors/DamageAbsorptionBehavior.cpp @@ -16,7 +16,7 @@ void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStrea return; } - auto* destroyable = target->GetComponent(); + auto destroyable = target->GetComponent(); if (destroyable == nullptr) { return; diff --git a/dGame/dComponents/Component.cpp b/dGame/dComponents/Component.cpp index d04397f4..d46c57dc 100644 --- a/dGame/dComponents/Component.cpp +++ b/dGame/dComponents/Component.cpp @@ -37,3 +37,7 @@ void Component::LoadConfigData() { void Component::LoadTemplateData() { } + +void Component::Serialize(RakNet::BitStream* bitStream, bool isConstruction = false) { + +} diff --git a/dGame/dComponents/Component.h b/dGame/dComponents/Component.h index 25df2d87..c9690811 100644 --- a/dGame/dComponents/Component.h +++ b/dGame/dComponents/Component.h @@ -4,6 +4,10 @@ class Entity; +namespace RakNet { + class BitStream; +} + /** * Component base class, provides methods for game loop updates, usage events and loading and saving to XML. */ @@ -56,6 +60,11 @@ public: * Loads the data of this component from the cdclient database */ virtual void LoadTemplateData(); + + /** + * Serializes the component for delivery to the client(s) + */ + virtual void Serialize(RakNet::BitStream* bitStream, bool isConstruction = false); protected: /** diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index 1c22bdcd..3400aa11 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -85,7 +85,7 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac Entity* entity = EntityManager::Instance()->GetEntity(user->GetLastUsedChar()->GetObjectID()); if (!entity) return; - ControllablePhysicsComponent* comp = static_cast(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS)); + auto comp = entity->GetComponent(); if (!comp) return; /* @@ -100,7 +100,7 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac } */ - auto* possessorComponent = entity->GetComponent(); + auto possessorComponent = entity->GetComponent(); NiPoint3 position; inStream.Read(position.x); @@ -142,13 +142,13 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac auto* possassableEntity = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable()); if (possassableEntity != nullptr) { - auto* possessableComponent = possassableEntity->GetComponent(); + auto possessableComponent = possassableEntity->GetComponent(); if (possessableComponent) { // While possessing something, only update char if we are attached to the thing we are possessing if (possessableComponent->GetPossessionType() != ePossessionType::ATTACHED_VISIBLE) updateChar = false; } - auto* vehiclePhysicsComponent = possassableEntity->GetComponent(); + auto vehiclePhysicsComponent = possassableEntity->GetComponent(); if (vehiclePhysicsComponent != nullptr) { // This is flipped for whatever reason rotation = NiQuaternion(rotation.z, rotation.y, rotation.x, rotation.w); @@ -163,7 +163,7 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac vehiclePhysicsComponent->SetDirtyAngularVelocity(angVelocityFlag); } else { // Need to get the mount's controllable physics - auto* controllablePhysicsComponent = possassableEntity->GetComponent(); + auto controllablePhysicsComponent = possassableEntity->GetComponent(); if (!controllablePhysicsComponent) return; controllablePhysicsComponent->SetPosition(position); controllablePhysicsComponent->SetRotation(rotation); @@ -186,7 +186,7 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac // Handle statistics - auto* characterComponent = entity->GetComponent(); + auto characterComponent = entity->GetComponent(); if (characterComponent != nullptr) { characterComponent->TrackPositionUpdate(position); } diff --git a/dScripts/NtFactionSpyServer.cpp b/dScripts/NtFactionSpyServer.cpp index a1161880..5c3d689b 100644 --- a/dScripts/NtFactionSpyServer.cpp +++ b/dScripts/NtFactionSpyServer.cpp @@ -13,13 +13,7 @@ void NtFactionSpyServer::OnStartup(Entity* self) { SetVariables(self); // Set the proximity to sense later - auto* proximityMonitor = self->GetComponent(); - if (proximityMonitor == nullptr) { - proximityMonitor = new ProximityMonitorComponent(self, -1, -1); - self->AddComponent(eReplicaComponentType::PROXIMITY_MONITOR, proximityMonitor); - } - - proximityMonitor->SetProximityRadius(self->GetVar(m_SpyProximityVariable), m_ProximityName); + self->SetProximityRadius(self->GetVar(m_SpyProximityVariable), m_ProximityName); } void NtFactionSpyServer::SetVariables(Entity* self) { diff --git a/dScripts/ai/AG/AgStromlingProperty.cpp b/dScripts/ai/AG/AgStromlingProperty.cpp index 9a9ae33b..83f5ab7a 100644 --- a/dScripts/ai/AG/AgStromlingProperty.cpp +++ b/dScripts/ai/AG/AgStromlingProperty.cpp @@ -12,6 +12,5 @@ void AgStromlingProperty::OnStartup(Entity* self) { 4 }; - auto* movementAIComponent = new MovementAIComponent(self, movementInfo); - self->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAIComponent); + self->AddComponent(movementInfo); }