Fully re-implemented initialize

This commit is contained in:
David Markowitz 2023-06-12 01:29:43 -07:00
parent fc719cbb0a
commit 36c44ecc83
13 changed files with 444 additions and 260 deletions

View File

@ -56,7 +56,10 @@ const uint32_t LWOCLONEID_INVALID = -1; //!< Invalid LWOCLONEID
const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID const uint16_t LWOINSTANCEID_INVALID = -1; //!< Invalid LWOINSTANCEID
const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID const uint16_t LWOMAPID_INVALID = -1; //!< Invalid LWOMAPID
const uint64_t LWOZONEID_INVALID = 0; //!< Invalid LWOZONEID 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; const float PI = 3.14159f;

View File

@ -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() { void Entity::Initialize() {
// A few edge cases to tackle first // A few edge cases to tackle first
const auto triggerInfo = GetVarAsString(u"trigger_id"); const auto triggerInfo = GetVarAsString(u"trigger_id");
@ -222,11 +245,11 @@ void Entity::Initialize() {
TemplateComponents components = componentsRegistry->GetTemplateComponents(m_TemplateID); TemplateComponents components = componentsRegistry->GetTemplateComponents(m_TemplateID);
ApplyComponentWhitelist(components); ApplyComponentWhitelist(components);
ApplyComponentBlacklist(components); ApplyComponentBlacklist(components);
AddPathComponent(components);
// Brick-by-Brick models use custom physics depending on _something_ but the client uses 4246 as the simple // 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 // 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. // 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) { for (const auto& [componentTemplate, componentId] : components) {
switch (componentTemplate) { switch (componentTemplate) {
case eReplicaComponentType::CONTROLLABLE_PHYSICS: case eReplicaComponentType::CONTROLLABLE_PHYSICS:
@ -247,7 +270,7 @@ void Entity::Initialize() {
break; break;
case eReplicaComponentType::SCRIPT: { case eReplicaComponentType::SCRIPT: {
AddComponent<ScriptComponent>(ScriptComponent::GetScriptName(this, componentId)); AddComponent<ScriptComponent>(ScriptComponent::GetScriptName(this, componentId));
if (m_TemplateID == ZONE_CONTROL_LOT) { if (m_TemplateID == LOT_ZONE_CONTROL) {
const auto zoneScript = ScriptComponent::GetZoneScriptName(componentId); const auto zoneScript = ScriptComponent::GetZoneScriptName(componentId);
if (!zoneScript.empty()) AddComponent<ScriptComponent>(zoneScript); if (!zoneScript.empty()) AddComponent<ScriptComponent>(zoneScript);
} }
@ -257,7 +280,7 @@ void Entity::Initialize() {
AddComponent<BouncerComponent>(); AddComponent<BouncerComponent>();
break; break;
case eReplicaComponentType::DESTROYABLE: case eReplicaComponentType::DESTROYABLE:
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(); if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(componentId);
break; break;
case eReplicaComponentType::SKILL: case eReplicaComponentType::SKILL:
AddComponent<SkillComponent>(); AddComponent<SkillComponent>();
@ -279,13 +302,14 @@ void Entity::Initialize() {
break; break;
case eReplicaComponentType::COLLECTIBLE: case eReplicaComponentType::COLLECTIBLE:
AddComponent<CollectibleComponent>(); AddComponent<CollectibleComponent>();
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(); if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(componentId);
break; break;
case eReplicaComponentType::MOVING_PLATFORM: case eReplicaComponentType::MOVING_PLATFORM:
AddComponent<MovingPlatformComponent>(GetVarAsString(u"attached_path")); AddComponent<MovingPlatformComponent>(GetVarAsString(u"attached_path"));
break; break;
case eReplicaComponentType::PET: case eReplicaComponentType::PET:
AddComponent<PetComponent>(componentId); AddComponent<PetComponent>(componentId);
AddComponent<MovementAIComponent>();
break; break;
case eReplicaComponentType::HAVOK_VEHICLE_PHYSICS: { case eReplicaComponentType::HAVOK_VEHICLE_PHYSICS: {
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>(); auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>();
@ -295,6 +319,9 @@ void Entity::Initialize() {
} }
break; break;
} }
case eReplicaComponentType::MOVEMENT_AI:
AddComponent<MovementAIComponent>();
break;
case eReplicaComponentType::PROPERTY: case eReplicaComponentType::PROPERTY:
AddComponent<PropertyComponent>(); AddComponent<PropertyComponent>();
break; break;
@ -309,7 +336,7 @@ void Entity::Initialize() {
case eReplicaComponentType::MODEL_BEHAVIOR: { case eReplicaComponentType::MODEL_BEHAVIOR: {
AddComponent<ModelBehaviorComponent>(); AddComponent<ModelBehaviorComponent>();
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) { if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
auto* destroyableComponent = AddComponent<DestroyableComponent>(); auto* destroyableComponent = AddComponent<DestroyableComponent>(componentId);
if (destroyableComponent) { if (destroyableComponent) {
destroyableComponent->SetHealth(1); destroyableComponent->SetHealth(1);
destroyableComponent->SetMaxHealth(1.0f); destroyableComponent->SetMaxHealth(1.0f);
@ -327,7 +354,7 @@ void Entity::Initialize() {
break; break;
case eReplicaComponentType::QUICK_BUILD: case eReplicaComponentType::QUICK_BUILD:
AddComponent<QuickBuildComponent>(componentId); AddComponent<QuickBuildComponent>(componentId);
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(); if (!HasComponent(eReplicaComponentType::DESTROYABLE)) AddComponent<DestroyableComponent>(componentId);
break; break;
case eReplicaComponentType::SWITCH: case eReplicaComponentType::SWITCH:
AddComponent<SwitchComponent>(); AddComponent<SwitchComponent>();
@ -335,9 +362,22 @@ void Entity::Initialize() {
case eReplicaComponentType::MINIGAME_CONTROL: case eReplicaComponentType::MINIGAME_CONTROL:
AddComponent<MinigameControlComponent>(); AddComponent<MinigameControlComponent>();
break; break;
case eReplicaComponentType::BASE_COMBAT_AI: case eReplicaComponentType::BASE_COMBAT_AI: {
AddComponent<BaseCombatAIComponent>(componentId); 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; break;
}
case eReplicaComponentType::MODULE_ASSEMBLY: case eReplicaComponentType::MODULE_ASSEMBLY:
AddComponent<ModuleAssemblyComponent>(); AddComponent<ModuleAssemblyComponent>();
break; break;
@ -362,6 +402,9 @@ void Entity::Initialize() {
case eReplicaComponentType::SOUND_TRIGGER: case eReplicaComponentType::SOUND_TRIGGER:
AddComponent<SoundTriggerComponent>(); AddComponent<SoundTriggerComponent>();
break; break;
case eReplicaComponentType::PROXIMITY_MONITOR:
AddComponent<ProximityMonitorComponent>();
break;
case eReplicaComponentType::MULTI_ZONE_ENTRANCE: case eReplicaComponentType::MULTI_ZONE_ENTRANCE:
AddComponent<MultiZoneEntranceComponent>(); AddComponent<MultiZoneEntranceComponent>();
break; break;
@ -390,7 +433,6 @@ void Entity::Initialize() {
case eReplicaComponentType::PLATFORM_BOUNDARY: case eReplicaComponentType::PLATFORM_BOUNDARY:
case eReplicaComponentType::MODULE: case eReplicaComponentType::MODULE:
case eReplicaComponentType::JETPACKPAD: case eReplicaComponentType::JETPACKPAD:
case eReplicaComponentType::MOVEMENT_AI:
case eReplicaComponentType::EXHIBIT: case eReplicaComponentType::EXHIBIT:
case eReplicaComponentType::OVERHEAD_ICON: case eReplicaComponentType::OVERHEAD_ICON:
case eReplicaComponentType::PET_CONTROL: case eReplicaComponentType::PET_CONTROL:
@ -419,7 +461,6 @@ void Entity::Initialize() {
case eReplicaComponentType::DROPPED_LOOT: case eReplicaComponentType::DROPPED_LOOT:
case eReplicaComponentType::FACTION_TRIGGER: case eReplicaComponentType::FACTION_TRIGGER:
case eReplicaComponentType::BBB: case eReplicaComponentType::BBB:
case eReplicaComponentType::PROXIMITY_MONITOR:
case eReplicaComponentType::RACING_SOUND_TRIGGER: case eReplicaComponentType::RACING_SOUND_TRIGGER:
case eReplicaComponentType::CHAT_BUBBLE: case eReplicaComponentType::CHAT_BUBBLE:
case eReplicaComponentType::FRIENDS_LIST: 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) { std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
component.second->LoadTemplateData(); component.second->LoadTemplateData();
}); });
@ -471,11 +519,47 @@ void Entity::Initialize() {
std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) { std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
component.second->Startup(); component.second->Startup();
}); });
if (!IsPlayer()) return; // No save data to load for non players // No save data to load for non players
if (!IsPlayer()) std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
std::for_each(m_Components.begin(), m_Components.end(), [this](auto& component) {
component.second->LoadFromXml(m_Character->GetXMLDoc()); 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 { bool Entity::operator==(const Entity& other) const {

View File

@ -66,6 +66,11 @@ public:
// For adding and removing components based on LDF keys // For adding and removing components based on LDF keys
void ApplyComponentConfig(TemplateComponents& components) const; 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(); virtual void Initialize();
bool operator==(const Entity& other) const; bool operator==(const Entity& other) const;

View File

@ -1,4 +1,4 @@
Entity::Initialize() { // Entity::Initialize() {
/** /**
* Setup trigger * Setup trigger
*/ */
@ -204,75 +204,75 @@ Entity::Initialize() {
// if (destroyableComponentID > 0 || collectibleComponentID > 0) { // if (destroyableComponentID > 0 || collectibleComponentID > 0) {
// DestroyableComponent* comp = new DestroyableComponent(this); // DestroyableComponent* comp = new DestroyableComponent(this);
if (m_Character) { // if (m_Character) {
comp->LoadFromXml(m_Character->GetXMLDoc()); // comp->LoadFromXml(m_Character->GetXMLDoc());
} else { // } else {
if (componentID > 0) { // if (componentID > 0) {
// std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); }); // // std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
if (destCompData.size() > 0) { // if (destCompData.size() > 0) {
if (HasComponent(eReplicaComponentType::RACING_STATS)) { // if (HasComponent(eReplicaComponentType::RACING_STATS)) {
destCompData[0].imagination = 60; // destCompData[0].imagination = 60;
} // }
comp->SetHealth(destCompData[0].life); // comp->SetHealth(destCompData[0].life);
comp->SetImagination(destCompData[0].imagination); // comp->SetImagination(destCompData[0].imagination);
comp->SetArmor(destCompData[0].armor); // comp->SetArmor(destCompData[0].armor);
comp->SetMaxHealth(destCompData[0].life); // comp->SetMaxHealth(destCompData[0].life);
comp->SetMaxImagination(destCompData[0].imagination); // comp->SetMaxImagination(destCompData[0].imagination);
comp->SetMaxArmor(destCompData[0].armor); // 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 // // Now get currency information
uint32_t npcMinLevel = destCompData[0].level; // uint32_t npcMinLevel = destCompData[0].level;
uint32_t currencyIndex = destCompData[0].CurrencyIndex; // uint32_t currencyIndex = destCompData[0].CurrencyIndex;
CDCurrencyTableTable* currencyTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>(); // CDCurrencyTableTable* currencyTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>();
std::vector<CDCurrencyTable> currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); }); // std::vector<CDCurrencyTable> currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); });
if (currencyValues.size() > 0) { // if (currencyValues.size() > 0) {
// Set the coins // // Set the coins
comp->SetMinCoins(currencyValues[0].minvalue); // comp->SetMinCoins(currencyValues[0].minvalue);
comp->SetMaxCoins(currencyValues[0].maxvalue); // comp->SetMaxCoins(currencyValues[0].maxvalue);
} // }
// extraInfo overrides // // extraInfo overrides
comp->SetIsSmashable(GetVarAs<int32_t>(u"is_smashable") != 0); // // comp->SetIsSmashable(GetVarAs<int32_t>(u"is_smashable") != 0);
} // }
} else { // } else {
comp->SetHealth(1); // comp->SetHealth(1);
comp->SetArmor(0); // comp->SetArmor(0);
comp->SetMaxHealth(1); // comp->SetMaxHealth(1);
comp->SetMaxArmor(0); // comp->SetMaxArmor(0);
comp->SetIsSmashable(true); // comp->SetIsSmashable(true);
comp->AddFaction(-1); // comp->AddFaction(-1);
comp->AddFaction(6); //Smashables // comp->AddFaction(6); //Smashables
// A race car has 60 imagination, other entities defaults to 0. // // A race car has 60 imagination, other entities defaults to 0.
comp->SetImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0); // comp->SetImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0);
comp->SetMaxImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0); // comp->SetMaxImagination(HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0);
} // }
} // }
if (destCompData.size() > 0) { // if (destCompData.size() > 0) {
comp->AddFaction(destCompData[0].faction); // comp->AddFaction(destCompData[0].faction);
std::stringstream ss(destCompData[0].factionList); // std::stringstream ss(destCompData[0].factionList);
std::string token; // std::string token;
while (std::getline(ss, token, ',')) { // while (std::getline(ss, token, ',')) {
if (std::stoi(token) == destCompData[0].faction) continue; // if (std::stoi(token) == destCompData[0].faction) continue;
if (token != "") { // if (token != "") {
comp->AddFaction(std::stoi(token)); // comp->AddFaction(std::stoi(token));
} // }
} // }
} // }
// m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp)); // 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))); // m_Components.insert(std::make_pair(eReplicaComponentType::RAIL_ACTIVATOR, new RailActivatorComponent(this, railComponentID)));
// } // }
int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI); // int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI);
if (movementAIID > 0) { // if (movementAIID > 0) {
CDMovementAIComponentTable* moveAITable = CDClientManager::Instance().GetTable<CDMovementAIComponentTable>(); // CDMovementAIComponentTable* moveAITable = CDClientManager::Instance().GetTable<CDMovementAIComponentTable>();
std::vector<CDMovementAIComponent> moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); }); // std::vector<CDMovementAIComponent> moveAIComp = moveAITable->Query([=](CDMovementAIComponent entry) {return (entry.id == movementAIID); });
if (moveAIComp.size() > 0) { // if (moveAIComp.size() > 0) {
MovementAIInfo moveInfo = MovementAIInfo(); // MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = moveAIComp[0].MovementType; // moveInfo.movementType = moveAIComp[0].MovementType;
moveInfo.wanderChance = moveAIComp[0].WanderChance; // moveInfo.wanderChance = moveAIComp[0].WanderChance;
moveInfo.wanderRadius = moveAIComp[0].WanderRadius; // moveInfo.wanderRadius = moveAIComp[0].WanderRadius;
moveInfo.wanderSpeed = moveAIComp[0].WanderSpeed; // moveInfo.wanderSpeed = moveAIComp[0].WanderSpeed;
moveInfo.wanderDelayMax = moveAIComp[0].WanderDelayMax; // moveInfo.wanderDelayMax = moveAIComp[0].WanderDelayMax;
moveInfo.wanderDelayMin = moveAIComp[0].WanderDelayMin; // moveInfo.wanderDelayMin = moveAIComp[0].WanderDelayMin;
bool useWanderDB = GetVar<bool>(u"usewanderdb"); // bool useWanderDB = GetVar<bool>(u"usewanderdb");
if (!useWanderDB) { // if (!useWanderDB) {
const auto wanderOverride = GetVarAs<float>(u"wanderRadius"); // const auto wanderOverride = GetVarAs<float>(u"wanderRadius");
if (wanderOverride != 0.0f) { // if (wanderOverride != 0.0f) {
moveInfo.wanderRadius = wanderOverride; // moveInfo.wanderRadius = wanderOverride;
} // }
} // }
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)));
} // }
} else if (petComponentId > 0 || combatAiId > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) { // } else if (petComponentId > 0 || combatAiId > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) {
MovementAIInfo moveInfo = MovementAIInfo(); // MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = ""; // moveInfo.movementType = "";
moveInfo.wanderChance = 0; // moveInfo.wanderChance = 0;
moveInfo.wanderRadius = 16; // moveInfo.wanderRadius = 16;
moveInfo.wanderSpeed = 2.5f; // moveInfo.wanderSpeed = 2.5f;
moveInfo.wanderDelayMax = 5; // moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2; // 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"); // std::string pathName = GetVarAsString(u"attached_path");
const Path* path = dZoneManager::Instance()->GetZone()->GetPath(pathName); // 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: // //Check to see if we have an attached path and add the appropiate component to handle it:
if (path){ // if (path){
// if we have a moving platform path, then we need a moving platform component // // if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) { // if (path->pathType == PathType::MovingPlatform) {
MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName); // MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName);
m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat)); // m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat));
// else if we are a movement path // // else if we are a movement path
} /*else if (path->pathType == PathType::Movement) { // } /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent<MovementAIComponent>(); // auto movementAIcomp = GetComponent<MovementAIComponent>();
if (movementAIcomp){ // if (movementAIcomp){
// TODO: set path in existing movementAIComp // // TODO: set path in existing movementAIComp
} else { // } else {
// TODO: create movementAIcomp and set path // // TODO: create movementAIcomp and set path
} // }
}*/ // }*/
} // }
// else { // else {
// else we still need to setup moving platform if it has a moving platform comp but no path // 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); // 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); // int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
if (proximityMonitorID > 0) { // if (proximityMonitorID > 0) {
CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance().GetTable<CDProximityMonitorComponentTable>(); // CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance().GetTable<CDProximityMonitorComponentTable>();
std::vector<CDProximityMonitorComponent> proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); }); // std::vector<CDProximityMonitorComponent> proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); });
if (proxCompData.size() > 0) { // if (proxCompData.size() > 0) {
std::vector<std::string> proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ','); // std::vector<std::string> proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
ProximityMonitorComponent* comp = new ProximityMonitorComponent(this, std::stoi(proximityStr[0]), std::stoi(proximityStr[1])); // ProximityMonitorComponent* comp = new ProximityMonitorComponent(this, std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
m_Components.insert(std::make_pair(eReplicaComponentType::PROXIMITY_MONITOR, comp)); // 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 // Hacky way to trigger these when the object has had a chance to get constructed
AddCallbackTimer(0, [this]() { // AddCallbackTimer(0, [this]() {
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { // for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
script->OnStartup(this); // script->OnStartup(this);
} // }
}); // });
if (!m_Character && EntityManager::Instance()->GetGhostingEnabled()) { // if (!m_Character && EntityManager::Instance()->GetGhostingEnabled()) {
// Don't ghost what is likely large scene elements // // 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))) { // if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) {
goto no_ghosting; // goto no_ghosting;
} // }
/* Filter for ghosting candidates. // /* Filter for ghosting candidates.
* // *
* Don't ghost moving platforms, until we've got proper syncing for those. // * 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 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. // * Don't ghost property related objects, as the client expects those to always be loaded.
*/ // */
if ( // if (
!EntityManager::IsExcludedFromGhosting(GetLOT()) && // !EntityManager::IsExcludedFromGhosting(GetLOT()) &&
!HasComponent(eReplicaComponentType::SCRIPTED_ACTIVITY) && // !HasComponent(eReplicaComponentType::SCRIPTED_ACTIVITY) &&
!HasComponent(eReplicaComponentType::MOVING_PLATFORM) && // !HasComponent(eReplicaComponentType::MOVING_PLATFORM) &&
!HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) && // !HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) &&
!HasComponent(eReplicaComponentType::PROPERTY) && // !HasComponent(eReplicaComponentType::PROPERTY) &&
!HasComponent(eReplicaComponentType::RACING_CONTROL) && // !HasComponent(eReplicaComponentType::RACING_CONTROL) &&
!HasComponent(eReplicaComponentType::VEHICLE_PHYSICS) // !HasComponent(eReplicaComponentType::VEHICLE_PHYSICS)
) // )
//if (HasComponent(eReplicaComponentType::BASE_COMBAT_AI)) // {
{ // m_IsGhostingCandidate = true;
m_IsGhostingCandidate = true; // }
}
if (GetLOT() == 6368) { // if (GetLOT() == 6368) m_IsGhostingCandidate = true;
m_IsGhostingCandidate = true;
}
// Special case for collectibles in Ninjago // // Special case for collectibles in Ninjago
if (HasComponent(eReplicaComponentType::COLLECTIBLE) && Game::server->GetZoneID() == 2000) { // if (HasComponent(eReplicaComponentType::COLLECTIBLE) && Game::server->GetZoneID() == 2000) {
m_IsGhostingCandidate = true; // m_IsGhostingCandidate = true;
} // }
} // }
no_ghosting: // no_ghosting:
TriggerEvent(eTriggerEventType::CREATE, this); // TriggerEvent(eTriggerEventType::CREATE, this);
if (m_Character) { // if (m_Character) {
auto controllablePhysicsComponent = GetComponent<ControllablePhysicsComponent>(); // auto controllablePhysicsComponent = GetComponent<ControllablePhysicsComponent>();
auto levelComponent = GetComponent<LevelProgressionComponent>(); // auto levelComponent = GetComponent<LevelProgressionComponent>();
if (controllablePhysicsComponent && levelComponent) { // if (controllablePhysicsComponent && levelComponent) {
controllablePhysicsComponent->SetSpeedMultiplier(levelComponent->GetSpeedBase() / 500.0f); // controllablePhysicsComponent->SetSpeedMultiplier(levelComponent->GetSpeedBase() / 500.0f);
} // }
} // }
} // }

View File

@ -37,8 +37,9 @@
#include "eGameActivity.h" #include "eGameActivity.h"
#include "CDComponentsRegistryTable.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_iArmor = 0;
m_fMaxArmor = 0.0f; m_fMaxArmor = 0.0f;
m_iImagination = 0; m_iImagination = 0;
@ -62,6 +63,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
m_MinCoins = 0; m_MinCoins = 0;
m_MaxCoins = 0; m_MaxCoins = 0;
m_DamageReduction = 0; m_DamageReduction = 0;
m_ComponentId = componentId;
m_ImmuneToBasicAttackCount = 0; m_ImmuneToBasicAttackCount = 0;
m_ImmuneToDamageOverTimeCount = 0; m_ImmuneToDamageOverTimeCount = 0;
@ -73,49 +75,71 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
m_ImmuneToQuickbuildInterruptCount = 0; m_ImmuneToQuickbuildInterruptCount = 0;
m_ImmuneToPullToPointCount = 0; m_ImmuneToPullToPointCount = 0;
} }
void DestroyableComponent::Startup() {
DestroyableComponent::~DestroyableComponent() {
} }
void DestroyableComponent::LoadConfigData() {
void DestroyableComponent::Reinitialize(LOT templateID) { SetIsSmashable(m_ParentEntity->GetVarAs<int32_t>(u"is_smashable") != 0);
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::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); SetHealth(1);
SetImagination(0);
SetArmor(0); SetArmor(0);
SetMaxHealth(1); SetMaxHealth(1);
SetMaxImagination(0);
SetMaxArmor(0); SetMaxArmor(0);
SetIsSmashable(true); 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);
} }
} }

View File

@ -21,19 +21,15 @@ class DestroyableComponent : public Component {
public: public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE; inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
DestroyableComponent(Entity* parentEntity); DestroyableComponent(Entity* parentEntity, int32_t componentId = -1);
~DestroyableComponent() override;
void Startup() override;
void LoadConfigData() override;
void LoadTemplateData() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
void LoadFromXml(tinyxml2::XMLDocument* doc) override; void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(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 * 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. * stats will also update.
@ -458,6 +454,8 @@ public:
void DoHardcoreModeDrops(const LWOOBJID source); void DoHardcoreModeDrops(const LWOOBJID source);
private: private:
// The ID of this component
int32_t m_ComponentId;
/** /**
* Whether or not the health should be serialized * Whether or not the health should be serialized
*/ */

View File

@ -35,6 +35,10 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
uint32_t characterVersion; uint32_t characterVersion;
level->QueryAttribute("cv", &characterVersion); level->QueryAttribute("cv", &characterVersion);
m_CharacterVersion = static_cast<eCharacterVersion>(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) { void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {

View File

@ -13,22 +13,18 @@
#include "CDComponentsRegistryTable.h" #include "CDComponentsRegistryTable.h"
#include "CDPhysicsComponentTable.h" #include "CDPhysicsComponentTable.h"
#include "CDMovementAIComponentTable.h"
std::map<LOT, float> MovementAIComponent::m_PhysicsSpeedCache = {}; std::map<LOT, float> MovementAIComponent::m_PhysicsSpeedCache = {};
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) { MovementAIComponent::MovementAIComponent(Entity* parent, int32_t componentId) : Component(parent) {
m_Info = std::move(info); m_ComponentId = componentId;
m_Done = true; m_Done = true;
m_BaseCombatAI = nullptr; m_BaseCombatAI = nullptr;
m_BaseCombatAI = m_ParentEntity->GetComponent<BaseCombatAIComponent>(); 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_BaseSpeed = GetBaseSpeed(m_ParentEntity->GetLOT());
m_NextWaypoint = GetCurrentPosition(); m_NextWaypoint = GetCurrentPosition();
@ -43,7 +39,48 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
m_LockRotation = false; 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) { void MovementAIComponent::Update(const float deltaTime) {
if (m_Interrupted) { if (m_Interrupted) {

View File

@ -23,6 +23,10 @@ class BaseCombatAIComponent;
* Information that describes the different variables used to make an entity move around * Information that describes the different variables used to make an entity move around
*/ */
struct MovementAIInfo { struct MovementAIInfo {
// copy assignment
MovementAIInfo& operator=(const MovementAIInfo& other) = default;
std::string movementType; std::string movementType;
/** /**
@ -59,8 +63,10 @@ class MovementAIComponent : public Component {
public: public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI; inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
MovementAIComponent(Entity* parentEntity, MovementAIInfo info); MovementAIComponent(Entity* parentEntity, int32_t componentId = -1);
~MovementAIComponent() override; void Startup() override;
void LoadTemplateData() override;
void LoadConfigData() override;
void Update(float deltaTime) override; void Update(float deltaTime) override;
@ -217,6 +223,7 @@ public:
*/ */
static float GetBaseSpeed(LOT lot); static float GetBaseSpeed(LOT lot);
void SetMoveInfo(const MovementAIInfo& value);
private: private:
/** /**
@ -326,6 +333,8 @@ private:
* Cache of all lots and their respective speeds * Cache of all lots and their respective speeds
*/ */
static std::map<LOT, float> m_PhysicsSpeedCache; static std::map<LOT, float> m_PhysicsSpeedCache;
int32_t m_ComponentId;
}; };
#endif // MOVEMENTAICOMPONENT_H #endif // MOVEMENTAICOMPONENT_H

View File

@ -4,14 +4,13 @@
#include "ControllablePhysicsComponent.h" #include "ControllablePhysicsComponent.h"
#include "EntityManager.h" #include "EntityManager.h"
#include "SimplePhysicsComponent.h" #include "SimplePhysicsComponent.h"
#include "CDClientManager.h"
#include "CDProximityMonitorComponentTable.h"
const std::map<LWOOBJID, dpEntity*> ProximityMonitorComponent::m_EmptyObjectMap = {}; const std::map<LWOOBJID, dpEntity*> ProximityMonitorComponent::m_EmptyObjectMap = {};
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) { ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int32_t componentId) : Component(parent) {
if (radiusSmall != -1 && radiusLarge != -1) { m_ComponentId = componentId;
SetProximityRadius(radiusSmall, "rocketSmall");
SetProximityRadius(radiusLarge, "rocketLarge");
}
} }
ProximityMonitorComponent::~ProximityMonitorComponent() { ProximityMonitorComponent::~ProximityMonitorComponent() {
@ -24,6 +23,25 @@ ProximityMonitorComponent::~ProximityMonitorComponent() {
m_ProximitiesData.clear(); 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) { void ProximityMonitorComponent::SetProximityRadius(float proxRadius, const std::string& name) {
dpEntity* en = new dpEntity(m_ParentEntity->GetObjectID(), proxRadius); dpEntity* en = new dpEntity(m_ParentEntity->GetObjectID(), proxRadius);
en->SetPosition(m_ParentEntity->GetPosition()); en->SetPosition(m_ParentEntity->GetPosition());

View File

@ -21,8 +21,10 @@ class ProximityMonitorComponent : public Component {
public: public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR; 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; ~ProximityMonitorComponent() override;
void LoadTemplateData() override;
void Update(float deltaTime) override; void Update(float deltaTime) override;
/** /**
@ -71,6 +73,8 @@ private:
* Default value for the proximity data * Default value for the proximity data
*/ */
static const std::map<LWOOBJID, dpEntity*> m_EmptyObjectMap; static const std::map<LWOOBJID, dpEntity*> m_EmptyObjectMap;
int32_t m_ComponentId = 0;
}; };
#endif // PROXIMITYMONITORCOMPONENT_H #endif // PROXIMITYMONITORCOMPONENT_H

View File

@ -12,5 +12,6 @@ void AgStromlingProperty::OnStartup(Entity* self) {
4 4
}; };
self->AddComponent<MovementAIComponent>(movementInfo); auto* movementAiComponent = self->AddComponent<MovementAIComponent>(0U);
if (movementAiComponent) movementAiComponent->SetMoveInfo(movementInfo);
} }

View File

@ -287,11 +287,11 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self); auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self);
EntityManager::Instance()->ConstructEntity(enemy); EntityManager::Instance()->ConstructEntity(enemy);
auto movementAI = enemy->AddComponent<MovementAIComponent, MovementAIInfo>({}); auto movementAiComponent = enemy->AddComponent<MovementAIComponent>(0U);
movementAI->SetSpeed(toSpawn.initialSpeed); movementAiComponent->SetSpeed(toSpawn.initialSpeed);
movementAI->SetCurrentSpeed(toSpawn.initialSpeed); movementAiComponent->SetCurrentSpeed(toSpawn.initialSpeed);
movementAI->SetHaltDistance(0.0f); movementAiComponent->SetHaltDistance(0.0f);
std::vector<NiPoint3> pathWaypoints; std::vector<NiPoint3> pathWaypoints;
@ -303,7 +303,7 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) {
std::reverse(pathWaypoints.begin(), pathWaypoints.end()); std::reverse(pathWaypoints.begin(), pathWaypoints.end());
} }
movementAI->SetPath(pathWaypoints); movementAiComponent->SetPath(pathWaypoints);
enemy->AddDieCallback([this, self, enemy, name]() { enemy->AddDieCallback([this, self, enemy, name]() {
RegisterHit(self, enemy, name); RegisterHit(self, enemy, name);