mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-11-04 06:32:00 +00:00 
			
		
		
		
	Fully re-implemented initialize
This commit is contained in:
		@@ -56,7 +56,10 @@ const uint32_t LWOCLONEID_INVALID = -1;     //!< Invalid LWOCLONEID
 | 
			
		||||
const uint16_t LWOINSTANCEID_INVALID = -1;  //!< Invalid LWOINSTANCEID
 | 
			
		||||
const uint16_t LWOMAPID_INVALID = -1;       //!< Invalid LWOMAPID
 | 
			
		||||
const uint64_t LWOZONEID_INVALID = 0;       //!< Invalid LWOZONEID
 | 
			
		||||
const uint32_t ZONE_CONTROL_LOT = 2365;
 | 
			
		||||
const LOT LOT_ZONE_CONTROL = 2365;
 | 
			
		||||
const LOT LOT_3D_AMBIENT_SOUND = 6368;
 | 
			
		||||
const LOT LOT_MODEL_IN_WORLD = 14;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const float PI = 3.14159f;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								dGame/Entity.cpp
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								dGame/Entity.cpp
									
									
									
									
									
								
							@@ -205,6 +205,29 @@ void Entity::ApplyComponentConfig(TemplateComponents& components) const {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Entity::AddPathComponent(TemplateComponents& components) const {
 | 
			
		||||
	const Path* path = dZoneManager::Instance()->GetZone()->GetPath(GetVarAsString(u"attached_path"));
 | 
			
		||||
	//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) {
 | 
			
		||||
			bool hasMovingPlatform = std::count_if(components.begin(), components.end(), [](const auto& componentCandidate) {
 | 
			
		||||
				return componentCandidate.first == eReplicaComponentType::MOVING_PLATFORM;
 | 
			
		||||
				}) > 0;
 | 
			
		||||
			if (!hasMovingPlatform) components.emplace_back(eReplicaComponentType::MOVING_PLATFORM, 0U);
 | 
			
		||||
		} else if (path->pathType == PathType::Movement) {
 | 
			
		||||
			bool hasMovementAi = std::count_if(components.begin(), components.end(), [](const auto& componentCandidate) {
 | 
			
		||||
				return componentCandidate.first == eReplicaComponentType::MOVEMENT_AI;
 | 
			
		||||
				}) > 0;
 | 
			
		||||
			if (!hasMovementAi) {
 | 
			
		||||
				components.emplace_back(eReplicaComponentType::MOVEMENT_AI, 0U);
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			Game::logger->Log("Entity", "Unsupported path type %i provided for lot %i.", path->pathType, GetLOT());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Entity::Initialize() {
 | 
			
		||||
	// A few edge cases to tackle first
 | 
			
		||||
	const auto triggerInfo = GetVarAsString(u"trigger_id");
 | 
			
		||||
@@ -222,11 +245,11 @@ void Entity::Initialize() {
 | 
			
		||||
	TemplateComponents components = componentsRegistry->GetTemplateComponents(m_TemplateID);
 | 
			
		||||
	ApplyComponentWhitelist(components);
 | 
			
		||||
	ApplyComponentBlacklist(components);
 | 
			
		||||
	AddPathComponent(components);
 | 
			
		||||
	// Brick-by-Brick models use custom physics depending on _something_ but the client uses 4246 as the simple
 | 
			
		||||
	// physics component id and 4247 for phantom physics. We'll just use the simple physics component for now
 | 
			
		||||
	// since we dont know what the phantom physics are for at the moment.
 | 
			
		||||
	if (GetLOT() == 14) components.emplace_back(eReplicaComponentType::SIMPLE_PHYSICS, 4246U);
 | 
			
		||||
 | 
			
		||||
	if (GetLOT() == LOT_MODEL_IN_WORLD) components.emplace_back(eReplicaComponentType::SIMPLE_PHYSICS, 4246U);
 | 
			
		||||
	for (const auto& [componentTemplate, componentId] : components) {
 | 
			
		||||
		switch (componentTemplate) {
 | 
			
		||||
		case eReplicaComponentType::CONTROLLABLE_PHYSICS:
 | 
			
		||||
@@ -247,7 +270,7 @@ void Entity::Initialize() {
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::SCRIPT: {
 | 
			
		||||
			AddComponent<ScriptComponent>(ScriptComponent::GetScriptName(this, componentId));
 | 
			
		||||
			if (m_TemplateID == ZONE_CONTROL_LOT) {
 | 
			
		||||
			if (m_TemplateID == LOT_ZONE_CONTROL) {
 | 
			
		||||
				const auto zoneScript = ScriptComponent::GetZoneScriptName(componentId);
 | 
			
		||||
				if (!zoneScript.empty()) AddComponent<ScriptComponent>(zoneScript);
 | 
			
		||||
			}
 | 
			
		||||
@@ -257,7 +280,7 @@ void Entity::Initialize() {
 | 
			
		||||
			AddComponent<BouncerComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::DESTROYABLE:
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>();
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(componentId);
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::SKILL:
 | 
			
		||||
			AddComponent<SkillComponent>();
 | 
			
		||||
@@ -279,13 +302,14 @@ void Entity::Initialize() {
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::COLLECTIBLE:
 | 
			
		||||
			AddComponent<CollectibleComponent>();
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>();
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(componentId);
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::MOVING_PLATFORM:
 | 
			
		||||
			AddComponent<MovingPlatformComponent>(GetVarAsString(u"attached_path"));
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::PET:
 | 
			
		||||
			AddComponent<PetComponent>(componentId);
 | 
			
		||||
			AddComponent<MovementAIComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::HAVOK_VEHICLE_PHYSICS: {
 | 
			
		||||
			auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>();
 | 
			
		||||
@@ -295,6 +319,9 @@ void Entity::Initialize() {
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case eReplicaComponentType::MOVEMENT_AI:
 | 
			
		||||
			AddComponent<MovementAIComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::PROPERTY:
 | 
			
		||||
			AddComponent<PropertyComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
@@ -309,7 +336,7 @@ void Entity::Initialize() {
 | 
			
		||||
		case eReplicaComponentType::MODEL_BEHAVIOR: {
 | 
			
		||||
			AddComponent<ModelBehaviorComponent>();
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
 | 
			
		||||
				auto* destroyableComponent = AddComponent<DestroyableComponent>();
 | 
			
		||||
				auto* destroyableComponent = AddComponent<DestroyableComponent>(componentId);
 | 
			
		||||
				if (destroyableComponent) {
 | 
			
		||||
					destroyableComponent->SetHealth(1);
 | 
			
		||||
					destroyableComponent->SetMaxHealth(1.0f);
 | 
			
		||||
@@ -327,7 +354,7 @@ void Entity::Initialize() {
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::QUICK_BUILD:
 | 
			
		||||
			AddComponent<QuickBuildComponent>(componentId);
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>();
 | 
			
		||||
			if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(componentId);
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::SWITCH:
 | 
			
		||||
			AddComponent<SwitchComponent>();
 | 
			
		||||
@@ -335,9 +362,22 @@ void Entity::Initialize() {
 | 
			
		||||
		case eReplicaComponentType::MINIGAME_CONTROL:
 | 
			
		||||
			AddComponent<MinigameControlComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::BASE_COMBAT_AI:
 | 
			
		||||
			AddComponent<BaseCombatAIComponent>(componentId);
 | 
			
		||||
		case eReplicaComponentType::BASE_COMBAT_AI: {
 | 
			
		||||
			auto* baseCombatAiComponent = AddComponent<BaseCombatAIComponent>(componentId);
 | 
			
		||||
			if (baseCombatAiComponent && baseCombatAiComponent->GetTetherSpeed() > 0.0f) {
 | 
			
		||||
				auto* movementAiComponent = AddComponent<MovementAIComponent>();
 | 
			
		||||
				if (!movementAiComponent) break;
 | 
			
		||||
				MovementAIInfo movementAiInfo{};
 | 
			
		||||
				movementAiInfo.movementType = "";
 | 
			
		||||
				movementAiInfo.wanderChance = 0;
 | 
			
		||||
				movementAiInfo.wanderRadius = 16;
 | 
			
		||||
				movementAiInfo.wanderSpeed = 2.5f;
 | 
			
		||||
				movementAiInfo.wanderDelayMax = 5;
 | 
			
		||||
				movementAiInfo.wanderDelayMin = 2;
 | 
			
		||||
				movementAiComponent->SetMoveInfo(movementAiInfo);
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case eReplicaComponentType::MODULE_ASSEMBLY:
 | 
			
		||||
			AddComponent<ModuleAssemblyComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
@@ -362,6 +402,9 @@ void Entity::Initialize() {
 | 
			
		||||
		case eReplicaComponentType::SOUND_TRIGGER:
 | 
			
		||||
			AddComponent<SoundTriggerComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::PROXIMITY_MONITOR:
 | 
			
		||||
			AddComponent<ProximityMonitorComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
		case eReplicaComponentType::MULTI_ZONE_ENTRANCE:
 | 
			
		||||
			AddComponent<MultiZoneEntranceComponent>();
 | 
			
		||||
			break;
 | 
			
		||||
@@ -390,7 +433,6 @@ void Entity::Initialize() {
 | 
			
		||||
		case eReplicaComponentType::PLATFORM_BOUNDARY:
 | 
			
		||||
		case eReplicaComponentType::MODULE:
 | 
			
		||||
		case eReplicaComponentType::JETPACKPAD:
 | 
			
		||||
		case eReplicaComponentType::MOVEMENT_AI:
 | 
			
		||||
		case eReplicaComponentType::EXHIBIT:
 | 
			
		||||
		case eReplicaComponentType::OVERHEAD_ICON:
 | 
			
		||||
		case eReplicaComponentType::PET_CONTROL:
 | 
			
		||||
@@ -419,7 +461,6 @@ void Entity::Initialize() {
 | 
			
		||||
		case eReplicaComponentType::DROPPED_LOOT:
 | 
			
		||||
		case eReplicaComponentType::FACTION_TRIGGER:
 | 
			
		||||
		case eReplicaComponentType::BBB:
 | 
			
		||||
		case eReplicaComponentType::PROXIMITY_MONITOR:
 | 
			
		||||
		case eReplicaComponentType::RACING_SOUND_TRIGGER:
 | 
			
		||||
		case eReplicaComponentType::CHAT_BUBBLE:
 | 
			
		||||
		case eReplicaComponentType::FRIENDS_LIST:
 | 
			
		||||
@@ -460,6 +501,13 @@ void Entity::Initialize() {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	AddCallbackTimer(0.0f, [this]() {
 | 
			
		||||
		auto scripts = CppScripts::GetEntityScripts(this);
 | 
			
		||||
		std::for_each(scripts.begin(), scripts.end(), [this](const auto& script) {
 | 
			
		||||
			script->OnStartup(this);
 | 
			
		||||
			});
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
	std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
 | 
			
		||||
		component.second->LoadTemplateData();
 | 
			
		||||
		});
 | 
			
		||||
@@ -471,11 +519,47 @@ void Entity::Initialize() {
 | 
			
		||||
	std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
 | 
			
		||||
		component.second->Startup();
 | 
			
		||||
		});
 | 
			
		||||
	if (!IsPlayer()) return; // No save data to load for non players
 | 
			
		||||
 | 
			
		||||
	std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
 | 
			
		||||
	// No save data to load for non players
 | 
			
		||||
	if (!IsPlayer()) std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
 | 
			
		||||
		component.second->LoadFromXml(m_Character->GetXMLDoc());
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
	TriggerEvent(eTriggerEventType::CREATE, this);
 | 
			
		||||
	IsGhosted();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Entity::IsGhosted() {
 | 
			
		||||
	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))) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* 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)
 | 
			
		||||
			) {
 | 
			
		||||
			m_IsGhostingCandidate = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (GetLOT() == LOT_3D_AMBIENT_SOUND) m_IsGhostingCandidate = true;
 | 
			
		||||
 | 
			
		||||
		// Special case for collectibles in Ninjago
 | 
			
		||||
		if (HasComponent(eReplicaComponentType::COLLECTIBLE) && Game::server->GetZoneID() == 2000) {
 | 
			
		||||
			m_IsGhostingCandidate = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Entity::operator==(const Entity& other) const {
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,11 @@ public:
 | 
			
		||||
 | 
			
		||||
	// For adding and removing components based on LDF keys
 | 
			
		||||
	void ApplyComponentConfig(TemplateComponents& components) const;
 | 
			
		||||
 | 
			
		||||
	// Paths have several components they could add. This function will add them.
 | 
			
		||||
	void AddPathComponent(TemplateComponents& components) const;
 | 
			
		||||
 | 
			
		||||
	void IsGhosted();
 | 
			
		||||
	virtual void Initialize();
 | 
			
		||||
 | 
			
		||||
	bool operator==(const Entity& other) const;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
Entity::Initialize() {
 | 
			
		||||
// Entity::Initialize() {
 | 
			
		||||
	/**
 | 
			
		||||
	 * Setup trigger
 | 
			
		||||
	 */
 | 
			
		||||
@@ -204,75 +204,75 @@ Entity::Initialize() {
 | 
			
		||||
 | 
			
		||||
	// if (destroyableComponentID > 0 || collectibleComponentID > 0) {
 | 
			
		||||
		// DestroyableComponent* comp = new DestroyableComponent(this);
 | 
			
		||||
		if (m_Character) {
 | 
			
		||||
			comp->LoadFromXml(m_Character->GetXMLDoc());
 | 
			
		||||
		} else {
 | 
			
		||||
			if (componentID > 0) {
 | 
			
		||||
				// std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
 | 
			
		||||
		// if (m_Character) {
 | 
			
		||||
			// comp->LoadFromXml(m_Character->GetXMLDoc());
 | 
			
		||||
		// } else {
 | 
			
		||||
			// if (componentID > 0) {
 | 
			
		||||
			// 	// std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
 | 
			
		||||
 | 
			
		||||
				if (destCompData.size() > 0) {
 | 
			
		||||
					if (HasComponent(eReplicaComponentType::RACING_STATS)) {
 | 
			
		||||
						destCompData[0].imagination = 60;
 | 
			
		||||
					}
 | 
			
		||||
			// 	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->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->SetMaxHealth(destCompData[0].life);
 | 
			
		||||
			// 		comp->SetMaxImagination(destCompData[0].imagination);
 | 
			
		||||
			// 		comp->SetMaxArmor(destCompData[0].armor);
 | 
			
		||||
 | 
			
		||||
					comp->SetIsSmashable(destCompData[0].isSmashable);
 | 
			
		||||
			// 		comp->SetIsSmashable(destCompData[0].isSmashable);
 | 
			
		||||
 | 
			
		||||
					comp->SetLootMatrixID(destCompData[0].LootMatrixIndex);
 | 
			
		||||
			// 		comp->SetLootMatrixID(destCompData[0].LootMatrixIndex);
 | 
			
		||||
 | 
			
		||||
					// Now get currency information
 | 
			
		||||
					uint32_t npcMinLevel = destCompData[0].level;
 | 
			
		||||
					uint32_t currencyIndex = destCompData[0].CurrencyIndex;
 | 
			
		||||
			// 		// Now get currency information
 | 
			
		||||
			// 		uint32_t npcMinLevel = destCompData[0].level;
 | 
			
		||||
			// 		uint32_t currencyIndex = destCompData[0].CurrencyIndex;
 | 
			
		||||
 | 
			
		||||
					CDCurrencyTableTable* currencyTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>();
 | 
			
		||||
					std::vector<CDCurrencyTable> currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); });
 | 
			
		||||
			// 		CDCurrencyTableTable* currencyTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>();
 | 
			
		||||
			// 		std::vector<CDCurrencyTable> 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);
 | 
			
		||||
					}
 | 
			
		||||
			// 		if (currencyValues.size() > 0) {
 | 
			
		||||
			// 			// Set the coins
 | 
			
		||||
			// 			comp->SetMinCoins(currencyValues[0].minvalue);
 | 
			
		||||
			// 			comp->SetMaxCoins(currencyValues[0].maxvalue);
 | 
			
		||||
			// 		}
 | 
			
		||||
 | 
			
		||||
					// extraInfo overrides
 | 
			
		||||
					comp->SetIsSmashable(GetVarAs<int32_t>(u"is_smashable") != 0);
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				comp->SetHealth(1);
 | 
			
		||||
				comp->SetArmor(0);
 | 
			
		||||
			// 		// extraInfo overrides
 | 
			
		||||
			// 		// comp->SetIsSmashable(GetVarAs<int32_t>(u"is_smashable") != 0);
 | 
			
		||||
			// 	}
 | 
			
		||||
			// } else {
 | 
			
		||||
				// comp->SetHealth(1);
 | 
			
		||||
				// comp->SetArmor(0);
 | 
			
		||||
 | 
			
		||||
				comp->SetMaxHealth(1);
 | 
			
		||||
				comp->SetMaxArmor(0);
 | 
			
		||||
				// comp->SetMaxHealth(1);
 | 
			
		||||
				// comp->SetMaxArmor(0);
 | 
			
		||||
 | 
			
		||||
				comp->SetIsSmashable(true);
 | 
			
		||||
				comp->AddFaction(-1);
 | 
			
		||||
				comp->AddFaction(6); //Smashables
 | 
			
		||||
				// 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);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
				// // 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;
 | 
			
		||||
		// 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;
 | 
			
		||||
		// 	while (std::getline(ss, token, ',')) {
 | 
			
		||||
		// 		if (std::stoi(token) == destCompData[0].faction) continue;
 | 
			
		||||
 | 
			
		||||
				if (token != "") {
 | 
			
		||||
					comp->AddFaction(std::stoi(token));
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// 		if (token != "") {
 | 
			
		||||
		// 			comp->AddFaction(std::stoi(token));
 | 
			
		||||
		// 		}
 | 
			
		||||
		// 	}
 | 
			
		||||
		// }
 | 
			
		||||
 | 
			
		||||
		// m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp));
 | 
			
		||||
	}
 | 
			
		||||
@@ -505,64 +505,64 @@ Entity::Initialize() {
 | 
			
		||||
	// 	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<CDMovementAIComponentTable>();
 | 
			
		||||
		std::vector<CDMovementAIComponent> moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); });
 | 
			
		||||
	// int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI);
 | 
			
		||||
	// if (movementAIID > 0) {
 | 
			
		||||
	// 	CDMovementAIComponentTable* moveAITable = CDClientManager::Instance().GetTable<CDMovementAIComponentTable>();
 | 
			
		||||
	// 	std::vector<CDMovementAIComponent> moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); });
 | 
			
		||||
 | 
			
		||||
		if (moveAIComp.size() > 0) {
 | 
			
		||||
			MovementAIInfo moveInfo = MovementAIInfo();
 | 
			
		||||
	// 	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;
 | 
			
		||||
	// 		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<bool>(u"usewanderdb");
 | 
			
		||||
	// 		bool useWanderDB = GetVar<bool>(u"usewanderdb");
 | 
			
		||||
 | 
			
		||||
			if (!useWanderDB) {
 | 
			
		||||
				const auto wanderOverride = GetVarAs<float>(u"wanderRadius");
 | 
			
		||||
	// 		if (!useWanderDB) {
 | 
			
		||||
	// 			const auto wanderOverride = GetVarAs<float>(u"wanderRadius");
 | 
			
		||||
 | 
			
		||||
				if (wanderOverride != 0.0f) {
 | 
			
		||||
					moveInfo.wanderRadius = wanderOverride;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
	// 			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<BaseCombatAIComponent>()->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)));
 | 
			
		||||
	// 	}
 | 
			
		||||
	// } else if (petComponentId > 0 || combatAiId > 0 && GetComponent<BaseCombatAIComponent>()->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)));
 | 
			
		||||
	}
 | 
			
		||||
	// 	// 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);
 | 
			
		||||
	// 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<MovementAIComponent>();
 | 
			
		||||
			if (movementAIcomp){
 | 
			
		||||
				// TODO: set path in existing movementAIComp
 | 
			
		||||
			} else {
 | 
			
		||||
				// TODO: create movementAIcomp and set path
 | 
			
		||||
			}
 | 
			
		||||
		}*/
 | 
			
		||||
	} 
 | 
			
		||||
	// //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<MovementAIComponent>();
 | 
			
		||||
	// 		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);
 | 
			
		||||
@@ -572,70 +572,67 @@ Entity::Initialize() {
 | 
			
		||||
		// }
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
 | 
			
		||||
	if (proximityMonitorID > 0) {
 | 
			
		||||
		CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance().GetTable<CDProximityMonitorComponentTable>();
 | 
			
		||||
		std::vector<CDProximityMonitorComponent> proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); });
 | 
			
		||||
		if (proxCompData.size() > 0) {
 | 
			
		||||
			std::vector<std::string> 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));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
 | 
			
		||||
	// if (proximityMonitorID > 0) {
 | 
			
		||||
	// 	CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance().GetTable<CDProximityMonitorComponentTable>();
 | 
			
		||||
	// 	std::vector<CDProximityMonitorComponent> proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); });
 | 
			
		||||
	// 	if (proxCompData.size() > 0) {
 | 
			
		||||
	// 		std::vector<std::string> 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);
 | 
			
		||||
		}
 | 
			
		||||
		});
 | 
			
		||||
	// 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;
 | 
			
		||||
		}
 | 
			
		||||
	// 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;
 | 
			
		||||
		}
 | 
			
		||||
	// 	/* 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)
 | 
			
		||||
	// 		)
 | 
			
		||||
	// 	{
 | 
			
		||||
	// 		m_IsGhostingCandidate = true;
 | 
			
		||||
	// 	}
 | 
			
		||||
 | 
			
		||||
		if (GetLOT() == 6368) {
 | 
			
		||||
			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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// 	// Special case for collectibles in Ninjago
 | 
			
		||||
	// 	if (HasComponent(eReplicaComponentType::COLLECTIBLE) && Game::server->GetZoneID() == 2000) {
 | 
			
		||||
	// 		m_IsGhostingCandidate = true;
 | 
			
		||||
	// 	}
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
no_ghosting:
 | 
			
		||||
// no_ghosting:
 | 
			
		||||
 | 
			
		||||
	TriggerEvent(eTriggerEventType::CREATE, this);
 | 
			
		||||
	// TriggerEvent(eTriggerEventType::CREATE, this);
 | 
			
		||||
 | 
			
		||||
	if (m_Character) {
 | 
			
		||||
		auto controllablePhysicsComponent = GetComponent<ControllablePhysicsComponent>();
 | 
			
		||||
		auto levelComponent = GetComponent<LevelProgressionComponent>();
 | 
			
		||||
	// if (m_Character) {
 | 
			
		||||
	// 	auto controllablePhysicsComponent = GetComponent<ControllablePhysicsComponent>();
 | 
			
		||||
	// 	auto levelComponent = GetComponent<LevelProgressionComponent>();
 | 
			
		||||
 | 
			
		||||
		if (controllablePhysicsComponent && levelComponent) {
 | 
			
		||||
			controllablePhysicsComponent->SetSpeedMultiplier(levelComponent->GetSpeedBase() / 500.0f);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
	// 	if (controllablePhysicsComponent && levelComponent) {
 | 
			
		||||
	// 		controllablePhysicsComponent->SetSpeedMultiplier(levelComponent->GetSpeedBase() / 500.0f);
 | 
			
		||||
	// 	}
 | 
			
		||||
	// }
 | 
			
		||||
// }
 | 
			
		||||
 
 | 
			
		||||
@@ -37,8 +37,9 @@
 | 
			
		||||
#include "eGameActivity.h"
 | 
			
		||||
 | 
			
		||||
#include "CDComponentsRegistryTable.h"
 | 
			
		||||
#include "CDCurrencyTableTable.h"
 | 
			
		||||
 | 
			
		||||
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
 | 
			
		||||
DestroyableComponent::DestroyableComponent(Entity* parent, int32_t componentId) : Component(parent) {
 | 
			
		||||
	m_iArmor = 0;
 | 
			
		||||
	m_fMaxArmor = 0.0f;
 | 
			
		||||
	m_iImagination = 0;
 | 
			
		||||
@@ -62,6 +63,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
 | 
			
		||||
	m_MinCoins = 0;
 | 
			
		||||
	m_MaxCoins = 0;
 | 
			
		||||
	m_DamageReduction = 0;
 | 
			
		||||
	m_ComponentId = componentId;
 | 
			
		||||
 | 
			
		||||
	m_ImmuneToBasicAttackCount = 0;
 | 
			
		||||
	m_ImmuneToDamageOverTimeCount = 0;
 | 
			
		||||
@@ -73,49 +75,71 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
 | 
			
		||||
	m_ImmuneToQuickbuildInterruptCount = 0;
 | 
			
		||||
	m_ImmuneToPullToPointCount = 0;
 | 
			
		||||
}
 | 
			
		||||
void DestroyableComponent::Startup() {
 | 
			
		||||
 | 
			
		||||
DestroyableComponent::~DestroyableComponent() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DestroyableComponent::Reinitialize(LOT templateID) {
 | 
			
		||||
	CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
 | 
			
		||||
 | 
			
		||||
	int32_t buffComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::BUFF);
 | 
			
		||||
	int32_t collectibleComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::COLLECTIBLE);
 | 
			
		||||
	int32_t quickBuildComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::QUICK_BUILD);
 | 
			
		||||
 | 
			
		||||
	int32_t componentID = 0;
 | 
			
		||||
	if (collectibleComponentID > 0) componentID = collectibleComponentID;
 | 
			
		||||
	if (quickBuildComponentID > 0) componentID = quickBuildComponentID;
 | 
			
		||||
	if (buffComponentID > 0) componentID = buffComponentID;
 | 
			
		||||
 | 
			
		||||
	CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
 | 
			
		||||
	std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
 | 
			
		||||
 | 
			
		||||
	if (componentID > 0) {
 | 
			
		||||
		std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
 | 
			
		||||
 | 
			
		||||
		if (destCompData.size() > 0) {
 | 
			
		||||
			SetHealth(destCompData[0].life);
 | 
			
		||||
			SetImagination(destCompData[0].imagination);
 | 
			
		||||
			SetArmor(destCompData[0].armor);
 | 
			
		||||
 | 
			
		||||
			SetMaxHealth(destCompData[0].life);
 | 
			
		||||
			SetMaxImagination(destCompData[0].imagination);
 | 
			
		||||
			SetMaxArmor(destCompData[0].armor);
 | 
			
		||||
 | 
			
		||||
			SetIsSmashable(destCompData[0].isSmashable);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
void DestroyableComponent::LoadConfigData() {
 | 
			
		||||
	SetIsSmashable(m_ParentEntity->GetVarAs<int32_t>(u"is_smashable") != 0);
 | 
			
		||||
}
 | 
			
		||||
void DestroyableComponent::LoadTemplateData() {
 | 
			
		||||
	[[unlikely]] if (m_ParentEntity->IsPlayer()) return;
 | 
			
		||||
	auto* destroyableComponentTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
 | 
			
		||||
	auto destroyableDataLookup = destroyableComponentTable->Query([this](CDDestructibleComponent entry) { return (entry.id == this->m_ComponentId); });
 | 
			
		||||
	if (m_ComponentId == -1 || destroyableDataLookup.empty()) {
 | 
			
		||||
		SetHealth(1);
 | 
			
		||||
		SetImagination(0);
 | 
			
		||||
		SetArmor(0);
 | 
			
		||||
 | 
			
		||||
		SetMaxHealth(1);
 | 
			
		||||
		SetMaxImagination(0);
 | 
			
		||||
		SetMaxArmor(0);
 | 
			
		||||
 | 
			
		||||
		SetIsSmashable(true);
 | 
			
		||||
		AddFaction(-1);
 | 
			
		||||
		AddFaction(6); //Smashables
 | 
			
		||||
 | 
			
		||||
		// A race car has 60 imagination, other entities defaults to 0.
 | 
			
		||||
		SetImagination(m_ParentEntity->HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0);
 | 
			
		||||
		SetMaxImagination(m_ParentEntity->HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto destroyableData = destroyableDataLookup.at(0);
 | 
			
		||||
	if (m_ParentEntity->HasComponent(eReplicaComponentType::RACING_STATS)) {
 | 
			
		||||
		destroyableData.imagination = 60;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SetHealth(destroyableData.life);
 | 
			
		||||
	SetImagination(destroyableData.imagination);
 | 
			
		||||
	SetArmor(destroyableData.armor);
 | 
			
		||||
 | 
			
		||||
	SetMaxHealth(destroyableData.life);
 | 
			
		||||
	SetMaxImagination(destroyableData.imagination);
 | 
			
		||||
	SetMaxArmor(destroyableData.armor);
 | 
			
		||||
 | 
			
		||||
	SetIsSmashable(destroyableData.isSmashable);
 | 
			
		||||
 | 
			
		||||
	SetLootMatrixID(destroyableData.LootMatrixIndex);
 | 
			
		||||
 | 
			
		||||
	// Now get currency information
 | 
			
		||||
	uint32_t npcMinLevel = destroyableData.level;
 | 
			
		||||
	uint32_t currencyIndex = destroyableData.CurrencyIndex;
 | 
			
		||||
 | 
			
		||||
	auto* currencyTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>();
 | 
			
		||||
	auto currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); });
 | 
			
		||||
 | 
			
		||||
	if (currencyValues.size() > 0) {
 | 
			
		||||
		// Set the coins
 | 
			
		||||
		SetMinCoins(currencyValues.at(0).minvalue);
 | 
			
		||||
		SetMaxCoins(currencyValues.at(0).maxvalue);
 | 
			
		||||
	}
 | 
			
		||||
	AddFaction(destroyableData.faction);
 | 
			
		||||
	std::stringstream ss(destroyableData.factionList);
 | 
			
		||||
	std::string tokenStr;
 | 
			
		||||
 | 
			
		||||
	while (std::getline(ss, tokenStr, ',')) {
 | 
			
		||||
		int32_t factionToAdd = -2;
 | 
			
		||||
		if (!GeneralUtils::TryParse(tokenStr, factionToAdd) || factionToAdd == -2 || factionToAdd == destroyableData.faction) continue;
 | 
			
		||||
 | 
			
		||||
		AddFaction(factionToAdd);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -661,9 +685,9 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//check if hardcore mode is enabled
 | 
			
		||||
    if (EntityManager::Instance()->GetHardcoreMode()) {
 | 
			
		||||
	if (EntityManager::Instance()->GetHardcoreMode()) {
 | 
			
		||||
		DoHardcoreModeDrops(source);
 | 
			
		||||
    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Smash(source, eKillType::VIOLENT, u"", skillID);
 | 
			
		||||
}
 | 
			
		||||
@@ -823,16 +847,16 @@ void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DestroyableComponent::SetStatusImmunity(
 | 
			
		||||
		const eStateChangeType state,
 | 
			
		||||
		const bool bImmuneToBasicAttack,
 | 
			
		||||
		const bool bImmuneToDamageOverTime,
 | 
			
		||||
		const bool bImmuneToKnockback,
 | 
			
		||||
		const bool bImmuneToInterrupt,
 | 
			
		||||
		const bool bImmuneToSpeed,
 | 
			
		||||
		const bool bImmuneToImaginationGain,
 | 
			
		||||
		const bool bImmuneToImaginationLoss,
 | 
			
		||||
		const bool bImmuneToQuickbuildInterrupt,
 | 
			
		||||
		const bool bImmuneToPullToPoint) {
 | 
			
		||||
	const eStateChangeType state,
 | 
			
		||||
	const bool bImmuneToBasicAttack,
 | 
			
		||||
	const bool bImmuneToDamageOverTime,
 | 
			
		||||
	const bool bImmuneToKnockback,
 | 
			
		||||
	const bool bImmuneToInterrupt,
 | 
			
		||||
	const bool bImmuneToSpeed,
 | 
			
		||||
	const bool bImmuneToImaginationGain,
 | 
			
		||||
	const bool bImmuneToImaginationLoss,
 | 
			
		||||
	const bool bImmuneToQuickbuildInterrupt,
 | 
			
		||||
	const bool bImmuneToPullToPoint) {
 | 
			
		||||
 | 
			
		||||
	if (state == eStateChangeType::POP) {
 | 
			
		||||
		if (bImmuneToBasicAttack && m_ImmuneToBasicAttackCount > 0) 				m_ImmuneToBasicAttackCount -= 1;
 | 
			
		||||
@@ -845,7 +869,7 @@ void DestroyableComponent::SetStatusImmunity(
 | 
			
		||||
		if (bImmuneToQuickbuildInterrupt && m_ImmuneToQuickbuildInterruptCount > 0) m_ImmuneToQuickbuildInterruptCount -= 1;
 | 
			
		||||
		if (bImmuneToPullToPoint && m_ImmuneToPullToPointCount > 0) 				m_ImmuneToPullToPointCount -= 1;
 | 
			
		||||
 | 
			
		||||
	} else if (state == eStateChangeType::PUSH){
 | 
			
		||||
	} else if (state == eStateChangeType::PUSH) {
 | 
			
		||||
		if (bImmuneToBasicAttack) 			m_ImmuneToBasicAttackCount += 1;
 | 
			
		||||
		if (bImmuneToDamageOverTime) 		m_ImmuneToDamageOverTimeCount += 1;
 | 
			
		||||
		if (bImmuneToKnockback) 			m_ImmuneToKnockbackCount += 1;
 | 
			
		||||
@@ -972,7 +996,7 @@ void DestroyableComponent::AddOnHitCallback(const std::function<void(Entity*)>&
 | 
			
		||||
	m_OnHitCallbacks.push_back(callback);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
 | 
			
		||||
void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
 | 
			
		||||
	//check if this is a player:
 | 
			
		||||
	if (m_ParentEntity->IsPlayer()) {
 | 
			
		||||
		//remove hardcore_lose_uscore_on_death_percent from the player's uscore:
 | 
			
		||||
@@ -990,9 +1014,9 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
 | 
			
		||||
			if (inventory) {
 | 
			
		||||
				//get the items inventory:
 | 
			
		||||
				auto items = inventory->GetInventory(eInventoryType::ITEMS);
 | 
			
		||||
				if (items){
 | 
			
		||||
				if (items) {
 | 
			
		||||
					auto itemMap = items->GetItems();
 | 
			
		||||
					if (!itemMap.empty()){
 | 
			
		||||
					if (!itemMap.empty()) {
 | 
			
		||||
						for (const auto& item : itemMap) {
 | 
			
		||||
							//drop the item:
 | 
			
		||||
							if (!item.second) continue;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,19 +21,15 @@ class DestroyableComponent : public Component {
 | 
			
		||||
public:
 | 
			
		||||
	inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
 | 
			
		||||
 | 
			
		||||
	DestroyableComponent(Entity* parentEntity);
 | 
			
		||||
	~DestroyableComponent() override;
 | 
			
		||||
	DestroyableComponent(Entity* parentEntity, int32_t componentId = -1);
 | 
			
		||||
 | 
			
		||||
	void Startup() override;
 | 
			
		||||
	void LoadConfigData() override;
 | 
			
		||||
	void LoadTemplateData() override;
 | 
			
		||||
	void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
 | 
			
		||||
	void LoadFromXml(tinyxml2::XMLDocument* doc) override;
 | 
			
		||||
	void UpdateXml(tinyxml2::XMLDocument* doc) override;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Initializes the component using a different LOT
 | 
			
		||||
	 * @param templateID the ID to use for initialization
 | 
			
		||||
	 */
 | 
			
		||||
	void Reinitialize(LOT templateID);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Sets the health of this entity. Makes sure this is serialized on the next tick and if this is a character its
 | 
			
		||||
	 * stats will also update.
 | 
			
		||||
@@ -458,6 +454,8 @@ public:
 | 
			
		||||
	void DoHardcoreModeDrops(const LWOOBJID source);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	// The ID of this component
 | 
			
		||||
	int32_t m_ComponentId;
 | 
			
		||||
	/**
 | 
			
		||||
	 * Whether or not the health should be serialized
 | 
			
		||||
	 */
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,10 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
 | 
			
		||||
	uint32_t characterVersion;
 | 
			
		||||
	level->QueryAttribute("cv", &characterVersion);
 | 
			
		||||
	m_CharacterVersion = static_cast<eCharacterVersion>(characterVersion);
 | 
			
		||||
	auto* controllablePhysicsComponent = m_ParentEntity->GetComponent<ControllablePhysicsComponent>();
 | 
			
		||||
 | 
			
		||||
	if (!controllablePhysicsComponent) return;
 | 
			
		||||
	controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
 | 
			
		||||
@@ -68,7 +72,7 @@ void LevelProgressionComponent::HandleLevelUp() {
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
		case 9:
 | 
			
		||||
			SetSpeedBase(static_cast<float>(reward->value) );
 | 
			
		||||
			SetSpeedBase(static_cast<float>(reward->value));
 | 
			
		||||
			controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
 | 
			
		||||
			break;
 | 
			
		||||
		case 11:
 | 
			
		||||
@@ -82,7 +86,7 @@ void LevelProgressionComponent::HandleLevelUp() {
 | 
			
		||||
	if (rewardingItem) GameMessages::NotifyLevelRewards(m_ParentEntity->GetObjectID(), m_ParentEntity->GetSystemAddress(), m_Level, !rewardingItem);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LevelProgressionComponent::SetRetroactiveBaseSpeed(){
 | 
			
		||||
void LevelProgressionComponent::SetRetroactiveBaseSpeed() {
 | 
			
		||||
	if (m_Level >= 20) m_SpeedBase = 525.0f;
 | 
			
		||||
	auto* controllablePhysicsComponent = m_ParentEntity->GetComponent<ControllablePhysicsComponent>();
 | 
			
		||||
	if (controllablePhysicsComponent) controllablePhysicsComponent->SetSpeedMultiplier(m_SpeedBase / 500.0f);
 | 
			
		||||
 
 | 
			
		||||
@@ -13,22 +13,18 @@
 | 
			
		||||
 | 
			
		||||
#include "CDComponentsRegistryTable.h"
 | 
			
		||||
#include "CDPhysicsComponentTable.h"
 | 
			
		||||
#include "CDMovementAIComponentTable.h"
 | 
			
		||||
 | 
			
		||||
std::map<LOT, float> MovementAIComponent::m_PhysicsSpeedCache = {};
 | 
			
		||||
 | 
			
		||||
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
 | 
			
		||||
	m_Info = std::move(info);
 | 
			
		||||
MovementAIComponent::MovementAIComponent(Entity* parent, int32_t componentId) : Component(parent) {
 | 
			
		||||
	m_ComponentId = componentId;
 | 
			
		||||
	m_Done = true;
 | 
			
		||||
 | 
			
		||||
	m_BaseCombatAI = nullptr;
 | 
			
		||||
 | 
			
		||||
	m_BaseCombatAI = m_ParentEntity->GetComponent<BaseCombatAIComponent>();
 | 
			
		||||
 | 
			
		||||
	//Try and fix the insane values:
 | 
			
		||||
	if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius = m_Info.wanderRadius * 0.5f;
 | 
			
		||||
	if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
 | 
			
		||||
	if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed = m_Info.wanderSpeed * 0.5f;
 | 
			
		||||
 | 
			
		||||
	m_BaseSpeed = GetBaseSpeed(m_ParentEntity->GetLOT());
 | 
			
		||||
 | 
			
		||||
	m_NextWaypoint = GetCurrentPosition();
 | 
			
		||||
@@ -43,7 +39,48 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
 | 
			
		||||
	m_LockRotation = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MovementAIComponent::~MovementAIComponent() = default;
 | 
			
		||||
void MovementAIComponent::Startup() {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MovementAIComponent::LoadConfigData() {
 | 
			
		||||
	bool useWanderDB = m_ParentEntity->GetVar<bool>(u"usewanderdb");
 | 
			
		||||
 | 
			
		||||
	if (!useWanderDB) {
 | 
			
		||||
		const auto wanderOverride = m_ParentEntity->GetVarAs<float>(u"wanderRadius");
 | 
			
		||||
 | 
			
		||||
		if (wanderOverride != 0.0f) {
 | 
			
		||||
			m_Info.wanderRadius = wanderOverride;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MovementAIComponent::LoadTemplateData() {
 | 
			
		||||
	if (m_ComponentId == -1) return;
 | 
			
		||||
	auto* movementAiComponentTable = CDClientManager::Instance().GetTable<CDMovementAIComponentTable>();
 | 
			
		||||
	auto movementEntries = movementAiComponentTable->Query([this](CDMovementAIComponent entry) {return (entry.id == this->m_ComponentId); });
 | 
			
		||||
	if (movementEntries.empty()) return;
 | 
			
		||||
	auto movementEntry = movementEntries.at(0);
 | 
			
		||||
	MovementAIInfo moveInfo{};
 | 
			
		||||
 | 
			
		||||
	moveInfo.movementType = movementEntry.MovementType;
 | 
			
		||||
	moveInfo.wanderChance = movementEntry.WanderChance;
 | 
			
		||||
	moveInfo.wanderRadius = movementEntry.WanderRadius;
 | 
			
		||||
	moveInfo.wanderSpeed = movementEntry.WanderSpeed;
 | 
			
		||||
	moveInfo.wanderDelayMax = movementEntry.WanderDelayMax;
 | 
			
		||||
	moveInfo.wanderDelayMin = movementEntry.WanderDelayMin;
 | 
			
		||||
 | 
			
		||||
	this->SetMoveInfo(moveInfo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MovementAIComponent::SetMoveInfo(const MovementAIInfo& info) {
 | 
			
		||||
	m_Info = info;
 | 
			
		||||
 | 
			
		||||
	//Try and fix the insane values:
 | 
			
		||||
	if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f;
 | 
			
		||||
	if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
 | 
			
		||||
	if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MovementAIComponent::Update(const float deltaTime) {
 | 
			
		||||
	if (m_Interrupted) {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,10 @@ class BaseCombatAIComponent;
 | 
			
		||||
 * Information that describes the different variables used to make an entity move around
 | 
			
		||||
 */
 | 
			
		||||
struct MovementAIInfo {
 | 
			
		||||
 | 
			
		||||
	// copy assignment
 | 
			
		||||
	MovementAIInfo& operator=(const MovementAIInfo& other) = default;
 | 
			
		||||
	
 | 
			
		||||
	std::string movementType;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -59,8 +63,10 @@ class MovementAIComponent : public Component {
 | 
			
		||||
public:
 | 
			
		||||
	inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
 | 
			
		||||
 | 
			
		||||
	MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
 | 
			
		||||
	~MovementAIComponent() override;
 | 
			
		||||
	MovementAIComponent(Entity* parentEntity, int32_t componentId = -1);
 | 
			
		||||
	void Startup() override;
 | 
			
		||||
	void LoadTemplateData() override;
 | 
			
		||||
	void LoadConfigData() override;
 | 
			
		||||
 | 
			
		||||
	void Update(float deltaTime) override;
 | 
			
		||||
 | 
			
		||||
@@ -217,6 +223,7 @@ public:
 | 
			
		||||
	 */
 | 
			
		||||
	static float GetBaseSpeed(LOT lot);
 | 
			
		||||
 | 
			
		||||
	void SetMoveInfo(const MovementAIInfo& value);
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -326,6 +333,8 @@ private:
 | 
			
		||||
	 * Cache of all lots and their respective speeds
 | 
			
		||||
	 */
 | 
			
		||||
	static std::map<LOT, float> m_PhysicsSpeedCache;
 | 
			
		||||
 | 
			
		||||
	int32_t m_ComponentId;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // MOVEMENTAICOMPONENT_H
 | 
			
		||||
 
 | 
			
		||||
@@ -4,14 +4,13 @@
 | 
			
		||||
#include "ControllablePhysicsComponent.h"
 | 
			
		||||
#include "EntityManager.h"
 | 
			
		||||
#include "SimplePhysicsComponent.h"
 | 
			
		||||
#include "CDClientManager.h"
 | 
			
		||||
#include "CDProximityMonitorComponentTable.h"
 | 
			
		||||
 | 
			
		||||
const std::map<LWOOBJID, dpEntity*> ProximityMonitorComponent::m_EmptyObjectMap = {};
 | 
			
		||||
 | 
			
		||||
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) {
 | 
			
		||||
	if (radiusSmall != -1 && radiusLarge != -1) {
 | 
			
		||||
		SetProximityRadius(radiusSmall, "rocketSmall");
 | 
			
		||||
		SetProximityRadius(radiusLarge, "rocketLarge");
 | 
			
		||||
	}
 | 
			
		||||
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int32_t componentId) : Component(parent) {
 | 
			
		||||
	m_ComponentId = componentId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ProximityMonitorComponent::~ProximityMonitorComponent() {
 | 
			
		||||
@@ -24,6 +23,25 @@ ProximityMonitorComponent::~ProximityMonitorComponent() {
 | 
			
		||||
	m_ProximitiesData.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ProximityMonitorComponent::LoadTemplateData() {
 | 
			
		||||
	if (m_ComponentId == -1) return;
 | 
			
		||||
	auto* proxCompTable = CDClientManager::Instance().GetTable<CDProximityMonitorComponentTable>();
 | 
			
		||||
	auto proxCompData = proxCompTable->Query([this](CDProximityMonitorComponent entry) { return (entry.id == this->m_ComponentId); });
 | 
			
		||||
 | 
			
		||||
	if (!proxCompData.empty()) {
 | 
			
		||||
		float radiusSmall = -1.0f;
 | 
			
		||||
		float radiusLarge = -1.0f;
 | 
			
		||||
		auto proximitySplit = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
 | 
			
		||||
		if (proximitySplit.size() < 2) return;
 | 
			
		||||
		GeneralUtils::TryParse(proximitySplit.at(0), radiusSmall);
 | 
			
		||||
		GeneralUtils::TryParse(proximitySplit.at(1), radiusLarge);
 | 
			
		||||
		if (radiusSmall != -1.0f && radiusLarge != -1.0f) {
 | 
			
		||||
			SetProximityRadius(radiusSmall, "rocketSmall");
 | 
			
		||||
			SetProximityRadius(radiusLarge, "rocketLarge");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ProximityMonitorComponent::SetProximityRadius(float proxRadius, const std::string& name) {
 | 
			
		||||
	dpEntity* en = new dpEntity(m_ParentEntity->GetObjectID(), proxRadius);
 | 
			
		||||
	en->SetPosition(m_ParentEntity->GetPosition());
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,10 @@ class ProximityMonitorComponent : public Component {
 | 
			
		||||
public:
 | 
			
		||||
	inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
 | 
			
		||||
 | 
			
		||||
	ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
 | 
			
		||||
	ProximityMonitorComponent(Entity* parentEntity, int32_t componentId = -1);
 | 
			
		||||
	~ProximityMonitorComponent() override;
 | 
			
		||||
 | 
			
		||||
	void LoadTemplateData() override;
 | 
			
		||||
	void Update(float deltaTime) override;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
@@ -71,6 +73,8 @@ private:
 | 
			
		||||
	 * Default value for the proximity data
 | 
			
		||||
	 */
 | 
			
		||||
	static const std::map<LWOOBJID, dpEntity*> m_EmptyObjectMap;
 | 
			
		||||
 | 
			
		||||
	int32_t m_ComponentId = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // PROXIMITYMONITORCOMPONENT_H
 | 
			
		||||
 
 | 
			
		||||
@@ -12,5 +12,6 @@ void AgStromlingProperty::OnStartup(Entity* self) {
 | 
			
		||||
		4
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	self->AddComponent<MovementAIComponent>(movementInfo);
 | 
			
		||||
	auto* movementAiComponent = self->AddComponent<MovementAIComponent>(0U);
 | 
			
		||||
	if (movementAiComponent) movementAiComponent->SetMoveInfo(movementInfo);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -287,11 +287,11 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
 | 
			
		||||
			auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self);
 | 
			
		||||
			EntityManager::Instance()->ConstructEntity(enemy);
 | 
			
		||||
 | 
			
		||||
			auto movementAI = enemy->AddComponent<MovementAIComponent, MovementAIInfo>({});
 | 
			
		||||
 | 
			
		||||
			movementAI->SetSpeed(toSpawn.initialSpeed);
 | 
			
		||||
			movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
 | 
			
		||||
			movementAI->SetHaltDistance(0.0f);
 | 
			
		||||
			auto movementAiComponent = enemy->AddComponent<MovementAIComponent>(0U);
 | 
			
		||||
	
 | 
			
		||||
			movementAiComponent->SetSpeed(toSpawn.initialSpeed);
 | 
			
		||||
			movementAiComponent->SetCurrentSpeed(toSpawn.initialSpeed);
 | 
			
		||||
			movementAiComponent->SetHaltDistance(0.0f);
 | 
			
		||||
 | 
			
		||||
			std::vector<NiPoint3> pathWaypoints;
 | 
			
		||||
 | 
			
		||||
@@ -303,7 +303,7 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
 | 
			
		||||
				std::reverse(pathWaypoints.begin(), pathWaypoints.end());
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			movementAI->SetPath(pathWaypoints);
 | 
			
		||||
			movementAiComponent->SetPath(pathWaypoints);
 | 
			
		||||
 | 
			
		||||
			enemy->AddDieCallback([this, self, enemy, name]() {
 | 
			
		||||
				RegisterHit(self, enemy, name);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user