Compare commits

..

35 Commits

Author SHA1 Message Date
David Markowitz
90ac91e0df Use consistent calling
try to always have the first parameter match how you got the script for readability
2024-03-06 03:23:37 -08:00
David Markowitz
946b59f02f fix incorrect script grab for trigger 2024-03-06 03:19:49 -08:00
David Markowitz
e76996f98f Update CMakeLists.txt 2024-03-06 02:12:27 -08:00
David Markowitz
109f556ef7 Merge branch 'main' into remove-multiple-script-syntax-ffffffffff 2024-03-06 02:11:27 -08:00
David Markowitz
e1d176260a Merge branch 'main' into remove-multiple-script-syntax-ffffffffff 2024-03-04 03:12:57 -08:00
David Markowitz
c09f46aadc Update CppScripts.h 2024-03-04 03:12:52 -08:00
David Markowitz
3fa5d4791d Merge branch 'specify-path' into remove-multiple-script-syntax-ffffffffff 2024-03-03 04:42:32 -08:00
David Markowitz
261eb2295d Merge branch 'fix/cmake-libs-2' into remove-multiple-script-syntax-ffffffffff 2024-03-03 04:36:52 -08:00
David Markowitz
da15c6d16b Remove code changes
Will fix in another PR.
2024-03-03 04:32:31 -08:00
David Markowitz
5807dccda7 fix include paths 2024-03-03 04:30:03 -08:00
David Markowitz
247b88dbd5 fix include paths 2024-03-03 04:29:09 -08:00
David Markowitz
9ac922bbaa remove syntax of multiple scripts 2024-03-03 04:18:22 -08:00
David Markowitz
2eadfa2efb Merge branch 'main' into fix/cmake-libs-2 2024-03-03 04:17:27 -08:00
David Markowitz
8907cd467d fix not building on unix 2024-01-25 02:45:47 -08:00
David Markowitz
702dcbb8d2 Merge branch 'main' into fix/cmake-libs-2 2024-01-25 02:43:29 -08:00
Xiphoseer
6b94e7f9ed try: install_name_tool 2024-01-05 23:29:40 +01:00
Xiphoseer
decce5b4c5 fix: macos? 2024-01-05 22:54:07 +01:00
Xiphoseer
a52cfb5b0b fix: macos? 2024-01-05 22:32:27 +01:00
Xiphoseer
4569ea29d5 fix: macos? 2024-01-05 22:18:39 +01:00
Xiphoseer
dab70ac096 fix: macos? 2024-01-05 21:45:50 +01:00
Xiphoseer
94c56e527a fix: macos? 2024-01-05 21:17:44 +01:00
Xiphoseer
7c1c4d7581 fix: Dockerfile 2024-01-05 21:01:13 +01:00
Xiphoseer
cb84dbcc22 fix: macos? 2024-01-05 20:59:52 +01:00
Xiphoseer
6fb88e79a0 fix: dPropertyBehaviors 2024-01-05 20:28:18 +01:00
Xiphoseer
cb065a07af feat: Move scripts to CMAKE_MODULE_PATH 2024-01-05 20:14:07 +01:00
Xiphoseer
17305831a1 fix: mariadb C/C++ on apple 2024-01-05 20:14:07 +01:00
Xiphoseer
259067c64a fix: update dockerfile 2024-01-05 20:14:07 +01:00
Xiphoseer
a166e3ef3f wip: try simplified connector build 2024-01-05 20:14:07 +01:00
Xiphoseer
2ad3cb79d3 fix: bcrypt 2024-01-05 20:14:07 +01:00
Xiphoseer
d6d5cb7515 fix: rebase 2024-01-05 20:14:07 +01:00
Xiphoseer
d67ac7759b fix: object libs 2024-01-05 20:14:07 +01:00
Xiphoseer
4586a0ffea fix: dCommon 2024-01-05 20:14:07 +01:00
Xiphoseer
7509237e69 fix: dDatabase 2024-01-05 20:14:07 +01:00
Xiphoseer
0f1e226960 fix: remove dZoneManager from global include 2024-01-05 20:14:07 +01:00
Xiphoseer
bfe39a919e fix: more include changes 2024-01-05 20:14:07 +01:00
46 changed files with 295 additions and 880 deletions

View File

@@ -4,8 +4,6 @@ include(CTest)
set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file

View File

@@ -264,8 +264,8 @@ namespace GeneralUtils {
* @returns The enum entry's value in its underlying type
*/
template <Enum eType>
constexpr std::underlying_type_t<eType> ToUnderlying(const eType entry) noexcept {
return static_cast<std::underlying_type_t<eType>>(entry);
constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) noexcept {
return static_cast<typename std::underlying_type_t<eType>>(entry);
}
// on Windows we need to undef these or else they conflict with our numeric limits calls

View File

@@ -1,59 +0,0 @@
#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

@@ -58,7 +58,7 @@ void CDLootTableTable::LoadValuesFromDatabase() {
CDLootTable entry;
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
entries[lootTableIndex].emplace_back(ReadRow(tableData));
entries[lootTableIndex].push_back(ReadRow(tableData));
tableData.nextRow();
}
for (auto& [id, table] : entries) {
@@ -66,7 +66,7 @@ void CDLootTableTable::LoadValuesFromDatabase() {
}
}
const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) {
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
auto& entries = GetEntriesMutable();
auto itr = entries.find(tableId);
if (itr != entries.end()) {
@@ -79,7 +79,7 @@ const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) {
while (!tableData.eof()) {
CDLootTable entry;
entries[tableId].emplace_back(ReadRow(tableData));
entries[tableId].push_back(ReadRow(tableData));
tableData.nextRow();
}
SortTable(entries[tableId]);

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDLootTable {
uint32_t itemid; //!< The LOT of the item
uint32_t LootTableIndex; //!< The Loot Table Index
@@ -22,5 +20,6 @@ private:
public:
void LoadValuesFromDatabase();
// Queries the table with a custom "where" clause
const LootTableEntries& GetTable(const uint32_t tableId);
const LootTableEntries& GetTable(uint32_t tableId);
};

View File

@@ -20,7 +20,7 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail");
while (!tableData.eof()) {
auto& entry = entries.emplace_back();
CDMissionEmail entry;
entry.ID = tableData.getIntField("ID", -1);
entry.messageType = tableData.getIntField("messageType", -1);
entry.notificationGroup = tableData.getIntField("notificationGroup", -1);
@@ -30,8 +30,11 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
entry.locStatus = tableData.getIntField("locStatus", -1);
entry.gate_version = tableData.getStringField("gate_version", "");
entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
//! Queries the table with a custom "where" clause

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDMissionEmail {
uint32_t ID;
uint32_t messageType;

View File

@@ -20,15 +20,18 @@ void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent");
while (!tableData.eof()) {
auto& entry = entries.emplace_back();
CDMissionNPCComponent entry;
entry.id = tableData.getIntField("id", -1);
entry.missionID = tableData.getIntField("missionID", -1);
entry.offersMission = tableData.getIntField("offersMission", -1) == 1 ? true : false;
entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false;
entry.gate_version = tableData.getStringField("gate_version", "");
entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
//! Queries the table with a custom "where" clause

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDMissionNPCComponent {
uint32_t id; //!< The ID
uint32_t missionID; //!< The Mission ID
@@ -19,3 +17,4 @@ public:
// Queries the table with a custom "where" clause
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
};

View File

@@ -20,7 +20,7 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks");
while (!tableData.eof()) {
auto& entry = entries.emplace_back();
CDMissionTasks entry;
entry.id = tableData.getIntField("id", -1);
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
entry.taskType = tableData.getIntField("taskType", -1);
@@ -35,8 +35,11 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false);
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) {
@@ -48,7 +51,7 @@ std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMiss
return data;
}
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(const uint32_t missionID) {
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) {
std::vector<CDMissionTasks*> tasks;
// TODO: this should not be linear(?) and also shouldnt need to be a pointer

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDMissionTasks {
uint32_t id; //!< The Mission ID that the task belongs to
UNUSED(uint32_t locStatus); //!< ???
@@ -27,7 +25,7 @@ public:
// Queries the table with a custom "where" clause
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
std::vector<CDMissionTasks*> GetByMissionID(const uint32_t missionID);
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
// TODO: Remove this and replace it with a proper lookup function.
const CDTable::StorageType& GetEntries() const;

View File

@@ -22,7 +22,7 @@ void CDMissionsTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions");
while (!tableData.eof()) {
auto& entry = entries.emplace_back();
CDMissions entry;
entry.id = tableData.getIntField("id", -1);
entry.defined_type = tableData.getStringField("defined_type", "");
entry.defined_subtype = tableData.getStringField("defined_subtype", "");
@@ -76,6 +76,7 @@ void CDMissionsTable::LoadValuesFromDatabase() {
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1);
entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();

View File

@@ -75,3 +75,4 @@ public:
static CDMissions Default;
};

View File

@@ -20,7 +20,7 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent");
while (!tableData.eof()) {
auto& entry = entries.emplace_back();
CDMovementAIComponent entry;
entry.id = tableData.getIntField("id", -1);
entry.MovementType = tableData.getStringField("MovementType", "");
entry.WanderChance = tableData.getFloatField("WanderChance", -1.0f);
@@ -30,8 +30,11 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f);
entry.attachedPath = tableData.getStringField("attachedPath", "");
entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDMovementAIComponent {
uint32_t id;
std::string MovementType;

View File

@@ -20,14 +20,17 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills");
while (!tableData.eof()) {
auto &entry = entries.emplace_back();
CDObjectSkills entry;
entry.objectTemplate = tableData.getIntField("objectTemplate", -1);
entry.skillID = tableData.getIntField("skillID", -1);
entry.castOnType = tableData.getIntField("castOnType", -1);
entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1);
entries.push_back(entry);
tableData.nextRow();
}
tableData.finalize();
}
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDObjectSkills {
uint32_t objectTemplate; //!< The LOT of the item
uint32_t skillID; //!< The Skill ID of the object

View File

@@ -1,7 +1,7 @@
#include "CDObjectsTable.h"
namespace {
CDObjects ObjDefault;
CDObjects m_default;
};
void CDObjectsTable::LoadValuesFromDatabase() {
@@ -20,10 +20,8 @@ void CDObjectsTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) {
const uint32_t lot = tableData.getIntField("id", 0);
auto& entry = entries[lot];
entry.id = lot;
CDObjects entry;
entry.id = tableData.getIntField("id", -1);
entry.name = tableData.getStringField("name", "");
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
entry.type = tableData.getStringField("type", "");
@@ -38,34 +36,35 @@ void CDObjectsTable::LoadValuesFromDatabase() {
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow();
}
ObjDefault.id = 0;
tableData.finalize();
m_default.id = 0;
}
const CDObjects& CDObjectsTable::GetByID(const uint32_t lot) {
const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
auto& entries = GetEntriesMutable();
const auto& it = entries.find(lot);
const auto& it = entries.find(LOT);
if (it != entries.end()) {
return it->second;
}
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
query.bind(1, static_cast<int32_t>(lot));
query.bind(1, static_cast<int32_t>(LOT));
auto tableData = query.execQuery();
if (tableData.eof()) {
entries.emplace(lot, ObjDefault);
return ObjDefault;
entries.insert(std::make_pair(LOT, m_default));
return m_default;
}
// Now get the data
while (!tableData.eof()) {
const uint32_t lot = tableData.getIntField("id", 0);
auto& entry = entries[lot];
entry.id = lot;
CDObjects entry;
entry.id = tableData.getIntField("id", -1);
entry.name = tableData.getStringField("name", "");
UNUSED(entry.placeable = tableData.getIntField("placeable", -1));
entry.type = tableData.getStringField("type", "");
@@ -80,15 +79,17 @@ const CDObjects& CDObjectsTable::GetByID(const uint32_t lot) {
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1));
entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow();
}
tableData.finalize();
const auto& it2 = entries.find(lot);
const auto& it2 = entries.find(LOT);
if (it2 != entries.end()) {
return it2->second;
}
return ObjDefault;
return m_default;
}

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDObjects {
uint32_t id; //!< The LOT of the object
std::string name; //!< The internal name of the object
@@ -26,6 +24,6 @@ class CDObjectsTable : public CDTable<CDObjectsTable, std::map<uint32_t, CDObjec
public:
void LoadValuesFromDatabase();
// Gets an entry by ID
const CDObjects& GetByID(const uint32_t lot);
const CDObjects& GetByID(uint32_t LOT);
};

View File

@@ -19,11 +19,12 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
// Now get the data
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent");
while (!tableData.eof()) {
auto& entry = entries.emplace_back();
CDPackageComponent entry;
entry.id = tableData.getIntField("id", -1);
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
entry.packageType = tableData.getIntField("packageType", -1);
entries.push_back(entry);
tableData.nextRow();
}

View File

@@ -3,8 +3,6 @@
// Custom Classes
#include "CDTable.h"
#include <cstdint>
struct CDPackageComponent {
uint32_t id;
uint32_t LootMatrixIndex;

View File

@@ -4,31 +4,32 @@ void CDPhysicsComponentTable::LoadValuesFromDatabase() {
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
auto& entries = GetEntriesMutable();
while (!tableData.eof()) {
const uint32_t componentID = tableData.getIntField("id", -1);
auto& entry = entries[componentID];
entry.id = componentID;
CDPhysicsComponent entry;
entry.id = tableData.getIntField("id", -1);
entry.bStatic = tableData.getIntField("static", -1) != 0;
entry.physicsAsset = tableData.getStringField("physics_asset", "");
UNUSED_COLUMN(entry.jump = tableData.getIntField("jump", -1) != 0;)
UNUSED_COLUMN(entry.doubleJump = tableData.getIntField("doublejump", -1) != 0;)
entry.speed = static_cast<float>(tableData.getFloatField("speed", -1));
UNUSED_COLUMN(entry.rotSpeed = tableData.getFloatField("rotSpeed", -1);)
entry.playerHeight = static_cast<float>(tableData.getFloatField("playerHeight"));
entry.playerRadius = static_cast<float>(tableData.getFloatField("playerRadius"));
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
entry.speed = tableData.getFloatField("speed", -1);
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
entry.playerHeight = tableData.getFloatField("playerHeight");
entry.playerRadius = tableData.getFloatField("playerRadius");
entry.pcShapeType = tableData.getIntField("pcShapeType");
entry.collisionGroup = tableData.getIntField("collisionGroup");
UNUSED_COLUMN(entry.airSpeed = tableData.getFloatField("airSpeed");)
UNUSED_COLUMN(entry.boundaryAsset = tableData.getStringField("boundaryAsset");)
UNUSED_COLUMN(entry.jumpAirSpeed = tableData.getFloatField("jumpAirSpeed");)
UNUSED_COLUMN(entry.friction = tableData.getFloatField("friction");)
UNUSED_COLUMN(entry.gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset");)
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
UNUSED(entry->friction = tableData.getFloatField("friction"));
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
entries.insert(std::make_pair(entry.id, entry));
tableData.nextRow();
}
tableData.finalize();
}
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(const uint32_t componentID) {
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(uint32_t componentID) {
auto& entries = GetEntriesMutable();
auto itr = entries.find(componentID);
return itr != entries.end() ? &itr->second : nullptr;

View File

@@ -1,6 +1,5 @@
#pragma once
#include "CDTable.h"
#include <cstdint>
#include <string>
struct CDPhysicsComponent {
@@ -8,7 +7,7 @@ struct CDPhysicsComponent {
bool bStatic;
std::string physicsAsset;
UNUSED(bool jump);
UNUSED(bool doubleJump);
UNUSED(bool doublejump);
float speed;
UNUSED(float rotSpeed);
float playerHeight;
@@ -27,5 +26,5 @@ public:
void LoadValuesFromDatabase();
static const std::string GetTableName() { return "PhysicsComponent"; };
CDPhysicsComponent* GetByID(const uint32_t componentID);
CDPhysicsComponent* GetByID(uint32_t componentID);
};

View File

@@ -731,9 +731,15 @@ void Entity::Initialize() {
// if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) {
AddComponent<MovingPlatformComponent>(pathName);
} else if (path->pathType == PathType::Movement) {
AddComponent<MovementAIComponent>(MovementAIInfo{})->SetupPath(pathName);
}
// else if we are a movement path
} /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent<MovementAIComponent>();
if (movementAIcomp){
// TODO: set path in existing movementAIComp
} else {
// TODO: create movementAIcomp and set path
}
}*/
} else {
// else we still need to setup moving platform if it has a moving platform comp but no path
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);

View File

@@ -418,16 +418,10 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
}
void EntityManager::SerializeEntity(Entity* entity) {
if (!entity) return;
EntityManager::SerializeEntity(*entity);
}
if (!entity || entity->GetNetworkId() == 0) return;
void EntityManager::SerializeEntity(const Entity& entity) {
if (entity.GetNetworkId() == 0) return;
if (std::find(m_EntitiesToSerialize.cbegin(), m_EntitiesToSerialize.cend(), entity.GetObjectID()) == m_EntitiesToSerialize.cend()) {
m_EntitiesToSerialize.push_back(entity.GetObjectID());
if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) {
m_EntitiesToSerialize.push_back(entity->GetObjectID());
}
}

View File

@@ -45,7 +45,6 @@ public:
void ConstructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS, bool skipChecks = false);
void DestructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
void SerializeEntity(Entity* entity);
void SerializeEntity(const Entity& entity);
void ConstructAllEntities(const SystemAddress& sysAddr);
void DestructAllEntities(const SystemAddress& sysAddr);

View File

@@ -9,15 +9,11 @@
#include "UserManager.h"
#include "CDMissionsTable.h"
AchievementVendorComponent::AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {
RefreshInventory(true);
};
bool AchievementVendorComponent::SellsItem(Entity* buyer, const LOT lot) {
auto* missionComponent = buyer->GetComponent<MissionComponent>();
if (!missionComponent) return false;
if (m_PlayerPurchasableItems[buyer->GetObjectID()].contains(lot)) {
if (m_PlayerPurchasableItems[buyer->GetObjectID()].contains(lot)){
return true;
}
@@ -39,7 +35,7 @@ void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM);
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
uint32_t costLOT = itemComp.commendationLOT;
if (costLOT == -1 || !SellsItem(buyer, lot)) {
auto* user = UserManager::Instance()->GetUser(buyer->GetSystemAddress());
CheatDetection::ReportCheat(user, buyer->GetSystemAddress(), "Attempted to buy item %i from achievement vendor %i that is not purchasable", lot, m_Parent->GetLOT());
@@ -48,7 +44,7 @@ void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
}
auto* inventoryComponent = buyer->GetComponent<InventoryComponent>();
if (!inventoryComponent) {
if (!inventoryComponent) {
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
return;
}
@@ -73,9 +69,4 @@ void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
}
void AchievementVendorComponent::RefreshInventory(bool isCreation) {
SetHasStandardCostItems(true);
Game::entityManager->SerializeEntity(m_Parent);
}
}

View File

@@ -11,9 +11,7 @@ class Entity;
class AchievementVendorComponent final : public VendorComponent {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ACHIEVEMENT_VENDOR;
AchievementVendorComponent(Entity* parent);
void RefreshInventory(bool isCreation = false) override;
AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {};
bool SellsItem(Entity* buyer, const LOT lot);
void Buy(Entity* buyer, LOT lot, uint32_t count);

View File

@@ -648,7 +648,7 @@ void BaseCombatAIComponent::Wander() {
const NiPoint3 delta =
{
radius * cos(theta),
m_Parent->GetPosition().y,
0,
radius * sin(theta)
};

View File

@@ -26,6 +26,7 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy
m_SpeedMultiplier = 1;
m_GravityScale = 1;
m_DirtyCheats = false;
m_IgnoreMultipliers = false;
m_DirtyEquippedItemInfo = true;
m_PickupRadius = 0.0f;
@@ -65,9 +66,7 @@ ControllablePhysicsComponent::~ControllablePhysicsComponent() {
}
void ControllablePhysicsComponent::Update(float deltaTime) {
if (m_Velocity == NiPoint3Constant::ZERO) return;
SetPosition(m_Position + (m_Velocity * deltaTime));
Game::entityManager->SerializeEntity(m_Parent);
}
void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
@@ -93,31 +92,31 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
outBitStream.Write(m_ImmuneToStunInteractCount);
}
outBitStream.Write(m_DirtyCheats || bIsInitialUpdate);
if (m_DirtyCheats || bIsInitialUpdate) {
if (m_IgnoreMultipliers) m_DirtyCheats = false;
outBitStream.Write(m_DirtyCheats);
if (m_DirtyCheats) {
outBitStream.Write(m_GravityScale);
outBitStream.Write(m_SpeedMultiplier);
if (!bIsInitialUpdate) m_DirtyCheats = false;
m_DirtyCheats = false;
}
outBitStream.Write(m_DirtyEquippedItemInfo || bIsInitialUpdate);
if (m_DirtyEquippedItemInfo || bIsInitialUpdate) {
outBitStream.Write(m_DirtyEquippedItemInfo);
if (m_DirtyEquippedItemInfo) {
outBitStream.Write(m_PickupRadius);
outBitStream.Write(m_InJetpackMode);
if (!bIsInitialUpdate) m_DirtyEquippedItemInfo = false;
m_DirtyEquippedItemInfo = false;
}
outBitStream.Write(m_DirtyBubble || bIsInitialUpdate);
if (m_DirtyBubble || bIsInitialUpdate) {
outBitStream.Write(m_DirtyBubble);
if (m_DirtyBubble) {
outBitStream.Write(m_IsInBubble);
if (m_IsInBubble) {
outBitStream.Write(m_BubbleType);
outBitStream.Write(m_SpecialAnims);
}
if (!bIsInitialUpdate) m_DirtyBubble = false;
m_DirtyBubble = false;
}
outBitStream.Write(m_DirtyPosition || bIsInitialUpdate);
@@ -150,8 +149,7 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
outBitStream.Write(m_AngularVelocity.z);
}
outBitStream.Write0(); // local_space_info, always zero for now.
outBitStream.Write0();
if (!bIsInitialUpdate) {
m_DirtyPosition = false;
outBitStream.Write(m_IsTeleporting);

View File

@@ -174,6 +174,18 @@ public:
*/
const float GetGravityScale() const { return m_GravityScale; }
/**
* Sets the ignore multipliers value, allowing you to skip the serialization of speed and gravity multipliers
* @param value whether or not to ignore multipliers
*/
void SetIgnoreMultipliers(bool value) { m_IgnoreMultipliers = value; }
/**
* Returns the current ignore multipliers value
* @return the current ignore multipliers value
*/
const bool GetIgnoreMultipliers() const { return m_IgnoreMultipliers; }
/**
* Can make an entity static, making it unable to move around
* @param value whether or not the entity is static
@@ -341,6 +353,11 @@ private:
*/
bool m_DirtyCheats;
/**
* Makes it so that the speed multiplier and gravity scale are no longer serialized if false
*/
bool m_IgnoreMultipliers;
/**
* Whether this entity is static, making it unable to move
*/

View File

@@ -316,7 +316,6 @@ public:
*/
const std::vector<int32_t>& GetFactionIDs() const { return m_FactionIDs; }
const bool BelongsToFaction(int32_t factionID) const {return std::find(m_FactionIDs.begin(), m_FactionIDs.end(), factionID) != m_FactionIDs.end(); }
/**
* Returns all the faction IDs that this entity considers an enemy
* @return all the faction IDs that this entity considers an enemy

View File

@@ -12,13 +12,6 @@
#include "CDClientManager.h"
#include "Game.h"
#include "dZoneManager.h"
#include "eTriggerEventType.h"
#include "eWaypointCommandType.h"
#include "RenderComponent.h"
#include "SkillComponent.h"
#include "InventoryComponent.h"
#include "ProximityMonitorComponent.h"
#include "DestroyableComponent.h"
#include "CDComponentsRegistryTable.h"
#include "CDPhysicsComponentTable.h"
@@ -34,7 +27,6 @@ namespace {
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
m_Info = info;
m_IsPaused = true;
m_AtFinalWaypoint = true;
m_BaseCombatAI = nullptr;
@@ -57,61 +49,19 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
m_TimeTravelled = 0;
m_CurrentSpeed = 0;
m_MaxSpeed = 0;
m_StartingWaypointIndex = -1;
m_CurrentPathWaypointIndex = 0;
m_LockRotation = false;
m_IsInReverse = false;
m_NextPathWaypointIndex = 0;
}
float MovementAIComponent::GetCurrentPathWaypointSpeed() const {
if (!m_Path || m_CurrentPathWaypointIndex >= m_CurrentPath.size() || m_CurrentPathWaypointIndex < 0) {
return 1.0f;
}
return m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).movingPlatform.speed;
}
void MovementAIComponent::SetupPath(const std::string& pathname) {
std::string path = pathname;
if (path.empty()) {
path = m_Parent->GetVarAsString(u"attached_path");
if (path.empty()) {
LOG("No path to load for %i:%llu", m_Parent->GetLOT(), m_Parent->GetObjectID());
return;
}
}
const Path* pathData = Game::zoneManager->GetZone()->GetPath(path);
if (pathData) {
LOG("found path %i %s", m_Parent->GetLOT(), path.c_str());
m_Path = pathData;
if (!HasAttachedPathStart() && m_Parent->HasVar(u"attached_path_start")) m_StartingWaypointIndex = m_Parent->GetVar<uint32_t>(u"attached_path_start");
if (m_Path && HasAttachedPathStart() && (m_StartingWaypointIndex < 0 || m_StartingWaypointIndex >= m_Path->pathWaypoints.size())) {
LOG("WARNING: attached path start is out of bounds for %i:%llu, defaulting path start to 0",
m_Parent->GetLOT(), m_Parent->GetObjectID());
m_StartingWaypointIndex = 0;
}
std::vector<NiPoint3> waypoints;
for (const auto& waypoint : m_Path->pathWaypoints) {
waypoints.push_back(waypoint.position);
}
SetPath(waypoints);
} else {
LOG("No path found for %i:%llu", m_Parent->GetLOT(), m_Parent->GetObjectID());
}
}
void MovementAIComponent::Update(const float deltaTime) {
if (m_PullingToPoint) {
const auto source = GetCurrentWaypoint();
// Just a guess at the speed...
const auto speed = deltaTime * 2.5f;
NiPoint3 velocity = (m_PullPoint - source) * speed;
SetPosition(source + velocity);
// We are close enough to the pulled to point, stop pulling
if (Vector3::DistanceSquared(m_Parent->GetPosition(), m_PullPoint) < std::pow(2, 2)) {
m_PullingToPoint = false;
}
@@ -119,8 +69,8 @@ void MovementAIComponent::Update(const float deltaTime) {
return;
}
// Are we done or paused?
if (AtFinalWaypoint() || IsPaused()) return;
// Are we done?
if (AtFinalWaypoint()) return;
if (m_HaltDistance > 0) {
// Prevent us from hugging the target
@@ -140,16 +90,14 @@ void MovementAIComponent::Update(const float deltaTime) {
NiPoint3 velocity = NiPoint3Constant::ZERO;
// If we have no acceleration, then we have no max speed.
// If we have no base speed, then we cannot scale the speed by it.
// Do we have another waypoint to seek?
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) {
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
{
m_NextWaypoint = GetCurrentWaypoint();
if (m_NextWaypoint == source) {
m_TimeToTravel = 0.0f;
return;
goto nextAction;
}
if (m_CurrentSpeed < m_MaxSpeed) {
@@ -160,14 +108,14 @@ void MovementAIComponent::Update(const float deltaTime) {
m_CurrentSpeed = m_MaxSpeed;
}
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed * current speed
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
const auto delta = m_NextWaypoint - source;
// Normalize the vector
const auto length = delta.Length();
if (length > 0) {
velocity = (delta / length).Unitize() * speed;
velocity = (delta / length) * speed;
}
// Calclute the time it will take to reach the next waypoint with the current speed
@@ -177,9 +125,14 @@ void MovementAIComponent::Update(const float deltaTime) {
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
} else {
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
// All checks for how to progress when you arrive at a waypoint will be handled in this else block.
HandleWaypointArrived(0);
return;
if (m_CurrentPath.empty()) {
Stop();
return;
}
SetDestination(m_CurrentPath.top());
m_CurrentPath.pop();
}
nextAction:
@@ -189,27 +142,6 @@ nextAction:
Game::entityManager->SerializeEntity(m_Parent);
}
void MovementAIComponent::ReversePath() {
if (m_CurrentPath.empty()) return;
if (m_NextPathWaypointIndex < 0) m_NextPathWaypointIndex = 0;
if (m_NextPathWaypointIndex >= m_CurrentPath.size()) m_NextPathWaypointIndex = m_CurrentPath.size() - 1;
m_CurrentPathWaypointIndex = m_NextPathWaypointIndex;
m_IsInReverse = !m_IsInReverse;
AdvancePathWaypointIndex();
}
bool MovementAIComponent::AdvancePathWaypointIndex() {
if (m_CurrentPath.empty()) return false;
m_CurrentPathWaypointIndex = m_NextPathWaypointIndex;
if (m_IsInReverse) {
if (m_CurrentPathWaypointIndex >= 0) m_NextPathWaypointIndex--;
return m_CurrentPathWaypointIndex >= 0;
} else {
if (m_CurrentPathWaypointIndex <= m_CurrentPath.size()) m_NextPathWaypointIndex++;
return m_CurrentPathWaypointIndex < m_CurrentPath.size();
}
}
const MovementAIInfo& MovementAIComponent::GetInfo() const {
return m_Info;
}
@@ -230,15 +162,14 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
NiPoint3 MovementAIComponent::ApproximateLocation() const {
auto source = m_Parent->GetPosition();
if (AtFinalWaypoint()) return source;
NiPoint3 approximation = source;
// Only have physics sim for controllable physics
if (!m_Parent->HasComponent(ControllablePhysicsComponent::ComponentType)) {
auto destination = GetNextWaypoint();
auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0;
approximation = source + ((destination - source) * percentageToWaypoint);
}
if (AtFinalWaypoint()) return source;
auto destination = m_NextWaypoint;
auto percentageToWaypoint = m_TimeToTravel > 0 ? m_TimeTravelled / m_TimeToTravel : 0;
auto approximation = source + ((destination - source) * percentageToWaypoint);
if (dpWorld::IsLoaded()) {
approximation.y = dpWorld::GetNavMesh()->GetHeightAtPoint(approximation);
@@ -267,26 +198,6 @@ bool MovementAIComponent::Warp(const NiPoint3& point) {
return true;
}
void MovementAIComponent::Pause() {
if (AtFinalWaypoint() || IsPaused()) return;
SetPosition(ApproximateLocation());
SetVelocity(NiPoint3Constant::ZERO);
// Clear this as we may be somewhere else when we resume movement.
m_InterpolatedWaypoints.clear();
m_IsPaused = true;
m_PathIndex = 0;
m_TimeToTravel = 0;
m_TimeTravelled = 0;
}
void MovementAIComponent::Resume() {
if (AtFinalWaypoint() || !IsPaused()) return;
m_IsPaused = false;
SetDestination(GetCurrentPathWaypoint());
SetMaxSpeed(GetCurrentPathWaypointSpeed());
}
void MovementAIComponent::Stop() {
if (AtFinalWaypoint()) return;
@@ -298,15 +209,13 @@ void MovementAIComponent::Stop() {
m_TimeTravelled = 0;
m_AtFinalWaypoint = true;
m_IsPaused = true;
m_InterpolatedWaypoints.clear();
m_CurrentPath.clear();
while (!m_CurrentPath.empty()) m_CurrentPath.pop();
m_PathIndex = 0;
m_CurrentSpeed = 0;
m_CurrentPathWaypointIndex = 0;
Game::entityManager->SerializeEntity(m_Parent);
}
@@ -318,31 +227,13 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
m_PullPoint = point;
}
const NiPoint3& MovementAIComponent::GetCurrentPathWaypoint() const {
if (m_CurrentPathWaypointIndex >= m_CurrentPath.size() || m_CurrentPathWaypointIndex < 0) {
return m_Parent->GetPosition();
}
return m_CurrentPath.at(m_CurrentPathWaypointIndex);
}
void MovementAIComponent::SetPath(const std::vector<NiPoint3>& path, bool startInReverse) {
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
if (path.empty()) return;
m_CurrentPath = path;
m_IsInReverse = startInReverse;
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) {
this->m_CurrentPath.push(point);
});
// Start the Entity out at the first waypoint with their next waypoint being the same one.
// This is so AdvancePathWaypointIndex can do the recovery from effectively a paused state.
m_CurrentPathWaypointIndex = m_IsInReverse ? m_CurrentPath.size() - 1 : 0;
m_NextPathWaypointIndex = m_IsInReverse ? m_CurrentPath.size() - 1 : 0;
if (HasAttachedPathStart()) {
m_CurrentPathWaypointIndex = m_StartingWaypointIndex;
m_NextPathWaypointIndex = m_StartingWaypointIndex;
}
AdvancePathWaypointIndex();
SetDestination(GetCurrentPathWaypoint());
SetMaxSpeed(GetCurrentPathWaypointSpeed());
SetDestination(path.front());
}
float MovementAIComponent::GetBaseSpeed(LOT lot) {
@@ -415,9 +306,6 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
std::vector<NiPoint3> computedPath;
if (dpWorld::IsLoaded()) {
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
} else {
// If we do not have a navmesh, we do not want an AI to be going towards points that are far below or above the map.
//
}
// Somehow failed
@@ -431,7 +319,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
auto step = delta / 10.0f;
for (int i = 0; i < 10; i++) {
start += step;
// TODO: Replace this with += when the NiPoint3::operator+= is fixed
start = start + step;
computedPath.push_back(start);
}
@@ -454,7 +343,6 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
m_TimeToTravel = 0;
m_AtFinalWaypoint = false;
m_IsPaused = false;
}
NiPoint3 MovementAIComponent::GetDestination() const {
@@ -466,253 +354,3 @@ void MovementAIComponent::SetMaxSpeed(const float value) {
m_MaxSpeed = value;
m_Acceleration = value / 5;
}
void MovementAIComponent::HandleWaypointArrived(uint32_t commandIndex) {
m_Parent->TriggerEvent(eTriggerEventType::ARRIVED);
m_Parent->TriggerEvent(eTriggerEventType::ARRIVED_AT_DESIRED_WAYPOINT);
if (!m_Path || commandIndex >= m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).commands.size()) {
if (!AdvancePathWaypointIndex()) {
// We only want to handle path logic if we actually have a path setup for following
if (m_Path && !m_CurrentPath.empty()) {
if (m_Path->pathBehavior == PathBehavior::Bounce) {
ReversePath();
} else if (m_Path->pathBehavior == PathBehavior::Loop) {
m_CurrentPathWaypointIndex = 0;
m_NextPathWaypointIndex = 0;
AdvancePathWaypointIndex();
SetDestination(GetCurrentPathWaypoint());
SetMaxSpeed(GetCurrentPathWaypointSpeed());
} else {
Stop();
m_Parent->TriggerEvent(eTriggerEventType::ARRIVED_AT_END_OF_PATH);
}
} else {
Stop();
}
return;
}
SetDestination(GetCurrentPathWaypoint());
SetMaxSpeed(GetCurrentPathWaypointSpeed());
return;
}
if (!IsPaused()) Pause();
const auto& data = m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).commands.at(commandIndex).data;
const auto& command = m_Path->pathWaypoints.at(m_CurrentPathWaypointIndex).commands.at(commandIndex).command;
float delay = 0.0f;
switch (command) {
case eWaypointCommandType::STOP:
Stop();
break;
case eWaypointCommandType::GROUP_EMOTE:
delay = HandleWaypointCommandGroupEmote(data);
break;
case eWaypointCommandType::SET_VARIABLE:
HandleWaypointCommandSetVariable(data);
break;
case eWaypointCommandType::CAST_SKILL:
HandleWaypointCommandCastSkill(data);
break;
case eWaypointCommandType::EQUIP_INVENTORY:
HandleWaypointCommandEquipInventory(data);
break;
case eWaypointCommandType::UNEQUIP_INVENTORY:
HandleWaypointCommandUnequipInventory(data);
break;
case eWaypointCommandType::DELAY:
delay = HandleWaypointCommandDelay(data);
break;
case eWaypointCommandType::EMOTE:
delay = RenderComponent::PlayAnimation(m_Parent, data);
break;
case eWaypointCommandType::TELEPORT:
HandleWaypointCommandTeleport(data);
break;
case eWaypointCommandType::PATH_SPEED:
HandleWaypointCommandPathSpeed(data);
break;
case eWaypointCommandType::REMOVE_NPC:
HandleWaypointCommandRemoveNPC(data);
break;
case eWaypointCommandType::CHANGE_WAYPOINT:
HandleWaypointCommandChangeWaypoint(data);
break;
case eWaypointCommandType::KILL_SELF:
m_Parent->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
break;
case eWaypointCommandType::DELETE_SELF:
m_Parent->Kill();
break;
case eWaypointCommandType::SPAWN_OBJECT:
HandleWaypointCommandSpawnObject(data);
break;
case eWaypointCommandType::PLAY_SOUND:
GameMessages::SendPlayNDAudioEmitter(m_Parent, UNASSIGNED_SYSTEM_ADDRESS, data);
break;
case eWaypointCommandType::BOUNCE:
LOG("Unable to process bounce waypoint command server side!");
break;
case eWaypointCommandType::INVALID:
default:
LOG("Got invalid waypoint command %i", command);
break;
}
m_Parent->AddCallbackTimer(delay, [this, commandIndex]() {
this->HandleWaypointArrived(commandIndex + 1);
}
);
}
float MovementAIComponent::HandleWaypointCommandGroupEmote(const std::string& data) {
const auto& split = GeneralUtils::SplitString(data, ';');
if (split.size() != 2) return 0.0f;
const auto& entities = Game::entityManager->GetEntitiesInGroup(split.at(0));
float delay = 0.0f;
for (auto& entity : entities) {
delay = RenderComponent::PlayAnimation(entity, split.at(1));
}
return delay;
}
void MovementAIComponent::HandleWaypointCommandSetVariable(const std::string& data) {
const auto& split = GeneralUtils::SplitString(data, ',');
m_Parent->SetNetworkVar(GeneralUtils::ASCIIToUTF16(split.at(0)), split.at(1));
}
void MovementAIComponent::HandleWaypointCommandCastSkill(const std::string& data) {
if (data.empty()) return;
auto* skillComponent = m_Parent->GetComponent<SkillComponent>();
if (!skillComponent) {
LOG("Skill component not found!");
return;
}
auto skillId = GeneralUtils::TryParse<uint32_t>(data);
if (skillId && skillId != 0) skillComponent->CastSkill(skillId.value());
}
void MovementAIComponent::HandleWaypointCommandEquipInventory(const std::string& data) {
if (data.empty()) return;
auto* inventoryComponent = m_Parent->GetComponent<InventoryComponent>();
if (!inventoryComponent) {
LOG("Inventory component not found!");
return;
}
// the client says use slot 0 of items
const auto inventory = inventoryComponent->GetInventory(eInventoryType::ITEMS);
if (!inventory) return;
const auto slots = inventory->GetSlots();
const auto item = slots.find(0);
if (item != slots.end()) inventoryComponent->EquipItem(item->second);
}
void MovementAIComponent::HandleWaypointCommandUnequipInventory(const std::string& data) {
if (data.empty()) return;
auto* inventoryComponent = m_Parent->GetComponent<InventoryComponent>();
if (!inventoryComponent) {
LOG("Inventory component not found!");
return;
}
// the client says use slot 0 of items
const auto inventory = inventoryComponent->GetInventory(eInventoryType::ITEMS);
if (!inventory) return;
const auto slots = inventory->GetSlots();
const auto item = slots.find(0);
if (item != slots.end()) inventoryComponent->UnEquipItem(item->second);
}
float MovementAIComponent::HandleWaypointCommandDelay(const std::string& data) {
auto delay = GeneralUtils::TryParse<float>(data);
if (!delay) {
LOG("Failed to parse delay %s", data.c_str());
}
return delay.value_or(0.0f);
}
void MovementAIComponent::HandleWaypointCommandTeleport(const std::string& data) {
auto posString = GeneralUtils::SplitString(data, ',');
if (posString.size() == 0) return;
auto newPos = NiPoint3();
std::optional<float> intermediate;
if (posString.size() >= 1) {
intermediate = GeneralUtils::TryParse<float>(posString.at(0));
if (!intermediate) return;
newPos.x = intermediate.value();
if (posString.size() >= 2) {
intermediate = GeneralUtils::TryParse<float>(posString.at(1));
if (!intermediate) return;
newPos.y = intermediate.value();
if (posString.size() >= 3) {
intermediate = GeneralUtils::TryParse<float>(posString.at(2));
if (!intermediate) return;
newPos.z = intermediate.value();
}
}
}
GameMessages::SendTeleport(m_Parent->GetObjectID(), newPos, NiQuaternionConstant::IDENTITY, UNASSIGNED_SYSTEM_ADDRESS);
}
void MovementAIComponent::HandleWaypointCommandPathSpeed(const std::string& data) {
auto speed = GeneralUtils::TryParse<float>(data);
if (!speed) return;
SetMaxSpeed(speed.value());
}
void MovementAIComponent::HandleWaypointCommandRemoveNPC(const std::string& data) {
if (data.empty()) return;
auto* proximityMonitorComponent = m_Parent->GetComponent<ProximityMonitorComponent>();
if (!proximityMonitorComponent) {
LOG("Proximity monitor component not found!");
return;
}
const auto foundObjs = proximityMonitorComponent->GetProximityObjects("KillOBJS");
for (auto& [objid, phyEntity] : foundObjs) {
auto entity = Game::entityManager->GetEntity(objid);
if (!entity) return;
auto* destroyableComponent = m_Parent->GetComponent<DestroyableComponent>();
if (!destroyableComponent) {
LOG("Destroyable component not found!");
return;
}
int32_t factionID = -1;
auto parsed = GeneralUtils::TryParse<uint32_t>(data);
if (!parsed) return;
factionID = parsed.value();
if (destroyableComponent->BelongsToFaction(factionID)) m_Parent->Kill();
}
}
void MovementAIComponent::HandleWaypointCommandChangeWaypoint(const std::string& data) {
std::string path_string = "";
int32_t index = 0;
// sometimes there's a path and what waypoint to start, which are comma separated
if (data.find(",") != std::string::npos) {
auto datas = GeneralUtils::SplitString(data, ',');
path_string = datas.at(0);
auto parsed = GeneralUtils::TryParse<int32_t>(datas.at(1));
if (!parsed) return;
index = parsed.value();
} else path_string = data;
if (path_string != "") {
SetPathStartingWaypointIndex(index);
SetupPath(path_string);
}
}
void MovementAIComponent::HandleWaypointCommandSpawnObject(const std::string& data) {
LOT newObjectLOT = 0;
auto parsed = GeneralUtils::TryParse<LOT>(data);
if (!parsed) return;
newObjectLOT = parsed.value();
EntityInfo info{};
info.lot = newObjectLOT;
info.pos = m_Parent->GetPosition();
info.rot = m_Parent->GetRotation();
auto* spawnedEntity = Game::entityManager->CreateEntity(info, nullptr, m_Parent);
Game::entityManager->ConstructEntity(spawnedEntity);
m_Parent->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
}

View File

@@ -18,7 +18,6 @@
class ControllablePhysicsComponent;
class BaseCombatAIComponent;
class Path;
/**
* Information that describes the different variables used to make an entity move around
@@ -54,7 +53,7 @@ struct MovementAIInfo {
/**
* Component that handles the movement settings of an entity. Not to be confused with the BaseCombatAI component that
* actually handles attacking and following enemy entities.
* actually handles attackig and following enemy entities.
*/
class MovementAIComponent final : public Component {
public:
@@ -154,19 +153,6 @@ public:
*/
NiPoint3 GetNextWaypoint() const { return m_NextWaypoint; }
NiPoint3 GetNextPathWaypoint() const {
if (m_CurrentPath.empty()) return GetNextWaypoint();
if (m_IsInReverse) {
return m_CurrentPathWaypointIndex - 1 < 0 ?
m_CurrentPath.front() :
m_CurrentPath.at(m_CurrentPathWaypointIndex - 1);
} else {
return m_CurrentPathWaypointIndex + 1 >= m_CurrentPath.size() ?
m_CurrentPath.back() :
m_CurrentPath.at(m_CurrentPathWaypointIndex + 1);
}
}
/**
* Returns the approximate current location of the entity, including y coordinates
* @return the approximate current location of the entity
@@ -187,32 +173,11 @@ public:
*/
bool AtFinalWaypoint() const { return m_AtFinalWaypoint; }
bool IsPaused() const { return m_IsPaused; }
/**
* Pauses the current pathing of this entity. The current path waypoint will be saved for resuming later.
*/
void Pause();
/**
* Resumes pathing from the current position to the destination that was set
* when the entity was paused.
*/
void Resume();
/**
* Renders the entity stationary
*/
void Stop();
void ReversePath();
void HandleWaypointArrived(uint32_t commandIndex);
void SetupPath(const std::string& pathname);
float GetCurrentPathWaypointSpeed() const;
/**
* Stops the current movement and moves the entity to a certain point. Will continue until it's close enough,
* after which its AI is enabled again.
@@ -224,16 +189,7 @@ public:
* Sets a path to follow for the AI
* @param path the path to follow
*/
void SetPath(const std::vector<NiPoint3>& path, bool startsInReverse = false);
// Advance the path waypoint index and return if there is a next waypoint
bool AdvancePathWaypointIndex();
const NiPoint3& GetCurrentPathWaypoint() const;
void SetPathStartingWaypointIndex(int32_t value) { m_StartingWaypointIndex = value; }
bool HasAttachedPathStart() const { return m_StartingWaypointIndex != -1; }
void SetPath(std::vector<NiPoint3> path);
/**
* Returns the base speed from the DB for a given LOT
@@ -242,20 +198,7 @@ public:
*/
static float GetBaseSpeed(LOT lot);
const bool GetIsInReverse(){ return m_IsInReverse; };
private:
float HandleWaypointCommandGroupEmote(const std::string& data);
void HandleWaypointCommandSetVariable(const std::string& data);
void HandleWaypointCommandCastSkill(const std::string& data);
void HandleWaypointCommandEquipInventory(const std::string& data);
void HandleWaypointCommandUnequipInventory(const std::string& data);
float HandleWaypointCommandDelay(const std::string& data);
void HandleWaypointCommandTeleport(const std::string& data);
void HandleWaypointCommandPathSpeed(const std::string& data);
void HandleWaypointCommandRemoveNPC(const std::string& data);
void HandleWaypointCommandChangeWaypoint(const std::string& data);
void HandleWaypointCommandSpawnObject(const std::string& data);
/**
* Sets the current position of the entity
@@ -298,7 +241,7 @@ private:
/**
* The path this entity is currently traversing
*/
int32_t m_PathIndex;
uint32_t m_PathIndex;
/**
* If the entity has reached it last waypoint
@@ -358,37 +301,7 @@ private:
/**
* The path from the current position to the destination.
*/
std::vector<NiPoint3> m_CurrentPath;
/**
* The index of the current waypoint in the path
*/
int32_t m_CurrentPathWaypointIndex;
/**
* The index of the next waypoint in the path
*/
int32_t m_NextPathWaypointIndex;
/**
* Whether or not the path is being read in reverse
*/
bool m_IsInReverse;
/**
* Whether or not the current movement via pathing is paused.
*/
bool m_IsPaused;
/**
* The optional path this component will follow.
*/
const Path* m_Path = nullptr;
/**
* The starting index for the provided path
*/
int32_t m_StartingWaypointIndex = -1;
std::stack<NiPoint3> m_CurrentPath;
};
#endif // MOVEMENTAICOMPONENT_H

View File

@@ -353,6 +353,7 @@ private:
/**
* Pet information loaded from the CDClientDatabase
* TODO: Switch to a reference when safe to do so
*/
CDPetComponent m_PetInfo;
};

View File

@@ -63,7 +63,7 @@ bool ProximityMonitorComponent::IsInProximity(const std::string& name, LWOOBJID
void ProximityMonitorComponent::Update(float deltaTime) {
for (const auto& prox : m_ProximitiesData) {
if (!prox.second) continue;
prox.second->SetPosition(m_Parent->GetPosition());
//Process enter events
for (auto* en : prox.second->GetNewObjects()) {
m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER");

View File

@@ -15,9 +15,8 @@
#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;
@@ -44,7 +43,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<Entity*> targetEntities = GatherTargets(command, optionalTarget);
@@ -56,119 +55,107 @@ 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:
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;
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;
// 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;
}
}
}
@@ -177,25 +164,20 @@ std::vector<Entity*> TriggerComponent::GatherTargets(LUTriggers::Command* comman
std::vector<Entity*> 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 == "targetTeam" && 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) {
auto* member = Game::entityManager->GetEntity(memberId);
if (member) entities.push_back(member);
}
} else if (command->target == "objGroup") {
entities = Game::entityManager->GetEntitiesInGroup(command->targetName);
} else if (command->target == "allPlayers") {
} else if (command->target == "objGroup") entities = Game::entityManager->GetEntitiesInGroup(command->targetName);
else if (command->target == "allPlayers") {
for (auto* player : PlayerManager::GetAllPlayers()) {
entities.push_back(player);
}
} else if (command->target == "allNPCs") {
/*UNUSED*/
}
} else if (command->target == "allNPCs") { /*UNUSED*/ }
return entities;
}
@@ -204,12 +186,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<eKillType>(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<TriggerComponent>();
if (!triggerComponent) {
LOG_DEBUG("Trigger component not found!");
@@ -218,7 +200,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<QuickBuildComponent>();
if (!quickBuildComponent) {
LOG_DEBUG("Rebuild component not found!");
@@ -227,7 +209,7 @@ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args
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;
NiPoint3 position = targetEntity->GetPosition();
@@ -237,7 +219,7 @@ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::s
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;
const NiPoint3 vector = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
@@ -246,7 +228,7 @@ void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std:
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;
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
@@ -264,7 +246,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>();
if (!phantomPhysicsComponent) {
LOG_DEBUG("Phantom Physics component not found!");
@@ -288,7 +270,7 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args)
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) {
LOG_DEBUG("Not enough variables!");
return;
@@ -297,7 +279,7 @@ void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::str
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);
}
@@ -345,7 +327,7 @@ void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vector<std
// then we need a good way to convert this from a string to that enum
if (argArray.at(0) != "exploretask") return;
MissionComponent* missionComponent = targetEntity->GetComponent<MissionComponent>();
if (!missionComponent) {
if (!missionComponent){
LOG_DEBUG("Mission component not found!");
return;
}
@@ -357,7 +339,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::s
const auto effectID = GeneralUtils::TryParse<int32_t>(argArray.at(1));
if (!effectID) return;
std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2));
float priority = 1;
if (argArray.size() == 4) {
priority = GeneralUtils::TryParse<float>(argArray.at(3)).value_or(priority);
@@ -366,7 +348,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::s
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>();
if (!skillComponent) {
LOG_DEBUG("Skill component not found!");
@@ -394,7 +376,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<NiPoint3>(argArray.at(2), argArray.at(3), argArray.at(4)).value_or(NiPoint3Constant::ZERO);
phantomPhysicsComponent->SetDirection(direction);
@@ -420,25 +402,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();
}
@@ -447,50 +429,9 @@ 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<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,12 +44,6 @@ 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<std::string> argArray);
LUTriggers::Trigger* m_Trigger;
};

View File

@@ -26,7 +26,7 @@ public:
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void OnUse(Entity* originator) override;
virtual void RefreshInventory(bool isCreation = false);
void RefreshInventory(bool isCreation = false);
void SetupConstants();
bool SellsItem(const LOT item) const;
float GetBuyScalar() const { return m_BuyScalar; }

View File

@@ -285,7 +285,7 @@ void ParseXml(const std::string& file) {
}
if (zoneID.value() != currentZoneID) {
LOG_DEBUG("Skipping (%s) %i location because it is in %i and not the current zone (%i)", name, lot, zoneID.value(), currentZoneID);
LOG_DEBUG("Skipping location because it is in %i and not the current zone (%i)", zoneID.value(), currentZoneID);
continue;
}

View File

@@ -229,7 +229,7 @@ void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAdd
RakNet::BitStream loginResponse;
BitStreamUtils::WriteHeader(loginResponse, eConnectionType::CLIENT, eClientMessageType::LOGIN_RESPONSE);
loginResponse.Write(responseCode);
loginResponse.Write<uint8_t>(GeneralUtils::CastUnderlyingType(responseCode));
// Event Gating
loginResponse.Write(LUString(Game::config->GetValue("event_1")));

View File

@@ -29,7 +29,7 @@ void StoryBoxInteractServer::OnUse(Entity* self, Entity* user) {
return;
}
if (!self->HasVar(u"storyText")) return;
if (!self->HasVar(u"storyText") || !self->HasVar(u"altFlagID")) return;
const auto storyText = self->GetVarAsString(u"storyText");
if (storyText.length() > 2) {
auto storyValue = GeneralUtils::TryParse<uint32_t>(storyText.substr(storyText.length() - 2));

View File

@@ -17,7 +17,6 @@
#include "eTriggerCommandType.h"
#include "eTriggerEventType.h"
#include "eWaypointCommandType.h"
#include "dNavMesh.h"
Zone::Zone(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) :
@@ -453,23 +452,15 @@ void Zone::LoadPath(std::istream& file) {
std::string value;
BinaryIO::ReadString<uint8_t>(file, value, BinaryIO::ReadType::WideString);
LDFBaseData* ldfConfig = nullptr;
if (path.pathType == PathType::Movement || path.pathType == PathType::Rail) {
// 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());
ldfConfig = LDFBaseData::DataFromString(parameter + "=0:" + value);
} else {
waypoint.config.emplace_back(LDFBaseData::DataFromString(parameter + "=" + value));
ldfConfig = 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) {

View File

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

View File

@@ -1,7 +1,7 @@
set(DCOMMONTEST_SOURCES
"AMFDeserializeTests.cpp"
"Amf3Tests.cpp"
"ToUnderlyingTests.cpp"
"CastUnderlyingTypeTests.cpp"
"HeaderSkipTest.cpp"
"TestCDFeatureGatingTable.cpp"
"TestLDFFormat.cpp"

View File

@@ -7,13 +7,13 @@
#include "eWorldMessageType.h"
#define ASSERT_TYPE_EQ(TYPE, ENUM)\
ASSERT_TRUE(typeid(TYPE) == typeid(GeneralUtils::ToUnderlying(static_cast<ENUM>(0))));
ASSERT_TRUE(typeid(TYPE) == typeid(GeneralUtils::CastUnderlyingType(static_cast<ENUM>(0))));
#define ASSERT_TYPE_NE(TYPE, ENUM)\
ASSERT_FALSE(typeid(TYPE) == typeid(GeneralUtils::ToUnderlying(static_cast<ENUM>(0))));
ASSERT_FALSE(typeid(TYPE) == typeid(GeneralUtils::CastUnderlyingType(static_cast<ENUM>(0))));
// Verify that the underlying enum types are being cast correctly
TEST(ToUnderlyingTests, VerifyToUnderlying) {
TEST(CastUnderlyingTypeTests, VerifyCastUnderlyingType) {
ASSERT_TYPE_EQ(uint8_t, eGameMasterLevel);
ASSERT_TYPE_EQ(uint16_t, eGameMessageType);
ASSERT_TYPE_EQ(uint32_t, eWorldMessageType)