mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 20:14:31 -06:00
Compare commits
35 Commits
moreMoveme
...
remove-mul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90ac91e0df | ||
|
|
946b59f02f | ||
|
|
e76996f98f | ||
|
|
109f556ef7 | ||
|
|
e1d176260a | ||
|
|
c09f46aadc | ||
|
|
3fa5d4791d | ||
|
|
261eb2295d | ||
|
|
da15c6d16b | ||
|
|
5807dccda7 | ||
|
|
247b88dbd5 | ||
|
|
9ac922bbaa | ||
|
|
2eadfa2efb | ||
|
|
8907cd467d | ||
|
|
702dcbb8d2 | ||
|
|
6b94e7f9ed | ||
|
|
decce5b4c5 | ||
|
|
a52cfb5b0b | ||
|
|
4569ea29d5 | ||
|
|
dab70ac096 | ||
|
|
94c56e527a | ||
|
|
7c1c4d7581 | ||
|
|
cb84dbcc22 | ||
|
|
6fb88e79a0 | ||
|
|
cb065a07af | ||
|
|
17305831a1 | ||
|
|
259067c64a | ||
|
|
a166e3ef3f | ||
|
|
2ad3cb79d3 | ||
|
|
d6d5cb7515 | ||
|
|
d67ac7759b | ||
|
|
4586a0ffea | ||
|
|
7509237e69 | ||
|
|
0f1e226960 | ||
|
|
bfe39a919e |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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__
|
||||
@@ -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]);
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Custom Classes
|
||||
#include "CDTable.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct CDMissionEmail {
|
||||
uint32_t ID;
|
||||
uint32_t messageType;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -75,3 +75,4 @@ public:
|
||||
|
||||
static CDMissions Default;
|
||||
};
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Custom Classes
|
||||
#include "CDTable.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct CDMovementAIComponent {
|
||||
uint32_t id;
|
||||
std::string MovementType;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// Custom Classes
|
||||
#include "CDTable.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct CDPackageComponent {
|
||||
uint32_t id;
|
||||
uint32_t LootMatrixIndex;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -648,7 +648,7 @@ void BaseCombatAIComponent::Wander() {
|
||||
const NiPoint3 delta =
|
||||
{
|
||||
radius * cos(theta),
|
||||
m_Parent->GetPosition().y,
|
||||
0,
|
||||
radius * sin(theta)
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -353,6 +353,7 @@ private:
|
||||
|
||||
/**
|
||||
* Pet information loaded from the CDClientDatabase
|
||||
* TODO: Switch to a reference when safe to do so
|
||||
*/
|
||||
CDPetComponent m_PetInfo;
|
||||
};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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")));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
set(DCOMMONTEST_SOURCES
|
||||
"AMFDeserializeTests.cpp"
|
||||
"Amf3Tests.cpp"
|
||||
"ToUnderlyingTests.cpp"
|
||||
"CastUnderlyingTypeTests.cpp"
|
||||
"HeaderSkipTest.cpp"
|
||||
"TestCDFeatureGatingTable.cpp"
|
||||
"TestLDFFormat.cpp"
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user