mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-18 03:37:23 -06:00
Compare commits
95 Commits
remove-mul
...
issue-960
| Author | SHA1 | Date | |
|---|---|---|---|
| bf58cf85cc | |||
| f6f3cdc3c0 | |||
| 66cf96af1a | |||
| 0e6cb8ab19 | |||
| 42cf2b6377 | |||
| 3cfbc9d3df | |||
| 5ba37ff7d6 | |||
| 8f00f1601c | |||
|
|
1454fcd003 | ||
| 5e3c869141 | |||
|
|
af651f0d63 | ||
| ff38503597 | |||
| 3f22bf5cc0 | |||
| 9d5d2a68ee | |||
| 1a14c29c39 | |||
| 2ef45bd7ee | |||
| b56d077892 | |||
|
|
a54600b41e | ||
|
|
342da927f5 | ||
|
|
01086d05c8 | ||
|
|
cce5755366 | ||
|
|
e966d3a644 | ||
|
|
9328021339 | ||
|
|
d1134fdd62 | ||
|
|
efa658bc31 | ||
|
|
e59525d2ae | ||
|
|
0348db72a5 | ||
|
|
debc2a96e2 | ||
|
|
8ae1a8ff7c | ||
|
|
f0960d48b2 | ||
|
|
dc430d9758 | ||
|
|
dea10c6d56 | ||
|
|
ed00551982 | ||
|
|
d6cac65a8d | ||
|
|
d8f079cb1b | ||
|
|
c8e0bb0db0 | ||
|
|
d9d262d3f1 | ||
|
|
d0a5678290 | ||
|
|
35321b22d9 | ||
|
|
8837b110ab | ||
|
|
09a8c99f3e | ||
|
|
e3b108e00e | ||
|
|
9f382aca42 | ||
|
|
4d1395e522 | ||
| 9e36510c6b | |||
|
|
2ca61c3e57 | ||
| 07cb19cc30 | |||
|
|
794b254fe7 | ||
|
|
ab7f6f0b57 | ||
|
|
58cc569c75 | ||
|
|
35c463656d | ||
| 3801a97722 | |||
|
|
0367c67c85 | ||
|
|
8fdc212cda | ||
| 99e7349f6c | |||
|
|
fafe2aefad | ||
|
|
5049f215ba | ||
|
|
3a6123fe36 | ||
|
|
b8b2b687e2 | ||
| d067a8d12f | |||
|
|
1ee45639af | ||
|
|
db192d2cde | ||
|
|
28ce8ac54d | ||
|
|
be0a2f6f14 | ||
|
|
3260a063cb | ||
| feeac2e041 | |||
|
|
18c27b14c8 | ||
|
|
bcfaa6c7fe | ||
|
|
06e7d57e0d | ||
|
|
b340d7c8f9 | ||
|
|
24de0e5fdb | ||
| 20408d8dfe | |||
|
|
c1c5db6593 | ||
|
|
884a41f36a | ||
|
|
bbc0908989 | ||
|
|
5996f3cbf4 | ||
|
|
150031861d | ||
|
|
9d8e0a9c4a | ||
|
|
bd9b790e1d | ||
|
|
39b81b6263 | ||
|
|
1e09ec92e3 | ||
|
|
2b253a8248 | ||
|
|
3262bc3a86 | ||
|
|
3a4e554da9 | ||
|
|
35ce8771e5 | ||
|
|
b9092a3cce | ||
|
|
0b4f70a76b | ||
|
|
4bc4624bc9 | ||
|
|
3a6313a3ba | ||
|
|
6e3b5acede | ||
|
|
fe4b29f643 | ||
|
|
fcb89b3c7a | ||
|
|
1a0aaf3123 | ||
|
|
9a26ba0a72 | ||
|
|
6c9c826e19 |
@@ -1,9 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(Darkflame)
|
project(Darkflame)
|
||||||
|
|
||||||
|
# check if the path to the source directory contains a space
|
||||||
|
if("${CMAKE_SOURCE_DIR}" MATCHES " ")
|
||||||
|
message(FATAL_ERROR "The server cannot build in the path (" ${CMAKE_SOURCE_DIR} ") because it contains a space. Please move the server to a path without spaces.")
|
||||||
|
endif()
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CXX_STANDARD_REQUIRED ON)
|
set(CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
|
||||||
|
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
|
||||||
|
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
# Read variables from file
|
# Read variables from file
|
||||||
@@ -70,7 +79,8 @@ if(UNIX)
|
|||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
|
||||||
elseif(MSVC)
|
elseif(MSVC)
|
||||||
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
|
||||||
add_compile_options("/wd4267" "/utf-8")
|
# Also disable non-portable MSVC volatile behavior
|
||||||
|
add_compile_options("/wd4267" "/utf-8" "/volatile:iso")
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
@@ -100,7 +110,7 @@ make_directory(${CMAKE_BINARY_DIR}/resServer)
|
|||||||
make_directory(${CMAKE_BINARY_DIR}/logs)
|
make_directory(${CMAKE_BINARY_DIR}/logs)
|
||||||
|
|
||||||
# Copy resource files on first build
|
# Copy resource files on first build
|
||||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blocklist.dcf")
|
||||||
message(STATUS "Checking resource file integrity")
|
message(STATUS "Checking resource file integrity")
|
||||||
|
|
||||||
include(Utils)
|
include(Utils)
|
||||||
@@ -211,29 +221,29 @@ if (APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Load all of our third party directories
|
# Load all of our third party directories
|
||||||
add_subdirectory(thirdparty)
|
add_subdirectory(thirdparty SYSTEM)
|
||||||
|
|
||||||
# Create our list of include directories
|
# Create our list of include directories
|
||||||
set(INCLUDED_DIRECTORIES
|
include_directories(
|
||||||
"dPhysics"
|
"dPhysics"
|
||||||
|
|
||||||
"dNavigation"
|
"dNavigation"
|
||||||
|
|
||||||
"dNet"
|
"dNet"
|
||||||
|
|
||||||
"thirdparty/magic_enum/include/magic_enum"
|
|
||||||
"thirdparty/raknet/Source"
|
|
||||||
"thirdparty/tinyxml2"
|
|
||||||
"thirdparty/recastnavigation"
|
|
||||||
"thirdparty/SQLite"
|
|
||||||
"thirdparty/cpplinq"
|
|
||||||
"thirdparty/cpp-httplib"
|
|
||||||
"thirdparty/MD5"
|
|
||||||
|
|
||||||
"tests"
|
"tests"
|
||||||
"tests/dCommonTests"
|
"tests/dCommonTests"
|
||||||
"tests/dGameTests"
|
"tests/dGameTests"
|
||||||
"tests/dGameTests/dComponentsTests"
|
"tests/dGameTests/dComponentsTests"
|
||||||
|
|
||||||
|
SYSTEM "thirdparty/magic_enum/include/magic_enum"
|
||||||
|
SYSTEM "thirdparty/raknet/Source"
|
||||||
|
SYSTEM "thirdparty/tinyxml2"
|
||||||
|
SYSTEM "thirdparty/recastnavigation"
|
||||||
|
SYSTEM "thirdparty/SQLite"
|
||||||
|
SYSTEM "thirdparty/cpplinq"
|
||||||
|
SYSTEM "thirdparty/cpp-httplib"
|
||||||
|
SYSTEM "thirdparty/MD5"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
# Add system specfic includes for Apple, Windows and Other Unix OS' (including Linux)
|
||||||
@@ -242,14 +252,9 @@ if(APPLE)
|
|||||||
include_directories("/usr/local/include/")
|
include_directories("/usr/local/include/")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Actually include the directories from our list
|
|
||||||
foreach(dir ${INCLUDED_DIRECTORIES})
|
|
||||||
include_directories(${PROJECT_SOURCE_DIR}/${dir})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Add linking directories:
|
# Add linking directories:
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
|
||||||
endif()
|
endif()
|
||||||
file(
|
file(
|
||||||
GLOB HEADERS_DZONEMANAGER
|
GLOB HEADERS_DZONEMANAGER
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=2
|
||||||
PROJECT_VERSION_MINOR=1
|
PROJECT_VERSION_MINOR=3
|
||||||
PROJECT_VERSION_PATCH=1
|
PROJECT_VERSION_PATCH=0
|
||||||
|
|
||||||
# Debugging
|
# Debugging
|
||||||
# Set DYNAMIC to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
# Set DYNAMIC to 1 to enable the -rdynamic flag for the linker, yielding some symbols in crashlogs.
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ COPY --from=build /app/build/*Server /app/
|
|||||||
|
|
||||||
# Necessary suplimentary files
|
# Necessary suplimentary files
|
||||||
COPY --from=build /app/build/*.ini /app/configs/
|
COPY --from=build /app/build/*.ini /app/configs/
|
||||||
COPY --from=build /app/build/vanity/*.* /app/vanity/*
|
COPY --from=build /app/build/vanity/*.* /app/vanity/
|
||||||
COPY --from=build /app/build/navmeshes /app/navmeshes
|
COPY --from=build /app/build/navmeshes /app/navmeshes
|
||||||
COPY --from=build /app/build/migrations /app/migrations
|
COPY --from=build /app/build/migrations /app/migrations
|
||||||
COPY --from=build /app/build/*.dcf /app/
|
COPY --from=build /app/build/*.dcf /app/
|
||||||
@@ -39,7 +39,7 @@ COPY --from=build /app/build/*.dcf /app/
|
|||||||
# backup of config and vanity files to copy to the host incase
|
# backup of config and vanity files to copy to the host incase
|
||||||
# of a mount clobbering the copy from above
|
# of a mount clobbering the copy from above
|
||||||
COPY --from=build /app/build/*.ini /app/default-configs/
|
COPY --from=build /app/build/*.ini /app/default-configs/
|
||||||
COPY --from=build /app/build/vanity/*.* /app/default-vanity/*
|
COPY --from=build /app/build/vanity/*.* /app/default-vanity/
|
||||||
|
|
||||||
# needed as the container runs with the root user
|
# needed as the container runs with the root user
|
||||||
# and therefore sudo doesn't exist
|
# and therefore sudo doesn't exist
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
|
|||||||
|
|
||||||
### Windows packages
|
### Windows packages
|
||||||
Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed.
|
Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed.
|
||||||
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.18**</font> or later!).
|
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.25**</font> or later!).
|
||||||
|
|
||||||
### MacOS packages
|
### MacOS packages
|
||||||
Ensure you have [brew](https://brew.sh) installed.
|
Ensure you have [brew](https://brew.sh) installed.
|
||||||
@@ -73,7 +73,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Required CMake version
|
#### Required CMake version
|
||||||
This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed.
|
This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed.
|
||||||
You can check your CMake version by using the following command in a terminal.
|
You can check your CMake version by using the following command in a terminal.
|
||||||
```bash
|
```bash
|
||||||
cmake --version
|
cmake --version
|
||||||
|
|||||||
@@ -141,6 +141,6 @@ elseif(APPLE)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Add directories to include lists
|
# Add directories to include lists
|
||||||
target_include_directories(MariaDB::ConnCpp INTERFACE ${MARIADB_INCLUDE_DIR})
|
target_include_directories(MariaDB::ConnCpp SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
|
||||||
|
|
||||||
set(MariaDB_FOUND TRUE)
|
set(MariaDB_FOUND TRUE)
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
|
|||||||
ExportWordlistToDCF(filepath + ".dcf", true);
|
ExportWordlistToDCF(filepath + ".dcf", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
|
if (BinaryIO::DoesFileExist("blocklist.dcf")) {
|
||||||
ReadWordlistDCF("blacklist.dcf", false);
|
ReadWordlistDCF("blocklist.dcf", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Read player names that are ok as well:
|
//Read player names that are ok as well:
|
||||||
@@ -44,20 +44,20 @@ dChatFilter::~dChatFilter() {
|
|||||||
m_DeniedWords.clear();
|
m_DeniedWords.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
|
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool allowList) {
|
||||||
std::ifstream file(filepath);
|
std::ifstream file(filepath);
|
||||||
if (file) {
|
if (file) {
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
|
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
|
||||||
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
|
||||||
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
|
if (allowList) m_ApprovedWords.push_back(CalculateHash(line));
|
||||||
else m_DeniedWords.push_back(CalculateHash(line));
|
else m_DeniedWords.push_back(CalculateHash(line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
|
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
|
||||||
std::ifstream file(filepath, std::ios::binary);
|
std::ifstream file(filepath, std::ios::binary);
|
||||||
if (file) {
|
if (file) {
|
||||||
fileHeader hdr;
|
fileHeader hdr;
|
||||||
@@ -70,13 +70,13 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
|
|||||||
if (hdr.formatVersion == formatVersion) {
|
if (hdr.formatVersion == formatVersion) {
|
||||||
size_t wordsToRead = 0;
|
size_t wordsToRead = 0;
|
||||||
BinaryIO::BinaryRead(file, wordsToRead);
|
BinaryIO::BinaryRead(file, wordsToRead);
|
||||||
if (whiteList) m_ApprovedWords.reserve(wordsToRead);
|
if (allowList) m_ApprovedWords.reserve(wordsToRead);
|
||||||
else m_DeniedWords.reserve(wordsToRead);
|
else m_DeniedWords.reserve(wordsToRead);
|
||||||
|
|
||||||
size_t word = 0;
|
size_t word = 0;
|
||||||
for (size_t i = 0; i < wordsToRead; ++i) {
|
for (size_t i = 0; i < wordsToRead; ++i) {
|
||||||
BinaryIO::BinaryRead(file, word);
|
BinaryIO::BinaryRead(file, word);
|
||||||
if (whiteList) m_ApprovedWords.push_back(word);
|
if (allowList) m_ApprovedWords.push_back(word);
|
||||||
else m_DeniedWords.push_back(word);
|
else m_DeniedWords.push_back(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,14 +90,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
|
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowList) {
|
||||||
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
|
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
|
||||||
if (file) {
|
if (file) {
|
||||||
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
|
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
|
||||||
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
|
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
|
||||||
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
|
BinaryIO::BinaryWrite(file, size_t(allowList ? m_ApprovedWords.size() : m_DeniedWords.size()));
|
||||||
|
|
||||||
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
|
for (size_t word : allowList ? m_ApprovedWords : m_DeniedWords) {
|
||||||
BinaryIO::BinaryWrite(file, word);
|
BinaryIO::BinaryWrite(file, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,10 +105,10 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteLis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList) {
|
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList) {
|
||||||
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
|
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
|
||||||
if (message.empty()) return { };
|
if (message.empty()) return { };
|
||||||
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
|
if (!allowList && m_DeniedWords.empty()) return { { 0, message.length() } };
|
||||||
|
|
||||||
std::stringstream sMessage(message);
|
std::stringstream sMessage(message);
|
||||||
std::string segment;
|
std::string segment;
|
||||||
@@ -126,16 +126,16 @@ std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::
|
|||||||
|
|
||||||
size_t hash = CalculateHash(segment);
|
size_t hash = CalculateHash(segment);
|
||||||
|
|
||||||
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
|
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && allowList) {
|
||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
|
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && allowList) {
|
||||||
m_UserUnapprovedWordCache.push_back(hash);
|
m_UserUnapprovedWordCache.push_back(hash);
|
||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
|
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !allowList) {
|
||||||
m_UserUnapprovedWordCache.push_back(hash);
|
m_UserUnapprovedWordCache.push_back(hash);
|
||||||
listOfBadSegments.emplace_back(position, originalSegment.length());
|
listOfBadSegments.emplace_back(position, originalSegment.length());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ public:
|
|||||||
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
|
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
|
||||||
~dChatFilter();
|
~dChatFilter();
|
||||||
|
|
||||||
void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
|
void ReadWordlistPlaintext(const std::string& filepath, bool allowList);
|
||||||
bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
|
bool ReadWordlistDCF(const std::string& filepath, bool allowList);
|
||||||
void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
|
void ExportWordlistToDCF(const std::string& filepath, bool allowList);
|
||||||
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList = true);
|
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_DontGenerateDCF;
|
bool m_DontGenerateDCF;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
// The only thing not auto-handled is instance activities force joining the team on the server.
|
// The only thing not auto-handled is instance activities force joining the team on the server.
|
||||||
|
|
||||||
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
|
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receivingPlayer);
|
bitStream.Write(receivingPlayer);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
|
|||||||
@@ -14,11 +14,11 @@
|
|||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
|
||||||
#include "eClientMessageType.h"
|
#include "eClientMessageType.h"
|
||||||
#include "eGameMessageType.h"
|
#include "eGameMessageType.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
#include "ChatPackets.h"
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||||
//Get from the packet which player we want to do something with:
|
//Get from the packet which player we want to do something with:
|
||||||
@@ -60,7 +60,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
|
|
||||||
//Now, we need to send the friendlist to the server they came from:
|
//Now, we need to send the friendlist to the server they came from:
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(playerID);
|
bitStream.Write(playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -355,6 +355,67 @@ void ChatPacketHandler::HandleGMLevelUpdate(Packet* packet) {
|
|||||||
inStream.Read(player.gmLevel);
|
inStream.Read(player.gmLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ChatPacketHandler::HandleWho(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
FindPlayerRequest request;
|
||||||
|
request.Deserialize(inStream);
|
||||||
|
|
||||||
|
const auto& sender = Game::playerContainer.GetPlayerData(request.requestor);
|
||||||
|
if (!sender) return;
|
||||||
|
|
||||||
|
const auto& player = Game::playerContainer.GetPlayerData(request.playerName.GetAsString());
|
||||||
|
bool online = player;
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
|
bitStream.Write(request.requestor);
|
||||||
|
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::WHO_RESPONSE);
|
||||||
|
bitStream.Write<uint8_t>(online);
|
||||||
|
bitStream.Write(player.zoneID.GetMapID());
|
||||||
|
bitStream.Write(player.zoneID.GetInstanceID());
|
||||||
|
bitStream.Write(player.zoneID.GetCloneID());
|
||||||
|
bitStream.Write(request.playerName);
|
||||||
|
|
||||||
|
SystemAddress sysAddr = sender.sysAddr;
|
||||||
|
SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatPacketHandler::HandleShowAll(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
ShowAllRequest request;
|
||||||
|
request.Deserialize(inStream);
|
||||||
|
|
||||||
|
const auto& sender = Game::playerContainer.GetPlayerData(request.requestor);
|
||||||
|
if (!sender) return;
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
|
bitStream.Write(request.requestor);
|
||||||
|
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::SHOW_ALL_RESPONSE);
|
||||||
|
bitStream.Write<uint8_t>(!request.displayZoneData && !request.displayIndividualPlayers);
|
||||||
|
bitStream.Write(Game::playerContainer.GetPlayerCount());
|
||||||
|
bitStream.Write(Game::playerContainer.GetSimCount());
|
||||||
|
bitStream.Write<uint8_t>(request.displayIndividualPlayers);
|
||||||
|
bitStream.Write<uint8_t>(request.displayZoneData);
|
||||||
|
if (request.displayZoneData || request.displayIndividualPlayers){
|
||||||
|
for (auto& [playerID, playerData ]: Game::playerContainer.GetAllPlayers()){
|
||||||
|
if (!playerData) continue;
|
||||||
|
bitStream.Write<uint8_t>(0); // structure packing
|
||||||
|
if (request.displayIndividualPlayers) bitStream.Write(LUWString(playerData.playerName));
|
||||||
|
if (request.displayZoneData) {
|
||||||
|
bitStream.Write(playerData.zoneID.GetMapID());
|
||||||
|
bitStream.Write(playerData.zoneID.GetInstanceID());
|
||||||
|
bitStream.Write(playerData.zoneID.GetCloneID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemAddress sysAddr = sender.sysAddr;
|
||||||
|
SEND_PACKET;
|
||||||
|
}
|
||||||
|
|
||||||
// the structure the client uses to send this packet is shared in many chat messages
|
// the structure the client uses to send this packet is shared in many chat messages
|
||||||
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
|
||||||
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||||
@@ -454,7 +515,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
|
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(routeTo.playerID);
|
bitStream.Write(routeTo.playerID);
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||||
@@ -696,7 +757,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
|
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -711,7 +772,7 @@ void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerD
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -738,7 +799,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool b
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -763,7 +824,7 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -780,7 +841,7 @@ void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -809,7 +870,7 @@ void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFr
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -835,7 +896,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bD
|
|||||||
|
|
||||||
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -869,7 +930,7 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
|
|||||||
[bool] - is FTP*/
|
[bool] - is FTP*/
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(friendData.playerID);
|
bitStream.Write(friendData.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -906,7 +967,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
|||||||
}
|
}
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
@@ -920,7 +981,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
|||||||
|
|
||||||
void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
|
void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
// Portion that will get routed:
|
// Portion that will get routed:
|
||||||
@@ -943,7 +1004,7 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
|
|||||||
|
|
||||||
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
|
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
|
||||||
bitStream.Write(receiver.playerID);
|
bitStream.Write(receiver.playerID);
|
||||||
|
|
||||||
//portion that will get routed:
|
//portion that will get routed:
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ namespace ChatPacketHandler {
|
|||||||
void HandleFriendResponse(Packet* packet);
|
void HandleFriendResponse(Packet* packet);
|
||||||
void HandleRemoveFriend(Packet* packet);
|
void HandleRemoveFriend(Packet* packet);
|
||||||
void HandleGMLevelUpdate(Packet* packet);
|
void HandleGMLevelUpdate(Packet* packet);
|
||||||
|
void HandleWho(Packet* packet);
|
||||||
|
void HandleShowAll(Packet* packet);
|
||||||
|
|
||||||
void HandleChatMessage(Packet* packet);
|
void HandleChatMessage(Packet* packet);
|
||||||
void HandlePrivateChatMessage(Packet* packet);
|
void HandlePrivateChatMessage(Packet* packet);
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
#include "PlayerContainer.h"
|
#include "PlayerContainer.h"
|
||||||
#include "ChatPacketHandler.h"
|
#include "ChatPacketHandler.h"
|
||||||
#include "eChatMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
|
||||||
#include "eWorldMessageType.h"
|
#include "eWorldMessageType.h"
|
||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
@@ -180,49 +179,32 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
|
if (packet->length < 1) return;
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
LOG("A server has disconnected, erasing their connected players from the list.");
|
LOG("A server has disconnected, erasing their connected players from the list.");
|
||||||
}
|
} else if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
||||||
|
|
||||||
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
|
|
||||||
LOG("A server is connecting, awaiting user list.");
|
LOG("A server is connecting, awaiting user list.");
|
||||||
}
|
} else if (packet->length < 4 || packet->data[0] != ID_USER_PACKET_ENUM) return; // Nothing left to process or not the right packet type
|
||||||
|
|
||||||
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
|
CINSTREAM;
|
||||||
|
inStream.SetReadOffset(BYTES_TO_BITS(1));
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
|
eConnectionType connection;
|
||||||
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
|
eChatMessageType chatMessageID;
|
||||||
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
|
|
||||||
Game::playerContainer.InsertPlayer(packet);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
|
inStream.Read(connection);
|
||||||
Game::playerContainer.RemovePlayer(packet);
|
if (connection != eConnectionType::CHAT) return;
|
||||||
break;
|
inStream.Read(chatMessageID);
|
||||||
|
|
||||||
case eChatInternalMessageType::MUTE_UPDATE:
|
switch (chatMessageID) {
|
||||||
|
case eChatMessageType::GM_MUTE:
|
||||||
Game::playerContainer.MuteUpdate(packet);
|
Game::playerContainer.MuteUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::CREATE_TEAM:
|
case eChatMessageType::CREATE_TEAM:
|
||||||
Game::playerContainer.CreateTeamServer(packet);
|
Game::playerContainer.CreateTeamServer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::ANNOUNCEMENT: {
|
|
||||||
//we just forward this packet to every connected server
|
|
||||||
CINSTREAM;
|
|
||||||
Game::server->Send(inStream, packet->systemAddress, true); //send to everyone except origin
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG("Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
|
|
||||||
eChatMessageType chat_message_type = static_cast<eChatMessageType>(packet->data[3]);
|
|
||||||
switch (chat_message_type) {
|
|
||||||
case eChatMessageType::GET_FRIENDS_LIST:
|
case eChatMessageType::GET_FRIENDS_LIST:
|
||||||
ChatPacketHandler::HandleFriendlistRequest(packet);
|
ChatPacketHandler::HandleFriendlistRequest(packet);
|
||||||
break;
|
break;
|
||||||
@@ -296,6 +278,23 @@ void HandlePacket(Packet* packet) {
|
|||||||
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
ChatPacketHandler::HandleGMLevelUpdate(packet);
|
||||||
break;
|
break;
|
||||||
case eChatMessageType::LOGIN_SESSION_NOTIFY:
|
case eChatMessageType::LOGIN_SESSION_NOTIFY:
|
||||||
|
Game::playerContainer.InsertPlayer(packet);
|
||||||
|
break;
|
||||||
|
case eChatMessageType::GM_ANNOUNCE:{
|
||||||
|
// we just forward this packet to every connected server
|
||||||
|
inStream.ResetReadPointer();
|
||||||
|
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case eChatMessageType::UNEXPECTED_DISCONNECT:
|
||||||
|
Game::playerContainer.RemovePlayer(packet);
|
||||||
|
break;
|
||||||
|
case eChatMessageType::WHO:
|
||||||
|
ChatPacketHandler::HandleWho(packet);
|
||||||
|
break;
|
||||||
|
case eChatMessageType::SHOW_ALL:
|
||||||
|
ChatPacketHandler::HandleShowAll(packet);
|
||||||
|
break;
|
||||||
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
|
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
|
||||||
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
|
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
|
||||||
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
|
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
|
||||||
@@ -308,7 +307,6 @@ void HandlePacket(Packet* packet) {
|
|||||||
case eChatMessageType::GUILD_KICK:
|
case eChatMessageType::GUILD_KICK:
|
||||||
case eChatMessageType::GUILD_GET_STATUS:
|
case eChatMessageType::GUILD_GET_STATUS:
|
||||||
case eChatMessageType::GUILD_GET_ALL:
|
case eChatMessageType::GUILD_GET_ALL:
|
||||||
case eChatMessageType::SHOW_ALL:
|
|
||||||
case eChatMessageType::BLUEPRINT_MODERATED:
|
case eChatMessageType::BLUEPRINT_MODERATED:
|
||||||
case eChatMessageType::BLUEPRINT_MODEL_READY:
|
case eChatMessageType::BLUEPRINT_MODEL_READY:
|
||||||
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
|
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
|
||||||
@@ -323,7 +321,6 @@ void HandlePacket(Packet* packet) {
|
|||||||
case eChatMessageType::CSR_REQUEST:
|
case eChatMessageType::CSR_REQUEST:
|
||||||
case eChatMessageType::CSR_REPLY:
|
case eChatMessageType::CSR_REPLY:
|
||||||
case eChatMessageType::GM_KICK:
|
case eChatMessageType::GM_KICK:
|
||||||
case eChatMessageType::GM_ANNOUNCE:
|
|
||||||
case eChatMessageType::WORLD_ROUTE_PACKET:
|
case eChatMessageType::WORLD_ROUTE_PACKET:
|
||||||
case eChatMessageType::GET_ZONE_POPULATIONS:
|
case eChatMessageType::GET_ZONE_POPULATIONS:
|
||||||
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
|
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
|
||||||
@@ -332,33 +329,18 @@ void HandlePacket(Packet* packet) {
|
|||||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
|
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
|
||||||
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||||
case eChatMessageType::UGCC_REQUEST:
|
case eChatMessageType::UGCC_REQUEST:
|
||||||
case eChatMessageType::WHO:
|
|
||||||
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||||
case eChatMessageType::ACHIEVEMENT_NOTIFY:
|
case eChatMessageType::ACHIEVEMENT_NOTIFY:
|
||||||
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||||
case eChatMessageType::UNEXPECTED_DISCONNECT:
|
|
||||||
case eChatMessageType::PLAYER_READY:
|
case eChatMessageType::PLAYER_READY:
|
||||||
case eChatMessageType::GET_DONATION_TOTAL:
|
case eChatMessageType::GET_DONATION_TOTAL:
|
||||||
case eChatMessageType::UPDATE_DONATION:
|
case eChatMessageType::UPDATE_DONATION:
|
||||||
case eChatMessageType::PRG_CSR_COMMAND:
|
case eChatMessageType::PRG_CSR_COMMAND:
|
||||||
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
|
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
|
||||||
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
|
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
|
||||||
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chat_message_type).data(), chat_message_type);
|
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG("Unknown CHAT Message id: %i", chat_message_type);
|
LOG("Unknown CHAT Message id: %i", chatMessageID);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
|
|
||||||
switch (static_cast<eWorldMessageType>(packet->data[3])) {
|
|
||||||
case eWorldMessageType::ROUTE_PACKET: {
|
|
||||||
LOG("Routing packet from world");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG("Unknown World id: %i", int(packet->data[3]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
|
||||||
#include "ChatPackets.h"
|
#include "ChatPackets.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
#include "eChatMessageType.h"
|
||||||
|
|
||||||
void PlayerContainer::Initialize() {
|
void PlayerContainer::Initialize() {
|
||||||
m_MaxNumberOfBestFriends =
|
m_MaxNumberOfBestFriends =
|
||||||
@@ -49,6 +49,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
data.sysAddr = packet->systemAddress;
|
data.sysAddr = packet->systemAddress;
|
||||||
|
|
||||||
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
||||||
|
m_PlayerCount++;
|
||||||
|
|
||||||
LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
|
LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
|
||||||
|
|
||||||
@@ -87,6 +88,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_PlayerCount--;
|
||||||
LOG("Removed user: %llu", playerID);
|
LOG("Removed user: %llu", playerID);
|
||||||
m_Players.erase(playerID);
|
m_Players.erase(playerID);
|
||||||
|
|
||||||
@@ -145,7 +147,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
|
|||||||
|
|
||||||
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_MUTE);
|
||||||
|
|
||||||
bitStream.Write(player);
|
bitStream.Write(player);
|
||||||
bitStream.Write(time);
|
bitStream.Write(time);
|
||||||
@@ -352,7 +354,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
|
|||||||
|
|
||||||
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::TEAM_GET_STATUS);
|
||||||
|
|
||||||
bitStream.Write(team->teamID);
|
bitStream.Write(team->teamID);
|
||||||
bitStream.Write(deleteTeam);
|
bitStream.Write(deleteTeam);
|
||||||
@@ -390,7 +392,7 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
|
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
|
||||||
return m_Players[playerID];
|
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {
|
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ public:
|
|||||||
const PlayerData& GetPlayerData(const std::string& playerName);
|
const PlayerData& GetPlayerData(const std::string& playerName);
|
||||||
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
|
PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
|
||||||
PlayerData& GetPlayerDataMutable(const std::string& playerName);
|
PlayerData& GetPlayerDataMutable(const std::string& playerName);
|
||||||
|
uint32_t GetPlayerCount() { return m_PlayerCount; };
|
||||||
|
uint32_t GetSimCount() { return m_SimCount; };
|
||||||
|
const std::map<LWOOBJID, PlayerData>& GetAllPlayers() { return m_Players; };
|
||||||
|
|
||||||
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
|
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
|
||||||
TeamData* CreateTeam(LWOOBJID leader, bool local = false);
|
TeamData* CreateTeam(LWOOBJID leader, bool local = false);
|
||||||
@@ -93,5 +96,7 @@ private:
|
|||||||
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
std::unordered_map<LWOOBJID, std::u16string> m_Names;
|
||||||
uint32_t m_MaxNumberOfBestFriends = 5;
|
uint32_t m_MaxNumberOfBestFriends = 5;
|
||||||
uint32_t m_MaxNumberOfFriends = 50;
|
uint32_t m_MaxNumberOfFriends = 50;
|
||||||
|
uint32_t m_PlayerCount = 0;
|
||||||
|
uint32_t m_SimCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -120,6 +120,8 @@ void CatchUnhandled(int sig) {
|
|||||||
if (eptr) std::rethrow_exception(eptr);
|
if (eptr) std::rethrow_exception(eptr);
|
||||||
} catch(const std::exception& e) {
|
} catch(const std::exception& e) {
|
||||||
LOG("Caught exception: '%s'", e.what());
|
LOG("Caught exception: '%s'", e.what());
|
||||||
|
} catch (...) {
|
||||||
|
LOG("Caught unknown exception.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef INCLUDE_BACKTRACE
|
#ifndef INCLUDE_BACKTRACE
|
||||||
@@ -199,7 +201,7 @@ void OnTerminate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MakeBacktrace() {
|
void MakeBacktrace() {
|
||||||
struct sigaction sigact;
|
struct sigaction sigact{};
|
||||||
|
|
||||||
sigact.sa_sigaction = CritErrHdlr;
|
sigact.sa_sigaction = CritErrHdlr;
|
||||||
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
|
sigact.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||||
|
|||||||
@@ -8,23 +8,23 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline size_t MinSize(size_t size, const std::basic_string_view<T>& string) {
|
static inline size_t MinSize(const size_t size, const std::basic_string_view<T> string) {
|
||||||
if (size == size_t(-1) || size > string.size()) {
|
if (size == SIZE_MAX || size > string.size()) {
|
||||||
return string.size();
|
return string.size();
|
||||||
} else {
|
} else {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsLeadSurrogate(char16_t c) {
|
inline bool IsLeadSurrogate(const char16_t c) {
|
||||||
return (0xD800 <= c) && (c <= 0xDBFF);
|
return (0xD800 <= c) && (c <= 0xDBFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsTrailSurrogate(char16_t c) {
|
inline bool IsTrailSurrogate(const char16_t c) {
|
||||||
return (0xDC00 <= c) && (c <= 0xDFFF);
|
return (0xDC00 <= c) && (c <= 0xDFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
|
inline void PushUTF8CodePoint(std::string& ret, const char32_t cp) {
|
||||||
if (cp <= 0x007F) {
|
if (cp <= 0x007F) {
|
||||||
ret.push_back(static_cast<uint8_t>(cp));
|
ret.push_back(static_cast<uint8_t>(cp));
|
||||||
} else if (cp <= 0x07FF) {
|
} else if (cp <= 0x07FF) {
|
||||||
@@ -46,16 +46,16 @@ inline void PushUTF8CodePoint(std::string& ret, char32_t cp) {
|
|||||||
|
|
||||||
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
|
constexpr const char16_t REPLACEMENT_CHARACTER = 0xFFFD;
|
||||||
|
|
||||||
bool _IsSuffixChar(uint8_t c) {
|
bool static _IsSuffixChar(const uint8_t c) {
|
||||||
return (c & 0xC0) == 0x80;
|
return (c & 0xC0) == 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
bool GeneralUtils::details::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
||||||
size_t rem = slice.length();
|
const size_t rem = slice.length();
|
||||||
if (slice.empty()) return false;
|
if (slice.empty()) return false;
|
||||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
|
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&slice.front());
|
||||||
if (rem > 0) {
|
if (rem > 0) {
|
||||||
uint8_t first = bytes[0];
|
const uint8_t first = bytes[0];
|
||||||
if (first < 0x80) { // 1 byte character
|
if (first < 0x80) { // 1 byte character
|
||||||
out = static_cast<uint32_t>(first & 0x7F);
|
out = static_cast<uint32_t>(first & 0x7F);
|
||||||
slice.remove_prefix(1);
|
slice.remove_prefix(1);
|
||||||
@@ -64,7 +64,7 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
|||||||
// middle byte, not valid at start, fall through
|
// middle byte, not valid at start, fall through
|
||||||
} else if (first < 0xE0) { // two byte character
|
} else if (first < 0xE0) { // two byte character
|
||||||
if (rem > 1) {
|
if (rem > 1) {
|
||||||
uint8_t second = bytes[1];
|
const uint8_t second = bytes[1];
|
||||||
if (_IsSuffixChar(second)) {
|
if (_IsSuffixChar(second)) {
|
||||||
out = (static_cast<uint32_t>(first & 0x1F) << 6)
|
out = (static_cast<uint32_t>(first & 0x1F) << 6)
|
||||||
+ static_cast<uint32_t>(second & 0x3F);
|
+ static_cast<uint32_t>(second & 0x3F);
|
||||||
@@ -74,8 +74,8 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
|||||||
}
|
}
|
||||||
} else if (first < 0xF0) { // three byte character
|
} else if (first < 0xF0) { // three byte character
|
||||||
if (rem > 2) {
|
if (rem > 2) {
|
||||||
uint8_t second = bytes[1];
|
const uint8_t second = bytes[1];
|
||||||
uint8_t third = bytes[2];
|
const uint8_t third = bytes[2];
|
||||||
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
|
if (_IsSuffixChar(second) && _IsSuffixChar(third)) {
|
||||||
out = (static_cast<uint32_t>(first & 0x0F) << 12)
|
out = (static_cast<uint32_t>(first & 0x0F) << 12)
|
||||||
+ (static_cast<uint32_t>(second & 0x3F) << 6)
|
+ (static_cast<uint32_t>(second & 0x3F) << 6)
|
||||||
@@ -86,9 +86,9 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
|||||||
}
|
}
|
||||||
} else if (first < 0xF8) { // four byte character
|
} else if (first < 0xF8) { // four byte character
|
||||||
if (rem > 3) {
|
if (rem > 3) {
|
||||||
uint8_t second = bytes[1];
|
const uint8_t second = bytes[1];
|
||||||
uint8_t third = bytes[2];
|
const uint8_t third = bytes[2];
|
||||||
uint8_t fourth = bytes[3];
|
const uint8_t fourth = bytes[3];
|
||||||
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
|
if (_IsSuffixChar(second) && _IsSuffixChar(third) && _IsSuffixChar(fourth)) {
|
||||||
out = (static_cast<uint32_t>(first & 0x07) << 18)
|
out = (static_cast<uint32_t>(first & 0x07) << 18)
|
||||||
+ (static_cast<uint32_t>(second & 0x3F) << 12)
|
+ (static_cast<uint32_t>(second & 0x3F) << 12)
|
||||||
@@ -107,7 +107,7 @@ bool GeneralUtils::_NextUTF8Char(std::string_view& slice, uint32_t& out) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
|
/// See <https://www.ietf.org/rfc/rfc2781.html#section-2.1>
|
||||||
bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
|
bool PushUTF16CodePoint(std::u16string& output, const uint32_t U, const size_t size) {
|
||||||
if (output.length() >= size) return false;
|
if (output.length() >= size) return false;
|
||||||
if (U < 0x10000) {
|
if (U < 0x10000) {
|
||||||
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
|
// If U < 0x10000, encode U as a 16-bit unsigned integer and terminate.
|
||||||
@@ -120,7 +120,7 @@ bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
|
|||||||
// Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
|
// Let U' = U - 0x10000. Because U is less than or equal to 0x10FFFF,
|
||||||
// U' must be less than or equal to 0xFFFFF. That is, U' can be
|
// U' must be less than or equal to 0xFFFFF. That is, U' can be
|
||||||
// represented in 20 bits.
|
// represented in 20 bits.
|
||||||
uint32_t Ut = U - 0x10000;
|
const uint32_t Ut = U - 0x10000;
|
||||||
|
|
||||||
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
|
// Initialize two 16-bit unsigned integers, W1 and W2, to 0xD800 and
|
||||||
// 0xDC00, respectively. These integers each have 10 bits free to
|
// 0xDC00, respectively. These integers each have 10 bits free to
|
||||||
@@ -141,25 +141,25 @@ bool PushUTF16CodePoint(std::u16string& output, uint32_t U, size_t size) {
|
|||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view& string, size_t size) {
|
std::u16string GeneralUtils::UTF8ToUTF16(const std::string_view string, const size_t size) {
|
||||||
size_t newSize = MinSize(size, string);
|
const size_t newSize = MinSize(size, string);
|
||||||
std::u16string output;
|
std::u16string output;
|
||||||
output.reserve(newSize);
|
output.reserve(newSize);
|
||||||
std::string_view iterator = string;
|
std::string_view iterator = string;
|
||||||
|
|
||||||
uint32_t c;
|
uint32_t c;
|
||||||
while (_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
|
while (details::_NextUTF8Char(iterator, c) && PushUTF16CodePoint(output, c, size)) {}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Converts an std::string (ASCII) to UCS-2 / UTF-16
|
//! Converts an std::string (ASCII) to UCS-2 / UTF-16
|
||||||
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t size) {
|
std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view string, const size_t size) {
|
||||||
size_t newSize = MinSize(size, string);
|
const size_t newSize = MinSize(size, string);
|
||||||
std::u16string ret;
|
std::u16string ret;
|
||||||
ret.reserve(newSize);
|
ret.reserve(newSize);
|
||||||
|
|
||||||
for (size_t i = 0; i < newSize; i++) {
|
for (size_t i = 0; i < newSize; ++i) {
|
||||||
char c = string[i];
|
const char c = string[i];
|
||||||
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
|
// Note: both 7-bit ascii characters and REPLACEMENT_CHARACTER fit in one char16_t
|
||||||
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
|
ret.push_back((c > 0 && c <= 127) ? static_cast<char16_t>(c) : REPLACEMENT_CHARACTER);
|
||||||
}
|
}
|
||||||
@@ -169,18 +169,18 @@ std::u16string GeneralUtils::ASCIIToUTF16(const std::string_view& string, size_t
|
|||||||
|
|
||||||
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
|
//! Converts a (potentially-ill-formed) UTF-16 string to UTF-8
|
||||||
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
|
//! See: <http://simonsapin.github.io/wtf-8/#decoding-ill-formed-utf-16>
|
||||||
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t size) {
|
std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view string, const size_t size) {
|
||||||
size_t newSize = MinSize(size, string);
|
const size_t newSize = MinSize(size, string);
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.reserve(newSize);
|
ret.reserve(newSize);
|
||||||
|
|
||||||
for (size_t i = 0; i < newSize; i++) {
|
for (size_t i = 0; i < newSize; ++i) {
|
||||||
char16_t u = string[i];
|
const char16_t u = string[i];
|
||||||
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
|
if (IsLeadSurrogate(u) && (i + 1) < newSize) {
|
||||||
char16_t next = string[i + 1];
|
const char16_t next = string[i + 1];
|
||||||
if (IsTrailSurrogate(next)) {
|
if (IsTrailSurrogate(next)) {
|
||||||
i += 1;
|
i += 1;
|
||||||
char32_t cp = 0x10000
|
const char32_t cp = 0x10000
|
||||||
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
|
+ ((static_cast<char32_t>(u) - 0xD800) << 10)
|
||||||
+ (static_cast<char32_t>(next) - 0xDC00);
|
+ (static_cast<char32_t>(next) - 0xDC00);
|
||||||
PushUTF8CodePoint(ret, cp);
|
PushUTF8CodePoint(ret, cp);
|
||||||
@@ -195,40 +195,40 @@ std::string GeneralUtils::UTF16ToWTF8(const std::u16string_view& string, size_t
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string& a, const std::string& b) {
|
bool GeneralUtils::CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b) {
|
||||||
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });
|
return std::equal(a.begin(), a.end(), b.begin(), b.end(), [](char a, char b) { return tolower(a) == tolower(b); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Bits
|
// MARK: Bits
|
||||||
|
|
||||||
//! Sets a specific bit in a signed 64-bit integer
|
//! Sets a specific bit in a signed 64-bit integer
|
||||||
int64_t GeneralUtils::SetBit(int64_t value, uint32_t index) {
|
int64_t GeneralUtils::SetBit(int64_t value, const uint32_t index) {
|
||||||
return value |= 1ULL << index;
|
return value |= 1ULL << index;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Clears a specific bit in a signed 64-bit integer
|
//! Clears a specific bit in a signed 64-bit integer
|
||||||
int64_t GeneralUtils::ClearBit(int64_t value, uint32_t index) {
|
int64_t GeneralUtils::ClearBit(int64_t value, const uint32_t index) {
|
||||||
return value &= ~(1ULL << index);
|
return value &= ~(1ULL << index);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Checks a specific bit in a signed 64-bit integer
|
//! Checks a specific bit in a signed 64-bit integer
|
||||||
bool GeneralUtils::CheckBit(int64_t value, uint32_t index) {
|
bool GeneralUtils::CheckBit(int64_t value, const uint32_t index) {
|
||||||
return value & (1ULL << index);
|
return value & (1ULL << index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneralUtils::ReplaceInString(std::string& str, const std::string& from, const std::string& to) {
|
bool GeneralUtils::ReplaceInString(std::string& str, const std::string_view from, const std::string_view to) {
|
||||||
size_t start_pos = str.find(from);
|
const size_t start_pos = str.find(from);
|
||||||
if (start_pos == std::string::npos)
|
if (start_pos == std::string::npos)
|
||||||
return false;
|
return false;
|
||||||
str.replace(start_pos, from.length(), to);
|
str.replace(start_pos, from.length(), to);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t delimiter) {
|
std::vector<std::wstring> GeneralUtils::SplitString(const std::wstring_view str, const wchar_t delimiter) {
|
||||||
std::vector<std::wstring> vector = std::vector<std::wstring>();
|
std::vector<std::wstring> vector = std::vector<std::wstring>();
|
||||||
std::wstring current;
|
std::wstring current;
|
||||||
|
|
||||||
for (const auto& c : str) {
|
for (const wchar_t c : str) {
|
||||||
if (c == delimiter) {
|
if (c == delimiter) {
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = L"";
|
current = L"";
|
||||||
@@ -237,15 +237,15 @@ std::vector<std::wstring> GeneralUtils::SplitString(std::wstring& str, wchar_t d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.push_back(current);
|
vector.push_back(std::move(current));
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string& str, char16_t delimiter) {
|
std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string_view str, const char16_t delimiter) {
|
||||||
std::vector<std::u16string> vector = std::vector<std::u16string>();
|
std::vector<std::u16string> vector = std::vector<std::u16string>();
|
||||||
std::u16string current;
|
std::u16string current;
|
||||||
|
|
||||||
for (const auto& c : str) {
|
for (const char16_t c : str) {
|
||||||
if (c == delimiter) {
|
if (c == delimiter) {
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = u"";
|
current = u"";
|
||||||
@@ -254,17 +254,15 @@ std::vector<std::u16string> GeneralUtils::SplitString(const std::u16string& str,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.push_back(current);
|
vector.push_back(std::move(current));
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char delimiter) {
|
std::vector<std::string> GeneralUtils::SplitString(const std::string_view str, const char delimiter) {
|
||||||
std::vector<std::string> vector = std::vector<std::string>();
|
std::vector<std::string> vector = std::vector<std::string>();
|
||||||
std::string current = "";
|
std::string current = "";
|
||||||
|
|
||||||
for (size_t i = 0; i < str.length(); i++) {
|
for (const char c : str) {
|
||||||
char c = str[i];
|
|
||||||
|
|
||||||
if (c == delimiter) {
|
if (c == delimiter) {
|
||||||
vector.push_back(current);
|
vector.push_back(current);
|
||||||
current = "";
|
current = "";
|
||||||
@@ -273,8 +271,7 @@ std::vector<std::string> GeneralUtils::SplitString(const std::string& str, char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector.push_back(current);
|
vector.push_back(std::move(current));
|
||||||
|
|
||||||
return vector;
|
return vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,7 +280,7 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
|
|||||||
inStream.Read<uint32_t>(length);
|
inStream.Read<uint32_t>(length);
|
||||||
|
|
||||||
std::u16string string;
|
std::u16string string;
|
||||||
for (auto i = 0; i < length; i++) {
|
for (uint32_t i = 0; i < length; ++i) {
|
||||||
uint16_t c;
|
uint16_t c;
|
||||||
inStream.Read(c);
|
inStream.Read(c);
|
||||||
string.push_back(c);
|
string.push_back(c);
|
||||||
@@ -292,35 +289,35 @@ std::u16string GeneralUtils::ReadWString(RakNet::BitStream& inStream) {
|
|||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string& folder) {
|
std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::string_view folder) {
|
||||||
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
|
// Because we dont know how large the initial number before the first _ is we need to make it a map like so.
|
||||||
std::map<uint32_t, std::string> filenames{};
|
std::map<uint32_t, std::string> filenames{};
|
||||||
for (auto& t : std::filesystem::directory_iterator(folder)) {
|
for (const auto& t : std::filesystem::directory_iterator(folder)) {
|
||||||
auto filename = t.path().filename().string();
|
auto filename = t.path().filename().string();
|
||||||
auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
const auto index = std::stoi(GeneralUtils::SplitString(filename, '_').at(0));
|
||||||
filenames.insert(std::make_pair(index, filename));
|
filenames.emplace(index, std::move(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now sort the map by the oldest migration.
|
// Now sort the map by the oldest migration.
|
||||||
std::vector<std::string> sortedFiles{};
|
std::vector<std::string> sortedFiles{};
|
||||||
auto fileIterator = filenames.begin();
|
auto fileIterator = filenames.cbegin();
|
||||||
std::map<uint32_t, std::string>::iterator oldest = filenames.begin();
|
auto oldest = filenames.cbegin();
|
||||||
while (!filenames.empty()) {
|
while (!filenames.empty()) {
|
||||||
if (fileIterator == filenames.end()) {
|
if (fileIterator == filenames.cend()) {
|
||||||
sortedFiles.push_back(oldest->second);
|
sortedFiles.push_back(oldest->second);
|
||||||
filenames.erase(oldest);
|
filenames.erase(oldest);
|
||||||
fileIterator = filenames.begin();
|
fileIterator = filenames.cbegin();
|
||||||
oldest = filenames.begin();
|
oldest = filenames.cbegin();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (oldest->first > fileIterator->first) oldest = fileIterator;
|
if (oldest->first > fileIterator->first) oldest = fileIterator;
|
||||||
fileIterator++;
|
++fileIterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sortedFiles;
|
return sortedFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DARKFLAME_PLATFORM_MACOS
|
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
|
||||||
|
|
||||||
// MacOS floating-point parse function specializations
|
// MacOS floating-point parse function specializations
|
||||||
namespace GeneralUtils::details {
|
namespace GeneralUtils::details {
|
||||||
|
|||||||
@@ -3,17 +3,18 @@
|
|||||||
// C++
|
// C++
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <random>
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <functional>
|
||||||
|
#include <optional>
|
||||||
|
#include <random>
|
||||||
|
#include <span>
|
||||||
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <optional>
|
|
||||||
#include <functional>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <stdexcept>
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
|
|
||||||
#include "dPlatforms.h"
|
#include "dPlatforms.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
@@ -32,29 +33,31 @@ namespace GeneralUtils {
|
|||||||
//! Converts a plain ASCII string to a UTF-16 string
|
//! Converts a plain ASCII string to a UTF-16 string
|
||||||
/*!
|
/*!
|
||||||
\param string The string to convert
|
\param string The string to convert
|
||||||
\param size A size to trim the string to. Default is -1 (No trimming)
|
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
|
||||||
\return An UTF-16 representation of the string
|
\return An UTF-16 representation of the string
|
||||||
*/
|
*/
|
||||||
std::u16string ASCIIToUTF16(const std::string_view& string, size_t size = -1);
|
std::u16string ASCIIToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
|
||||||
|
|
||||||
//! Converts a UTF-8 String to a UTF-16 string
|
//! Converts a UTF-8 String to a UTF-16 string
|
||||||
/*!
|
/*!
|
||||||
\param string The string to convert
|
\param string The string to convert
|
||||||
\param size A size to trim the string to. Default is -1 (No trimming)
|
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
|
||||||
\return An UTF-16 representation of the string
|
\return An UTF-16 representation of the string
|
||||||
*/
|
*/
|
||||||
std::u16string UTF8ToUTF16(const std::string_view& string, size_t size = -1);
|
std::u16string UTF8ToUTF16(const std::string_view string, const size_t size = SIZE_MAX);
|
||||||
|
|
||||||
//! Internal, do not use
|
namespace details {
|
||||||
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
|
//! Internal, do not use
|
||||||
|
bool _NextUTF8Char(std::string_view& slice, uint32_t& out);
|
||||||
|
}
|
||||||
|
|
||||||
//! Converts a UTF-16 string to a UTF-8 string
|
//! Converts a UTF-16 string to a UTF-8 string
|
||||||
/*!
|
/*!
|
||||||
\param string The string to convert
|
\param string The string to convert
|
||||||
\param size A size to trim the string to. Default is -1 (No trimming)
|
\param size A size to trim the string to. Default is SIZE_MAX (No trimming)
|
||||||
\return An UTF-8 representation of the string
|
\return An UTF-8 representation of the string
|
||||||
*/
|
*/
|
||||||
std::string UTF16ToWTF8(const std::u16string_view& string, size_t size = -1);
|
std::string UTF16ToWTF8(const std::u16string_view string, const size_t size = SIZE_MAX);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares two basic strings but does so ignoring case sensitivity
|
* Compares two basic strings but does so ignoring case sensitivity
|
||||||
@@ -62,7 +65,7 @@ namespace GeneralUtils {
|
|||||||
* \param b the second string to compare against the first string
|
* \param b the second string to compare against the first string
|
||||||
* @return if the two strings are equal
|
* @return if the two strings are equal
|
||||||
*/
|
*/
|
||||||
bool CaseInsensitiveStringCompare(const std::string& a, const std::string& b);
|
bool CaseInsensitiveStringCompare(const std::string_view a, const std::string_view b);
|
||||||
|
|
||||||
// MARK: Bits
|
// MARK: Bits
|
||||||
|
|
||||||
@@ -70,9 +73,9 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
//! Sets a bit on a numerical value
|
//! Sets a bit on a numerical value
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void SetBit(T& value, eObjectBits bits) {
|
inline void SetBit(T& value, const eObjectBits bits) {
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
auto index = static_cast<size_t>(bits);
|
const auto index = static_cast<size_t>(bits);
|
||||||
if (index > (sizeof(T) * 8) - 1) {
|
if (index > (sizeof(T) * 8) - 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -82,9 +85,9 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
//! Clears a bit on a numerical value
|
//! Clears a bit on a numerical value
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void ClearBit(T& value, eObjectBits bits) {
|
inline void ClearBit(T& value, const eObjectBits bits) {
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
auto index = static_cast<size_t>(bits);
|
const auto index = static_cast<size_t>(bits);
|
||||||
if (index > (sizeof(T) * 8 - 1)) {
|
if (index > (sizeof(T) * 8 - 1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -97,14 +100,14 @@ namespace GeneralUtils {
|
|||||||
\param value The value to set the bit for
|
\param value The value to set the bit for
|
||||||
\param index The index of the bit
|
\param index The index of the bit
|
||||||
*/
|
*/
|
||||||
int64_t SetBit(int64_t value, uint32_t index);
|
int64_t SetBit(int64_t value, const uint32_t index);
|
||||||
|
|
||||||
//! Clears a specific bit in a signed 64-bit integer
|
//! Clears a specific bit in a signed 64-bit integer
|
||||||
/*!
|
/*!
|
||||||
\param value The value to clear the bit from
|
\param value The value to clear the bit from
|
||||||
\param index The index of the bit
|
\param index The index of the bit
|
||||||
*/
|
*/
|
||||||
int64_t ClearBit(int64_t value, uint32_t index);
|
int64_t ClearBit(int64_t value, const uint32_t index);
|
||||||
|
|
||||||
//! Checks a specific bit in a signed 64-bit integer
|
//! Checks a specific bit in a signed 64-bit integer
|
||||||
/*!
|
/*!
|
||||||
@@ -112,19 +115,19 @@ namespace GeneralUtils {
|
|||||||
\param index The index of the bit
|
\param index The index of the bit
|
||||||
\return Whether or not the bit is set
|
\return Whether or not the bit is set
|
||||||
*/
|
*/
|
||||||
bool CheckBit(int64_t value, uint32_t index);
|
bool CheckBit(int64_t value, const uint32_t index);
|
||||||
|
|
||||||
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
bool ReplaceInString(std::string& str, const std::string_view from, const std::string_view to);
|
||||||
|
|
||||||
std::u16string ReadWString(RakNet::BitStream& inStream);
|
std::u16string ReadWString(RakNet::BitStream& inStream);
|
||||||
|
|
||||||
std::vector<std::wstring> SplitString(std::wstring& str, wchar_t delimiter);
|
std::vector<std::wstring> SplitString(const std::wstring_view str, const wchar_t delimiter);
|
||||||
|
|
||||||
std::vector<std::u16string> SplitString(const std::u16string& str, char16_t delimiter);
|
std::vector<std::u16string> SplitString(const std::u16string_view str, const char16_t delimiter);
|
||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string& str, char delimiter);
|
std::vector<std::string> SplitString(const std::string_view str, const char delimiter);
|
||||||
|
|
||||||
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string& folder);
|
std::vector<std::string> GetSqlFileNamesFromFolder(const std::string_view folder);
|
||||||
|
|
||||||
// Concept constraining to enum types
|
// Concept constraining to enum types
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -144,7 +147,7 @@ namespace GeneralUtils {
|
|||||||
|
|
||||||
// If a boolean, present an alias to an intermediate integral type for parsing
|
// If a boolean, present an alias to an intermediate integral type for parsing
|
||||||
template <Numeric T> requires std::same_as<T, bool>
|
template <Numeric T> requires std::same_as<T, bool>
|
||||||
struct numeric_parse<T> { using type = uint32_t; };
|
struct numeric_parse<T> { using type = uint8_t; };
|
||||||
|
|
||||||
// Shorthand type alias
|
// Shorthand type alias
|
||||||
template <Numeric T>
|
template <Numeric T>
|
||||||
@@ -156,8 +159,9 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired value if it is equivalent to the string
|
* @returns An std::optional containing the desired value if it is equivalent to the string
|
||||||
*/
|
*/
|
||||||
template <Numeric T>
|
template <Numeric T>
|
||||||
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
|
[[nodiscard]] std::optional<T> TryParse(std::string_view str) {
|
||||||
numeric_parse_t<T> result;
|
numeric_parse_t<T> result;
|
||||||
|
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
|
||||||
|
|
||||||
const char* const strEnd = str.data() + str.size();
|
const char* const strEnd = str.data() + str.size();
|
||||||
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
|
const auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
|
||||||
@@ -166,7 +170,7 @@ namespace GeneralUtils {
|
|||||||
return isParsed ? static_cast<T>(result) : std::optional<T>{};
|
return isParsed ? static_cast<T>(result) : std::optional<T>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DARKFLAME_PLATFORM_MACOS
|
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
|
||||||
|
|
||||||
// MacOS floating-point parse helper function specializations
|
// MacOS floating-point parse helper function specializations
|
||||||
namespace details {
|
namespace details {
|
||||||
@@ -181,8 +185,10 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired value if it is equivalent to the string
|
* @returns An std::optional containing the desired value if it is equivalent to the string
|
||||||
*/
|
*/
|
||||||
template <std::floating_point T>
|
template <std::floating_point T>
|
||||||
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept
|
[[nodiscard]] std::optional<T> TryParse(std::string_view str) noexcept
|
||||||
try {
|
try {
|
||||||
|
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
|
||||||
|
|
||||||
size_t parseNum;
|
size_t parseNum;
|
||||||
const T result = details::_parse<T>(str, parseNum);
|
const T result = details::_parse<T>(str, parseNum);
|
||||||
const bool isParsed = str.length() == parseNum;
|
const bool isParsed = str.length() == parseNum;
|
||||||
@@ -202,7 +208,7 @@ namespace GeneralUtils {
|
|||||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string& strX, const std::string& strY, const std::string& strZ) {
|
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::string_view strX, const std::string_view strY, const std::string_view strZ) {
|
||||||
const auto x = TryParse<float>(strX);
|
const auto x = TryParse<float>(strX);
|
||||||
if (!x) return std::nullopt;
|
if (!x) return std::nullopt;
|
||||||
|
|
||||||
@@ -214,17 +220,17 @@ namespace GeneralUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TryParse overload for handling NiPoint3 by passingn a reference to a vector of three strings
|
* The TryParse overload for handling NiPoint3 by passing a span of three strings
|
||||||
* @param str The string vector representing the X, Y, and Xcoordinates
|
* @param str The string vector representing the X, Y, and Z coordinates
|
||||||
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
* @returns An std::optional containing the desired NiPoint3 if it can be constructed from the string parameters
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::vector<std::string>& str) {
|
[[nodiscard]] std::optional<NiPoint3> TryParse(const std::span<const std::string> str) {
|
||||||
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
return (str.size() == 3) ? TryParse<NiPoint3>(str[0], str[1], str[2]) : std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::u16string to_u16string(T value) {
|
std::u16string to_u16string(const T value) {
|
||||||
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
return GeneralUtils::ASCIIToUTF16(std::to_string(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +249,7 @@ namespace GeneralUtils {
|
|||||||
\param max The maximum to generate to
|
\param max The maximum to generate to
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
inline T GenerateRandomNumber(const std::size_t min, const std::size_t max) {
|
||||||
// Make sure it is a numeric type
|
// Make sure it is a numeric type
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
@@ -264,16 +270,16 @@ namespace GeneralUtils {
|
|||||||
* @returns The enum entry's value in its underlying type
|
* @returns The enum entry's value in its underlying type
|
||||||
*/
|
*/
|
||||||
template <Enum eType>
|
template <Enum eType>
|
||||||
constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) noexcept {
|
constexpr std::underlying_type_t<eType> ToUnderlying(const eType entry) noexcept {
|
||||||
return static_cast<typename std::underlying_type_t<eType>>(entry);
|
return static_cast<std::underlying_type_t<eType>>(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
||||||
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T GenerateRandomNumber() {
|
inline T GenerateRandomNumber() {
|
||||||
|
|||||||
@@ -31,22 +31,22 @@ public:
|
|||||||
|
|
||||||
virtual ~LDFBaseData() {}
|
virtual ~LDFBaseData() {}
|
||||||
|
|
||||||
virtual void WriteToPacket(RakNet::BitStream& packet) = 0;
|
virtual void WriteToPacket(RakNet::BitStream& packet) const = 0;
|
||||||
|
|
||||||
virtual const std::u16string& GetKey() = 0;
|
virtual const std::u16string& GetKey() const = 0;
|
||||||
|
|
||||||
virtual eLDFType GetValueType() = 0;
|
virtual eLDFType GetValueType() const = 0;
|
||||||
|
|
||||||
/** Gets a string from the key/value pair
|
/** Gets a string from the key/value pair
|
||||||
* @param includeKey Whether or not to include the key in the data
|
* @param includeKey Whether or not to include the key in the data
|
||||||
* @param includeTypeId Whether or not to include the type id in the data
|
* @param includeTypeId Whether or not to include the type id in the data
|
||||||
* @return The string representation of the data
|
* @return The string representation of the data
|
||||||
*/
|
*/
|
||||||
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) = 0;
|
virtual std::string GetString(bool includeKey = true, bool includeTypeId = true) const = 0;
|
||||||
|
|
||||||
virtual std::string GetValueAsString() = 0;
|
virtual std::string GetValueAsString() const = 0;
|
||||||
|
|
||||||
virtual LDFBaseData* Copy() = 0;
|
virtual LDFBaseData* Copy() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given an input string, return the data as a LDF key.
|
* Given an input string, return the data as a LDF key.
|
||||||
@@ -62,7 +62,7 @@ private:
|
|||||||
T value;
|
T value;
|
||||||
|
|
||||||
//! Writes the key to the packet
|
//! Writes the key to the packet
|
||||||
void WriteKey(RakNet::BitStream& packet) {
|
void WriteKey(RakNet::BitStream& packet) const {
|
||||||
packet.Write<uint8_t>(this->key.length() * sizeof(uint16_t));
|
packet.Write<uint8_t>(this->key.length() * sizeof(uint16_t));
|
||||||
for (uint32_t i = 0; i < this->key.length(); ++i) {
|
for (uint32_t i = 0; i < this->key.length(); ++i) {
|
||||||
packet.Write<uint16_t>(this->key[i]);
|
packet.Write<uint16_t>(this->key[i]);
|
||||||
@@ -70,7 +70,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Writes the value to the packet
|
//! Writes the value to the packet
|
||||||
void WriteValue(RakNet::BitStream& packet) {
|
void WriteValue(RakNet::BitStream& packet) const {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
packet.Write(this->value);
|
packet.Write(this->value);
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\return The value
|
\return The value
|
||||||
*/
|
*/
|
||||||
const T& GetValue(void) { return this->value; }
|
const T& GetValue(void) const { return this->value; }
|
||||||
|
|
||||||
//! Sets the value
|
//! Sets the value
|
||||||
/*!
|
/*!
|
||||||
@@ -102,13 +102,13 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\return The value string
|
\return The value string
|
||||||
*/
|
*/
|
||||||
std::string GetValueString(void) { return ""; }
|
std::string GetValueString(void) const { return ""; }
|
||||||
|
|
||||||
//! Writes the data to a packet
|
//! Writes the data to a packet
|
||||||
/*!
|
/*!
|
||||||
\param packet The packet
|
\param packet The packet
|
||||||
*/
|
*/
|
||||||
void WriteToPacket(RakNet::BitStream& packet) override {
|
void WriteToPacket(RakNet::BitStream& packet) const override {
|
||||||
this->WriteKey(packet);
|
this->WriteKey(packet);
|
||||||
this->WriteValue(packet);
|
this->WriteValue(packet);
|
||||||
}
|
}
|
||||||
@@ -117,13 +117,13 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
\return The key
|
\return The key
|
||||||
*/
|
*/
|
||||||
const std::u16string& GetKey(void) override { return this->key; }
|
const std::u16string& GetKey(void) const override { return this->key; }
|
||||||
|
|
||||||
//! Gets the LDF Type
|
//! Gets the LDF Type
|
||||||
/*!
|
/*!
|
||||||
\return The LDF value type
|
\return The LDF value type
|
||||||
*/
|
*/
|
||||||
eLDFType GetValueType(void) override { return LDF_TYPE_UNKNOWN; }
|
eLDFType GetValueType(void) const override { return LDF_TYPE_UNKNOWN; }
|
||||||
|
|
||||||
//! Gets the string data
|
//! Gets the string data
|
||||||
/*!
|
/*!
|
||||||
@@ -131,7 +131,7 @@ public:
|
|||||||
\param includeTypeId Whether or not to include the type id in the data
|
\param includeTypeId Whether or not to include the type id in the data
|
||||||
\return The string representation of the data
|
\return The string representation of the data
|
||||||
*/
|
*/
|
||||||
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) override {
|
std::string GetString(const bool includeKey = true, const bool includeTypeId = true) const override {
|
||||||
if (GetValueType() == -1) {
|
if (GetValueType() == -1) {
|
||||||
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
|
return GeneralUtils::UTF16ToWTF8(this->key) + "=-1:<server variable>";
|
||||||
}
|
}
|
||||||
@@ -154,11 +154,11 @@ public:
|
|||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetValueAsString() override {
|
std::string GetValueAsString() const override {
|
||||||
return this->GetValueString();
|
return this->GetValueString();
|
||||||
}
|
}
|
||||||
|
|
||||||
LDFBaseData* Copy() override {
|
LDFBaseData* Copy() const override {
|
||||||
return new LDFData<T>(key, value);
|
return new LDFData<T>(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,19 +166,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// LDF Types
|
// LDF Types
|
||||||
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) { return LDF_TYPE_UTF_16; };
|
template<> inline eLDFType LDFData<std::u16string>::GetValueType(void) const { return LDF_TYPE_UTF_16; };
|
||||||
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) { return LDF_TYPE_S32; };
|
template<> inline eLDFType LDFData<int32_t>::GetValueType(void) const { return LDF_TYPE_S32; };
|
||||||
template<> inline eLDFType LDFData<float>::GetValueType(void) { return LDF_TYPE_FLOAT; };
|
template<> inline eLDFType LDFData<float>::GetValueType(void) const { return LDF_TYPE_FLOAT; };
|
||||||
template<> inline eLDFType LDFData<double>::GetValueType(void) { return LDF_TYPE_DOUBLE; };
|
template<> inline eLDFType LDFData<double>::GetValueType(void) const { return LDF_TYPE_DOUBLE; };
|
||||||
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) { return LDF_TYPE_U32; };
|
template<> inline eLDFType LDFData<uint32_t>::GetValueType(void) const { return LDF_TYPE_U32; };
|
||||||
template<> inline eLDFType LDFData<bool>::GetValueType(void) { return LDF_TYPE_BOOLEAN; };
|
template<> inline eLDFType LDFData<bool>::GetValueType(void) const { return LDF_TYPE_BOOLEAN; };
|
||||||
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) { return LDF_TYPE_U64; };
|
template<> inline eLDFType LDFData<uint64_t>::GetValueType(void) const { return LDF_TYPE_U64; };
|
||||||
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) { return LDF_TYPE_OBJID; };
|
template<> inline eLDFType LDFData<LWOOBJID>::GetValueType(void) const { return LDF_TYPE_OBJID; };
|
||||||
template<> inline eLDFType LDFData<std::string>::GetValueType(void) { return LDF_TYPE_UTF_8; };
|
template<> inline eLDFType LDFData<std::string>::GetValueType(void) const { return LDF_TYPE_UTF_8; };
|
||||||
|
|
||||||
// The specialized version for std::u16string (UTF-16)
|
// The specialized version for std::u16string (UTF-16)
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) {
|
inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) const {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
|
|
||||||
packet.Write<uint32_t>(this->value.length());
|
packet.Write<uint32_t>(this->value.length());
|
||||||
@@ -189,7 +189,7 @@ inline void LDFData<std::u16string>::WriteValue(RakNet::BitStream& packet) {
|
|||||||
|
|
||||||
// The specialized version for bool
|
// The specialized version for bool
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) {
|
inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) const {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
|
|
||||||
packet.Write<uint8_t>(this->value);
|
packet.Write<uint8_t>(this->value);
|
||||||
@@ -197,7 +197,7 @@ inline void LDFData<bool>::WriteValue(RakNet::BitStream& packet) {
|
|||||||
|
|
||||||
// The specialized version for std::string (UTF-8)
|
// The specialized version for std::string (UTF-8)
|
||||||
template<>
|
template<>
|
||||||
inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) {
|
inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) const {
|
||||||
packet.Write<uint8_t>(this->GetValueType());
|
packet.Write<uint8_t>(this->GetValueType());
|
||||||
|
|
||||||
packet.Write<uint32_t>(this->value.length());
|
packet.Write<uint32_t>(this->value.length());
|
||||||
@@ -206,18 +206,18 @@ inline void LDFData<std::string>::WriteValue(RakNet::BitStream& packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::u16string>::GetValueString() {
|
template<> inline std::string LDFData<std::u16string>::GetValueString() const {
|
||||||
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
return GeneralUtils::UTF16ToWTF8(this->value, this->value.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline std::string LDFData<int32_t>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<int32_t>::GetValueString() const { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<float>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<float>::GetValueString() const { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<double>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<double>::GetValueString() const { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<uint32_t>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<uint32_t>::GetValueString() const { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<bool>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<bool>::GetValueString() const { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<uint64_t>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<uint64_t>::GetValueString() const { return std::to_string(this->value); }
|
||||||
template<> inline std::string LDFData<LWOOBJID>::GetValueString() { return std::to_string(this->value); }
|
template<> inline std::string LDFData<LWOOBJID>::GetValueString() const { return std::to_string(this->value); }
|
||||||
|
|
||||||
template<> inline std::string LDFData<std::string>::GetValueString() { return this->value; }
|
template<> inline std::string LDFData<std::string>::GetValueString() const { return this->value; }
|
||||||
|
|
||||||
#endif //!__LDFFORMAT__H__
|
#endif //!__LDFFORMAT__H__
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "BinaryPathFinder.h"
|
#include "BinaryPathFinder.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
|
|||||||
55
dCommon/dEnums/eCSRCommand.h
Normal file
55
dCommon/dEnums/eCSRCommand.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef __ECSRCOMMAND__H__
|
||||||
|
#define __ECSRCOMMAND__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class eCSRCommand : uint32_t {
|
||||||
|
QUERY_SERVER_STATUS = 0,
|
||||||
|
QUERY_CHARACTER_LOCATION,
|
||||||
|
QUERY_CHARACTER_ONLINE_STATUS,
|
||||||
|
INVENTORY_ADD_ITEM,
|
||||||
|
INVENTORY_DELETE_ITEM,
|
||||||
|
MODERATE_MUTE_ACCOUNT,
|
||||||
|
MODERATE_BAN_ACCOUNT,
|
||||||
|
MODERATE_EDUCATE_CHARACTER,
|
||||||
|
MODERATE_KICK_CHARACTER,
|
||||||
|
MODERATE_WARN_CHARACTER,
|
||||||
|
MODERATE_RENAME_CHARACTER,
|
||||||
|
MODERATE_DELETE_CHARACTER_FRIEND,
|
||||||
|
MODERATE_KILL_CHARACTER,
|
||||||
|
UPDATE_CHARACTER_HEALTH,
|
||||||
|
UPDATE_CHARACTER_ARMOR,
|
||||||
|
UPDATE_CHARACTER_IMAGINATION,
|
||||||
|
UPDATE_CHARACTER_MAX_HEALTH,
|
||||||
|
UPDATE_CHARACTER_MAX_ARMOR,
|
||||||
|
UPDATE_CHARACTER_MAX_IMAGINATION,
|
||||||
|
UPDATE_CHARACTER_CURRENCY,
|
||||||
|
UPDATE_CHARACTER_REPUTATION,
|
||||||
|
UPDATE_CHARACTER_LEGO_SCORE,
|
||||||
|
UPDATE_CHARACTER_EMOTES,
|
||||||
|
UPDATE_CHARACTER_ADD_ACHIEVEMENT,
|
||||||
|
UPDATE_CHARACTER_COMPLETE_ACHIEVEMENT,
|
||||||
|
UPDATE_CHARACTER_REMOVE_ACHIEVEMENT,
|
||||||
|
UPDATE_CHARACTER_POSITION_OFFLINE,
|
||||||
|
UPDATE_CHARACTER_INV_SLOT_AMOUNT,
|
||||||
|
UTILITY_SAVE_CHARACTER,
|
||||||
|
UTILITY_SEND_MAIL,
|
||||||
|
UTILITY_GIVE_ITEM_TO_ALL_PLAYERS_ONLINE,
|
||||||
|
METRICS_CONFIGURE,
|
||||||
|
DISABLE_ZONE,
|
||||||
|
INIT_DONATION_AMOUNT,
|
||||||
|
KILL_SERVERS_COUNTDOWN,
|
||||||
|
DISABLE_FAQ,
|
||||||
|
THROTTLEQUEUE,
|
||||||
|
GATEGM_ACCESS,
|
||||||
|
RECONNECT_CRISP,
|
||||||
|
MODERATE_KICK_ACCOUNT,
|
||||||
|
TOGGLE_CRISP_SERVER,
|
||||||
|
QUICK_DRAIN_SERVER,
|
||||||
|
QUICK_DRAIN_SERVER_RENEW,
|
||||||
|
REPLICATE_CHARACTER,
|
||||||
|
GET_SERVER_STATUS,
|
||||||
|
RELOAD_SERVER_INIS
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__ECSRCOMMAND__H__
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef __ECHATINTERNALMESSAGETYPE__H__
|
|
||||||
#define __ECHATINTERNALMESSAGETYPE__H__
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
enum eChatInternalMessageType : uint32_t {
|
|
||||||
PLAYER_ADDED_NOTIFICATION = 0,
|
|
||||||
PLAYER_REMOVED_NOTIFICATION,
|
|
||||||
ADD_FRIEND,
|
|
||||||
ADD_BEST_FRIEND,
|
|
||||||
ADD_TO_TEAM,
|
|
||||||
ADD_BLOCK,
|
|
||||||
REMOVE_FRIEND,
|
|
||||||
REMOVE_BLOCK,
|
|
||||||
REMOVE_FROM_TEAM,
|
|
||||||
DELETE_TEAM,
|
|
||||||
REPORT,
|
|
||||||
PRIVATE_CHAT,
|
|
||||||
PRIVATE_CHAT_RESPONSE,
|
|
||||||
ANNOUNCEMENT,
|
|
||||||
MAIL_COUNT_UPDATE,
|
|
||||||
MAIL_SEND_NOTIFY,
|
|
||||||
REQUEST_USER_LIST,
|
|
||||||
FRIEND_LIST,
|
|
||||||
ROUTE_TO_PLAYER,
|
|
||||||
TEAM_UPDATE,
|
|
||||||
MUTE_UPDATE,
|
|
||||||
CREATE_TEAM,
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__ECHATINTERNALMESSAGETYPE__H__
|
|
||||||
@@ -72,7 +72,9 @@ enum class eChatMessageType :uint32_t {
|
|||||||
UPDATE_DONATION,
|
UPDATE_DONATION,
|
||||||
PRG_CSR_COMMAND,
|
PRG_CSR_COMMAND,
|
||||||
HEARTBEAT_REQUEST_FROM_WORLD,
|
HEARTBEAT_REQUEST_FROM_WORLD,
|
||||||
UPDATE_FREE_TRIAL_STATUS
|
UPDATE_FREE_TRIAL_STATUS,
|
||||||
|
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
|
||||||
|
CREATE_TEAM,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //!__ECHATMESSAGETYPE__H__
|
#endif //!__ECHATMESSAGETYPE__H__
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ enum class eConnectionType : uint16_t {
|
|||||||
SERVER = 0,
|
SERVER = 0,
|
||||||
AUTH,
|
AUTH,
|
||||||
CHAT,
|
CHAT,
|
||||||
CHAT_INTERNAL,
|
WORLD = 4,
|
||||||
WORLD,
|
|
||||||
CLIENT,
|
CLIENT,
|
||||||
MASTER
|
MASTER
|
||||||
};
|
};
|
||||||
|
|||||||
16
dCommon/dEnums/eDeletionRestrictionsCheckType.h
Normal file
16
dCommon/dEnums/eDeletionRestrictionsCheckType.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef __EDELETIONRESTRICTIONSCHECKTYPE__H__
|
||||||
|
#define __EDELETIONRESTRICTIONSCHECKTYPE__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
enum class eDeletionRestrictionsCheckType : uint32_t {
|
||||||
|
INCLUDE_LOTS,
|
||||||
|
EXCLUDE_LOTS,
|
||||||
|
ANY_OF_THESE,
|
||||||
|
ALL_OF_THESE,
|
||||||
|
WHILE_IN_ZONE,
|
||||||
|
ALWAYS_RESTRICTED,
|
||||||
|
MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__EDELETIONRESTRICTIONSCHECKTYPE__H__
|
||||||
@@ -790,9 +790,10 @@ enum class eGameMessageType : uint16_t {
|
|||||||
GET_MISSION_TYPE_STATES = 853,
|
GET_MISSION_TYPE_STATES = 853,
|
||||||
GET_TIME_PLAYED = 854,
|
GET_TIME_PLAYED = 854,
|
||||||
SET_MISSION_VIEWED = 855,
|
SET_MISSION_VIEWED = 855,
|
||||||
SLASH_COMMAND_TEXT_FEEDBACK = 856,
|
HKX_VEHICLE_LOADED = 856,
|
||||||
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 857,
|
SLASH_COMMAND_TEXT_FEEDBACK = 857,
|
||||||
BROADCAST_TEXT_TO_CHATBOX = 858,
|
BROADCAST_TEXT_TO_CHATBOX = 858,
|
||||||
|
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 859,
|
||||||
OPEN_PROPERTY_MANAGEMENT = 860,
|
OPEN_PROPERTY_MANAGEMENT = 860,
|
||||||
OPEN_PROPERTY_VENDOR = 861,
|
OPEN_PROPERTY_VENDOR = 861,
|
||||||
VOTE_ON_PROPERTY = 862,
|
VOTE_ON_PROPERTY = 862,
|
||||||
|
|||||||
59
dCommon/dEnums/eWaypointCommandType.h
Normal file
59
dCommon/dEnums/eWaypointCommandType.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
#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__
|
||||||
@@ -29,8 +29,8 @@ enum class eWorldMessageType : uint32_t {
|
|||||||
ROUTE_PACKET, // Social?
|
ROUTE_PACKET, // Social?
|
||||||
POSITION_UPDATE,
|
POSITION_UPDATE,
|
||||||
MAIL,
|
MAIL,
|
||||||
WORD_CHECK, // Whitelist word check
|
WORD_CHECK, // AllowList word check
|
||||||
STRING_CHECK, // Whitelist string check
|
STRING_CHECK, // AllowList string check
|
||||||
GET_PLAYERS_IN_ZONE,
|
GET_PLAYERS_IN_ZONE,
|
||||||
REQUEST_UGC_MANIFEST_INFO,
|
REQUEST_UGC_MANIFEST_INFO,
|
||||||
BLUEPRINT_GET_ALL_DATA_REQUEST,
|
BLUEPRINT_GET_ALL_DATA_REQUEST,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "CDScriptComponentTable.h"
|
#include "CDScriptComponentTable.h"
|
||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
#include "CDZoneTableTable.h"
|
#include "CDZoneTableTable.h"
|
||||||
|
#include "CDTamingBuildPuzzleTable.h"
|
||||||
#include "CDVendorComponentTable.h"
|
#include "CDVendorComponentTable.h"
|
||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
#include "CDPackageComponentTable.h"
|
#include "CDPackageComponentTable.h"
|
||||||
@@ -40,8 +41,7 @@
|
|||||||
#include "CDRailActivatorComponent.h"
|
#include "CDRailActivatorComponent.h"
|
||||||
#include "CDRewardCodesTable.h"
|
#include "CDRewardCodesTable.h"
|
||||||
#include "CDPetComponentTable.h"
|
#include "CDPetComponentTable.h"
|
||||||
|
#include "CDDeletionRestrictionsTable.h"
|
||||||
#include <exception>
|
|
||||||
|
|
||||||
#ifndef CDCLIENT_CACHE_ALL
|
#ifndef CDCLIENT_CACHE_ALL
|
||||||
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
// Uncomment this to cache the full cdclient database into memory. This will make the server load faster, but will use more memory.
|
||||||
@@ -55,13 +55,6 @@
|
|||||||
#define CDCLIENT_DONT_CACHE_TABLE(x)
|
#define CDCLIENT_DONT_CACHE_TABLE(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class CDClientConnectionException : public std::exception {
|
|
||||||
public:
|
|
||||||
virtual const char* what() const throw() {
|
|
||||||
return "CDClientDatabase is not connected!";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Using a macro to reduce repetitive code and issues from copy and paste.
|
// Using a macro to reduce repetitive code and issues from copy and paste.
|
||||||
// As a note, ## in a macro is used to concatenate two tokens together.
|
// As a note, ## in a macro is used to concatenate two tokens together.
|
||||||
|
|
||||||
@@ -108,11 +101,15 @@ DEFINE_TABLE_STORAGE(CDRewardCodesTable);
|
|||||||
DEFINE_TABLE_STORAGE(CDRewardsTable);
|
DEFINE_TABLE_STORAGE(CDRewardsTable);
|
||||||
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
|
DEFINE_TABLE_STORAGE(CDScriptComponentTable);
|
||||||
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
|
DEFINE_TABLE_STORAGE(CDSkillBehaviorTable);
|
||||||
|
DEFINE_TABLE_STORAGE(CDTamingBuildPuzzleTable);
|
||||||
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
|
DEFINE_TABLE_STORAGE(CDVendorComponentTable);
|
||||||
DEFINE_TABLE_STORAGE(CDZoneTableTable);
|
DEFINE_TABLE_STORAGE(CDZoneTableTable);
|
||||||
|
DEFINE_TABLE_STORAGE(CDDeletionRestrictionsTable)
|
||||||
|
|
||||||
void CDClientManager::LoadValuesFromDatabase() {
|
void CDClientManager::LoadValuesFromDatabase() {
|
||||||
if (!CDClientDatabase::isConnected) throw CDClientConnectionException();
|
if (!CDClientDatabase::isConnected) {
|
||||||
|
throw std::runtime_error{ "CDClientDatabase is not connected!" };
|
||||||
|
}
|
||||||
|
|
||||||
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
CDActivityRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
CDActivitiesTable::Instance().LoadValuesFromDatabase();
|
||||||
@@ -152,8 +149,10 @@ void CDClientManager::LoadValuesFromDatabase() {
|
|||||||
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
CDRewardsTable::Instance().LoadValuesFromDatabase();
|
||||||
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
CDScriptComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
CDSkillBehaviorTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDTamingBuildPuzzleTable::Instance().LoadValuesFromDatabase();
|
||||||
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
CDVendorComponentTable::Instance().LoadValuesFromDatabase();
|
||||||
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
CDZoneTableTable::Instance().LoadValuesFromDatabase();
|
||||||
|
CDDeletionRestrictionsTable::Instance().LoadValuesFromDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDClientManager::LoadValuesFromDefaults() {
|
void CDClientManager::LoadValuesFromDefaults() {
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "CDDeletionRestrictionsTable.h"
|
||||||
|
#include "GeneralUtils.h"
|
||||||
|
#include "eDeletionRestrictionsCheckType.h"
|
||||||
|
|
||||||
|
CDDeletionRestriction CDDeletionRestrictionsTable::Default = {
|
||||||
|
.id = 0,
|
||||||
|
.restricted = false,
|
||||||
|
.ids = {},
|
||||||
|
.checkType = eDeletionRestrictionsCheckType::MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
void CDDeletionRestrictionsTable::LoadValuesFromDatabase() {
|
||||||
|
auto& entries = GetEntriesMutable();
|
||||||
|
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM DeletionRestrictions");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
CDDeletionRestriction entry;
|
||||||
|
entry.id = tableData.getIntField("id", -1);
|
||||||
|
if (entry.id == -1) continue;
|
||||||
|
entry.restricted = tableData.getIntField("restricted", -1);
|
||||||
|
const std::string raw_ids = tableData.getStringField("ids", "");
|
||||||
|
if (!raw_ids.empty()) {
|
||||||
|
for (const auto& idstr : GeneralUtils::SplitString(raw_ids, ',')) {
|
||||||
|
if (!idstr.empty()) {
|
||||||
|
const auto id = GeneralUtils::TryParse<int32_t>(idstr);
|
||||||
|
if (id) entry.ids.push_back(id.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entry.checkType = static_cast<eDeletionRestrictionsCheckType>(tableData.getIntField("checkType", static_cast<int>(eDeletionRestrictionsCheckType::MAX)));
|
||||||
|
|
||||||
|
entries.insert(std::make_pair(entry.id, entry));
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const CDDeletionRestriction& CDDeletionRestrictionsTable::GetByID(uint32_t id) {
|
||||||
|
auto& entries = GetEntries();
|
||||||
|
const auto& it = entries.find(id);
|
||||||
|
if (it != entries.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
enum class eDeletionRestrictionsCheckType : uint32_t;
|
||||||
|
|
||||||
|
struct CDDeletionRestriction {
|
||||||
|
uint32_t id;
|
||||||
|
bool restricted;
|
||||||
|
std::vector<uint32_t> ids;
|
||||||
|
eDeletionRestrictionsCheckType checkType;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDDeletionRestrictionsTable : public CDTable<CDDeletionRestrictionsTable, std::map<uint32_t, CDDeletionRestriction>> {
|
||||||
|
public:
|
||||||
|
void LoadValuesFromDatabase();
|
||||||
|
const CDDeletionRestriction& GetByID(uint32_t id);
|
||||||
|
|
||||||
|
static CDDeletionRestriction Default;
|
||||||
|
};
|
||||||
@@ -33,7 +33,7 @@ struct CDItemComponent {
|
|||||||
uint32_t itemRating; //!< ???
|
uint32_t itemRating; //!< ???
|
||||||
bool isTwoHanded; //!< Whether or not the item is double handed
|
bool isTwoHanded; //!< Whether or not the item is double handed
|
||||||
uint32_t minNumRequired; //!< Maybe the minimum number required for a mission, or to own this object?
|
uint32_t minNumRequired; //!< Maybe the minimum number required for a mission, or to own this object?
|
||||||
uint32_t delResIndex; //!< ???
|
uint32_t delResIndex; //!< Relates to DeletionRestrictions Table
|
||||||
uint32_t currencyLOT; //!< ???
|
uint32_t currencyLOT; //!< ???
|
||||||
uint32_t altCurrencyCost; //!< ???
|
uint32_t altCurrencyCost; //!< ???
|
||||||
std::string subItems; //!< A comma seperate string of sub items (maybe for multi-itemed things like faction test gear set)
|
std::string subItems; //!< A comma seperate string of sub items (maybe for multi-itemed things like faction test gear set)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
|||||||
CDLootTable entry;
|
CDLootTable entry;
|
||||||
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
uint32_t lootTableIndex = tableData.getIntField("LootTableIndex", -1);
|
||||||
|
|
||||||
entries[lootTableIndex].push_back(ReadRow(tableData));
|
entries[lootTableIndex].emplace_back(ReadRow(tableData));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
for (auto& [id, table] : entries) {
|
for (auto& [id, table] : entries) {
|
||||||
@@ -66,7 +66,7 @@ void CDLootTableTable::LoadValuesFromDatabase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
|
const LootTableEntries& CDLootTableTable::GetTable(const uint32_t tableId) {
|
||||||
auto& entries = GetEntriesMutable();
|
auto& entries = GetEntriesMutable();
|
||||||
auto itr = entries.find(tableId);
|
auto itr = entries.find(tableId);
|
||||||
if (itr != entries.end()) {
|
if (itr != entries.end()) {
|
||||||
@@ -79,7 +79,7 @@ const LootTableEntries& CDLootTableTable::GetTable(uint32_t tableId) {
|
|||||||
|
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDLootTable entry;
|
CDLootTable entry;
|
||||||
entries[tableId].push_back(ReadRow(tableData));
|
entries[tableId].emplace_back(ReadRow(tableData));
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
SortTable(entries[tableId]);
|
SortTable(entries[tableId]);
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDLootTable {
|
struct CDLootTable {
|
||||||
uint32_t itemid; //!< The LOT of the item
|
uint32_t itemid; //!< The LOT of the item
|
||||||
uint32_t LootTableIndex; //!< The Loot Table Index
|
uint32_t LootTableIndex; //!< The Loot Table Index
|
||||||
@@ -20,6 +22,5 @@ private:
|
|||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
const LootTableEntries& GetTable(uint32_t tableId);
|
const LootTableEntries& GetTable(const uint32_t tableId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionEmail");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDMissionEmail entry;
|
auto& entry = entries.emplace_back();
|
||||||
entry.ID = tableData.getIntField("ID", -1);
|
entry.ID = tableData.getIntField("ID", -1);
|
||||||
entry.messageType = tableData.getIntField("messageType", -1);
|
entry.messageType = tableData.getIntField("messageType", -1);
|
||||||
entry.notificationGroup = tableData.getIntField("notificationGroup", -1);
|
entry.notificationGroup = tableData.getIntField("notificationGroup", -1);
|
||||||
@@ -30,11 +30,8 @@ void CDMissionEmailTable::LoadValuesFromDatabase() {
|
|||||||
entry.locStatus = tableData.getIntField("locStatus", -1);
|
entry.locStatus = tableData.getIntField("locStatus", -1);
|
||||||
entry.gate_version = tableData.getStringField("gate_version", "");
|
entry.gate_version = tableData.getStringField("gate_version", "");
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
//! Queries the table with a custom "where" clause
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDMissionEmail {
|
struct CDMissionEmail {
|
||||||
uint32_t ID;
|
uint32_t ID;
|
||||||
uint32_t messageType;
|
uint32_t messageType;
|
||||||
|
|||||||
@@ -20,18 +20,15 @@ void CDMissionNPCComponentTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionNPCComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDMissionNPCComponent entry;
|
auto& entry = entries.emplace_back();
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.missionID = tableData.getIntField("missionID", -1);
|
entry.missionID = tableData.getIntField("missionID", -1);
|
||||||
entry.offersMission = tableData.getIntField("offersMission", -1) == 1 ? true : false;
|
entry.offersMission = tableData.getIntField("offersMission", -1) == 1 ? true : false;
|
||||||
entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false;
|
entry.acceptsMission = tableData.getIntField("acceptsMission", -1) == 1 ? true : false;
|
||||||
entry.gate_version = tableData.getStringField("gate_version", "");
|
entry.gate_version = tableData.getStringField("gate_version", "");
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Queries the table with a custom "where" clause
|
//! Queries the table with a custom "where" clause
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDMissionNPCComponent {
|
struct CDMissionNPCComponent {
|
||||||
uint32_t id; //!< The ID
|
uint32_t id; //!< The ID
|
||||||
uint32_t missionID; //!< The Mission ID
|
uint32_t missionID; //!< The Mission ID
|
||||||
@@ -17,4 +19,3 @@ public:
|
|||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
std::vector<CDMissionNPCComponent> Query(std::function<bool(CDMissionNPCComponent)> predicate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MissionTasks");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDMissionTasks entry;
|
auto& entry = entries.emplace_back();
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
|
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
|
||||||
entry.taskType = tableData.getIntField("taskType", -1);
|
entry.taskType = tableData.getIntField("taskType", -1);
|
||||||
@@ -35,11 +35,8 @@ void CDMissionTasksTable::LoadValuesFromDatabase() {
|
|||||||
UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false);
|
UNUSED(entry.localize = tableData.getIntField("localize", -1) == 1 ? true : false);
|
||||||
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) {
|
std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMissionTasks)> predicate) {
|
||||||
@@ -51,7 +48,7 @@ std::vector<CDMissionTasks> CDMissionTasksTable::Query(std::function<bool(CDMiss
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(uint32_t missionID) {
|
std::vector<CDMissionTasks*> CDMissionTasksTable::GetByMissionID(const uint32_t missionID) {
|
||||||
std::vector<CDMissionTasks*> tasks;
|
std::vector<CDMissionTasks*> tasks;
|
||||||
|
|
||||||
// TODO: this should not be linear(?) and also shouldnt need to be a pointer
|
// TODO: this should not be linear(?) and also shouldnt need to be a pointer
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDMissionTasks {
|
struct CDMissionTasks {
|
||||||
uint32_t id; //!< The Mission ID that the task belongs to
|
uint32_t id; //!< The Mission ID that the task belongs to
|
||||||
UNUSED(uint32_t locStatus); //!< ???
|
UNUSED(uint32_t locStatus); //!< ???
|
||||||
@@ -25,7 +27,7 @@ public:
|
|||||||
// Queries the table with a custom "where" clause
|
// Queries the table with a custom "where" clause
|
||||||
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
|
std::vector<CDMissionTasks> Query(std::function<bool(CDMissionTasks)> predicate);
|
||||||
|
|
||||||
std::vector<CDMissionTasks*> GetByMissionID(uint32_t missionID);
|
std::vector<CDMissionTasks*> GetByMissionID(const uint32_t missionID);
|
||||||
|
|
||||||
// TODO: Remove this and replace it with a proper lookup function.
|
// TODO: Remove this and replace it with a proper lookup function.
|
||||||
const CDTable::StorageType& GetEntries() const;
|
const CDTable::StorageType& GetEntries() const;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ void CDMissionsTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Missions");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDMissions entry;
|
auto& entry = entries.emplace_back();
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.defined_type = tableData.getStringField("defined_type", "");
|
entry.defined_type = tableData.getStringField("defined_type", "");
|
||||||
entry.defined_subtype = tableData.getStringField("defined_subtype", "");
|
entry.defined_subtype = tableData.getStringField("defined_subtype", "");
|
||||||
@@ -76,7 +76,6 @@ void CDMissionsTable::LoadValuesFromDatabase() {
|
|||||||
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
|
UNUSED(entry.locStatus = tableData.getIntField("locStatus", -1));
|
||||||
entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1);
|
entry.reward_bankinventory = tableData.getIntField("reward_bankinventory", -1);
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
|||||||
@@ -75,4 +75,3 @@ public:
|
|||||||
|
|
||||||
static CDMissions Default;
|
static CDMissions Default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM MovementAIComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDMovementAIComponent entry;
|
auto& entry = entries.emplace_back();
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.MovementType = tableData.getStringField("MovementType", "");
|
entry.MovementType = tableData.getStringField("MovementType", "");
|
||||||
entry.WanderChance = tableData.getFloatField("WanderChance", -1.0f);
|
entry.WanderChance = tableData.getFloatField("WanderChance", -1.0f);
|
||||||
@@ -30,11 +30,8 @@ void CDMovementAIComponentTable::LoadValuesFromDatabase() {
|
|||||||
entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f);
|
entry.WanderRadius = tableData.getFloatField("WanderRadius", -1.0f);
|
||||||
entry.attachedPath = tableData.getStringField("attachedPath", "");
|
entry.attachedPath = tableData.getStringField("attachedPath", "");
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
|
std::vector<CDMovementAIComponent> CDMovementAIComponentTable::Query(std::function<bool(CDMovementAIComponent)> predicate) {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDMovementAIComponent {
|
struct CDMovementAIComponent {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
std::string MovementType;
|
std::string MovementType;
|
||||||
|
|||||||
@@ -20,17 +20,14 @@ void CDObjectSkillsTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM ObjectSkills");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDObjectSkills entry;
|
auto &entry = entries.emplace_back();
|
||||||
entry.objectTemplate = tableData.getIntField("objectTemplate", -1);
|
entry.objectTemplate = tableData.getIntField("objectTemplate", -1);
|
||||||
entry.skillID = tableData.getIntField("skillID", -1);
|
entry.skillID = tableData.getIntField("skillID", -1);
|
||||||
entry.castOnType = tableData.getIntField("castOnType", -1);
|
entry.castOnType = tableData.getIntField("castOnType", -1);
|
||||||
entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1);
|
entry.AICombatWeight = tableData.getIntField("AICombatWeight", -1);
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
|
std::vector<CDObjectSkills> CDObjectSkillsTable::Query(std::function<bool(CDObjectSkills)> predicate) {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDObjectSkills {
|
struct CDObjectSkills {
|
||||||
uint32_t objectTemplate; //!< The LOT of the item
|
uint32_t objectTemplate; //!< The LOT of the item
|
||||||
uint32_t skillID; //!< The Skill ID of the object
|
uint32_t skillID; //!< The Skill ID of the object
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "CDObjectsTable.h"
|
#include "CDObjectsTable.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
CDObjects m_default;
|
CDObjects ObjDefault;
|
||||||
};
|
};
|
||||||
|
|
||||||
void CDObjectsTable::LoadValuesFromDatabase() {
|
void CDObjectsTable::LoadValuesFromDatabase() {
|
||||||
@@ -20,8 +20,10 @@ void CDObjectsTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Objects");
|
||||||
auto& entries = GetEntriesMutable();
|
auto& entries = GetEntriesMutable();
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDObjects entry;
|
const uint32_t lot = tableData.getIntField("id", 0);
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
|
auto& entry = entries[lot];
|
||||||
|
entry.id = lot;
|
||||||
entry.name = tableData.getStringField("name", "");
|
entry.name = tableData.getStringField("name", "");
|
||||||
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
|
UNUSED_COLUMN(entry.placeable = tableData.getIntField("placeable", -1);)
|
||||||
entry.type = tableData.getStringField("type", "");
|
entry.type = tableData.getStringField("type", "");
|
||||||
@@ -36,35 +38,34 @@ void CDObjectsTable::LoadValuesFromDatabase() {
|
|||||||
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
|
UNUSED_COLUMN(entry.gate_version = tableData.getStringField("gate_version", "");)
|
||||||
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
|
UNUSED_COLUMN(entry.HQ_valid = tableData.getIntField("HQ_valid", -1);)
|
||||||
|
|
||||||
entries.insert(std::make_pair(entry.id, entry));
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
ObjDefault.id = 0;
|
||||||
|
|
||||||
m_default.id = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
|
const CDObjects& CDObjectsTable::GetByID(const uint32_t lot) {
|
||||||
auto& entries = GetEntriesMutable();
|
auto& entries = GetEntriesMutable();
|
||||||
const auto& it = entries.find(LOT);
|
const auto& it = entries.find(lot);
|
||||||
if (it != entries.end()) {
|
if (it != entries.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Objects WHERE id = ?;");
|
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();
|
auto tableData = query.execQuery();
|
||||||
if (tableData.eof()) {
|
if (tableData.eof()) {
|
||||||
entries.insert(std::make_pair(LOT, m_default));
|
entries.emplace(lot, ObjDefault);
|
||||||
return m_default;
|
return ObjDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now get the data
|
// Now get the data
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDObjects entry;
|
const uint32_t lot = tableData.getIntField("id", 0);
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
|
auto& entry = entries[lot];
|
||||||
|
entry.id = lot;
|
||||||
entry.name = tableData.getStringField("name", "");
|
entry.name = tableData.getStringField("name", "");
|
||||||
UNUSED(entry.placeable = tableData.getIntField("placeable", -1));
|
UNUSED(entry.placeable = tableData.getIntField("placeable", -1));
|
||||||
entry.type = tableData.getStringField("type", "");
|
entry.type = tableData.getStringField("type", "");
|
||||||
@@ -79,17 +80,15 @@ const CDObjects& CDObjectsTable::GetByID(uint32_t LOT) {
|
|||||||
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
UNUSED(entry.gate_version = tableData.getStringField("gate_version", ""));
|
||||||
UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1));
|
UNUSED(entry.HQ_valid = tableData.getIntField("HQ_valid", -1));
|
||||||
|
|
||||||
entries.insert(std::make_pair(entry.id, entry));
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
|
||||||
const auto& it2 = entries.find(LOT);
|
const auto& it2 = entries.find(lot);
|
||||||
if (it2 != entries.end()) {
|
if (it2 != entries.end()) {
|
||||||
return it2->second;
|
return it2->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_default;
|
return ObjDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDObjects {
|
struct CDObjects {
|
||||||
uint32_t id; //!< The LOT of the object
|
uint32_t id; //!< The LOT of the object
|
||||||
std::string name; //!< The internal name of the object
|
std::string name; //!< The internal name of the object
|
||||||
@@ -24,6 +26,6 @@ class CDObjectsTable : public CDTable<CDObjectsTable, std::map<uint32_t, CDObjec
|
|||||||
public:
|
public:
|
||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
// Gets an entry by ID
|
// Gets an entry by ID
|
||||||
const CDObjects& GetByID(uint32_t LOT);
|
const CDObjects& GetByID(const uint32_t lot);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -19,12 +19,11 @@ void CDPackageComponentTable::LoadValuesFromDatabase() {
|
|||||||
// Now get the data
|
// Now get the data
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PackageComponent");
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDPackageComponent entry;
|
auto& entry = entries.emplace_back();
|
||||||
entry.id = tableData.getIntField("id", -1);
|
entry.id = tableData.getIntField("id", -1);
|
||||||
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
entry.LootMatrixIndex = tableData.getIntField("LootMatrixIndex", -1);
|
||||||
entry.packageType = tableData.getIntField("packageType", -1);
|
entry.packageType = tableData.getIntField("packageType", -1);
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
// Custom Classes
|
// Custom Classes
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
struct CDPackageComponent {
|
struct CDPackageComponent {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t LootMatrixIndex;
|
uint32_t LootMatrixIndex;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ void CDPetComponentTable::LoadValuesFromDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CDPetComponentTable::LoadValuesFromDefaults() {
|
void CDPetComponentTable::LoadValuesFromDefaults() {
|
||||||
GetEntriesMutable().insert(std::make_pair(defaultEntry.id, defaultEntry));
|
GetEntriesMutable().emplace(defaultEntry.id, defaultEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
|
CDPetComponent& CDPetComponentTable::GetByID(const uint32_t componentID) {
|
||||||
|
|||||||
@@ -4,32 +4,31 @@ void CDPhysicsComponentTable::LoadValuesFromDatabase() {
|
|||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM PhysicsComponent");
|
||||||
auto& entries = GetEntriesMutable();
|
auto& entries = GetEntriesMutable();
|
||||||
while (!tableData.eof()) {
|
while (!tableData.eof()) {
|
||||||
CDPhysicsComponent entry;
|
const uint32_t componentID = tableData.getIntField("id", -1);
|
||||||
entry.id = tableData.getIntField("id", -1);
|
|
||||||
|
auto& entry = entries[componentID];
|
||||||
|
entry.id = componentID;
|
||||||
entry.bStatic = tableData.getIntField("static", -1) != 0;
|
entry.bStatic = tableData.getIntField("static", -1) != 0;
|
||||||
entry.physicsAsset = tableData.getStringField("physics_asset", "");
|
entry.physicsAsset = tableData.getStringField("physics_asset", "");
|
||||||
UNUSED(entry->jump = tableData.getIntField("jump", -1) != 0);
|
UNUSED_COLUMN(entry.jump = tableData.getIntField("jump", -1) != 0;)
|
||||||
UNUSED(entry->doublejump = tableData.getIntField("doublejump", -1) != 0);
|
UNUSED_COLUMN(entry.doubleJump = tableData.getIntField("doublejump", -1) != 0;)
|
||||||
entry.speed = tableData.getFloatField("speed", -1);
|
entry.speed = static_cast<float>(tableData.getFloatField("speed", -1));
|
||||||
UNUSED(entry->rotSpeed = tableData.getFloatField("rotSpeed", -1));
|
UNUSED_COLUMN(entry.rotSpeed = tableData.getFloatField("rotSpeed", -1);)
|
||||||
entry.playerHeight = tableData.getFloatField("playerHeight");
|
entry.playerHeight = static_cast<float>(tableData.getFloatField("playerHeight"));
|
||||||
entry.playerRadius = tableData.getFloatField("playerRadius");
|
entry.playerRadius = static_cast<float>(tableData.getFloatField("playerRadius"));
|
||||||
entry.pcShapeType = tableData.getIntField("pcShapeType");
|
entry.pcShapeType = tableData.getIntField("pcShapeType");
|
||||||
entry.collisionGroup = tableData.getIntField("collisionGroup");
|
entry.collisionGroup = tableData.getIntField("collisionGroup");
|
||||||
UNUSED(entry->airSpeed = tableData.getFloatField("airSpeed"));
|
UNUSED_COLUMN(entry.airSpeed = tableData.getFloatField("airSpeed");)
|
||||||
UNUSED(entry->boundaryAsset = tableData.getStringField("boundaryAsset"));
|
UNUSED_COLUMN(entry.boundaryAsset = tableData.getStringField("boundaryAsset");)
|
||||||
UNUSED(entry->jumpAirSpeed = tableData.getFloatField("jumpAirSpeed"));
|
UNUSED_COLUMN(entry.jumpAirSpeed = tableData.getFloatField("jumpAirSpeed");)
|
||||||
UNUSED(entry->friction = tableData.getFloatField("friction"));
|
UNUSED_COLUMN(entry.friction = tableData.getFloatField("friction");)
|
||||||
UNUSED(entry->gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset"));
|
UNUSED_COLUMN(entry.gravityVolumeAsset = tableData.getStringField("gravityVolumeAsset");)
|
||||||
|
|
||||||
entries.insert(std::make_pair(entry.id, entry));
|
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
tableData.finalize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(uint32_t componentID) {
|
CDPhysicsComponent* CDPhysicsComponentTable::GetByID(const uint32_t componentID) {
|
||||||
auto& entries = GetEntriesMutable();
|
auto& entries = GetEntriesMutable();
|
||||||
auto itr = entries.find(componentID);
|
auto itr = entries.find(componentID);
|
||||||
return itr != entries.end() ? &itr->second : nullptr;
|
return itr != entries.end() ? &itr->second : nullptr;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
struct CDPhysicsComponent {
|
struct CDPhysicsComponent {
|
||||||
@@ -7,7 +8,7 @@ struct CDPhysicsComponent {
|
|||||||
bool bStatic;
|
bool bStatic;
|
||||||
std::string physicsAsset;
|
std::string physicsAsset;
|
||||||
UNUSED(bool jump);
|
UNUSED(bool jump);
|
||||||
UNUSED(bool doublejump);
|
UNUSED(bool doubleJump);
|
||||||
float speed;
|
float speed;
|
||||||
UNUSED(float rotSpeed);
|
UNUSED(float rotSpeed);
|
||||||
float playerHeight;
|
float playerHeight;
|
||||||
@@ -26,5 +27,5 @@ public:
|
|||||||
void LoadValuesFromDatabase();
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
static const std::string GetTableName() { return "PhysicsComponent"; };
|
static const std::string GetTableName() { return "PhysicsComponent"; };
|
||||||
CDPhysicsComponent* GetByID(uint32_t componentID);
|
CDPhysicsComponent* GetByID(const uint32_t componentID);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#include "CDTamingBuildPuzzleTable.h"
|
||||||
|
|
||||||
|
void CDTamingBuildPuzzleTable::LoadValuesFromDatabase() {
|
||||||
|
// First, get the size of the table
|
||||||
|
uint32_t size = 0;
|
||||||
|
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM TamingBuildPuzzles");
|
||||||
|
while (!tableSize.eof()) {
|
||||||
|
size = tableSize.getIntField(0, 0);
|
||||||
|
tableSize.nextRow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve the size
|
||||||
|
auto& entries = GetEntriesMutable();
|
||||||
|
entries.reserve(size);
|
||||||
|
|
||||||
|
// Now get the data
|
||||||
|
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM TamingBuildPuzzles");
|
||||||
|
while (!tableData.eof()) {
|
||||||
|
const auto lot = static_cast<LOT>(tableData.getIntField("NPCLot", LOT_NULL));
|
||||||
|
entries.emplace(lot, CDTamingBuildPuzzle{
|
||||||
|
.puzzleModelLot = lot,
|
||||||
|
.validPieces{ tableData.getStringField("ValidPiecesLXF") },
|
||||||
|
.timeLimit = static_cast<float>(tableData.getFloatField("Timelimit", 30.0f)),
|
||||||
|
.numValidPieces = tableData.getIntField("NumValidPieces", 6),
|
||||||
|
.imaginationCost = tableData.getIntField("imagCostPerBuild", 10)
|
||||||
|
});
|
||||||
|
tableData.nextRow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CDTamingBuildPuzzle* CDTamingBuildPuzzleTable::GetByLOT(const LOT lot) const {
|
||||||
|
const auto& entries = GetEntries();
|
||||||
|
const auto itr = entries.find(lot);
|
||||||
|
return itr != entries.cend() ? &itr->second : nullptr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CDTable.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information for the minigame to be completed
|
||||||
|
*/
|
||||||
|
struct CDTamingBuildPuzzle {
|
||||||
|
UNUSED_COLUMN(uint32_t id = 0;)
|
||||||
|
|
||||||
|
// The LOT of the object that is to be created
|
||||||
|
LOT puzzleModelLot = LOT_NULL;
|
||||||
|
|
||||||
|
// The LOT of the NPC
|
||||||
|
UNUSED_COLUMN(LOT npcLot = LOT_NULL;)
|
||||||
|
|
||||||
|
// The .lxfml file that contains the bricks required to build the model
|
||||||
|
std::string validPieces{};
|
||||||
|
|
||||||
|
// The .lxfml file that contains the bricks NOT required to build the model
|
||||||
|
UNUSED_COLUMN(std::string invalidPieces{};)
|
||||||
|
|
||||||
|
// Difficulty value
|
||||||
|
UNUSED_COLUMN(int32_t difficulty = 1;)
|
||||||
|
|
||||||
|
// The time limit to complete the build
|
||||||
|
float timeLimit = 30.0f;
|
||||||
|
|
||||||
|
// The number of pieces required to complete the minigame
|
||||||
|
int32_t numValidPieces = 6;
|
||||||
|
|
||||||
|
// Number of valid pieces
|
||||||
|
UNUSED_COLUMN(int32_t totalNumPieces = 16;)
|
||||||
|
|
||||||
|
// Model name
|
||||||
|
UNUSED_COLUMN(std::string modelName{};)
|
||||||
|
|
||||||
|
// The .lxfml file that contains the full model
|
||||||
|
UNUSED_COLUMN(std::string fullModel{};)
|
||||||
|
|
||||||
|
// The duration of the pet taming minigame
|
||||||
|
UNUSED_COLUMN(float duration = 45.0f;)
|
||||||
|
|
||||||
|
// The imagination cost for the tamer to start the minigame
|
||||||
|
int32_t imaginationCost = 10;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDTamingBuildPuzzleTable : public CDTable<CDTamingBuildPuzzleTable, std::unordered_map<LOT, CDTamingBuildPuzzle>> {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Load values from the CD client database
|
||||||
|
*/
|
||||||
|
void LoadValuesFromDatabase();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pet ability table corresponding to the pet LOT
|
||||||
|
* @returns A pointer to the corresponding table, or nullptr if one cannot be found
|
||||||
|
*/
|
||||||
|
[[nodiscard]]
|
||||||
|
const CDTamingBuildPuzzle* GetByLOT(const LOT lot) const;
|
||||||
|
};
|
||||||
@@ -36,5 +36,8 @@ set(DDATABASE_CDCLIENTDATABASE_CDCLIENTTABLES_SOURCES "CDActivitiesTable.cpp"
|
|||||||
"CDRewardsTable.cpp"
|
"CDRewardsTable.cpp"
|
||||||
"CDScriptComponentTable.cpp"
|
"CDScriptComponentTable.cpp"
|
||||||
"CDSkillBehaviorTable.cpp"
|
"CDSkillBehaviorTable.cpp"
|
||||||
|
"CDTamingBuildPuzzleTable.cpp"
|
||||||
"CDVendorComponentTable.cpp"
|
"CDVendorComponentTable.cpp"
|
||||||
"CDZoneTableTable.cpp" PARENT_SCOPE)
|
"CDZoneTableTable.cpp"
|
||||||
|
"CDDeletionRestrictionsTable.cpp"
|
||||||
|
PARENT_SCOPE)
|
||||||
|
|||||||
@@ -27,12 +27,11 @@ Character::Character(uint32_t id, User* parentUser) {
|
|||||||
m_ID = id;
|
m_ID = id;
|
||||||
m_ParentUser = parentUser;
|
m_ParentUser = parentUser;
|
||||||
m_OurEntity = nullptr;
|
m_OurEntity = nullptr;
|
||||||
m_Doc = nullptr;
|
m_GMLevel = eGameMasterLevel::CIVILIAN;
|
||||||
|
m_PermissionMap = static_cast<ePermissionMap>(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Character::~Character() {
|
Character::~Character() {
|
||||||
if (m_Doc) delete m_Doc;
|
|
||||||
m_Doc = nullptr;
|
|
||||||
m_OurEntity = nullptr;
|
m_OurEntity = nullptr;
|
||||||
m_ParentUser = nullptr;
|
m_ParentUser = nullptr;
|
||||||
}
|
}
|
||||||
@@ -55,8 +54,6 @@ void Character::UpdateInfoFromDatabase() {
|
|||||||
m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused.
|
m_ZoneInstanceID = 0; //These values don't really matter, these are only used on the char select screen and seem unused.
|
||||||
m_ZoneCloneID = 0;
|
m_ZoneCloneID = 0;
|
||||||
|
|
||||||
m_Doc = nullptr;
|
|
||||||
|
|
||||||
//Quickly and dirtly parse the xmlData to get the info we need:
|
//Quickly and dirtly parse the xmlData to get the info we need:
|
||||||
DoQuickXMLDataParse();
|
DoQuickXMLDataParse();
|
||||||
|
|
||||||
@@ -70,18 +67,13 @@ void Character::UpdateInfoFromDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Character::UpdateFromDatabase() {
|
void Character::UpdateFromDatabase() {
|
||||||
if (m_Doc) delete m_Doc;
|
|
||||||
UpdateInfoFromDatabase();
|
UpdateInfoFromDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::DoQuickXMLDataParse() {
|
void Character::DoQuickXMLDataParse() {
|
||||||
if (m_XMLData.size() == 0) return;
|
if (m_XMLData.size() == 0) return;
|
||||||
|
|
||||||
delete m_Doc;
|
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
|
||||||
m_Doc = new tinyxml2::XMLDocument();
|
|
||||||
if (!m_Doc) return;
|
|
||||||
|
|
||||||
if (m_Doc->Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
|
|
||||||
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
|
LOG("Loaded xmlData for character %s (%i)!", m_Name.c_str(), m_ID);
|
||||||
} else {
|
} else {
|
||||||
LOG("Failed to load xmlData!");
|
LOG("Failed to load xmlData!");
|
||||||
@@ -89,7 +81,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf");
|
tinyxml2::XMLElement* mf = m_Doc.FirstChildElement("obj")->FirstChildElement("mf");
|
||||||
if (!mf) {
|
if (!mf) {
|
||||||
LOG("Failed to find mf tag!");
|
LOG("Failed to find mf tag!");
|
||||||
return;
|
return;
|
||||||
@@ -108,7 +100,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
mf->QueryAttribute("ess", &m_Eyes);
|
mf->QueryAttribute("ess", &m_Eyes);
|
||||||
mf->QueryAttribute("ms", &m_Mouth);
|
mf->QueryAttribute("ms", &m_Mouth);
|
||||||
|
|
||||||
tinyxml2::XMLElement* inv = m_Doc->FirstChildElement("obj")->FirstChildElement("inv");
|
tinyxml2::XMLElement* inv = m_Doc.FirstChildElement("obj")->FirstChildElement("inv");
|
||||||
if (!inv) {
|
if (!inv) {
|
||||||
LOG("Char has no inv!");
|
LOG("Char has no inv!");
|
||||||
return;
|
return;
|
||||||
@@ -141,7 +133,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char");
|
tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (character) {
|
if (character) {
|
||||||
character->QueryAttribute("cc", &m_Coins);
|
character->QueryAttribute("cc", &m_Coins);
|
||||||
int32_t gm_level = 0;
|
int32_t gm_level = 0;
|
||||||
@@ -205,7 +197,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
character->QueryAttribute("lzrw", &m_OriginalRotation.w);
|
character->QueryAttribute("lzrw", &m_OriginalRotation.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
|
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
|
||||||
if (flags) {
|
if (flags) {
|
||||||
auto* currentChild = flags->FirstChildElement();
|
auto* currentChild = flags->FirstChildElement();
|
||||||
while (currentChild) {
|
while (currentChild) {
|
||||||
@@ -239,12 +231,10 @@ void Character::SetBuildMode(bool buildMode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Character::SaveXMLToDatabase() {
|
void Character::SaveXMLToDatabase() {
|
||||||
if (!m_Doc) return;
|
|
||||||
|
|
||||||
//For metrics, we'll record the time it took to save:
|
//For metrics, we'll record the time it took to save:
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
|
|
||||||
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char");
|
tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (character) {
|
if (character) {
|
||||||
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
|
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
|
||||||
character->SetAttribute("cc", m_Coins);
|
character->SetAttribute("cc", m_Coins);
|
||||||
@@ -266,11 +256,11 @@ void Character::SaveXMLToDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto emotes = character->FirstChildElement("ue");
|
auto emotes = character->FirstChildElement("ue");
|
||||||
if (!emotes) emotes = m_Doc->NewElement("ue");
|
if (!emotes) emotes = m_Doc.NewElement("ue");
|
||||||
|
|
||||||
emotes->DeleteChildren();
|
emotes->DeleteChildren();
|
||||||
for (int emoteID : m_UnlockedEmotes) {
|
for (int emoteID : m_UnlockedEmotes) {
|
||||||
auto emote = m_Doc->NewElement("e");
|
auto emote = m_Doc.NewElement("e");
|
||||||
emote->SetAttribute("id", emoteID);
|
emote->SetAttribute("id", emoteID);
|
||||||
|
|
||||||
emotes->LinkEndChild(emote);
|
emotes->LinkEndChild(emote);
|
||||||
@@ -280,15 +270,15 @@ void Character::SaveXMLToDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Export our flags:
|
//Export our flags:
|
||||||
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
|
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
|
||||||
if (!flags) {
|
if (!flags) {
|
||||||
flags = m_Doc->NewElement("flag"); //Create a flags tag if we don't have one
|
flags = m_Doc.NewElement("flag"); //Create a flags tag if we don't have one
|
||||||
m_Doc->FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time
|
m_Doc.FirstChildElement("obj")->LinkEndChild(flags); //Link it to the obj tag so we can find next time
|
||||||
}
|
}
|
||||||
|
|
||||||
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
|
flags->DeleteChildren(); //Clear it if we have anything, so that we can fill it up again without dupes
|
||||||
for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) {
|
for (std::pair<uint32_t, uint64_t> flag : m_PlayerFlags) {
|
||||||
auto* f = m_Doc->NewElement("f");
|
auto* f = m_Doc.NewElement("f");
|
||||||
f->SetAttribute("id", flag.first);
|
f->SetAttribute("id", flag.first);
|
||||||
|
|
||||||
//Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute.
|
//Because of the joy that is tinyxml2, it doesn't offer a function to set a uint64 as an attribute.
|
||||||
@@ -301,7 +291,7 @@ void Character::SaveXMLToDatabase() {
|
|||||||
|
|
||||||
// Prevents the news feed from showing up on world transfers
|
// Prevents the news feed from showing up on world transfers
|
||||||
if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) {
|
if (GetPlayerFlag(ePlayerFlag::IS_NEWS_SCREEN_VISIBLE)) {
|
||||||
auto* s = m_Doc->NewElement("s");
|
auto* s = m_Doc.NewElement("s");
|
||||||
s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE);
|
s->SetAttribute("si", ePlayerFlag::IS_NEWS_SCREEN_VISIBLE);
|
||||||
flags->LinkEndChild(s);
|
flags->LinkEndChild(s);
|
||||||
}
|
}
|
||||||
@@ -326,7 +316,7 @@ void Character::SaveXMLToDatabase() {
|
|||||||
|
|
||||||
void Character::SetIsNewLogin() {
|
void Character::SetIsNewLogin() {
|
||||||
// If we dont have a flag element, then we cannot have a s element as a child of flag.
|
// If we dont have a flag element, then we cannot have a s element as a child of flag.
|
||||||
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
|
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
|
||||||
if (!flags) return;
|
if (!flags) return;
|
||||||
|
|
||||||
auto* currentChild = flags->FirstChildElement();
|
auto* currentChild = flags->FirstChildElement();
|
||||||
@@ -344,7 +334,7 @@ void Character::SetIsNewLogin() {
|
|||||||
void Character::WriteToDatabase() {
|
void Character::WriteToDatabase() {
|
||||||
//Dump our xml into m_XMLData:
|
//Dump our xml into m_XMLData:
|
||||||
tinyxml2::XMLPrinter printer(0, true, 0);
|
tinyxml2::XMLPrinter printer(0, true, 0);
|
||||||
m_Doc->Print(&printer);
|
m_Doc.Print(&printer);
|
||||||
|
|
||||||
//Finally, save to db:
|
//Finally, save to db:
|
||||||
Database::Get()->UpdateCharacterXml(m_ID, printer.CStr());
|
Database::Get()->UpdateCharacterXml(m_ID, printer.CStr());
|
||||||
@@ -421,15 +411,15 @@ void Character::SetRetroactiveFlags() {
|
|||||||
|
|
||||||
void Character::SaveXmlRespawnCheckpoints() {
|
void Character::SaveXmlRespawnCheckpoints() {
|
||||||
//Export our respawn points:
|
//Export our respawn points:
|
||||||
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
|
auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
|
||||||
if (!points) {
|
if (!points) {
|
||||||
points = m_Doc->NewElement("res");
|
points = m_Doc.NewElement("res");
|
||||||
m_Doc->FirstChildElement("obj")->LinkEndChild(points);
|
m_Doc.FirstChildElement("obj")->LinkEndChild(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
points->DeleteChildren();
|
points->DeleteChildren();
|
||||||
for (const auto& point : m_WorldRespawnCheckpoints) {
|
for (const auto& point : m_WorldRespawnCheckpoints) {
|
||||||
auto* r = m_Doc->NewElement("r");
|
auto* r = m_Doc.NewElement("r");
|
||||||
r->SetAttribute("w", point.first);
|
r->SetAttribute("w", point.first);
|
||||||
|
|
||||||
r->SetAttribute("x", point.second.x);
|
r->SetAttribute("x", point.second.x);
|
||||||
@@ -443,7 +433,7 @@ void Character::SaveXmlRespawnCheckpoints() {
|
|||||||
void Character::LoadXmlRespawnCheckpoints() {
|
void Character::LoadXmlRespawnCheckpoints() {
|
||||||
m_WorldRespawnCheckpoints.clear();
|
m_WorldRespawnCheckpoints.clear();
|
||||||
|
|
||||||
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
|
auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
|
||||||
if (!points) {
|
if (!points) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public:
|
|||||||
void LoadXmlRespawnCheckpoints();
|
void LoadXmlRespawnCheckpoints();
|
||||||
|
|
||||||
const std::string& GetXMLData() const { return m_XMLData; }
|
const std::string& GetXMLData() const { return m_XMLData; }
|
||||||
tinyxml2::XMLDocument* GetXMLDoc() const { return m_Doc; }
|
const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Out of abundance of safety and clarity of what this saves, this is its own function.
|
* Out of abundance of safety and clarity of what this saves, this is its own function.
|
||||||
@@ -464,22 +464,22 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The ID of this character. First 32 bits of the ObjectID.
|
* The ID of this character. First 32 bits of the ObjectID.
|
||||||
*/
|
*/
|
||||||
uint32_t m_ID;
|
uint32_t m_ID{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 64-bit unique ID used in the game.
|
* The 64-bit unique ID used in the game.
|
||||||
*/
|
*/
|
||||||
LWOOBJID m_ObjectID;
|
LWOOBJID m_ObjectID{ LWOOBJID_EMPTY };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The user that owns this character.
|
* The user that owns this character.
|
||||||
*/
|
*/
|
||||||
User* m_ParentUser;
|
User* m_ParentUser{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the character is in game, this is the entity that it represents, else nullptr.
|
* If the character is in game, this is the entity that it represents, else nullptr.
|
||||||
*/
|
*/
|
||||||
Entity* m_OurEntity;
|
Entity* m_OurEntity{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0-9, the Game Master level of this character.
|
* 0-9, the Game Master level of this character.
|
||||||
@@ -506,17 +506,17 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Whether the custom name of this character is rejected
|
* Whether the custom name of this character is rejected
|
||||||
*/
|
*/
|
||||||
bool m_NameRejected;
|
bool m_NameRejected{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current amount of coins of this character
|
* The current amount of coins of this character
|
||||||
*/
|
*/
|
||||||
int64_t m_Coins;
|
int64_t m_Coins{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the character is building
|
* Whether the character is building
|
||||||
*/
|
*/
|
||||||
bool m_BuildMode;
|
bool m_BuildMode{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The items equipped by the character on world load
|
* The items equipped by the character on world load
|
||||||
@@ -583,7 +583,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The ID of the properties of this character
|
* The ID of the properties of this character
|
||||||
*/
|
*/
|
||||||
uint32_t m_PropertyCloneID;
|
uint32_t m_PropertyCloneID{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The XML data for this character, stored as string
|
* The XML data for this character, stored as string
|
||||||
@@ -613,7 +613,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The last time this character logged in
|
* The last time this character logged in
|
||||||
*/
|
*/
|
||||||
uint64_t m_LastLogin;
|
uint64_t m_LastLogin{};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The gameplay flags this character has (not just true values)
|
* The gameplay flags this character has (not just true values)
|
||||||
@@ -623,7 +623,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The character XML belonging to this character
|
* The character XML belonging to this character
|
||||||
*/
|
*/
|
||||||
tinyxml2::XMLDocument* m_Doc;
|
tinyxml2::XMLDocument m_Doc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title of an announcement this character made (reserved for GMs)
|
* Title of an announcement this character made (reserved for GMs)
|
||||||
|
|||||||
@@ -476,8 +476,7 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
|
||||||
auto* xmlDoc = m_Character ? m_Character->GetXMLDoc() : nullptr;
|
AddComponent<InventoryComponent>();
|
||||||
AddComponent<InventoryComponent>(xmlDoc);
|
|
||||||
}
|
}
|
||||||
// if this component exists, then we initialize it. it's value is always 0
|
// if this component exists, then we initialize it. it's value is always 0
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
|
||||||
@@ -731,15 +730,21 @@ void Entity::Initialize() {
|
|||||||
// if we have a moving platform path, then we need a moving platform component
|
// if we have a moving platform path, then we need a moving platform component
|
||||||
if (path->pathType == PathType::MovingPlatform) {
|
if (path->pathType == PathType::MovingPlatform) {
|
||||||
AddComponent<MovingPlatformComponent>(pathName);
|
AddComponent<MovingPlatformComponent>(pathName);
|
||||||
// else if we are a movement path
|
} else if (path->pathType == PathType::Movement) {
|
||||||
} /*else if (path->pathType == PathType::Movement) {
|
auto movementAIcomponent = GetComponent<MovementAIComponent>();
|
||||||
auto movementAIcomp = GetComponent<MovementAIComponent>();
|
if (movementAIcomponent && combatAiId == 0) {
|
||||||
if (movementAIcomp){
|
movementAIcomponent->SetPath(pathName);
|
||||||
// TODO: set path in existing movementAIComp
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: create movementAIcomp and set path
|
MovementAIInfo moveInfo = MovementAIInfo();
|
||||||
|
moveInfo.movementType = "";
|
||||||
|
moveInfo.wanderChance = 0;
|
||||||
|
moveInfo.wanderRadius = 16;
|
||||||
|
moveInfo.wanderSpeed = 2.5f;
|
||||||
|
moveInfo.wanderDelayMax = 5;
|
||||||
|
moveInfo.wanderDelayMin = 2;
|
||||||
|
AddComponent<MovementAIComponent>(moveInfo);
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
} else {
|
} else {
|
||||||
// else we still need to setup moving platform if it has a moving platform comp but no path
|
// 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);
|
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
|
||||||
@@ -1238,7 +1243,7 @@ void Entity::WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType
|
|||||||
outBitStream.Write0();
|
outBitStream.Write0();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) {
|
void Entity::UpdateXMLDoc(tinyxml2::XMLDocument& doc) {
|
||||||
//This function should only ever be called from within Character, meaning doc should always exist when this is called.
|
//This function should only ever be called from within Character, meaning doc should always exist when this is called.
|
||||||
//Naturally, we don't include any non-player components in this update function.
|
//Naturally, we don't include any non-player components in this update function.
|
||||||
|
|
||||||
@@ -1529,7 +1534,7 @@ void Entity::Kill(Entity* murderer, const eKillType killType) {
|
|||||||
bool waitForDeathAnimation = false;
|
bool waitForDeathAnimation = false;
|
||||||
|
|
||||||
if (destroyableComponent) {
|
if (destroyableComponent) {
|
||||||
waitForDeathAnimation = destroyableComponent->GetDeathBehavior() == 0 && killType != eKillType::SILENT;
|
waitForDeathAnimation = !destroyableComponent->GetIsSmashable() && destroyableComponent->GetDeathBehavior() == 0 && killType != eKillType::SILENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Live waited a hard coded 12 seconds for death animations of type 0 before networking destruction!
|
// Live waited a hard coded 12 seconds for death animations of type 0 before networking destruction!
|
||||||
@@ -1629,10 +1634,8 @@ void Entity::PickupItem(const LWOOBJID& objectID) {
|
|||||||
CDObjectSkillsTable* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
|
CDObjectSkillsTable* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
|
||||||
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
|
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
|
||||||
for (CDObjectSkills skill : skills) {
|
for (CDObjectSkills skill : skills) {
|
||||||
CDSkillBehaviorTable* skillBehTable = CDClientManager::GetTable<CDSkillBehaviorTable>();
|
|
||||||
|
|
||||||
auto* skillComponent = GetComponent<SkillComponent>();
|
auto* skillComponent = GetComponent<SkillComponent>();
|
||||||
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID());
|
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
|
||||||
|
|
||||||
auto* missionComponent = GetComponent<MissionComponent>();
|
auto* missionComponent = GetComponent<MissionComponent>();
|
||||||
|
|
||||||
@@ -1837,6 +1840,12 @@ const NiPoint3& Entity::GetPosition() const {
|
|||||||
return vehicel->GetPosition();
|
return vehicel->GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* rigidBodyPhantomPhysicsComponent = GetComponent<RigidbodyPhantomPhysicsComponent>();
|
||||||
|
|
||||||
|
if (rigidBodyPhantomPhysicsComponent != nullptr) {
|
||||||
|
return rigidBodyPhantomPhysicsComponent->GetPosition();
|
||||||
|
}
|
||||||
|
|
||||||
return NiPoint3Constant::ZERO;
|
return NiPoint3Constant::ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1865,6 +1874,12 @@ const NiQuaternion& Entity::GetRotation() const {
|
|||||||
return vehicel->GetRotation();
|
return vehicel->GetRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* rigidBodyPhantomPhysicsComponent = GetComponent<RigidbodyPhantomPhysicsComponent>();
|
||||||
|
|
||||||
|
if (rigidBodyPhantomPhysicsComponent != nullptr) {
|
||||||
|
return rigidBodyPhantomPhysicsComponent->GetRotation();
|
||||||
|
}
|
||||||
|
|
||||||
return NiQuaternionConstant::IDENTITY;
|
return NiQuaternionConstant::IDENTITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1893,6 +1908,12 @@ void Entity::SetPosition(const NiPoint3& position) {
|
|||||||
vehicel->SetPosition(position);
|
vehicel->SetPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* rigidBodyPhantomPhysicsComponent = GetComponent<RigidbodyPhantomPhysicsComponent>();
|
||||||
|
|
||||||
|
if (rigidBodyPhantomPhysicsComponent != nullptr) {
|
||||||
|
rigidBodyPhantomPhysicsComponent->SetPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(this);
|
Game::entityManager->SerializeEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1921,6 +1942,12 @@ void Entity::SetRotation(const NiQuaternion& rotation) {
|
|||||||
vehicel->SetRotation(rotation);
|
vehicel->SetRotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* rigidBodyPhantomPhysicsComponent = GetComponent<RigidbodyPhantomPhysicsComponent>();
|
||||||
|
|
||||||
|
if (rigidBodyPhantomPhysicsComponent != nullptr) {
|
||||||
|
rigidBodyPhantomPhysicsComponent->SetRotation(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(this);
|
Game::entityManager->SerializeEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ public:
|
|||||||
|
|
||||||
void WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
|
void WriteBaseReplicaData(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
|
||||||
void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
|
void WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType packetType);
|
||||||
void UpdateXMLDoc(tinyxml2::XMLDocument* doc);
|
void UpdateXMLDoc(tinyxml2::XMLDocument& doc);
|
||||||
void Update(float deltaTime);
|
void Update(float deltaTime);
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|||||||
@@ -418,10 +418,16 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::SerializeEntity(Entity* entity) {
|
void EntityManager::SerializeEntity(Entity* entity) {
|
||||||
if (!entity || entity->GetNetworkId() == 0) return;
|
if (!entity) return;
|
||||||
|
|
||||||
|
EntityManager::SerializeEntity(*entity);
|
||||||
|
}
|
||||||
|
|
||||||
if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) {
|
void EntityManager::SerializeEntity(const Entity& entity) {
|
||||||
m_EntitiesToSerialize.push_back(entity->GetObjectID());
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
void ConstructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS, bool skipChecks = false);
|
void ConstructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS, bool skipChecks = false);
|
||||||
void DestructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
void DestructEntity(Entity* entity, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
void SerializeEntity(Entity* entity);
|
void SerializeEntity(Entity* entity);
|
||||||
|
void SerializeEntity(const Entity& entity);
|
||||||
|
|
||||||
void ConstructAllEntities(const SystemAddress& sysAddr);
|
void ConstructAllEntities(const SystemAddress& sysAddr);
|
||||||
void DestructAllEntities(const SystemAddress& sysAddr);
|
void DestructAllEntities(const SystemAddress& sysAddr);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ User::User(const SystemAddress& sysAddr, const std::string& username, const std:
|
|||||||
m_AccountID = 0;
|
m_AccountID = 0;
|
||||||
m_Username = "";
|
m_Username = "";
|
||||||
m_SessionKey = "";
|
m_SessionKey = "";
|
||||||
|
m_MuteExpire = 0;
|
||||||
|
|
||||||
m_MaxGMLevel = eGameMasterLevel::CIVILIAN; //The max GM level this account can assign to it's characters
|
m_MaxGMLevel = eGameMasterLevel::CIVILIAN; //The max GM level this account can assign to it's characters
|
||||||
m_LastCharID = 0;
|
m_LastCharID = 0;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include "eCharacterCreationResponse.h"
|
#include "eCharacterCreationResponse.h"
|
||||||
#include "eRenameResponse.h"
|
#include "eRenameResponse.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "CheatDetection.h"
|
#include "CheatDetection.h"
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ void UserManager::Initialize() {
|
|||||||
auto chatListStream = Game::assetManager->GetFile("chatplus_en_us.txt");
|
auto chatListStream = Game::assetManager->GetFile("chatplus_en_us.txt");
|
||||||
if (!chatListStream) {
|
if (!chatListStream) {
|
||||||
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "chatplus_en_us.txt").string().c_str());
|
LOG("Failed to load %s", (Game::assetManager->GetResPath() / "chatplus_en_us.txt").string().c_str());
|
||||||
throw std::runtime_error("Aborting initialization due to missing chat whitelist file.");
|
throw std::runtime_error("Aborting initialization due to missing chat allowlist file.");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (std::getline(chatListStream, line, '\n')) {
|
while (std::getline(chatListStream, line, '\n')) {
|
||||||
@@ -422,7 +422,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
Database::Get()->DeleteCharacter(charID);
|
Database::Get()->DeleteCharacter(charID);
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
|
||||||
bitStream.Write(objectID);
|
bitStream.Write(objectID);
|
||||||
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||||
|
|
||||||
@@ -536,13 +536,13 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
|
|||||||
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
||||||
try {
|
try {
|
||||||
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
||||||
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ? AND icc.decal == ?"
|
"select obj.id as objectId from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ? AND icc.decal == ?"
|
||||||
);
|
);
|
||||||
stmt.bind(1, "character create shirt");
|
stmt.bind(1, "character create shirt");
|
||||||
stmt.bind(2, static_cast<int>(shirtColor));
|
stmt.bind(2, static_cast<int>(shirtColor));
|
||||||
stmt.bind(3, static_cast<int>(shirtStyle));
|
stmt.bind(3, static_cast<int>(shirtStyle));
|
||||||
auto tableData = stmt.execQuery();
|
auto tableData = stmt.execQuery();
|
||||||
auto shirtLOT = tableData.getIntField(0, 4069);
|
auto shirtLOT = tableData.getIntField("objectId", 4069);
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
return shirtLOT;
|
return shirtLOT;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
@@ -555,12 +555,12 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
|||||||
uint32_t FindCharPantsID(uint32_t pantsColor) {
|
uint32_t FindCharPantsID(uint32_t pantsColor) {
|
||||||
try {
|
try {
|
||||||
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
||||||
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ?"
|
"select obj.id as objectId from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ?"
|
||||||
);
|
);
|
||||||
stmt.bind(1, "cc pants");
|
stmt.bind(1, "cc pants");
|
||||||
stmt.bind(2, static_cast<int>(pantsColor));
|
stmt.bind(2, static_cast<int>(pantsColor));
|
||||||
auto tableData = stmt.execQuery();
|
auto tableData = stmt.execQuery();
|
||||||
auto pantsLOT = tableData.getIntField(0, 2508);
|
auto pantsLOT = tableData.getIntField("objectId", 2508);
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
return pantsLOT;
|
return pantsLOT;
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
|
|||||||
if (healthDamageDealt >= 1) {
|
if (healthDamageDealt >= 1) {
|
||||||
successState = eBasicAttackSuccessTypes::SUCCESS;
|
successState = eBasicAttackSuccessTypes::SUCCESS;
|
||||||
} else if (armorDamageDealt >= 1) {
|
} else if (armorDamageDealt >= 1) {
|
||||||
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
|
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplate::EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bitStream.Write(armorDamageDealt);
|
bitStream.Write(armorDamageDealt);
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "BehaviorTemplates.h"
|
#include "BehaviorTemplate.h"
|
||||||
#include "BehaviorBranchContext.h"
|
#include "BehaviorBranchContext.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -110,176 +110,176 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
|
|||||||
Behavior* behavior = nullptr;
|
Behavior* behavior = nullptr;
|
||||||
|
|
||||||
switch (templateId) {
|
switch (templateId) {
|
||||||
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
|
case BehaviorTemplate::EMPTY: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
|
case BehaviorTemplate::BASIC_ATTACK:
|
||||||
behavior = new BasicAttackBehavior(behaviorId);
|
behavior = new BasicAttackBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_TAC_ARC:
|
case BehaviorTemplate::TAC_ARC:
|
||||||
behavior = new TacArcBehavior(behaviorId);
|
behavior = new TacArcBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_AND:
|
case BehaviorTemplate::AND:
|
||||||
behavior = new AndBehavior(behaviorId);
|
behavior = new AndBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK:
|
case BehaviorTemplate::PROJECTILE_ATTACK:
|
||||||
behavior = new ProjectileAttackBehavior(behaviorId);
|
behavior = new ProjectileAttackBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_HEAL:
|
case BehaviorTemplate::HEAL:
|
||||||
behavior = new HealBehavior(behaviorId);
|
behavior = new HealBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH:
|
case BehaviorTemplate::MOVEMENT_SWITCH:
|
||||||
behavior = new MovementSwitchBehavior(behaviorId);
|
behavior = new MovementSwitchBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT:
|
case BehaviorTemplate::AREA_OF_EFFECT:
|
||||||
behavior = new AreaOfEffectBehavior(behaviorId);
|
behavior = new AreaOfEffectBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT:
|
case BehaviorTemplate::PLAY_EFFECT:
|
||||||
behavior = new PlayEffectBehavior(behaviorId);
|
behavior = new PlayEffectBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_IMMUNITY:
|
case BehaviorTemplate::IMMUNITY:
|
||||||
behavior = new ImmunityBehavior(behaviorId);
|
behavior = new ImmunityBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break;
|
case BehaviorTemplate::DAMAGE_BUFF: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION:
|
case BehaviorTemplate::DAMAGE_ABSORBTION:
|
||||||
behavior = new DamageAbsorptionBehavior(behaviorId);
|
behavior = new DamageAbsorptionBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_OVER_TIME:
|
case BehaviorTemplate::OVER_TIME:
|
||||||
behavior = new OverTimeBehavior(behaviorId);
|
behavior = new OverTimeBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_IMAGINATION:
|
case BehaviorTemplate::IMAGINATION:
|
||||||
behavior = new ImaginationBehavior(behaviorId);
|
behavior = new ImaginationBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER:
|
case BehaviorTemplate::TARGET_CASTER:
|
||||||
behavior = new TargetCasterBehavior(behaviorId);
|
behavior = new TargetCasterBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_STUN:
|
case BehaviorTemplate::STUN:
|
||||||
behavior = new StunBehavior(behaviorId);
|
behavior = new StunBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_DURATION:
|
case BehaviorTemplate::DURATION:
|
||||||
behavior = new DurationBehavior(behaviorId);
|
behavior = new DurationBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_KNOCKBACK:
|
case BehaviorTemplate::KNOCKBACK:
|
||||||
behavior = new KnockbackBehavior(behaviorId);
|
behavior = new KnockbackBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY:
|
case BehaviorTemplate::ATTACK_DELAY:
|
||||||
behavior = new AttackDelayBehavior(behaviorId);
|
behavior = new AttackDelayBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
|
case BehaviorTemplate::CAR_BOOST:
|
||||||
behavior = new CarBoostBehavior(behaviorId);
|
behavior = new CarBoostBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_FALL_SPEED:
|
case BehaviorTemplate::FALL_SPEED:
|
||||||
behavior = new FallSpeedBehavior(behaviorId);
|
behavior = new FallSpeedBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
|
case BehaviorTemplate::SHIELD: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
|
case BehaviorTemplate::REPAIR_ARMOR:
|
||||||
behavior = new RepairBehavior(behaviorId);
|
behavior = new RepairBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SPEED:
|
case BehaviorTemplate::SPEED:
|
||||||
behavior = new SpeedBehavior(behaviorId);
|
behavior = new SpeedBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
|
case BehaviorTemplate::DARK_INSPIRATION:
|
||||||
behavior = new DarkInspirationBehavior(behaviorId);
|
behavior = new DarkInspirationBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
|
case BehaviorTemplate::LOOT_BUFF:
|
||||||
behavior = new LootBuffBehavior(behaviorId);
|
behavior = new LootBuffBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION:
|
case BehaviorTemplate::VENTURE_VISION:
|
||||||
behavior = new VentureVisionBehavior(behaviorId);
|
behavior = new VentureVisionBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT:
|
case BehaviorTemplate::SPAWN_OBJECT:
|
||||||
behavior = new SpawnBehavior(behaviorId);
|
behavior = new SpawnBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break;
|
case BehaviorTemplate::LAY_BRICK: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SWITCH:
|
case BehaviorTemplate::SWITCH:
|
||||||
behavior = new SwitchBehavior(behaviorId);
|
behavior = new SwitchBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_BUFF:
|
case BehaviorTemplate::BUFF:
|
||||||
behavior = new BuffBehavior(behaviorId);
|
behavior = new BuffBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_JETPACK:
|
case BehaviorTemplate::JETPACK:
|
||||||
behavior = new JetPackBehavior(behaviorId);
|
behavior = new JetPackBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
|
case BehaviorTemplate::SKILL_EVENT:
|
||||||
behavior = new SkillEventBehavior(behaviorId);
|
behavior = new SkillEventBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM:
|
case BehaviorTemplate::CONSUME_ITEM:
|
||||||
behavior = new ConsumeItemBehavior(behaviorId);
|
behavior = new ConsumeItemBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
|
case BehaviorTemplate::SKILL_CAST_FAILED:
|
||||||
behavior = new SkillCastFailedBehavior(behaviorId);
|
behavior = new SkillCastFailedBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break;
|
case BehaviorTemplate::IMITATION_SKUNK_STINK: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS:
|
case BehaviorTemplate::CHANGE_IDLE_FLAGS:
|
||||||
behavior = new ChangeIdleFlagsBehavior(behaviorId);
|
behavior = new ChangeIdleFlagsBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF:
|
case BehaviorTemplate::APPLY_BUFF:
|
||||||
behavior = new ApplyBuffBehavior(behaviorId);
|
behavior = new ApplyBuffBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CHAIN:
|
case BehaviorTemplate::CHAIN:
|
||||||
behavior = new ChainBehavior(behaviorId);
|
behavior = new ChainBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION:
|
case BehaviorTemplate::CHANGE_ORIENTATION:
|
||||||
behavior = new ChangeOrientationBehavior(behaviorId);
|
behavior = new ChangeOrientationBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT:
|
case BehaviorTemplate::FORCE_MOVEMENT:
|
||||||
behavior = new ForceMovementBehavior(behaviorId);
|
behavior = new ForceMovementBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_INTERRUPT:
|
case BehaviorTemplate::INTERRUPT:
|
||||||
behavior = new InterruptBehavior(behaviorId);
|
behavior = new InterruptBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break;
|
case BehaviorTemplate::ALTER_COOLDOWN: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CHARGE_UP:
|
case BehaviorTemplate::CHARGE_UP:
|
||||||
behavior = new ChargeUpBehavior(behaviorId);
|
behavior = new ChargeUpBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE:
|
case BehaviorTemplate::SWITCH_MULTIPLE:
|
||||||
behavior = new SwitchMultipleBehavior(behaviorId);
|
behavior = new SwitchMultipleBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_START:
|
case BehaviorTemplate::START:
|
||||||
behavior = new StartBehavior(behaviorId);
|
behavior = new StartBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_END:
|
case BehaviorTemplate::END:
|
||||||
behavior = new EndBehavior(behaviorId);
|
behavior = new EndBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break;
|
case BehaviorTemplate::ALTER_CHAIN_DELAY: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_CAMERA: break;
|
case BehaviorTemplate::CAMERA: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF:
|
case BehaviorTemplate::REMOVE_BUFF:
|
||||||
behavior = new RemoveBuffBehavior(behaviorId);
|
behavior = new RemoveBuffBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_GRAB: break;
|
case BehaviorTemplate::GRAB: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break;
|
case BehaviorTemplate::MODULAR_BUILD: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL:
|
case BehaviorTemplate::NPC_COMBAT_SKILL:
|
||||||
behavior = new NpcCombatSkillBehavior(behaviorId);
|
behavior = new NpcCombatSkillBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_BLOCK:
|
case BehaviorTemplate::BLOCK:
|
||||||
behavior = new BlockBehavior(behaviorId);
|
behavior = new BlockBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_VERIFY:
|
case BehaviorTemplate::VERIFY:
|
||||||
behavior = new VerifyBehavior(behaviorId);
|
behavior = new VerifyBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_TAUNT:
|
case BehaviorTemplate::TAUNT:
|
||||||
behavior = new TauntBehavior(behaviorId);
|
behavior = new TauntBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT:
|
case BehaviorTemplate::AIR_MOVEMENT:
|
||||||
behavior = new AirMovementBehavior(behaviorId);
|
behavior = new AirMovementBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD:
|
case BehaviorTemplate::SPAWN_QUICKBUILD:
|
||||||
behavior = new SpawnBehavior(behaviorId);
|
behavior = new SpawnBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT:
|
case BehaviorTemplate::PULL_TO_POINT:
|
||||||
behavior = new PullToPointBehavior(behaviorId);
|
behavior = new PullToPointBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break;
|
case BehaviorTemplate::PROPERTY_ROTATE: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION:
|
case BehaviorTemplate::DAMAGE_REDUCTION:
|
||||||
behavior = new DamageReductionBehavior(behaviorId);
|
behavior = new DamageReductionBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT:
|
case BehaviorTemplate::PROPERTY_TELEPORT:
|
||||||
behavior = new PropertyTeleportBehavior(behaviorId);
|
behavior = new PropertyTeleportBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET:
|
case BehaviorTemplate::PROPERTY_CLEAR_TARGET:
|
||||||
behavior = new ClearTargetBehavior(behaviorId);
|
behavior = new ClearTargetBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break;
|
case BehaviorTemplate::TAKE_PICTURE: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
|
case BehaviorTemplate::MOUNT: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
|
case BehaviorTemplate::SKILL_SET: break;
|
||||||
default:
|
default:
|
||||||
//LOG("Failed to load behavior with invalid template id (%i)!", templateId);
|
//LOG("Failed to load behavior with invalid template id (%i)!", templateId);
|
||||||
break;
|
break;
|
||||||
@@ -296,19 +296,19 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
|
|||||||
return behavior;
|
return behavior;
|
||||||
}
|
}
|
||||||
|
|
||||||
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
|
BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
|
||||||
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
|
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
|
||||||
|
|
||||||
BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY;
|
BehaviorTemplate templateID = BehaviorTemplate::EMPTY;
|
||||||
// Find behavior template by its behavior id. Default to 0.
|
// Find behavior template by its behavior id. Default to 0.
|
||||||
if (behaviorTemplateTable) {
|
if (behaviorTemplateTable) {
|
||||||
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
|
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
|
||||||
if (templateEntry.behaviorID == behaviorId) {
|
if (templateEntry.behaviorID == behaviorId) {
|
||||||
templateID = static_cast<BehaviorTemplates>(templateEntry.templateID);
|
templateID = static_cast<BehaviorTemplate>(templateEntry.templateID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) {
|
if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) {
|
||||||
LOG("Failed to load behavior template with id (%i)!", behaviorId);
|
LOG("Failed to load behavior template with id (%i)!", behaviorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,26 +335,22 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
|
|||||||
|
|
||||||
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
|
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
|
||||||
|
|
||||||
if (m_effectNames == nullptr) {
|
const auto itr = m_effectNames.find(typeString);
|
||||||
m_effectNames = new std::unordered_map<std::string, std::string>();
|
|
||||||
} else {
|
|
||||||
const auto pair = m_effectNames->find(typeString);
|
|
||||||
|
|
||||||
if (type.empty()) {
|
if (type.empty()) {
|
||||||
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
|
type = GeneralUtils::ASCIIToUTF16(m_effectType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pair != m_effectNames->end()) {
|
if (itr != m_effectNames.end()) {
|
||||||
if (renderComponent == nullptr) {
|
if (renderComponent == nullptr) {
|
||||||
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
|
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true);
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderComponent->PlayEffect(effectId, type, pair->second, secondary);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderComponent->PlayEffect(effectId, type, itr->second, secondary);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The SQlite result object becomes invalid if the query object leaves scope.
|
// The SQlite result object becomes invalid if the query object leaves scope.
|
||||||
@@ -381,19 +377,19 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto name = std::string(result.getStringField(0));
|
const auto name = std::string(result.getStringField("effectName"));
|
||||||
|
|
||||||
if (type.empty()) {
|
if (type.empty()) {
|
||||||
const auto typeResult = result.getStringField(1);
|
const auto typeResult = result.getStringField("effectType");
|
||||||
|
|
||||||
type = GeneralUtils::ASCIIToUTF16(typeResult);
|
type = GeneralUtils::ASCIIToUTF16(typeResult);
|
||||||
|
|
||||||
m_effectType = new std::string(typeResult);
|
m_effectType = typeResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
result.finalize();
|
result.finalize();
|
||||||
|
|
||||||
m_effectNames->insert_or_assign(typeString, name);
|
m_effectNames.insert_or_assign(typeString, name);
|
||||||
|
|
||||||
if (renderComponent == nullptr) {
|
if (renderComponent == nullptr) {
|
||||||
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
|
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
|
||||||
@@ -423,8 +419,7 @@ Behavior::Behavior(const uint32_t behaviorId) {
|
|||||||
|
|
||||||
if (behaviorId == 0) {
|
if (behaviorId == 0) {
|
||||||
this->m_effectId = 0;
|
this->m_effectId = 0;
|
||||||
this->m_effectHandle = nullptr;
|
this->m_templateId = BehaviorTemplate::EMPTY;
|
||||||
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we do not proceed if we are trying to load an invalid behavior
|
// Make sure we do not proceed if we are trying to load an invalid behavior
|
||||||
@@ -432,17 +427,16 @@ Behavior::Behavior(const uint32_t behaviorId) {
|
|||||||
LOG("Failed to load behavior with id (%i)!", behaviorId);
|
LOG("Failed to load behavior with id (%i)!", behaviorId);
|
||||||
|
|
||||||
this->m_effectId = 0;
|
this->m_effectId = 0;
|
||||||
this->m_effectHandle = nullptr;
|
this->m_templateId = BehaviorTemplate::EMPTY;
|
||||||
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID);
|
this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID);
|
||||||
|
|
||||||
this->m_effectId = templateInDatabase.effectID;
|
this->m_effectId = templateInDatabase.effectID;
|
||||||
|
|
||||||
this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
|
this->m_effectHandle = *templateInDatabase.effectHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -507,9 +501,3 @@ void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream,
|
|||||||
|
|
||||||
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Behavior::~Behavior() {
|
|
||||||
delete m_effectNames;
|
|
||||||
delete m_effectType;
|
|
||||||
delete m_effectHandle;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "BitStream.h"
|
#include "BitStream.h"
|
||||||
#include "BehaviorTemplates.h"
|
#include "BehaviorTemplate.h"
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
struct BehaviorContext;
|
struct BehaviorContext;
|
||||||
@@ -26,7 +26,7 @@ public:
|
|||||||
|
|
||||||
static Behavior* CreateBehavior(uint32_t behaviorId);
|
static Behavior* CreateBehavior(uint32_t behaviorId);
|
||||||
|
|
||||||
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId);
|
static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Utilities
|
* Utilities
|
||||||
@@ -39,11 +39,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
uint32_t m_behaviorId;
|
uint32_t m_behaviorId;
|
||||||
BehaviorTemplates m_templateId;
|
BehaviorTemplate m_templateId;
|
||||||
uint32_t m_effectId;
|
uint32_t m_effectId;
|
||||||
std::string* m_effectHandle = nullptr;
|
std::string m_effectHandle;
|
||||||
std::unordered_map<std::string, std::string>* m_effectNames = nullptr;
|
std::unordered_map<std::string, std::string> m_effectNames;
|
||||||
std::string* m_effectType = nullptr;
|
std::string m_effectType;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Behavior parameters
|
* Behavior parameters
|
||||||
@@ -88,5 +88,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
explicit Behavior(uint32_t behaviorId);
|
explicit Behavior(uint32_t behaviorId);
|
||||||
virtual ~Behavior();
|
virtual ~Behavior() = default;
|
||||||
|
|
||||||
|
Behavior(const Behavior& other) = default;
|
||||||
|
Behavior(Behavior&& other) = default;
|
||||||
|
|
||||||
|
Behavior& operator=(const Behavior& other) = default;
|
||||||
|
Behavior& operator=(Behavior&& other) = default;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ void BehaviorContext::ExecuteUpdates() {
|
|||||||
this->scheduledUpdates.clear();
|
this->scheduledUpdates.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bitStream) {
|
bool BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bitStream) {
|
||||||
BehaviorSyncEntry entry;
|
BehaviorSyncEntry entry;
|
||||||
auto found = false;
|
auto found = false;
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
|
|||||||
if (!found) {
|
if (!found) {
|
||||||
LOG("Failed to find behavior sync entry with sync id (%i)!", syncId);
|
LOG("Failed to find behavior sync entry with sync id (%i)!", syncId);
|
||||||
|
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* behavior = entry.behavior;
|
auto* behavior = entry.behavior;
|
||||||
@@ -137,10 +137,11 @@ void BehaviorContext::SyncBehavior(const uint32_t syncId, RakNet::BitStream& bit
|
|||||||
if (behavior == nullptr) {
|
if (behavior == nullptr) {
|
||||||
LOG("Invalid behavior for sync id (%i)!", syncId);
|
LOG("Invalid behavior for sync id (%i)!", syncId);
|
||||||
|
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
behavior->Sync(this, bitStream, branch);
|
behavior->Sync(this, bitStream, branch);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -224,6 +225,16 @@ bool BehaviorContext::CalculateUpdate(const float deltaTime) {
|
|||||||
for (auto i = 0u; i < this->syncEntries.size(); ++i) {
|
for (auto i = 0u; i < this->syncEntries.size(); ++i) {
|
||||||
auto entry = this->syncEntries.at(i);
|
auto entry = this->syncEntries.at(i);
|
||||||
|
|
||||||
|
if (entry.behavior->m_templateId == BehaviorTemplate::ATTACK_DELAY) {
|
||||||
|
auto* self = Game::entityManager->GetEntity(originator);
|
||||||
|
if (self) {
|
||||||
|
auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||||
|
if (destroyableComponent && destroyableComponent->GetHealth() <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.time > 0) {
|
if (entry.time > 0) {
|
||||||
entry.time -= deltaTime;
|
entry.time -= deltaTime;
|
||||||
|
|
||||||
@@ -333,7 +344,7 @@ void BehaviorContext::FilterTargets(std::vector<Entity*>& targets, std::forward_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle targeting the caster
|
// handle targeting the caster
|
||||||
if (candidate == caster){
|
if (candidate == caster) {
|
||||||
// if we aren't targeting self, erase, otherise increment and continue
|
// if we aren't targeting self, erase, otherise increment and continue
|
||||||
if (!targetSelf) index = targets.erase(index);
|
if (!targetSelf) index = targets.erase(index);
|
||||||
else index++;
|
else index++;
|
||||||
@@ -356,24 +367,24 @@ void BehaviorContext::FilterTargets(std::vector<Entity*>& targets, std::forward_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if they are dead, then earse and continue
|
// if they are dead, then earse and continue
|
||||||
if (candidateDestroyableComponent->GetIsDead()){
|
if (candidateDestroyableComponent->GetIsDead()) {
|
||||||
index = targets.erase(index);
|
index = targets.erase(index);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if their faction is explicitly included, increment and continue
|
// if their faction is explicitly included, increment and continue
|
||||||
auto candidateFactions = candidateDestroyableComponent->GetFactionIDs();
|
auto candidateFactions = candidateDestroyableComponent->GetFactionIDs();
|
||||||
if (CheckFactionList(includeFactionList, candidateFactions)){
|
if (CheckFactionList(includeFactionList, candidateFactions)) {
|
||||||
index++;
|
index++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if they are a team member
|
// check if they are a team member
|
||||||
if (targetTeam){
|
if (targetTeam) {
|
||||||
auto* team = TeamManager::Instance()->GetTeam(this->caster);
|
auto* team = TeamManager::Instance()->GetTeam(this->caster);
|
||||||
if (team){
|
if (team) {
|
||||||
// if we find a team member keep it and continue to skip enemy checks
|
// if we find a team member keep it and continue to skip enemy checks
|
||||||
if(std::find(team->members.begin(), team->members.end(), candidate->GetObjectID()) != team->members.end()){
|
if (std::find(team->members.begin(), team->members.end(), candidate->GetObjectID()) != team->members.end()) {
|
||||||
index++;
|
index++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -419,8 +430,8 @@ bool BehaviorContext::CheckTargetingRequirements(const Entity* target) const {
|
|||||||
// returns true if any of the object factions are in the faction list
|
// returns true if any of the object factions are in the faction list
|
||||||
bool BehaviorContext::CheckFactionList(std::forward_list<int32_t>& factionList, std::vector<int32_t>& objectsFactions) const {
|
bool BehaviorContext::CheckFactionList(std::forward_list<int32_t>& factionList, std::vector<int32_t>& objectsFactions) const {
|
||||||
if (factionList.empty() || objectsFactions.empty()) return false;
|
if (factionList.empty() || objectsFactions.empty()) return false;
|
||||||
for (auto faction : factionList){
|
for (auto faction : factionList) {
|
||||||
if(std::find(objectsFactions.begin(), objectsFactions.end(), faction) != objectsFactions.end()) return true;
|
if (std::find(objectsFactions.begin(), objectsFactions.end(), faction) != objectsFactions.end()) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ struct BehaviorContext
|
|||||||
|
|
||||||
void ExecuteUpdates();
|
void ExecuteUpdates();
|
||||||
|
|
||||||
void SyncBehavior(uint32_t syncId, RakNet::BitStream& bitStream);
|
bool SyncBehavior(uint32_t syncId, RakNet::BitStream& bitStream);
|
||||||
|
|
||||||
void Update(float deltaTime);
|
void Update(float deltaTime);
|
||||||
|
|
||||||
|
|||||||
70
dGame/dBehaviors/BehaviorTemplate.h
Normal file
70
dGame/dBehaviors/BehaviorTemplate.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum class BehaviorTemplate : unsigned int {
|
||||||
|
EMPTY, // Not a real behavior, indicates invalid behaviors
|
||||||
|
BASIC_ATTACK,
|
||||||
|
TAC_ARC,
|
||||||
|
AND,
|
||||||
|
PROJECTILE_ATTACK,
|
||||||
|
HEAL,
|
||||||
|
MOVEMENT_SWITCH,
|
||||||
|
AREA_OF_EFFECT,
|
||||||
|
PLAY_EFFECT,
|
||||||
|
IMMUNITY,
|
||||||
|
DAMAGE_BUFF,
|
||||||
|
DAMAGE_ABSORBTION,
|
||||||
|
OVER_TIME,
|
||||||
|
IMAGINATION,
|
||||||
|
TARGET_CASTER,
|
||||||
|
STUN,
|
||||||
|
DURATION,
|
||||||
|
KNOCKBACK,
|
||||||
|
ATTACK_DELAY,
|
||||||
|
CAR_BOOST,
|
||||||
|
FALL_SPEED,
|
||||||
|
SHIELD,
|
||||||
|
REPAIR_ARMOR,
|
||||||
|
SPEED,
|
||||||
|
DARK_INSPIRATION,
|
||||||
|
LOOT_BUFF,
|
||||||
|
VENTURE_VISION,
|
||||||
|
SPAWN_OBJECT,
|
||||||
|
LAY_BRICK,
|
||||||
|
SWITCH,
|
||||||
|
BUFF,
|
||||||
|
JETPACK,
|
||||||
|
SKILL_EVENT,
|
||||||
|
CONSUME_ITEM,
|
||||||
|
SKILL_CAST_FAILED,
|
||||||
|
IMITATION_SKUNK_STINK,
|
||||||
|
CHANGE_IDLE_FLAGS,
|
||||||
|
APPLY_BUFF,
|
||||||
|
CHAIN,
|
||||||
|
CHANGE_ORIENTATION,
|
||||||
|
FORCE_MOVEMENT,
|
||||||
|
INTERRUPT,
|
||||||
|
ALTER_COOLDOWN,
|
||||||
|
CHARGE_UP,
|
||||||
|
SWITCH_MULTIPLE,
|
||||||
|
START,
|
||||||
|
END,
|
||||||
|
ALTER_CHAIN_DELAY,
|
||||||
|
CAMERA,
|
||||||
|
REMOVE_BUFF,
|
||||||
|
GRAB,
|
||||||
|
MODULAR_BUILD,
|
||||||
|
NPC_COMBAT_SKILL,
|
||||||
|
BLOCK,
|
||||||
|
VERIFY,
|
||||||
|
TAUNT,
|
||||||
|
AIR_MOVEMENT,
|
||||||
|
SPAWN_QUICKBUILD,
|
||||||
|
PULL_TO_POINT,
|
||||||
|
PROPERTY_ROTATE,
|
||||||
|
DAMAGE_REDUCTION,
|
||||||
|
PROPERTY_TELEPORT,
|
||||||
|
PROPERTY_CLEAR_TARGET,
|
||||||
|
TAKE_PICTURE,
|
||||||
|
MOUNT,
|
||||||
|
SKILL_SET
|
||||||
|
};
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include "BehaviorTemplates.h"
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
enum class BehaviorTemplates : unsigned int {
|
|
||||||
BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors
|
|
||||||
BEHAVIOR_BASIC_ATTACK,
|
|
||||||
BEHAVIOR_TAC_ARC,
|
|
||||||
BEHAVIOR_AND,
|
|
||||||
BEHAVIOR_PROJECTILE_ATTACK,
|
|
||||||
BEHAVIOR_HEAL,
|
|
||||||
BEHAVIOR_MOVEMENT_SWITCH,
|
|
||||||
BEHAVIOR_AREA_OF_EFFECT,
|
|
||||||
BEHAVIOR_PLAY_EFFECT,
|
|
||||||
BEHAVIOR_IMMUNITY,
|
|
||||||
BEHAVIOR_DAMAGE_BUFF,
|
|
||||||
BEHAVIOR_DAMAGE_ABSORBTION,
|
|
||||||
BEHAVIOR_OVER_TIME,
|
|
||||||
BEHAVIOR_IMAGINATION,
|
|
||||||
BEHAVIOR_TARGET_CASTER,
|
|
||||||
BEHAVIOR_STUN,
|
|
||||||
BEHAVIOR_DURATION,
|
|
||||||
BEHAVIOR_KNOCKBACK,
|
|
||||||
BEHAVIOR_ATTACK_DELAY,
|
|
||||||
BEHAVIOR_CAR_BOOST,
|
|
||||||
BEHAVIOR_FALL_SPEED,
|
|
||||||
BEHAVIOR_SHIELD,
|
|
||||||
BEHAVIOR_REPAIR_ARMOR,
|
|
||||||
BEHAVIOR_SPEED,
|
|
||||||
BEHAVIOR_DARK_INSPIRATION,
|
|
||||||
BEHAVIOR_LOOT_BUFF,
|
|
||||||
BEHAVIOR_VENTURE_VISION,
|
|
||||||
BEHAVIOR_SPAWN_OBJECT,
|
|
||||||
BEHAVIOR_LAY_BRICK,
|
|
||||||
BEHAVIOR_SWITCH,
|
|
||||||
BEHAVIOR_BUFF,
|
|
||||||
BEHAVIOR_JETPACK,
|
|
||||||
BEHAVIOR_SKILL_EVENT,
|
|
||||||
BEHAVIOR_CONSUME_ITEM,
|
|
||||||
BEHAVIOR_SKILL_CAST_FAILED,
|
|
||||||
BEHAVIOR_IMITATION_SKUNK_STINK,
|
|
||||||
BEHAVIOR_CHANGE_IDLE_FLAGS,
|
|
||||||
BEHAVIOR_APPLY_BUFF,
|
|
||||||
BEHAVIOR_CHAIN,
|
|
||||||
BEHAVIOR_CHANGE_ORIENTATION,
|
|
||||||
BEHAVIOR_FORCE_MOVEMENT,
|
|
||||||
BEHAVIOR_INTERRUPT,
|
|
||||||
BEHAVIOR_ALTER_COOLDOWN,
|
|
||||||
BEHAVIOR_CHARGE_UP,
|
|
||||||
BEHAVIOR_SWITCH_MULTIPLE,
|
|
||||||
BEHAVIOR_START,
|
|
||||||
BEHAVIOR_END,
|
|
||||||
BEHAVIOR_ALTER_CHAIN_DELAY,
|
|
||||||
BEHAVIOR_CAMERA,
|
|
||||||
BEHAVIOR_REMOVE_BUFF,
|
|
||||||
BEHAVIOR_GRAB,
|
|
||||||
BEHAVIOR_MODULAR_BUILD,
|
|
||||||
BEHAVIOR_NPC_COMBAT_SKILL,
|
|
||||||
BEHAVIOR_BLOCK,
|
|
||||||
BEHAVIOR_VERIFY,
|
|
||||||
BEHAVIOR_TAUNT,
|
|
||||||
BEHAVIOR_AIR_MOVEMENT,
|
|
||||||
BEHAVIOR_SPAWN_QUICKBUILD,
|
|
||||||
BEHAVIOR_PULL_TO_POINT,
|
|
||||||
BEHAVIOR_PROPERTY_ROTATE,
|
|
||||||
BEHAVIOR_DAMAGE_REDUCTION,
|
|
||||||
BEHAVIOR_PROPERTY_TELEPORT,
|
|
||||||
BEHAVIOR_PROPERTY_CLEAR_TARGET,
|
|
||||||
BEHAVIOR_TAKE_PICTURE,
|
|
||||||
BEHAVIOR_MOUNT,
|
|
||||||
BEHAVIOR_SKILL_SET
|
|
||||||
};
|
|
||||||
@@ -7,7 +7,6 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
|
|||||||
"Behavior.cpp"
|
"Behavior.cpp"
|
||||||
"BehaviorBranchContext.cpp"
|
"BehaviorBranchContext.cpp"
|
||||||
"BehaviorContext.cpp"
|
"BehaviorContext.cpp"
|
||||||
"BehaviorTemplates.cpp"
|
|
||||||
"BlockBehavior.cpp"
|
"BlockBehavior.cpp"
|
||||||
"BuffBehavior.cpp"
|
"BuffBehavior.cpp"
|
||||||
"CarBoostBehavior.cpp"
|
"CarBoostBehavior.cpp"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
|
||||||
void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
|
void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
|
||||||
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
|
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||||
if (this->m_hitAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
|
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,36 +8,50 @@
|
|||||||
|
|
||||||
|
|
||||||
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||||
if (branch.target != context->originator) {
|
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
|
||||||
bool unknown = false;
|
|
||||||
|
|
||||||
if (!bitStream.Read(unknown)) {
|
if (usedTarget != context->originator) {
|
||||||
LOG("Unable to read unknown1 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
bool isTargetImmuneStuns = false;
|
||||||
|
if (!bitStream.Read(isTargetImmuneStuns)) {
|
||||||
|
LOG("Unable to read isTargetImmune from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (unknown) return;
|
if (isTargetImmuneStuns) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->m_interruptBlock) {
|
if (!this->m_interruptBlock) {
|
||||||
bool unknown = false;
|
bool isBlockingInterrupts = false;
|
||||||
|
if (!bitStream.Read(isBlockingInterrupts)) {
|
||||||
if (!bitStream.Read(unknown)) {
|
LOG("Unable to read isBlockingInterrupts from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
||||||
LOG("Unable to read unknown2 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (unknown) return;
|
if (isBlockingInterrupts) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->m_target) // Guess...
|
bool hasInterruptedStatusEffects = false;
|
||||||
{
|
if (!bitStream.Read(hasInterruptedStatusEffects)) {
|
||||||
bool unknown = false;
|
LOG("Unable to read hasInterruptedStatusEffects from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
if (!bitStream.Read(unknown)) {
|
if (hasInterruptedStatusEffects) {
|
||||||
LOG("Unable to read unknown3 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
bool hasMoreInterruptedStatusEffects = false;
|
||||||
return;
|
int32_t loopLimit = 0;
|
||||||
};
|
while (bitStream.Read(hasMoreInterruptedStatusEffects) && hasMoreInterruptedStatusEffects) {
|
||||||
|
int32_t statusEffectID = 0;
|
||||||
|
bitStream.Read(statusEffectID);
|
||||||
|
// nothing happens with this data yes. I have no idea why or what it was used for, but the client literally just reads it and does nothing with it.
|
||||||
|
// 0x004faca4 for a reference. it also has a hard loop limit of 100 soo,
|
||||||
|
loopLimit++;
|
||||||
|
if (loopLimit > 100) {
|
||||||
|
// if this is hit you have a problem
|
||||||
|
LOG("Loop limit reached for interrupted status effects, aborting Handle due to bad bitstream! %i", bitStream.GetNumberOfUnreadBits());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOG_DEBUG("Interrupted status effect ID: %i", statusEffectID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (branch.target == context->originator) return;
|
if (branch.target == context->originator) return;
|
||||||
@@ -55,7 +69,8 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS
|
|||||||
|
|
||||||
|
|
||||||
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||||
if (branch.target != context->originator) {
|
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
|
||||||
|
if (usedTarget != context->originator) {
|
||||||
bitStream.Write(false);
|
bitStream.Write(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
|
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
|
||||||
uint32_t movementType{};
|
uint32_t movementType{};
|
||||||
if (!bitStream.Read(movementType)) {
|
if (!bitStream.Read(movementType)) {
|
||||||
if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
if (this->m_groundAction->m_templateId == BehaviorTemplate::EMPTY &&
|
||||||
this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
this->m_jumpAction->m_templateId == BehaviorTemplate::EMPTY &&
|
||||||
this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
this->m_fallingAction->m_templateId == BehaviorTemplate::EMPTY &&
|
||||||
this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
this->m_doubleJumpAction->m_templateId == BehaviorTemplate::EMPTY &&
|
||||||
this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
this->m_airAction->m_templateId == BehaviorTemplate::EMPTY &&
|
||||||
this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
|
this->m_jetpackAction->m_templateId == BehaviorTemplate::EMPTY &&
|
||||||
this->m_movingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
|
this->m_movingAction->m_templateId == BehaviorTemplate::EMPTY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
||||||
@@ -47,7 +47,7 @@ void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream&
|
|||||||
Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) {
|
Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) {
|
||||||
float actionValue = GetFloat(movementType, -1.0f);
|
float actionValue = GetFloat(movementType, -1.0f);
|
||||||
auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f);
|
auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f);
|
||||||
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
|
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplate::EMPTY) {
|
||||||
loadedBehavior = this->m_groundAction;
|
loadedBehavior = this->m_groundAction;
|
||||||
}
|
}
|
||||||
return loadedBehavior;
|
return loadedBehavior;
|
||||||
|
|||||||
@@ -9,17 +9,16 @@ void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit
|
|||||||
auto* target = Game::entityManager->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
auto* caster = Game::entityManager->GetEntity(context->originator);
|
auto* caster = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
|
||||||
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
|
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||||
SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
|
||||||
auto* target = Game::entityManager->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
auto* caster = Game::entityManager->GetEntity(context->originator);
|
auto* caster = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
|
||||||
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
|
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
#include "BuffComponent.h"
|
#include "BuffComponent.h"
|
||||||
|
|
||||||
void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
|
void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
|
||||||
auto state = true;
|
bool state = true;
|
||||||
|
|
||||||
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
|
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
|
||||||
if (!bitStream.Read(state)) {
|
if (!bitStream.Read(state)) {
|
||||||
LOG("Unable to read state from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
LOG("Unable to read state from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
|
||||||
return;
|
return;
|
||||||
@@ -18,49 +18,59 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
|
|||||||
|
|
||||||
auto* entity = Game::entityManager->GetEntity(context->originator);
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (!entity) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||||
|
|
||||||
if (destroyableComponent == nullptr) {
|
if (destroyableComponent) {
|
||||||
return;
|
if (m_isEnemyFaction) {
|
||||||
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
if (target) state = destroyableComponent->IsEnemy(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
|
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
|
||||||
|
behaviorToCall->Handle(context, bitStream, branch);
|
||||||
if (state) {
|
|
||||||
this->m_actionTrue->Handle(context, bitStream, branch);
|
|
||||||
} else {
|
|
||||||
this->m_actionFalse->Handle(context, bitStream, branch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
|
||||||
auto state = true;
|
bool state = true;
|
||||||
|
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
|
||||||
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
|
|
||||||
auto* entity = Game::entityManager->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
state = entity != nullptr;
|
state = entity != nullptr;
|
||||||
|
|
||||||
if (state && m_targetHasBuff != 0) {
|
if (state) {
|
||||||
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
if (m_targetHasBuff != 0) {
|
||||||
|
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
||||||
|
|
||||||
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
|
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
|
||||||
state = false;
|
state = false;
|
||||||
|
}
|
||||||
|
} else if (m_imagination > 0) {
|
||||||
|
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||||
|
|
||||||
|
if (destroyableComponent && destroyableComponent->GetImagination() < m_imagination) {
|
||||||
|
state = false;
|
||||||
|
}
|
||||||
|
} else if (m_Distance > -1.0f) {
|
||||||
|
auto* originator = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
|
if (originator) {
|
||||||
|
const auto distance = (originator->GetPosition() - entity->GetPosition()).Length();
|
||||||
|
|
||||||
|
state = distance <= m_Distance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitStream.Write(state);
|
bitStream.Write(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state) {
|
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
|
||||||
this->m_actionTrue->Calculate(context, bitStream, branch);
|
behaviorToCall->Calculate(context, bitStream, branch);
|
||||||
} else {
|
|
||||||
this->m_actionFalse->Calculate(context, bitStream, branch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitchBehavior::Load() {
|
void SwitchBehavior::Load() {
|
||||||
@@ -72,5 +82,7 @@ void SwitchBehavior::Load() {
|
|||||||
|
|
||||||
this->m_isEnemyFaction = GetBoolean("isEnemyFaction");
|
this->m_isEnemyFaction = GetBoolean("isEnemyFaction");
|
||||||
|
|
||||||
this->m_targetHasBuff = GetInt("target_has_buff");
|
this->m_targetHasBuff = GetInt("target_has_buff", -1);
|
||||||
|
|
||||||
|
this->m_Distance = GetFloat("distance", -1.0f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ public:
|
|||||||
|
|
||||||
int32_t m_targetHasBuff;
|
int32_t m_targetHasBuff;
|
||||||
|
|
||||||
|
float m_Distance;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inherited
|
* Inherited
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -47,11 +47,11 @@ void SwitchMultipleBehavior::Load() {
|
|||||||
auto result = query.execQuery();
|
auto result = query.execQuery();
|
||||||
|
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
const auto behavior_id = static_cast<uint32_t>(result.getFloatField(1));
|
const auto behavior_id = static_cast<uint32_t>(result.getFloatField("behavior"));
|
||||||
|
|
||||||
auto* behavior = CreateBehavior(behavior_id);
|
auto* behavior = CreateBehavior(behavior_id);
|
||||||
|
|
||||||
auto value = result.getFloatField(2);
|
auto value = result.getFloatField("value");
|
||||||
|
|
||||||
this->m_behaviors.emplace_back(value, behavior);
|
this->m_behaviors.emplace_back(value, behavior);
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,15 @@
|
|||||||
#include "UserManager.h"
|
#include "UserManager.h"
|
||||||
#include "CDMissionsTable.h"
|
#include "CDMissionsTable.h"
|
||||||
|
|
||||||
|
AchievementVendorComponent::AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {
|
||||||
|
RefreshInventory(true);
|
||||||
|
};
|
||||||
|
|
||||||
bool AchievementVendorComponent::SellsItem(Entity* buyer, const LOT lot) {
|
bool AchievementVendorComponent::SellsItem(Entity* buyer, const LOT lot) {
|
||||||
auto* missionComponent = buyer->GetComponent<MissionComponent>();
|
auto* missionComponent = buyer->GetComponent<MissionComponent>();
|
||||||
if (!missionComponent) return false;
|
if (!missionComponent) return false;
|
||||||
|
|
||||||
if (m_PlayerPurchasableItems[buyer->GetObjectID()].contains(lot)){
|
if (m_PlayerPurchasableItems[buyer->GetObjectID()].contains(lot)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +39,7 @@ void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
|
|||||||
int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM);
|
int itemCompID = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::ITEM);
|
||||||
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
CDItemComponent itemComp = itemComponentTable->GetItemComponentByID(itemCompID);
|
||||||
uint32_t costLOT = itemComp.commendationLOT;
|
uint32_t costLOT = itemComp.commendationLOT;
|
||||||
|
|
||||||
if (costLOT == -1 || !SellsItem(buyer, lot)) {
|
if (costLOT == -1 || !SellsItem(buyer, lot)) {
|
||||||
auto* user = UserManager::Instance()->GetUser(buyer->GetSystemAddress());
|
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());
|
CheatDetection::ReportCheat(user, buyer->GetSystemAddress(), "Attempted to buy item %i from achievement vendor %i that is not purchasable", lot, m_Parent->GetLOT());
|
||||||
@@ -44,7 +48,7 @@ void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* inventoryComponent = buyer->GetComponent<InventoryComponent>();
|
auto* inventoryComponent = buyer->GetComponent<InventoryComponent>();
|
||||||
if (!inventoryComponent) {
|
if (!inventoryComponent) {
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_FAIL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -69,4 +73,9 @@ void AchievementVendorComponent::Buy(Entity* buyer, LOT lot, uint32_t count) {
|
|||||||
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
|
inventoryComponent->AddItem(lot, count, eLootSourceType::VENDOR);
|
||||||
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
|
GameMessages::SendVendorTransactionResult(buyer, buyer->GetSystemAddress(), eVendorTransactionResult::PURCHASE_SUCCESS);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AchievementVendorComponent::RefreshInventory(bool isCreation) {
|
||||||
|
SetHasStandardCostItems(true);
|
||||||
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ class Entity;
|
|||||||
class AchievementVendorComponent final : public VendorComponent {
|
class AchievementVendorComponent final : public VendorComponent {
|
||||||
public:
|
public:
|
||||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ACHIEVEMENT_VENDOR;
|
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ACHIEVEMENT_VENDOR;
|
||||||
AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {};
|
AchievementVendorComponent(Entity* parent);
|
||||||
|
|
||||||
|
void RefreshInventory(bool isCreation = false) override;
|
||||||
bool SellsItem(Entity* buyer, const LOT lot);
|
bool SellsItem(Entity* buyer, const LOT lot);
|
||||||
void Buy(Entity* buyer, LOT lot, uint32_t count);
|
void Buy(Entity* buyer, LOT lot, uint32_t count);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "eMissionTaskType.h"
|
#include "eMissionTaskType.h"
|
||||||
#include "eMatchUpdate.h"
|
#include "eMatchUpdate.h"
|
||||||
#include "eConnectionType.h"
|
#include "eConnectionType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
|
|
||||||
#include "CDCurrencyTableTable.h"
|
#include "CDCurrencyTableTable.h"
|
||||||
#include "CDActivityRewardsTable.h"
|
#include "CDActivityRewardsTable.h"
|
||||||
@@ -501,7 +501,7 @@ void ActivityInstance::StartZone() {
|
|||||||
// only make a team if we have more than one participant
|
// only make a team if we have more than one participant
|
||||||
if (participants.size() > 1) {
|
if (participants.size() > 1) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::CREATE_TEAM);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::CREATE_TEAM);
|
||||||
|
|
||||||
bitStream.Write(leader->GetObjectID());
|
bitStream.Write(leader->GetObjectID());
|
||||||
bitStream.Write(m_Participants.size());
|
bitStream.Write(m_Participants.size());
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
|
|
||||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) {
|
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) {
|
||||||
m_Target = LWOOBJID_EMPTY;
|
m_Target = LWOOBJID_EMPTY;
|
||||||
SetAiState(AiState::spawn);
|
m_DirtyStateOrTarget = true;
|
||||||
|
m_State = AiState::spawn;
|
||||||
m_Timer = 1.0f;
|
m_Timer = 1.0f;
|
||||||
m_StartPosition = parent->GetPosition();
|
m_StartPosition = parent->GetPosition();
|
||||||
m_MovementAI = nullptr;
|
m_MovementAI = nullptr;
|
||||||
@@ -45,20 +46,20 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id):
|
|||||||
auto componentResult = componentQuery.execQuery();
|
auto componentResult = componentQuery.execQuery();
|
||||||
|
|
||||||
if (!componentResult.eof()) {
|
if (!componentResult.eof()) {
|
||||||
if (!componentResult.fieldIsNull(0))
|
if (!componentResult.fieldIsNull("aggroRadius"))
|
||||||
m_AggroRadius = componentResult.getFloatField(0);
|
m_AggroRadius = componentResult.getFloatField("aggroRadius");
|
||||||
|
|
||||||
if (!componentResult.fieldIsNull(1))
|
if (!componentResult.fieldIsNull("tetherSpeed"))
|
||||||
m_TetherSpeed = componentResult.getFloatField(1);
|
m_TetherSpeed = componentResult.getFloatField("tetherSpeed");
|
||||||
|
|
||||||
if (!componentResult.fieldIsNull(2))
|
if (!componentResult.fieldIsNull("pursuitSpeed"))
|
||||||
m_PursuitSpeed = componentResult.getFloatField(2);
|
m_PursuitSpeed = componentResult.getFloatField("pursuitSpeed");
|
||||||
|
|
||||||
if (!componentResult.fieldIsNull(3))
|
if (!componentResult.fieldIsNull("softTetherRadius"))
|
||||||
m_SoftTetherRadius = componentResult.getFloatField(3);
|
m_SoftTetherRadius = componentResult.getFloatField("softTetherRadius");
|
||||||
|
|
||||||
if (!componentResult.fieldIsNull(4))
|
if (!componentResult.fieldIsNull("hardTetherRadius"))
|
||||||
m_HardTetherRadius = componentResult.getFloatField(4);
|
m_HardTetherRadius = componentResult.getFloatField("hardTetherRadius");
|
||||||
}
|
}
|
||||||
|
|
||||||
componentResult.finalize();
|
componentResult.finalize();
|
||||||
@@ -82,11 +83,11 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id):
|
|||||||
auto result = skillQuery.execQuery();
|
auto result = skillQuery.execQuery();
|
||||||
|
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
const auto skillId = static_cast<uint32_t>(result.getIntField(0));
|
const auto skillId = static_cast<uint32_t>(result.getIntField("skillID"));
|
||||||
|
|
||||||
const auto abilityCooldown = static_cast<float>(result.getFloatField(1));
|
const auto abilityCooldown = static_cast<float>(result.getFloatField("cooldown"));
|
||||||
|
|
||||||
const auto behaviorId = static_cast<uint32_t>(result.getIntField(2));
|
const auto behaviorId = static_cast<uint32_t>(result.getIntField("behaviorID"));
|
||||||
|
|
||||||
auto* behavior = Behavior::CreateBehavior(behaviorId);
|
auto* behavior = Behavior::CreateBehavior(behaviorId);
|
||||||
|
|
||||||
@@ -150,19 +151,18 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
|||||||
m_dpEntityEnemy->SetPosition(m_Parent->GetPosition());
|
m_dpEntityEnemy->SetPosition(m_Parent->GetPosition());
|
||||||
|
|
||||||
//Process enter events
|
//Process enter events
|
||||||
for (auto en : m_dpEntity->GetNewObjects()) {
|
for (const auto id : m_dpEntity->GetNewObjects()) {
|
||||||
m_Parent->OnCollisionPhantom(en->GetObjectID());
|
m_Parent->OnCollisionPhantom(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Process exit events
|
//Process exit events
|
||||||
for (auto en : m_dpEntity->GetRemovedObjects()) {
|
for (const auto id : m_dpEntity->GetRemovedObjects()) {
|
||||||
m_Parent->OnCollisionLeavePhantom(en->GetObjectID());
|
m_Parent->OnCollisionLeavePhantom(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we should stop the tether effect
|
// Check if we should stop the tether effect
|
||||||
if (m_TetherEffectActive) {
|
if (m_TetherEffectActive) {
|
||||||
m_TetherTime -= deltaTime;
|
m_TetherTime -= deltaTime;
|
||||||
const auto& info = m_MovementAI->GetInfo();
|
|
||||||
if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared(
|
if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared(
|
||||||
m_StartPosition,
|
m_StartPosition,
|
||||||
m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0)
|
m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0)
|
||||||
|
|||||||
@@ -326,9 +326,9 @@ Entity* BuffComponent::GetParent() const {
|
|||||||
return m_Parent;
|
return m_Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
// Load buffs
|
// Load buffs
|
||||||
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
|
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
|
||||||
|
|
||||||
// Make sure we have a clean buff element.
|
// Make sure we have a clean buff element.
|
||||||
auto* buffElement = dest->FirstChildElement("buff");
|
auto* buffElement = dest->FirstChildElement("buff");
|
||||||
@@ -386,15 +386,15 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void BuffComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
// Save buffs
|
// Save buffs
|
||||||
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
|
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
|
||||||
|
|
||||||
// Make sure we have a clean buff element.
|
// Make sure we have a clean buff element.
|
||||||
auto* buffElement = dest->FirstChildElement("buff");
|
auto* buffElement = dest->FirstChildElement("buff");
|
||||||
|
|
||||||
if (buffElement == nullptr) {
|
if (buffElement == nullptr) {
|
||||||
buffElement = doc->NewElement("buff");
|
buffElement = doc.NewElement("buff");
|
||||||
|
|
||||||
dest->LinkEndChild(buffElement);
|
dest->LinkEndChild(buffElement);
|
||||||
} else {
|
} else {
|
||||||
@@ -402,7 +402,7 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [id, buff] : m_Buffs) {
|
for (const auto& [id, buff] : m_Buffs) {
|
||||||
auto* buffEntry = doc->NewElement("b");
|
auto* buffEntry = doc.NewElement("b");
|
||||||
// TODO: change this if to if (buff.cancelOnZone || buff.cancelOnLogout) handling at some point. No current way to differentiate between zone transfer and logout.
|
// TODO: change this if to if (buff.cancelOnZone || buff.cancelOnLogout) handling at some point. No current way to differentiate between zone transfer and logout.
|
||||||
if (buff.cancelOnZone) continue;
|
if (buff.cancelOnZone) continue;
|
||||||
|
|
||||||
@@ -450,7 +450,7 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
|
|||||||
param.value = result.getFloatField("NumberValue");
|
param.value = result.getFloatField("NumberValue");
|
||||||
param.effectId = result.getIntField("EffectID");
|
param.effectId = result.getIntField("EffectID");
|
||||||
|
|
||||||
if (!result.fieldIsNull(3)) {
|
if (!result.fieldIsNull("StringValue")) {
|
||||||
std::istringstream stream(result.getStringField("StringValue"));
|
std::istringstream stream(result.getStringField("StringValue"));
|
||||||
std::string token;
|
std::string token;
|
||||||
|
|
||||||
|
|||||||
@@ -57,9 +57,9 @@ public:
|
|||||||
|
|
||||||
Entity* GetParent() const;
|
Entity* GetParent() const;
|
||||||
|
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
|
|||||||
@@ -186,9 +186,9 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
|
|||||||
m_GMLevel = gmlevel;
|
m_GMLevel = gmlevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
|
|
||||||
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (!character) {
|
if (!character) {
|
||||||
LOG("Failed to find char tag while loading XML!");
|
LOG("Failed to find char tag while loading XML!");
|
||||||
return;
|
return;
|
||||||
@@ -299,8 +299,8 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* minifig = doc->FirstChildElement("obj")->FirstChildElement("mf");
|
tinyxml2::XMLElement* minifig = doc.FirstChildElement("obj")->FirstChildElement("mf");
|
||||||
if (!minifig) {
|
if (!minifig) {
|
||||||
LOG("Failed to find mf tag while updating XML!");
|
LOG("Failed to find mf tag while updating XML!");
|
||||||
return;
|
return;
|
||||||
@@ -320,7 +320,7 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
// done with minifig
|
// done with minifig
|
||||||
|
|
||||||
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (!character) {
|
if (!character) {
|
||||||
LOG("Failed to find char tag while updating XML!");
|
LOG("Failed to find char tag while updating XML!");
|
||||||
return;
|
return;
|
||||||
@@ -338,11 +338,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
// Set the zone statistics of the form <zs><s/> ... <s/></zs>
|
// Set the zone statistics of the form <zs><s/> ... <s/></zs>
|
||||||
auto zoneStatistics = character->FirstChildElement("zs");
|
auto zoneStatistics = character->FirstChildElement("zs");
|
||||||
if (!zoneStatistics) zoneStatistics = doc->NewElement("zs");
|
if (!zoneStatistics) zoneStatistics = doc.NewElement("zs");
|
||||||
zoneStatistics->DeleteChildren();
|
zoneStatistics->DeleteChildren();
|
||||||
|
|
||||||
for (auto pair : m_ZoneStatistics) {
|
for (auto pair : m_ZoneStatistics) {
|
||||||
auto zoneStatistic = doc->NewElement("s");
|
auto zoneStatistic = doc.NewElement("s");
|
||||||
|
|
||||||
zoneStatistic->SetAttribute("map", pair.first);
|
zoneStatistic->SetAttribute("map", pair.first);
|
||||||
zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected);
|
zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected);
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ public:
|
|||||||
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
|
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
|
||||||
~CharacterComponent() override;
|
~CharacterComponent() override;
|
||||||
|
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ void Component::OnUse(Entity* originator) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Component::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void Component::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Component::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void Component::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ public:
|
|||||||
* Save data from this componennt to character XML
|
* Save data from this componennt to character XML
|
||||||
* @param doc the document to write data to
|
* @param doc the document to write data to
|
||||||
*/
|
*/
|
||||||
virtual void UpdateXml(tinyxml2::XMLDocument* doc);
|
virtual void UpdateXml(tinyxml2::XMLDocument& doc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load base data for this component from character XML
|
* Load base data for this component from character XML
|
||||||
* @param doc the document to read data from
|
* @param doc the document to read data from
|
||||||
*/
|
*/
|
||||||
virtual void LoadFromXml(tinyxml2::XMLDocument* doc);
|
virtual void LoadFromXml(const tinyxml2::XMLDocument& doc);
|
||||||
|
|
||||||
virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);
|
virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy
|
|||||||
m_SpeedMultiplier = 1;
|
m_SpeedMultiplier = 1;
|
||||||
m_GravityScale = 1;
|
m_GravityScale = 1;
|
||||||
m_DirtyCheats = false;
|
m_DirtyCheats = false;
|
||||||
m_IgnoreMultipliers = false;
|
|
||||||
|
|
||||||
m_DirtyEquippedItemInfo = true;
|
m_DirtyEquippedItemInfo = true;
|
||||||
m_PickupRadius = 0.0f;
|
m_PickupRadius = 0.0f;
|
||||||
@@ -92,31 +91,31 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
|
|||||||
outBitStream.Write(m_ImmuneToStunInteractCount);
|
outBitStream.Write(m_ImmuneToStunInteractCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_IgnoreMultipliers) m_DirtyCheats = false;
|
outBitStream.Write(m_DirtyCheats || bIsInitialUpdate);
|
||||||
|
if (m_DirtyCheats || bIsInitialUpdate) {
|
||||||
outBitStream.Write(m_DirtyCheats);
|
|
||||||
if (m_DirtyCheats) {
|
|
||||||
outBitStream.Write(m_GravityScale);
|
outBitStream.Write(m_GravityScale);
|
||||||
outBitStream.Write(m_SpeedMultiplier);
|
outBitStream.Write(m_SpeedMultiplier);
|
||||||
|
|
||||||
m_DirtyCheats = false;
|
if (!bIsInitialUpdate) m_DirtyCheats = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream.Write(m_DirtyEquippedItemInfo);
|
outBitStream.Write(m_DirtyEquippedItemInfo || bIsInitialUpdate);
|
||||||
if (m_DirtyEquippedItemInfo) {
|
if (m_DirtyEquippedItemInfo || bIsInitialUpdate) {
|
||||||
outBitStream.Write(m_PickupRadius);
|
outBitStream.Write(m_PickupRadius);
|
||||||
outBitStream.Write(m_InJetpackMode);
|
outBitStream.Write(m_InJetpackMode);
|
||||||
m_DirtyEquippedItemInfo = false;
|
|
||||||
|
if (!bIsInitialUpdate) m_DirtyEquippedItemInfo = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream.Write(m_DirtyBubble);
|
outBitStream.Write(m_DirtyBubble || bIsInitialUpdate);
|
||||||
if (m_DirtyBubble) {
|
if (m_DirtyBubble || bIsInitialUpdate) {
|
||||||
outBitStream.Write(m_IsInBubble);
|
outBitStream.Write(m_IsInBubble);
|
||||||
if (m_IsInBubble) {
|
if (m_IsInBubble) {
|
||||||
outBitStream.Write(m_BubbleType);
|
outBitStream.Write(m_BubbleType);
|
||||||
outBitStream.Write(m_SpecialAnims);
|
outBitStream.Write(m_SpecialAnims);
|
||||||
}
|
}
|
||||||
m_DirtyBubble = false;
|
|
||||||
|
if (!bIsInitialUpdate) m_DirtyBubble = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream.Write(m_DirtyPosition || bIsInitialUpdate);
|
outBitStream.Write(m_DirtyPosition || bIsInitialUpdate);
|
||||||
@@ -149,7 +148,8 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
|
|||||||
outBitStream.Write(m_AngularVelocity.z);
|
outBitStream.Write(m_AngularVelocity.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream.Write0();
|
outBitStream.Write0(); // local_space_info, always zero for now.
|
||||||
|
|
||||||
if (!bIsInitialUpdate) {
|
if (!bIsInitialUpdate) {
|
||||||
m_DirtyPosition = false;
|
m_DirtyPosition = false;
|
||||||
outBitStream.Write(m_IsTeleporting);
|
outBitStream.Write(m_IsTeleporting);
|
||||||
@@ -158,8 +158,8 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void ControllablePhysicsComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (!character) {
|
if (!character) {
|
||||||
LOG("Failed to find char tag!");
|
LOG("Failed to find char tag!");
|
||||||
return;
|
return;
|
||||||
@@ -178,8 +178,8 @@ void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
m_DirtyPosition = true;
|
m_DirtyPosition = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
|
||||||
if (!character) {
|
if (!character) {
|
||||||
LOG("Failed to find char tag while updating XML!");
|
LOG("Failed to find char tag while updating XML!");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ public:
|
|||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the position of this entity, also ensures this update is serialized next tick.
|
* Sets the position of this entity, also ensures this update is serialized next tick.
|
||||||
@@ -174,18 +174,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
const float GetGravityScale() const { return m_GravityScale; }
|
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
|
* Can make an entity static, making it unable to move around
|
||||||
* @param value whether or not the entity is static
|
* @param value whether or not the entity is static
|
||||||
@@ -353,11 +341,6 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool m_DirtyCheats;
|
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
|
* Whether this entity is static, making it unable to move
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -185,8 +185,8 @@ void DestroyableComponent::Update(float deltaTime) {
|
|||||||
m_DamageCooldownTimer -= deltaTime;
|
m_DamageCooldownTimer -= deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void DestroyableComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
|
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
LOG("Failed to find dest tag!");
|
LOG("Failed to find dest tag!");
|
||||||
return;
|
return;
|
||||||
@@ -207,8 +207,8 @@ void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
m_DirtyHealth = true;
|
m_DirtyHealth = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
|
tinyxml2::XMLElement* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
LOG("Failed to find dest tag!");
|
LOG("Failed to find dest tag!");
|
||||||
return;
|
return;
|
||||||
@@ -389,9 +389,9 @@ void DestroyableComponent::AddFaction(const int32_t factionID, const bool ignore
|
|||||||
|
|
||||||
if (result.eof()) return;
|
if (result.eof()) return;
|
||||||
|
|
||||||
if (result.fieldIsNull(0)) return;
|
if (result.fieldIsNull("enemyList")) return;
|
||||||
|
|
||||||
const auto* list_string = result.getStringField(0);
|
const auto* list_string = result.getStringField("enemyList");
|
||||||
|
|
||||||
std::stringstream ss(list_string);
|
std::stringstream ss(list_string);
|
||||||
std::string token;
|
std::string token;
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ public:
|
|||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the component using a different LOT
|
* Initializes the component using a different LOT
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "CDObjectSkillsTable.h"
|
#include "CDObjectSkillsTable.h"
|
||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
|
|
||||||
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) {
|
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
|
||||||
this->m_Dirty = true;
|
this->m_Dirty = true;
|
||||||
this->m_Equipped = {};
|
this->m_Equipped = {};
|
||||||
this->m_Pushed = {};
|
this->m_Pushed = {};
|
||||||
@@ -48,7 +48,8 @@ InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* do
|
|||||||
const auto lot = parent->GetLOT();
|
const auto lot = parent->GetLOT();
|
||||||
|
|
||||||
if (lot == 1) {
|
if (lot == 1) {
|
||||||
LoadXml(document);
|
auto* character = m_Parent->GetCharacter();
|
||||||
|
if (character) LoadXml(character->GetXMLDoc());
|
||||||
|
|
||||||
CheckProxyIntegrity();
|
CheckProxyIntegrity();
|
||||||
|
|
||||||
@@ -472,10 +473,10 @@ bool InventoryComponent::HasSpaceForLoot(const std::unordered_map<LOT, int32_t>&
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
|
void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
|
||||||
LoadPetXml(document);
|
LoadPetXml(document);
|
||||||
|
|
||||||
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv");
|
auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
|
||||||
|
|
||||||
if (inventoryElement == nullptr) {
|
if (inventoryElement == nullptr) {
|
||||||
LOG("Failed to find 'inv' xml element!");
|
LOG("Failed to find 'inv' xml element!");
|
||||||
@@ -557,19 +558,9 @@ void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
|
|||||||
itemElement->QueryAttribute("parent", &parent);
|
itemElement->QueryAttribute("parent", &parent);
|
||||||
// End custom xml
|
// End custom xml
|
||||||
|
|
||||||
std::vector<LDFBaseData*> config;
|
auto* item = new Item(id, lot, inventory, slot, count, bound, {}, parent, subKey);
|
||||||
|
|
||||||
auto* extraInfo = itemElement->FirstChildElement("x");
|
item->LoadConfigXml(*itemElement);
|
||||||
|
|
||||||
if (extraInfo) {
|
|
||||||
std::string modInfo = extraInfo->Attribute("ma");
|
|
||||||
|
|
||||||
LDFBaseData* moduleAssembly = new LDFData<std::u16string>(u"assemblyPartLOTs", GeneralUtils::ASCIIToUTF16(modInfo.substr(2, modInfo.size() - 1)));
|
|
||||||
|
|
||||||
config.push_back(moduleAssembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto* item = new Item(id, lot, inventory, slot, count, bound, config, parent, subKey);
|
|
||||||
|
|
||||||
if (equipped) {
|
if (equipped) {
|
||||||
const auto info = Inventory::FindItemComponent(lot);
|
const auto info = Inventory::FindItemComponent(lot);
|
||||||
@@ -594,10 +585,10 @@ void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
|
||||||
UpdatePetXml(document);
|
UpdatePetXml(document);
|
||||||
|
|
||||||
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv");
|
auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
|
||||||
|
|
||||||
if (inventoryElement == nullptr) {
|
if (inventoryElement == nullptr) {
|
||||||
LOG("Failed to find 'inv' xml element!");
|
LOG("Failed to find 'inv' xml element!");
|
||||||
@@ -631,7 +622,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
|||||||
bags->DeleteChildren();
|
bags->DeleteChildren();
|
||||||
|
|
||||||
for (const auto* inventory : inventoriesToSave) {
|
for (const auto* inventory : inventoriesToSave) {
|
||||||
auto* bag = document->NewElement("b");
|
auto* bag = document.NewElement("b");
|
||||||
|
|
||||||
bag->SetAttribute("t", inventory->GetType());
|
bag->SetAttribute("t", inventory->GetType());
|
||||||
bag->SetAttribute("m", static_cast<unsigned int>(inventory->GetSize()));
|
bag->SetAttribute("m", static_cast<unsigned int>(inventory->GetSize()));
|
||||||
@@ -654,14 +645,14 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* bagElement = document->NewElement("in");
|
auto* bagElement = document.NewElement("in");
|
||||||
|
|
||||||
bagElement->SetAttribute("t", inventory->GetType());
|
bagElement->SetAttribute("t", inventory->GetType());
|
||||||
|
|
||||||
for (const auto& pair : inventory->GetItems()) {
|
for (const auto& pair : inventory->GetItems()) {
|
||||||
auto* item = pair.second;
|
auto* item = pair.second;
|
||||||
|
|
||||||
auto* itemElement = document->NewElement("i");
|
auto* itemElement = document.NewElement("i");
|
||||||
|
|
||||||
itemElement->SetAttribute("l", item->GetLot());
|
itemElement->SetAttribute("l", item->GetLot());
|
||||||
itemElement->SetAttribute("id", item->GetId());
|
itemElement->SetAttribute("id", item->GetId());
|
||||||
@@ -675,17 +666,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
|||||||
itemElement->SetAttribute("parent", item->GetParent());
|
itemElement->SetAttribute("parent", item->GetParent());
|
||||||
// End custom xml
|
// End custom xml
|
||||||
|
|
||||||
for (auto* data : item->GetConfig()) {
|
item->SaveConfigXml(*itemElement);
|
||||||
if (data->GetKey() != u"assemblyPartLOTs") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* extraInfo = document->NewElement("x");
|
|
||||||
|
|
||||||
extraInfo->SetAttribute("ma", data->GetString(false).c_str());
|
|
||||||
|
|
||||||
itemElement->LinkEndChild(extraInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
bagElement->LinkEndChild(itemElement);
|
bagElement->LinkEndChild(itemElement);
|
||||||
}
|
}
|
||||||
@@ -894,8 +875,6 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
|||||||
|
|
||||||
RemoveSlot(item->GetInfo().equipLocation);
|
RemoveSlot(item->GetInfo().equipLocation);
|
||||||
|
|
||||||
PurgeProxies(item);
|
|
||||||
|
|
||||||
UnequipScripts(item);
|
UnequipScripts(item);
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
@@ -905,6 +884,8 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
|||||||
PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
||||||
Game::zoneManager->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
Game::zoneManager->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PurgeProxies(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1093,7 +1074,7 @@ void InventoryComponent::CheckItemSet(const LOT lot) {
|
|||||||
auto result = query.execQuery();
|
auto result = query.execQuery();
|
||||||
|
|
||||||
while (!result.eof()) {
|
while (!result.eof()) {
|
||||||
const auto id = result.getIntField(0);
|
const auto id = result.getIntField("setID");
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
@@ -1524,10 +1505,10 @@ void InventoryComponent::PurgeProxies(Item* item) {
|
|||||||
const auto root = item->GetParent();
|
const auto root = item->GetParent();
|
||||||
|
|
||||||
if (root != LWOOBJID_EMPTY) {
|
if (root != LWOOBJID_EMPTY) {
|
||||||
item = FindItemById(root);
|
Item* itemRoot = FindItemById(root);
|
||||||
|
|
||||||
if (item != nullptr) {
|
if (itemRoot != nullptr) {
|
||||||
UnEquipItem(item);
|
UnEquipItem(itemRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -1542,8 +1523,8 @@ void InventoryComponent::PurgeProxies(Item* item) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) {
|
void InventoryComponent::LoadPetXml(const tinyxml2::XMLDocument& document) {
|
||||||
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet");
|
auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
|
||||||
|
|
||||||
if (petInventoryElement == nullptr) {
|
if (petInventoryElement == nullptr) {
|
||||||
m_Pets.clear();
|
m_Pets.clear();
|
||||||
@@ -1574,19 +1555,19 @@ void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) {
|
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument& document) {
|
||||||
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet");
|
auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
|
||||||
|
|
||||||
if (petInventoryElement == nullptr) {
|
if (petInventoryElement == nullptr) {
|
||||||
petInventoryElement = document->NewElement("pet");
|
petInventoryElement = document.NewElement("pet");
|
||||||
|
|
||||||
document->FirstChildElement("obj")->LinkEndChild(petInventoryElement);
|
document.FirstChildElement("obj")->LinkEndChild(petInventoryElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
petInventoryElement->DeleteChildren();
|
petInventoryElement->DeleteChildren();
|
||||||
|
|
||||||
for (const auto& pet : m_Pets) {
|
for (const auto& pet : m_Pets) {
|
||||||
auto* petElement = document->NewElement("p");
|
auto* petElement = document.NewElement("p");
|
||||||
|
|
||||||
petElement->SetAttribute("id", pet.first);
|
petElement->SetAttribute("id", pet.first);
|
||||||
petElement->SetAttribute("l", pet.second.lot);
|
petElement->SetAttribute("l", pet.second.lot);
|
||||||
@@ -1599,18 +1580,18 @@ void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId){
|
bool InventoryComponent::SetSkill(int32_t slot, uint32_t skillId) {
|
||||||
BehaviorSlot behaviorSlot = BehaviorSlot::Invalid;
|
BehaviorSlot behaviorSlot = BehaviorSlot::Invalid;
|
||||||
if (slot == 1 ) behaviorSlot = BehaviorSlot::Primary;
|
if (slot == 1) behaviorSlot = BehaviorSlot::Primary;
|
||||||
else if (slot == 2 ) behaviorSlot = BehaviorSlot::Offhand;
|
else if (slot == 2) behaviorSlot = BehaviorSlot::Offhand;
|
||||||
else if (slot == 3 ) behaviorSlot = BehaviorSlot::Neck;
|
else if (slot == 3) behaviorSlot = BehaviorSlot::Neck;
|
||||||
else if (slot == 4 ) behaviorSlot = BehaviorSlot::Head;
|
else if (slot == 4) behaviorSlot = BehaviorSlot::Head;
|
||||||
else if (slot == 5 ) behaviorSlot = BehaviorSlot::Consumable;
|
else if (slot == 5) behaviorSlot = BehaviorSlot::Consumable;
|
||||||
else return false;
|
else return false;
|
||||||
return SetSkill(behaviorSlot, skillId);
|
return SetSkill(behaviorSlot, skillId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){
|
bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) {
|
||||||
if (skillId == 0) return false;
|
if (skillId == 0) return false;
|
||||||
const auto index = m_Skills.find(slot);
|
const auto index = m_Skills.find(slot);
|
||||||
if (index != m_Skills.end()) {
|
if (index != m_Skills.end()) {
|
||||||
@@ -1622,4 +1603,3 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId){
|
|||||||
m_Skills.insert_or_assign(slot, skillId);
|
m_Skills.insert_or_assign(slot, skillId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ enum class eItemType : int32_t;
|
|||||||
class InventoryComponent final : public Component {
|
class InventoryComponent final : public Component {
|
||||||
public:
|
public:
|
||||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||||
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
|
InventoryComponent(Entity* parent);
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||||
void LoadXml(tinyxml2::XMLDocument* document);
|
void LoadXml(const tinyxml2::XMLDocument& document);
|
||||||
void UpdateXml(tinyxml2::XMLDocument* document) override;
|
void UpdateXml(tinyxml2::XMLDocument& document) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an inventory of the specified type, if it exists
|
* Returns an inventory of the specified type, if it exists
|
||||||
@@ -470,13 +470,13 @@ private:
|
|||||||
* Saves all the pet information stored in inventory items to the database
|
* Saves all the pet information stored in inventory items to the database
|
||||||
* @param document the xml doc to save to
|
* @param document the xml doc to save to
|
||||||
*/
|
*/
|
||||||
void LoadPetXml(tinyxml2::XMLDocument* document);
|
void LoadPetXml(const tinyxml2::XMLDocument& document);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all the pet information from an xml doc into items
|
* Loads all the pet information from an xml doc into items
|
||||||
* @param document the xml doc to load from
|
* @param document the xml doc to load from
|
||||||
*/
|
*/
|
||||||
void UpdatePetXml(tinyxml2::XMLDocument* document);
|
void UpdatePetXml(tinyxml2::XMLDocument& document);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component
|
|||||||
m_CharacterVersion = eCharacterVersion::LIVE;
|
m_CharacterVersion = eCharacterVersion::LIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl");
|
tinyxml2::XMLElement* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
|
||||||
if (!level) {
|
if (!level) {
|
||||||
LOG("Failed to find lvl tag while updating XML!");
|
LOG("Failed to find lvl tag while updating XML!");
|
||||||
return;
|
return;
|
||||||
@@ -24,8 +24,8 @@ void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion));
|
level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void LevelProgressionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl");
|
auto* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
|
||||||
if (!level) {
|
if (!level) {
|
||||||
LOG("Failed to find lvl tag while loading XML!");
|
LOG("Failed to find lvl tag while loading XML!");
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ public:
|
|||||||
* Save data from this componennt to character XML
|
* Save data from this componennt to character XML
|
||||||
* @param doc the document to write data to
|
* @param doc the document to write data to
|
||||||
*/
|
*/
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load base data for this component from character XML
|
* Load base data for this component from character XML
|
||||||
* @param doc the document to read data from
|
* @param doc the document to read data from
|
||||||
*/
|
*/
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current level of the entity
|
* Gets the current level of the entity
|
||||||
|
|||||||
@@ -466,8 +466,8 @@ bool MissionComponent::RequiresItem(const LOT lot) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!result.fieldIsNull(0)) {
|
if (!result.fieldIsNull("type")) {
|
||||||
const auto type = std::string(result.getStringField(0));
|
const auto type = std::string(result.getStringField("type"));
|
||||||
|
|
||||||
result.finalize();
|
result.finalize();
|
||||||
|
|
||||||
@@ -504,10 +504,8 @@ bool MissionComponent::RequiresItem(const LOT lot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||||
if (doc == nullptr) return;
|
auto* mis = doc.FirstChildElement("obj")->FirstChildElement("mis");
|
||||||
|
|
||||||
auto* mis = doc->FirstChildElement("obj")->FirstChildElement("mis");
|
|
||||||
|
|
||||||
if (mis == nullptr) return;
|
if (mis == nullptr) return;
|
||||||
|
|
||||||
@@ -523,7 +521,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
auto* mission = new Mission(this, missionId);
|
auto* mission = new Mission(this, missionId);
|
||||||
|
|
||||||
mission->LoadFromXml(doneM);
|
mission->LoadFromXml(*doneM);
|
||||||
|
|
||||||
doneM = doneM->NextSiblingElement();
|
doneM = doneM->NextSiblingElement();
|
||||||
|
|
||||||
@@ -540,7 +538,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
auto* mission = new Mission(this, missionId);
|
auto* mission = new Mission(this, missionId);
|
||||||
|
|
||||||
mission->LoadFromXml(currentM);
|
mission->LoadFromXml(*currentM);
|
||||||
|
|
||||||
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
|
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
|
||||||
mission->SetUniqueMissionOrderID(missionOrder);
|
mission->SetUniqueMissionOrderID(missionOrder);
|
||||||
@@ -554,25 +552,23 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||||
if (doc == nullptr) return;
|
|
||||||
|
|
||||||
auto shouldInsertMis = false;
|
auto shouldInsertMis = false;
|
||||||
|
|
||||||
auto* obj = doc->FirstChildElement("obj");
|
auto* obj = doc.FirstChildElement("obj");
|
||||||
|
|
||||||
auto* mis = obj->FirstChildElement("mis");
|
auto* mis = obj->FirstChildElement("mis");
|
||||||
|
|
||||||
if (mis == nullptr) {
|
if (mis == nullptr) {
|
||||||
mis = doc->NewElement("mis");
|
mis = doc.NewElement("mis");
|
||||||
|
|
||||||
shouldInsertMis = true;
|
shouldInsertMis = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
mis->DeleteChildren();
|
mis->DeleteChildren();
|
||||||
|
|
||||||
auto* done = doc->NewElement("done");
|
auto* done = doc.NewElement("done");
|
||||||
auto* cur = doc->NewElement("cur");
|
auto* cur = doc.NewElement("cur");
|
||||||
|
|
||||||
for (const auto& pair : m_Missions) {
|
for (const auto& pair : m_Missions) {
|
||||||
auto* mission = pair.second;
|
auto* mission = pair.second;
|
||||||
@@ -580,10 +576,10 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
if (mission) {
|
if (mission) {
|
||||||
const auto complete = mission->IsComplete();
|
const auto complete = mission->IsComplete();
|
||||||
|
|
||||||
auto* m = doc->NewElement("m");
|
auto* m = doc.NewElement("m");
|
||||||
|
|
||||||
if (complete) {
|
if (complete) {
|
||||||
mission->UpdateXml(m);
|
mission->UpdateXml(*m);
|
||||||
|
|
||||||
done->LinkEndChild(m);
|
done->LinkEndChild(m);
|
||||||
|
|
||||||
@@ -591,7 +587,7 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
}
|
}
|
||||||
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
|
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
|
||||||
|
|
||||||
mission->UpdateXml(m);
|
mission->UpdateXml(*m);
|
||||||
|
|
||||||
cur->LinkEndChild(m);
|
cur->LinkEndChild(m);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ public:
|
|||||||
explicit MissionComponent(Entity* parent);
|
explicit MissionComponent(Entity* parent);
|
||||||
~MissionComponent() override;
|
~MissionComponent() override;
|
||||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
||||||
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
|
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||||
void UpdateXml(tinyxml2::XMLDocument* doc) override;
|
void UpdateXml(tinyxml2::XMLDocument& doc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all the missions for this entity, mapped by mission ID
|
* Returns all the missions for this entity, mapped by mission ID
|
||||||
|
|||||||
@@ -50,9 +50,44 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
|||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
m_MaxSpeed = 0;
|
m_MaxSpeed = 0;
|
||||||
m_LockRotation = false;
|
m_LockRotation = false;
|
||||||
|
m_Path = nullptr;
|
||||||
|
m_SourcePosition = m_Parent->GetPosition();
|
||||||
|
m_Paused = false;
|
||||||
|
m_SavedVelocity = NiPoint3Constant::ZERO;
|
||||||
|
|
||||||
|
if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::SetPath(const std::string pathName) {
|
||||||
|
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
|
||||||
|
if (!pathName.empty()) LOG("WARNING: %s path %s", m_Path ? "Found" : "Failed to find", pathName.c_str());
|
||||||
|
if (!m_Path) return;
|
||||||
|
SetMaxSpeed(1);
|
||||||
|
SetCurrentSpeed(m_BaseSpeed);
|
||||||
|
SetPath(m_Path->pathWaypoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::Pause() {
|
||||||
|
if (m_Paused) return;
|
||||||
|
m_Paused = true;
|
||||||
|
SetPosition(ApproximateLocation());
|
||||||
|
m_SavedVelocity = GetVelocity();
|
||||||
|
SetVelocity(NiPoint3Constant::ZERO);
|
||||||
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MovementAIComponent::Resume() {
|
||||||
|
if (!m_Paused) return;
|
||||||
|
m_Paused = false;
|
||||||
|
SetVelocity(m_SavedVelocity);
|
||||||
|
m_SavedVelocity = NiPoint3Constant::ZERO;
|
||||||
|
SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), m_NextWaypoint));
|
||||||
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::Update(const float deltaTime) {
|
void MovementAIComponent::Update(const float deltaTime) {
|
||||||
|
if (m_Paused) return;
|
||||||
|
|
||||||
if (m_PullingToPoint) {
|
if (m_PullingToPoint) {
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentWaypoint();
|
||||||
|
|
||||||
@@ -81,64 +116,65 @@ void MovementAIComponent::Update(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_TimeTravelled += deltaTime;
|
m_TimeTravelled += deltaTime;
|
||||||
|
|
||||||
|
SetPosition(ApproximateLocation());
|
||||||
|
|
||||||
if (m_TimeTravelled < m_TimeToTravel) return;
|
if (m_TimeTravelled < m_TimeToTravel) return;
|
||||||
m_TimeTravelled = 0.0f;
|
m_TimeTravelled = 0.0f;
|
||||||
|
|
||||||
const auto source = GetCurrentWaypoint();
|
const auto source = GetCurrentWaypoint();
|
||||||
|
|
||||||
SetPosition(source);
|
SetPosition(source);
|
||||||
|
m_SourcePosition = source;
|
||||||
NiPoint3 velocity = NiPoint3Constant::ZERO;
|
|
||||||
|
|
||||||
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
|
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
|
||||||
{
|
{
|
||||||
m_NextWaypoint = GetCurrentWaypoint();
|
m_NextWaypoint = GetCurrentWaypoint();
|
||||||
|
|
||||||
if (m_NextWaypoint == source) {
|
if (m_NextWaypoint == source) {
|
||||||
m_TimeToTravel = 0.0f;
|
m_TimeToTravel = 0.0f;
|
||||||
|
} else {
|
||||||
|
m_CurrentSpeed = std::min(m_CurrentSpeed + m_Acceleration, m_MaxSpeed);
|
||||||
|
|
||||||
goto nextAction;
|
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.0f) {
|
||||||
|
SetVelocity((delta / length) * speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calclute the time it will take to reach the next waypoint with the current speed
|
||||||
|
m_TimeTravelled = 0.0f;
|
||||||
|
m_TimeToTravel = length / speed;
|
||||||
|
|
||||||
|
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_CurrentSpeed < m_MaxSpeed) {
|
|
||||||
m_CurrentSpeed += m_Acceleration;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_CurrentSpeed > m_MaxSpeed) {
|
|
||||||
m_CurrentSpeed = m_MaxSpeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) * speed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calclute the time it will take to reach the next waypoint with the current speed
|
|
||||||
m_TimeTravelled = 0.0f;
|
|
||||||
m_TimeToTravel = length / speed;
|
|
||||||
|
|
||||||
SetRotation(NiQuaternion::LookAt(source, m_NextWaypoint));
|
|
||||||
} else {
|
} else {
|
||||||
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
|
||||||
if (m_CurrentPath.empty()) {
|
if (m_CurrentPath.empty()) {
|
||||||
Stop();
|
if (m_Path) {
|
||||||
|
if (m_Path->pathBehavior == PathBehavior::Loop) {
|
||||||
return;
|
SetPath(m_Path->pathWaypoints);
|
||||||
|
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
|
||||||
|
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
|
||||||
|
std::reverse(waypoints.begin(), waypoints.end());
|
||||||
|
SetPath(waypoints);
|
||||||
|
} else if (m_Path->pathBehavior == PathBehavior::Once) {
|
||||||
|
Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SetDestination(m_CurrentPath.top());
|
SetDestination(m_CurrentPath.top().position);
|
||||||
|
|
||||||
m_CurrentPath.pop();
|
m_CurrentPath.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
nextAction:
|
|
||||||
|
|
||||||
SetVelocity(velocity);
|
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +197,7 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
NiPoint3 MovementAIComponent::ApproximateLocation() const {
|
||||||
auto source = m_Parent->GetPosition();
|
auto source = m_SourcePosition;
|
||||||
|
|
||||||
if (AtFinalWaypoint()) return source;
|
if (AtFinalWaypoint()) return source;
|
||||||
|
|
||||||
@@ -227,13 +263,13 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
|||||||
m_PullPoint = point;
|
m_PullPoint = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
|
void MovementAIComponent::SetPath(std::vector<PathWaypoint> path) {
|
||||||
if (path.empty()) return;
|
if (path.empty()) return;
|
||||||
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) {
|
std::for_each(path.rbegin(), path.rend() - 1, [this](const PathWaypoint& point) {
|
||||||
this->m_CurrentPath.push(point);
|
this->m_CurrentPath.push(point);
|
||||||
});
|
});
|
||||||
|
|
||||||
SetDestination(path.front());
|
SetDestination(path.front().position);
|
||||||
}
|
}
|
||||||
|
|
||||||
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
||||||
@@ -278,6 +314,23 @@ void MovementAIComponent::SetRotation(const NiQuaternion& value) {
|
|||||||
if (!m_LockRotation) m_Parent->SetRotation(value);
|
if (!m_LockRotation) m_Parent->SetRotation(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NiPoint3 MovementAIComponent::GetVelocity() const {
|
||||||
|
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
||||||
|
|
||||||
|
if (controllablePhysicsComponent != nullptr) {
|
||||||
|
return controllablePhysicsComponent->GetVelocity();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
|
||||||
|
|
||||||
|
if (simplePhysicsComponent != nullptr) {
|
||||||
|
return simplePhysicsComponent->GetVelocity();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NiPoint3Constant::ZERO;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
||||||
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
||||||
|
|
||||||
@@ -294,7 +347,7 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
void MovementAIComponent::SetDestination(const NiPoint3 destination) {
|
||||||
if (m_PullingToPoint) return;
|
if (m_PullingToPoint) return;
|
||||||
|
|
||||||
const auto location = ApproximateLocation();
|
const auto location = ApproximateLocation();
|
||||||
@@ -303,6 +356,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
|||||||
SetPosition(location);
|
SetPosition(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_SourcePosition = location;
|
||||||
|
|
||||||
std::vector<NiPoint3> computedPath;
|
std::vector<NiPoint3> computedPath;
|
||||||
if (dpWorld::IsLoaded()) {
|
if (dpWorld::IsLoaded()) {
|
||||||
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
|
||||||
@@ -319,8 +374,7 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
|
|||||||
auto step = delta / 10.0f;
|
auto step = delta / 10.0f;
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
// TODO: Replace this with += when the NiPoint3::operator+= is fixed
|
start += step;
|
||||||
start = start + step;
|
|
||||||
|
|
||||||
computedPath.push_back(start);
|
computedPath.push_back(start);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,14 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
#include "Zone.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class ControllablePhysicsComponent;
|
class ControllablePhysicsComponent;
|
||||||
class BaseCombatAIComponent;
|
class BaseCombatAIComponent;
|
||||||
|
|
||||||
|
struct Path;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information that describes the different variables used to make an entity move around
|
* Information that describes the different variables used to make an entity move around
|
||||||
*/
|
*/
|
||||||
@@ -61,6 +64,8 @@ public:
|
|||||||
|
|
||||||
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
||||||
|
|
||||||
|
void SetPath(const std::string pathName);
|
||||||
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,7 +78,7 @@ public:
|
|||||||
* Set a destination point for the entity to move towards
|
* Set a destination point for the entity to move towards
|
||||||
* @param value the destination point to move towards
|
* @param value the destination point to move towards
|
||||||
*/
|
*/
|
||||||
void SetDestination(const NiPoint3& value);
|
void SetDestination(const NiPoint3 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current rotation this entity is moving towards
|
* Returns the current rotation this entity is moving towards
|
||||||
@@ -189,7 +194,13 @@ public:
|
|||||||
* Sets a path to follow for the AI
|
* Sets a path to follow for the AI
|
||||||
* @param path the path to follow
|
* @param path the path to follow
|
||||||
*/
|
*/
|
||||||
void SetPath(std::vector<NiPoint3> path);
|
void SetPath(std::vector<PathWaypoint> path);
|
||||||
|
|
||||||
|
void Pause();
|
||||||
|
|
||||||
|
void Resume();
|
||||||
|
|
||||||
|
NiPoint3 GetVelocity() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the base speed from the DB for a given LOT
|
* Returns the base speed from the DB for a given LOT
|
||||||
@@ -301,7 +312,15 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The path from the current position to the destination.
|
* The path from the current position to the destination.
|
||||||
*/
|
*/
|
||||||
std::stack<NiPoint3> m_CurrentPath;
|
std::stack<PathWaypoint> m_CurrentPath;
|
||||||
|
|
||||||
|
const Path* m_Path = nullptr;
|
||||||
|
|
||||||
|
NiPoint3 m_SourcePosition;
|
||||||
|
|
||||||
|
bool m_Paused;
|
||||||
|
|
||||||
|
NiPoint3 m_SavedVelocity;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MOVEMENTAICOMPONENT_H
|
#endif // MOVEMENTAICOMPONENT_H
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user