2021-12-05 17:54:36 +00:00
|
|
|
#include "MovementAIComponent.h"
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
#include "ControllablePhysicsComponent.h"
|
|
|
|
#include "BaseCombatAIComponent.h"
|
|
|
|
#include "dpCommon.h"
|
|
|
|
#include "dpWorld.h"
|
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "SimplePhysicsComponent.h"
|
2022-12-18 15:46:04 +00:00
|
|
|
#include "CDClientManager.h"
|
2023-08-04 02:38:04 +00:00
|
|
|
#include "Game.h"
|
|
|
|
#include "dZoneManager.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-03-17 14:36:21 +00:00
|
|
|
#include "CDComponentsRegistryTable.h"
|
|
|
|
#include "CDPhysicsComponentTable.h"
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
namespace {
|
|
|
|
/**
|
|
|
|
* Cache of all lots and their respective speeds
|
|
|
|
*/
|
|
|
|
std::map<LOT, float> m_PhysicsSpeedCache;
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
|
2023-08-04 02:38:04 +00:00
|
|
|
m_Info = info;
|
2023-08-07 07:44:57 +00:00
|
|
|
m_IsPaused = true;
|
2023-08-04 02:38:04 +00:00
|
|
|
m_AtFinalWaypoint = true;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
m_BaseCombatAI = nullptr;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_BaseCombatAI = m_Parent->GetComponent<BaseCombatAIComponent>();
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
//Try and fix the insane values:
|
2023-08-04 02:38:04 +00:00
|
|
|
if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f;
|
2021-12-05 17:54:36 +00:00
|
|
|
if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
|
2023-08-04 02:38:04 +00:00
|
|
|
if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
m_BaseSpeed = GetBaseSpeed(m_Parent->GetLOT());
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_NextWaypoint = m_Parent->GetPosition();
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Acceleration = 0.4f;
|
2023-08-04 02:38:04 +00:00
|
|
|
m_PullingToPoint = false;
|
|
|
|
m_PullPoint = NiPoint3::ZERO;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_HaltDistance = 0;
|
2023-08-04 02:38:04 +00:00
|
|
|
m_TimeToTravel = 0;
|
|
|
|
m_TimeTravelled = 0;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_CurrentSpeed = 0;
|
2023-08-04 02:38:04 +00:00
|
|
|
m_MaxSpeed = 0;
|
2023-08-07 03:25:22 +00:00
|
|
|
m_CurrentPathWaypointIndex = 0;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_LockRotation = false;
|
2023-08-07 04:15:06 +00:00
|
|
|
m_IsInReverse = false;
|
|
|
|
m_NextPathWaypointIndex = 0;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-08-08 01:40:06 +00:00
|
|
|
void MovementAIComponent::SetupPath(const std::string& pathname) {
|
|
|
|
std::string path = pathname;
|
|
|
|
if (path.empty()) path = m_Parent->GetVarAsString(u"attached_path");
|
|
|
|
if (path.empty()) {
|
|
|
|
Game::logger->Log("MovementAIComponent", "No path to load for %i:%llu", m_Parent->GetLOT(), m_Parent->GetObjectID());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const Path* pathData = Game::zoneManager->GetZone()->GetPath(path);
|
|
|
|
if (pathData) {
|
|
|
|
Game::logger->Log("MovementAIComponent", "found path %s", path.c_str());
|
|
|
|
} else {
|
|
|
|
Game::logger->Log("MovementAIComponent", "No path found for %i:%llu", m_Parent->GetLOT(), m_Parent->GetObjectID());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
void MovementAIComponent::Update(const float deltaTime) {
|
2023-08-04 02:38:04 +00:00
|
|
|
if (m_PullingToPoint) {
|
2021-12-05 17:54:36 +00:00
|
|
|
const auto source = GetCurrentWaypoint();
|
|
|
|
|
|
|
|
const auto speed = deltaTime * 2.5f;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
NiPoint3 velocity = (m_PullPoint - source) * speed;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
SetPosition(source + velocity);
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) {
|
|
|
|
m_PullingToPoint = false;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-07 07:44:57 +00:00
|
|
|
// Are we done or paused?
|
|
|
|
if (AtFinalWaypoint() || IsPaused()) return;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (m_HaltDistance > 0) {
|
2023-08-04 02:38:04 +00:00
|
|
|
// Prevent us from hugging the target
|
|
|
|
if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < std::pow(m_HaltDistance, 2)) {
|
2021-12-05 17:54:36 +00:00
|
|
|
Stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_TimeTravelled += deltaTime;
|
|
|
|
if (m_TimeTravelled < m_TimeToTravel) return;
|
|
|
|
m_TimeTravelled = 0.0f;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
const auto source = GetCurrentWaypoint();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
SetPosition(source);
|
|
|
|
|
|
|
|
NiPoint3 velocity = NiPoint3::ZERO;
|
|
|
|
|
2023-03-14 11:12:26 +00:00
|
|
|
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
|
2021-12-05 17:54:36 +00:00
|
|
|
{
|
|
|
|
m_NextWaypoint = GetCurrentWaypoint();
|
|
|
|
|
|
|
|
if (m_NextWaypoint == source) {
|
2023-08-04 02:38:04 +00:00
|
|
|
m_TimeToTravel = 0.0f;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
goto nextAction;
|
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
if (m_CurrentSpeed < m_MaxSpeed) {
|
2021-12-05 17:54:36 +00:00
|
|
|
m_CurrentSpeed += m_Acceleration;
|
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
if (m_CurrentSpeed > m_MaxSpeed) {
|
|
|
|
m_CurrentSpeed = m_MaxSpeed;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
const auto delta = m_NextWaypoint - source;
|
|
|
|
|
|
|
|
// Normalize the vector
|
2023-08-04 02:38:04 +00:00
|
|
|
const auto length = delta.Length();
|
2021-12-05 17:54:36 +00:00
|
|
|
if (length > 0) {
|
2023-08-04 02:38:04 +00:00
|
|
|
velocity = (delta / length) * speed;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Calclute the time it will take to reach the next waypoint with the current speed
|
2023-08-04 02:38:04 +00:00
|
|
|
m_TimeTravelled = 0.0f;
|
|
|
|
m_TimeToTravel = length / speed;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
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
|
2023-08-07 09:03:09 +00:00
|
|
|
HandleWaypointArrived();
|
2023-08-07 04:15:06 +00:00
|
|
|
if (!AdvancePathWaypointIndex()) {
|
2021-12-05 17:54:36 +00:00
|
|
|
Stop();
|
|
|
|
return;
|
|
|
|
}
|
2023-08-07 03:25:22 +00:00
|
|
|
SetDestination(GetCurrentPathWaypoint());
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
nextAction:
|
|
|
|
|
|
|
|
SetVelocity(velocity);
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-08-07 08:46:03 +00:00
|
|
|
void MovementAIComponent::ReversePath() {
|
|
|
|
if (m_CurrentPath.empty()) return;
|
|
|
|
if (m_NextPathWaypointIndex < 0) m_NextPathWaypointIndex = 0;
|
|
|
|
if (m_NextPathWaypointIndex >= m_CurrentPath.size()) m_NextPathWaypointIndex = m_CurrentPath.size() - 1;
|
|
|
|
m_CurrentPathWaypointIndex = m_NextPathWaypointIndex;
|
|
|
|
m_IsInReverse = !m_IsInReverse;
|
|
|
|
AdvancePathWaypointIndex();
|
|
|
|
}
|
|
|
|
|
2023-08-07 03:25:22 +00:00
|
|
|
bool MovementAIComponent::AdvancePathWaypointIndex() {
|
2023-08-07 04:15:06 +00:00
|
|
|
m_CurrentPathWaypointIndex = m_NextPathWaypointIndex;
|
|
|
|
if (m_IsInReverse) {
|
2023-08-07 06:40:30 +00:00
|
|
|
if (m_CurrentPathWaypointIndex >= 0) m_NextPathWaypointIndex--;
|
|
|
|
return m_CurrentPathWaypointIndex >= 0;
|
2023-08-07 04:15:06 +00:00
|
|
|
} else {
|
2023-08-07 06:40:30 +00:00
|
|
|
if (m_CurrentPathWaypointIndex <= m_CurrentPath.size()) m_NextPathWaypointIndex++;
|
2023-08-07 04:15:06 +00:00
|
|
|
return m_CurrentPathWaypointIndex < m_CurrentPath.size();
|
|
|
|
}
|
2023-08-07 03:25:22 +00:00
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
const MovementAIInfo& MovementAIComponent::GetInfo() const {
|
|
|
|
return m_Info;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MovementAIComponent::AdvanceWaypointIndex() {
|
2023-08-04 02:38:04 +00:00
|
|
|
if (m_PathIndex >= m_InterpolatedWaypoints.size()) {
|
2021-12-05 17:54:36 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
m_PathIndex++;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
2023-08-04 02:38:04 +00:00
|
|
|
return m_PathIndex >= m_InterpolatedWaypoints.size() ? m_Parent->GetPosition() : m_InterpolatedWaypoints[m_PathIndex];
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
2023-08-04 02:38:04 +00:00
|
|
|
auto source = m_Parent->GetPosition();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
if (AtFinalWaypoint()) return source;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
auto destination = m_NextWaypoint;
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
auto approximation = source + ((destination - source) * percentageToWaypoint);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (dpWorld::Instance().IsLoaded()) {
|
2022-08-02 05:30:19 +00:00
|
|
|
approximation.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(approximation);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return approximation;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MovementAIComponent::Warp(const NiPoint3& point) {
|
|
|
|
Stop();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
NiPoint3 destination = point;
|
|
|
|
|
|
|
|
if (dpWorld::Instance().IsLoaded()) {
|
2022-08-02 05:30:19 +00:00
|
|
|
destination.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
if (std::abs(destination.y - point.y) > 3) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetPosition(destination);
|
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-08-07 07:44:57 +00:00
|
|
|
void MovementAIComponent::Pause() {
|
|
|
|
if (AtFinalWaypoint() || IsPaused()) return;
|
|
|
|
SetPosition(ApproximateLocation());
|
|
|
|
SetVelocity(NiPoint3::ZERO);
|
|
|
|
|
|
|
|
// Clear this as we may be somewhere else when we resume movement.
|
|
|
|
m_InterpolatedWaypoints.clear();
|
|
|
|
m_IsPaused = true;
|
|
|
|
m_PathIndex = 0;
|
|
|
|
m_TimeToTravel = 0;
|
|
|
|
m_TimeTravelled = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MovementAIComponent::Resume() {
|
|
|
|
if (AtFinalWaypoint() || !IsPaused()) return;
|
|
|
|
m_IsPaused = false;
|
|
|
|
SetDestination(GetCurrentPathWaypoint());
|
|
|
|
}
|
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
void MovementAIComponent::Stop() {
|
2023-08-04 02:38:04 +00:00
|
|
|
if (AtFinalWaypoint()) return;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
SetPosition(ApproximateLocation());
|
|
|
|
|
|
|
|
SetVelocity(NiPoint3::ZERO);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_TimeToTravel = 0;
|
|
|
|
m_TimeTravelled = 0;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_AtFinalWaypoint = true;
|
2023-08-07 09:03:09 +00:00
|
|
|
m_IsPaused = true;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_InterpolatedWaypoints.clear();
|
2023-08-07 03:25:22 +00:00
|
|
|
m_CurrentPath.clear();
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
m_PathIndex = 0;
|
|
|
|
|
|
|
|
m_CurrentSpeed = 0;
|
2023-08-07 03:25:22 +00:00
|
|
|
m_CurrentPathWaypointIndex = 0;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-07-15 20:56:33 +00:00
|
|
|
Game::entityManager->SerializeEntity(m_Parent);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
|
|
|
Stop();
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_PullingToPoint = true;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_PullPoint = point;
|
|
|
|
}
|
|
|
|
|
2023-08-07 06:40:30 +00:00
|
|
|
const NiPoint3& MovementAIComponent::GetCurrentPathWaypoint() const {
|
|
|
|
if (m_CurrentPathWaypointIndex >= m_CurrentPath.size() || m_CurrentPathWaypointIndex < 0) {
|
|
|
|
return m_Parent->GetPosition();
|
|
|
|
}
|
|
|
|
return m_CurrentPath.at(m_CurrentPathWaypointIndex);
|
|
|
|
}
|
|
|
|
|
2023-08-07 04:15:06 +00:00
|
|
|
void MovementAIComponent::SetPath(std::vector<NiPoint3> path, bool startInReverse) {
|
2023-08-04 02:38:04 +00:00
|
|
|
if (path.empty()) return;
|
2023-08-07 03:25:22 +00:00
|
|
|
m_CurrentPath = path;
|
2023-08-07 04:15:06 +00:00
|
|
|
m_IsInReverse = startInReverse;
|
2023-08-07 03:25:22 +00:00
|
|
|
|
2023-08-07 04:15:06 +00:00
|
|
|
// Start the Entity out at the first waypoint with their next waypoint being the same one.
|
|
|
|
// This is so AdvancePathWaypointIndex can do the recovery from effectively a paused state.
|
|
|
|
m_CurrentPathWaypointIndex = m_IsInReverse ? m_CurrentPath.size() - 1 : 0;
|
|
|
|
m_NextPathWaypointIndex = m_IsInReverse ? m_CurrentPath.size() - 1 : 0;
|
|
|
|
AdvancePathWaypointIndex();
|
2023-08-07 06:40:30 +00:00
|
|
|
SetDestination(GetCurrentPathWaypoint());
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
|
|
|
// Check if the lot is in the cache
|
|
|
|
const auto& it = m_PhysicsSpeedCache.find(lot);
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2021-12-05 17:54:36 +00:00
|
|
|
if (it != m_PhysicsSpeedCache.end()) {
|
|
|
|
return it->second;
|
|
|
|
}
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-03-17 14:36:21 +00:00
|
|
|
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
|
|
|
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
int32_t componentID;
|
|
|
|
CDPhysicsComponent* physicsComponent = nullptr;
|
|
|
|
|
2023-03-04 07:16:37 +00:00
|
|
|
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::CONTROLLABLE_PHYSICS, -1);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
if (componentID == -1) {
|
|
|
|
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::SIMPLE_PHYSICS, -1);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
physicsComponent = physicsComponentTable->GetByID(componentID);
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-03-27 08:13:34 +00:00
|
|
|
// Client defaults speed to 10 and if the speed is also null in the table, it defaults to 10.
|
2023-08-04 02:38:04 +00:00
|
|
|
float speed = physicsComponent != nullptr ? physicsComponent->speed : 10.0f;
|
2023-03-27 08:13:34 +00:00
|
|
|
|
2023-04-12 05:25:02 +00:00
|
|
|
float delta = fabs(speed) - 1.0f;
|
|
|
|
|
|
|
|
if (delta <= std::numeric_limits<float>::epsilon()) speed = 10.0f;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
m_PhysicsSpeedCache[lot] = speed;
|
|
|
|
|
|
|
|
return speed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MovementAIComponent::SetPosition(const NiPoint3& value) {
|
2023-08-04 02:38:04 +00:00
|
|
|
m_Parent->SetPosition(value);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MovementAIComponent::SetRotation(const NiQuaternion& value) {
|
2023-08-04 02:38:04 +00:00
|
|
|
if (!m_LockRotation) m_Parent->SetRotation(value);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
|
|
|
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
|
|
|
|
|
|
|
if (controllablePhysicsComponent != nullptr) {
|
|
|
|
controllablePhysicsComponent->SetVelocity(value);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
|
|
|
|
|
|
|
|
if (simplePhysicsComponent != nullptr) {
|
|
|
|
simplePhysicsComponent->SetVelocity(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
|
|
|
if (m_PullingToPoint) return;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
const auto location = ApproximateLocation();
|
|
|
|
|
|
|
|
if (!AtFinalWaypoint()) {
|
|
|
|
SetPosition(location);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<NiPoint3> computedPath;
|
|
|
|
if (dpWorld::Instance().IsLoaded()) {
|
2023-08-04 02:38:04 +00:00
|
|
|
computedPath = dpWorld::Instance().GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Somehow failed
|
|
|
|
if (computedPath.empty()) {
|
2021-12-05 17:54:36 +00:00
|
|
|
// Than take 10 points between the current position and the destination and make that the path
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
auto start = location;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
auto delta = destination - start;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
auto step = delta / 10.0f;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++) {
|
2023-08-06 22:53:37 +00:00
|
|
|
start += step;
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
computedPath.push_back(start);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_InterpolatedWaypoints.clear();
|
2021-12-05 17:54:36 +00:00
|
|
|
|
|
|
|
// Simply path
|
2023-08-04 02:38:04 +00:00
|
|
|
for (auto& point : computedPath) {
|
2021-12-05 17:54:36 +00:00
|
|
|
if (dpWorld::Instance().IsLoaded()) {
|
2022-08-02 05:30:19 +00:00
|
|
|
point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_InterpolatedWaypoints.push_back(point);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_PathIndex = 0;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_TimeTravelled = 0;
|
|
|
|
m_TimeToTravel = 0;
|
2022-07-28 13:39:57 +00:00
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
m_AtFinalWaypoint = false;
|
2023-08-07 07:44:57 +00:00
|
|
|
m_IsPaused = false;
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NiPoint3 MovementAIComponent::GetDestination() const {
|
2023-08-04 02:38:04 +00:00
|
|
|
return m_InterpolatedWaypoints.empty() ? m_Parent->GetPosition() : m_InterpolatedWaypoints.back();
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2023-08-04 02:38:04 +00:00
|
|
|
void MovementAIComponent::SetMaxSpeed(const float value) {
|
|
|
|
if (value == m_MaxSpeed) return;
|
|
|
|
m_MaxSpeed = value;
|
2021-12-05 17:54:36 +00:00
|
|
|
m_Acceleration = value / 5;
|
|
|
|
}
|
2023-08-07 09:03:09 +00:00
|
|
|
|
2023-08-08 01:40:06 +00:00
|
|
|
#include "MovementAIComponentAronwk.cpp"
|