mirror of
				https://github.com/DarkflameUniverse/DarkflameServer.git
				synced 2025-11-03 22:21:59 +00:00 
			
		
		
		
	Merge branch 'main' into item-component
This commit is contained in:
		@@ -414,6 +414,7 @@ enum eReplicaComponentType : int32_t {
 | 
			
		||||
	COMPONENT_TYPE_MODULE_ASSEMBLY = 61,			//!< The ModuleAssembly Component
 | 
			
		||||
	COMPONENT_TYPE_PROPERTY_VENDOR = 65,			//!< The PropertyVendor Component
 | 
			
		||||
	COMPONENT_TYPE_ROCKET_LAUNCH = 67,			//!< The RocketLaunch Component
 | 
			
		||||
	COMPONENT_TYPE_TRIGGER = 69,
 | 
			
		||||
	COMPONENT_TYPE_RACING_CONTROL = 71,			//!< The RacingControl Component
 | 
			
		||||
	COMPONENT_TYPE_MISSION_OFFER = 73,			//!< The MissionOffer Component
 | 
			
		||||
	COMPONENT_TYPE_EXHIBIT = 75,			//!< The Exhibit Component
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										119
									
								
								dCommon/dEnums/eTriggerCommandType.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								dCommon/dEnums/eTriggerCommandType.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
#ifndef __ETRIGGERCOMMANDTYPE__H__
 | 
			
		||||
#define __ETRIGGERCOMMANDTYPE__H__
 | 
			
		||||
 | 
			
		||||
// For info about Trigger Command see:
 | 
			
		||||
// https://docs.lu-dev.net/en/latest/file-structures/lutriggers.html?highlight=trigger#possible-values-commands
 | 
			
		||||
 | 
			
		||||
enum class eTriggerCommandType {
 | 
			
		||||
	INVALID,
 | 
			
		||||
	ZONE_PLAYER,
 | 
			
		||||
	FIRE_EVENT,
 | 
			
		||||
	DESTROY_OBJ,
 | 
			
		||||
	TOGGLE_TRIGGER,
 | 
			
		||||
	RESET_REBUILD,
 | 
			
		||||
	SET_PATH,
 | 
			
		||||
	SET_PICK_TYPE,
 | 
			
		||||
	MOVE_OBJECT,
 | 
			
		||||
	ROTATE_OBJECT,
 | 
			
		||||
	PUSH_OBJECT,
 | 
			
		||||
	REPEL_OBJECT,
 | 
			
		||||
	SET_TIMER,
 | 
			
		||||
	CANCEL_TIMER,
 | 
			
		||||
	PLAY_CINEMATIC,
 | 
			
		||||
	TOGGLE_BBB,
 | 
			
		||||
	UPDATE_MISSION,
 | 
			
		||||
	SET_BOUNCER_STATE,
 | 
			
		||||
	BOUNCE_ALL_ON_BOUNCER,
 | 
			
		||||
	TURN_AROUND_ON_PATH,
 | 
			
		||||
	GO_FORWARD_ON_PATH,
 | 
			
		||||
	GO_BACKWARD_ON_PATH,
 | 
			
		||||
	STOP_PATHING,
 | 
			
		||||
	START_PATHING,
 | 
			
		||||
	LOCK_OR_UNLOCK_CONTROLS,
 | 
			
		||||
	PLAY_EFFECT,
 | 
			
		||||
	STOP_EFFECT,
 | 
			
		||||
	ACTIVATE_MUSIC_CUE,
 | 
			
		||||
	DEACTIVATE_MUSIC_CUE,
 | 
			
		||||
	FLASH_MUSIC_CUE,
 | 
			
		||||
	SET_MUSIC_PARAMETER,
 | 
			
		||||
	PLAY_2D_AMBIENT_SOUND,
 | 
			
		||||
	STOP_2D_AMBIENT_SOUND,
 | 
			
		||||
	PLAY_3D_AMBIENT_SOUND,
 | 
			
		||||
	STOP_3D_AMBIENT_SOUND,
 | 
			
		||||
	ACTIVATE_MIXER_PROGRAM,
 | 
			
		||||
	DEACTIVATE_MIXER_PROGRAM,
 | 
			
		||||
	CAST_SKILL,
 | 
			
		||||
	DISPLAY_ZONE_SUMMARY,
 | 
			
		||||
	SET_PHYSICS_VOLUME_EFFECT,
 | 
			
		||||
	SET_PHYSICS_VOLUME_STATUS,
 | 
			
		||||
	SET_MODEL_TO_BUILD,
 | 
			
		||||
	SPAWN_MODEL_BRICKS,
 | 
			
		||||
	ACTIVATE_SPAWNER_NETWORK,
 | 
			
		||||
	DEACTIVATE_SPAWNER_NETWORK,
 | 
			
		||||
	RESET_SPAWNER_NETWORK,
 | 
			
		||||
	DESTROY_SPAWNER_NETWORK_OBJECTS,
 | 
			
		||||
	GO_TO_WAYPOINT,
 | 
			
		||||
	ACTIVATE_PHYSICS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TriggerCommandType {
 | 
			
		||||
public:
 | 
			
		||||
	static eTriggerCommandType StringToTriggerCommandType(std::string commandString) {
 | 
			
		||||
		const std::map<std::string, eTriggerCommandType> TriggerCommandMap = {
 | 
			
		||||
			{ "zonePlayer", eTriggerCommandType::ZONE_PLAYER},
 | 
			
		||||
			{ "fireEvent", eTriggerCommandType::FIRE_EVENT},
 | 
			
		||||
			{ "destroyObj", eTriggerCommandType::DESTROY_OBJ},
 | 
			
		||||
			{ "toggleTrigger", eTriggerCommandType::TOGGLE_TRIGGER},
 | 
			
		||||
			{ "resetRebuild", eTriggerCommandType::RESET_REBUILD},
 | 
			
		||||
			{ "setPath", eTriggerCommandType::SET_PATH},
 | 
			
		||||
			{ "setPickType", eTriggerCommandType::SET_PICK_TYPE},
 | 
			
		||||
			{ "moveObject", eTriggerCommandType::MOVE_OBJECT},
 | 
			
		||||
			{ "rotateObject", eTriggerCommandType::ROTATE_OBJECT},
 | 
			
		||||
			{ "pushObject", eTriggerCommandType::PUSH_OBJECT},
 | 
			
		||||
			{ "repelObject", eTriggerCommandType::REPEL_OBJECT},
 | 
			
		||||
			{ "setTimer", eTriggerCommandType::SET_TIMER},
 | 
			
		||||
			{ "cancelTimer", eTriggerCommandType::CANCEL_TIMER},
 | 
			
		||||
			{ "playCinematic", eTriggerCommandType::PLAY_CINEMATIC},
 | 
			
		||||
			{ "toggleBBB", eTriggerCommandType::TOGGLE_BBB},
 | 
			
		||||
			{ "updateMission", eTriggerCommandType::UPDATE_MISSION},
 | 
			
		||||
			{ "setBouncerState", eTriggerCommandType::SET_BOUNCER_STATE},
 | 
			
		||||
			{ "bounceAllOnBouncer", eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER},
 | 
			
		||||
			{ "turnAroundOnPath", eTriggerCommandType::TURN_AROUND_ON_PATH},
 | 
			
		||||
			{ "goForwardOnPath", eTriggerCommandType::GO_FORWARD_ON_PATH},
 | 
			
		||||
			{ "goBackwardOnPath", eTriggerCommandType::GO_BACKWARD_ON_PATH},
 | 
			
		||||
			{ "stopPathing", eTriggerCommandType::STOP_PATHING},
 | 
			
		||||
			{ "startPathing", eTriggerCommandType::START_PATHING},
 | 
			
		||||
			{ "LockOrUnlockControls", eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS},
 | 
			
		||||
			{ "PlayEffect", eTriggerCommandType::PLAY_EFFECT},
 | 
			
		||||
			{ "StopEffect", eTriggerCommandType::STOP_EFFECT},
 | 
			
		||||
			{ "activateMusicCue", eTriggerCommandType::ACTIVATE_MUSIC_CUE},
 | 
			
		||||
			{ "deactivateMusicCue", eTriggerCommandType::DEACTIVATE_MUSIC_CUE},
 | 
			
		||||
			{ "flashMusicCue", eTriggerCommandType::FLASH_MUSIC_CUE},
 | 
			
		||||
			{ "setMusicParameter", eTriggerCommandType::SET_MUSIC_PARAMETER},
 | 
			
		||||
			{ "play2DAmbientSound", eTriggerCommandType::PLAY_2D_AMBIENT_SOUND},
 | 
			
		||||
			{ "stop2DAmbientSound", eTriggerCommandType::STOP_2D_AMBIENT_SOUND},
 | 
			
		||||
			{ "play3DAmbientSound", eTriggerCommandType::PLAY_3D_AMBIENT_SOUND},
 | 
			
		||||
			{ "stop3DAmbientSound", eTriggerCommandType::STOP_3D_AMBIENT_SOUND},
 | 
			
		||||
			{ "activateMixerProgram", eTriggerCommandType::ACTIVATE_MIXER_PROGRAM},
 | 
			
		||||
			{ "deactivateMixerProgram", eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM},
 | 
			
		||||
			{ "CastSkill", eTriggerCommandType::CAST_SKILL},
 | 
			
		||||
			{ "displayZoneSummary", eTriggerCommandType::DISPLAY_ZONE_SUMMARY},
 | 
			
		||||
			{ "SetPhysicsVolumeEffect", eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT},
 | 
			
		||||
			{ "SetPhysicsVolumeStatus", eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS},
 | 
			
		||||
			{ "setModelToBuild", eTriggerCommandType::SET_MODEL_TO_BUILD},
 | 
			
		||||
			{ "spawnModelBricks", eTriggerCommandType::SPAWN_MODEL_BRICKS},
 | 
			
		||||
			{ "ActivateSpawnerNetwork", eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK},
 | 
			
		||||
			{ "DeactivateSpawnerNetwork", eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK},
 | 
			
		||||
			{ "ResetSpawnerNetwork", eTriggerCommandType::RESET_SPAWNER_NETWORK},
 | 
			
		||||
			{ "DestroySpawnerNetworkObjects", eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS},
 | 
			
		||||
			{ "Go_To_Waypoint", eTriggerCommandType::GO_TO_WAYPOINT},
 | 
			
		||||
			{ "ActivatePhysics", eTriggerCommandType::ACTIVATE_PHYSICS}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		auto intermed = TriggerCommandMap.find(commandString);
 | 
			
		||||
		return (intermed != TriggerCommandMap.end()) ? intermed->second : eTriggerCommandType::INVALID;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  //!__ETRIGGERCOMMANDTYPE__H__
 | 
			
		||||
							
								
								
									
										53
									
								
								dCommon/dEnums/eTriggerEventType.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								dCommon/dEnums/eTriggerEventType.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
#ifndef __ETRIGGEREVENTTYPE__H__
 | 
			
		||||
#define __ETRIGGEREVENTTYPE__H__
 | 
			
		||||
 | 
			
		||||
enum class eTriggerEventType {
 | 
			
		||||
	INVALID,
 | 
			
		||||
	DESTROY,
 | 
			
		||||
	CUSTOM_EVENT,
 | 
			
		||||
	ENTER,
 | 
			
		||||
	EXIT,
 | 
			
		||||
	CREATE,
 | 
			
		||||
	HIT,
 | 
			
		||||
	TIMER_DONE,
 | 
			
		||||
	REBUILD_COMPLETE,
 | 
			
		||||
	ACTIVATED,
 | 
			
		||||
	DEACTIVATED,
 | 
			
		||||
	ARRIVED,
 | 
			
		||||
	ARRIVED_AT_END_OF_PATH,
 | 
			
		||||
	ZONE_SUMMARY_DISMISSED,
 | 
			
		||||
	ARRIVED_AT_DESIRED_WAYPOINT,
 | 
			
		||||
	PET_ON_SWITCH,
 | 
			
		||||
	PET_OFF_SWITCH,
 | 
			
		||||
	INTERACT
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class TriggerEventType {
 | 
			
		||||
public:
 | 
			
		||||
	static eTriggerEventType StringToTriggerEventType(std::string commandString) {
 | 
			
		||||
		const std::map<std::string, eTriggerEventType> TriggerEventMap = {
 | 
			
		||||
			{"OnDestroy", eTriggerEventType::DESTROY},
 | 
			
		||||
			{"OnCustomEvent", eTriggerEventType::CUSTOM_EVENT},
 | 
			
		||||
			{"OnEnter", eTriggerEventType::ENTER},
 | 
			
		||||
			{"OnExit", eTriggerEventType::EXIT},
 | 
			
		||||
			{"OnCreate", eTriggerEventType::CREATE},
 | 
			
		||||
			{"OnHit", eTriggerEventType::HIT},
 | 
			
		||||
			{"OnTimerDone", eTriggerEventType::TIMER_DONE},
 | 
			
		||||
			{"OnRebuildComplete", eTriggerEventType::REBUILD_COMPLETE},
 | 
			
		||||
			{"OnActivated", eTriggerEventType::ACTIVATED},
 | 
			
		||||
			{"OnDeactivated", eTriggerEventType::DEACTIVATED},
 | 
			
		||||
			{"OnArrived", eTriggerEventType::ARRIVED},
 | 
			
		||||
			{"OnArrivedAtEndOfPath", eTriggerEventType::ARRIVED_AT_END_OF_PATH},
 | 
			
		||||
			{"OnZoneSummaryDismissed", eTriggerEventType::ZONE_SUMMARY_DISMISSED},
 | 
			
		||||
			{"OnArrivedAtDesiredWaypoint", eTriggerEventType::ARRIVED_AT_DESIRED_WAYPOINT},
 | 
			
		||||
			{"OnPetOnSwitch", eTriggerEventType::PET_ON_SWITCH},
 | 
			
		||||
			{"OnPetOffSwitch", eTriggerEventType::PET_OFF_SWITCH},
 | 
			
		||||
			{"OnInteract", eTriggerEventType::INTERACT},
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		auto intermed = TriggerEventMap.find(commandString);
 | 
			
		||||
		return (intermed != TriggerEventMap.end()) ? intermed->second : eTriggerEventType::INVALID;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  //!__ETRIGGEREVENTTYPE__H__
 | 
			
		||||
							
								
								
									
										137
									
								
								dGame/Entity.cpp
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								dGame/Entity.cpp
									
									
									
									
									
								
							@@ -23,6 +23,7 @@
 | 
			
		||||
#include "EntityCallbackTimer.h"
 | 
			
		||||
#include "Loot.h"
 | 
			
		||||
#include "eMissionTaskType.h"
 | 
			
		||||
#include "eTriggerEventType.h"
 | 
			
		||||
 | 
			
		||||
//Component includes:
 | 
			
		||||
#include "Component.h"
 | 
			
		||||
@@ -68,6 +69,7 @@
 | 
			
		||||
#include "ShootingGalleryComponent.h"
 | 
			
		||||
#include "RailActivatorComponent.h"
 | 
			
		||||
#include "LUPExhibitComponent.h"
 | 
			
		||||
#include "TriggerComponent.h"
 | 
			
		||||
#include "ItemComponent.h"
 | 
			
		||||
 | 
			
		||||
Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity) {
 | 
			
		||||
@@ -77,7 +79,6 @@ Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity)
 | 
			
		||||
	m_Character = nullptr;
 | 
			
		||||
	m_GMLevel = 0;
 | 
			
		||||
	m_CollectibleID = 0;
 | 
			
		||||
	m_Trigger = nullptr; //new LUTriggers::Trigger();
 | 
			
		||||
	m_NetworkID = 0;
 | 
			
		||||
	m_Groups = {};
 | 
			
		||||
	m_OwnerOverride = LWOOBJID_EMPTY;
 | 
			
		||||
@@ -133,30 +134,9 @@ void Entity::Initialize() {
 | 
			
		||||
	 * Setup trigger
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	const auto triggerName = GetVarAsString(u"trigger_id");
 | 
			
		||||
	const auto triggerInfo = GetVarAsString(u"trigger_id");
 | 
			
		||||
 | 
			
		||||
	if (!triggerName.empty()) {
 | 
			
		||||
		std::stringstream ss(triggerName);
 | 
			
		||||
		std::vector<std::string> tokens;
 | 
			
		||||
		std::string token;
 | 
			
		||||
		while (std::getline(ss, token, ':')) {
 | 
			
		||||
			tokens.push_back(token);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		uint32_t sceneID = std::stoi(tokens[0]);
 | 
			
		||||
		uint32_t triggerID = std::stoi(tokens[1]);
 | 
			
		||||
 | 
			
		||||
		if (m_Trigger != nullptr) {
 | 
			
		||||
			delete m_Trigger;
 | 
			
		||||
			m_Trigger = nullptr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_Trigger = dZoneManager::Instance()->GetZone()->GetTrigger(sceneID, triggerID);
 | 
			
		||||
 | 
			
		||||
		if (m_Trigger == nullptr) {
 | 
			
		||||
			m_Trigger = new LUTriggers::Trigger();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (!triggerInfo.empty()) m_Components.emplace(COMPONENT_TYPE_TRIGGER, new TriggerComponent(this, triggerInfo));
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Setup groups
 | 
			
		||||
@@ -770,7 +750,7 @@ void Entity::Initialize() {
 | 
			
		||||
 | 
			
		||||
no_ghosting:
 | 
			
		||||
 | 
			
		||||
	TriggerEvent("OnCreate");
 | 
			
		||||
	TriggerEvent(eTriggerEventType::CREATE);
 | 
			
		||||
 | 
			
		||||
	if (m_Character) {
 | 
			
		||||
		auto* controllablePhysicsComponent = GetComponent<ControllablePhysicsComponent>();
 | 
			
		||||
@@ -947,12 +927,16 @@ void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacke
 | 
			
		||||
			outBitStream->Write0(); //No ldf data
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_Trigger != nullptr && m_Trigger->events.size() > 0) {
 | 
			
		||||
			outBitStream->Write1();
 | 
			
		||||
		} else {
 | 
			
		||||
		TriggerComponent* triggerComponent;
 | 
			
		||||
		if (TryGetComponent(COMPONENT_TYPE_TRIGGER, triggerComponent)) {
 | 
			
		||||
			// has trigger component, check to see if we have events to handle
 | 
			
		||||
			auto* trigger = triggerComponent->GetTrigger();
 | 
			
		||||
			outBitStream->Write<bool>(trigger && trigger->events.size() > 0);
 | 
			
		||||
		} else { // no trigger componenet, so definitely no triggers
 | 
			
		||||
			outBitStream->Write0();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		if (m_ParentEntity != nullptr || m_SpawnerID != 0) {
 | 
			
		||||
			outBitStream->Write1();
 | 
			
		||||
			if (m_ParentEntity != nullptr) outBitStream->Write(GeneralUtils::SetBit(m_ParentEntity->GetObjectID(), OBJECT_BIT_CLIENT));
 | 
			
		||||
@@ -1312,7 +1296,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
 | 
			
		||||
		switchComp->EntityEnter(other);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TriggerEvent("OnEnter", other);
 | 
			
		||||
	TriggerEvent(eTriggerEventType::ENTER, other);
 | 
			
		||||
 | 
			
		||||
	// POI system
 | 
			
		||||
	const auto& poi = GetVar<std::u16string>(u"POI");
 | 
			
		||||
@@ -1346,7 +1330,7 @@ void Entity::OnCollisionLeavePhantom(const LWOOBJID otherEntity) {
 | 
			
		||||
	auto* other = EntityManager::Instance()->GetEntity(otherEntity);
 | 
			
		||||
	if (!other) return;
 | 
			
		||||
 | 
			
		||||
	TriggerEvent("OnLeave", other);
 | 
			
		||||
	TriggerEvent(eTriggerEventType::EXIT, other);
 | 
			
		||||
 | 
			
		||||
	SwitchComponent* switchComp = GetComponent<SwitchComponent>();
 | 
			
		||||
	if (switchComp) {
 | 
			
		||||
@@ -1394,7 +1378,7 @@ void Entity::OnEmoteReceived(const int32_t emote, Entity* target) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Entity::OnUse(Entity* originator) {
 | 
			
		||||
	TriggerEvent("OnInteract");
 | 
			
		||||
	TriggerEvent(eTriggerEventType::INTERACT);
 | 
			
		||||
 | 
			
		||||
	for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
 | 
			
		||||
		script->OnUse(this, originator);
 | 
			
		||||
@@ -1738,94 +1722,9 @@ bool Entity::IsPlayer() const {
 | 
			
		||||
	return m_TemplateID == 1 && GetSystemAddress() != UNASSIGNED_SYSTEM_ADDRESS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Entity::TriggerEvent(std::string eventID, Entity* optionalTarget) {
 | 
			
		||||
	if (m_Trigger != nullptr && m_Trigger->enabled) {
 | 
			
		||||
		for (LUTriggers::Event* triggerEvent : m_Trigger->events) {
 | 
			
		||||
			if (triggerEvent->eventID == eventID) {
 | 
			
		||||
				for (LUTriggers::Command* cmd : triggerEvent->commands) {
 | 
			
		||||
					HandleTriggerCommand(cmd->id, cmd->target, cmd->targetName, cmd->args, optionalTarget);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This should probably get it's own triggers class at some point...
 | 
			
		||||
void Entity::HandleTriggerCommand(std::string id, std::string target, std::string targetName, std::string args, Entity* optionalTarget) {
 | 
			
		||||
	std::vector<std::string> argArray;
 | 
			
		||||
	// Parse args
 | 
			
		||||
	std::stringstream ssData(args);
 | 
			
		||||
	std::string token;
 | 
			
		||||
	char deliminator = ',';
 | 
			
		||||
 | 
			
		||||
	while (std::getline(ssData, token, deliminator)) {
 | 
			
		||||
		std::string lowerToken;
 | 
			
		||||
		for (char character : token) {
 | 
			
		||||
			lowerToken.push_back(std::tolower(character)); // make lowercase to ensure it works
 | 
			
		||||
		}
 | 
			
		||||
		argArray.push_back(lowerToken);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::vector<Entity*> targetEntities;
 | 
			
		||||
	if (target == "self") targetEntities.push_back(this);
 | 
			
		||||
	if (target == "objGroup") targetEntities = EntityManager::Instance()->GetEntitiesInGroup(targetName);
 | 
			
		||||
	if (optionalTarget) targetEntities.push_back(optionalTarget);
 | 
			
		||||
	if (targetEntities.size() == 0) return;
 | 
			
		||||
	for (Entity* targetEntity : targetEntities) {
 | 
			
		||||
		if (!targetEntity) continue;
 | 
			
		||||
 | 
			
		||||
		if (id == "SetPhysicsVolumeEffect") {
 | 
			
		||||
			PhantomPhysicsComponent* phanPhys = GetComponent<PhantomPhysicsComponent>();
 | 
			
		||||
			if (!phanPhys) return;
 | 
			
		||||
 | 
			
		||||
			phanPhys->SetPhysicsEffectActive(true);
 | 
			
		||||
			uint32_t effectType = 0;
 | 
			
		||||
			if (argArray[0] == "push") effectType = 0;
 | 
			
		||||
			else if (argArray[0] == "attract") effectType = 1;
 | 
			
		||||
			else if (argArray[0] == "repulse") effectType = 2;
 | 
			
		||||
			else if (argArray[0] == "gravity") effectType = 3;
 | 
			
		||||
			else if (argArray[0] == "friction") effectType = 4;
 | 
			
		||||
 | 
			
		||||
			phanPhys->SetEffectType(effectType);
 | 
			
		||||
			phanPhys->SetDirectionalMultiplier(std::stof(argArray[1]));
 | 
			
		||||
			if (argArray.size() > 4) {
 | 
			
		||||
				NiPoint3 direction = NiPoint3::ZERO;
 | 
			
		||||
				GeneralUtils::TryParse<float>(argArray[2], direction.x);
 | 
			
		||||
				GeneralUtils::TryParse<float>(argArray[3], direction.y);
 | 
			
		||||
				GeneralUtils::TryParse<float>(argArray[4], direction.z);
 | 
			
		||||
				phanPhys->SetDirection(direction);
 | 
			
		||||
			}
 | 
			
		||||
			if (argArray.size() > 5) {
 | 
			
		||||
				phanPhys->SetMin(std::stoi(argArray[6]));
 | 
			
		||||
				phanPhys->SetMax(std::stoi(argArray[7]));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (target == "self") {
 | 
			
		||||
				EntityManager::Instance()->ConstructEntity(this);
 | 
			
		||||
			}
 | 
			
		||||
		} else if (id == "updateMission") {
 | 
			
		||||
			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]));
 | 
			
		||||
			}
 | 
			
		||||
		} else if (id == "fireEvent") {
 | 
			
		||||
			for (CppScripts::Script* script : CppScripts::GetEntityScripts(targetEntity)) {
 | 
			
		||||
				script->OnFireEventServerSide(targetEntity, this, args, 0, 0, 0);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
void Entity::TriggerEvent(eTriggerEventType event, Entity* optionalTarget) {
 | 
			
		||||
	auto* triggerComponent = GetComponent<TriggerComponent>();
 | 
			
		||||
	if (triggerComponent) triggerComponent->TriggerEvent(event, optionalTarget);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Entity* Entity::GetOwner() const {
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,6 @@ namespace Loot {
 | 
			
		||||
namespace tinyxml2 {
 | 
			
		||||
	class XMLDocument;
 | 
			
		||||
};
 | 
			
		||||
namespace LUTriggers {
 | 
			
		||||
	struct Trigger;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Player;
 | 
			
		||||
class EntityInfo;
 | 
			
		||||
@@ -33,6 +30,7 @@ class Component;
 | 
			
		||||
class Item;
 | 
			
		||||
class Character;
 | 
			
		||||
class EntityCallbackTimer;
 | 
			
		||||
enum class eTriggerEventType;
 | 
			
		||||
 | 
			
		||||
namespace CppScripts {
 | 
			
		||||
	class Script;
 | 
			
		||||
@@ -67,8 +65,6 @@ public:
 | 
			
		||||
 | 
			
		||||
	Entity* GetParentEntity() const { return m_ParentEntity; }
 | 
			
		||||
 | 
			
		||||
	LUTriggers::Trigger* GetTrigger() const { return m_Trigger; }
 | 
			
		||||
 | 
			
		||||
	std::vector<std::string>& GetGroups() { return m_Groups; };
 | 
			
		||||
 | 
			
		||||
	Spawner* GetSpawner() const { return m_Spawner; }
 | 
			
		||||
@@ -221,9 +217,8 @@ public:
 | 
			
		||||
	void RegisterCoinDrop(uint64_t count);
 | 
			
		||||
 | 
			
		||||
	void ScheduleKillAfterUpdate(Entity* murderer = nullptr);
 | 
			
		||||
	void TriggerEvent(std::string eveneventtID, Entity* optionalTarget = nullptr);
 | 
			
		||||
	void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr);
 | 
			
		||||
	void ScheduleDestructionAfterUpdate() { m_ShouldDestroyAfterUpdate = true; }
 | 
			
		||||
	void HandleTriggerCommand(std::string id, std::string target, std::string targetName, std::string args, Entity* optionalTarget);
 | 
			
		||||
 | 
			
		||||
	virtual NiPoint3 GetRespawnPosition() const { return NiPoint3::ZERO; }
 | 
			
		||||
	virtual NiQuaternion GetRespawnRotation() const { return NiQuaternion::IDENTITY; }
 | 
			
		||||
@@ -308,8 +303,6 @@ protected:
 | 
			
		||||
	bool m_HasSpawnerNodeID;
 | 
			
		||||
	uint32_t m_SpawnerNodeID;
 | 
			
		||||
 | 
			
		||||
	LUTriggers::Trigger* m_Trigger;
 | 
			
		||||
 | 
			
		||||
	Character* m_Character;
 | 
			
		||||
 | 
			
		||||
	Entity* m_ParentEntity; //For spawners and the like
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
#include "dLogger.h"
 | 
			
		||||
#include "MessageIdentifiers.h"
 | 
			
		||||
#include "dConfig.h"
 | 
			
		||||
#include "eTriggerEventType.h"
 | 
			
		||||
 | 
			
		||||
EntityManager* EntityManager::m_Address = nullptr;
 | 
			
		||||
 | 
			
		||||
@@ -585,7 +586,7 @@ void EntityManager::ScheduleForKill(Entity* entity) {
 | 
			
		||||
 | 
			
		||||
	SwitchComponent* switchComp = entity->GetComponent<SwitchComponent>();
 | 
			
		||||
	if (switchComp) {
 | 
			
		||||
		entity->TriggerEvent("OnDectivated");
 | 
			
		||||
		entity->TriggerEvent(eTriggerEventType::DEACTIVATED);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const auto objectId = entity->GetObjectID();
 | 
			
		||||
 
 | 
			
		||||
@@ -40,5 +40,6 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
 | 
			
		||||
	"SkillComponent.cpp"
 | 
			
		||||
	"SoundTriggerComponent.cpp"
 | 
			
		||||
	"SwitchComponent.cpp"
 | 
			
		||||
	"TriggerComponent.cpp"
 | 
			
		||||
	"VehiclePhysicsComponent.cpp"
 | 
			
		||||
	"VendorComponent.cpp" PARENT_SCOPE)
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,13 @@
 | 
			
		||||
#include "EchoStartSkill.h"
 | 
			
		||||
#include "dMessageIdentifiers.h"
 | 
			
		||||
#include "DoClientProjectileImpact.h"
 | 
			
		||||
#include "CDClientManager.h"
 | 
			
		||||
 | 
			
		||||
ProjectileSyncEntry::ProjectileSyncEntry() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::unordered_map<uint32_t, uint32_t> SkillComponent::m_skillBehaviorCache = {};
 | 
			
		||||
 | 
			
		||||
bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t skillUid, RakNet::BitStream* bitStream, const LWOOBJID target, uint32_t skillID) {
 | 
			
		||||
	auto* context = new BehaviorContext(this->m_Parent->GetObjectID());
 | 
			
		||||
 | 
			
		||||
@@ -210,6 +213,29 @@ void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, B
 | 
			
		||||
	this->m_managedProjectiles.push_back(entry);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID){
 | 
			
		||||
	uint32_t behaviorId = -1;
 | 
			
		||||
	// try to find it via the cache
 | 
			
		||||
	const auto& pair = m_skillBehaviorCache.find(skillId);
 | 
			
		||||
 | 
			
		||||
	// if it's not in the cache look it up and cache it
 | 
			
		||||
	if (pair == m_skillBehaviorCache.end()) {
 | 
			
		||||
		auto skillTable = CDClientManager::Instance()->GetTable<CDSkillBehaviorTable>("SkillBehavior");
 | 
			
		||||
		behaviorId = skillTable->GetSkillByID(skillId).behaviorID;
 | 
			
		||||
		m_skillBehaviorCache.insert_or_assign(skillId, behaviorId);
 | 
			
		||||
	} else {
 | 
			
		||||
		behaviorId = pair->second;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check to see if we got back a valid behavior
 | 
			
		||||
	if (behaviorId == -1) {
 | 
			
		||||
		Game::logger->LogDebug("SkillComponent", "Tried to cast skill %i but found no behavior", skillId);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return CalculateBehavior(skillId, behaviorId, target, false, false, optionalOriginatorID).success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, const uint32_t behaviorId, const LWOOBJID target, const bool ignoreTarget, const bool clientInitalized, const LWOOBJID originatorOverride) {
 | 
			
		||||
	auto* bitStream = new RakNet::BitStream();
 | 
			
		||||
 
 | 
			
		||||
@@ -119,6 +119,15 @@ public:
 | 
			
		||||
	 */
 | 
			
		||||
	void RegisterPlayerProjectile(LWOOBJID projectileId, BehaviorContext* context, const BehaviorBranchContext& branch, LOT lot);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Wrapper for CalculateBehavior that mimics the call structure in scripts and helps reduce magic numbers
 | 
			
		||||
	 * @param skillId the skill to cast
 | 
			
		||||
	 * @param target the target of the skill
 | 
			
		||||
	 * @param optionalOriginatorID change the originator of the skill
 | 
			
		||||
	 * @return if the case succeeded
 | 
			
		||||
	 */
 | 
			
		||||
	bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Initializes a server-side skill calculation.
 | 
			
		||||
	 * @param skillId the skill ID
 | 
			
		||||
@@ -190,6 +199,11 @@ private:
 | 
			
		||||
	 */
 | 
			
		||||
	uint32_t m_skillUid;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Cache for looking up a behavior id via a skill ID
 | 
			
		||||
	 */
 | 
			
		||||
	static std::unordered_map<uint32_t, uint32_t> m_skillBehaviorCache;
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Sync a server-side projectile calculation.
 | 
			
		||||
	 * @param entry the projectile information
 | 
			
		||||
 
 | 
			
		||||
@@ -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");
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										187
									
								
								dGame/dComponents/TriggerComponent.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								dGame/dComponents/TriggerComponent.cpp
									
									
									
									
									
										Normal 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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										34
									
								
								dGame/dComponents/TriggerComponent.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								dGame/dComponents/TriggerComponent.h
									
									
									
									
									
										Normal 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__
 | 
			
		||||
@@ -73,6 +73,7 @@
 | 
			
		||||
#include "MovingPlatformComponent.h"
 | 
			
		||||
#include "dMessageIdentifiers.h"
 | 
			
		||||
#include "eMissionState.h"
 | 
			
		||||
#include "TriggerComponent.h"
 | 
			
		||||
 | 
			
		||||
void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entity* entity, const SystemAddress& sysAddr) {
 | 
			
		||||
	std::string chatCommand;
 | 
			
		||||
@@ -1984,8 +1985,12 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
 | 
			
		||||
					ChatPackets::SendSystemMessage(sysAddr, u"Active: " + (GeneralUtils::to_u16string(phantomPhysicsComponent->GetPhysicsEffectActive())));
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (closest->GetTrigger() != nullptr) {
 | 
			
		||||
					ChatPackets::SendSystemMessage(sysAddr, u"Trigger: " + (GeneralUtils::to_u16string(closest->GetTrigger()->id)));
 | 
			
		||||
				auto* triggerComponent = closest->GetComponent<TriggerComponent>();
 | 
			
		||||
				if (triggerComponent){
 | 
			
		||||
					auto trigger = triggerComponent->GetTrigger();
 | 
			
		||||
					if (trigger) {
 | 
			
		||||
						ChatPackets::SendSystemMessage(sysAddr, u"Trigger: " + (GeneralUtils::to_u16string(trigger->id)));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ void CoilBackpackBase::NotifyHitOrHealResult(Entity* self, Entity* attacker, int
 | 
			
		||||
		if (self->GetVar<uint8_t>(u"coilCount") > 4) {
 | 
			
		||||
			auto* skillComponent = self->GetComponent<SkillComponent>();
 | 
			
		||||
			if (!skillComponent) return;
 | 
			
		||||
			skillComponent->CalculateBehavior(m_SkillId, m_BehaviorId, self->GetObjectID());
 | 
			
		||||
			skillComponent->CastSkill(m_SkillId);
 | 
			
		||||
			self->SetVar<uint8_t>(u"coilCount", 0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,8 @@
 | 
			
		||||
 | 
			
		||||
class CoilBackpackBase: public CppScripts::Script {
 | 
			
		||||
public:
 | 
			
		||||
	CoilBackpackBase(uint32_t skillId, uint32_t behaviorId) {
 | 
			
		||||
	CoilBackpackBase(uint32_t skillId) {
 | 
			
		||||
		m_SkillId = skillId;
 | 
			
		||||
		m_BehaviorId = behaviorId;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void OnFactionTriggerItemEquipped(Entity* itemOwner, LWOOBJID itemObjId) override;
 | 
			
		||||
@@ -15,7 +14,6 @@ public:
 | 
			
		||||
	void OnFactionTriggerItemUnequipped(Entity* itemOwner, LWOOBJID itemObjId) override;
 | 
			
		||||
private:
 | 
			
		||||
	uint32_t m_SkillId = 0;
 | 
			
		||||
	uint32_t m_BehaviorId = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  //!__GemPackBase__H__
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,9 @@
 | 
			
		||||
 | 
			
		||||
class GemPack : public CoilBackpackBase {
 | 
			
		||||
public:
 | 
			
		||||
	GemPack() : CoilBackpackBase(skillId, behaviorId) {};
 | 
			
		||||
	GemPack() : CoilBackpackBase(skillId) {};
 | 
			
		||||
private:
 | 
			
		||||
	static const uint32_t skillId = 1488;
 | 
			
		||||
	static const uint32_t behaviorId = 36779;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  //!__GEMPACK__H__
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,9 @@
 | 
			
		||||
 | 
			
		||||
class ShardArmor : public CoilBackpackBase {
 | 
			
		||||
public:
 | 
			
		||||
	ShardArmor() : CoilBackpackBase(skillId, behaviorId) {};
 | 
			
		||||
	ShardArmor() : CoilBackpackBase(skillId) {};
 | 
			
		||||
private:
 | 
			
		||||
	static const uint32_t skillId = 1249;
 | 
			
		||||
	static const uint32_t behaviorId = 29086;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  //!__SHARDARMOR__H__
 | 
			
		||||
 
 | 
			
		||||
@@ -5,10 +5,9 @@
 | 
			
		||||
 | 
			
		||||
class TeslaPack : public CoilBackpackBase {
 | 
			
		||||
public:
 | 
			
		||||
	TeslaPack() : CoilBackpackBase(skillId, behaviorId) {};
 | 
			
		||||
	TeslaPack() : CoilBackpackBase(skillId) {};
 | 
			
		||||
private:
 | 
			
		||||
	static const uint32_t skillId = 1001;
 | 
			
		||||
	static const uint32_t behaviorId = 20917;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  //!__TESLAPACK__H__
 | 
			
		||||
 
 | 
			
		||||
@@ -6,17 +6,20 @@
 | 
			
		||||
 | 
			
		||||
class Command;
 | 
			
		||||
class Event;
 | 
			
		||||
enum class eTriggerCommandType;
 | 
			
		||||
enum class eTriggerEventType;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace LUTriggers {
 | 
			
		||||
	struct Command {
 | 
			
		||||
		std::string id;
 | 
			
		||||
		eTriggerCommandType id;
 | 
			
		||||
		std::string target;
 | 
			
		||||
		std::string targetName;
 | 
			
		||||
		std::string args;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Event {
 | 
			
		||||
		std::string eventID;
 | 
			
		||||
		eTriggerEventType id;
 | 
			
		||||
		std::vector<Command*> commands;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,9 @@
 | 
			
		||||
#include "Spawner.h"
 | 
			
		||||
#include "dZoneManager.h"
 | 
			
		||||
 | 
			
		||||
#include "eTriggerCommandType.h"
 | 
			
		||||
#include "eTriggerEventType.h"
 | 
			
		||||
 | 
			
		||||
Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) :
 | 
			
		||||
	m_ZoneID(mapID, instanceID, cloneID) {
 | 
			
		||||
	m_NumberOfScenesLoaded = 0;
 | 
			
		||||
@@ -296,11 +299,11 @@ std::vector<LUTriggers::Trigger*> Zone::LoadLUTriggers(std::string triggerFile,
 | 
			
		||||
		auto currentEvent = currentTrigger->FirstChildElement("event");
 | 
			
		||||
		while (currentEvent) {
 | 
			
		||||
			LUTriggers::Event* newEvent = new LUTriggers::Event();
 | 
			
		||||
			newEvent->eventID = currentEvent->Attribute("id");
 | 
			
		||||
			newEvent->id = TriggerEventType::StringToTriggerEventType(currentEvent->Attribute("id"));
 | 
			
		||||
			auto currentCommand = currentEvent->FirstChildElement("command");
 | 
			
		||||
			while (currentCommand) {
 | 
			
		||||
				LUTriggers::Command* newCommand = new LUTriggers::Command();
 | 
			
		||||
				newCommand->id = currentCommand->Attribute("id");
 | 
			
		||||
				newCommand->id = TriggerCommandType::StringToTriggerCommandType(currentCommand->Attribute("id"));
 | 
			
		||||
				newCommand->target = currentCommand->Attribute("target");
 | 
			
		||||
				if (currentCommand->Attribute("targetName") != NULL) {
 | 
			
		||||
					newCommand->targetName = currentCommand->Attribute("targetName");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user