diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index 9107a62d..82cc3c33 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -317,18 +317,6 @@ void Entity::Initialize() { m_Components.insert(std::make_pair(COMPONENT_TYPE_SOUND_TRIGGER, comp)); } - //Check to see if we have a moving platform component: - //Which, for some reason didn't get added to the ComponentsRegistry so we have to check for a path manually here. - std::string attachedPath = GetVarAsString(u"attached_path"); - - if ((!attachedPath.empty())){ - const auto* path = dZoneManager::Instance()->GetZone()->GetPath(attachedPath); - if (path->pathType == PathType::MovingPlatform || compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_MOVING_PLATFORM, -1) != -1) { - MovingPlatformComponent* plat = new MovingPlatformComponent(this, attachedPath); - m_Components.insert(std::make_pair(COMPONENT_TYPE_MOVING_PLATFORM, plat)); - } - } - //Also check for the collectible id: m_CollectibleID = GetVarAs(u"collectible_id"); @@ -699,6 +687,38 @@ void Entity::Initialize() { m_Components.insert(std::make_pair(COMPONENT_TYPE_MOVEMENT_AI, new MovementAIComponent(this, moveInfo))); } + std::string attachedPath = GetVarAsString(u"attached_path"); + Path* path = nullptr; + if ((!attachedPath.empty())){ + path = const_cast(dZoneManager::Instance()->GetZone()->GetPath(attachedPath)); + } + + if (path){ + if (path->pathType == PathType::MovingPlatform || compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_MOVING_PLATFORM, -1) != -1) { + MovingPlatformComponent* plat = new MovingPlatformComponent(this, attachedPath); + m_Components.insert(std::make_pair(COMPONENT_TYPE_MOVING_PLATFORM, plat)); + } else if (path->pathType == PathType::Movement && !HasComponent(COMPONENT_TYPE_MOVEMENT_AI)){ + MovementAIInfo moveInfo = MovementAIInfo(); + + // no wandering for you + moveInfo.movementType = ""; + moveInfo.wanderChance = 0; + moveInfo.wanderRadius = 0; + moveInfo.wanderSpeed = 0.0f; + moveInfo.wanderDelayMax = 0; + moveInfo.wanderDelayMin = 0; + + auto* movementAIcomp = new MovementAIComponent(this, moveInfo); + if (movementAIcomp) movementAIcomp->SetPath(path); + + m_Components.insert(std::make_pair(COMPONENT_TYPE_MOVEMENT_AI, movementAIcomp)); + } else if (path->pathType == PathType::Movement && HasComponent(COMPONENT_TYPE_MOVEMENT_AI)){ + auto* movementAIcomp = this->GetComponent(); + if (movementAIcomp) movementAIcomp->SetPath(path); + } + } + + int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_PROXIMITY_MONITOR); if (proximityMonitorID > 0) { CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance()->GetTable("ProximityMonitorComponent"); diff --git a/dGame/dComponents/ControllablePhysicsComponent.cpp b/dGame/dComponents/ControllablePhysicsComponent.cpp index 15a7c9c5..859a20dc 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.cpp +++ b/dGame/dComponents/ControllablePhysicsComponent.cpp @@ -33,11 +33,6 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Com m_PickupRadius = 0.0f; m_DirtyPickupRadiusScale = true; m_IsTeleporting = false; - m_AttachedPath = entity->GetVarAsString(u"attached_path"); - m_PathWaypoint = entity->GetVarAs(u"attached_path_start"); - m_PathSpeed = 2.5f; - m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT()); - if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI return; @@ -59,96 +54,6 @@ ControllablePhysicsComponent::~ControllablePhysicsComponent() { } void ControllablePhysicsComponent::Update(float deltaTime) { - if (m_AttachedPath != ""){ - const auto* path = dZoneManager::Instance()->GetZone()->GetPath(m_AttachedPath); - - if (!m_Paused){ - if (path->pathWaypoints.size() > m_PathWaypoint) { - auto mod_speed = m_BaseSpeed; - if (m_PathSpeed < 1.0) { - mod_speed = m_BaseSpeed * m_PathSpeed; - } else { - mod_speed = m_PathSpeed; - } - - auto speed = deltaTime * mod_speed; - auto source = GetPosition(); - auto dest = path->pathWaypoints.at(m_PathWaypoint).position; - dest.y = source.y; // hacky way to not glitch with weird heights - - // if we are close enough to the destination waypoint - if (Vector3::DistanceSquared(source, dest) < 2 * 2) { - if (path->pathBehavior == PathBehavior::Loop) { - if (path->waypointCount < m_PathWaypoint + 1) { - m_PathWaypoint = 0; - } else m_PathWaypoint++; - } else if (path->pathBehavior == PathBehavior::Once){ - if (path->waypointCount < m_PathWaypoint + 1) { - m_AttachedPath = ""; - } else m_PathWaypoint++; - } - m_Paused = true; - return; - } - - const auto delta = dest - source; - const auto length = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z); - NiPoint3 velocity; - NiPoint3 velocity_pos; - if (length > 0) { - velocity_pos.x = (delta.x / length) * speed; - velocity_pos.y = (delta.y / length) * speed; - velocity_pos.z = (delta.z / length) * speed; - } - speed = speed + 2.8f; - if (length > 0) { - velocity.x = (delta.x / length) * speed; - velocity.y = (delta.y / length) * speed; - velocity.z = (delta.z / length) * speed; - } - SetRotation(NiQuaternion::LookAt(source, dest)); - SetVelocity(velocity); - SetPosition(source + velocity_pos); - EntityManager::Instance()->SerializeEntity(m_Parent); - } else if (path->pathBehavior == PathBehavior::Loop) m_PathWaypoint = 0; - - } else { // paused, meaing we are at a waypoint, and we want to do something - if (m_PausedTime > 0) { - m_PausedTime = m_PausedTime - deltaTime; - } else if (m_PausedTime < 0){ - m_Paused = false; - m_PausedTime = 0; - } else if (path->pathWaypoints.size() > m_PathWaypoint) { - PathWaypoint waypoint = path->pathWaypoints.at(m_PathWaypoint); - if (waypoint.config.size() > 0) { - for (LDFBaseData* action : waypoint.config) { - if (action) { - if (action->GetKey() == u"delay"){ - m_PausedTime = std::stof(action->GetValueAsString()); - SetVelocity(NiPoint3::ZERO); - EntityManager::Instance()->SerializeEntity(m_Parent); - } else if (action->GetKey() == u"emote"){ - GameMessages::SendPlayAnimation(m_Parent, GeneralUtils::UTF8ToUTF16(action->GetValueAsString())); - m_PausedTime += 10; - SetVelocity(NiPoint3::ZERO); - EntityManager::Instance()->SerializeEntity(m_Parent); - } else if (action->GetKey() == u"pathspeed") { - m_PathSpeed = std::stof(action->GetValueAsString()); - if (m_PathSpeed < 2.5f) m_PathSpeed = 2.5f; - } else if (action->GetKey() == u"changeWP") { - m_AttachedPath = action->GetValueAsString(); - } else { - Game::logger->LogDebug("ControllablePhysicsComponent", "Unhandled action %s", GeneralUtils::UTF16ToWTF8(action->GetKey()).c_str()); - } - } - } - } - if (m_PausedTime == 0) { - m_Paused = false; - } - } else if (path->pathBehavior == PathBehavior::Loop) m_PathWaypoint = 0; - } - } } void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { @@ -370,36 +275,3 @@ void ControllablePhysicsComponent::RemovePickupRadiusScale(float value) { } EntityManager::Instance()->SerializeEntity(m_Parent); } - -// void ControllablePhysicsComponent::FollowWaypoints(bool paused, std::string newPathName, int newPathStart = 0){ -// m_Paused = paused; -// m_AttachedPath = newPathName; -// m_PathWaypoint = newPathStart; -// } - -// void ControllablePhysicsComponent::FollowWaypoints(std::string newPathName, int newPathStart = 0){ -// m_AttachedPath = newPathName; -// m_PathWaypoint = newPathStart; -// } - -float ControllablePhysicsComponent::GetBaseSpeed(LOT lot) { - - CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance()->GetTable("ComponentsRegistry"); - CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance()->GetTable("PhysicsComponent"); - - int32_t componentID; - CDPhysicsComponent* physicsComponent = nullptr; - - componentID = componentRegistryTable->GetByIDAndType(lot, COMPONENT_TYPE_CONTROLLABLE_PHYSICS, -1); - - if (componentID != -1) physicsComponent = physicsComponentTable->GetByID(componentID); - - float speed; - if (physicsComponent == nullptr) { - speed = 8; - } else { - speed = physicsComponent->speed; - } - - return speed; -} diff --git a/dGame/dComponents/ControllablePhysicsComponent.h b/dGame/dComponents/ControllablePhysicsComponent.h index 10fe7a2e..ba5c6e26 100644 --- a/dGame/dComponents/ControllablePhysicsComponent.h +++ b/dGame/dComponents/ControllablePhysicsComponent.h @@ -257,43 +257,6 @@ public: */ std::vector GetActivePickupRadiusScales() { return m_ActivePickupRadiusScales; }; - /** - * @brief tell an npc how to use it's given path - * - * @param paused if they are not moving - */ - void FollowWaypoints(bool paused) {m_Paused = paused;}; - - /** - * @brief tell an npc how to use it's given path - * - * @param paused if they are not moving - * @param newPathName the new path to use - * @param newPathStart the waypoint on the new path to start at - */ - void FollowWaypoints(bool paused, std::string newPathName, int newPathStart = 0); - - /** - * @brief tell an npc how to use it's given path - * - * @param newPathName the new path to use - * @param newPathStart the waypoint on the new path to start at - */ - void FollowWaypoints(std::string newPathName, int newPathStart = 0); - - /** - * @brief starts pathing - * - */ - void FollowWaypoints(){m_Paused = false;}; - - /** - * Returns the base speed from the DB for a given LOT - * @param lot the lot to check for - * @return the base speed of the lot - */ - static float GetBaseSpeed(LOT lot); - private: /** * The entity that owns this component @@ -410,36 +373,6 @@ private: */ bool m_IsTeleporting; - /** - * The walking path the entity has - */ - std::string m_AttachedPath; - - /** - * The curent pay waypoint - */ - int m_PathWaypoint; - - /** - * If the path is being followed - */ - bool m_Paused = false; - - /** - * the speed at which they will path - */ - float m_PathSpeed; - - /** - * if we are waiting on a delay - */ - float m_PausedTime = 0.0; - - /** - * The laden speed of an object - */ - float m_BaseSpeed; - }; #endif // CONTROLLABLEPHYSICSCOMPONENT_H diff --git a/dGame/dComponents/MovementAIComponent.cpp b/dGame/dComponents/MovementAIComponent.cpp index ed6ed483..18dac63a 100644 --- a/dGame/dComponents/MovementAIComponent.cpp +++ b/dGame/dComponents/MovementAIComponent.cpp @@ -9,12 +9,13 @@ #include "dpWorld.h" #include "EntityManager.h" #include "SimplePhysicsComponent.h" +#include "dZoneManager.h" std::map MovementAIComponent::m_PhysicsSpeedCache = {}; MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) { m_Info = std::move(info); - m_Done = true; + m_Done = false; m_BaseCombatAI = nullptr; @@ -32,18 +33,30 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : m_Interrupted = false; m_PullPoint = {}; m_HaltDistance = 0; - m_Timer = 0; + m_CurrentSpeed = 0; m_Speed = 0; + m_WaypointPathSpeed = 1.0f; + + m_TotalTime = 0; + m_Timer = 0; + m_LockRotation = false; + + m_WaypointPathIndex = parent->GetVarAs(u"attached_path_start"); + + + m_NavPathIndex = 0; } MovementAIComponent::~MovementAIComponent() = default; void MovementAIComponent::Update(const float deltaTime) { + + // pull to point update take priority if (m_Interrupted) { - const auto source = GetCurrentWaypoint(); + const auto source = GetCurrentPosition(); const auto speed = deltaTime * 2.5f; @@ -62,112 +75,255 @@ void MovementAIComponent::Update(const float deltaTime) { return; } - if (AtFinalWaypoint()) // Are we done? - { + // Navmesh pathing logic + if (!m_Queue.empty()) { + PullToPoint(m_Queue.top()); + + m_Queue.pop(); return; } - if (m_HaltDistance > 0) { - if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < m_HaltDistance * m_HaltDistance) // Prevent us from hugging the target - { - Stop(); + // waypoint pathing logic + if (m_CurrentPath){ + if (!m_Done && !m_Waiting){ + if (m_CurrentPath->pathWaypoints.size() > m_WaypointPathIndex) { + auto speed = m_BaseSpeed * m_PathSpeed; + auto source = m_Parent->GetPosition(); + auto dest = m_CurrentPath->pathWaypoints.at(m_WaypointPathIndex).position; - return; + // TODO: do this better and more sanely + auto hasNavMesh = dpWorld::Instance().IsLoaded(); + if (hasNavMesh) dest.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(dest); + if (abs(dest.y - source.y) > 10) dest.y = source.y; // hacky way to not glitch with weird heights without nav meshes + + // if we are close enough to the destination waypoint + if (Vector3::DistanceSquared(source, dest) < 2 * 2) { + if (!AdvancePathWaypointIndex()) return; + } + + const auto delta = dest - source; + const auto length = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z); + NiPoint3 velocity; + if (length > 0) { + velocity.x = (delta.x / length) * m_BaseSpeed; + velocity.y = (delta.y / length) * m_BaseSpeed; + velocity.z = (delta.z / length) * m_BaseSpeed; + } + NiPoint3 velocity_pos; + if (length > 0) { + velocity_pos.x = (delta.x / length) * speed * deltaTime; + velocity_pos.y = (delta.y / length) * speed * deltaTime; + velocity_pos.z = (delta.z / length) * speed * deltaTime; + } + // Game::logger->Log("ControllablePhysicsComponent", "v.x %f v.y %f v.z %f", velocity.x, velocity.y, velocity.z); + SetRotation(NiQuaternion::LookAt(source, dest)); + SetVelocity(velocity); + SetPosition(source + velocity_pos); + EntityManager::Instance()->SerializeEntity(m_Parent); + } + } else if (!m_Done && m_Waiting) { // waiting, meaing we are at a waypoint, and we want to do something + // handle waiting + if (m_WaitingTime > 0) { + m_WaitingTime = m_WaitingTime - deltaTime; + } else if (m_WaitingTime < 0){ + m_Waiting = false; + m_WaitingTime = 0; + // end handle waiting + } else if (m_CurrentPath->pathWaypoints.size() > m_WaypointPathIndex) ArrivedAtPathWaypoint(); } } - if (m_Timer > 0) { - m_Timer -= deltaTime; - - if (m_Timer > 0) { - return; - } - - m_Timer = 0; - } - - const auto source = GetCurrentWaypoint(); - - SetPosition(source); - - NiPoint3 velocity = NiPoint3::ZERO; - - if (AdvanceWaypointIndex()) // Do we have another waypoint to seek? - { - m_NextWaypoint = GetCurrentWaypoint(); - - if (m_NextWaypoint == source) { - m_Timer = 0; - - goto nextAction; - } - - if (m_CurrentSpeed < m_Speed) { - m_CurrentSpeed += m_Acceleration; - } - - if (m_CurrentSpeed > m_Speed) { - m_CurrentSpeed = m_Speed; - } - - const auto speed = m_CurrentSpeed * m_BaseSpeed; - - const auto delta = m_NextWaypoint - source; - - // Normalize the vector - const auto length = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z); - - if (length > 0) { - velocity.x = (delta.x / length) * speed; - velocity.y = (delta.y / length) * speed; - velocity.z = (delta.z / length) * speed; - } - - // Calclute the time it will take to reach the next waypoint with the current speed - m_TotalTime = m_Timer = length / speed; - - SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint)); - } else { - // Check if there are more waypoints in the queue, if so set our next destination to the next waypoint - if (!m_Queue.empty()) { - SetDestination(m_Queue.top()); - - m_Queue.pop(); - } else { - // We have reached our final waypoint - Stop(); - - return; - } - } - -nextAction: - - SetVelocity(velocity); - - EntityManager::Instance()->SerializeEntity(m_Parent); } +// if (m_HaltDistance > 0) { +// if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < m_HaltDistance * m_HaltDistance) // Prevent us from hugging the target +// { +// Stop(); + +// return; +// } +// } + +// if (m_Timer > 0) { +// m_Timer -= deltaTime; + +// if (m_Timer > 0) { +// return; +// } + +// m_Timer = 0; +// } + +// const auto source = GetCurrentWaypoint(); + +// SetPosition(source); + +// NiPoint3 velocity = NiPoint3::ZERO; + +// if (AdvanceWaypointIndex()) // Do we have another waypoint to seek? +// { +// m_NextWaypoint = GetCurrentWaypoint(); + +// if (m_NextWaypoint == source) { +// m_Timer = 0; + +// goto nextAction; +// } + +// if (m_CurrentSpeed < m_Speed) { +// m_CurrentSpeed += m_Acceleration; +// } + +// if (m_CurrentSpeed > m_Speed) { +// m_CurrentSpeed = m_Speed; +// } + +// const auto speed = m_CurrentSpeed * m_BaseSpeed; + +// const auto delta = m_NextWaypoint - source; + +// // Normalize the vector +// const auto length = sqrtf(delta.x * delta.x + delta.y * delta.y + delta.z * delta.z); + +// if (length > 0) { +// velocity.x = (delta.x / length) * speed; +// velocity.y = (delta.y / length) * speed; +// velocity.z = (delta.z / length) * speed; +// } + +// // Calclute the time it will take to reach the next waypoint with the current speed +// m_TotalTime = m_Timer = length / speed; + +// SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint)); +// } else { +// // Check if there are more waypoints in the queue, if so set our next destination to the next waypoint +// if (!m_Queue.empty()) { +// SetDestination(m_Queue.top()); + +// m_Queue.pop(); +// } else { +// // We have reached our final waypoint +// Stop(); + +// return; +// } +// } + +// nextAction: + +// SetVelocity(velocity); + +// EntityManager::Instance()->SerializeEntity(m_Parent); + const MovementAIInfo& MovementAIComponent::GetInfo() const { return m_Info; } -bool MovementAIComponent::AdvanceWaypointIndex() { - if (m_PathIndex >= m_CurrentPath.size()) { - return false; +void MovementAIComponent::ArrivedAtPathWaypoint(){ + // TODO: Call scripts here + + PathWaypoint waypoint = m_CurrentPath->pathWaypoints.at(m_WaypointPathIndex); + + if (waypoint.config.size() > 0) { + + for (LDFBaseData* action : waypoint.config) { + if (action) { + + // delay: has time as float + if (action->GetKey() == u"delay"){ + m_WaitingTime += std::stof(action->GetValueAsString()); + SetVelocity(NiPoint3::ZERO); + EntityManager::Instance()->SerializeEntity(m_Parent); + + // emote: has name of animation to play + } else if (action->GetKey() == u"emote"){ + GameMessages::SendPlayAnimation(m_Parent, GeneralUtils::UTF8ToUTF16(action->GetValueAsString())); + // TODO Get proper animation time and add to wait + m_WaitingTime += 1; + SetVelocity(NiPoint3::ZERO); + EntityManager::Instance()->SerializeEntity(m_Parent); + + // pathspeed: has pathing speed as a float + } else if (action->GetKey() == u"pathspeed") { + m_PathSpeed = std::stof(action->GetValueAsString()); + + // changeWP: , the command and waypoint are optional + } else if (action->GetKey() == u"changeWP") { + // use an intermediate value since it can be one or two things + auto intermed = action->GetValueAsString(); + std::string path_string = ""; + + // sometimes there's a path and what waypoint to start, which are comma separated + if (intermed.find(",") != std::string::npos){ + auto datas = GeneralUtils::SplitString(intermed, ','); + path_string = datas[0]; + m_WaypointPathIndex = stoi(datas[1]) - 1; // becuase 0 vs 1 indexed + } else { + path_string = intermed; + m_WaypointPathIndex = 0; + } + + if (path_string != "") { + m_CurrentPath = const_cast(dZoneManager::Instance()->GetZone()->GetPath(path_string)); + } else m_CurrentPath = nullptr; + + } else { + // We don't recognize the action, let a dev know + Game::logger->LogDebug("ControllablePhysicsComponent", "Unhandled action %s", GeneralUtils::UTF16ToWTF8(action->GetKey()).c_str()); + } + } + } } - m_PathIndex++; + if (m_WaitingTime == 0) { // if we don't have any time to wait + m_Waiting = false; + } +} +bool MovementAIComponent::AdvancePathWaypointIndex() { + + if (m_CurrentPath->pathBehavior == PathBehavior::Loop) { + if (m_CurrentPath->pathWaypoints.size() < m_WaypointPathIndex + 1) { + // If we reach the end, go back to the starting index since the path is a loop + m_WaypointPathIndex = 0; + } else m_WaypointPathIndex++; // Otherwise continue + + } else if (m_CurrentPath->pathBehavior == PathBehavior::Bounce){ // Ping Pong + // Are we going in reverse already? + if (m_Reverse){ // Then we're subtracting + if (m_WaypointPathIndex - 1 < 0){ // Stop reversing if we are at the beginning + m_Reverse = false; + m_WaypointPathIndex++; + } else m_WaypointPathIndex--; // Otherwise continue reverseing + } else { // Then we're adding + if (m_CurrentPath->pathWaypoints.size() < m_WaypointPathIndex + 1){ // Start reversing if we are at the end + m_Reverse = true; + m_WaypointPathIndex--; + } else m_WaypointPathIndex++; // Otherwise continue going up + } + + } else if (m_CurrentPath->pathBehavior == PathBehavior::Once){ + if (m_CurrentPath->pathWaypoints.size() < m_WaypointPathIndex + 1) { + m_CurrentPath = nullptr; // If we reach the end, we don't continue + return false; + } else m_WaypointPathIndex++; // Otherwise continue + } + + m_Waiting = true; return true; } +bool MovementAIComponent::AdvanceNavWaypointIndex() { + +} + + NiPoint3 MovementAIComponent::GetCurrentWaypoint() const { - if (m_PathIndex >= m_CurrentPath.size()) { + if (m_PathIndex >= m_CurrentPath->pathWaypoints.size()) { return GetCurrentPosition(); } - return m_CurrentPath[m_PathIndex]; + return m_CurrentPath->pathWaypoints[m_PathIndex].position; } NiPoint3 MovementAIComponent::GetNextWaypoint() const { @@ -178,6 +334,7 @@ NiPoint3 MovementAIComponent::GetCurrentPosition() const { return m_Parent->GetPosition(); } +// get's the approximate location where the entity should be on the path NiPoint3 MovementAIComponent::ApproximateLocation() const { auto source = GetCurrentPosition(); @@ -235,7 +392,8 @@ void MovementAIComponent::Stop() { return; } - SetPosition(ApproximateLocation()); + // SetPosition(ApproximateLocation()); + SetPosition(GetCurrentPosition()); SetVelocity(NiPoint3::ZERO); @@ -243,10 +401,6 @@ void MovementAIComponent::Stop() { m_Done = true; - m_CurrentPath = {}; - - m_PathIndex = 0; - m_CurrentSpeed = 0; EntityManager::Instance()->SerializeEntity(m_Parent); @@ -259,18 +413,6 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) { m_PullPoint = point; } -void MovementAIComponent::SetPath(std::vector path) { - std::reverse(path.begin(), path.end()); - - for (const auto& point : path) { - m_Queue.push(point); - } - - SetDestination(m_Queue.top()); - - m_Queue.pop(); -} - float MovementAIComponent::GetBaseSpeed(LOT lot) { // Check if the lot is in the cache const auto& it = m_PhysicsSpeedCache.find(lot); @@ -409,9 +551,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) { return; } - m_CurrentPath.clear(); - - m_CurrentPath.push_back(location); + m_Queue.push(location); // Simply path for (auto point : computedPath) { @@ -419,10 +559,10 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) { point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point); } - m_CurrentPath.push_back(point); + m_Queue.push(point); } - m_CurrentPath.push_back(computedPath[computedPath.size() - 1]); + m_Queue.push(computedPath[computedPath.size() - 1]); m_PathIndex = 0; @@ -432,11 +572,11 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) { } NiPoint3 MovementAIComponent::GetDestination() const { - if (m_CurrentPath.empty()) { + if (!m_CurrentPath) { return GetCurrentPosition(); } - return m_CurrentPath[m_CurrentPath.size() - 1]; + return m_CurrentPath->pathWaypoints[m_CurrentPath->pathWaypoints.size() - 1].position; } void MovementAIComponent::SetSpeed(const float value) { diff --git a/dGame/dComponents/MovementAIComponent.h b/dGame/dComponents/MovementAIComponent.h index 82cd48a0..3c2e7110 100644 --- a/dGame/dComponents/MovementAIComponent.h +++ b/dGame/dComponents/MovementAIComponent.h @@ -145,7 +145,11 @@ public: * Attempts to update the waypoint index, making the entity move to the next waypoint * @return true if the waypoint could be increased, false if the entity is at the last waypoint already */ - bool AdvanceWaypointIndex(); + bool AdvancePathWaypointIndex(); + + bool AdvanceNavWaypointIndex(); + + void ArrivedAtPathWaypoint(); /** * Returns the waypoint the entity is currently moving towards @@ -207,7 +211,7 @@ public: * Sets a path to follow for the AI * @param path the path to follow */ - void SetPath(std::vector path); + void SetPath(Path* path) {if (path) {m_CurrentPath = path; m_Done = false; m_Timer = 0;};}; /** * Returns the base speed from the DB for a given LOT @@ -216,6 +220,36 @@ public: */ static float GetBaseSpeed(LOT lot); + // /** + // * @brief tell an npc how to use it's given path + // * + // * @param paused if they are not moving + // */ + // void FollowWaypoints(bool paused) {m_Paused = paused;}; + + // /** + // * @brief tell an npc how to use it's given path + // * + // * @param paused if they are not moving + // * @param newPathName the new path to use + // * @param newPathStart the waypoint on the new path to start at + // */ + // void FollowWaypoints(bool paused, std::string newPathName, int newPathStart = 0); + + // /** + // * @brief tell an npc how to use it's given path + // * + // * @param newPathName the new path to use + // * @param newPathStart the waypoint on the new path to start at + // */ + // void FollowWaypoints(std::string newPathName, int newPathStart = 0); + + // /** + // * @brief starts pathing + // * + // */ + // void FollowWaypoints(){m_Paused = false;}; + private: /** @@ -314,7 +348,7 @@ private: /** * The path the entity is currently following */ - std::vector m_CurrentPath; + Path* m_CurrentPath; /** * Queue of positions to traverse @@ -325,6 +359,32 @@ private: * Cache of all lots and their respective speeds */ static std::map m_PhysicsSpeedCache; + + /** + * If we are waiting for some reason + */ + bool m_Waiting = false; + + /** + * If we are waiting on a delay + */ + float m_WaitingTime = 0.0; + + /** + * The speed at which they will path + */ + float m_PathSpeed; + + /** + * If we are traverseing a waypoint path in reverse + */ + bool m_Reverse = false; + + int m_WaypointPathIndex; + + float m_WaypointPathSpeed; + int m_NavPathIndex; + }; #endif // MOVEMENTAICOMPONENT_H diff --git a/dScripts/ActivityManager.cpp b/dScripts/ActivityManager.cpp index 18d72311..4374337e 100644 --- a/dScripts/ActivityManager.cpp +++ b/dScripts/ActivityManager.cpp @@ -124,8 +124,6 @@ void ActivityManager::ActivityTimerStart(Entity* self, const std::string& timerN auto* timer = new ActivityTimer{ timerName, updateInterval, stopTime }; activeTimers.push_back(timer); - Game::logger->Log("ActivityManager", "Starting timer '%s', %f, %f", timerName.c_str(), updateInterval, stopTime); - self->AddTimer(GetPrefixedName(timer->name), timer->updateInterval); } @@ -205,10 +203,8 @@ void ActivityManager::OnTimerDone(Entity* self, std::string timerName) { activeTimers.erase(std::remove(activeTimers.begin(), activeTimers.end(), timer), activeTimers.end()); delete timer; - Game::logger->Log("ActivityManager", "Executing timer '%s'", activityTimerName.c_str()); OnActivityTimerDone(self, activityTimerName); } else { - Game::logger->Log("ActivityManager", "Updating timer '%s'", activityTimerName.c_str()); OnActivityTimerUpdate(self, timer->name, timer->stopTime - timer->runTime, timer->runTime); self->AddTimer(GetPrefixedName(timer->name), timer->updateInterval); } diff --git a/dScripts/BossSpiderQueenEnemyServer.cpp b/dScripts/BossSpiderQueenEnemyServer.cpp index ef81c888..f785ff1a 100644 --- a/dScripts/BossSpiderQueenEnemyServer.cpp +++ b/dScripts/BossSpiderQueenEnemyServer.cpp @@ -60,8 +60,6 @@ void BossSpiderQueenEnemyServer::OnDie(Entity* self, Entity* killer) { missionComponent->CompleteMission(instanceMissionID); } - Game::logger->Log("BossSpiderQueenEnemyServer", "Starting timer..."); - // There is suppose to be a 0.1 second delay here but that may be admitted? auto* controller = EntityManager::Instance()->GetZoneControlEntity(); diff --git a/dScripts/SGCannon.cpp b/dScripts/SGCannon.cpp index 049837a4..9eb32002 100644 --- a/dScripts/SGCannon.cpp +++ b/dScripts/SGCannon.cpp @@ -287,38 +287,27 @@ void SGCannon::OnActivityTimerDone(Entity* self, const std::string& name) { Game::logger->Log("SGCannon", "Spawning enemy %i on path %s", toSpawn.lot, path->pathName.c_str()); auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self); - EntityManager::Instance()->ConstructEntity(enemy); + if (enemy) { + EntityManager::Instance()->ConstructEntity(enemy); + auto* movementAI = enemy->GetComponent(); - if (true) { - auto* movementAI = new MovementAIComponent(enemy, {}); - - enemy->AddComponent(COMPONENT_TYPE_MOVEMENT_AI, movementAI); + if (!movementAI) return; movementAI->SetSpeed(toSpawn.initialSpeed); movementAI->SetCurrentSpeed(toSpawn.initialSpeed); movementAI->SetHaltDistance(0.0f); - std::vector pathWaypoints; - - for (const auto& waypoint : path->pathWaypoints) { - pathWaypoints.push_back(waypoint.position); - } - - if (GeneralUtils::GenerateRandomNumber(0, 1) < 0.5f) { - std::reverse(pathWaypoints.begin(), pathWaypoints.end()); - } - - movementAI->SetPath(pathWaypoints); - enemy->AddDieCallback([this, self, enemy, name]() { RegisterHit(self, enemy, name); - }); - } + } + ); - // Save the enemy and tell it to start pathing - if (enemy != nullptr) { + // Save the enemy const_cast&>(self->GetVar>(SpawnedObjects)).push_back(enemy->GetObjectID()); - GameMessages::SendPlatformResync(enemy, UNASSIGNED_SYSTEM_ADDRESS); + + // if we are a moving platform, tell it to move + auto* movingPlatformComponent = enemy->GetComponent(); + if (movingPlatformComponent) GameMessages::SendPlatformResync(enemy, UNASSIGNED_SYSTEM_ADDRESS); } } } else if (name == EndGameBufferTimer) {