Split out LUTriggers into it's own component (#986)

* Split out LUTriggers into it's own component

* some cleanup

* fix debug log

* use emplace and tryParse

* slight refactor to make the work on startup
rather than at runtime
Also TODO's for getting targets via all the possible methods

* address feedback
This commit is contained in:
Aaron Kimbrell
2023-02-10 02:29:53 -06:00
committed by GitHub
parent d17f51183e
commit 91c0c1fcfb
13 changed files with 437 additions and 137 deletions

View File

@@ -38,5 +38,6 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"SkillComponent.cpp"
"SoundTriggerComponent.cpp"
"SwitchComponent.cpp"
"TriggerComponent.cpp"
"VehiclePhysicsComponent.cpp"
"VendorComponent.cpp" PARENT_SCOPE)

View File

@@ -1,5 +1,6 @@
#include "SwitchComponent.h"
#include "EntityManager.h"
#include "eTriggerEventType.h"
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
@@ -42,7 +43,7 @@ void SwitchComponent::EntityEnter(Entity* entity) {
}
m_Active = true;
if (!m_Parent) return;
m_Parent->TriggerEvent("OnActivated");
m_Parent->TriggerEvent(eTriggerEventType::ACTIVATED);
const auto grpName = m_Parent->GetVarAsString(u"grp_name");
@@ -78,7 +79,7 @@ void SwitchComponent::Update(float deltaTime) {
if (m_Timer <= 0.0f) {
m_Active = false;
if (!m_Parent) return;
m_Parent->TriggerEvent("OnDectivated");
m_Parent->TriggerEvent(eTriggerEventType::DEACTIVATED);
const auto grpName = m_Parent->GetVarAsString(u"grp_name");

View File

@@ -0,0 +1,187 @@
#include "TriggerComponent.h"
#include "dZoneManager.h"
#include "LUTriggers.h"
#include "eTriggerCommandType.h"
#include "MissionComponent.h"
#include "PhantomPhysicsComponent.h"
#include "CDMissionTasksTable.h"
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo): Component(parent) {
m_Parent = parent;
m_Trigger = nullptr;
std::vector<std::string> tokens = GeneralUtils::SplitString(triggerInfo, ':');
uint32_t sceneID;
GeneralUtils::TryParse<uint32_t>(tokens.at(0), sceneID);
uint32_t triggerID;
GeneralUtils::TryParse<uint32_t>(tokens.at(1), triggerID);
m_Trigger = dZoneManager::Instance()->GetZone()->GetTrigger(sceneID, triggerID);
if (!m_Trigger) m_Trigger = new LUTriggers::Trigger();
}
void TriggerComponent::TriggerEvent(eTriggerEventType event, Entity* optionalTarget) {
if (m_Trigger && m_Trigger->enabled) {
for (LUTriggers::Event* triggerEvent : m_Trigger->events) {
if (triggerEvent->id == event) {
for (LUTriggers::Command* command : triggerEvent->commands) {
HandleTriggerCommand(command, optionalTarget);
}
}
}
}
}
void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) {
auto argArray = GeneralUtils::SplitString(command->args, ',');
// determine targets
std::vector<Entity*> targetEntities = GatherTargets(command, optionalTarget);
// if we have no targets, then we are done
if (targetEntities.empty()) return;
for (Entity* targetEntity : targetEntities) {
if (!targetEntity) continue;
switch (command->id) {
case eTriggerCommandType::ZONE_PLAYER: break;
case eTriggerCommandType::FIRE_EVENT:
HandleFireEvent(targetEntity, command->args);
break;
case eTriggerCommandType::DESTROY_OBJ: break;
case eTriggerCommandType::TOGGLE_TRIGGER: break;
case eTriggerCommandType::RESET_REBUILD: break;
case eTriggerCommandType::SET_PATH: break;
case eTriggerCommandType::SET_PICK_TYPE: break;
case eTriggerCommandType::MOVE_OBJECT: break;
case eTriggerCommandType::ROTATE_OBJECT: break;
case eTriggerCommandType::PUSH_OBJECT: break;
case eTriggerCommandType::REPEL_OBJECT: break;
case eTriggerCommandType::SET_TIMER: break;
case eTriggerCommandType::CANCEL_TIMER: break;
case eTriggerCommandType::PLAY_CINEMATIC: break;
case eTriggerCommandType::TOGGLE_BBB: 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: break;
case eTriggerCommandType::STOP_EFFECT: 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;
case eTriggerCommandType::CAST_SKILL: break;
case eTriggerCommandType::DISPLAY_ZONE_SUMMARY: break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT:
HandleSetPhysicsVolume(targetEntity, argArray, command->target);
break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS: break;
case eTriggerCommandType::SET_MODEL_TO_BUILD: break;
case eTriggerCommandType::SPAWN_MODEL_BRICKS: break;
case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK: break;
case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK: break;
case eTriggerCommandType::RESET_SPAWNER_NETWORK: break;
case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS: break;
case eTriggerCommandType::GO_TO_WAYPOINT: break;
case eTriggerCommandType::ACTIVATE_PHYSICS: break;
default:
Game::logger->LogDebug("TriggerComponent", "Event %i was not handled!", command->id);
break;
}
}
}
std::vector<Entity*> TriggerComponent::GatherTargets(LUTriggers::Command* command, Entity* optionalTarget) {
std::vector<Entity*> entities = {};
if (command->target == "self") entities.push_back(m_Parent);
else if (command->target == "zone") { /*TODO*/ }
else if (command->target == "target") { /*TODO*/ }
else if (command->target == "targetTeam") { /*TODO*/ }
else if (command->target == "objGroup") entities = EntityManager::Instance()->GetEntitiesInGroup(command->targetName);
else if (command->target == "allPlayers") { /*TODO*/ }
else if (command->target == "allNPCs") { /*TODO*/ }
if (optionalTarget) entities.push_back(optionalTarget);
return entities;
}
void TriggerComponent::HandleSetPhysicsVolume(Entity* targetEntity, std::vector<std::string> argArray, std::string target) {
PhantomPhysicsComponent* phanPhys = m_Parent->GetComponent<PhantomPhysicsComponent>();
if (!phanPhys) return;
phanPhys->SetPhysicsEffectActive(true);
uint32_t effectType = 0;
std::transform(argArray.at(0).begin(), argArray.at(0).end(), argArray.at(0).begin(), ::tolower); //Transform to lowercase
if (argArray.at(0) == "push") effectType = 0;
else if (argArray.at(0) == "attract") effectType = 1;
else if (argArray.at(0) == "repulse") effectType = 2;
else if (argArray.at(0) == "gravity") effectType = 3;
else if (argArray.at(0) == "friction") effectType = 4;
phanPhys->SetEffectType(effectType);
phanPhys->SetDirectionalMultiplier(std::stof(argArray.at(1)));
if (argArray.size() > 4) {
NiPoint3 direction = NiPoint3::ZERO;
GeneralUtils::TryParse<float>(argArray.at(2), direction.x);
GeneralUtils::TryParse<float>(argArray.at(3), direction.y);
GeneralUtils::TryParse<float>(argArray.at(4), direction.z);
phanPhys->SetDirection(direction);
}
if (argArray.size() > 5) {
uint32_t min;
GeneralUtils::TryParse<uint32_t>(argArray.at(6), min);
phanPhys->SetMin(min);
uint32_t max;
GeneralUtils::TryParse<uint32_t>(argArray.at(7), max);
phanPhys->SetMax(max);
}
// TODO: why is this contruct and not serialize?
if (target == "self") EntityManager::Instance()->ConstructEntity(m_Parent);
}
void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vector<std::string> argArray) {
CDMissionTasksTable* missionTasksTable = CDClientManager::Instance()->GetTable<CDMissionTasksTable>("MissionTasks");
std::vector<CDMissionTasks> missionTasks = missionTasksTable->Query([=](CDMissionTasks entry) {
std::string lowerTargetGroup;
for (char character : entry.targetGroup) {
lowerTargetGroup.push_back(std::tolower(character)); // make lowercase to ensure it works
}
return (lowerTargetGroup == argArray[4]);
});
for (const CDMissionTasks& task : missionTasks) {
MissionComponent* missionComponent = targetEntity->GetComponent<MissionComponent>();
if (!missionComponent) continue;
missionComponent->ForceProgress(task.id, task.uid, std::stoi(argArray[2]));
}
}
void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) {
for (CppScripts::Script* script : CppScripts::GetEntityScripts(targetEntity)) {
script->OnFireEventServerSide(targetEntity, m_Parent, args, 0, 0, 0);
}
}

View File

@@ -0,0 +1,34 @@
#ifndef __TRIGGERCOMPONENT__H__
#define __TRIGGERCOMPONENT__H__
#include "Component.h"
namespace LUTriggers {
struct Trigger;
struct Command;
};
class TriggerComponent : public Component {
public:
static const uint32_t ComponentType = COMPONENT_TYPE_TRIGGER;
explicit TriggerComponent(Entity* parent, const std::string triggerInfo);
void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr);
LUTriggers::Trigger* GetTrigger() const { return m_Trigger; }
private:
void HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget);
std::vector<std::string> ParseArgs(std::string args);
std::vector<Entity*> GatherTargets(LUTriggers::Command* command, Entity* optionalTarget);
// Trigger Event Handlers
void HandleSetPhysicsVolume(Entity* targetEntity, std::vector<std::string> argArray, std::string target);
void HandleUpdateMission(Entity* targetEntity, std::vector<std::string> argArray);
void HandleFireEvent(Entity* targetEntity, std::string args);
void HandleCastSkill(Entity* targetEntity, uint32_t skillID);
LUTriggers::Trigger* m_Trigger;
};
#endif //!__TRIGGERCOMPONENT__H__