mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-05-23 15:22:28 +00:00
WIP refactor into movment AI
So that combat behavior isn't fighting pathing
This commit is contained in:
parent
e70e2025a8
commit
e5233d5ce7
@ -317,18 +317,6 @@ void Entity::Initialize() {
|
|||||||
m_Components.insert(std::make_pair(COMPONENT_TYPE_SOUND_TRIGGER, comp));
|
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:
|
//Also check for the collectible id:
|
||||||
m_CollectibleID = GetVarAs<int32_t>(u"collectible_id");
|
m_CollectibleID = GetVarAs<int32_t>(u"collectible_id");
|
||||||
|
|
||||||
@ -699,6 +687,38 @@ void Entity::Initialize() {
|
|||||||
m_Components.insert(std::make_pair(COMPONENT_TYPE_MOVEMENT_AI, new MovementAIComponent(this, moveInfo)));
|
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<Path*>(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<MovementAIComponent>();
|
||||||
|
if (movementAIcomp) movementAIcomp->SetPath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_PROXIMITY_MONITOR);
|
int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, COMPONENT_TYPE_PROXIMITY_MONITOR);
|
||||||
if (proximityMonitorID > 0) {
|
if (proximityMonitorID > 0) {
|
||||||
CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance()->GetTable<CDProximityMonitorComponentTable>("ProximityMonitorComponent");
|
CDProximityMonitorComponentTable* proxCompTable = CDClientManager::Instance()->GetTable<CDProximityMonitorComponentTable>("ProximityMonitorComponent");
|
||||||
|
@ -33,11 +33,6 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Com
|
|||||||
m_PickupRadius = 0.0f;
|
m_PickupRadius = 0.0f;
|
||||||
m_DirtyPickupRadiusScale = true;
|
m_DirtyPickupRadiusScale = true;
|
||||||
m_IsTeleporting = false;
|
m_IsTeleporting = false;
|
||||||
m_AttachedPath = entity->GetVarAsString(u"attached_path");
|
|
||||||
m_PathWaypoint = entity->GetVarAs<int>(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
|
if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI
|
||||||
return;
|
return;
|
||||||
@ -59,96 +54,6 @@ ControllablePhysicsComponent::~ControllablePhysicsComponent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::Update(float deltaTime) {
|
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) {
|
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);
|
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<CDComponentsRegistryTable>("ComponentsRegistry");
|
|
||||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance()->GetTable<CDPhysicsComponentTable>("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;
|
|
||||||
}
|
|
||||||
|
@ -257,43 +257,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::vector<float> GetActivePickupRadiusScales() { return m_ActivePickupRadiusScales; };
|
std::vector<float> 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:
|
private:
|
||||||
/**
|
/**
|
||||||
* The entity that owns this component
|
* The entity that owns this component
|
||||||
@ -410,36 +373,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool m_IsTeleporting;
|
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
|
#endif // CONTROLLABLEPHYSICSCOMPONENT_H
|
||||||
|
@ -9,12 +9,13 @@
|
|||||||
#include "dpWorld.h"
|
#include "dpWorld.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
#include "SimplePhysicsComponent.h"
|
#include "SimplePhysicsComponent.h"
|
||||||
|
#include "dZoneManager.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, MovementAIInfo info) : Component(parent) {
|
||||||
m_Info = std::move(info);
|
m_Info = std::move(info);
|
||||||
m_Done = true;
|
m_Done = false;
|
||||||
|
|
||||||
m_BaseCombatAI = nullptr;
|
m_BaseCombatAI = nullptr;
|
||||||
|
|
||||||
@ -32,18 +33,30 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
|||||||
m_Interrupted = false;
|
m_Interrupted = false;
|
||||||
m_PullPoint = {};
|
m_PullPoint = {};
|
||||||
m_HaltDistance = 0;
|
m_HaltDistance = 0;
|
||||||
m_Timer = 0;
|
|
||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
m_Speed = 0;
|
m_Speed = 0;
|
||||||
|
m_WaypointPathSpeed = 1.0f;
|
||||||
|
|
||||||
|
|
||||||
m_TotalTime = 0;
|
m_TotalTime = 0;
|
||||||
|
m_Timer = 0;
|
||||||
|
|
||||||
m_LockRotation = false;
|
m_LockRotation = false;
|
||||||
|
|
||||||
|
m_WaypointPathIndex = parent->GetVarAs<int>(u"attached_path_start");
|
||||||
|
|
||||||
|
|
||||||
|
m_NavPathIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
MovementAIComponent::~MovementAIComponent() = default;
|
MovementAIComponent::~MovementAIComponent() = default;
|
||||||
|
|
||||||
void MovementAIComponent::Update(const float deltaTime) {
|
void MovementAIComponent::Update(const float deltaTime) {
|
||||||
|
|
||||||
|
// pull to point update take priority
|
||||||
if (m_Interrupted) {
|
if (m_Interrupted) {
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentPosition();
|
||||||
|
|
||||||
const auto speed = deltaTime * 2.5f;
|
const auto speed = deltaTime * 2.5f;
|
||||||
|
|
||||||
@ -62,112 +75,255 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AtFinalWaypoint()) // Are we done?
|
// Navmesh pathing logic
|
||||||
{
|
if (!m_Queue.empty()) {
|
||||||
|
PullToPoint(m_Queue.top());
|
||||||
|
|
||||||
|
m_Queue.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_HaltDistance > 0) {
|
// waypoint pathing logic
|
||||||
if (Vector3::DistanceSquared(ApproximateLocation(), GetDestination()) < m_HaltDistance * m_HaltDistance) // Prevent us from hugging the target
|
if (m_CurrentPath){
|
||||||
{
|
if (!m_Done && !m_Waiting){
|
||||||
Stop();
|
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 {
|
const MovementAIInfo& MovementAIComponent::GetInfo() const {
|
||||||
return m_Info;
|
return m_Info;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MovementAIComponent::AdvanceWaypointIndex() {
|
void MovementAIComponent::ArrivedAtPathWaypoint(){
|
||||||
if (m_PathIndex >= m_CurrentPath.size()) {
|
// TODO: Call scripts here
|
||||||
return false;
|
|
||||||
|
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: <path to change to>,<waypoint to use> 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<Path*>(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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MovementAIComponent::AdvanceNavWaypointIndex() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
||||||
if (m_PathIndex >= m_CurrentPath.size()) {
|
if (m_PathIndex >= m_CurrentPath->pathWaypoints.size()) {
|
||||||
return GetCurrentPosition();
|
return GetCurrentPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_CurrentPath[m_PathIndex];
|
return m_CurrentPath->pathWaypoints[m_PathIndex].position;
|
||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetNextWaypoint() const {
|
NiPoint3 MovementAIComponent::GetNextWaypoint() const {
|
||||||
@ -178,6 +334,7 @@ NiPoint3 MovementAIComponent::GetCurrentPosition() const {
|
|||||||
return m_Parent->GetPosition();
|
return m_Parent->GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get's the approximate location where the entity should be on the path
|
||||||
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
||||||
auto source = GetCurrentPosition();
|
auto source = GetCurrentPosition();
|
||||||
|
|
||||||
@ -235,7 +392,8 @@ void MovementAIComponent::Stop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetPosition(ApproximateLocation());
|
// SetPosition(ApproximateLocation());
|
||||||
|
SetPosition(GetCurrentPosition());
|
||||||
|
|
||||||
SetVelocity(NiPoint3::ZERO);
|
SetVelocity(NiPoint3::ZERO);
|
||||||
|
|
||||||
@ -243,10 +401,6 @@ void MovementAIComponent::Stop() {
|
|||||||
|
|
||||||
m_Done = true;
|
m_Done = true;
|
||||||
|
|
||||||
m_CurrentPath = {};
|
|
||||||
|
|
||||||
m_PathIndex = 0;
|
|
||||||
|
|
||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||||
@ -259,18 +413,6 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
|||||||
m_PullPoint = point;
|
m_PullPoint = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetPath(std::vector<NiPoint3> 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) {
|
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
||||||
// Check if the lot is in the cache
|
// Check if the lot is in the cache
|
||||||
const auto& it = m_PhysicsSpeedCache.find(lot);
|
const auto& it = m_PhysicsSpeedCache.find(lot);
|
||||||
@ -409,9 +551,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentPath.clear();
|
m_Queue.push(location);
|
||||||
|
|
||||||
m_CurrentPath.push_back(location);
|
|
||||||
|
|
||||||
// Simply path
|
// Simply path
|
||||||
for (auto point : computedPath) {
|
for (auto point : computedPath) {
|
||||||
@ -419,10 +559,10 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) {
|
|||||||
point.y = dpWorld::Instance().GetNavMesh()->GetHeightAtPoint(point);
|
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;
|
m_PathIndex = 0;
|
||||||
|
|
||||||
@ -432,11 +572,11 @@ void MovementAIComponent::SetDestination(const NiPoint3& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::GetDestination() const {
|
NiPoint3 MovementAIComponent::GetDestination() const {
|
||||||
if (m_CurrentPath.empty()) {
|
if (!m_CurrentPath) {
|
||||||
return GetCurrentPosition();
|
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) {
|
void MovementAIComponent::SetSpeed(const float value) {
|
||||||
|
@ -145,7 +145,11 @@ public:
|
|||||||
* Attempts to update the waypoint index, making the entity move to the next waypoint
|
* 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
|
* @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
|
* Returns the waypoint the entity is currently moving towards
|
||||||
@ -207,7 +211,7 @@ 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(Path* path) {if (path) {m_CurrentPath = path; m_Done = false; m_Timer = 0;};};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base speed from the DB for a given LOT
|
* Returns the base speed from the DB for a given LOT
|
||||||
@ -216,6 +220,36 @@ public:
|
|||||||
*/
|
*/
|
||||||
static float GetBaseSpeed(LOT lot);
|
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:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,7 +348,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The path the entity is currently following
|
* The path the entity is currently following
|
||||||
*/
|
*/
|
||||||
std::vector<NiPoint3> m_CurrentPath;
|
Path* m_CurrentPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue of positions to traverse
|
* Queue of positions to traverse
|
||||||
@ -325,6 +359,32 @@ 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
#endif // MOVEMENTAICOMPONENT_H
|
||||||
|
@ -124,8 +124,6 @@ void ActivityManager::ActivityTimerStart(Entity* self, const std::string& timerN
|
|||||||
auto* timer = new ActivityTimer{ timerName, updateInterval, stopTime };
|
auto* timer = new ActivityTimer{ timerName, updateInterval, stopTime };
|
||||||
activeTimers.push_back(timer);
|
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);
|
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.erase(std::remove(activeTimers.begin(), activeTimers.end(), timer),
|
||||||
activeTimers.end());
|
activeTimers.end());
|
||||||
delete timer;
|
delete timer;
|
||||||
Game::logger->Log("ActivityManager", "Executing timer '%s'", activityTimerName.c_str());
|
|
||||||
OnActivityTimerDone(self, activityTimerName);
|
OnActivityTimerDone(self, activityTimerName);
|
||||||
} else {
|
} else {
|
||||||
Game::logger->Log("ActivityManager", "Updating timer '%s'", activityTimerName.c_str());
|
|
||||||
OnActivityTimerUpdate(self, timer->name, timer->stopTime - timer->runTime, timer->runTime);
|
OnActivityTimerUpdate(self, timer->name, timer->stopTime - timer->runTime, timer->runTime);
|
||||||
self->AddTimer(GetPrefixedName(timer->name), timer->updateInterval);
|
self->AddTimer(GetPrefixedName(timer->name), timer->updateInterval);
|
||||||
}
|
}
|
||||||
|
@ -60,8 +60,6 @@ void BossSpiderQueenEnemyServer::OnDie(Entity* self, Entity* killer) {
|
|||||||
missionComponent->CompleteMission(instanceMissionID);
|
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?
|
// There is suppose to be a 0.1 second delay here but that may be admitted?
|
||||||
auto* controller = EntityManager::Instance()->GetZoneControlEntity();
|
auto* controller = EntityManager::Instance()->GetZoneControlEntity();
|
||||||
|
|
||||||
|
@ -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());
|
Game::logger->Log("SGCannon", "Spawning enemy %i on path %s", toSpawn.lot, path->pathName.c_str());
|
||||||
|
|
||||||
auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self);
|
auto* enemy = EntityManager::Instance()->CreateEntity(info, nullptr, self);
|
||||||
EntityManager::Instance()->ConstructEntity(enemy);
|
if (enemy) {
|
||||||
|
EntityManager::Instance()->ConstructEntity(enemy);
|
||||||
|
auto* movementAI = enemy->GetComponent<MovementAIComponent>();
|
||||||
|
|
||||||
if (true) {
|
if (!movementAI) return;
|
||||||
auto* movementAI = new MovementAIComponent(enemy, {});
|
|
||||||
|
|
||||||
enemy->AddComponent(COMPONENT_TYPE_MOVEMENT_AI, movementAI);
|
|
||||||
|
|
||||||
movementAI->SetSpeed(toSpawn.initialSpeed);
|
movementAI->SetSpeed(toSpawn.initialSpeed);
|
||||||
movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
|
movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
|
||||||
movementAI->SetHaltDistance(0.0f);
|
movementAI->SetHaltDistance(0.0f);
|
||||||
|
|
||||||
std::vector<NiPoint3> pathWaypoints;
|
|
||||||
|
|
||||||
for (const auto& waypoint : path->pathWaypoints) {
|
|
||||||
pathWaypoints.push_back(waypoint.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) {
|
|
||||||
std::reverse(pathWaypoints.begin(), pathWaypoints.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
movementAI->SetPath(pathWaypoints);
|
|
||||||
|
|
||||||
enemy->AddDieCallback([this, self, enemy, name]() {
|
enemy->AddDieCallback([this, self, enemy, name]() {
|
||||||
RegisterHit(self, enemy, name);
|
RegisterHit(self, enemy, name);
|
||||||
});
|
}
|
||||||
}
|
);
|
||||||
|
|
||||||
// Save the enemy and tell it to start pathing
|
// Save the enemy
|
||||||
if (enemy != nullptr) {
|
|
||||||
const_cast<std::vector<LWOOBJID>&>(self->GetVar<std::vector<LWOOBJID>>(SpawnedObjects)).push_back(enemy->GetObjectID());
|
const_cast<std::vector<LWOOBJID>&>(self->GetVar<std::vector<LWOOBJID>>(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<MovingPlatformComponent>();
|
||||||
|
if (movingPlatformComponent) GameMessages::SendPlatformResync(enemy, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (name == EndGameBufferTimer) {
|
} else if (name == EndGameBufferTimer) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user