From 2b6f7c331ca2fdcec9d96cfdc1a53b5a10435c60 Mon Sep 17 00:00:00 2001 From: David Markowitz Date: Thu, 7 Mar 2024 01:40:29 -0800 Subject: [PATCH] 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. --- dCommon/dEnums/eWaypointCommandType.h | 59 +++++ dGame/dComponents/TriggerComponent.cpp | 295 +++++++++++++++---------- dGame/dComponents/TriggerComponent.h | 6 + dZoneManager/Zone.cpp | 17 +- dZoneManager/Zone.h | 9 + 5 files changed, 261 insertions(+), 125 deletions(-) create mode 100644 dCommon/dEnums/eWaypointCommandType.h diff --git a/dCommon/dEnums/eWaypointCommandType.h b/dCommon/dEnums/eWaypointCommandType.h new file mode 100644 index 00000000..308f3764 --- /dev/null +++ b/dCommon/dEnums/eWaypointCommandType.h @@ -0,0 +1,59 @@ + +#ifndef __EWAYPOINTCOMMANDTYPES__H__ +#define __EWAYPOINTCOMMANDTYPES__H__ + +#include + +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 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__ diff --git a/dGame/dComponents/TriggerComponent.cpp b/dGame/dComponents/TriggerComponent.cpp index e43ebc5d..1ae414c3 100644 --- a/dGame/dComponents/TriggerComponent.cpp +++ b/dGame/dComponents/TriggerComponent.cpp @@ -15,8 +15,9 @@ #include "PlayerManager.h" #include "Game.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_Trigger = nullptr; @@ -43,7 +44,7 @@ void TriggerComponent::TriggerEvent(eTriggerEventType event, Entity* optionalTar } void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) { - auto argArray = GeneralUtils::SplitString(command->args, ','); + auto argArray = GeneralUtils::SplitString(command->args, ','); // determine targets std::vector targetEntities = GatherTargets(command, optionalTarget); @@ -55,107 +56,119 @@ void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity if (!targetEntity) continue; switch (command->id) { - case eTriggerCommandType::ZONE_PLAYER: break; - case eTriggerCommandType::FIRE_EVENT: - HandleFireEvent(targetEntity, command->args); - break; - case eTriggerCommandType::DESTROY_OBJ: - HandleDestroyObject(targetEntity, command->args); - break; - case eTriggerCommandType::TOGGLE_TRIGGER: - HandleToggleTrigger(targetEntity, command->args); - break; - case eTriggerCommandType::RESET_REBUILD: - HandleResetRebuild(targetEntity, command->args); - break; - case eTriggerCommandType::SET_PATH: break; - case eTriggerCommandType::SET_PICK_TYPE: break; - case eTriggerCommandType::MOVE_OBJECT: - HandleMoveObject(targetEntity, argArray); - break; - case eTriggerCommandType::ROTATE_OBJECT: - HandleRotateObject(targetEntity, argArray); - break; - case eTriggerCommandType::PUSH_OBJECT: - HandlePushObject(targetEntity, argArray); - break; - case eTriggerCommandType::REPEL_OBJECT: - HandleRepelObject(targetEntity, command->args); - break; - case eTriggerCommandType::SET_TIMER: - HandleSetTimer(targetEntity, argArray); - break; - case eTriggerCommandType::CANCEL_TIMER: - HandleCancelTimer(targetEntity, command->args); - break; - case eTriggerCommandType::PLAY_CINEMATIC: - HandlePlayCinematic(targetEntity, argArray); - break; - case eTriggerCommandType::TOGGLE_BBB: - HandleToggleBBB(targetEntity, command->args); - break; - case eTriggerCommandType::UPDATE_MISSION: - HandleUpdateMission(targetEntity, argArray); - break; - case eTriggerCommandType::SET_BOUNCER_STATE: break; - case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break; - case eTriggerCommandType::TURN_AROUND_ON_PATH: break; - case eTriggerCommandType::GO_FORWARD_ON_PATH: break; - case eTriggerCommandType::GO_BACKWARD_ON_PATH: break; - case eTriggerCommandType::STOP_PATHING: break; - case eTriggerCommandType::START_PATHING: break; - case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break; - case eTriggerCommandType::PLAY_EFFECT: - HandlePlayEffect(targetEntity, argArray); - break; - case eTriggerCommandType::STOP_EFFECT: - GameMessages::SendStopFXEffect(targetEntity, true, command->args); - break; - case eTriggerCommandType::CAST_SKILL: - HandleCastSkill(targetEntity, command->args); - break; - case eTriggerCommandType::DISPLAY_ZONE_SUMMARY: - GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID()); - break; - case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT: - HandleSetPhysicsVolumeEffect(targetEntity, argArray); - break; - case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS: - HandleSetPhysicsVolumeStatus(targetEntity, command->args); - break; - case eTriggerCommandType::SET_MODEL_TO_BUILD: break; - case eTriggerCommandType::SPAWN_MODEL_BRICKS: break; - case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK: - HandleActivateSpawnerNetwork(command->args); - 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; + case eTriggerCommandType::ZONE_PLAYER: break; + case eTriggerCommandType::FIRE_EVENT: + HandleFireEvent(targetEntity, command->args); + break; + case eTriggerCommandType::DESTROY_OBJ: + HandleDestroyObject(targetEntity, command->args); + break; + case eTriggerCommandType::TOGGLE_TRIGGER: + HandleToggleTrigger(targetEntity, command->args); + break; + case eTriggerCommandType::RESET_REBUILD: + HandleResetRebuild(targetEntity, command->args); + break; + case eTriggerCommandType::SET_PATH: + HandleSetPath(targetEntity, argArray); + break; + case eTriggerCommandType::SET_PICK_TYPE: break; + case eTriggerCommandType::MOVE_OBJECT: + HandleMoveObject(targetEntity, argArray); + break; + case eTriggerCommandType::ROTATE_OBJECT: + HandleRotateObject(targetEntity, argArray); + break; + case eTriggerCommandType::PUSH_OBJECT: + HandlePushObject(targetEntity, argArray); + break; + case eTriggerCommandType::REPEL_OBJECT: + HandleRepelObject(targetEntity, command->args); + break; + case eTriggerCommandType::SET_TIMER: + HandleSetTimer(targetEntity, argArray); + break; + case eTriggerCommandType::CANCEL_TIMER: + HandleCancelTimer(targetEntity, command->args); + break; + case eTriggerCommandType::PLAY_CINEMATIC: + HandlePlayCinematic(targetEntity, argArray); + break; + case eTriggerCommandType::TOGGLE_BBB: + HandleToggleBBB(targetEntity, command->args); + break; + case eTriggerCommandType::UPDATE_MISSION: + HandleUpdateMission(targetEntity, argArray); + break; + case eTriggerCommandType::SET_BOUNCER_STATE: break; + case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break; + case eTriggerCommandType::TURN_AROUND_ON_PATH: + HandleTurnAroundOnPath(targetEntity); + break; + case eTriggerCommandType::GO_FORWARD_ON_PATH: + HandleGoForwardOnPath(targetEntity); + break; + case eTriggerCommandType::GO_BACKWARD_ON_PATH: + HandleGoBackwardOnPath(targetEntity); + break; + case eTriggerCommandType::STOP_PATHING: + HandleStopPathing(targetEntity); + break; + case eTriggerCommandType::START_PATHING: + HandleStartPathing(targetEntity); + break; + case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break; + case eTriggerCommandType::PLAY_EFFECT: + HandlePlayEffect(targetEntity, argArray); + break; + case eTriggerCommandType::STOP_EFFECT: + GameMessages::SendStopFXEffect(targetEntity, true, command->args); + break; + case eTriggerCommandType::CAST_SKILL: + HandleCastSkill(targetEntity, command->args); + break; + case eTriggerCommandType::DISPLAY_ZONE_SUMMARY: + GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID()); + break; + case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT: + HandleSetPhysicsVolumeEffect(targetEntity, argArray); + break; + case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS: + HandleSetPhysicsVolumeStatus(targetEntity, command->args); + break; + case eTriggerCommandType::SET_MODEL_TO_BUILD: break; + case eTriggerCommandType::SPAWN_MODEL_BRICKS: break; + case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK: + HandleActivateSpawnerNetwork(command->args); + 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 - case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break; - case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break; - case eTriggerCommandType::FLASH_MUSIC_CUE: break; - case eTriggerCommandType::SET_MUSIC_PARAMETER: break; - case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break; - case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break; - case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break; - case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break; - case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break; - case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break; + case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break; + case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break; + case eTriggerCommandType::FLASH_MUSIC_CUE: break; + case eTriggerCommandType::SET_MUSIC_PARAMETER: break; + case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break; + case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break; + case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break; + case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break; + case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break; + case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break; // DEPRECATED BLOCK END - default: - LOG_DEBUG("Event %i was not handled!", command->id); - break; + default: + LOG_DEBUG("Event %i was not handled!", command->id); + break; } } } @@ -164,8 +177,7 @@ std::vector TriggerComponent::GatherTargets(LUTriggers::Command* comman std::vector entities = {}; if (command->target == "self") entities.push_back(m_Parent); - else if (command->target == "zone") { /*TODO*/ } - else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget); + else if (command->target == "zone") { /*TODO*/ } else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget); else if (command->target == "targetTeam" && optionalTarget) { auto* team = TeamManager::Instance()->GetTeam(optionalTarget->GetObjectID()); for (const auto memberId : team->members) { @@ -186,12 +198,12 @@ void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) { 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(args).value_or(eKillType::VIOLENT); 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(); if (!triggerComponent) { LOG_DEBUG("Trigger component not found!"); @@ -200,7 +212,7 @@ void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string arg triggerComponent->SetTriggerEnabled(args == "1"); } -void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args){ +void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args) { auto* quickBuildComponent = targetEntity->GetComponent(); if (!quickBuildComponent) { LOG_DEBUG("Rebuild component not found!"); @@ -209,7 +221,7 @@ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args quickBuildComponent->ResetQuickBuild(args == "1"); } -void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector argArray) { if (argArray.size() <= 2) return; NiPoint3 position = targetEntity->GetPosition(); @@ -219,7 +231,7 @@ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vectorSetPosition(position); } -void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector argArray) { if (argArray.size() <= 2) return; const NiPoint3 vector = GeneralUtils::TryParse(argArray).value_or(NiPoint3Constant::ZERO); @@ -228,7 +240,7 @@ void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vectorSetRotation(rotation); } -void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector argArray) { if (argArray.size() < 3) return; auto* phantomPhysicsComponent = m_Parent->GetComponent(); @@ -246,7 +258,7 @@ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vectorGetComponent(); if (!phantomPhysicsComponent) { LOG_DEBUG("Phantom Physics component not found!"); @@ -270,7 +282,7 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args) Game::entityManager->SerializeEntity(m_Parent); } -void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector argArray){ +void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector argArray) { if (argArray.size() != 2) { LOG_DEBUG("Not enough variables!"); return; @@ -279,7 +291,7 @@ void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vectorAddTimer(argArray.at(0), time); } -void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args){ +void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args) { m_Parent->CancelTimer(args); } @@ -327,7 +339,7 @@ void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vectorGetComponent(); - if (!missionComponent){ + if (!missionComponent) { LOG_DEBUG("Mission component not found!"); return; } @@ -339,7 +351,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector(argArray.at(1)); if (!effectID) return; std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2)); - + float priority = 1; if (argArray.size() == 4) { priority = GeneralUtils::TryParse(argArray.at(3)).value_or(priority); @@ -348,7 +360,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vectorGetComponent(); if (!skillComponent) { LOG_DEBUG("Skill component not found!"); @@ -376,7 +388,7 @@ void TriggerComponent::HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::v phantomPhysicsComponent->SetEffectType(effectType); phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1))); if (argArray.size() > 4) { - const NiPoint3 direction = + const NiPoint3 direction = GeneralUtils::TryParse(argArray.at(2), argArray.at(3), argArray.at(4)).value_or(NiPoint3Constant::ZERO); phantomPhysicsComponent->SetDirection(direction); @@ -402,25 +414,25 @@ void TriggerComponent::HandleSetPhysicsVolumeStatus(Entity* targetEntity, std::s Game::entityManager->SerializeEntity(targetEntity); } -void TriggerComponent::HandleActivateSpawnerNetwork(std::string args){ +void TriggerComponent::HandleActivateSpawnerNetwork(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->Activate(); } } -void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args){ +void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->Deactivate(); } } -void TriggerComponent::HandleResetSpawnerNetwork(std::string args){ +void TriggerComponent::HandleResetSpawnerNetwork(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->Reset(); } } -void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){ +void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args) { for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) { if (spawner) spawner->DestroyAllEntities(); } @@ -429,9 +441,50 @@ void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){ void TriggerComponent::HandleActivatePhysics(Entity* targetEntity, std::string args) { if (args == "true") { // 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 } else { LOG_DEBUG("Invalid argument for ActivatePhysics Trigger: %s", args.c_str()); } } + +void TriggerComponent::HandleSetPath(Entity* targetEntity, std::vector argArray) { + auto* movementAIComponent = targetEntity->GetComponent(); + if (!movementAIComponent) return; + // movementAIComponent->SetupPath(argArray.at(0)); + if (argArray.size() >= 2) { + auto index = GeneralUtils::TryParse(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(); + // if (movementAIComponent) movementAIComponent->ReversePath(); +} + +void TriggerComponent::HandleGoForwardOnPath(Entity* targetEntity) { + auto* movementAIComponent = targetEntity->GetComponent(); + if (!movementAIComponent) return; + // if (movementAIComponent->GetIsInReverse()) movementAIComponent->ReversePath(); +} + +void TriggerComponent::HandleGoBackwardOnPath(Entity* targetEntity) { + auto* movementAIComponent = targetEntity->GetComponent(); + if (!movementAIComponent) return; + // if (!movementAIComponent->GetIsInReverse()) movementAIComponent->ReversePath(); +} + +void TriggerComponent::HandleStopPathing(Entity* targetEntity) { + auto* movementAIComponent = targetEntity->GetComponent(); + // if (movementAIComponent) movementAIComponent->Pause(); +} + +void TriggerComponent::HandleStartPathing(Entity* targetEntity) { + auto* movementAIComponent = targetEntity->GetComponent(); + // if (movementAIComponent) movementAIComponent->Resume(); +} diff --git a/dGame/dComponents/TriggerComponent.h b/dGame/dComponents/TriggerComponent.h index 5610f24a..94a7682e 100644 --- a/dGame/dComponents/TriggerComponent.h +++ b/dGame/dComponents/TriggerComponent.h @@ -44,6 +44,12 @@ private: void HandleResetSpawnerNetwork(std::string args); void HandleDestroySpawnerNetworkObjects(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 argArray); LUTriggers::Trigger* m_Trigger; }; diff --git a/dZoneManager/Zone.cpp b/dZoneManager/Zone.cpp index 38c3a1ee..44532fc9 100644 --- a/dZoneManager/Zone.cpp +++ b/dZoneManager/Zone.cpp @@ -17,6 +17,7 @@ #include "eTriggerCommandType.h" #include "eTriggerEventType.h" +#include "eWaypointCommandType.h" #include "dNavMesh.h" Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) : @@ -452,15 +453,23 @@ void Zone::LoadPath(std::istream& file) { std::string value; BinaryIO::ReadString(file, value, BinaryIO::ReadType::WideString); - LDFBaseData* ldfConfig = nullptr; 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 { - 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, // the waypoint is located near 0 height, if (path.pathType == PathType::Movement) { diff --git a/dZoneManager/Zone.h b/dZoneManager/Zone.h index 2f394510..c5bac6a6 100644 --- a/dZoneManager/Zone.h +++ b/dZoneManager/Zone.h @@ -13,6 +13,14 @@ namespace LUTriggers { class Level; +enum class eWaypointCommandType : uint32_t; + +struct WaypointCommand { + eWaypointCommandType command; + std::string data; +}; + + struct SceneRef { std::string filename; uint32_t id; @@ -69,6 +77,7 @@ struct PathWaypoint { RacingPathWaypoint racing; float speed; std::vector config; + std::vector commands; }; enum class PathType : uint32_t {