Compare commits

..

35 Commits

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

View File

@@ -1,12 +1,9 @@
cmake_minimum_required(VERSION 3.25)
cmake_minimum_required(VERSION 3.18)
project(Darkflame)
include(CTest)
set(CMAKE_CXX_STANDARD 20)
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")
# Read variables from file
@@ -73,8 +70,7 @@ if(UNIX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2 -fPIC")
elseif(MSVC)
# Skip warning for invalid conversion from size_t to uint32_t for all targets below for now
# Also disable non-portable MSVC volatile behavior
add_compile_options("/wd4267" "/utf-8" "/volatile:iso")
add_compile_options("/wd4267" "/utf-8")
elseif(WIN32)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
endif()
@@ -104,7 +100,7 @@ make_directory(${CMAKE_BINARY_DIR}/resServer)
make_directory(${CMAKE_BINARY_DIR}/logs)
# Copy resource files on first build
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blocklist.dcf")
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
message(STATUS "Checking resource file integrity")
include(Utils)
@@ -215,29 +211,29 @@ if (APPLE)
endif()
# Load all of our third party directories
add_subdirectory(thirdparty SYSTEM)
add_subdirectory(thirdparty)
# Create our list of include directories
include_directories(
set(INCLUDED_DIRECTORIES
"dPhysics"
"dNavigation"
"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/dCommonTests"
"tests/dGameTests"
"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)
@@ -246,9 +242,14 @@ if(APPLE)
include_directories("/usr/local/include/")
endif()
# Actually include the directories from our list
foreach(dir ${INCLUDED_DIRECTORIES})
include_directories(${PROJECT_SOURCE_DIR}/${dir})
endforeach()
# Add linking directories:
if (UNIX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast -Werror") # Warning flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif()
file(
GLOB HEADERS_DZONEMANAGER

View File

@@ -51,7 +51,7 @@ git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
### 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.
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.25**</font> or later!).
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.18**</font> or later!).
### MacOS packages
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
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.
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.
You can check your CMake version by using the following command in a terminal.
```bash
cmake --version

View File

@@ -141,6 +141,6 @@ elseif(APPLE)
endif()
# Add directories to include lists
target_include_directories(MariaDB::ConnCpp SYSTEM INTERFACE ${MARIADB_INCLUDE_DIR})
target_include_directories(MariaDB::ConnCpp INTERFACE ${MARIADB_INCLUDE_DIR})
set(MariaDB_FOUND TRUE)

View File

@@ -27,8 +27,8 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) {
ExportWordlistToDCF(filepath + ".dcf", true);
}
if (BinaryIO::DoesFileExist("blocklist.dcf")) {
ReadWordlistDCF("blocklist.dcf", false);
if (BinaryIO::DoesFileExist("blacklist.dcf")) {
ReadWordlistDCF("blacklist.dcf", false);
}
//Read player names that are ok as well:
@@ -44,20 +44,20 @@ dChatFilter::~dChatFilter() {
m_DeniedWords.clear();
}
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool allowList) {
void dChatFilter::ReadWordlistPlaintext(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath);
if (file) {
std::string line;
while (std::getline(file, line)) {
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase
if (allowList) m_ApprovedWords.push_back(CalculateHash(line));
if (whiteList) m_ApprovedWords.push_back(CalculateHash(line));
else m_DeniedWords.push_back(CalculateHash(line));
}
}
}
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool whiteList) {
std::ifstream file(filepath, std::ios::binary);
if (file) {
fileHeader hdr;
@@ -70,13 +70,13 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
if (hdr.formatVersion == formatVersion) {
size_t wordsToRead = 0;
BinaryIO::BinaryRead(file, wordsToRead);
if (allowList) m_ApprovedWords.reserve(wordsToRead);
if (whiteList) m_ApprovedWords.reserve(wordsToRead);
else m_DeniedWords.reserve(wordsToRead);
size_t word = 0;
for (size_t i = 0; i < wordsToRead; ++i) {
BinaryIO::BinaryRead(file, word);
if (allowList) m_ApprovedWords.push_back(word);
if (whiteList) m_ApprovedWords.push_back(word);
else m_DeniedWords.push_back(word);
}
@@ -90,14 +90,14 @@ bool dChatFilter::ReadWordlistDCF(const std::string& filepath, bool allowList) {
return false;
}
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowList) {
void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool whiteList) {
std::ofstream file(filepath, std::ios::binary | std::ios_base::out);
if (file) {
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header));
BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion));
BinaryIO::BinaryWrite(file, size_t(allowList ? m_ApprovedWords.size() : m_DeniedWords.size()));
BinaryIO::BinaryWrite(file, size_t(whiteList ? m_ApprovedWords.size() : m_DeniedWords.size()));
for (size_t word : allowList ? m_ApprovedWords : m_DeniedWords) {
for (size_t word : whiteList ? m_ApprovedWords : m_DeniedWords) {
BinaryIO::BinaryWrite(file, word);
}
@@ -105,10 +105,10 @@ void dChatFilter::ExportWordlistToDCF(const std::string& filepath, bool allowLis
}
}
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList) {
std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList) {
if (gmLevel > eGameMasterLevel::FORUM_MODERATOR) return { }; //If anything but a forum mod, return true.
if (message.empty()) return { };
if (!allowList && m_DeniedWords.empty()) return { { 0, message.length() } };
if (!whiteList && m_DeniedWords.empty()) return { { 0, message.length() } };
std::stringstream sMessage(message);
std::string segment;
@@ -126,16 +126,16 @@ std::vector<std::pair<uint8_t, uint8_t>> dChatFilter::IsSentenceOkay(const std::
size_t hash = CalculateHash(segment);
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && allowList) {
if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end() && whiteList) {
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && allowList) {
if (std::find(m_ApprovedWords.begin(), m_ApprovedWords.end(), hash) == m_ApprovedWords.end() && whiteList) {
m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.emplace_back(position, originalSegment.length());
}
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !allowList) {
if (std::find(m_DeniedWords.begin(), m_DeniedWords.end(), hash) != m_DeniedWords.end() && !whiteList) {
m_UserUnapprovedWordCache.push_back(hash);
listOfBadSegments.emplace_back(position, originalSegment.length());
}

View File

@@ -21,10 +21,10 @@ public:
dChatFilter(const std::string& filepath, bool dontGenerateDCF);
~dChatFilter();
void ReadWordlistPlaintext(const std::string& filepath, bool allowList);
bool ReadWordlistDCF(const std::string& filepath, bool allowList);
void ExportWordlistToDCF(const std::string& filepath, bool allowList);
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool allowList = true);
void ReadWordlistPlaintext(const std::string& filepath, bool whiteList);
bool ReadWordlistDCF(const std::string& filepath, bool whiteList);
void ExportWordlistToDCF(const std::string& filepath, bool whiteList);
std::vector<std::pair<uint8_t, uint8_t>> IsSentenceOkay(const std::string& message, eGameMasterLevel gmLevel, bool whiteList = true);
private:
bool m_DontGenerateDCF;

View File

@@ -1,6 +1,6 @@
#include "ChatIgnoreList.h"
#include "PlayerContainer.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "BitStreamUtils.h"
#include "Game.h"
#include "Logger.h"
@@ -13,7 +13,7 @@
// 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) {
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receivingPlayer);
//portion that will get routed:

View File

@@ -14,6 +14,7 @@
#include "eObjectBits.h"
#include "eConnectionType.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eClientMessageType.h"
#include "eGameMessageType.h"
#include "StringifiedEnum.h"
@@ -59,7 +60,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Now, we need to send the friendlist to the server they came from:
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(playerID);
//portion that will get routed:
@@ -453,7 +454,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) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(routeTo.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
@@ -695,7 +696,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -710,7 +711,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) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -737,7 +738,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) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -762,7 +763,7 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -779,7 +780,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) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -808,7 +809,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) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -834,7 +835,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bD
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -868,7 +869,7 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
[bool] - is FTP*/
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(friendData.playerID);
//portion that will get routed:
@@ -905,7 +906,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
}
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:
@@ -919,7 +920,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) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
// Portion that will get routed:
@@ -942,7 +943,7 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver.playerID);
//portion that will get routed:

View File

@@ -17,6 +17,7 @@
#include "PlayerContainer.h"
#include "ChatPacketHandler.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h"
#include "ChatIgnoreList.h"
#include "StringifiedEnum.h"
@@ -181,29 +182,47 @@ int main(int argc, char** argv) {
void HandlePacket(Packet* packet) {
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.");
} 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.");
} else if (packet->length < 4 || packet->data[0] != ID_USER_PACKET_ENUM) return; // Nothing left to process or not the right packet type
}
CINSTREAM;
inStream.SetReadOffset(BYTES_TO_BITS(1));
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
eConnectionType connection;
eChatMessageType chatMessageID;
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
Game::playerContainer.InsertPlayer(packet);
break;
inStream.Read(connection);
if (connection != eConnectionType::CHAT) return;
inStream.Read(chatMessageID);
switch (chatMessageID) {
case eChatMessageType::GM_MUTE:
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
Game::playerContainer.RemovePlayer(packet);
break;
case eChatInternalMessageType::MUTE_UPDATE:
Game::playerContainer.MuteUpdate(packet);
break;
case eChatMessageType::CREATE_TEAM:
case eChatInternalMessageType::CREATE_TEAM:
Game::playerContainer.CreateTeamServer(packet);
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:
ChatPacketHandler::HandleFriendlistRequest(packet);
break;
@@ -277,19 +296,6 @@ void HandlePacket(Packet* packet) {
ChatPacketHandler::HandleGMLevelUpdate(packet);
break;
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:
case eChatMessageType::SHOW_ALL:
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
@@ -302,6 +308,7 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::GUILD_KICK:
case eChatMessageType::GUILD_GET_STATUS:
case eChatMessageType::GUILD_GET_ALL:
case eChatMessageType::SHOW_ALL:
case eChatMessageType::BLUEPRINT_MODERATED:
case eChatMessageType::BLUEPRINT_MODEL_READY:
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
@@ -316,6 +323,7 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::CSR_REQUEST:
case eChatMessageType::CSR_REPLY:
case eChatMessageType::GM_KICK:
case eChatMessageType::GM_ANNOUNCE:
case eChatMessageType::WORLD_ROUTE_PACKET:
case eChatMessageType::GET_ZONE_POPULATIONS:
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
@@ -324,18 +332,33 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
case eChatMessageType::UGCC_REQUEST:
case eChatMessageType::WHO:
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
case eChatMessageType::ACHIEVEMENT_NOTIFY:
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
case eChatMessageType::UNEXPECTED_DISCONNECT:
case eChatMessageType::PLAYER_READY:
case eChatMessageType::GET_DONATION_TOTAL:
case eChatMessageType::UPDATE_DONATION:
case eChatMessageType::PRG_CSR_COMMAND:
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chat_message_type).data(), chat_message_type);
break;
default:
LOG("Unknown CHAT Message id: %i", chatMessageID);
LOG("Unknown CHAT Message id: %i", chat_message_type);
}
}
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]));
}
}
}

View File

@@ -9,9 +9,9 @@
#include "BitStreamUtils.h"
#include "Database.h"
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "ChatPackets.h"
#include "dConfig.h"
#include "eChatMessageType.h"
void PlayerContainer::Initialize() {
m_MaxNumberOfBestFriends =
@@ -145,7 +145,7 @@ void PlayerContainer::CreateTeamServer(Packet* packet) {
void PlayerContainer::BroadcastMuteUpdate(LWOOBJID player, time_t time) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_MUTE);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE);
bitStream.Write(player);
bitStream.Write(time);
@@ -352,7 +352,7 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::TEAM_GET_STATUS);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::TEAM_UPDATE);
bitStream.Write(team->teamID);
bitStream.Write(deleteTeam);
@@ -390,7 +390,7 @@ LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
return m_Players.contains(playerID) ? m_Players[playerID] : m_Players[LWOOBJID_EMPTY];
return m_Players[playerID];
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {

View File

@@ -120,8 +120,6 @@ void CatchUnhandled(int sig) {
if (eptr) std::rethrow_exception(eptr);
} catch(const std::exception& e) {
LOG("Caught exception: '%s'", e.what());
} catch (...) {
LOG("Caught unknown exception.");
}
#ifndef INCLUDE_BACKTRACE

View File

@@ -320,7 +320,7 @@ std::vector<std::string> GeneralUtils::GetSqlFileNamesFromFolder(const std::stri
return sortedFiles;
}
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
#ifdef DARKFLAME_PLATFORM_MACOS
// MacOS floating-point parse function specializations
namespace GeneralUtils::details {

View File

@@ -156,9 +156,8 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <Numeric T>
[[nodiscard]] std::optional<T> TryParse(std::string_view str) {
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) {
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 auto [parseEnd, ec] = std::from_chars(str.data(), strEnd, result);
@@ -167,7 +166,7 @@ namespace GeneralUtils {
return isParsed ? static_cast<T>(result) : std::optional<T>{};
}
#if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
#ifdef DARKFLAME_PLATFORM_MACOS
// MacOS floating-point parse helper function specializations
namespace details {
@@ -182,10 +181,8 @@ namespace GeneralUtils {
* @returns An std::optional containing the desired value if it is equivalent to the string
*/
template <std::floating_point T>
[[nodiscard]] std::optional<T> TryParse(std::string_view str) noexcept
[[nodiscard]] std::optional<T> TryParse(const std::string_view str) noexcept
try {
while (!str.empty() && std::isspace(str.front())) str.remove_prefix(1);
size_t parseNum;
const T result = details::_parse<T>(str, parseNum);
const bool isParsed = str.length() == parseNum;
@@ -267,8 +264,8 @@ namespace GeneralUtils {
* @returns The enum entry's value in its underlying type
*/
template <Enum eType>
constexpr std::underlying_type_t<eType> ToUnderlying(const eType entry) noexcept {
return static_cast<std::underlying_type_t<eType>>(entry);
constexpr typename std::underlying_type_t<eType> CastUnderlyingType(const eType entry) noexcept {
return static_cast<typename std::underlying_type_t<eType>>(entry);
}
// on Windows we need to undef these or else they conflict with our numeric limits calls

View File

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

View File

@@ -72,9 +72,7 @@ enum class eChatMessageType :uint32_t {
UPDATE_DONATION,
PRG_CSR_COMMAND,
HEARTBEAT_REQUEST_FROM_WORLD,
UPDATE_FREE_TRIAL_STATUS,
// CUSTOM DLU MESSAGE ID FOR INTERNAL USE
CREATE_TEAM,
UPDATE_FREE_TRIAL_STATUS
};
#endif //!__ECHATMESSAGETYPE__H__

View File

@@ -5,7 +5,8 @@ enum class eConnectionType : uint16_t {
SERVER = 0,
AUTH,
CHAT,
WORLD = 4,
CHAT_INTERNAL,
WORLD,
CLIENT,
MASTER
};

View File

@@ -790,10 +790,9 @@ enum class eGameMessageType : uint16_t {
GET_MISSION_TYPE_STATES = 853,
GET_TIME_PLAYED = 854,
SET_MISSION_VIEWED = 855,
HKX_VEHICLE_LOADED = 856,
SLASH_COMMAND_TEXT_FEEDBACK = 857,
SLASH_COMMAND_TEXT_FEEDBACK = 856,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 857,
BROADCAST_TEXT_TO_CHATBOX = 858,
HANDLE_SLASH_COMMAND_KORE_DEBUGGER = 859,
OPEN_PROPERTY_MANAGEMENT = 860,
OPEN_PROPERTY_VENDOR = 861,
VOTE_ON_PROPERTY = 862,

View File

@@ -1,59 +0,0 @@
#ifndef __EWAYPOINTCOMMANDTYPES__H__
#define __EWAYPOINTCOMMANDTYPES__H__
#include <cstdint>
enum class eWaypointCommandType : uint32_t {
INVALID,
BOUNCE,
STOP,
GROUP_EMOTE,
SET_VARIABLE,
CAST_SKILL,
EQUIP_INVENTORY,
UNEQUIP_INVENTORY,
DELAY,
EMOTE,
TELEPORT,
PATH_SPEED,
REMOVE_NPC,
CHANGE_WAYPOINT,
DELETE_SELF,
KILL_SELF,
SPAWN_OBJECT,
PLAY_SOUND,
};
class WaypointCommandType {
public:
static eWaypointCommandType StringToWaypointCommandType(std::string commandString) {
const std::map<std::string, eWaypointCommandType> WaypointCommandTypeMap = {
{"bounce", eWaypointCommandType::BOUNCE},
{"stop", eWaypointCommandType::STOP},
{"groupemote", eWaypointCommandType::GROUP_EMOTE},
{"setvar", eWaypointCommandType::SET_VARIABLE},
{"castskill", eWaypointCommandType::CAST_SKILL},
{"eqInvent", eWaypointCommandType::EQUIP_INVENTORY},
{"unInvent", eWaypointCommandType::UNEQUIP_INVENTORY},
{"delay", eWaypointCommandType::DELAY},
{"femote", eWaypointCommandType::EMOTE},
{"emote", eWaypointCommandType::EMOTE},
{"teleport", eWaypointCommandType::TELEPORT},
{"pathspeed", eWaypointCommandType::PATH_SPEED},
{"removeNPC", eWaypointCommandType::REMOVE_NPC},
{"changeWP", eWaypointCommandType::CHANGE_WAYPOINT},
{"DeleteSelf", eWaypointCommandType::DELETE_SELF},
{"killself", eWaypointCommandType::KILL_SELF},
{"removeself", eWaypointCommandType::DELETE_SELF},
{"spawnOBJ", eWaypointCommandType::SPAWN_OBJECT},
{"playSound", eWaypointCommandType::PLAY_SOUND},
};
auto intermed = WaypointCommandTypeMap.find(commandString);
return (intermed != WaypointCommandTypeMap.end()) ? intermed->second : eWaypointCommandType::INVALID;
};
};
#endif //!__EWAYPOINTCOMMANDTYPES__H__

View File

@@ -29,8 +29,8 @@ enum class eWorldMessageType : uint32_t {
ROUTE_PACKET, // Social?
POSITION_UPDATE,
MAIL,
WORD_CHECK, // AllowList word check
STRING_CHECK, // AllowList string check
WORD_CHECK, // Whitelist word check
STRING_CHECK, // Whitelist string check
GET_PLAYERS_IN_ZONE,
REQUEST_UGC_MANIFEST_INFO,
BLUEPRINT_GET_ALL_DATA_REQUEST,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -27,9 +27,12 @@ Character::Character(uint32_t id, User* parentUser) {
m_ID = id;
m_ParentUser = parentUser;
m_OurEntity = nullptr;
m_Doc = nullptr;
}
Character::~Character() {
if (m_Doc) delete m_Doc;
m_Doc = nullptr;
m_OurEntity = nullptr;
m_ParentUser = nullptr;
}
@@ -52,6 +55,8 @@ 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_ZoneCloneID = 0;
m_Doc = nullptr;
//Quickly and dirtly parse the xmlData to get the info we need:
DoQuickXMLDataParse();
@@ -65,13 +70,18 @@ void Character::UpdateInfoFromDatabase() {
}
void Character::UpdateFromDatabase() {
if (m_Doc) delete m_Doc;
UpdateInfoFromDatabase();
}
void Character::DoQuickXMLDataParse() {
if (m_XMLData.size() == 0) return;
if (m_Doc.Parse(m_XMLData.c_str(), m_XMLData.size()) == 0) {
delete m_Doc;
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);
} else {
LOG("Failed to load xmlData!");
@@ -79,7 +89,7 @@ void Character::DoQuickXMLDataParse() {
return;
}
tinyxml2::XMLElement* mf = m_Doc.FirstChildElement("obj")->FirstChildElement("mf");
tinyxml2::XMLElement* mf = m_Doc->FirstChildElement("obj")->FirstChildElement("mf");
if (!mf) {
LOG("Failed to find mf tag!");
return;
@@ -98,7 +108,7 @@ void Character::DoQuickXMLDataParse() {
mf->QueryAttribute("ess", &m_Eyes);
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) {
LOG("Char has no inv!");
return;
@@ -131,7 +141,7 @@ void Character::DoQuickXMLDataParse() {
}
tinyxml2::XMLElement* character = m_Doc.FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = m_Doc->FirstChildElement("obj")->FirstChildElement("char");
if (character) {
character->QueryAttribute("cc", &m_Coins);
int32_t gm_level = 0;
@@ -195,7 +205,7 @@ void Character::DoQuickXMLDataParse() {
character->QueryAttribute("lzrw", &m_OriginalRotation.w);
}
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
if (flags) {
auto* currentChild = flags->FirstChildElement();
while (currentChild) {
@@ -229,10 +239,12 @@ void Character::SetBuildMode(bool buildMode) {
}
void Character::SaveXMLToDatabase() {
if (!m_Doc) return;
//For metrics, we'll record the time it took to save:
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) {
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
character->SetAttribute("cc", m_Coins);
@@ -254,11 +266,11 @@ void Character::SaveXMLToDatabase() {
}
auto emotes = character->FirstChildElement("ue");
if (!emotes) emotes = m_Doc.NewElement("ue");
if (!emotes) emotes = m_Doc->NewElement("ue");
emotes->DeleteChildren();
for (int emoteID : m_UnlockedEmotes) {
auto emote = m_Doc.NewElement("e");
auto emote = m_Doc->NewElement("e");
emote->SetAttribute("id", emoteID);
emotes->LinkEndChild(emote);
@@ -268,15 +280,15 @@ void Character::SaveXMLToDatabase() {
}
//Export our flags:
auto* flags = m_Doc.FirstChildElement("obj")->FirstChildElement("flag");
auto* flags = m_Doc->FirstChildElement("obj")->FirstChildElement("flag");
if (!flags) {
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
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
}
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) {
auto* f = m_Doc.NewElement("f");
auto* f = m_Doc->NewElement("f");
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.
@@ -289,7 +301,7 @@ void Character::SaveXMLToDatabase() {
// Prevents the news feed from showing up on world transfers
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);
flags->LinkEndChild(s);
}
@@ -314,7 +326,7 @@ void Character::SaveXMLToDatabase() {
void Character::SetIsNewLogin() {
// 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;
auto* currentChild = flags->FirstChildElement();
@@ -332,7 +344,7 @@ void Character::SetIsNewLogin() {
void Character::WriteToDatabase() {
//Dump our xml into m_XMLData:
tinyxml2::XMLPrinter printer(0, true, 0);
m_Doc.Print(&printer);
m_Doc->Print(&printer);
//Finally, save to db:
Database::Get()->UpdateCharacterXml(m_ID, printer.CStr());
@@ -409,15 +421,15 @@ void Character::SetRetroactiveFlags() {
void Character::SaveXmlRespawnCheckpoints() {
//Export our respawn points:
auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
if (!points) {
points = m_Doc.NewElement("res");
m_Doc.FirstChildElement("obj")->LinkEndChild(points);
points = m_Doc->NewElement("res");
m_Doc->FirstChildElement("obj")->LinkEndChild(points);
}
points->DeleteChildren();
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("x", point.second.x);
@@ -431,7 +443,7 @@ void Character::SaveXmlRespawnCheckpoints() {
void Character::LoadXmlRespawnCheckpoints() {
m_WorldRespawnCheckpoints.clear();
auto* points = m_Doc.FirstChildElement("obj")->FirstChildElement("res");
auto* points = m_Doc->FirstChildElement("obj")->FirstChildElement("res");
if (!points) {
return;
}

View File

@@ -37,7 +37,7 @@ public:
void LoadXmlRespawnCheckpoints();
const std::string& GetXMLData() const { return m_XMLData; }
const tinyxml2::XMLDocument& GetXMLDoc() const { return m_Doc; }
tinyxml2::XMLDocument* GetXMLDoc() const { return m_Doc; }
/**
* Out of abundance of safety and clarity of what this saves, this is its own function.
@@ -623,7 +623,7 @@ private:
/**
* 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)

View File

@@ -254,7 +254,7 @@ void Entity::Initialize() {
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL) > 0) {
AddComponent<MiniGameControlComponent>(m_TemplateID);
AddComponent<MiniGameControlComponent>();
}
uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
@@ -476,7 +476,8 @@ void Entity::Initialize() {
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
AddComponent<InventoryComponent>();
auto* xmlDoc = m_Character ? m_Character->GetXMLDoc() : nullptr;
AddComponent<InventoryComponent>(xmlDoc);
}
// 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) {
@@ -666,7 +667,7 @@ void Entity::Initialize() {
// Shooting gallery component
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SHOOTING_GALLERY) > 0) {
AddComponent<ShootingGalleryComponent>(m_TemplateID);
AddComponent<ShootingGalleryComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1) != -1) {
@@ -730,21 +731,15 @@ void Entity::Initialize() {
// if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) {
AddComponent<MovingPlatformComponent>(pathName);
} else if (path->pathType == PathType::Movement) {
auto movementAIcomponent = GetComponent<MovementAIComponent>();
if (movementAIcomponent && combatAiId == 0) {
movementAIcomponent->SetPath(pathName);
// else if we are a movement path
} /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent<MovementAIComponent>();
if (movementAIcomp){
// TODO: set path in existing movementAIComp
} else {
MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = "";
moveInfo.wanderChance = 0;
moveInfo.wanderRadius = 16;
moveInfo.wanderSpeed = 2.5f;
moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2;
AddComponent<MovementAIComponent>(moveInfo);
// TODO: create movementAIcomp and set path
}
}
}*/
} else {
// else we still need to setup moving platform if it has a moving platform comp but no path
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
@@ -1243,7 +1238,7 @@ void Entity::WriteComponents(RakNet::BitStream& outBitStream, eReplicaPacketType
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.
//Naturally, we don't include any non-player components in this update function.
@@ -1634,8 +1629,10 @@ void Entity::PickupItem(const LWOOBJID& objectID) {
CDObjectSkillsTable* skillsTable = CDClientManager::GetTable<CDObjectSkillsTable>();
std::vector<CDObjectSkills> skills = skillsTable->Query([=](CDObjectSkills entry) {return (entry.objectTemplate == p.second.lot); });
for (CDObjectSkills skill : skills) {
CDSkillBehaviorTable* skillBehTable = CDClientManager::GetTable<CDSkillBehaviorTable>();
auto* skillComponent = GetComponent<SkillComponent>();
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID(), skill.castOnType, NiQuaternion(0, 0, 0, 0));
if (skillComponent) skillComponent->CastSkill(skill.skillID, GetObjectID(), GetObjectID());
auto* missionComponent = GetComponent<MissionComponent>();

View File

@@ -174,7 +174,7 @@ public:
void WriteBaseReplicaData(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);
// Events

View File

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

View File

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

View File

@@ -26,7 +26,7 @@
#include "eCharacterCreationResponse.h"
#include "eRenameResponse.h"
#include "eConnectionType.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "BitStreamUtils.h"
#include "CheatDetection.h"
@@ -83,7 +83,7 @@ void UserManager::Initialize() {
auto chatListStream = Game::assetManager->GetFile("chatplus_en_us.txt");
if (!chatListStream) {
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 allowlist file.");
throw std::runtime_error("Aborting initialization due to missing chat whitelist file.");
}
while (std::getline(chatListStream, line, '\n')) {
@@ -422,7 +422,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
Database::Get()->DeleteCharacter(charID);
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION);
bitStream.Write(objectID);
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);

View File

@@ -222,7 +222,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
if (healthDamageDealt >= 1) {
successState = eBasicAttackSuccessTypes::SUCCESS;
} else if (armorDamageDealt >= 1) {
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplate::EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
successState = this->m_OnFailArmor->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY ? eBasicAttackSuccessTypes::FAILIMMUNE : eBasicAttackSuccessTypes::FAILARMOR;
}
bitStream.Write(armorDamageDealt);

View File

@@ -5,7 +5,7 @@
#include "CDActivitiesTable.h"
#include "Game.h"
#include "Logger.h"
#include "BehaviorTemplate.h"
#include "BehaviorTemplates.h"
#include "BehaviorBranchContext.h"
#include <unordered_map>
@@ -110,176 +110,176 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
Behavior* behavior = nullptr;
switch (templateId) {
case BehaviorTemplate::EMPTY: break;
case BehaviorTemplate::BASIC_ATTACK:
case BehaviorTemplates::BEHAVIOR_EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId);
break;
case BehaviorTemplate::TAC_ARC:
case BehaviorTemplates::BEHAVIOR_TAC_ARC:
behavior = new TacArcBehavior(behaviorId);
break;
case BehaviorTemplate::AND:
case BehaviorTemplates::BEHAVIOR_AND:
behavior = new AndBehavior(behaviorId);
break;
case BehaviorTemplate::PROJECTILE_ATTACK:
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK:
behavior = new ProjectileAttackBehavior(behaviorId);
break;
case BehaviorTemplate::HEAL:
case BehaviorTemplates::BEHAVIOR_HEAL:
behavior = new HealBehavior(behaviorId);
break;
case BehaviorTemplate::MOVEMENT_SWITCH:
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH:
behavior = new MovementSwitchBehavior(behaviorId);
break;
case BehaviorTemplate::AREA_OF_EFFECT:
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT:
behavior = new AreaOfEffectBehavior(behaviorId);
break;
case BehaviorTemplate::PLAY_EFFECT:
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT:
behavior = new PlayEffectBehavior(behaviorId);
break;
case BehaviorTemplate::IMMUNITY:
case BehaviorTemplates::BEHAVIOR_IMMUNITY:
behavior = new ImmunityBehavior(behaviorId);
break;
case BehaviorTemplate::DAMAGE_BUFF: break;
case BehaviorTemplate::DAMAGE_ABSORBTION:
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION:
behavior = new DamageAbsorptionBehavior(behaviorId);
break;
case BehaviorTemplate::OVER_TIME:
case BehaviorTemplates::BEHAVIOR_OVER_TIME:
behavior = new OverTimeBehavior(behaviorId);
break;
case BehaviorTemplate::IMAGINATION:
case BehaviorTemplates::BEHAVIOR_IMAGINATION:
behavior = new ImaginationBehavior(behaviorId);
break;
case BehaviorTemplate::TARGET_CASTER:
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER:
behavior = new TargetCasterBehavior(behaviorId);
break;
case BehaviorTemplate::STUN:
case BehaviorTemplates::BEHAVIOR_STUN:
behavior = new StunBehavior(behaviorId);
break;
case BehaviorTemplate::DURATION:
case BehaviorTemplates::BEHAVIOR_DURATION:
behavior = new DurationBehavior(behaviorId);
break;
case BehaviorTemplate::KNOCKBACK:
case BehaviorTemplates::BEHAVIOR_KNOCKBACK:
behavior = new KnockbackBehavior(behaviorId);
break;
case BehaviorTemplate::ATTACK_DELAY:
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY:
behavior = new AttackDelayBehavior(behaviorId);
break;
case BehaviorTemplate::CAR_BOOST:
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
behavior = new CarBoostBehavior(behaviorId);
break;
case BehaviorTemplate::FALL_SPEED:
case BehaviorTemplates::BEHAVIOR_FALL_SPEED:
behavior = new FallSpeedBehavior(behaviorId);
break;
case BehaviorTemplate::SHIELD: break;
case BehaviorTemplate::REPAIR_ARMOR:
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
behavior = new RepairBehavior(behaviorId);
break;
case BehaviorTemplate::SPEED:
case BehaviorTemplates::BEHAVIOR_SPEED:
behavior = new SpeedBehavior(behaviorId);
break;
case BehaviorTemplate::DARK_INSPIRATION:
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION:
behavior = new DarkInspirationBehavior(behaviorId);
break;
case BehaviorTemplate::LOOT_BUFF:
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF:
behavior = new LootBuffBehavior(behaviorId);
break;
case BehaviorTemplate::VENTURE_VISION:
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION:
behavior = new VentureVisionBehavior(behaviorId);
break;
case BehaviorTemplate::SPAWN_OBJECT:
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplate::LAY_BRICK: break;
case BehaviorTemplate::SWITCH:
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break;
case BehaviorTemplates::BEHAVIOR_SWITCH:
behavior = new SwitchBehavior(behaviorId);
break;
case BehaviorTemplate::BUFF:
case BehaviorTemplates::BEHAVIOR_BUFF:
behavior = new BuffBehavior(behaviorId);
break;
case BehaviorTemplate::JETPACK:
case BehaviorTemplates::BEHAVIOR_JETPACK:
behavior = new JetPackBehavior(behaviorId);
break;
case BehaviorTemplate::SKILL_EVENT:
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT:
behavior = new SkillEventBehavior(behaviorId);
break;
case BehaviorTemplate::CONSUME_ITEM:
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM:
behavior = new ConsumeItemBehavior(behaviorId);
break;
case BehaviorTemplate::SKILL_CAST_FAILED:
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED:
behavior = new SkillCastFailedBehavior(behaviorId);
break;
case BehaviorTemplate::IMITATION_SKUNK_STINK: break;
case BehaviorTemplate::CHANGE_IDLE_FLAGS:
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break;
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS:
behavior = new ChangeIdleFlagsBehavior(behaviorId);
break;
case BehaviorTemplate::APPLY_BUFF:
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF:
behavior = new ApplyBuffBehavior(behaviorId);
break;
case BehaviorTemplate::CHAIN:
case BehaviorTemplates::BEHAVIOR_CHAIN:
behavior = new ChainBehavior(behaviorId);
break;
case BehaviorTemplate::CHANGE_ORIENTATION:
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION:
behavior = new ChangeOrientationBehavior(behaviorId);
break;
case BehaviorTemplate::FORCE_MOVEMENT:
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT:
behavior = new ForceMovementBehavior(behaviorId);
break;
case BehaviorTemplate::INTERRUPT:
case BehaviorTemplates::BEHAVIOR_INTERRUPT:
behavior = new InterruptBehavior(behaviorId);
break;
case BehaviorTemplate::ALTER_COOLDOWN: break;
case BehaviorTemplate::CHARGE_UP:
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break;
case BehaviorTemplates::BEHAVIOR_CHARGE_UP:
behavior = new ChargeUpBehavior(behaviorId);
break;
case BehaviorTemplate::SWITCH_MULTIPLE:
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE:
behavior = new SwitchMultipleBehavior(behaviorId);
break;
case BehaviorTemplate::START:
case BehaviorTemplates::BEHAVIOR_START:
behavior = new StartBehavior(behaviorId);
break;
case BehaviorTemplate::END:
case BehaviorTemplates::BEHAVIOR_END:
behavior = new EndBehavior(behaviorId);
break;
case BehaviorTemplate::ALTER_CHAIN_DELAY: break;
case BehaviorTemplate::CAMERA: break;
case BehaviorTemplate::REMOVE_BUFF:
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break;
case BehaviorTemplates::BEHAVIOR_CAMERA: break;
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF:
behavior = new RemoveBuffBehavior(behaviorId);
break;
case BehaviorTemplate::GRAB: break;
case BehaviorTemplate::MODULAR_BUILD: break;
case BehaviorTemplate::NPC_COMBAT_SKILL:
case BehaviorTemplates::BEHAVIOR_GRAB: break;
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break;
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL:
behavior = new NpcCombatSkillBehavior(behaviorId);
break;
case BehaviorTemplate::BLOCK:
case BehaviorTemplates::BEHAVIOR_BLOCK:
behavior = new BlockBehavior(behaviorId);
break;
case BehaviorTemplate::VERIFY:
case BehaviorTemplates::BEHAVIOR_VERIFY:
behavior = new VerifyBehavior(behaviorId);
break;
case BehaviorTemplate::TAUNT:
case BehaviorTemplates::BEHAVIOR_TAUNT:
behavior = new TauntBehavior(behaviorId);
break;
case BehaviorTemplate::AIR_MOVEMENT:
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT:
behavior = new AirMovementBehavior(behaviorId);
break;
case BehaviorTemplate::SPAWN_QUICKBUILD:
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD:
behavior = new SpawnBehavior(behaviorId);
break;
case BehaviorTemplate::PULL_TO_POINT:
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT:
behavior = new PullToPointBehavior(behaviorId);
break;
case BehaviorTemplate::PROPERTY_ROTATE: break;
case BehaviorTemplate::DAMAGE_REDUCTION:
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION:
behavior = new DamageReductionBehavior(behaviorId);
break;
case BehaviorTemplate::PROPERTY_TELEPORT:
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT:
behavior = new PropertyTeleportBehavior(behaviorId);
break;
case BehaviorTemplate::PROPERTY_CLEAR_TARGET:
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET:
behavior = new ClearTargetBehavior(behaviorId);
break;
case BehaviorTemplate::TAKE_PICTURE: break;
case BehaviorTemplate::MOUNT: break;
case BehaviorTemplate::SKILL_SET: break;
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break;
case BehaviorTemplates::BEHAVIOR_MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break;
default:
//LOG("Failed to load behavior with invalid template id (%i)!", templateId);
break;
@@ -296,19 +296,19 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
return behavior;
}
BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
BehaviorTemplate templateID = BehaviorTemplate::EMPTY;
BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY;
// Find behavior template by its behavior id. Default to 0.
if (behaviorTemplateTable) {
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
if (templateEntry.behaviorID == behaviorId) {
templateID = static_cast<BehaviorTemplate>(templateEntry.templateID);
templateID = static_cast<BehaviorTemplates>(templateEntry.templateID);
}
}
if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) {
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) {
LOG("Failed to load behavior template with id (%i)!", behaviorId);
}
@@ -335,22 +335,26 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
const auto typeString = GeneralUtils::UTF16ToWTF8(type);
const auto itr = m_effectNames.find(typeString);
if (m_effectNames == nullptr) {
m_effectNames = new std::unordered_map<std::string, std::string>();
} else {
const auto pair = m_effectNames->find(typeString);
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(m_effectType);
}
if (type.empty()) {
type = GeneralUtils::ASCIIToUTF16(*m_effectType);
}
if (itr != m_effectNames.end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, itr->second, secondary, 1, 1, true);
if (pair != m_effectNames->end()) {
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, pair->second, secondary, 1, 1, true);
return;
}
renderComponent->PlayEffect(effectId, type, pair->second, secondary);
return;
}
renderComponent->PlayEffect(effectId, type, itr->second, secondary);
return;
}
// The SQlite result object becomes invalid if the query object leaves scope.
@@ -384,12 +388,12 @@ void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID
type = GeneralUtils::ASCIIToUTF16(typeResult);
m_effectType = typeResult;
m_effectType = new std::string(typeResult);
}
result.finalize();
m_effectNames.insert_or_assign(typeString, name);
m_effectNames->insert_or_assign(typeString, name);
if (renderComponent == nullptr) {
GameMessages::SendPlayFXEffect(targetEntity, effectId, type, name, secondary, 1, 1, true);
@@ -419,7 +423,8 @@ Behavior::Behavior(const uint32_t behaviorId) {
if (behaviorId == 0) {
this->m_effectId = 0;
this->m_templateId = BehaviorTemplate::EMPTY;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
}
// Make sure we do not proceed if we are trying to load an invalid behavior
@@ -427,16 +432,17 @@ Behavior::Behavior(const uint32_t behaviorId) {
LOG("Failed to load behavior with id (%i)!", behaviorId);
this->m_effectId = 0;
this->m_templateId = BehaviorTemplate::EMPTY;
this->m_effectHandle = nullptr;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY;
return;
}
this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID);
this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID);
this->m_effectId = templateInDatabase.effectID;
this->m_effectHandle = *templateInDatabase.effectHandle;
this->m_effectHandle = *templateInDatabase.effectHandle != "" ? new std::string(*templateInDatabase.effectHandle) : nullptr;
}
@@ -501,3 +507,9 @@ void Behavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream,
void Behavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
}
Behavior::~Behavior() {
delete m_effectNames;
delete m_effectType;
delete m_effectHandle;
}

View File

@@ -6,7 +6,7 @@
#include <unordered_map>
#include "BitStream.h"
#include "BehaviorTemplate.h"
#include "BehaviorTemplates.h"
#include "dCommonVars.h"
struct BehaviorContext;
@@ -26,7 +26,7 @@ public:
static Behavior* CreateBehavior(uint32_t behaviorId);
static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId);
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId);
/*
* Utilities
@@ -39,11 +39,11 @@ public:
*/
uint32_t m_behaviorId;
BehaviorTemplate m_templateId;
BehaviorTemplates m_templateId;
uint32_t m_effectId;
std::string m_effectHandle;
std::unordered_map<std::string, std::string> m_effectNames;
std::string m_effectType;
std::string* m_effectHandle = nullptr;
std::unordered_map<std::string, std::string>* m_effectNames = nullptr;
std::string* m_effectType = nullptr;
/*
* Behavior parameters
@@ -88,11 +88,5 @@ public:
*/
explicit Behavior(uint32_t behaviorId);
virtual ~Behavior() = default;
Behavior(const Behavior& other) = default;
Behavior(Behavior&& other) = default;
Behavior& operator=(const Behavior& other) = default;
Behavior& operator=(Behavior&& other) = default;
virtual ~Behavior();
};

View File

@@ -1,70 +0,0 @@
#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
};

View File

@@ -0,0 +1 @@
#include "BehaviorTemplates.h"

View File

@@ -0,0 +1,70 @@
#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
};

View File

@@ -7,6 +7,7 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
"Behavior.cpp"
"BehaviorBranchContext.cpp"
"BehaviorContext.cpp"
"BehaviorTemplates.cpp"
"BlockBehavior.cpp"
"BuffBehavior.cpp"
"CarBoostBehavior.cpp"

View File

@@ -7,7 +7,7 @@
#include "Logger.h"
void ForceMovementBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
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) {
return;
}
@@ -38,7 +38,7 @@ void ForceMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream& bi
}
void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (this->m_hitAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitEnemyAction->m_templateId == BehaviorTemplate::EMPTY && this->m_hitFactionAction->m_templateId == BehaviorTemplate::EMPTY) {
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) {
return;
}

View File

@@ -8,50 +8,36 @@
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (branch.target != context->originator) {
bool unknown = false;
if (usedTarget != context->originator) {
bool isTargetImmuneStuns = false;
if (!bitStream.Read(isTargetImmuneStuns)) {
LOG("Unable to read isTargetImmune from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
if (!bitStream.Read(unknown)) {
LOG("Unable to read unknown1 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (isTargetImmuneStuns) return;
if (unknown) return;
}
if (!this->m_interruptBlock) {
bool isBlockingInterrupts = false;
if (!bitStream.Read(isBlockingInterrupts)) {
LOG("Unable to read isBlockingInterrupts from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
bool unknown = false;
if (!bitStream.Read(unknown)) {
LOG("Unable to read unknown2 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (isBlockingInterrupts) return;
if (unknown) return;
}
bool hasInterruptedStatusEffects = false;
if (!bitStream.Read(hasInterruptedStatusEffects)) {
LOG("Unable to read hasInterruptedStatusEffects from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (this->m_target) // Guess...
{
bool unknown = false;
if (hasInterruptedStatusEffects) {
bool hasMoreInterruptedStatusEffects = false;
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 (!bitStream.Read(unknown)) {
LOG("Unable to read unknown3 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
}
if (branch.target == context->originator) return;
@@ -69,8 +55,7 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (usedTarget != context->originator) {
if (branch.target != context->originator) {
bitStream.Write(false);
}

View File

@@ -6,13 +6,13 @@
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
uint32_t movementType{};
if (!bitStream.Read(movementType)) {
if (this->m_groundAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplate::EMPTY) {
if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
return;
}
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) {
float actionValue = GetFloat(movementType, -1.0f);
auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f);
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplate::EMPTY) {
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) {
loadedBehavior = this->m_groundAction;
}
return loadedBehavior;

View File

@@ -9,16 +9,17 @@ void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bit
auto* target = Game::entityManager->GetEntity(branch.target);
auto* caster = Game::entityManager->GetEntity(context->originator);
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
}
}
void SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
void
SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
auto* target = Game::entityManager->GetEntity(branch.target);
auto* caster = Game::entityManager->GetEntity(context->originator);
if (caster != nullptr && target != nullptr && !this->m_effectHandle.empty()) {
target->GetScript()->OnSkillEventFired(target, caster, this->m_effectHandle);
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
target->GetScript()->OnSkillEventFired(target, caster, *this->m_effectHandle);
}
}

View File

@@ -7,9 +7,9 @@
#include "BuffComponent.h"
void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
bool state = true;
auto state = true;
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
if (!bitStream.Read(state)) {
LOG("Unable to read state from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
@@ -18,59 +18,49 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStre
auto* entity = Game::entityManager->GetEntity(context->originator);
if (!entity) return;
if (entity == nullptr) {
return;
}
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
if (destroyableComponent) {
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());
if (destroyableComponent == nullptr) {
return;
}
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
behaviorToCall->Handle(context, bitStream, branch);
LOG_DEBUG("[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
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) {
bool state = true;
if (m_imagination > 0 || m_targetHasBuff > 0 || m_Distance > -1.0f) {
auto state = true;
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
auto* entity = Game::entityManager->GetEntity(branch.target);
state = entity != nullptr;
if (state) {
if (m_targetHasBuff != 0) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
if (state && m_targetHasBuff != 0) {
auto* buffComponent = entity->GetComponent<BuffComponent>();
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
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;
}
if (buffComponent != nullptr && !buffComponent->HasBuff(m_targetHasBuff)) {
state = false;
}
}
bitStream.Write(state);
}
auto* behaviorToCall = state ? m_actionTrue : m_actionFalse;
behaviorToCall->Calculate(context, bitStream, branch);
if (state) {
this->m_actionTrue->Calculate(context, bitStream, branch);
} else {
this->m_actionFalse->Calculate(context, bitStream, branch);
}
}
void SwitchBehavior::Load() {
@@ -82,7 +72,5 @@ void SwitchBehavior::Load() {
this->m_isEnemyFaction = GetBoolean("isEnemyFaction");
this->m_targetHasBuff = GetInt("target_has_buff", -1);
this->m_Distance = GetFloat("distance", -1.0f);
this->m_targetHasBuff = GetInt("target_has_buff");
}

View File

@@ -14,8 +14,6 @@ public:
int32_t m_targetHasBuff;
float m_Distance;
/*
* Inherited
*/

View File

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

View File

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

View File

@@ -21,7 +21,7 @@
#include "eMissionTaskType.h"
#include "eMatchUpdate.h"
#include "eConnectionType.h"
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "CDCurrencyTableTable.h"
#include "CDActivityRewardsTable.h"
@@ -501,7 +501,7 @@ void ActivityInstance::StartZone() {
// only make a team if we have more than one participant
if (participants.size() > 1) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::CREATE_TEAM);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::CREATE_TEAM);
bitStream.Write(leader->GetObjectID());
bitStream.Write(m_Participants.size());

View File

@@ -150,18 +150,19 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
m_dpEntityEnemy->SetPosition(m_Parent->GetPosition());
//Process enter events
for (const auto id : m_dpEntity->GetNewObjects()) {
m_Parent->OnCollisionPhantom(id);
for (auto en : m_dpEntity->GetNewObjects()) {
m_Parent->OnCollisionPhantom(en->GetObjectID());
}
//Process exit events
for (const auto id : m_dpEntity->GetRemovedObjects()) {
m_Parent->OnCollisionLeavePhantom(id);
for (auto en : m_dpEntity->GetRemovedObjects()) {
m_Parent->OnCollisionLeavePhantom(en->GetObjectID());
}
// Check if we should stop the tether effect
if (m_TetherEffectActive) {
m_TetherTime -= deltaTime;
const auto& info = m_MovementAI->GetInfo();
if (m_Target != LWOOBJID_EMPTY || (NiPoint3::DistanceSquared(
m_StartPosition,
m_Parent->GetPosition()) < 20 * 20 && m_TetherTime <= 0)

View File

@@ -326,9 +326,9 @@ Entity* BuffComponent::GetParent() const {
return m_Parent;
}
void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
// Load buffs
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff");
@@ -386,15 +386,15 @@ void BuffComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
}
}
void BuffComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// Save buffs
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
auto* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
// Make sure we have a clean buff element.
auto* buffElement = dest->FirstChildElement("buff");
if (buffElement == nullptr) {
buffElement = doc.NewElement("buff");
buffElement = doc->NewElement("buff");
dest->LinkEndChild(buffElement);
} else {
@@ -402,7 +402,7 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
}
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.
if (buff.cancelOnZone) continue;

View File

@@ -57,9 +57,9 @@ public:
Entity* GetParent() const;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -47,6 +47,7 @@ set(DGAME_DCOMPONENTS_SOURCES
"TriggerComponent.cpp"
"HavokVehiclePhysicsComponent.cpp"
"VendorComponent.cpp"
"MiniGameControlComponent.cpp"
"ScriptComponent.cpp"
)

View File

@@ -186,9 +186,9 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
m_GMLevel = gmlevel;
}
void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while loading XML!");
return;
@@ -299,8 +299,8 @@ void CharacterComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
}
}
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* minifig = doc.FirstChildElement("obj")->FirstChildElement("mf");
void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* minifig = doc->FirstChildElement("obj")->FirstChildElement("mf");
if (!minifig) {
LOG("Failed to find mf tag while updating XML!");
return;
@@ -320,7 +320,7 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
// done with minifig
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while updating XML!");
return;
@@ -338,11 +338,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
// Set the zone statistics of the form <zs><s/> ... <s/></zs>
auto zoneStatistics = character->FirstChildElement("zs");
if (!zoneStatistics) zoneStatistics = doc.NewElement("zs");
if (!zoneStatistics) zoneStatistics = doc->NewElement("zs");
zoneStatistics->DeleteChildren();
for (auto pair : m_ZoneStatistics) {
auto zoneStatistic = doc.NewElement("s");
auto zoneStatistic = doc->NewElement("s");
zoneStatistic->SetAttribute("map", pair.first);
zoneStatistic->SetAttribute("ac", pair.second.m_AchievementsCollected);

View File

@@ -70,8 +70,8 @@ public:
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
~CharacterComponent() override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;

View File

@@ -21,11 +21,11 @@ void Component::OnUse(Entity* originator) {
}
void Component::UpdateXml(tinyxml2::XMLDocument& doc) {
void Component::UpdateXml(tinyxml2::XMLDocument* doc) {
}
void Component::LoadFromXml(const tinyxml2::XMLDocument& doc) {
void Component::LoadFromXml(tinyxml2::XMLDocument* doc) {
}

View File

@@ -34,13 +34,13 @@ public:
* Save data from this componennt to character XML
* @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
* @param doc the document to read data from
*/
virtual void LoadFromXml(const tinyxml2::XMLDocument& doc);
virtual void LoadFromXml(tinyxml2::XMLDocument* doc);
virtual void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);

View File

@@ -26,6 +26,7 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Phy
m_SpeedMultiplier = 1;
m_GravityScale = 1;
m_DirtyCheats = false;
m_IgnoreMultipliers = false;
m_DirtyEquippedItemInfo = true;
m_PickupRadius = 0.0f;
@@ -91,31 +92,31 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
outBitStream.Write(m_ImmuneToStunInteractCount);
}
outBitStream.Write(m_DirtyCheats || bIsInitialUpdate);
if (m_DirtyCheats || bIsInitialUpdate) {
if (m_IgnoreMultipliers) m_DirtyCheats = false;
outBitStream.Write(m_DirtyCheats);
if (m_DirtyCheats) {
outBitStream.Write(m_GravityScale);
outBitStream.Write(m_SpeedMultiplier);
if (!bIsInitialUpdate) m_DirtyCheats = false;
m_DirtyCheats = false;
}
outBitStream.Write(m_DirtyEquippedItemInfo || bIsInitialUpdate);
if (m_DirtyEquippedItemInfo || bIsInitialUpdate) {
outBitStream.Write(m_DirtyEquippedItemInfo);
if (m_DirtyEquippedItemInfo) {
outBitStream.Write(m_PickupRadius);
outBitStream.Write(m_InJetpackMode);
if (!bIsInitialUpdate) m_DirtyEquippedItemInfo = false;
m_DirtyEquippedItemInfo = false;
}
outBitStream.Write(m_DirtyBubble || bIsInitialUpdate);
if (m_DirtyBubble || bIsInitialUpdate) {
outBitStream.Write(m_DirtyBubble);
if (m_DirtyBubble) {
outBitStream.Write(m_IsInBubble);
if (m_IsInBubble) {
outBitStream.Write(m_BubbleType);
outBitStream.Write(m_SpecialAnims);
}
if (!bIsInitialUpdate) m_DirtyBubble = false;
m_DirtyBubble = false;
}
outBitStream.Write(m_DirtyPosition || bIsInitialUpdate);
@@ -148,8 +149,7 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
outBitStream.Write(m_AngularVelocity.z);
}
outBitStream.Write0(); // local_space_info, always zero for now.
outBitStream.Write0();
if (!bIsInitialUpdate) {
m_DirtyPosition = false;
outBitStream.Write(m_IsTeleporting);
@@ -158,8 +158,8 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream& outBitStream, bo
}
}
void ControllablePhysicsComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* character = doc.FirstChildElement("obj")->FirstChildElement("char");
void ControllablePhysicsComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag!");
return;
@@ -178,8 +178,8 @@ void ControllablePhysicsComponent::LoadFromXml(const tinyxml2::XMLDocument& doc)
m_DirtyPosition = true;
}
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* character = doc.FirstChildElement("obj")->FirstChildElement("char");
void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
if (!character) {
LOG("Failed to find char tag while updating XML!");
return;

View File

@@ -28,8 +28,8 @@ public:
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
/**
* Sets the position of this entity, also ensures this update is serialized next tick.
@@ -174,6 +174,18 @@ public:
*/
const float GetGravityScale() const { return m_GravityScale; }
/**
* Sets the ignore multipliers value, allowing you to skip the serialization of speed and gravity multipliers
* @param value whether or not to ignore multipliers
*/
void SetIgnoreMultipliers(bool value) { m_IgnoreMultipliers = value; }
/**
* Returns the current ignore multipliers value
* @return the current ignore multipliers value
*/
const bool GetIgnoreMultipliers() const { return m_IgnoreMultipliers; }
/**
* Can make an entity static, making it unable to move around
* @param value whether or not the entity is static
@@ -341,6 +353,11 @@ private:
*/
bool m_DirtyCheats;
/**
* Makes it so that the speed multiplier and gravity scale are no longer serialized if false
*/
bool m_IgnoreMultipliers;
/**
* Whether this entity is static, making it unable to move
*/

View File

@@ -185,8 +185,8 @@ void DestroyableComponent::Update(float deltaTime) {
m_DamageCooldownTimer -= deltaTime;
}
void DestroyableComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
void DestroyableComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
if (!dest) {
LOG("Failed to find dest tag!");
return;
@@ -207,8 +207,8 @@ void DestroyableComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
m_DirtyHealth = true;
}
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* dest = doc.FirstChildElement("obj")->FirstChildElement("dest");
void DestroyableComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* dest = doc->FirstChildElement("obj")->FirstChildElement("dest");
if (!dest) {
LOG("Failed to find dest tag!");
return;

View File

@@ -26,8 +26,8 @@ public:
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
/**
* Initializes the component using a different LOT

View File

@@ -38,7 +38,7 @@
#include "CDObjectSkillsTable.h"
#include "CDSkillBehaviorTable.h"
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) {
this->m_Dirty = true;
this->m_Equipped = {};
this->m_Pushed = {};
@@ -48,8 +48,7 @@ InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
const auto lot = parent->GetLOT();
if (lot == 1) {
auto* character = m_Parent->GetCharacter();
if (character) LoadXml(character->GetXMLDoc());
LoadXml(document);
CheckProxyIntegrity();
@@ -473,10 +472,10 @@ bool InventoryComponent::HasSpaceForLoot(const std::unordered_map<LOT, int32_t>&
return true;
}
void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
void InventoryComponent::LoadXml(tinyxml2::XMLDocument* document) {
LoadPetXml(document);
auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv");
if (inventoryElement == nullptr) {
LOG("Failed to find 'inv' xml element!");
@@ -595,10 +594,10 @@ void InventoryComponent::LoadXml(const tinyxml2::XMLDocument& document) {
}
}
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
UpdatePetXml(document);
auto* inventoryElement = document.FirstChildElement("obj")->FirstChildElement("inv");
auto* inventoryElement = document->FirstChildElement("obj")->FirstChildElement("inv");
if (inventoryElement == nullptr) {
LOG("Failed to find 'inv' xml element!");
@@ -632,7 +631,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
bags->DeleteChildren();
for (const auto* inventory : inventoriesToSave) {
auto* bag = document.NewElement("b");
auto* bag = document->NewElement("b");
bag->SetAttribute("t", inventory->GetType());
bag->SetAttribute("m", static_cast<unsigned int>(inventory->GetSize()));
@@ -655,14 +654,14 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
continue;
}
auto* bagElement = document.NewElement("in");
auto* bagElement = document->NewElement("in");
bagElement->SetAttribute("t", inventory->GetType());
for (const auto& pair : inventory->GetItems()) {
auto* item = pair.second;
auto* itemElement = document.NewElement("i");
auto* itemElement = document->NewElement("i");
itemElement->SetAttribute("l", item->GetLot());
itemElement->SetAttribute("id", item->GetId());
@@ -681,7 +680,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
continue;
}
auto* extraInfo = document.NewElement("x");
auto* extraInfo = document->NewElement("x");
extraInfo->SetAttribute("ma", data->GetString(false).c_str());
@@ -696,20 +695,22 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
}
void InventoryComponent::Serialize(RakNet::BitStream& outBitStream, const bool bIsInitialUpdate) {
// LWOInventoryComponent_EquippedItem
outBitStream.Write(bIsInitialUpdate || m_Dirty);
if (bIsInitialUpdate || m_Dirty) {
outBitStream.Write(true);
outBitStream.Write<uint32_t>(m_Equipped.size());
for (const auto& pair : m_Equipped) {
const auto item = pair.second;
if (bIsInitialUpdate) AddItemSkills(item.lot);
if (bIsInitialUpdate) {
AddItemSkills(item.lot);
}
outBitStream.Write(item.id);
outBitStream.Write(item.lot);
outBitStream.Write0(); // subkey
outBitStream.Write0();
outBitStream.Write(item.count > 0);
if (item.count > 0) outBitStream.Write(item.count);
@@ -717,7 +718,7 @@ void InventoryComponent::Serialize(RakNet::BitStream& outBitStream, const bool b
outBitStream.Write(item.slot != 0);
if (item.slot != 0) outBitStream.Write<uint16_t>(item.slot);
outBitStream.Write0(); // inventory type
outBitStream.Write0();
bool flag = !item.config.empty();
outBitStream.Write(flag);
@@ -744,21 +745,11 @@ void InventoryComponent::Serialize(RakNet::BitStream& outBitStream, const bool b
}
m_Dirty = false;
} else {
outBitStream.Write(false);
}
// EquippedModelTransform
outBitStream.Write(false);
/*
outBitStream.Write(bIsInitialUpdate || m_Dirty); // Same dirty or different?
if (bIsInitialUpdate || m_Dirty) {
outBitStream.Write<uint32_t>(m_Equipped.size()); // Equiped models?
for (const auto& [location, item] : m_Equipped) {
outBitStream.Write(item.id);
outBitStream.Write(item.pos);
outBitStream.Write(item.rot);
}
}
*/
}
void InventoryComponent::Update(float deltaTime) {
@@ -1551,8 +1542,8 @@ void InventoryComponent::PurgeProxies(Item* item) {
}
}
void InventoryComponent::LoadPetXml(const tinyxml2::XMLDocument& document) {
auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
void InventoryComponent::LoadPetXml(tinyxml2::XMLDocument* document) {
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet");
if (petInventoryElement == nullptr) {
m_Pets.clear();
@@ -1583,19 +1574,19 @@ void InventoryComponent::LoadPetXml(const tinyxml2::XMLDocument& document) {
}
}
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument& document) {
auto* petInventoryElement = document.FirstChildElement("obj")->FirstChildElement("pet");
void InventoryComponent::UpdatePetXml(tinyxml2::XMLDocument* document) {
auto* petInventoryElement = document->FirstChildElement("obj")->FirstChildElement("pet");
if (petInventoryElement == nullptr) {
petInventoryElement = document.NewElement("pet");
petInventoryElement = document->NewElement("pet");
document.FirstChildElement("obj")->LinkEndChild(petInventoryElement);
document->FirstChildElement("obj")->LinkEndChild(petInventoryElement);
}
petInventoryElement->DeleteChildren();
for (const auto& pet : m_Pets) {
auto* petElement = document.NewElement("p");
auto* petElement = document->NewElement("p");
petElement->SetAttribute("id", pet.first);
petElement->SetAttribute("l", pet.second.lot);

View File

@@ -38,12 +38,12 @@ enum class eItemType : int32_t;
class InventoryComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
InventoryComponent(Entity* parent);
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
void Update(float deltaTime) override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
void LoadXml(const tinyxml2::XMLDocument& document);
void UpdateXml(tinyxml2::XMLDocument& document) override;
void LoadXml(tinyxml2::XMLDocument* document);
void UpdateXml(tinyxml2::XMLDocument* document) override;
/**
* 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
* @param document the xml doc to save to
*/
void LoadPetXml(const tinyxml2::XMLDocument& document);
void LoadPetXml(tinyxml2::XMLDocument* document);
/**
* Loads all the pet information from an xml doc into items
* @param document the xml doc to load from
*/
void UpdatePetXml(tinyxml2::XMLDocument& document);
void UpdatePetXml(tinyxml2::XMLDocument* document);
};
#endif

View File

@@ -2,16 +2,4 @@
void ItemComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
outBitStream.Write0();
/*
outBitStream.Write(isConstruction || m_Dirty); // Same dirty or different?
if (isConstruction || m_Dirty) {
outBitStream.Write(m_parent->GetObjectID());
outBitStream.Write(moderationStatus);
outBitStream.Write(!description.empty());
if (!description.empty()) {
outBitStream.Write<uint32_t>(description.size());
outBitStream.Write(description) // u16string
}
}
*/
}

View File

@@ -13,8 +13,8 @@ LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component
m_CharacterVersion = eCharacterVersion::LIVE;
}
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
tinyxml2::XMLElement* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl");
if (!level) {
LOG("Failed to find lvl tag while updating XML!");
return;
@@ -24,8 +24,8 @@ void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion));
}
void LevelProgressionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* level = doc.FirstChildElement("obj")->FirstChildElement("lvl");
void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
tinyxml2::XMLElement* level = doc->FirstChildElement("obj")->FirstChildElement("lvl");
if (!level) {
LOG("Failed to find lvl tag while loading XML!");
return;

View File

@@ -27,13 +27,13 @@ public:
* Save data from this componennt to character XML
* @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
* @param doc the document to read data from
*/
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
/**
* Gets the current level of the entity

View File

@@ -0,0 +1,5 @@
#include "MiniGameControlComponent.h"
void MiniGameControlComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
outBitStream.Write<uint32_t>(0x40000000);
}

View File

@@ -1,13 +1,15 @@
#ifndef __MINIGAMECONTROLCOMPONENT__H__
#define __MINIGAMECONTROLCOMPONENT__H__
#include "ActivityComponent.h"
#include "Component.h"
#include "eReplicaComponentType.h"
class MiniGameControlComponent final : public ActivityComponent {
class MiniGameControlComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
MiniGameControlComponent(Entity* parent, LOT lot) : ActivityComponent(parent, lot) {}
MiniGameControlComponent(Entity* parent) : Component(parent) {}
void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);
};
#endif //!__MINIGAMECONTROLCOMPONENT__H__

View File

@@ -504,8 +504,10 @@ bool MissionComponent::RequiresItem(const LOT lot) {
}
void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* mis = doc.FirstChildElement("obj")->FirstChildElement("mis");
void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
if (doc == nullptr) return;
auto* mis = doc->FirstChildElement("obj")->FirstChildElement("mis");
if (mis == nullptr) return;
@@ -521,7 +523,7 @@ void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* mission = new Mission(this, missionId);
mission->LoadFromXml(*doneM);
mission->LoadFromXml(doneM);
doneM = doneM->NextSiblingElement();
@@ -538,7 +540,7 @@ void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
auto* mission = new Mission(this, missionId);
mission->LoadFromXml(*currentM);
mission->LoadFromXml(currentM);
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
mission->SetUniqueMissionOrderID(missionOrder);
@@ -552,23 +554,25 @@ void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
}
void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
if (doc == nullptr) return;
auto shouldInsertMis = false;
auto* obj = doc.FirstChildElement("obj");
auto* obj = doc->FirstChildElement("obj");
auto* mis = obj->FirstChildElement("mis");
if (mis == nullptr) {
mis = doc.NewElement("mis");
mis = doc->NewElement("mis");
shouldInsertMis = true;
}
mis->DeleteChildren();
auto* done = doc.NewElement("done");
auto* cur = doc.NewElement("cur");
auto* done = doc->NewElement("done");
auto* cur = doc->NewElement("cur");
for (const auto& pair : m_Missions) {
auto* mission = pair.second;
@@ -576,10 +580,10 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
if (mission) {
const auto complete = mission->IsComplete();
auto* m = doc.NewElement("m");
auto* m = doc->NewElement("m");
if (complete) {
mission->UpdateXml(*m);
mission->UpdateXml(m);
done->LinkEndChild(m);
@@ -587,7 +591,7 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
}
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
mission->UpdateXml(*m);
mission->UpdateXml(m);
cur->LinkEndChild(m);
}

View File

@@ -31,8 +31,8 @@ public:
explicit MissionComponent(Entity* parent);
~MissionComponent() override;
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
void UpdateXml(tinyxml2::XMLDocument& doc) override;
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
/**
* Returns all the missions for this entity, mapped by mission ID

View File

@@ -50,44 +50,9 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
m_CurrentSpeed = 0;
m_MaxSpeed = 0;
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) {
if (m_Paused) return;
if (m_PullingToPoint) {
const auto source = GetCurrentWaypoint();
@@ -116,65 +81,64 @@ void MovementAIComponent::Update(const float deltaTime) {
}
m_TimeTravelled += deltaTime;
SetPosition(ApproximateLocation());
if (m_TimeTravelled < m_TimeToTravel) return;
m_TimeTravelled = 0.0f;
const auto source = GetCurrentWaypoint();
SetPosition(source);
m_SourcePosition = source;
NiPoint3 velocity = NiPoint3Constant::ZERO;
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
{
m_NextWaypoint = GetCurrentWaypoint();
if (m_NextWaypoint == source) {
m_TimeToTravel = 0.0f;
} else {
m_CurrentSpeed = std::min(m_CurrentSpeed + m_Acceleration, 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.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));
goto nextAction;
}
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 {
// 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_Path) {
if (m_Path->pathBehavior == PathBehavior::Loop) {
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;
}
Stop();
return;
}
SetDestination(m_CurrentPath.top().position);
SetDestination(m_CurrentPath.top());
m_CurrentPath.pop();
}
nextAction:
SetVelocity(velocity);
Game::entityManager->SerializeEntity(m_Parent);
}
@@ -197,7 +161,7 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
}
NiPoint3 MovementAIComponent::ApproximateLocation() const {
auto source = m_SourcePosition;
auto source = m_Parent->GetPosition();
if (AtFinalWaypoint()) return source;
@@ -263,13 +227,13 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
m_PullPoint = point;
}
void MovementAIComponent::SetPath(std::vector<PathWaypoint> path) {
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) {
if (path.empty()) return;
std::for_each(path.rbegin(), path.rend() - 1, [this](const PathWaypoint& point) {
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) {
this->m_CurrentPath.push(point);
});
SetDestination(path.front().position);
SetDestination(path.front());
}
float MovementAIComponent::GetBaseSpeed(LOT lot) {
@@ -314,23 +278,6 @@ void MovementAIComponent::SetRotation(const NiQuaternion& 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) {
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
@@ -347,7 +294,7 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) {
}
}
void MovementAIComponent::SetDestination(const NiPoint3 destination) {
void MovementAIComponent::SetDestination(const NiPoint3& destination) {
if (m_PullingToPoint) return;
const auto location = ApproximateLocation();
@@ -356,8 +303,6 @@ void MovementAIComponent::SetDestination(const NiPoint3 destination) {
SetPosition(location);
}
m_SourcePosition = location;
std::vector<NiPoint3> computedPath;
if (dpWorld::IsLoaded()) {
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);
@@ -374,7 +319,8 @@ void MovementAIComponent::SetDestination(const NiPoint3 destination) {
auto step = delta / 10.0f;
for (int i = 0; i < 10; i++) {
start += step;
// TODO: Replace this with += when the NiPoint3::operator+= is fixed
start = start + step;
computedPath.push_back(start);
}

View File

@@ -14,14 +14,11 @@
#include "Logger.h"
#include "Component.h"
#include "eReplicaComponentType.h"
#include "Zone.h"
#include <vector>
class ControllablePhysicsComponent;
class BaseCombatAIComponent;
struct Path;
/**
* Information that describes the different variables used to make an entity move around
*/
@@ -64,8 +61,6 @@ public:
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
void SetPath(const std::string pathName);
void Update(float deltaTime) override;
/**
@@ -78,7 +73,7 @@ public:
* Set a destination point for the entity 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
@@ -194,13 +189,7 @@ public:
* Sets a path to follow for the AI
* @param path the path to follow
*/
void SetPath(std::vector<PathWaypoint> path);
void Pause();
void Resume();
NiPoint3 GetVelocity() const;
void SetPath(std::vector<NiPoint3> path);
/**
* Returns the base speed from the DB for a given LOT
@@ -312,15 +301,7 @@ private:
/**
* The path from the current position to the destination.
*/
std::stack<PathWaypoint> m_CurrentPath;
const Path* m_Path = nullptr;
NiPoint3 m_SourcePosition;
bool m_Paused;
NiPoint3 m_SavedVelocity;
std::stack<NiPoint3> m_CurrentPath;
};
#endif // MOVEMENTAICOMPONENT_H

View File

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

View File

@@ -187,7 +187,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : PhysicsCompon
//add fallback cube:
m_dpEntity = new dpEntity(m_Parent->GetObjectID(), 2.0f, 2.0f, 2.0f);
}
m_dpEntity->SetScale(m_Scale);
m_dpEntity->SetRotation(m_Rotation);
m_dpEntity->SetPosition(m_Position);
@@ -323,13 +323,14 @@ void PhantomPhysicsComponent::Update(float deltaTime) {
if (!m_dpEntity) return;
//Process enter events
for (const auto id : m_dpEntity->GetNewObjects()) {
ApplyCollisionEffect(id, m_EffectType, m_DirectionalMultiplier);
m_Parent->OnCollisionPhantom(id);
for (auto en : m_dpEntity->GetNewObjects()) {
if (!en) continue;
ApplyCollisionEffect(en->GetObjectID(), m_EffectType, m_DirectionalMultiplier);
m_Parent->OnCollisionPhantom(en->GetObjectID());
//If we are a respawn volume, inform the client:
if (m_IsRespawnVolume) {
auto* const entity = Game::entityManager->GetEntity(id);
auto entity = Game::entityManager->GetEntity(en->GetObjectID());
if (entity) {
GameMessages::SendPlayerReachedRespawnCheckpoint(entity, m_RespawnPos, m_RespawnRot);
@@ -340,9 +341,10 @@ void PhantomPhysicsComponent::Update(float deltaTime) {
}
//Process exit events
for (const auto id : m_dpEntity->GetRemovedObjects()) {
ApplyCollisionEffect(id, m_EffectType, 1.0f);
m_Parent->OnCollisionLeavePhantom(id);
for (auto en : m_dpEntity->GetRemovedObjects()) {
if (!en) continue;
ApplyCollisionEffect(en->GetObjectID(), m_EffectType, 1.0f);
m_Parent->OnCollisionLeavePhantom(en->GetObjectID());
}
}

View File

@@ -352,11 +352,16 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"userModelID", info.spawnerID));
info.nodes[0]->config.push_back(new LDFData<int>(u"modelType", 2));
info.nodes[0]->config.push_back(new LDFData<bool>(u"propertyObjectID", true));
info.nodes[0]->config.push_back(new LDFData<int>(u"componentWhitelist", 1));
auto ldfModelBehavior = new LDFData<LWOOBJID>(u"modelBehaviors", 0);
auto userModelID = new LDFData<LWOOBJID>(u"userModelID", info.spawnerID);
auto modelType = new LDFData<int>(u"modelType", 2);
auto propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
auto componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
info.nodes[0]->config.push_back(componentWhitelist);
info.nodes[0]->config.push_back(ldfModelBehavior);
info.nodes[0]->config.push_back(modelType);
info.nodes[0]->config.push_back(propertyObjectID);
info.nodes[0]->config.push_back(userModelID);
auto* model = spawner->Spawn();
@@ -580,17 +585,29 @@ void PropertyManagementComponent::Load() {
GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER);
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT);
settings.push_back(new LDFData<LWOOBJID>(u"blueprintid", blueprintID));
settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
settings.push_back(new LDFData<int>(u"modelType", 2));
settings.push_back(new LDFData<bool>(u"propertyObjectID", true));
settings.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id));
LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintid", blueprintID);
LDFBaseData* componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
LDFBaseData* modelType = new LDFData<int>(u"modelType", 2);
LDFBaseData* propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", databaseModel.id);
settings.push_back(ldfBlueprintID);
settings.push_back(componentWhitelist);
settings.push_back(modelType);
settings.push_back(propertyObjectID);
settings.push_back(userModelID);
} else {
settings.push_back(new LDFData<int>(u"modelType", 2));
settings.push_back(new LDFData<LWOOBJID>(u"userModelID", databaseModel.id));
settings.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
settings.push_back(new LDFData<bool>(u"propertyObjectID", true));
settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
auto modelType = new LDFData<int>(u"modelType", 2);
auto userModelID = new LDFData<LWOOBJID>(u"userModelID", databaseModel.id);
auto ldfModelBehavior = new LDFData<LWOOBJID>(u"modelBehaviors", 0);
auto propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
auto componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
settings.push_back(componentWhitelist);
settings.push_back(ldfModelBehavior);
settings.push_back(modelType);
settings.push_back(propertyObjectID);
settings.push_back(userModelID);
}
node->config = settings;

View File

@@ -5,7 +5,7 @@
#include "EntityManager.h"
#include "SimplePhysicsComponent.h"
const std::unordered_set<LWOOBJID> ProximityMonitorComponent::m_EmptyObjectSet = {};
const std::map<LWOOBJID, dpEntity*> ProximityMonitorComponent::m_EmptyObjectMap = {};
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) {
if (radiusSmall != -1 && radiusLarge != -1) {
@@ -38,41 +38,40 @@ void ProximityMonitorComponent::SetProximityRadius(dpEntity* entity, const std::
m_ProximitiesData.insert(std::make_pair(name, entity));
}
const std::unordered_set<LWOOBJID>& ProximityMonitorComponent::GetProximityObjects(const std::string& name) {
const auto iter = m_ProximitiesData.find(name);
const std::map<LWOOBJID, dpEntity*>& ProximityMonitorComponent::GetProximityObjects(const std::string& name) {
const auto& iter = m_ProximitiesData.find(name);
if (iter == m_ProximitiesData.cend()) {
return m_EmptyObjectSet;
if (iter == m_ProximitiesData.end()) {
return m_EmptyObjectMap;
}
return iter->second->GetCurrentlyCollidingObjects();
}
bool ProximityMonitorComponent::IsInProximity(const std::string& name, LWOOBJID objectID) {
const auto iter = m_ProximitiesData.find(name);
const auto& iter = m_ProximitiesData.find(name);
if (iter == m_ProximitiesData.cend()) {
if (iter == m_ProximitiesData.end()) {
return false;
}
const auto& collisions = iter->second->GetCurrentlyCollidingObjects();
const auto& collitions = iter->second->GetCurrentlyCollidingObjects();
return collisions.contains(objectID);
return collitions.find(objectID) != collitions.end();
}
void ProximityMonitorComponent::Update(float deltaTime) {
for (const auto& prox : m_ProximitiesData) {
if (!prox.second) continue;
prox.second->SetPosition(m_Parent->GetPosition());
//Process enter events
for (const auto id : prox.second->GetNewObjects()) {
m_Parent->OnCollisionProximity(id, prox.first, "ENTER");
for (auto* en : prox.second->GetNewObjects()) {
m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "ENTER");
}
//Process exit events
for (const auto id : prox.second->GetRemovedObjects()) {
m_Parent->OnCollisionProximity(id, prox.first, "LEAVE");
for (auto* en : prox.second->GetRemovedObjects()) {
m_Parent->OnCollisionProximity(en->GetObjectID(), prox.first, "LEAVE");
}
}
}

View File

@@ -6,8 +6,6 @@
#ifndef PROXIMITYMONITORCOMPONENT_H
#define PROXIMITYMONITORCOMPONENT_H
#include <unordered_set>
#include "BitStream.h"
#include "Entity.h"
#include "dpWorld.h"
@@ -44,9 +42,9 @@ public:
/**
* Returns the last of entities that are used to check proximity, given a name
* @param name the proximity name to retrieve physics objects for
* @return a set of physics entity object IDs for this name
* @return a map of physics entities for this name, indexed by object ID
*/
const std::unordered_set<LWOOBJID>& GetProximityObjects(const std::string& name);
const std::map<LWOOBJID, dpEntity*>& GetProximityObjects(const std::string& name);
/**
* Checks if the passed object is in proximity of the named proximity sensor
@@ -72,7 +70,7 @@ private:
/**
* Default value for the proximity data
*/
static const std::unordered_set<LWOOBJID> m_EmptyObjectSet;
static const std::map<LWOOBJID, dpEntity*> m_EmptyObjectMap;
};
#endif // PROXIMITYMONITORCOMPONENT_H

View File

@@ -2,6 +2,11 @@
#include "EntityManager.h"
#include "ScriptedActivityComponent.h"
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent) : Component(parent) {
}
ShootingGalleryComponent::~ShootingGalleryComponent() = default;
void ShootingGalleryComponent::SetStaticParams(const StaticShootingGalleryParams& params) {
m_StaticParams = params;
}
@@ -12,15 +17,20 @@ void ShootingGalleryComponent::SetDynamicParams(const DynamicShootingGalleryPara
Game::entityManager->SerializeEntity(m_Parent);
}
void ShootingGalleryComponent::SetCurrentPlayerID(LWOOBJID playerID) {
m_CurrentPlayerID = playerID;
m_Dirty = true;
AddActivityPlayerData(playerID);
};
void ShootingGalleryComponent::Serialize(RakNet::BitStream& outBitStream, bool isInitialUpdate) {
ActivityComponent::Serialize(outBitStream, isInitialUpdate);
// Start ScriptedActivityComponent
outBitStream.Write<bool>(true);
if (m_CurrentPlayerID == LWOOBJID_EMPTY) {
outBitStream.Write<uint32_t>(0);
} else {
outBitStream.Write<uint32_t>(1);
outBitStream.Write<LWOOBJID>(m_CurrentPlayerID);
for (size_t i = 0; i < 10; i++) {
outBitStream.Write<float_t>(0.0f);
}
}
// End ScriptedActivityComponent
if (isInitialUpdate) {
outBitStream.Write<float_t>(m_StaticParams.cameraPosition.GetX());

View File

@@ -2,7 +2,7 @@
#include "dCommonVars.h"
#include "NiPoint3.h"
#include "Entity.h"
#include "ActivityComponent.h"
#include "Component.h"
#include "eReplicaComponentType.h"
/**
@@ -71,11 +71,12 @@ struct StaticShootingGalleryParams {
* A very ancient component that was used to guide shooting galleries, it's still kind of used but a lot of logic is
* also in the related scripts.
*/
class ShootingGalleryComponent final : public ActivityComponent {
class ShootingGalleryComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
explicit ShootingGalleryComponent(Entity* parent, LOT lot) : ActivityComponent(parent, lot) {}
explicit ShootingGalleryComponent(Entity* parent);
~ShootingGalleryComponent();
void Serialize(RakNet::BitStream& outBitStream, bool isInitialUpdate) override;
/**
@@ -106,8 +107,13 @@ public:
* Sets the entity that's currently playing the shooting gallery
* @param playerID the entity to set
*/
void SetCurrentPlayerID(LWOOBJID playerID);
void SetCurrentPlayerID(LWOOBJID playerID) { m_CurrentPlayerID = playerID; m_Dirty = true; };
/**
* Returns the player that's currently playing the shooting gallery
* @return the player that's currently playing the shooting gallery
*/
LWOOBJID GetCurrentPlayerID() const { return m_CurrentPlayerID; };
private:
/**

View File

@@ -227,7 +227,7 @@ void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, B
this->m_managedProjectiles.push_back(entry);
}
bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID, const int32_t castType, const NiQuaternion rotationOverride) {
bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID) {
uint32_t behaviorId = -1;
// try to find it via the cache
const auto& pair = m_skillBehaviorCache.find(skillId);
@@ -247,19 +247,11 @@ bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LW
return false;
}
return CalculateBehavior(skillId, behaviorId, target, false, false, optionalOriginatorID, castType, rotationOverride).success;
return CalculateBehavior(skillId, behaviorId, target, false, false, optionalOriginatorID).success;
}
SkillExecutionResult SkillComponent::CalculateBehavior(
const uint32_t skillId,
const uint32_t behaviorId,
const LWOOBJID target,
const bool ignoreTarget,
const bool clientInitalized,
const LWOOBJID originatorOverride,
const int32_t castType,
const NiQuaternion rotationOverride) {
SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, const uint32_t behaviorId, const LWOOBJID target, const bool ignoreTarget, const bool clientInitalized, const LWOOBJID originatorOverride) {
RakNet::BitStream bitStream{};
auto* behavior = Behavior::CreateBehavior(behaviorId);
@@ -291,7 +283,7 @@ SkillExecutionResult SkillComponent::CalculateBehavior(
// Echo start skill
EchoStartSkill start;
start.iCastType = castType;
start.iCastType = 0;
start.skillID = skillId;
start.uiSkillHandle = context->skillUId;
start.optionalOriginatorID = context->originator;
@@ -302,10 +294,6 @@ SkillExecutionResult SkillComponent::CalculateBehavior(
if (originator != nullptr) {
start.originatorRot = originator->GetRotation();
}
if (rotationOverride != NiQuaternionConstant::IDENTITY) {
start.originatorRot = rotationOverride;
}
//start.optionalTargetID = target;
start.sBitStream.assign(reinterpret_cast<char*>(bitStream.GetData()), bitStream.GetNumberOfBytesUsed());
@@ -476,7 +464,7 @@ void SkillComponent::HandleUnCast(const uint32_t behaviorId, const LWOOBJID targ
behavior->UnCast(&context, { target });
}
SkillComponent::SkillComponent(Entity* parent) : Component(parent) {
SkillComponent::SkillComponent(Entity* parent): Component(parent) {
this->m_skillUid = 0;
}
@@ -486,32 +474,6 @@ SkillComponent::~SkillComponent() {
void SkillComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
if (bIsInitialUpdate) outBitStream.Write0();
/*
outBitStream.Write(bIsInitialUpdate && !m_managedBehaviors.empty());
if (bIsInitialUpdate && !m_managedBehaviors.empty()) {
outBitStream.Write<uint32_t>(m_managedBehaviors.size());
for (const auto& [id, skill] : m_managedBehaviors) {
outBitStream.Write(skill.skillUID);
outBitStream.Write(skill.skillID);
outBitStream.Write(skill.cast_type);
outBitStream.Write(skill.cancel_type);
outBitStream.Write(skill.behavior_count);
for (auto& index : skill.behavior_count) {
outBitStream.Write<uint32_t>(behaviorUID); // Maybe
outBitStream.Write<uint32_t>(action);
outBitStream.Write<uint32_t>(wait_time_ms);
outBitStream.Write<uint32_t>(template_id);
outBitStream.Write(casterObjId);
outBitStream.Write(originatorObjId);
outBitStream.Write(targetObjId);
outBitStream.Write<bool>(usedMouse);
outBitStream.Write(cooldown);
outBitStream.Write(charge_time);
outBitStream.Write(imagination_cost);
}
}
}
*/
}
/// <summary>

View File

@@ -127,7 +127,7 @@ public:
* @param optionalOriginatorID change the originator of the skill
* @return if the case succeeded
*/
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = NiQuaternionConstant::IDENTITY);
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY);
/**
* Initializes a server-side skill calculation.
@@ -139,7 +139,7 @@ public:
* @param originatorOverride an override for the originator of the skill calculation
* @return the result of the skill calculation
*/
SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY, const int32_t castType = 0, const NiQuaternion rotationOverride = NiQuaternionConstant::IDENTITY);
SkillExecutionResult CalculateBehavior(uint32_t skillId, uint32_t behaviorId, LWOOBJID target, bool ignoreTarget = false, bool clientInitalized = false, LWOOBJID originatorOverride = LWOOBJID_EMPTY);
/**
* Register a server-side projectile.

View File

@@ -15,9 +15,8 @@
#include "PlayerManager.h"
#include "Game.h"
#include "EntityManager.h"
#include "MovementAIComponent.h"
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo) : Component(parent) {
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo): Component(parent) {
m_Parent = parent;
m_Trigger = nullptr;
@@ -44,7 +43,7 @@ void TriggerComponent::TriggerEvent(eTriggerEventType event, Entity* optionalTar
}
void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) {
auto argArray = GeneralUtils::SplitString(command->args, ',');
auto argArray = GeneralUtils::SplitString(command->args, ',');
// determine targets
std::vector<Entity*> targetEntities = GatherTargets(command, optionalTarget);
@@ -56,119 +55,107 @@ void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity
if (!targetEntity) continue;
switch (command->id) {
case eTriggerCommandType::ZONE_PLAYER: break;
case eTriggerCommandType::FIRE_EVENT:
HandleFireEvent(targetEntity, command->args);
break;
case eTriggerCommandType::DESTROY_OBJ:
HandleDestroyObject(targetEntity, command->args);
break;
case eTriggerCommandType::TOGGLE_TRIGGER:
HandleToggleTrigger(targetEntity, command->args);
break;
case eTriggerCommandType::RESET_REBUILD:
HandleResetRebuild(targetEntity, command->args);
break;
case eTriggerCommandType::SET_PATH:
HandleSetPath(targetEntity, argArray);
break;
case eTriggerCommandType::SET_PICK_TYPE: break;
case eTriggerCommandType::MOVE_OBJECT:
HandleMoveObject(targetEntity, argArray);
break;
case eTriggerCommandType::ROTATE_OBJECT:
HandleRotateObject(targetEntity, argArray);
break;
case eTriggerCommandType::PUSH_OBJECT:
HandlePushObject(targetEntity, argArray);
break;
case eTriggerCommandType::REPEL_OBJECT:
HandleRepelObject(targetEntity, command->args);
break;
case eTriggerCommandType::SET_TIMER:
HandleSetTimer(targetEntity, argArray);
break;
case eTriggerCommandType::CANCEL_TIMER:
HandleCancelTimer(targetEntity, command->args);
break;
case eTriggerCommandType::PLAY_CINEMATIC:
HandlePlayCinematic(targetEntity, argArray);
break;
case eTriggerCommandType::TOGGLE_BBB:
HandleToggleBBB(targetEntity, command->args);
break;
case eTriggerCommandType::UPDATE_MISSION:
HandleUpdateMission(targetEntity, argArray);
break;
case eTriggerCommandType::SET_BOUNCER_STATE: break;
case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break;
case eTriggerCommandType::TURN_AROUND_ON_PATH:
HandleTurnAroundOnPath(targetEntity);
break;
case eTriggerCommandType::GO_FORWARD_ON_PATH:
HandleGoForwardOnPath(targetEntity);
break;
case eTriggerCommandType::GO_BACKWARD_ON_PATH:
HandleGoBackwardOnPath(targetEntity);
break;
case eTriggerCommandType::STOP_PATHING:
HandleStopPathing(targetEntity);
break;
case eTriggerCommandType::START_PATHING:
HandleStartPathing(targetEntity);
break;
case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break;
case eTriggerCommandType::PLAY_EFFECT:
HandlePlayEffect(targetEntity, argArray);
break;
case eTriggerCommandType::STOP_EFFECT:
GameMessages::SendStopFXEffect(targetEntity, true, command->args);
break;
case eTriggerCommandType::CAST_SKILL:
HandleCastSkill(targetEntity, command->args);
break;
case eTriggerCommandType::DISPLAY_ZONE_SUMMARY:
GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID());
break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT:
HandleSetPhysicsVolumeEffect(targetEntity, argArray);
break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS:
HandleSetPhysicsVolumeStatus(targetEntity, command->args);
break;
case eTriggerCommandType::SET_MODEL_TO_BUILD: break;
case eTriggerCommandType::SPAWN_MODEL_BRICKS: break;
case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK:
HandleActivateSpawnerNetwork(command->args);
break;
case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK:
HandleDeactivateSpawnerNetwork(command->args);
break;
case eTriggerCommandType::RESET_SPAWNER_NETWORK:
HandleResetSpawnerNetwork(command->args);
break;
case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS:
HandleDestroySpawnerNetworkObjects(command->args);
break;
case eTriggerCommandType::GO_TO_WAYPOINT: break;
case eTriggerCommandType::ACTIVATE_PHYSICS:
HandleActivatePhysics(targetEntity, command->args);
break;
case eTriggerCommandType::ZONE_PLAYER: break;
case eTriggerCommandType::FIRE_EVENT:
HandleFireEvent(targetEntity, command->args);
break;
case eTriggerCommandType::DESTROY_OBJ:
HandleDestroyObject(targetEntity, command->args);
break;
case eTriggerCommandType::TOGGLE_TRIGGER:
HandleToggleTrigger(targetEntity, command->args);
break;
case eTriggerCommandType::RESET_REBUILD:
HandleResetRebuild(targetEntity, command->args);
break;
case eTriggerCommandType::SET_PATH: break;
case eTriggerCommandType::SET_PICK_TYPE: break;
case eTriggerCommandType::MOVE_OBJECT:
HandleMoveObject(targetEntity, argArray);
break;
case eTriggerCommandType::ROTATE_OBJECT:
HandleRotateObject(targetEntity, argArray);
break;
case eTriggerCommandType::PUSH_OBJECT:
HandlePushObject(targetEntity, argArray);
break;
case eTriggerCommandType::REPEL_OBJECT:
HandleRepelObject(targetEntity, command->args);
break;
case eTriggerCommandType::SET_TIMER:
HandleSetTimer(targetEntity, argArray);
break;
case eTriggerCommandType::CANCEL_TIMER:
HandleCancelTimer(targetEntity, command->args);
break;
case eTriggerCommandType::PLAY_CINEMATIC:
HandlePlayCinematic(targetEntity, argArray);
break;
case eTriggerCommandType::TOGGLE_BBB:
HandleToggleBBB(targetEntity, command->args);
break;
case eTriggerCommandType::UPDATE_MISSION:
HandleUpdateMission(targetEntity, argArray);
break;
case eTriggerCommandType::SET_BOUNCER_STATE: break;
case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break;
case eTriggerCommandType::TURN_AROUND_ON_PATH: break;
case eTriggerCommandType::GO_FORWARD_ON_PATH: break;
case eTriggerCommandType::GO_BACKWARD_ON_PATH: break;
case eTriggerCommandType::STOP_PATHING: break;
case eTriggerCommandType::START_PATHING: break;
case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break;
case eTriggerCommandType::PLAY_EFFECT:
HandlePlayEffect(targetEntity, argArray);
break;
case eTriggerCommandType::STOP_EFFECT:
GameMessages::SendStopFXEffect(targetEntity, true, command->args);
break;
case eTriggerCommandType::CAST_SKILL:
HandleCastSkill(targetEntity, command->args);
break;
case eTriggerCommandType::DISPLAY_ZONE_SUMMARY:
GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID());
break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT:
HandleSetPhysicsVolumeEffect(targetEntity, argArray);
break;
case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS:
HandleSetPhysicsVolumeStatus(targetEntity, command->args);
break;
case eTriggerCommandType::SET_MODEL_TO_BUILD: break;
case eTriggerCommandType::SPAWN_MODEL_BRICKS: break;
case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK:
HandleActivateSpawnerNetwork(command->args);
break;
case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK:
HandleDeactivateSpawnerNetwork(command->args);
break;
case eTriggerCommandType::RESET_SPAWNER_NETWORK:
HandleResetSpawnerNetwork(command->args);
break;
case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS:
HandleDestroySpawnerNetworkObjects(command->args);
break;
case eTriggerCommandType::GO_TO_WAYPOINT: break;
case eTriggerCommandType::ACTIVATE_PHYSICS:
HandleActivatePhysics(targetEntity, command->args);
break;
// DEPRECATED BLOCK START
case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break;
case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break;
case eTriggerCommandType::FLASH_MUSIC_CUE: break;
case eTriggerCommandType::SET_MUSIC_PARAMETER: break;
case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break;
case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break;
case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break;
case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break;
case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break;
case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break;
case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break;
case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break;
case eTriggerCommandType::FLASH_MUSIC_CUE: break;
case eTriggerCommandType::SET_MUSIC_PARAMETER: break;
case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break;
case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break;
case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break;
case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break;
case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break;
case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break;
// DEPRECATED BLOCK END
default:
LOG_DEBUG("Event %i was not handled!", command->id);
break;
default:
LOG_DEBUG("Event %i was not handled!", command->id);
break;
}
}
}
@@ -177,25 +164,20 @@ std::vector<Entity*> TriggerComponent::GatherTargets(LUTriggers::Command* comman
std::vector<Entity*> entities = {};
if (command->target == "self") entities.push_back(m_Parent);
else if (command->target == "zone") {
/*TODO*/
} else if (command->target == "target" && optionalTarget) {
entities.push_back(optionalTarget);
} else if (command->target == "targetTeam" && optionalTarget) {
else if (command->target == "zone") { /*TODO*/ }
else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget);
else if (command->target == "targetTeam" && optionalTarget) {
auto* team = TeamManager::Instance()->GetTeam(optionalTarget->GetObjectID());
for (const auto memberId : team->members) {
auto* member = Game::entityManager->GetEntity(memberId);
if (member) entities.push_back(member);
}
} else if (command->target == "objGroup") {
entities = Game::entityManager->GetEntitiesInGroup(command->targetName);
} else if (command->target == "allPlayers") {
} else if (command->target == "objGroup") entities = Game::entityManager->GetEntitiesInGroup(command->targetName);
else if (command->target == "allPlayers") {
for (auto* player : PlayerManager::GetAllPlayers()) {
entities.push_back(player);
}
} else if (command->target == "allNPCs") {
/*UNUSED*/
}
} else if (command->target == "allNPCs") { /*UNUSED*/ }
return entities;
}
@@ -204,12 +186,12 @@ void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) {
targetEntity->GetScript()->OnFireEventServerSide(targetEntity, m_Parent, args, 0, 0, 0);
}
void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args) {
void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args){
const eKillType killType = GeneralUtils::TryParse<eKillType>(args).value_or(eKillType::VIOLENT);
targetEntity->Smash(m_Parent->GetObjectID(), killType);
}
void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args) {
void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args){
auto* triggerComponent = targetEntity->GetComponent<TriggerComponent>();
if (!triggerComponent) {
LOG_DEBUG("Trigger component not found!");
@@ -218,7 +200,7 @@ void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string arg
triggerComponent->SetTriggerEnabled(args == "1");
}
void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args) {
void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args){
auto* quickBuildComponent = targetEntity->GetComponent<QuickBuildComponent>();
if (!quickBuildComponent) {
LOG_DEBUG("Rebuild component not found!");
@@ -227,7 +209,7 @@ void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args
quickBuildComponent->ResetQuickBuild(args == "1");
}
void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray) {
void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() <= 2) return;
NiPoint3 position = targetEntity->GetPosition();
@@ -237,7 +219,7 @@ void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::s
targetEntity->SetPosition(position);
}
void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray) {
void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() <= 2) return;
const NiPoint3 vector = GeneralUtils::TryParse<NiPoint3>(argArray).value_or(NiPoint3Constant::ZERO);
@@ -246,7 +228,7 @@ void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std:
targetEntity->SetRotation(rotation);
}
void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray) {
void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() < 3) return;
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
@@ -264,7 +246,7 @@ void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::s
}
void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args) {
void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args){
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
if (!phantomPhysicsComponent) {
LOG_DEBUG("Phantom Physics component not found!");
@@ -288,7 +270,7 @@ void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args)
Game::entityManager->SerializeEntity(m_Parent);
}
void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::string> argArray) {
void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::string> argArray){
if (argArray.size() != 2) {
LOG_DEBUG("Not enough variables!");
return;
@@ -297,7 +279,7 @@ void TriggerComponent::HandleSetTimer(Entity* targetEntity, std::vector<std::str
m_Parent->AddTimer(argArray.at(0), time);
}
void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args) {
void TriggerComponent::HandleCancelTimer(Entity* targetEntity, std::string args){
m_Parent->CancelTimer(args);
}
@@ -345,7 +327,7 @@ void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vector<std
// then we need a good way to convert this from a string to that enum
if (argArray.at(0) != "exploretask") return;
MissionComponent* missionComponent = targetEntity->GetComponent<MissionComponent>();
if (!missionComponent) {
if (!missionComponent){
LOG_DEBUG("Mission component not found!");
return;
}
@@ -357,7 +339,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::s
const auto effectID = GeneralUtils::TryParse<int32_t>(argArray.at(1));
if (!effectID) return;
std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2));
float priority = 1;
if (argArray.size() == 4) {
priority = GeneralUtils::TryParse<float>(argArray.at(3)).value_or(priority);
@@ -366,7 +348,7 @@ void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::s
GameMessages::SendPlayFXEffect(targetEntity, effectID.value(), effectType, argArray.at(0), LWOOBJID_EMPTY, priority);
}
void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args) {
void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args){
auto* skillComponent = targetEntity->GetComponent<SkillComponent>();
if (!skillComponent) {
LOG_DEBUG("Skill component not found!");
@@ -394,7 +376,7 @@ void TriggerComponent::HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::v
phantomPhysicsComponent->SetEffectType(effectType);
phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1)));
if (argArray.size() > 4) {
const NiPoint3 direction =
const NiPoint3 direction =
GeneralUtils::TryParse<NiPoint3>(argArray.at(2), argArray.at(3), argArray.at(4)).value_or(NiPoint3Constant::ZERO);
phantomPhysicsComponent->SetDirection(direction);
@@ -420,25 +402,25 @@ void TriggerComponent::HandleSetPhysicsVolumeStatus(Entity* targetEntity, std::s
Game::entityManager->SerializeEntity(targetEntity);
}
void TriggerComponent::HandleActivateSpawnerNetwork(std::string args) {
void TriggerComponent::HandleActivateSpawnerNetwork(std::string args){
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->Activate();
}
}
void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args) {
void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args){
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->Deactivate();
}
}
void TriggerComponent::HandleResetSpawnerNetwork(std::string args) {
void TriggerComponent::HandleResetSpawnerNetwork(std::string args){
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->Reset();
}
}
void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args) {
void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){
for (auto* spawner : Game::zoneManager->GetSpawnersByName(args)) {
if (spawner) spawner->DestroyAllEntities();
}
@@ -447,50 +429,9 @@ void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args) {
void TriggerComponent::HandleActivatePhysics(Entity* targetEntity, std::string args) {
if (args == "true") {
// TODO add physics entity if there isn't one
} else if (args == "false") {
} else if (args == "false"){
// TODO remove Phsyics entity if there is one
} else {
LOG_DEBUG("Invalid argument for ActivatePhysics Trigger: %s", args.c_str());
}
}
void TriggerComponent::HandleSetPath(Entity* targetEntity, std::vector<std::string> argArray) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// movementAIComponent->SetupPath(argArray.at(0));
if (argArray.size() >= 2) {
auto index = GeneralUtils::TryParse<int32_t>(argArray.at(1));
if (!index) return;
// movementAIComponent->SetPathStartingWaypointIndex(index.value());
}
if (argArray.size() >= 3 && argArray.at(2) == "1") {
// movementAIComponent->ReversePath();
}
}
void TriggerComponent::HandleTurnAroundOnPath(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
// if (movementAIComponent) movementAIComponent->ReversePath();
}
void TriggerComponent::HandleGoForwardOnPath(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// if (movementAIComponent->GetIsInReverse()) movementAIComponent->ReversePath();
}
void TriggerComponent::HandleGoBackwardOnPath(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return;
// if (!movementAIComponent->GetIsInReverse()) movementAIComponent->ReversePath();
}
void TriggerComponent::HandleStopPathing(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
// if (movementAIComponent) movementAIComponent->Pause();
}
void TriggerComponent::HandleStartPathing(Entity* targetEntity) {
auto* movementAIComponent = targetEntity->GetComponent<MovementAIComponent>();
// if (movementAIComponent) movementAIComponent->Resume();
}

View File

@@ -44,12 +44,6 @@ private:
void HandleResetSpawnerNetwork(std::string args);
void HandleDestroySpawnerNetworkObjects(std::string args);
void HandleActivatePhysics(Entity* targetEntity, std::string args);
void HandleTurnAroundOnPath(Entity* targetEntity);
void HandleGoForwardOnPath(Entity* targetEntity);
void HandleGoBackwardOnPath(Entity* targetEntity);
void HandleStopPathing(Entity* targetEntity);
void HandleStartPathing(Entity* targetEntity);
void HandleSetPath(Entity* targetEntity, std::vector<std::string> argArray);
LUTriggers::Trigger* m_Trigger;
};

View File

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

View File

@@ -2663,11 +2663,17 @@ void GameMessages::HandleBBBSaveRequest(RakNet::BitStream& inStream, Entity* ent
info.spawnerID = entity->GetObjectID();
info.spawnerNodeID = 0;
info.settings.push_back(new LDFData<LWOOBJID>(u"blueprintid", blueprintID));
info.settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
info.settings.push_back(new LDFData<int>(u"modelType", 2));
info.settings.push_back(new LDFData<bool>(u"propertyObjectID", true));
info.settings.push_back(new LDFData<LWOOBJID>(u"userModelID", newIDL));
LDFBaseData* ldfBlueprintID = new LDFData<LWOOBJID>(u"blueprintid", blueprintID);
LDFBaseData* componentWhitelist = new LDFData<int>(u"componentWhitelist", 1);
LDFBaseData* modelType = new LDFData<int>(u"modelType", 2);
LDFBaseData* propertyObjectID = new LDFData<bool>(u"propertyObjectID", true);
LDFBaseData* userModelID = new LDFData<LWOOBJID>(u"userModelID", newIDL);
info.settings.push_back(ldfBlueprintID);
info.settings.push_back(componentWhitelist);
info.settings.push_back(modelType);
info.settings.push_back(propertyObjectID);
info.settings.push_back(userModelID);
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
if (newEntity) {
@@ -4660,7 +4666,7 @@ void GameMessages::HandleBuyFromVendor(RakNet::BitStream& inStream, Entity* enti
if (!user) return;
Entity* player = Game::entityManager->GetEntity(user->GetLoggedInChar());
if (!player) return;
// handle buying normal items
auto* vendorComponent = entity->GetComponent<VendorComponent>();
if (vendorComponent) {
@@ -5290,7 +5296,7 @@ void GameMessages::HandleRemoveItemFromInventory(RakNet::BitStream& inStream, En
bool iLootTypeSourceIsDefault = false;
LWOOBJID iLootTypeSource = LWOOBJID_EMPTY;
bool iObjIDIsDefault = false;
LWOOBJID iObjID = LWOOBJID_EMPTY;
LWOOBJID iObjID;
bool iObjTemplateIsDefault = false;
LOT iObjTemplate = LOT_NULL;
bool iRequestingObjIDIsDefault = false;
@@ -6197,15 +6203,3 @@ void GameMessages::HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Ent
if (!characterComponent) return;
characterComponent->SetCurrentInteracting(LWOOBJID_EMPTY);
}
void GameMessages::SendSlashCommandFeedbackText(Entity* entity, std::u16string text) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(entity->GetObjectID());
bitStream.Write(eGameMessageType::SLASH_COMMAND_TEXT_FEEDBACK);
bitStream.Write<uint32_t>(text.size());
bitStream.Write(text);
auto sysAddr = entity->GetSystemAddress();
SEND_PACKET;
}

View File

@@ -664,8 +664,6 @@ namespace GameMessages {
void HandleRemoveDonationItem(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
void HandleConfirmDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity);
void HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity);
void SendSlashCommandFeedbackText(Entity* entity, std::u16string text);
};
#endif // GAMEMESSAGES_H

View File

@@ -65,24 +65,24 @@ Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) {
}
}
void Mission::LoadFromXml(const tinyxml2::XMLElement& element) {
void Mission::LoadFromXml(tinyxml2::XMLElement* element) {
// Start custom XML
if (element.Attribute("state") != nullptr) {
m_State = static_cast<eMissionState>(std::stoul(element.Attribute("state")));
if (element->Attribute("state") != nullptr) {
m_State = static_cast<eMissionState>(std::stoul(element->Attribute("state")));
}
// End custom XML
if (element.Attribute("cct") != nullptr) {
m_Completions = std::stoul(element.Attribute("cct"));
if (element->Attribute("cct") != nullptr) {
m_Completions = std::stoul(element->Attribute("cct"));
m_Timestamp = std::stoul(element.Attribute("cts"));
m_Timestamp = std::stoul(element->Attribute("cts"));
if (IsComplete()) {
return;
}
}
auto* task = element.FirstChildElement();
auto* task = element->FirstChildElement();
auto index = 0U;
@@ -132,19 +132,19 @@ void Mission::LoadFromXml(const tinyxml2::XMLElement& element) {
}
}
void Mission::UpdateXml(tinyxml2::XMLElement& element) {
void Mission::UpdateXml(tinyxml2::XMLElement* element) {
// Start custom XML
element.SetAttribute("state", static_cast<unsigned int>(m_State));
element->SetAttribute("state", static_cast<unsigned int>(m_State));
// End custom XML
element.DeleteChildren();
element->DeleteChildren();
element.SetAttribute("id", static_cast<unsigned int>(info.id));
element->SetAttribute("id", static_cast<unsigned int>(info.id));
if (m_Completions > 0) {
element.SetAttribute("cct", static_cast<unsigned int>(m_Completions));
element->SetAttribute("cct", static_cast<unsigned int>(m_Completions));
element.SetAttribute("cts", static_cast<unsigned int>(m_Timestamp));
element->SetAttribute("cts", static_cast<unsigned int>(m_Timestamp));
if (IsComplete()) {
return;
@@ -155,27 +155,27 @@ void Mission::UpdateXml(tinyxml2::XMLElement& element) {
if (task->GetType() == eMissionTaskType::COLLECTION ||
task->GetType() == eMissionTaskType::VISIT_PROPERTY) {
auto* child = element.GetDocument()->NewElement("sv");
auto* child = element->GetDocument()->NewElement("sv");
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
element.LinkEndChild(child);
element->LinkEndChild(child);
for (auto unique : task->GetUnique()) {
auto* uniqueElement = element.GetDocument()->NewElement("sv");
auto* uniqueElement = element->GetDocument()->NewElement("sv");
uniqueElement->SetAttribute("v", static_cast<unsigned int>(unique));
element.LinkEndChild(uniqueElement);
element->LinkEndChild(uniqueElement);
}
break;
}
auto* child = element.GetDocument()->NewElement("sv");
auto* child = element->GetDocument()->NewElement("sv");
child->SetAttribute("v", static_cast<unsigned int>(task->GetProgress()));
element.LinkEndChild(child);
element->LinkEndChild(child);
}
}

View File

@@ -28,8 +28,8 @@ public:
Mission(MissionComponent* missionComponent, uint32_t missionId);
~Mission();
void LoadFromXml(const tinyxml2::XMLElement& element);
void UpdateXml(tinyxml2::XMLElement& element);
void LoadFromXml(tinyxml2::XMLElement* element);
void UpdateXml(tinyxml2::XMLElement* element);
/**
* Returns the ID of this mission

Some files were not shown because too many files have changed in this diff Show More