mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-21 11:59:37 -06:00
Compare commits
71 Commits
limit-user
...
moreMoveme
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f71b774a0a | ||
|
|
0f6b47a833 | ||
|
|
cf8332d3fd | ||
|
|
3cd91d6771 | ||
|
|
db46fa8792 | ||
|
|
b2fee30588 | ||
|
|
e3fc8b90b2 | ||
|
|
3e26b444b9 | ||
|
|
f2efa4f4f9 | ||
|
|
8c8fc2ae87 | ||
|
|
243ae9a69b | ||
|
|
9225ae7d44 | ||
|
|
e6bf86da84 | ||
|
|
e56d3c6579 | ||
|
|
02de7ef28a | ||
|
|
ae891aa4c3 | ||
|
|
124f6dad2a | ||
|
|
15fc39f3bb | ||
|
|
152a33f937 | ||
|
|
772ac06e94 | ||
|
|
6863ee9d76 | ||
|
|
458db4682b | ||
| dd2338601e | |||
|
|
daf5a7ffa9 | ||
|
|
67cd990d98 | ||
|
|
294efe0fe0 | ||
| c70eb77c14 | |||
|
|
e3ae0b6304 | ||
|
|
a9fd7c5e08 | ||
|
|
4f447eb441 | ||
|
|
11b1f5b9d4 | ||
| 8dd7553421 | |||
| 5612e57590 | |||
| 2bb39f4fa5 | |||
| 691a42ba20 | |||
| e35b95f3c8 | |||
| b37574c05e | |||
| 5168404567 | |||
|
|
92e2ab55d9 | ||
|
|
959d19c8eb | ||
|
|
b659edd980 | ||
|
|
abce40f17f | ||
| a63d7df0d2 | |||
|
|
1b54387677 | ||
|
|
56ab6bd4c3 | ||
| 84ba38bd1d | |||
|
|
2db8caadde | ||
|
|
40c59c7f51 | ||
|
|
fba8fc9c45 | ||
|
|
a3b62d60f0 | ||
| facc225b82 | |||
|
|
97b683fd59 | ||
| 1207d896a8 | |||
|
|
5f7a108154 | ||
|
|
fc56777969 | ||
|
|
cceaa96415 | ||
|
|
1d4d1414e9 | ||
|
|
4fbd536e74 | ||
|
|
ed0c979544 | ||
|
|
d372278b25 | ||
|
|
b546c96193 | ||
|
|
aa734ef7ae | ||
|
|
6a5ff30a32 | ||
|
|
3e12dd782b | ||
|
|
bce87aaa06 | ||
|
|
20b2a62932 | ||
|
|
600f0974e7 | ||
|
|
a50e56e8ff | ||
|
|
8117773c56 | ||
| 2946a612fb | |||
| 67ec10ac0d |
@@ -731,15 +731,9 @@ void Entity::Initialize() {
|
|||||||
// 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) {
|
||||||
AddComponent<MovingPlatformComponent>(pathName);
|
AddComponent<MovingPlatformComponent>(pathName);
|
||||||
// else if we are a movement path
|
} else if (path->pathType == PathType::Movement) {
|
||||||
} /*else if (path->pathType == PathType::Movement) {
|
AddComponent<MovementAIComponent>(MovementAIInfo{})->SetupPath(pathName);
|
||||||
auto movementAIcomp = GetComponent<MovementAIComponent>();
|
|
||||||
if (movementAIcomp){
|
|
||||||
// TODO: set path in existing movementAIComp
|
|
||||||
} else {
|
|
||||||
// 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);
|
||||||
|
|||||||
@@ -648,7 +648,7 @@ void BaseCombatAIComponent::Wander() {
|
|||||||
const NiPoint3 delta =
|
const NiPoint3 delta =
|
||||||
{
|
{
|
||||||
radius * cos(theta),
|
radius * cos(theta),
|
||||||
0,
|
m_Parent->GetPosition().y,
|
||||||
radius * sin(theta)
|
radius * sin(theta)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ ControllablePhysicsComponent::~ControllablePhysicsComponent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::Update(float deltaTime) {
|
void ControllablePhysicsComponent::Update(float deltaTime) {
|
||||||
|
if (m_Velocity == NiPoint3Constant::ZERO) return;
|
||||||
|
SetPosition(m_Position + (m_Velocity * deltaTime));
|
||||||
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||||
|
|||||||
@@ -316,6 +316,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
const std::vector<int32_t>& GetFactionIDs() const { return m_FactionIDs; }
|
const std::vector<int32_t>& GetFactionIDs() const { return m_FactionIDs; }
|
||||||
|
|
||||||
|
const bool BelongsToFaction(int32_t factionID) const {return std::find(m_FactionIDs.begin(), m_FactionIDs.end(), factionID) != m_FactionIDs.end(); }
|
||||||
/**
|
/**
|
||||||
* Returns all the faction IDs that this entity considers an enemy
|
* Returns all the faction IDs that this entity considers an enemy
|
||||||
* @return all the faction IDs that this entity considers an enemy
|
* @return all the faction IDs that this entity considers an enemy
|
||||||
|
|||||||
@@ -12,6 +12,13 @@
|
|||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
|
#include "eTriggerEventType.h"
|
||||||
|
#include "eWaypointCommandType.h"
|
||||||
|
#include "RenderComponent.h"
|
||||||
|
#include "SkillComponent.h"
|
||||||
|
#include "InventoryComponent.h"
|
||||||
|
#include "ProximityMonitorComponent.h"
|
||||||
|
#include "DestroyableComponent.h"
|
||||||
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
#include "CDPhysicsComponentTable.h"
|
#include "CDPhysicsComponentTable.h"
|
||||||
@@ -27,6 +34,7 @@ namespace {
|
|||||||
|
|
||||||
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
|
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
|
||||||
m_Info = info;
|
m_Info = info;
|
||||||
|
m_IsPaused = true;
|
||||||
m_AtFinalWaypoint = true;
|
m_AtFinalWaypoint = true;
|
||||||
|
|
||||||
m_BaseCombatAI = nullptr;
|
m_BaseCombatAI = nullptr;
|
||||||
@@ -49,19 +57,61 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
|||||||
m_TimeTravelled = 0;
|
m_TimeTravelled = 0;
|
||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
m_MaxSpeed = 0;
|
m_MaxSpeed = 0;
|
||||||
|
m_StartingWaypointIndex = -1;
|
||||||
|
m_CurrentPathWaypointIndex = 0;
|
||||||
m_LockRotation = false;
|
m_LockRotation = false;
|
||||||
|
m_IsInReverse = false;
|
||||||
|
m_NextPathWaypointIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float MovementAIComponent::GetCurrentPathWaypointSpeed() const {
|
||||||
|
if (!m_Path || m_CurrentPathWaypointIndex >= m_CurrentPath.size() || m_CurrentPathWaypointIndex < 0) {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
return m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).movingPlatform.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::SetupPath(const std::string& pathname) {
|
||||||
|
std::string path = pathname;
|
||||||
|
if (path.empty()) {
|
||||||
|
path = m_Parent->GetVarAsString(u"attached_path");
|
||||||
|
if (path.empty()) {
|
||||||
|
LOG("No path to load for %i:%llu", m_Parent->GetLOT(), m_Parent->GetObjectID());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const Path* pathData = Game::zoneManager->GetZone()->GetPath(path);
|
||||||
|
if (pathData) {
|
||||||
|
LOG("found path %i %s", m_Parent->GetLOT(), path.c_str());
|
||||||
|
m_Path = pathData;
|
||||||
|
if (!HasAttachedPathStart() && m_Parent->HasVar(u"attached_path_start")) m_StartingWaypointIndex = m_Parent->GetVar<uint32_t>(u"attached_path_start");
|
||||||
|
if (m_Path && HasAttachedPathStart() && (m_StartingWaypointIndex < 0 || m_StartingWaypointIndex >= m_Path->pathWaypoints.size())) {
|
||||||
|
LOG("WARNING: attached path start is out of bounds for %i:%llu, defaulting path start to 0",
|
||||||
|
m_Parent->GetLOT(), m_Parent->GetObjectID());
|
||||||
|
m_StartingWaypointIndex = 0;
|
||||||
|
}
|
||||||
|
std::vector<NiPoint3> waypoints;
|
||||||
|
for (const auto& waypoint : m_Path->pathWaypoints) {
|
||||||
|
waypoints.push_back(waypoint.position);
|
||||||
|
}
|
||||||
|
SetPath(waypoints);
|
||||||
|
} else {
|
||||||
|
LOG("No path found for %i:%llu", m_Parent->GetLOT(), m_Parent->GetObjectID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::Update(const float deltaTime) {
|
void MovementAIComponent::Update(const float deltaTime) {
|
||||||
if (m_PullingToPoint) {
|
if (m_PullingToPoint) {
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentWaypoint();
|
||||||
|
|
||||||
|
// Just a guess at the speed...
|
||||||
const auto speed = deltaTime * 2.5f;
|
const auto speed = deltaTime * 2.5f;
|
||||||
|
|
||||||
NiPoint3 velocity = (m_PullPoint - source) * speed;
|
NiPoint3 velocity = (m_PullPoint - source) * speed;
|
||||||
|
|
||||||
SetPosition(source + velocity);
|
SetPosition(source + velocity);
|
||||||
|
|
||||||
|
// We are close enough to the pulled to point, stop pulling
|
||||||
if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) {
|
if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) {
|
||||||
m_PullingToPoint = false;
|
m_PullingToPoint = false;
|
||||||
}
|
}
|
||||||
@@ -69,8 +119,8 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are we done?
|
// Are we done or paused?
|
||||||
if (AtFinalWaypoint()) return;
|
if (AtFinalWaypoint() || IsPaused()) return;
|
||||||
|
|
||||||
if (m_HaltDistance > 0) {
|
if (m_HaltDistance > 0) {
|
||||||
// Prevent us from hugging the target
|
// Prevent us from hugging the target
|
||||||
@@ -90,14 +140,16 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
|
|
||||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
||||||
|
|
||||||
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
|
// If we have no acceleration, then we have no max speed.
|
||||||
{
|
// If we have no base speed, then we cannot scale the speed by it.
|
||||||
|
// Do we have another waypoint to seek?
|
||||||
|
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) {
|
||||||
m_NextWaypoint = GetCurrentWaypoint();
|
m_NextWaypoint = GetCurrentWaypoint();
|
||||||
|
|
||||||
if (m_NextWaypoint == source) {
|
if (m_NextWaypoint == source) {
|
||||||
m_TimeToTravel = 0.0f;
|
m_TimeToTravel = 0.0f;
|
||||||
|
|
||||||
goto nextAction;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_CurrentSpeed < m_MaxSpeed) {
|
if (m_CurrentSpeed < m_MaxSpeed) {
|
||||||
@@ -108,14 +160,14 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
m_CurrentSpeed = m_MaxSpeed;
|
m_CurrentSpeed = m_MaxSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
|
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed * current speed
|
||||||
|
|
||||||
const auto delta = m_NextWaypoint - source;
|
const auto delta = m_NextWaypoint - source;
|
||||||
|
|
||||||
// Normalize the vector
|
// Normalize the vector
|
||||||
const auto length = delta.Length();
|
const auto length = delta.Length();
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
velocity = (delta / length) * speed;
|
velocity = (delta / length).Unitize() * speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calclute the time it will take to reach the next waypoint with the current speed
|
// Calclute the time it will take to reach the next waypoint with the current speed
|
||||||
@@ -125,15 +177,10 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
||||||
} else {
|
} else {
|
||||||
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
||||||
if (m_CurrentPath.empty()) {
|
// All checks for how to progress when you arrive at a waypoint will be handled in this else block.
|
||||||
Stop();
|
HandleWaypointArrived(0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SetDestination(m_CurrentPath.top());
|
|
||||||
|
|
||||||
m_CurrentPath.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
nextAction:
|
nextAction:
|
||||||
|
|
||||||
@@ -142,6 +189,27 @@ nextAction:
|
|||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MovementAIComponent::AdvancePathWaypointIndex() {
|
||||||
|
if (m_CurrentPath.empty()) return false;
|
||||||
|
m_CurrentPathWaypointIndex = m_NextPathWaypointIndex;
|
||||||
|
if (m_IsInReverse) {
|
||||||
|
if (m_CurrentPathWaypointIndex >= 0) m_NextPathWaypointIndex--;
|
||||||
|
return m_CurrentPathWaypointIndex >= 0;
|
||||||
|
} else {
|
||||||
|
if (m_CurrentPathWaypointIndex <= m_CurrentPath.size()) m_NextPathWaypointIndex++;
|
||||||
|
return m_CurrentPathWaypointIndex < m_CurrentPath.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const MovementAIInfo& MovementAIComponent::GetInfo() const {
|
const MovementAIInfo& MovementAIComponent::GetInfo() const {
|
||||||
return m_Info;
|
return m_Info;
|
||||||
}
|
}
|
||||||
@@ -162,14 +230,15 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
|||||||
|
|
||||||
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
||||||
auto source = m_Parent->GetPosition();
|
auto source = m_Parent->GetPosition();
|
||||||
|
|
||||||
if (AtFinalWaypoint()) return source;
|
if (AtFinalWaypoint()) return source;
|
||||||
|
NiPoint3 approximation = source;
|
||||||
|
|
||||||
auto destination = m_NextWaypoint;
|
// Only have physics sim for controllable physics
|
||||||
|
if (!m_Parent->HasComponent(ControllablePhysicsComponent::ComponentType)) {
|
||||||
|
auto destination = GetNextWaypoint();
|
||||||
auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0;
|
auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0;
|
||||||
|
approximation = source + ((destination - source) * percentageToWaypoint);
|
||||||
auto approximation = source + ((destination - source) * percentageToWaypoint);
|
}
|
||||||
|
|
||||||
if (dpWorld::IsLoaded()) {
|
if (dpWorld::IsLoaded()) {
|
||||||
approximation.y = dpWorld::GetNavMesh()->GetHeightAtPoint(approximation);
|
approximation.y = dpWorld::GetNavMesh()->GetHeightAtPoint(approximation);
|
||||||
@@ -198,6 +267,26 @@ bool MovementAIComponent::Warp(const NiPoint3& point) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::Pause() {
|
||||||
|
if (AtFinalWaypoint() || IsPaused()) return;
|
||||||
|
SetPosition(ApproximateLocation());
|
||||||
|
SetVelocity(NiPoint3Constant::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());
|
||||||
|
SetMaxSpeed(GetCurrentPathWaypointSpeed());
|
||||||
|
}
|
||||||
|
|
||||||
void MovementAIComponent::Stop() {
|
void MovementAIComponent::Stop() {
|
||||||
if (AtFinalWaypoint()) return;
|
if (AtFinalWaypoint()) return;
|
||||||
|
|
||||||
@@ -209,13 +298,15 @@ void MovementAIComponent::Stop() {
|
|||||||
m_TimeTravelled = 0;
|
m_TimeTravelled = 0;
|
||||||
|
|
||||||
m_AtFinalWaypoint = true;
|
m_AtFinalWaypoint = true;
|
||||||
|
m_IsPaused = true;
|
||||||
|
|
||||||
m_InterpolatedWaypoints.clear();
|
m_InterpolatedWaypoints.clear();
|
||||||
while (!m_CurrentPath.empty()) m_CurrentPath.pop();
|
m_CurrentPath.clear();
|
||||||
|
|
||||||
m_PathIndex = 0;
|
m_PathIndex = 0;
|
||||||
|
|
||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
|
m_CurrentPathWaypointIndex = 0;
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
@@ -227,13 +318,31 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
|||||||
m_PullPoint = point;
|
m_PullPoint = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
|
const NiPoint3& MovementAIComponent::GetCurrentPathWaypoint() const {
|
||||||
if (path.empty()) return;
|
if (m_CurrentPathWaypointIndex >= m_CurrentPath.size() || m_CurrentPathWaypointIndex < 0) {
|
||||||
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) {
|
return m_Parent->GetPosition();
|
||||||
this->m_CurrentPath.push(point);
|
}
|
||||||
});
|
return m_CurrentPath.at(m_CurrentPathWaypointIndex);
|
||||||
|
}
|
||||||
|
|
||||||
SetDestination(path.front());
|
void MovementAIComponent::SetPath(const std::vector<NiPoint3>& path, bool startInReverse) {
|
||||||
|
if (path.empty()) return;
|
||||||
|
m_CurrentPath = path;
|
||||||
|
m_IsInReverse = startInReverse;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
if (HasAttachedPathStart()) {
|
||||||
|
m_CurrentPathWaypointIndex = m_StartingWaypointIndex;
|
||||||
|
m_NextPathWaypointIndex = m_StartingWaypointIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
AdvancePathWaypointIndex();
|
||||||
|
SetDestination(GetCurrentPathWaypoint());
|
||||||
|
SetMaxSpeed(GetCurrentPathWaypointSpeed());
|
||||||
}
|
}
|
||||||
|
|
||||||
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
||||||
@@ -306,6 +415,9 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
|||||||
std::vector<NiPoint3> computedPath;
|
std::vector<NiPoint3> computedPath;
|
||||||
if (dpWorld::IsLoaded()) {
|
if (dpWorld::IsLoaded()) {
|
||||||
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
||||||
|
} else {
|
||||||
|
// If we do not have a navmesh, we do not want an AI to be going towards points that are far below or above the map.
|
||||||
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
// Somehow failed
|
// Somehow failed
|
||||||
@@ -319,8 +431,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
|||||||
auto step = delta / 10.0f;
|
auto step = delta / 10.0f;
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
// TODO: Replace this with += when the NiPoint3::operator+= is fixed
|
start += step;
|
||||||
start = start + step;
|
|
||||||
|
|
||||||
computedPath.push_back(start);
|
computedPath.push_back(start);
|
||||||
}
|
}
|
||||||
@@ -343,6 +454,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
|||||||
m_TimeToTravel = 0;
|
m_TimeToTravel = 0;
|
||||||
|
|
||||||
m_AtFinalWaypoint = false;
|
m_AtFinalWaypoint = false;
|
||||||
|
m_IsPaused = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetDestination() const {
|
NiPoint3 MovementAIComponent::GetDestination() const {
|
||||||
@@ -354,3 +466,253 @@ void MovementAIComponent::SetMaxSpeed(const float value) {
|
|||||||
m_MaxSpeed = value;
|
m_MaxSpeed = value;
|
||||||
m_Acceleration = value / 5;
|
m_Acceleration = value / 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointArrived(uint32_t commandIndex) {
|
||||||
|
m_Parent->TriggerEvent(eTriggerEventType::ARRIVED);
|
||||||
|
m_Parent->TriggerEvent(eTriggerEventType::ARRIVED_AT_DESIRED_WAYPOINT);
|
||||||
|
if (!m_Path || commandIndex >= m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).commands.size()) {
|
||||||
|
if (!AdvancePathWaypointIndex()) {
|
||||||
|
// We only want to handle path logic if we actually have a path setup for following
|
||||||
|
if (m_Path && !m_CurrentPath.empty()) {
|
||||||
|
if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
||||||
|
ReversePath();
|
||||||
|
} else if (m_Path->pathBehavior == PathBehavior::Loop) {
|
||||||
|
m_CurrentPathWaypointIndex = 0;
|
||||||
|
m_NextPathWaypointIndex = 0;
|
||||||
|
AdvancePathWaypointIndex();
|
||||||
|
SetDestination(GetCurrentPathWaypoint());
|
||||||
|
SetMaxSpeed(GetCurrentPathWaypointSpeed());
|
||||||
|
} else {
|
||||||
|
Stop();
|
||||||
|
m_Parent->TriggerEvent(eTriggerEventType::ARRIVED_AT_END_OF_PATH);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SetDestination(GetCurrentPathWaypoint());
|
||||||
|
SetMaxSpeed(GetCurrentPathWaypointSpeed());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!IsPaused()) Pause();
|
||||||
|
const auto& data = m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).commands.at(commandIndex).data;
|
||||||
|
const auto& command = m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).commands.at(commandIndex).command;
|
||||||
|
float delay = 0.0f;
|
||||||
|
switch (command) {
|
||||||
|
case eWaypointCommandType::STOP:
|
||||||
|
Stop();
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::GROUP_EMOTE:
|
||||||
|
delay = HandleWaypointCommandGroupEmote(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::SET_VARIABLE:
|
||||||
|
HandleWaypointCommandSetVariable(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::CAST_SKILL:
|
||||||
|
HandleWaypointCommandCastSkill(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::EQUIP_INVENTORY:
|
||||||
|
HandleWaypointCommandEquipInventory(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::UNEQUIP_INVENTORY:
|
||||||
|
HandleWaypointCommandUnequipInventory(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::DELAY:
|
||||||
|
delay = HandleWaypointCommandDelay(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::EMOTE:
|
||||||
|
delay = RenderComponent::PlayAnimation(m_Parent, data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::TELEPORT:
|
||||||
|
HandleWaypointCommandTeleport(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::PATH_SPEED:
|
||||||
|
HandleWaypointCommandPathSpeed(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::REMOVE_NPC:
|
||||||
|
HandleWaypointCommandRemoveNPC(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::CHANGE_WAYPOINT:
|
||||||
|
HandleWaypointCommandChangeWaypoint(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::KILL_SELF:
|
||||||
|
m_Parent->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::DELETE_SELF:
|
||||||
|
m_Parent->Kill();
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::SPAWN_OBJECT:
|
||||||
|
HandleWaypointCommandSpawnObject(data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::PLAY_SOUND:
|
||||||
|
GameMessages::SendPlayNDAudioEmitter(m_Parent, UNASSIGNED_SYSTEM_ADDRESS, data);
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::BOUNCE:
|
||||||
|
LOG("Unable to process bounce waypoint command server side!");
|
||||||
|
break;
|
||||||
|
case eWaypointCommandType::INVALID:
|
||||||
|
default:
|
||||||
|
LOG("Got invalid waypoint command %i", command);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Parent->AddCallbackTimer(delay, [this, commandIndex]() {
|
||||||
|
this->HandleWaypointArrived(commandIndex + 1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
float MovementAIComponent::HandleWaypointCommandGroupEmote(const std::string& data) {
|
||||||
|
const auto& split = GeneralUtils::SplitString(data, ';');
|
||||||
|
if (split.size() != 2) return 0.0f;
|
||||||
|
const auto& entities = Game::entityManager->GetEntitiesInGroup(split.at(0));
|
||||||
|
float delay = 0.0f;
|
||||||
|
for (auto& entity : entities) {
|
||||||
|
delay = RenderComponent::PlayAnimation(entity, split.at(1));
|
||||||
|
}
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandSetVariable(const std::string& data) {
|
||||||
|
const auto& split = GeneralUtils::SplitString(data, ',');
|
||||||
|
m_Parent->SetNetworkVar(GeneralUtils::ASCIIToUTF16(split.at(0)), split.at(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandCastSkill(const std::string& data) {
|
||||||
|
if (data.empty()) return;
|
||||||
|
auto* skillComponent = m_Parent->GetComponent<SkillComponent>();
|
||||||
|
if (!skillComponent) {
|
||||||
|
LOG("Skill component not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto skillId = GeneralUtils::TryParse<uint32_t>(data);
|
||||||
|
if (skillId && skillId != 0) skillComponent->CastSkill(skillId.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandEquipInventory(const std::string& data) {
|
||||||
|
if (data.empty()) return;
|
||||||
|
auto* inventoryComponent = m_Parent->GetComponent<InventoryComponent>();
|
||||||
|
if (!inventoryComponent) {
|
||||||
|
LOG("Inventory component not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// the client says use slot 0 of items
|
||||||
|
const auto inventory = inventoryComponent->GetInventory(eInventoryType::ITEMS);
|
||||||
|
if (!inventory) return;
|
||||||
|
const auto slots = inventory->GetSlots();
|
||||||
|
const auto item = slots.find(0);
|
||||||
|
if (item != slots.end()) inventoryComponent->EquipItem(item->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandUnequipInventory(const std::string& data) {
|
||||||
|
if (data.empty()) return;
|
||||||
|
auto* inventoryComponent = m_Parent->GetComponent<InventoryComponent>();
|
||||||
|
if (!inventoryComponent) {
|
||||||
|
LOG("Inventory component not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// the client says use slot 0 of items
|
||||||
|
const auto inventory = inventoryComponent->GetInventory(eInventoryType::ITEMS);
|
||||||
|
if (!inventory) return;
|
||||||
|
const auto slots = inventory->GetSlots();
|
||||||
|
const auto item = slots.find(0);
|
||||||
|
if (item != slots.end()) inventoryComponent->UnEquipItem(item->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
float MovementAIComponent::HandleWaypointCommandDelay(const std::string& data) {
|
||||||
|
auto delay = GeneralUtils::TryParse<float>(data);
|
||||||
|
if (!delay) {
|
||||||
|
LOG("Failed to parse delay %s", data.c_str());
|
||||||
|
}
|
||||||
|
return delay.value_or(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandTeleport(const std::string& data) {
|
||||||
|
auto posString = GeneralUtils::SplitString(data, ',');
|
||||||
|
if (posString.size() == 0) return;
|
||||||
|
auto newPos = NiPoint3();
|
||||||
|
std::optional<float> intermediate;
|
||||||
|
if (posString.size() >= 1) {
|
||||||
|
intermediate = GeneralUtils::TryParse<float>(posString.at(0));
|
||||||
|
if (!intermediate) return;
|
||||||
|
|
||||||
|
newPos.x = intermediate.value();
|
||||||
|
if (posString.size() >= 2) {
|
||||||
|
intermediate = GeneralUtils::TryParse<float>(posString.at(1));
|
||||||
|
if (!intermediate) return;
|
||||||
|
|
||||||
|
newPos.y = intermediate.value();
|
||||||
|
if (posString.size() >= 3) {
|
||||||
|
intermediate = GeneralUtils::TryParse<float>(posString.at(2));
|
||||||
|
if (!intermediate) return;
|
||||||
|
|
||||||
|
newPos.z = intermediate.value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameMessages::SendTeleport(m_Parent->GetObjectID(), newPos, NiQuaternionConstant::IDENTITY, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandPathSpeed(const std::string& data) {
|
||||||
|
auto speed = GeneralUtils::TryParse<float>(data);
|
||||||
|
if (!speed) return;
|
||||||
|
SetMaxSpeed(speed.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandRemoveNPC(const std::string& data) {
|
||||||
|
if (data.empty()) return;
|
||||||
|
auto* proximityMonitorComponent = m_Parent->GetComponent<ProximityMonitorComponent>();
|
||||||
|
if (!proximityMonitorComponent) {
|
||||||
|
LOG("Proximity monitor component not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto foundObjs = proximityMonitorComponent->GetProximityObjects("KillOBJS");
|
||||||
|
for (auto& [objid, phyEntity] : foundObjs) {
|
||||||
|
auto entity = Game::entityManager->GetEntity(objid);
|
||||||
|
if (!entity) return;
|
||||||
|
auto* destroyableComponent = m_Parent->GetComponent<DestroyableComponent>();
|
||||||
|
if (!destroyableComponent) {
|
||||||
|
LOG("Destroyable component not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int32_t factionID = -1;
|
||||||
|
auto parsed = GeneralUtils::TryParse<uint32_t>(data);
|
||||||
|
if (!parsed) return;
|
||||||
|
factionID = parsed.value();
|
||||||
|
if (destroyableComponent->BelongsToFaction(factionID)) m_Parent->Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandChangeWaypoint(const std::string& data) {
|
||||||
|
std::string path_string = "";
|
||||||
|
int32_t index = 0;
|
||||||
|
// sometimes there's a path and what waypoint to start, which are comma separated
|
||||||
|
if (data.find(",") != std::string::npos) {
|
||||||
|
auto datas = GeneralUtils::SplitString(data, ',');
|
||||||
|
path_string = datas.at(0);
|
||||||
|
auto parsed = GeneralUtils::TryParse<int32_t>(datas.at(1));
|
||||||
|
if (!parsed) return;
|
||||||
|
index = parsed.value();
|
||||||
|
} else path_string = data;
|
||||||
|
|
||||||
|
if (path_string != "") {
|
||||||
|
SetPathStartingWaypointIndex(index);
|
||||||
|
SetupPath(path_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::HandleWaypointCommandSpawnObject(const std::string& data) {
|
||||||
|
LOT newObjectLOT = 0;
|
||||||
|
auto parsed = GeneralUtils::TryParse<LOT>(data);
|
||||||
|
if (!parsed) return;
|
||||||
|
newObjectLOT = parsed.value();
|
||||||
|
EntityInfo info{};
|
||||||
|
info.lot = newObjectLOT;
|
||||||
|
info.pos = m_Parent->GetPosition();
|
||||||
|
info.rot = m_Parent->GetRotation();
|
||||||
|
auto* spawnedEntity = Game::entityManager->CreateEntity(info, nullptr, m_Parent);
|
||||||
|
Game::entityManager->ConstructEntity(spawnedEntity);
|
||||||
|
m_Parent->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
class ControllablePhysicsComponent;
|
class ControllablePhysicsComponent;
|
||||||
class BaseCombatAIComponent;
|
class BaseCombatAIComponent;
|
||||||
|
class Path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -53,7 +54,7 @@ struct MovementAIInfo {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that handles the movement settings of an entity. Not to be confused with the BaseCombatAI component that
|
* Component that handles the movement settings of an entity. Not to be confused with the BaseCombatAI component that
|
||||||
* actually handles attackig and following enemy entities.
|
* actually handles attacking and following enemy entities.
|
||||||
*/
|
*/
|
||||||
class MovementAIComponent final : public Component {
|
class MovementAIComponent final : public Component {
|
||||||
public:
|
public:
|
||||||
@@ -153,6 +154,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
NiPoint3 GetNextWaypoint() const { return m_NextWaypoint; }
|
NiPoint3 GetNextWaypoint() const { return m_NextWaypoint; }
|
||||||
|
|
||||||
|
NiPoint3 GetNextPathWaypoint() const {
|
||||||
|
if (m_CurrentPath.empty()) return GetNextWaypoint();
|
||||||
|
if (m_IsInReverse) {
|
||||||
|
return m_CurrentPathWaypointIndex - 1 < 0 ?
|
||||||
|
m_CurrentPath.front() :
|
||||||
|
m_CurrentPath.at(m_CurrentPathWaypointIndex - 1);
|
||||||
|
} else {
|
||||||
|
return m_CurrentPathWaypointIndex + 1 >= m_CurrentPath.size() ?
|
||||||
|
m_CurrentPath.back() :
|
||||||
|
m_CurrentPath.at(m_CurrentPathWaypointIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the approximate current location of the entity, including y coordinates
|
* Returns the approximate current location of the entity, including y coordinates
|
||||||
* @return the approximate current location of the entity
|
* @return the approximate current location of the entity
|
||||||
@@ -173,11 +187,32 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool AtFinalWaypoint() const { return m_AtFinalWaypoint; }
|
bool AtFinalWaypoint() const { return m_AtFinalWaypoint; }
|
||||||
|
|
||||||
|
bool IsPaused() const { return m_IsPaused; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pauses the current pathing of this entity. The current path waypoint will be saved for resuming later.
|
||||||
|
*/
|
||||||
|
void Pause();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resumes pathing from the current position to the destination that was set
|
||||||
|
* when the entity was paused.
|
||||||
|
*/
|
||||||
|
void Resume();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the entity stationary
|
* Renders the entity stationary
|
||||||
*/
|
*/
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
void ReversePath();
|
||||||
|
|
||||||
|
void HandleWaypointArrived(uint32_t commandIndex);
|
||||||
|
|
||||||
|
void SetupPath(const std::string& pathname);
|
||||||
|
|
||||||
|
float GetCurrentPathWaypointSpeed() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops the current movement and moves the entity to a certain point. Will continue until it's close enough,
|
* Stops the current movement and moves the entity to a certain point. Will continue until it's close enough,
|
||||||
* after which its AI is enabled again.
|
* after which its AI is enabled again.
|
||||||
@@ -189,7 +224,16 @@ public:
|
|||||||
* Sets a path to follow for the AI
|
* Sets a path to follow for the AI
|
||||||
* @param path the path to follow
|
* @param path the path to follow
|
||||||
*/
|
*/
|
||||||
void SetPath(std::vector<NiPoint3> path);
|
void SetPath(const std::vector<NiPoint3>& path, bool startsInReverse = false);
|
||||||
|
|
||||||
|
// Advance the path waypoint index and return if there is a next waypoint
|
||||||
|
bool AdvancePathWaypointIndex();
|
||||||
|
|
||||||
|
const NiPoint3& GetCurrentPathWaypoint() const;
|
||||||
|
|
||||||
|
void SetPathStartingWaypointIndex(int32_t value) { m_StartingWaypointIndex = value; }
|
||||||
|
|
||||||
|
bool HasAttachedPathStart() const { return m_StartingWaypointIndex != -1; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base speed from the DB for a given LOT
|
* Returns the base speed from the DB for a given LOT
|
||||||
@@ -198,7 +242,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
static float GetBaseSpeed(LOT lot);
|
static float GetBaseSpeed(LOT lot);
|
||||||
|
|
||||||
|
const bool GetIsInReverse(){ return m_IsInReverse; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
float HandleWaypointCommandGroupEmote(const std::string& data);
|
||||||
|
void HandleWaypointCommandSetVariable(const std::string& data);
|
||||||
|
void HandleWaypointCommandCastSkill(const std::string& data);
|
||||||
|
void HandleWaypointCommandEquipInventory(const std::string& data);
|
||||||
|
void HandleWaypointCommandUnequipInventory(const std::string& data);
|
||||||
|
float HandleWaypointCommandDelay(const std::string& data);
|
||||||
|
void HandleWaypointCommandTeleport(const std::string& data);
|
||||||
|
void HandleWaypointCommandPathSpeed(const std::string& data);
|
||||||
|
void HandleWaypointCommandRemoveNPC(const std::string& data);
|
||||||
|
void HandleWaypointCommandChangeWaypoint(const std::string& data);
|
||||||
|
void HandleWaypointCommandSpawnObject(const std::string& data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current position of the entity
|
* Sets the current position of the entity
|
||||||
@@ -241,7 +298,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The path this entity is currently traversing
|
* The path this entity is currently traversing
|
||||||
*/
|
*/
|
||||||
uint32_t m_PathIndex;
|
int32_t m_PathIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the entity has reached it last waypoint
|
* If the entity has reached it last waypoint
|
||||||
@@ -301,7 +358,37 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The path from the current position to the destination.
|
* The path from the current position to the destination.
|
||||||
*/
|
*/
|
||||||
std::stack<NiPoint3> m_CurrentPath;
|
std::vector<NiPoint3> m_CurrentPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of the current waypoint in the path
|
||||||
|
*/
|
||||||
|
int32_t m_CurrentPathWaypointIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index of the next waypoint in the path
|
||||||
|
*/
|
||||||
|
int32_t m_NextPathWaypointIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the path is being read in reverse
|
||||||
|
*/
|
||||||
|
bool m_IsInReverse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the current movement via pathing is paused.
|
||||||
|
*/
|
||||||
|
bool m_IsPaused;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The optional path this component will follow.
|
||||||
|
*/
|
||||||
|
const Path* m_Path = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The starting index for the provided path
|
||||||
|
*/
|
||||||
|
int32_t m_StartingWaypointIndex = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOVEMENTAICOMPONENT_H
|
#endif // MOVEMENTAICOMPONENT_H
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ bool ProximityMonitorComponent::IsInProximity(const std::string& name, LWOOBJID
|
|||||||
void ProximityMonitorComponent::Update(float deltaTime) {
|
void ProximityMonitorComponent::Update(float deltaTime) {
|
||||||
for (const auto& prox : m_ProximitiesData) {
|
for (const auto& prox : m_ProximitiesData) {
|
||||||
if (!prox.second) continue;
|
if (!prox.second) continue;
|
||||||
|
prox.second->SetPosition(m_Parent->GetPosition());
|
||||||
//Process enter events
|
//Process enter events
|
||||||
for (auto* en : prox.second->GetNewObjects()) {
|
for (auto* en : prox.second->GetNewObjects()) {
|
||||||
m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER");
|
m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER");
|
||||||
|
|||||||
Reference in New Issue
Block a user