feat: add further MovementAI skeleton (#1499)

* add movement ai skeleton

Zone loading code is tested to load and read the correct values using logs.  other ldf data is unaffected as I walked around crux and dragons/apes can still spawn and be killed.

* format
This commit is contained in:
David Markowitz 2024-03-08 17:29:01 -08:00 committed by GitHub
parent 3a6313a3ba
commit 4bc4624bc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 271 additions and 129 deletions

View File

@ -0,0 +1,59 @@
#ifndef __EWAYPOINTCOMMANDTYPES__H__
#define __EWAYPOINTCOMMANDTYPES__H__
#include <cstdint>
enum class eWaypointCommandType : uint32_t {
INVALID,
BOUNCE,
STOP,
GROUP_EMOTE,
SET_VARIABLE,
CAST_SKILL,
EQUIP_INVENTORY,
UNEQUIP_INVENTORY,
DELAY,
EMOTE,
TELEPORT,
PATH_SPEED,
REMOVE_NPC,
CHANGE_WAYPOINT,
DELETE_SELF,
KILL_SELF,
SPAWN_OBJECT,
PLAY_SOUND,
};
class WaypointCommandType {
public:
static eWaypointCommandType StringToWaypointCommandType(std::string commandString) {
const std::map<std::string, eWaypointCommandType> WaypointCommandTypeMap = {
{"bounce", eWaypointCommandType::BOUNCE},
{"stop", eWaypointCommandType::STOP},
{"groupemote", eWaypointCommandType::GROUP_EMOTE},
{"setvar", eWaypointCommandType::SET_VARIABLE},
{"castskill", eWaypointCommandType::CAST_SKILL},
{"eqInvent", eWaypointCommandType::EQUIP_INVENTORY},
{"unInvent", eWaypointCommandType::UNEQUIP_INVENTORY},
{"delay", eWaypointCommandType::DELAY},
{"femote", eWaypointCommandType::EMOTE},
{"emote", eWaypointCommandType::EMOTE},
{"teleport", eWaypointCommandType::TELEPORT},
{"pathspeed", eWaypointCommandType::PATH_SPEED},
{"removeNPC", eWaypointCommandType::REMOVE_NPC},
{"changeWP", eWaypointCommandType::CHANGE_WAYPOINT},
{"DeleteSelf", eWaypointCommandType::DELETE_SELF},
{"killself", eWaypointCommandType::KILL_SELF},
{"removeself", eWaypointCommandType::DELETE_SELF},
{"spawnOBJ", eWaypointCommandType::SPAWN_OBJECT},
{"playSound", eWaypointCommandType::PLAY_SOUND},
};
auto intermed = WaypointCommandTypeMap.find(commandString);
return (intermed != WaypointCommandTypeMap.end()) ? intermed->second : eWaypointCommandType::INVALID;
};
};
#endif //!__EWAYPOINTCOMMANDTYPES__H__

View File

@ -15,8 +15,9 @@
#include "PlayerManager.h" #include "PlayerManager.h"
#include "Game.h" #include "Game.h"
#include "EntityManager.h" #include "EntityManager.h"
#include "MovementAIComponent.h"
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo): Component(parent) { TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo) : Component(parent) {
m_Parent = parent; m_Parent = parent;
m_Trigger = nullptr; m_Trigger = nullptr;
@ -43,7 +44,7 @@ void TriggerComponent::TriggerEvent(eTriggerEventType event, Entity* optionalTar
} }
void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) { void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) {
auto argArray = GeneralUtils::SplitString(command->args, ','); auto argArray = GeneralUtils::SplitString(command->args, ',');
// determine targets // determine targets
std::vector<Entity*> targetEntities = GatherTargets(command, optionalTarget); std::vector<Entity*> targetEntities = GatherTargets(command, optionalTarget);
@ -55,107 +56,119 @@ void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity
if (!targetEntity) continue; if (!targetEntity) continue;
switch (command->id) { switch (command->id) {
case eTriggerCommandType::ZONE_PLAYER: break; case eTriggerCommandType::ZONE_PLAYER: break;
case eTriggerCommandType::FIRE_EVENT: case eTriggerCommandType::FIRE_EVENT:
HandleFireEvent(targetEntity, command->args); HandleFireEvent(targetEntity, command->args);
break; break;
case eTriggerCommandType::DESTROY_OBJ: case eTriggerCommandType::DESTROY_OBJ:
HandleDestroyObject(targetEntity, command->args); HandleDestroyObject(targetEntity, command->args);
break; break;
case eTriggerCommandType::TOGGLE_TRIGGER: case eTriggerCommandType::TOGGLE_TRIGGER:
HandleToggleTrigger(targetEntity, command->args); HandleToggleTrigger(targetEntity, command->args);
break; break;
case eTriggerCommandType::RESET_REBUILD: case eTriggerCommandType::RESET_REBUILD:
HandleResetRebuild(targetEntity, command->args); HandleResetRebuild(targetEntity, command->args);
break; break;
case eTriggerCommandType::SET_PATH: break; case eTriggerCommandType::SET_PATH:
case eTriggerCommandType::SET_PICK_TYPE: break; HandleSetPath(targetEntity, argArray);
case eTriggerCommandType::MOVE_OBJECT: break;
HandleMoveObject(targetEntity, argArray); case eTriggerCommandType::SET_PICK_TYPE: break;
break; case eTriggerCommandType::MOVE_OBJECT:
case eTriggerCommandType::ROTATE_OBJECT: HandleMoveObject(targetEntity, argArray);
HandleRotateObject(targetEntity, argArray); break;
break; case eTriggerCommandType::ROTATE_OBJECT:
case eTriggerCommandType::PUSH_OBJECT: HandleRotateObject(targetEntity, argArray);
HandlePushObject(targetEntity, argArray); break;
break; case eTriggerCommandType::PUSH_OBJECT:
case eTriggerCommandType::REPEL_OBJECT: HandlePushObject(targetEntity, argArray);
HandleRepelObject(targetEntity, command->args); break;
break; case eTriggerCommandType::REPEL_OBJECT:
case eTriggerCommandType::SET_TIMER: HandleRepelObject(targetEntity, command->args);
HandleSetTimer(targetEntity, argArray); break;
break; case eTriggerCommandType::SET_TIMER:
case eTriggerCommandType::CANCEL_TIMER: HandleSetTimer(targetEntity, argArray);
HandleCancelTimer(targetEntity, command->args); break;
break; case eTriggerCommandType::CANCEL_TIMER:
case eTriggerCommandType::PLAY_CINEMATIC: HandleCancelTimer(targetEntity, command->args);
HandlePlayCinematic(targetEntity, argArray); break;
break; case eTriggerCommandType::PLAY_CINEMATIC:
case eTriggerCommandType::TOGGLE_BBB: HandlePlayCinematic(targetEntity, argArray);
HandleToggleBBB(targetEntity, command->args); break;
break; case eTriggerCommandType::TOGGLE_BBB:
case eTriggerCommandType::UPDATE_MISSION: HandleToggleBBB(targetEntity, command->args);
HandleUpdateMission(targetEntity, argArray); break;
break; case eTriggerCommandType::UPDATE_MISSION:
case eTriggerCommandType::SET_BOUNCER_STATE: break; HandleUpdateMission(targetEntity, argArray);
case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break; break;
case eTriggerCommandType::TURN_AROUND_ON_PATH: break; case eTriggerCommandType::SET_BOUNCER_STATE: break;
case eTriggerCommandType::GO_FORWARD_ON_PATH: break; case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break;
case eTriggerCommandType::GO_BACKWARD_ON_PATH: break; case eTriggerCommandType::TURN_AROUND_ON_PATH:
case eTriggerCommandType::STOP_PATHING: break; HandleTurnAroundOnPath(targetEntity);
case eTriggerCommandType::START_PATHING: break; break;
case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break; case eTriggerCommandType::GO_FORWARD_ON_PATH:
case eTriggerCommandType::PLAY_EFFECT: HandleGoForwardOnPath(targetEntity);
HandlePlayEffect(targetEntity, argArray); break;
break; case eTriggerCommandType::GO_BACKWARD_ON_PATH:
case eTriggerCommandType::STOP_EFFECT: HandleGoBackwardOnPath(targetEntity);
GameMessages::SendStopFXEffect(targetEntity, true, command->args); break;
break; case eTriggerCommandType::STOP_PATHING:
case eTriggerCommandType::CAST_SKILL: HandleStopPathing(targetEntity);
HandleCastSkill(targetEntity, command->args); break;
break; case eTriggerCommandType::START_PATHING:
case eTriggerCommandType::DISPLAY_ZONE_SUMMARY: HandleStartPathing(targetEntity);
GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID()); break;
break; case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT: case eTriggerCommandType::PLAY_EFFECT:
HandleSetPhysicsVolumeEffect(targetEntity, argArray); HandlePlayEffect(targetEntity, argArray);
break; break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS: case eTriggerCommandType::STOP_EFFECT:
HandleSetPhysicsVolumeStatus(targetEntity, command->args); GameMessages::SendStopFXEffect(targetEntity, true, command->args);
break; break;
case eTriggerCommandType::SET_MODEL_TO_BUILD: break; case eTriggerCommandType::CAST_SKILL:
case eTriggerCommandType::SPAWN_MODEL_BRICKS: break; HandleCastSkill(targetEntity, command->args);
case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK: break;
HandleActivateSpawnerNetwork(command->args); case eTriggerCommandType::DISPLAY_ZONE_SUMMARY:
break; GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID());
case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK: break;
HandleDeactivateSpawnerNetwork(command->args); case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT:
break; HandleSetPhysicsVolumeEffect(targetEntity, argArray);
case eTriggerCommandType::RESET_SPAWNER_NETWORK: break;
HandleResetSpawnerNetwork(command->args); case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS:
break; HandleSetPhysicsVolumeStatus(targetEntity, command->args);
case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS: break;
HandleDestroySpawnerNetworkObjects(command->args); case eTriggerCommandType::SET_MODEL_TO_BUILD: break;
break; case eTriggerCommandType::SPAWN_MODEL_BRICKS: break;
case eTriggerCommandType::GO_TO_WAYPOINT: break; case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK:
case eTriggerCommandType::ACTIVATE_PHYSICS: HandleActivateSpawnerNetwork(command->args);
HandleActivatePhysics(targetEntity, command->args); break;
break; case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK:
HandleDeactivateSpawnerNetwork(command->args);
break;
case eTriggerCommandType::RESET_SPAWNER_NETWORK:
HandleResetSpawnerNetwork(command->args);
break;
case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS:
HandleDestroySpawnerNetworkObjects(command->args);
break;
case eTriggerCommandType::GO_TO_WAYPOINT: break;
case eTriggerCommandType::ACTIVATE_PHYSICS:
HandleActivatePhysics(targetEntity, command->args);
break;
// DEPRECATED BLOCK START // DEPRECATED BLOCK START
case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break; case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break;
case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break; case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break;
case eTriggerCommandType::FLASH_MUSIC_CUE: break; case eTriggerCommandType::FLASH_MUSIC_CUE: break;
case eTriggerCommandType::SET_MUSIC_PARAMETER: break; case eTriggerCommandType::SET_MUSIC_PARAMETER: break;
case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break; case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break;
case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break; case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break;
case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break; case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break;
case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break; case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break;
case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break; case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break;
case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break; case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break;
// DEPRECATED BLOCK END // DEPRECATED BLOCK END
default: default:
LOG_DEBUG("Event %i was not handled!", command->id); LOG_DEBUG("Event %i was not handled!", command->id);
break; break;
} }
} }
} }
@ -164,20 +177,25 @@ std::vector<Entity*> TriggerComponent::GatherTargets(LUTriggers::Command* comman
std::vector<Entity*> entities = {}; std::vector<Entity*> entities = {};
if (command->target == "self") entities.push_back(m_Parent); if (command->target == "self") entities.push_back(m_Parent);
else if (command->target == "zone") { /*TODO*/ } else if (command->target == "zone") {
else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget); /*TODO*/
else if (command->target == "targetTeam" && optionalTarget) { } else if (command->target == "target" && optionalTarget) {
entities.push_back(optionalTarget);
} else if (command->target == "targetTeam" && optionalTarget) {
auto* team = TeamManager::Instance()->GetTeam(optionalTarget->GetObjectID()); auto* team = TeamManager::Instance()->GetTeam(optionalTarget->GetObjectID());
for (const auto memberId : team->members) { for (const auto memberId : team->members) {
auto* member = Game::entityManager->GetEntity(memberId); auto* member = Game::entityManager->GetEntity(memberId);
if (member) entities.push_back(member); if (member) entities.push_back(member);
} }
} else if (command->target == "objGroup") entities = Game::entityManager->GetEntitiesInGroup(command->targetName); } else if (command->target == "objGroup") {
else if (command->target == "allPlayers") { entities = Game::entityManager->GetEntitiesInGroup(command->targetName);
} else if (command->target == "allPlayers") {
for (auto* player : PlayerManager::GetAllPlayers()) { for (auto* player : PlayerManager::GetAllPlayers()) {
entities.push_back(player); entities.push_back(player);
} }
} else if (command->target == "allNPCs") { /*UNUSED*/ } } else if (command->target == "allNPCs") {
/*UNUSED*/
}
return entities; return entities;
} }
@ -186,12 +204,12 @@ void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) {
targetEntity->GetScript()->OnFireEventServerSide(targetEntity, m_Parent, args, 0, 0, 0); targetEntity->GetScript()->OnFireEventServerSide(targetEntity, m_Parent, args, 0, 0, 0);
} }
void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args){ void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args) {
const eKillType killType = GeneralUtils::TryParse<eKillType>(args).value_or(eKillType::VIOLENT); const eKillType killType = GeneralUtils::TryParse<eKillType>(args).value_or(eKillType::VIOLENT);
targetEntity->Smash(m_Parent->GetObjectID(), killType); targetEntity->Smash(m_Parent->GetObjectID(), killType);
} }
void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args){ void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args) {
auto* triggerComponent = targetEntity->GetComponent<TriggerComponent>(); auto* triggerComponent = targetEntity->GetComponent<TriggerComponent>();
if (!triggerComponent) { if (!triggerComponent) {
LOG_DEBUG("Trigger component not found!"); LOG_DEBUG("Trigger component not found!");
@ -200,7 +218,7 @@ void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string arg
triggerComponent->SetTriggerEnabled(args == "1"); triggerComponent->SetTriggerEnabled(args == "1");
} }
void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args){ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args) {
auto* quickBuildComponent = targetEntity->GetComponent<QuickBuildComponent>(); auto* quickBuildComponent = targetEntity->GetComponent<QuickBuildComponent>();
if (!quickBuildComponent) { if (!quickBuildComponent) {
LOG_DEBUG("Rebuild component not found!"); LOG_DEBUG("Rebuild component not found!");
@ -209,7 +227,7 @@ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args
quickBuildComponent->ResetQuickBuild(args == "1"); quickBuildComponent->ResetQuickBuild(args == "1");
} }
void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray) {
if (argArray.size() <= 2) return; if (argArray.size() <= 2) return;
NiPoint3 position = targetEntity->GetPosition(); NiPoint3 position = targetEntity->GetPosition();
@ -219,7 +237,7 @@ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::s
targetEntity->SetPosition(position); targetEntity->SetPosition(position);
} }
void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray) {
if (argArray.size() <= 2) return; if (argArray.size() <= 2) return;
const NiPoint3 vector = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO); const NiPoint3 vector = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
@ -228,7 +246,7 @@ void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std:
targetEntity->SetRotation(rotation); targetEntity->SetRotation(rotation);
} }
void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray) {
if (argArray.size() < 3) return; if (argArray.size() < 3) return;
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>(); auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
@ -246,7 +264,7 @@ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::s
} }
void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args){ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args) {
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>(); auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
if (!phantomPhysicsComponent) { if (!phantomPhysicsComponent) {
LOG_DEBUG("Phantom Physics component not found!"); LOG_DEBUG("Phantom Physics component not found!");
@ -270,7 +288,7 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args)
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }
void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::string> argArray){ void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::string> argArray) {
if (argArray.size() != 2) { if (argArray.size() != 2) {
LOG_DEBUG("Not enough variables!"); LOG_DEBUG("Not enough variables!");
return; return;
@ -279,7 +297,7 @@ void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::str
m_Parent->AddTimer(argArray.at(0), time); m_Parent->AddTimer(argArray.at(0), time);
} }
void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args){ void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args) {
m_Parent->CancelTimer(args); m_Parent->CancelTimer(args);
} }
@ -327,7 +345,7 @@ void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vector<std
// then we need a good way to convert this from a string to that enum // then we need a good way to convert this from a string to that enum
if (argArray.at(0) != "exploretask") return; if (argArray.at(0) != "exploretask") return;
MissionComponent* missionComponent = targetEntity->GetComponent<MissionComponent>(); MissionComponent* missionComponent = targetEntity->GetComponent<MissionComponent>();
if (!missionComponent){ if (!missionComponent) {
LOG_DEBUG("Mission component not found!"); LOG_DEBUG("Mission component not found!");
return; return;
} }
@ -339,7 +357,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::s
const auto effectID = GeneralUtils::TryParse<int32_t>(argArray.at(1)); const auto effectID = GeneralUtils::TryParse<int32_t>(argArray.at(1));
if (!effectID) return; if (!effectID) return;
std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2)); std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2));
float priority = 1; float priority = 1;
if (argArray.size() == 4) { if (argArray.size() == 4) {
priority = GeneralUtils::TryParse<float>(argArray.at(3)).value_or(priority); priority = GeneralUtils::TryParse<float>(argArray.at(3)).value_or(priority);
@ -348,7 +366,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::s
GameMessages::SendPlayFXEffect(targetEntity, effectID.value(), effectType, argArray.at(0), LWOOBJID_EMPTY, priority); GameMessages::SendPlayFXEffect(targetEntity, effectID.value(), effectType, argArray.at(0), LWOOBJID_EMPTY, priority);
} }
void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args){ void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args) {
auto* skillComponent = targetEntity->GetComponent<SkillComponent>(); auto* skillComponent = targetEntity->GetComponent<SkillComponent>();
if (!skillComponent) { if (!skillComponent) {
LOG_DEBUG("Skill component not found!"); LOG_DEBUG("Skill component not found!");
@ -376,7 +394,7 @@ void TriggerComponent::HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::v
phantomPhysicsComponent->SetEffectType(effectType); phantomPhysicsComponent->SetEffectType(effectType);
phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1))); phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1)));
if (argArray.size() > 4) { if (argArray.size() > 4) {
const NiPoint3 direction = const NiPoint3 direction =
GeneralUtils::TryParse<NiPoint3>(argArray.at(2), argArray.at(3), argArray.at(4)).value_or(NiPoint3Constant::ZERO); GeneralUtils::TryParse<NiPoint3>(argArray.at(2), argArray.at(3), argArray.at(4)).value_or(NiPoint3Constant::ZERO);
phantomPhysicsComponent->SetDirection(direction); phantomPhysicsComponent->SetDirection(direction);
@ -402,25 +420,25 @@ void TriggerComponent::HandleSetPhysicsVolumeStatus(Entity* targetEntity, std::s
Game::entityManager->SerializeEntity(targetEntity); Game::entityManager->SerializeEntity(targetEntity);
} }
void TriggerComponent::HandleActivateSpawnerNetwork(std::string args){ void TriggerComponent::HandleActivateSpawnerNetwork(std::string args) {
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->Activate(); if (spawner) spawner->Activate();
} }
} }
void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args){ void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args) {
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->Deactivate(); if (spawner) spawner->Deactivate();
} }
} }
void TriggerComponent::HandleResetSpawnerNetwork(std::string args){ void TriggerComponent::HandleResetSpawnerNetwork(std::string args) {
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->Reset(); if (spawner) spawner->Reset();
} }
} }
void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){ void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args) {
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->DestroyAllEntities(); if (spawner) spawner->DestroyAllEntities();
} }
@ -429,9 +447,50 @@ void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){
void TriggerComponent::HandleActivatePhysics(Entity* targetEntity, std::string args) { void TriggerComponent::HandleActivatePhysics(Entity* targetEntity, std::string args) {
if (args == "true") { if (args == "true") {
// TODO add physics entity if there isn't one // TODO add physics entity if there isn't one
} else if (args == "false"){ } else if (args == "false") {
// TODO remove Phsyics entity if there is one // TODO remove Phsyics entity if there is one
} else { } else {
LOG_DEBUG("Invalid argument for ActivatePhysics Trigger: %s", args.c_str()); LOG_DEBUG("Invalid argument for ActivatePhysics Trigger: %s", args.c_str());
} }
} }
void TriggerComponent::HandleSetPath(Entity* targetEntity, std::vector<std::string> argArray) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->SetupPath(argArray.at(0));
if (argArray.size() >= 2) {
auto index = GeneralUtils::TryParse<int32_t>(argArray.at(1));
if (!index) return;
// movementAIComponent->SetPathStartingWaypointIndex(index.value());
}
if (argArray.size() >= 3 && argArray.at(2) == "1") {
// movementAIComponent->ReversePath();
}
}
void TriggerComponent::HandleTurnAroundOnPath(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
// if (movementAIComponent) movementAIComponent->ReversePath();
}
void TriggerComponent::HandleGoForwardOnPath(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// if (movementAIComponent->GetIsInReverse()) movementAIComponent->ReversePath();
}
void TriggerComponent::HandleGoBackwardOnPath(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// if (!movementAIComponent->GetIsInReverse()) movementAIComponent->ReversePath();
}
void TriggerComponent::HandleStopPathing(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
// if (movementAIComponent) movementAIComponent->Pause();
}
void TriggerComponent::HandleStartPathing(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
// if (movementAIComponent) movementAIComponent->Resume();
}

View File

@ -44,6 +44,12 @@ private:
void HandleResetSpawnerNetwork(std::string args); void HandleResetSpawnerNetwork(std::string args);
void HandleDestroySpawnerNetworkObjects(std::string args); void HandleDestroySpawnerNetworkObjects(std::string args);
void HandleActivatePhysics(Entity* targetEntity, std::string args); void HandleActivatePhysics(Entity* targetEntity, std::string args);
void HandleTurnAroundOnPath(Entity* targetEntity);
void HandleGoForwardOnPath(Entity* targetEntity);
void HandleGoBackwardOnPath(Entity* targetEntity);
void HandleStopPathing(Entity* targetEntity);
void HandleStartPathing(Entity* targetEntity);
void HandleSetPath(Entity* targetEntity, std::vector<std::string> argArray);
LUTriggers::Trigger* m_Trigger; LUTriggers::Trigger* m_Trigger;
}; };

View File

@ -17,6 +17,7 @@
#include "eTriggerCommandType.h" #include "eTriggerCommandType.h"
#include "eTriggerEventType.h" #include "eTriggerEventType.h"
#include "eWaypointCommandType.h"
#include "dNavMesh.h" #include "dNavMesh.h"
Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) : Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) :
@ -452,15 +453,23 @@ void Zone::LoadPath(std::istream& file) {
std::string value; std::string value;
BinaryIO::ReadString<uint8_t>(file, value, BinaryIO::ReadType::WideString); BinaryIO::ReadString<uint8_t>(file, value, BinaryIO::ReadType::WideString);
LDFBaseData* ldfConfig = nullptr;
if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) { if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) {
ldfConfig = LDFBaseData::DataFromString(parameter + "=0:" + value); // cause NetDevil puts spaces in things that don't need spaces
parameter.erase(std::remove_if(parameter.begin(), parameter.end(), ::isspace), parameter.end());
auto waypointCommand = WaypointCommandType::StringToWaypointCommandType(parameter);
if (waypointCommand == eWaypointCommandType::DELAY) value.erase(std::remove_if(value.begin(), value.end(), ::isspace), value.end());
if (waypointCommand != eWaypointCommandType::INVALID) {
auto& command = waypoint.commands.emplace_back();
command.command = waypointCommand;
command.data = value;
} else LOG("Tried to load invalid waypoint command '%s'", parameter.c_str());
} else { } else {
ldfConfig = LDFBaseData::DataFromString(parameter + "=" + value); waypoint.config.emplace_back(LDFBaseData::DataFromString(parameter + "=" + value));
} }
if (ldfConfig) waypoint.config.push_back(ldfConfig);
} }
} }
// We verify the waypoint heights against the navmesh because in many movement paths, // We verify the waypoint heights against the navmesh because in many movement paths,
// the waypoint is located near 0 height, // the waypoint is located near 0 height,
if (path.pathType == PathType::Movement) { if (path.pathType == PathType::Movement) {

View File

@ -13,6 +13,14 @@ namespace LUTriggers {
class Level; class Level;
enum class eWaypointCommandType : uint32_t;
struct WaypointCommand {
eWaypointCommandType command;
std::string data;
};
struct SceneRef { struct SceneRef {
std::string filename; std::string filename;
uint32_t id; uint32_t id;
@ -69,6 +77,7 @@ struct PathWaypoint {
RacingPathWaypoint racing; RacingPathWaypoint racing;
float speed; float speed;
std::vector<LDFBaseData*> config; std::vector<LDFBaseData*> config;
std::vector<WaypointCommand> commands;
}; };
enum class PathType : uint32_t { enum class PathType : uint32_t {