mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-07-04 10:39:55 +00:00
Merge branch 'main' into npc-pathing
This commit is contained in:
commit
8388fdf2a7
26
.github/workflows/build-and-test.yml
vendored
26
.github/workflows/build-and-test.yml
vendored
@ -36,22 +36,16 @@ jobs:
|
|||||||
testPreset: "ci-${{matrix.os}}"
|
testPreset: "ci-${{matrix.os}}"
|
||||||
- name: artifacts
|
- name: artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
if: ${{ github.ref == 'ref/head/main' }}
|
|
||||||
with:
|
with:
|
||||||
name: build-${{matrix.os}}
|
name: build-${{matrix.os}}
|
||||||
path: |
|
path: |
|
||||||
build
|
build/*Server*
|
||||||
!build/tests
|
build/*.ini
|
||||||
!build/Testing
|
build/*.so
|
||||||
!build/CMakeFiles
|
build/*.dll
|
||||||
!build/DartConfiguration.tcl
|
build/vanity/
|
||||||
!build/CTestTestfile.cmake
|
build/navmeshes/
|
||||||
!build/CMakeCache.txt
|
build/migrations/
|
||||||
!build/build.ninja
|
build/*.dcf
|
||||||
!build/_deps
|
!build/*.pdb
|
||||||
!build/cmake_install.cmake
|
!build/d*/
|
||||||
!build/*.a
|
|
||||||
!build/*.lib
|
|
||||||
!build/*.dir
|
|
||||||
!build/*.vcxproj
|
|
||||||
!build/*.vcxproj.filters
|
|
||||||
|
@ -97,15 +97,56 @@ make_directory(${CMAKE_BINARY_DIR}/logs)
|
|||||||
|
|
||||||
# Copy resource files on first build
|
# Copy resource files on first build
|
||||||
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
set(RESOURCE_FILES "sharedconfig.ini" "authconfig.ini" "chatconfig.ini" "worldconfig.ini" "masterconfig.ini" "blacklist.dcf")
|
||||||
|
message(STATUS "Checking resource file integrity")
|
||||||
foreach (resource_file ${RESOURCE_FILES})
|
foreach (resource_file ${RESOURCE_FILES})
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
set(file_size 0)
|
||||||
|
if (EXISTS ${PROJECT_BINARY_DIR}/${resource_file})
|
||||||
|
file(SIZE ${PROJECT_BINARY_DIR}/${resource_file} file_size)
|
||||||
|
endif()
|
||||||
|
if (${file_size} EQUAL 0)
|
||||||
configure_file(
|
configure_file(
|
||||||
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
${CMAKE_SOURCE_DIR}/resources/${resource_file} ${PROJECT_BINARY_DIR}/${resource_file}
|
||||||
COPYONLY
|
COPYONLY
|
||||||
)
|
)
|
||||||
message("Moved ${resource_file} to project binary directory")
|
message(STATUS "Moved " ${resource_file} " to project binary directory")
|
||||||
|
elseif (resource_file MATCHES ".ini")
|
||||||
|
message(STATUS "Checking " ${resource_file} " for missing config options")
|
||||||
|
file(READ ${PROJECT_BINARY_DIR}/${resource_file} current_file_contents)
|
||||||
|
string(REPLACE "\\\n" "" current_file_contents ${current_file_contents})
|
||||||
|
string(REPLACE "\n" ";" current_file_contents ${current_file_contents})
|
||||||
|
set(parsed_current_file_contents "")
|
||||||
|
# Remove comment lines so they do not interfere with the variable parsing
|
||||||
|
foreach (line ${current_file_contents})
|
||||||
|
string(FIND ${line} "#" is_comment)
|
||||||
|
if (NOT ${is_comment} EQUAL 0)
|
||||||
|
string(APPEND parsed_current_file_contents ${line})
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
file(READ ${CMAKE_SOURCE_DIR}/resources/${resource_file} depot_file_contents)
|
||||||
|
string(REPLACE "\\\n" "" depot_file_contents ${depot_file_contents})
|
||||||
|
string(REPLACE "\n" ";" depot_file_contents ${depot_file_contents})
|
||||||
|
set(line_to_add "")
|
||||||
|
foreach (line ${depot_file_contents})
|
||||||
|
string(FIND ${line} "#" is_comment)
|
||||||
|
if (NOT ${is_comment} EQUAL 0)
|
||||||
|
string(REPLACE "=" ";" line_split ${line})
|
||||||
|
list(GET line_split 0 variable_name)
|
||||||
|
if (NOT ${parsed_current_file_contents} MATCHES ${variable_name})
|
||||||
|
message(STATUS "Adding missing config option " ${variable_name} " to " ${resource_file})
|
||||||
|
set(line_to_add ${line_to_add} ${line})
|
||||||
|
foreach (line_to_append ${line_to_add})
|
||||||
|
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n" ${line_to_append})
|
||||||
|
endforeach()
|
||||||
|
file(APPEND ${PROJECT_BINARY_DIR}/${resource_file} "\n")
|
||||||
|
endif()
|
||||||
|
set(line_to_add "")
|
||||||
|
else()
|
||||||
|
set(line_to_add ${line_to_add} ${line})
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
message(STATUS "Resource file integrity check complete")
|
||||||
|
|
||||||
# Copy navmesh data on first build and extract it
|
# Copy navmesh data on first build and extract it
|
||||||
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
if (NOT EXISTS ${PROJECT_BINARY_DIR}/navmeshes/)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
PROJECT_VERSION_MAJOR=1
|
PROJECT_VERSION_MAJOR=1
|
||||||
PROJECT_VERSION_MINOR=0
|
PROJECT_VERSION_MINOR=1
|
||||||
PROJECT_VERSION_PATCH=4
|
PROJECT_VERSION_PATCH=0
|
||||||
# LICENSE
|
# LICENSE
|
||||||
LICENSE=AGPL-3.0
|
LICENSE=AGPL-3.0
|
||||||
# The network version.
|
# The network version.
|
||||||
|
@ -338,7 +338,7 @@ This is a Work in Progress, but below are some quick links to documentaion for s
|
|||||||
## Former Contributors
|
## Former Contributors
|
||||||
* TheMachine
|
* TheMachine
|
||||||
* Matthew
|
* Matthew
|
||||||
* [Raine](https://github.com/Rainebannister)
|
* [Raine](https://github.com/uwainium)
|
||||||
* Bricknave
|
* Bricknave
|
||||||
|
|
||||||
## Special Thanks
|
## Special Thanks
|
||||||
|
@ -29,6 +29,7 @@ namespace Game {
|
|||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
dConfig* config = nullptr;
|
dConfig* config = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
|
std::mt19937 randomEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
dLogger* SetupLogger();
|
dLogger* SetupLogger();
|
||||||
@ -83,6 +84,8 @@ int main(int argc, char** argv) {
|
|||||||
delete res;
|
delete res;
|
||||||
delete stmt;
|
delete stmt;
|
||||||
|
|
||||||
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||||
uint32_t maxClients = 50;
|
uint32_t maxClients = 50;
|
||||||
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
|
uint32_t ourPort = 1001; //LU client is hardcoded to use this for auth port, so I'm making it the default.
|
||||||
@ -171,6 +174,8 @@ dLogger* SetupLogger() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
|
if (packet->length < 4) return;
|
||||||
|
|
||||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
|
||||||
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
|
if (static_cast<eServerMessageType>(packet->data[3]) == eServerMessageType::VERSION_CONFIRM) {
|
||||||
|
@ -22,10 +22,9 @@ extern PlayerContainer playerContainer;
|
|||||||
|
|
||||||
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||||
//Get from the packet which player we want to do something with:
|
//Get from the packet which player we want to do something with:
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = 0;
|
LWOOBJID playerID = 0;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
|
|
||||||
auto player = playerContainer.GetPlayerData(playerID);
|
auto player = playerContainer.GetPlayerData(playerID);
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
@ -99,10 +98,9 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
auto maxNumberOfBestFriendsAsString = Game::config->GetValue("max_number_of_best_friends");
|
auto maxNumberOfBestFriendsAsString = Game::config->GetValue("max_number_of_best_friends");
|
||||||
// If this config option doesn't exist, default to 5 which is what live used.
|
// If this config option doesn't exist, default to 5 which is what live used.
|
||||||
auto maxNumberOfBestFriends = maxNumberOfBestFriendsAsString != "" ? std::stoi(maxNumberOfBestFriendsAsString) : 5U;
|
auto maxNumberOfBestFriends = maxNumberOfBestFriendsAsString != "" ? std::stoi(maxNumberOfBestFriendsAsString) : 5U;
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID requestorPlayerID;
|
LWOOBJID requestorPlayerID;
|
||||||
inStream.Read(requestorPlayerID);
|
inStream.Read(requestorPlayerID);
|
||||||
inStream.Read(requestorPlayerID);
|
|
||||||
uint32_t spacing{};
|
uint32_t spacing{};
|
||||||
inStream.Read(spacing);
|
inStream.Read(spacing);
|
||||||
std::string playerName = "";
|
std::string playerName = "";
|
||||||
@ -247,10 +245,9 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
|
|
||||||
eAddFriendResponseCode clientResponseCode = static_cast<eAddFriendResponseCode>(packet->data[0x14]);
|
eAddFriendResponseCode clientResponseCode = static_cast<eAddFriendResponseCode>(packet->data[0x14]);
|
||||||
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
||||||
@ -323,10 +320,9 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
std::string friendName = PacketUtils::ReadString(0x14, packet, true);
|
std::string friendName = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
//we'll have to query the db here to find the user, since you can delete them while they're offline.
|
||||||
@ -381,10 +377,9 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
|
|
||||||
auto* sender = playerContainer.GetPlayerData(playerID);
|
auto* sender = playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
@ -501,10 +496,9 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
auto* player = playerContainer.GetPlayerData(playerID);
|
auto* player = playerContainer.GetPlayerData(playerID);
|
||||||
@ -542,10 +536,9 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
char declined = 0;
|
char declined = 0;
|
||||||
@ -576,10 +569,9 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
|
|
||||||
@ -593,10 +585,9 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
|
|
||||||
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
@ -624,10 +615,9 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
|
|
||||||
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
|
||||||
|
|
||||||
@ -647,10 +637,9 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
|
void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
|
|
||||||
@ -671,10 +660,9 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
inStream.Read(playerID);
|
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = playerContainer.GetTeam(playerID);
|
||||||
auto* data = playerContainer.GetPlayerData(playerID);
|
auto* data = playerContainer.GetPlayerData(playerID);
|
||||||
|
@ -203,6 +203,8 @@ void HandlePacket(Packet* packet) {
|
|||||||
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.");
|
Game::logger->Log("ChatServer", "A server is connecting, awaiting user list.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue.
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) {
|
||||||
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
|
switch (static_cast<eChatInternalMessageType>(packet->data[3])) {
|
||||||
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
|
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
|
||||||
|
@ -19,9 +19,8 @@ PlayerContainer::~PlayerContainer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::InsertPlayer(Packet* packet) {
|
void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
PlayerData* data = new PlayerData();
|
PlayerData* data = new PlayerData();
|
||||||
inStream.SetReadOffset(inStream.GetReadOffset() + 64);
|
|
||||||
inStream.Read(data->playerID);
|
inStream.Read(data->playerID);
|
||||||
|
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
@ -52,9 +51,8 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::RemovePlayer(Packet* packet) {
|
void PlayerContainer::RemovePlayer(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID); //skip header
|
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
|
//Before they get kicked, we need to also send a message to their friends saying that they disconnected.
|
||||||
@ -97,9 +95,8 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::MuteUpdate(Packet* packet) {
|
void PlayerContainer::MuteUpdate(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID); //skip header
|
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
time_t expire = 0;
|
time_t expire = 0;
|
||||||
inStream.Read(expire);
|
inStream.Read(expire);
|
||||||
@ -118,9 +115,8 @@ void PlayerContainer::MuteUpdate(Packet* packet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerContainer::CreateTeamServer(Packet* packet) {
|
void PlayerContainer::CreateTeamServer(Packet* packet) {
|
||||||
CINSTREAM;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
inStream.Read(playerID); //skip header
|
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
size_t membersSize = 0;
|
size_t membersSize = 0;
|
||||||
inStream.Read(membersSize);
|
inStream.Read(membersSize);
|
||||||
|
@ -1,77 +1,79 @@
|
|||||||
#include "AMFDeserialize.h"
|
#include "AMFDeserialize.h"
|
||||||
|
|
||||||
#include "AMFFormat.h"
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf
|
* AMF3 Reference document https://rtmp.veriskope.com/pdf/amf3-file-format-spec.pdf
|
||||||
* AMF3 Deserializer written by EmosewaMC
|
* AMF3 Deserializer written by EmosewaMC
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::Read(RakNet::BitStream* inStream) {
|
||||||
if (!inStream) return nullptr;
|
if (!inStream) return nullptr;
|
||||||
AMFValue* returnValue = nullptr;
|
AMFBaseValue* returnValue = nullptr;
|
||||||
// Read in the value type from the bitStream
|
// Read in the value type from the bitStream
|
||||||
int8_t marker;
|
eAmf marker;
|
||||||
inStream->Read(marker);
|
inStream->Read(marker);
|
||||||
// Based on the typing, create the value associated with that and return the base value class
|
// Based on the typing, create the value associated with that and return the base value class
|
||||||
switch (marker) {
|
switch (marker) {
|
||||||
case AMFValueType::AMFUndefined: {
|
case eAmf::Undefined: {
|
||||||
returnValue = new AMFUndefinedValue();
|
returnValue = new AMFBaseValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFNull: {
|
case eAmf::Null: {
|
||||||
returnValue = new AMFNullValue();
|
returnValue = new AMFNullValue();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFFalse: {
|
case eAmf::False: {
|
||||||
returnValue = new AMFFalseValue();
|
returnValue = new AMFBoolValue(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFTrue: {
|
case eAmf::True: {
|
||||||
returnValue = new AMFTrueValue();
|
returnValue = new AMFBoolValue(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFInteger: {
|
case eAmf::Integer: {
|
||||||
returnValue = ReadAmfInteger(inStream);
|
returnValue = ReadAmfInteger(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFDouble: {
|
case eAmf::Double: {
|
||||||
returnValue = ReadAmfDouble(inStream);
|
returnValue = ReadAmfDouble(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFString: {
|
case eAmf::String: {
|
||||||
returnValue = ReadAmfString(inStream);
|
returnValue = ReadAmfString(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case AMFValueType::AMFArray: {
|
case eAmf::Array: {
|
||||||
returnValue = ReadAmfArray(inStream);
|
returnValue = ReadAmfArray(inStream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO We do not need these values, but if someone wants to implement them
|
// These values are unimplemented in the live client and will remain unimplemented
|
||||||
// then please do so and add the corresponding unit tests.
|
// unless someone modifies the client to allow serializing of these values.
|
||||||
case AMFValueType::AMFXMLDoc:
|
case eAmf::XMLDoc:
|
||||||
case AMFValueType::AMFDate:
|
case eAmf::Date:
|
||||||
case AMFValueType::AMFObject:
|
case eAmf::Object:
|
||||||
case AMFValueType::AMFXML:
|
case eAmf::XML:
|
||||||
case AMFValueType::AMFByteArray:
|
case eAmf::ByteArray:
|
||||||
case AMFValueType::AMFVectorInt:
|
case eAmf::VectorInt:
|
||||||
case AMFValueType::AMFVectorUInt:
|
case eAmf::VectorUInt:
|
||||||
case AMFValueType::AMFVectorDouble:
|
case eAmf::VectorDouble:
|
||||||
case AMFValueType::AMFVectorObject:
|
case eAmf::VectorObject:
|
||||||
case AMFValueType::AMFDictionary: {
|
case eAmf::Dictionary: {
|
||||||
throw static_cast<AMFValueType>(marker);
|
throw marker;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw static_cast<AMFValueType>(marker);
|
throw std::invalid_argument("Invalid AMF3 marker" + std::to_string(static_cast<int32_t>(marker)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return returnValue;
|
return returnValue;
|
||||||
@ -99,7 +101,7 @@ uint32_t AMFDeserialize::ReadU29(RakNet::BitStream* inStream) {
|
|||||||
return actualNumber;
|
return actualNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
|
const std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
|
||||||
auto length = ReadU29(inStream);
|
auto length = ReadU29(inStream);
|
||||||
// Check if this is a reference
|
// Check if this is a reference
|
||||||
bool isReference = length % 2 == 1;
|
bool isReference = length % 2 == 1;
|
||||||
@ -113,48 +115,39 @@ std::string AMFDeserialize::ReadString(RakNet::BitStream* inStream) {
|
|||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
// Length is a reference to a previous index - use that as the read in value
|
// Length is a reference to a previous index - use that as the read in value
|
||||||
return accessedElements[length];
|
return accessedElements.at(length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfDouble(RakNet::BitStream* inStream) {
|
||||||
auto doubleValue = new AMFDoubleValue();
|
|
||||||
double value;
|
double value;
|
||||||
inStream->Read<double>(value);
|
inStream->Read<double>(value);
|
||||||
doubleValue->SetDoubleValue(value);
|
return new AMFDoubleValue(value);
|
||||||
return doubleValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfArray(RakNet::BitStream* inStream) {
|
||||||
auto arrayValue = new AMFArrayValue();
|
auto arrayValue = new AMFArrayValue();
|
||||||
|
|
||||||
// Read size of dense array
|
// Read size of dense array
|
||||||
auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
auto sizeOfDenseArray = (ReadU29(inStream) >> 1);
|
||||||
|
// Then read associative portion
|
||||||
// Then read Key'd portion
|
|
||||||
while (true) {
|
while (true) {
|
||||||
auto key = ReadString(inStream);
|
auto key = ReadString(inStream);
|
||||||
// No more values when we encounter an empty string
|
// No more associative values when we encounter an empty string key
|
||||||
if (key.size() == 0) break;
|
if (key.size() == 0) break;
|
||||||
arrayValue->InsertValue(key, Read(inStream));
|
arrayValue->Insert(key, Read(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally read dense portion
|
// Finally read dense portion
|
||||||
for (uint32_t i = 0; i < sizeOfDenseArray; i++) {
|
for (uint32_t i = 0; i < sizeOfDenseArray; i++) {
|
||||||
arrayValue->PushBackValue(Read(inStream));
|
arrayValue->Insert(i, Read(inStream));
|
||||||
}
|
}
|
||||||
|
|
||||||
return arrayValue;
|
return arrayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfString(RakNet::BitStream* inStream) {
|
||||||
auto stringValue = new AMFStringValue();
|
return new AMFStringValue(ReadString(inStream));
|
||||||
stringValue->SetStringValue(ReadString(inStream));
|
|
||||||
return stringValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AMFValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) {
|
AMFBaseValue* AMFDeserialize::ReadAmfInteger(RakNet::BitStream* inStream) {
|
||||||
auto integerValue = new AMFIntegerValue();
|
return new AMFIntValue(ReadU29(inStream));
|
||||||
integerValue->SetIntegerValue(ReadU29(inStream));
|
|
||||||
return integerValue;
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class AMFValue;
|
class AMFBaseValue;
|
||||||
|
|
||||||
class AMFDeserialize {
|
class AMFDeserialize {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -14,7 +15,7 @@ public:
|
|||||||
* @param inStream inStream to read value from.
|
* @param inStream inStream to read value from.
|
||||||
* @return Returns an AMFValue with all the information from the bitStream in it.
|
* @return Returns an AMFValue with all the information from the bitStream in it.
|
||||||
*/
|
*/
|
||||||
AMFValue* Read(RakNet::BitStream* inStream);
|
AMFBaseValue* Read(RakNet::BitStream* inStream);
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Private method to read a U29 integer from a bitstream
|
* @brief Private method to read a U29 integer from a bitstream
|
||||||
@ -30,7 +31,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return The read string
|
* @return The read string
|
||||||
*/
|
*/
|
||||||
std::string ReadString(RakNet::BitStream* inStream);
|
const std::string ReadString(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFDouble value from a bitStream
|
* @brief Read an AMFDouble value from a bitStream
|
||||||
@ -38,7 +39,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Double value represented as an AMFValue
|
* @return Double value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfDouble(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfDouble(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFArray from a bitStream
|
* @brief Read an AMFArray from a bitStream
|
||||||
@ -46,7 +47,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Array value represented as an AMFValue
|
* @return Array value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfArray(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfArray(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFString from a bitStream
|
* @brief Read an AMFString from a bitStream
|
||||||
@ -54,7 +55,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return String value represented as an AMFValue
|
* @return String value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfString(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfString(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read an AMFInteger from a bitStream
|
* @brief Read an AMFInteger from a bitStream
|
||||||
@ -62,7 +63,7 @@ private:
|
|||||||
* @param inStream bitStream to read data from
|
* @param inStream bitStream to read data from
|
||||||
* @return Integer value represented as an AMFValue
|
* @return Integer value represented as an AMFValue
|
||||||
*/
|
*/
|
||||||
AMFValue* ReadAmfInteger(RakNet::BitStream* inStream);
|
AMFBaseValue* ReadAmfInteger(RakNet::BitStream* inStream);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of strings read so far saved to be read by reference.
|
* List of strings read so far saved to be read by reference.
|
||||||
|
@ -1,156 +0,0 @@
|
|||||||
#include "AMFFormat.h"
|
|
||||||
|
|
||||||
// AMFInteger
|
|
||||||
void AMFIntegerValue::SetIntegerValue(uint32_t value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t AMFIntegerValue::GetIntegerValue() {
|
|
||||||
return this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFDouble
|
|
||||||
void AMFDoubleValue::SetDoubleValue(double value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
double AMFDoubleValue::GetDoubleValue() {
|
|
||||||
return this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFString
|
|
||||||
void AMFStringValue::SetStringValue(const std::string& value) {
|
|
||||||
this->value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AMFStringValue::GetStringValue() {
|
|
||||||
return this->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFXMLDoc
|
|
||||||
void AMFXMLDocValue::SetXMLDocValue(const std::string& value) {
|
|
||||||
this->xmlData = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AMFXMLDocValue::GetXMLDocValue() {
|
|
||||||
return this->xmlData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFDate
|
|
||||||
void AMFDateValue::SetDateValue(uint64_t value) {
|
|
||||||
this->millisecondTimestamp = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t AMFDateValue::GetDateValue() {
|
|
||||||
return this->millisecondTimestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Insert Value
|
|
||||||
void AMFArrayValue::InsertValue(const std::string& key, AMFValue* value) {
|
|
||||||
this->associative.insert(std::make_pair(key, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Remove Value
|
|
||||||
void AMFArrayValue::RemoveValue(const std::string& key) {
|
|
||||||
_AMFArrayMap_::iterator it = this->associative.find(key);
|
|
||||||
if (it != this->associative.end()) {
|
|
||||||
this->associative.erase(it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Associative Iterator Begin
|
|
||||||
_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueBegin() {
|
|
||||||
return this->associative.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Associative Iterator End
|
|
||||||
_AMFArrayMap_::iterator AMFArrayValue::GetAssociativeIteratorValueEnd() {
|
|
||||||
return this->associative.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Push Back Value
|
|
||||||
void AMFArrayValue::PushBackValue(AMFValue* value) {
|
|
||||||
this->dense.push_back(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Pop Back Value
|
|
||||||
void AMFArrayValue::PopBackValue() {
|
|
||||||
this->dense.pop_back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Dense List Size
|
|
||||||
uint32_t AMFArrayValue::GetDenseValueSize() {
|
|
||||||
return (uint32_t)this->dense.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Dense Iterator Begin
|
|
||||||
_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorBegin() {
|
|
||||||
return this->dense.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFArray Get Dense Iterator End
|
|
||||||
_AMFArrayList_::iterator AMFArrayValue::GetDenseIteratorEnd() {
|
|
||||||
return this->dense.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFArrayValue::~AMFArrayValue() {
|
|
||||||
for (auto valueToDelete : GetDenseArray()) {
|
|
||||||
if (valueToDelete) delete valueToDelete;
|
|
||||||
}
|
|
||||||
for (auto valueToDelete : GetAssociativeMap()) {
|
|
||||||
if (valueToDelete.second) delete valueToDelete.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Constructor
|
|
||||||
AMFObjectValue::AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits) {
|
|
||||||
this->traits.reserve(traits.size());
|
|
||||||
std::vector<std::pair<std::string, AMFValueType>>::iterator it = traits.begin();
|
|
||||||
while (it != traits.end()) {
|
|
||||||
this->traits.insert(std::make_pair(it->first, std::make_pair(it->second, new AMFNullValue())));
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Set Value
|
|
||||||
void AMFObjectValue::SetTraitValue(const std::string& trait, AMFValue* value) {
|
|
||||||
if (value) {
|
|
||||||
_AMFObjectTraits_::iterator it = this->traits.find(trait);
|
|
||||||
if (it != this->traits.end()) {
|
|
||||||
if (it->second.first == value->GetValueType()) {
|
|
||||||
it->second.second = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Value
|
|
||||||
AMFValue* AMFObjectValue::GetTraitValue(const std::string& trait) {
|
|
||||||
_AMFObjectTraits_::iterator it = this->traits.find(trait);
|
|
||||||
if (it != this->traits.end()) {
|
|
||||||
return it->second.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Trait Iterator Begin
|
|
||||||
_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorBegin() {
|
|
||||||
return this->traits.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Trait Iterator End
|
|
||||||
_AMFObjectTraits_::iterator AMFObjectValue::GetTraitsIteratorEnd() {
|
|
||||||
return this->traits.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
// AMFObject Get Trait Size
|
|
||||||
uint32_t AMFObjectValue::GetTraitArrayCount() {
|
|
||||||
return (uint32_t)this->traits.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
AMFObjectValue::~AMFObjectValue() {
|
|
||||||
for (auto valueToDelete = GetTraitsIteratorBegin(); valueToDelete != GetTraitsIteratorEnd(); valueToDelete++) {
|
|
||||||
if (valueToDelete->second.second) delete valueToDelete->second.second;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,413 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Custom Classes
|
|
||||||
#include "dCommonVars.h"
|
|
||||||
|
|
||||||
// C++
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file AMFFormat.hpp
|
|
||||||
\brief A class for managing AMF values
|
|
||||||
*/
|
|
||||||
|
|
||||||
class AMFValue; // Forward declaration
|
|
||||||
|
|
||||||
// Definitions
|
|
||||||
#define _AMFArrayMap_ std::unordered_map<std::string, AMFValue*>
|
|
||||||
#define _AMFArrayList_ std::vector<AMFValue*>
|
|
||||||
|
|
||||||
#define _AMFObjectTraits_ std::unordered_map<std::string, std::pair<AMFValueType, AMFValue*>>
|
|
||||||
#define _AMFObjectDynamicTraits_ std::unordered_map<std::string, AMFValue*>
|
|
||||||
|
|
||||||
//! An enum for each AMF value type
|
|
||||||
enum AMFValueType : unsigned char {
|
|
||||||
AMFUndefined = 0x00, //!< An undefined AMF Value
|
|
||||||
AMFNull = 0x01, //!< A null AMF value
|
|
||||||
AMFFalse = 0x02, //!< A false AMF value
|
|
||||||
AMFTrue = 0x03, //!< A true AMF value
|
|
||||||
AMFInteger = 0x04, //!< An integer AMF value
|
|
||||||
AMFDouble = 0x05, //!< A double AMF value
|
|
||||||
AMFString = 0x06, //!< A string AMF value
|
|
||||||
AMFXMLDoc = 0x07, //!< An XML Doc AMF value
|
|
||||||
AMFDate = 0x08, //!< A date AMF value
|
|
||||||
AMFArray = 0x09, //!< An array AMF value
|
|
||||||
AMFObject = 0x0A, //!< An object AMF value
|
|
||||||
AMFXML = 0x0B, //!< An XML AMF value
|
|
||||||
AMFByteArray = 0x0C, //!< A byte array AMF value
|
|
||||||
AMFVectorInt = 0x0D, //!< An integer vector AMF value
|
|
||||||
AMFVectorUInt = 0x0E, //!< An unsigned integer AMF value
|
|
||||||
AMFVectorDouble = 0x0F, //!< A double vector AMF value
|
|
||||||
AMFVectorObject = 0x10, //!< An object vector AMF value
|
|
||||||
AMFDictionary = 0x11 //!< A dictionary AMF value
|
|
||||||
};
|
|
||||||
|
|
||||||
//! An enum for the object value types
|
|
||||||
enum AMFObjectValueType : unsigned char {
|
|
||||||
AMFObjectAnonymous = 0x01,
|
|
||||||
AMFObjectTyped = 0x02,
|
|
||||||
AMFObjectDynamic = 0x03,
|
|
||||||
AMFObjectExternalizable = 0x04
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The base AMF value class
|
|
||||||
class AMFValue {
|
|
||||||
public:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
virtual AMFValueType GetValueType() = 0;
|
|
||||||
virtual ~AMFValue() {};
|
|
||||||
};
|
|
||||||
|
|
||||||
//! A typedef for a pointer to an AMF value
|
|
||||||
typedef AMFValue* NDGFxValue;
|
|
||||||
|
|
||||||
|
|
||||||
// The various AMF value types
|
|
||||||
|
|
||||||
//! The undefined value AMF type
|
|
||||||
class AMFUndefinedValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFUndefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The null value AMF type
|
|
||||||
class AMFNullValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFNull;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The false value AMF type
|
|
||||||
class AMFFalseValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFFalse;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The true value AMF type
|
|
||||||
class AMFTrueValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFTrue;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The integer value AMF type
|
|
||||||
class AMFIntegerValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
uint32_t value; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFInteger;
|
|
||||||
//! Sets the integer value
|
|
||||||
/*!
|
|
||||||
\param value The value to set
|
|
||||||
*/
|
|
||||||
void SetIntegerValue(uint32_t value);
|
|
||||||
|
|
||||||
//! Gets the integer value
|
|
||||||
/*!
|
|
||||||
\return The integer value
|
|
||||||
*/
|
|
||||||
uint32_t GetIntegerValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The double value AMF type
|
|
||||||
class AMFDoubleValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
double value; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFDouble;
|
|
||||||
//! Sets the double value
|
|
||||||
/*!
|
|
||||||
\param value The value to set to
|
|
||||||
*/
|
|
||||||
void SetDoubleValue(double value);
|
|
||||||
|
|
||||||
//! Gets the double value
|
|
||||||
/*!
|
|
||||||
\return The double value
|
|
||||||
*/
|
|
||||||
double GetDoubleValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The string value AMF type
|
|
||||||
class AMFStringValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
std::string value; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFString;
|
|
||||||
//! Sets the string value
|
|
||||||
/*!
|
|
||||||
\param value The string value to set to
|
|
||||||
*/
|
|
||||||
void SetStringValue(const std::string& value);
|
|
||||||
|
|
||||||
//! Gets the string value
|
|
||||||
/*!
|
|
||||||
\return The string value
|
|
||||||
*/
|
|
||||||
std::string GetStringValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The XML doc value AMF type
|
|
||||||
class AMFXMLDocValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
std::string xmlData; //!< The value of the AMF type
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFXMLDoc;
|
|
||||||
//! Sets the XML Doc value
|
|
||||||
/*!
|
|
||||||
\param value The value to set to
|
|
||||||
*/
|
|
||||||
void SetXMLDocValue(const std::string& value);
|
|
||||||
|
|
||||||
//! Gets the XML Doc value
|
|
||||||
/*!
|
|
||||||
\return The XML Doc value
|
|
||||||
*/
|
|
||||||
std::string GetXMLDocValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The date value AMF type
|
|
||||||
class AMFDateValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
uint64_t millisecondTimestamp; //!< The time in milliseconds since the ephoch
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFDate;
|
|
||||||
//! Sets the date time
|
|
||||||
/*!
|
|
||||||
\param value The value to set to
|
|
||||||
*/
|
|
||||||
void SetDateValue(uint64_t value);
|
|
||||||
|
|
||||||
//! Gets the date value
|
|
||||||
/*!
|
|
||||||
\return The date value in milliseconds since the epoch
|
|
||||||
*/
|
|
||||||
uint64_t GetDateValue();
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The array value AMF type
|
|
||||||
// This object will manage it's own memory map and list. Do not delete its values.
|
|
||||||
class AMFArrayValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
_AMFArrayMap_ associative; //!< The array map (associative part)
|
|
||||||
_AMFArrayList_ dense; //!< The array list (dense part)
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() override { return ValueType; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFArray;
|
|
||||||
|
|
||||||
~AMFArrayValue() override;
|
|
||||||
//! Inserts an item into the array map for a specific key
|
|
||||||
/*!
|
|
||||||
\param key The key to set
|
|
||||||
\param value The value to add
|
|
||||||
*/
|
|
||||||
void InsertValue(const std::string& key, AMFValue* value);
|
|
||||||
|
|
||||||
//! Removes an item for a specific key
|
|
||||||
/*!
|
|
||||||
\param key The key to remove
|
|
||||||
*/
|
|
||||||
void RemoveValue(const std::string& key);
|
|
||||||
|
|
||||||
//! Finds an AMF value
|
|
||||||
/*!
|
|
||||||
\return The AMF value if found, nullptr otherwise
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T* FindValue(const std::string& key) const {
|
|
||||||
_AMFArrayMap_::const_iterator it = this->associative.find(key);
|
|
||||||
if (it != this->associative.end() && T::ValueType == it->second->GetValueType()) {
|
|
||||||
return dynamic_cast<T*>(it->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Returns where the associative iterator begins
|
|
||||||
/*!
|
|
||||||
\return Where the array map iterator begins
|
|
||||||
*/
|
|
||||||
_AMFArrayMap_::iterator GetAssociativeIteratorValueBegin();
|
|
||||||
|
|
||||||
//! Returns where the associative iterator ends
|
|
||||||
/*!
|
|
||||||
\return Where the array map iterator ends
|
|
||||||
*/
|
|
||||||
_AMFArrayMap_::iterator GetAssociativeIteratorValueEnd();
|
|
||||||
|
|
||||||
//! Pushes back a value into the array list
|
|
||||||
/*!
|
|
||||||
\param value The value to push back
|
|
||||||
*/
|
|
||||||
void PushBackValue(AMFValue* value);
|
|
||||||
|
|
||||||
//! Pops back the last value in the array list
|
|
||||||
void PopBackValue();
|
|
||||||
|
|
||||||
//! Gets the count of the dense list
|
|
||||||
/*!
|
|
||||||
\return The dense list size
|
|
||||||
*/
|
|
||||||
uint32_t GetDenseValueSize();
|
|
||||||
|
|
||||||
//! Gets a specific value from the list for the specified index
|
|
||||||
/*!
|
|
||||||
\param index The index to get
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
T* GetValueAt(uint32_t index) {
|
|
||||||
if (index >= this->dense.size()) return nullptr;
|
|
||||||
AMFValue* foundValue = this->dense.at(index);
|
|
||||||
return T::ValueType == foundValue->GetValueType() ? dynamic_cast<T*>(foundValue) : nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Returns where the dense iterator begins
|
|
||||||
/*!
|
|
||||||
\return Where the iterator begins
|
|
||||||
*/
|
|
||||||
_AMFArrayList_::iterator GetDenseIteratorBegin();
|
|
||||||
|
|
||||||
//! Returns where the dense iterator ends
|
|
||||||
/*!
|
|
||||||
\return Where the iterator ends
|
|
||||||
*/
|
|
||||||
_AMFArrayList_::iterator GetDenseIteratorEnd();
|
|
||||||
|
|
||||||
//! Returns the associative map
|
|
||||||
/*!
|
|
||||||
\return The associative map
|
|
||||||
*/
|
|
||||||
_AMFArrayMap_ GetAssociativeMap() { return this->associative; };
|
|
||||||
|
|
||||||
//! Returns the dense array
|
|
||||||
/*!
|
|
||||||
\return The dense array
|
|
||||||
*/
|
|
||||||
_AMFArrayList_ GetDenseArray() { return this->dense; };
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The anonymous object value AMF type
|
|
||||||
class AMFObjectValue : public AMFValue {
|
|
||||||
private:
|
|
||||||
_AMFObjectTraits_ traits; //!< The object traits
|
|
||||||
|
|
||||||
//! Returns the AMF value type
|
|
||||||
/*!
|
|
||||||
\return The AMF value type
|
|
||||||
*/
|
|
||||||
AMFValueType GetValueType() override { return ValueType; }
|
|
||||||
~AMFObjectValue() override;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const AMFValueType ValueType = AMFObject;
|
|
||||||
//! Constructor
|
|
||||||
/*!
|
|
||||||
\param traits The traits to set
|
|
||||||
*/
|
|
||||||
AMFObjectValue(std::vector<std::pair<std::string, AMFValueType>> traits);
|
|
||||||
|
|
||||||
//! Gets the object value type
|
|
||||||
/*!
|
|
||||||
\return The object value type
|
|
||||||
*/
|
|
||||||
virtual AMFObjectValueType GetObjectValueType() { return AMFObjectAnonymous; }
|
|
||||||
|
|
||||||
//! Sets the value of a trait
|
|
||||||
/*!
|
|
||||||
\param trait The trait to set the value for
|
|
||||||
\param value The AMF value to set
|
|
||||||
*/
|
|
||||||
void SetTraitValue(const std::string& trait, AMFValue* value);
|
|
||||||
|
|
||||||
//! Gets a trait value
|
|
||||||
/*!
|
|
||||||
\param trait The trait to get the value for
|
|
||||||
\return The trait value
|
|
||||||
*/
|
|
||||||
AMFValue* GetTraitValue(const std::string& trait);
|
|
||||||
|
|
||||||
//! Gets the beginning of the object traits iterator
|
|
||||||
/*!
|
|
||||||
\return The AMF trait array iterator begin
|
|
||||||
*/
|
|
||||||
_AMFObjectTraits_::iterator GetTraitsIteratorBegin();
|
|
||||||
|
|
||||||
//! Gets the end of the object traits iterator
|
|
||||||
/*!
|
|
||||||
\return The AMF trait array iterator begin
|
|
||||||
*/
|
|
||||||
_AMFObjectTraits_::iterator GetTraitsIteratorEnd();
|
|
||||||
|
|
||||||
//! Gets the amount of traits
|
|
||||||
/*!
|
|
||||||
\return The amount of traits
|
|
||||||
*/
|
|
||||||
uint32_t GetTraitArrayCount();
|
|
||||||
};
|
|
@ -1,259 +0,0 @@
|
|||||||
#include "AMFFormat_BitStream.h"
|
|
||||||
|
|
||||||
// Writes an AMFValue pointer to a RakNet::BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value) {
|
|
||||||
if (value != nullptr) {
|
|
||||||
AMFValueType type = value->GetValueType();
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case AMFUndefined: {
|
|
||||||
AMFUndefinedValue* v = (AMFUndefinedValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFNull: {
|
|
||||||
AMFNullValue* v = (AMFNullValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFFalse: {
|
|
||||||
AMFFalseValue* v = (AMFFalseValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFTrue: {
|
|
||||||
AMFTrueValue* v = (AMFTrueValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFInteger: {
|
|
||||||
AMFIntegerValue* v = (AMFIntegerValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFDouble: {
|
|
||||||
AMFDoubleValue* v = (AMFDoubleValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFString: {
|
|
||||||
AMFStringValue* v = (AMFStringValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFXMLDoc: {
|
|
||||||
AMFXMLDocValue* v = (AMFXMLDocValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFDate: {
|
|
||||||
AMFDateValue* v = (AMFDateValue*)value;
|
|
||||||
this->Write(*v);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AMFArray: {
|
|
||||||
this->Write((AMFArrayValue*)value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case AMFObject:
|
|
||||||
case AMFXML:
|
|
||||||
case AMFByteArray:
|
|
||||||
case AMFVectorInt:
|
|
||||||
case AMFVectorUInt:
|
|
||||||
case AMFVectorDouble:
|
|
||||||
case AMFVectorObject:
|
|
||||||
case AMFDictionary:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A private function to write an value to a RakNet::BitStream
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
|
||||||
unsigned char b4 = (unsigned char)v;
|
|
||||||
if (v < 0x00200000) {
|
|
||||||
b4 = b4 & 0x7F;
|
|
||||||
if (v > 0x7F) {
|
|
||||||
unsigned char b3;
|
|
||||||
v = v >> 7;
|
|
||||||
b3 = ((unsigned char)(v)) | 0x80;
|
|
||||||
if (v > 0x7F) {
|
|
||||||
unsigned char b2;
|
|
||||||
v = v >> 7;
|
|
||||||
b2 = ((unsigned char)(v)) | 0x80;
|
|
||||||
bs->Write(b2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bs->Write(b3);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unsigned char b1;
|
|
||||||
unsigned char b2;
|
|
||||||
unsigned char b3;
|
|
||||||
|
|
||||||
v = v >> 8;
|
|
||||||
b3 = ((unsigned char)(v)) | 0x80;
|
|
||||||
v = v >> 7;
|
|
||||||
b2 = ((unsigned char)(v)) | 0x80;
|
|
||||||
v = v >> 7;
|
|
||||||
b1 = ((unsigned char)(v)) | 0x80;
|
|
||||||
|
|
||||||
bs->Write(b1);
|
|
||||||
bs->Write(b2);
|
|
||||||
bs->Write(b3);
|
|
||||||
}
|
|
||||||
|
|
||||||
bs->Write(b4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a flag number to a RakNet::BitStream
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
|
|
||||||
v = (v << 1) | 0x01;
|
|
||||||
WriteUInt29(bs, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an AMFString to a RakNet::BitStream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
|
|
||||||
WriteFlagNumber(bs, (uint32_t)str.size());
|
|
||||||
bs->Write(str.c_str(), (uint32_t)str.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an U16 to a bitstream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
|
|
||||||
bs->Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an U32 to a bitstream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
|
|
||||||
bs->Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes an U64 to a bitstream
|
|
||||||
*
|
|
||||||
* RakNet writes in the correct byte order - do not reverse this.
|
|
||||||
*/
|
|
||||||
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
|
|
||||||
bs->Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Writes an AMFUndefinedValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value) {
|
|
||||||
this->Write(AMFUndefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFNullValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value) {
|
|
||||||
this->Write(AMFNull);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFFalseValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value) {
|
|
||||||
this->Write(AMFFalse);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFTrueValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value) {
|
|
||||||
this->Write(AMFTrue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFIntegerValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value) {
|
|
||||||
this->Write(AMFInteger);
|
|
||||||
WriteUInt29(this, value.GetIntegerValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFDoubleValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value) {
|
|
||||||
this->Write(AMFDouble);
|
|
||||||
double d = value.GetDoubleValue();
|
|
||||||
WriteAMFU64(this, *((unsigned long long*) & d));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFStringValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value) {
|
|
||||||
this->Write(AMFString);
|
|
||||||
std::string v = value.GetStringValue();
|
|
||||||
WriteAMFString(this, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFXMLDocValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value) {
|
|
||||||
this->Write(AMFXMLDoc);
|
|
||||||
std::string v = value.GetXMLDocValue();
|
|
||||||
WriteAMFString(this, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFDateValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value) {
|
|
||||||
this->Write(AMFDate);
|
|
||||||
uint64_t date = value.GetDateValue();
|
|
||||||
WriteAMFU64(this, date);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writes an AMFArrayValue to BitStream
|
|
||||||
template<>
|
|
||||||
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value) {
|
|
||||||
this->Write(AMFArray);
|
|
||||||
uint32_t denseSize = value->GetDenseValueSize();
|
|
||||||
WriteFlagNumber(this, denseSize);
|
|
||||||
|
|
||||||
_AMFArrayMap_::iterator it = value->GetAssociativeIteratorValueBegin();
|
|
||||||
_AMFArrayMap_::iterator end = value->GetAssociativeIteratorValueEnd();
|
|
||||||
|
|
||||||
while (it != end) {
|
|
||||||
WriteAMFString(this, it->first);
|
|
||||||
this->Write(it->second);
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->Write(AMFNull);
|
|
||||||
|
|
||||||
if (denseSize > 0) {
|
|
||||||
_AMFArrayList_::iterator it2 = value->GetDenseIteratorBegin();
|
|
||||||
_AMFArrayList_::iterator end2 = value->GetDenseIteratorEnd();
|
|
||||||
|
|
||||||
while (it2 != end2) {
|
|
||||||
this->Write(*it2);
|
|
||||||
it2++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// Custom Classes
|
|
||||||
#include "AMFFormat.h"
|
|
||||||
|
|
||||||
// RakNet
|
|
||||||
#include <BitStream.h>
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file AMFFormat_BitStream.h
|
|
||||||
\brief A class that implements native writing of AMF values to RakNet::BitStream
|
|
||||||
*/
|
|
||||||
|
|
||||||
// We are using the RakNet namespace
|
|
||||||
namespace RakNet {
|
|
||||||
//! Writes an AMFValue pointer to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFValue*>(AMFValue* value);
|
|
||||||
|
|
||||||
//! Writes an AMFUndefinedValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFUndefinedValue>(AMFUndefinedValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFNullValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFNullValue>(AMFNullValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFFalseValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFFalseValue>(AMFFalseValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFTrueValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFTrueValue>(AMFTrueValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFIntegerValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFIntegerValue>(AMFIntegerValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFDoubleValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFDoubleValue>(AMFDoubleValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFStringValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFStringValue>(AMFStringValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFXMLDocValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFXMLDocValue>(AMFXMLDocValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFDateValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFDateValue>(AMFDateValue value);
|
|
||||||
|
|
||||||
//! Writes an AMFArrayValue to a RakNet::BitStream
|
|
||||||
/*!
|
|
||||||
\param value The value to write
|
|
||||||
*/
|
|
||||||
template <>
|
|
||||||
void RakNet::BitStream::Write<AMFArrayValue*>(AMFArrayValue* value);
|
|
||||||
} // namespace RakNet
|
|
367
dCommon/Amf3.h
Normal file
367
dCommon/Amf3.h
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
#ifndef __AMF3__H__
|
||||||
|
#define __AMF3__H__
|
||||||
|
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
enum class eAmf : uint8_t {
|
||||||
|
Undefined = 0x00, // An undefined AMF Value
|
||||||
|
Null = 0x01, // A null AMF value
|
||||||
|
False = 0x02, // A false AMF value
|
||||||
|
True = 0x03, // A true AMF value
|
||||||
|
Integer = 0x04, // An integer AMF value
|
||||||
|
Double = 0x05, // A double AMF value
|
||||||
|
String = 0x06, // A string AMF value
|
||||||
|
XMLDoc = 0x07, // Unused in the live client and cannot be serialized without modification. An XML Doc AMF value
|
||||||
|
Date = 0x08, // Unused in the live client and cannot be serialized without modification. A date AMF value
|
||||||
|
Array = 0x09, // An array AMF value
|
||||||
|
Object = 0x0A, // Unused in the live client and cannot be serialized without modification. An object AMF value
|
||||||
|
XML = 0x0B, // Unused in the live client and cannot be serialized without modification. An XML AMF value
|
||||||
|
ByteArray = 0x0C, // Unused in the live client and cannot be serialized without modification. A byte array AMF value
|
||||||
|
VectorInt = 0x0D, // Unused in the live client and cannot be serialized without modification. An integer vector AMF value
|
||||||
|
VectorUInt = 0x0E, // Unused in the live client and cannot be serialized without modification. An unsigned integer AMF value
|
||||||
|
VectorDouble = 0x0F, // Unused in the live client and cannot be serialized without modification. A double vector AMF value
|
||||||
|
VectorObject = 0x10, // Unused in the live client and cannot be serialized without modification. An object vector AMF value
|
||||||
|
Dictionary = 0x11 // Unused in the live client and cannot be serialized without modification. A dictionary AMF value
|
||||||
|
};
|
||||||
|
|
||||||
|
class AMFBaseValue {
|
||||||
|
public:
|
||||||
|
virtual eAmf GetValueType() { return eAmf::Undefined; };
|
||||||
|
AMFBaseValue() {};
|
||||||
|
virtual ~AMFBaseValue() {};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ValueType>
|
||||||
|
class AMFValue : public AMFBaseValue {
|
||||||
|
public:
|
||||||
|
AMFValue() {};
|
||||||
|
AMFValue(ValueType value) { SetValue(value); };
|
||||||
|
virtual ~AMFValue() override {};
|
||||||
|
|
||||||
|
eAmf GetValueType() override { return eAmf::Undefined; };
|
||||||
|
|
||||||
|
const ValueType& GetValue() { return data; };
|
||||||
|
void SetValue(ValueType value) { data = value; };
|
||||||
|
protected:
|
||||||
|
ValueType data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// As a string this is much easier to write and read from a BitStream.
|
||||||
|
template<>
|
||||||
|
class AMFValue<const char*> : public AMFBaseValue {
|
||||||
|
public:
|
||||||
|
AMFValue() {};
|
||||||
|
AMFValue(const char* value) { SetValue(std::string(value)); };
|
||||||
|
virtual ~AMFValue() override {};
|
||||||
|
|
||||||
|
eAmf GetValueType() override { return eAmf::String; };
|
||||||
|
|
||||||
|
const std::string& GetValue() { return data; };
|
||||||
|
void SetValue(std::string value) { data = value; };
|
||||||
|
protected:
|
||||||
|
std::string data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef AMFValue<std::nullptr_t> AMFNullValue;
|
||||||
|
typedef AMFValue<bool> AMFBoolValue;
|
||||||
|
typedef AMFValue<int32_t> AMFIntValue;
|
||||||
|
typedef AMFValue<std::string> AMFStringValue;
|
||||||
|
typedef AMFValue<double> AMFDoubleValue;
|
||||||
|
|
||||||
|
template<> inline eAmf AMFValue<std::nullptr_t>::GetValueType() { return eAmf::Null; };
|
||||||
|
template<> inline eAmf AMFValue<bool>::GetValueType() { return this->data ? eAmf::True : eAmf::False; };
|
||||||
|
template<> inline eAmf AMFValue<int32_t>::GetValueType() { return eAmf::Integer; };
|
||||||
|
template<> inline eAmf AMFValue<uint32_t>::GetValueType() { return eAmf::Integer; };
|
||||||
|
template<> inline eAmf AMFValue<std::string>::GetValueType() { return eAmf::String; };
|
||||||
|
template<> inline eAmf AMFValue<double>::GetValueType() { return eAmf::Double; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AMFArrayValue object holds 2 types of lists:
|
||||||
|
* An associative list where a key maps to a value
|
||||||
|
* A Dense list where elements are stored back to back
|
||||||
|
*
|
||||||
|
* Objects that are Registered are owned by this object
|
||||||
|
* and are not to be deleted by a caller.
|
||||||
|
*/
|
||||||
|
class AMFArrayValue : public AMFBaseValue {
|
||||||
|
|
||||||
|
typedef std::unordered_map<std::string, AMFBaseValue*> AMFAssociative;
|
||||||
|
typedef std::vector<AMFBaseValue*> AMFDense;
|
||||||
|
|
||||||
|
public:
|
||||||
|
eAmf GetValueType() override { return eAmf::Array; };
|
||||||
|
|
||||||
|
~AMFArrayValue() override {
|
||||||
|
for (auto valueToDelete : GetDense()) {
|
||||||
|
if (valueToDelete) {
|
||||||
|
delete valueToDelete;
|
||||||
|
valueToDelete = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto valueToDelete : GetAssociative()) {
|
||||||
|
if (valueToDelete.second) {
|
||||||
|
delete valueToDelete.second;
|
||||||
|
valueToDelete.second = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Associative portion of the object
|
||||||
|
*/
|
||||||
|
inline AMFAssociative& GetAssociative() { return this->associative; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the dense portion of the object
|
||||||
|
*/
|
||||||
|
inline AMFDense& GetDense() { return this->dense; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an AMFValue into the associative portion with the given key.
|
||||||
|
* If a duplicate is attempted to be inserted, it is ignored and the
|
||||||
|
* first value with that key is kept in the map.
|
||||||
|
*
|
||||||
|
* These objects are not to be deleted by the caller as they are owned by
|
||||||
|
* the AMFArray object which manages its own memory.
|
||||||
|
*
|
||||||
|
* @param key The key to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
*
|
||||||
|
* @return The inserted element if the type matched,
|
||||||
|
* or nullptr if a key existed and was not the same type
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
std::pair<AMFValue<ValueType>*, bool> Insert(const std::string& key, ValueType value) {
|
||||||
|
auto element = associative.find(key);
|
||||||
|
AMFValue<ValueType>* val = nullptr;
|
||||||
|
bool found = true;
|
||||||
|
if (element == associative.end()) {
|
||||||
|
val = new AMFValue<ValueType>(value);
|
||||||
|
associative.insert(std::make_pair(key, val));
|
||||||
|
} else {
|
||||||
|
val = dynamic_cast<AMFValue<ValueType>*>(element->second);
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
return std::make_pair(val, found);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Associates an array with a string key
|
||||||
|
std::pair<AMFBaseValue*, bool> Insert(const std::string& key) {
|
||||||
|
auto element = associative.find(key);
|
||||||
|
AMFArrayValue* val = nullptr;
|
||||||
|
bool found = true;
|
||||||
|
if (element == associative.end()) {
|
||||||
|
val = new AMFArrayValue();
|
||||||
|
associative.insert(std::make_pair(key, val));
|
||||||
|
} else {
|
||||||
|
val = dynamic_cast<AMFArrayValue*>(element->second);
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
return std::make_pair(val, found);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Associates an array with an integer key
|
||||||
|
std::pair<AMFBaseValue*, bool> Insert(const uint32_t& index) {
|
||||||
|
AMFArrayValue* val = nullptr;
|
||||||
|
bool inserted = false;
|
||||||
|
if (index >= dense.size()) {
|
||||||
|
dense.resize(index + 1);
|
||||||
|
val = new AMFArrayValue();
|
||||||
|
dense.at(index) = val;
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
return std::make_pair(dynamic_cast<AMFArrayValue*>(dense.at(index)), inserted);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserts an AMFValue into the AMFArray key'd by index.
|
||||||
|
* Attempting to insert the same key to the same value twice overwrites
|
||||||
|
* the previous value with the new one.
|
||||||
|
*
|
||||||
|
* @param index The index to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
* @return The inserted element, or nullptr if the type did not match
|
||||||
|
* what was at the index.
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
std::pair<AMFValue<ValueType>*, bool> Insert(const uint32_t& index, ValueType value) {
|
||||||
|
AMFValue<ValueType>* val = nullptr;
|
||||||
|
bool inserted = false;
|
||||||
|
if (index >= this->dense.size()) {
|
||||||
|
this->dense.resize(index + 1);
|
||||||
|
val = new AMFValue<ValueType>(value);
|
||||||
|
this->dense.at(index) = val;
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
return std::make_pair(dynamic_cast<AMFValue<ValueType>*>(this->dense.at(index)), inserted);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an AMFValue into the associative portion with the given key.
|
||||||
|
* If a duplicate is attempted to be inserted, it replaces the original
|
||||||
|
*
|
||||||
|
* The inserted element is now owned by this object and is not to be deleted
|
||||||
|
*
|
||||||
|
* @param key The key to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
*/
|
||||||
|
void Insert(const std::string& key, AMFBaseValue* value) {
|
||||||
|
auto element = associative.find(key);
|
||||||
|
if (element != associative.end() && element->second) {
|
||||||
|
delete element->second;
|
||||||
|
element->second = value;
|
||||||
|
} else {
|
||||||
|
associative.insert(std::make_pair(key, value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts an AMFValue into the associative portion with the given index.
|
||||||
|
* If a duplicate is attempted to be inserted, it replaces the original
|
||||||
|
*
|
||||||
|
* The inserted element is now owned by this object and is not to be deleted
|
||||||
|
*
|
||||||
|
* @param key The key to associate with the value
|
||||||
|
* @param value The value to insert
|
||||||
|
*/
|
||||||
|
void Insert(const uint32_t index, AMFBaseValue* value) {
|
||||||
|
if (index < dense.size()) {
|
||||||
|
AMFDense::iterator itr = dense.begin() + index;
|
||||||
|
if (*itr) delete dense.at(index);
|
||||||
|
} else {
|
||||||
|
dense.resize(index + 1);
|
||||||
|
}
|
||||||
|
dense.at(index) = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pushes an AMFValue into the back of the dense portion.
|
||||||
|
*
|
||||||
|
* These objects are not to be deleted by the caller as they are owned by
|
||||||
|
* the AMFArray object which manages its own memory.
|
||||||
|
*
|
||||||
|
* @param value The value to insert
|
||||||
|
*
|
||||||
|
* @return The inserted pointer, or nullptr should the key already be in use.
|
||||||
|
*/
|
||||||
|
template<typename ValueType>
|
||||||
|
inline AMFValue<ValueType>* Push(ValueType value) {
|
||||||
|
return Insert(this->dense.size(), value).first;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the key from the associative portion
|
||||||
|
*
|
||||||
|
* The pointer removed is now no longer managed by this container
|
||||||
|
*
|
||||||
|
* @param key The key to remove from the associative portion
|
||||||
|
*/
|
||||||
|
void Remove(const std::string& key, bool deleteValue = true) {
|
||||||
|
AMFAssociative::iterator it = this->associative.find(key);
|
||||||
|
if (it != this->associative.end()) {
|
||||||
|
if (deleteValue) delete it->second;
|
||||||
|
this->associative.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pops the last element in the dense portion, deleting it in the process.
|
||||||
|
*/
|
||||||
|
void Remove(const uint32_t index) {
|
||||||
|
if (!this->dense.empty() && index < this->dense.size()) {
|
||||||
|
auto itr = this->dense.begin() + index;
|
||||||
|
if (*itr) delete (*itr);
|
||||||
|
this->dense.erase(itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Pop() {
|
||||||
|
if (!this->dense.empty()) Remove(this->dense.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AMFArrayValue* GetArray(const std::string& key) {
|
||||||
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
|
if (it != this->associative.end()) {
|
||||||
|
return dynamic_cast<AMFArrayValue*>(it->second);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
AMFArrayValue* GetArray(const uint32_t index) {
|
||||||
|
return index >= this->dense.size() ? nullptr : dynamic_cast<AMFArrayValue*>(this->dense.at(index));
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AMFArrayValue* InsertArray(const std::string& key) {
|
||||||
|
return static_cast<AMFArrayValue*>(Insert(key).first);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AMFArrayValue* InsertArray(const uint32_t index) {
|
||||||
|
return static_cast<AMFArrayValue*>(Insert(index).first);
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AMFArrayValue* PushArray() {
|
||||||
|
return static_cast<AMFArrayValue*>(Insert(this->dense.size()).first);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an AMFValue by the key from the associative portion and converts it
|
||||||
|
* to the AmfValue template type. If the key did not exist, it is inserted.
|
||||||
|
*
|
||||||
|
* @tparam The target object type
|
||||||
|
* @param key The key to lookup
|
||||||
|
*
|
||||||
|
* @return The AMFValue
|
||||||
|
*/
|
||||||
|
template <typename AmfType>
|
||||||
|
AMFValue<AmfType>* Get(const std::string& key) const {
|
||||||
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
|
return it != this->associative.end() ?
|
||||||
|
dynamic_cast<AMFValue<AmfType>*>(it->second) :
|
||||||
|
nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get from the array but dont cast it
|
||||||
|
AMFBaseValue* Get(const std::string& key) const {
|
||||||
|
AMFAssociative::const_iterator it = this->associative.find(key);
|
||||||
|
return it != this->associative.end() ? it->second : nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get an AMFValue object at a position in the dense portion.
|
||||||
|
* Gets an AMFValue by the index from the dense portion and converts it
|
||||||
|
* to the AmfValue template type. If the index did not exist, it is inserted.
|
||||||
|
*
|
||||||
|
* @tparam The target object type
|
||||||
|
* @param index The index to get
|
||||||
|
* @return The casted object, or nullptr.
|
||||||
|
*/
|
||||||
|
template <typename AmfType>
|
||||||
|
AMFValue<AmfType>* Get(uint32_t index) const {
|
||||||
|
return index < this->dense.size() ?
|
||||||
|
dynamic_cast<AMFValue<AmfType>*>(this->dense.at(index)) :
|
||||||
|
nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get from the dense but dont cast it
|
||||||
|
AMFBaseValue* Get(const uint32_t index) const {
|
||||||
|
return index < this->dense.size() ? this->dense.at(index) : nullptr;
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||||
|
*/
|
||||||
|
AMFAssociative associative;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dense portion. These AMFValue's are stored one after
|
||||||
|
* another with the most recent addition being at the back.
|
||||||
|
*/
|
||||||
|
AMFDense dense;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__AMF3__H__
|
184
dCommon/AmfSerialize.cpp
Normal file
184
dCommon/AmfSerialize.cpp
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#include "AmfSerialize.h"
|
||||||
|
|
||||||
|
#include "Game.h"
|
||||||
|
#include "dLogger.h"
|
||||||
|
|
||||||
|
// Writes an AMFValue pointer to a RakNet::BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value) {
|
||||||
|
eAmf type = value.GetValueType();
|
||||||
|
this->Write(type);
|
||||||
|
switch (type) {
|
||||||
|
case eAmf::Integer: {
|
||||||
|
this->Write<AMFIntValue&>(*static_cast<AMFIntValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Double: {
|
||||||
|
this->Write<AMFDoubleValue&>(*static_cast<AMFDoubleValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::String: {
|
||||||
|
this->Write<AMFStringValue&>(*static_cast<AMFStringValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eAmf::Array: {
|
||||||
|
this->Write<AMFArrayValue&>(*static_cast<AMFArrayValue*>(&value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
Game::logger->Log("AmfSerialize", "Encountered unwritable AMFType %i!", type);
|
||||||
|
}
|
||||||
|
case eAmf::Undefined:
|
||||||
|
case eAmf::Null:
|
||||||
|
case eAmf::False:
|
||||||
|
case eAmf::True:
|
||||||
|
case eAmf::Date:
|
||||||
|
case eAmf::Object:
|
||||||
|
case eAmf::XML:
|
||||||
|
case eAmf::XMLDoc:
|
||||||
|
case eAmf::ByteArray:
|
||||||
|
case eAmf::VectorInt:
|
||||||
|
case eAmf::VectorUInt:
|
||||||
|
case eAmf::VectorDouble:
|
||||||
|
case eAmf::VectorObject:
|
||||||
|
case eAmf::Dictionary:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private function to write an value to a RakNet::BitStream
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteUInt29(RakNet::BitStream* bs, uint32_t v) {
|
||||||
|
unsigned char b4 = (unsigned char)v;
|
||||||
|
if (v < 0x00200000) {
|
||||||
|
b4 = b4 & 0x7F;
|
||||||
|
if (v > 0x7F) {
|
||||||
|
unsigned char b3;
|
||||||
|
v = v >> 7;
|
||||||
|
b3 = ((unsigned char)(v)) | 0x80;
|
||||||
|
if (v > 0x7F) {
|
||||||
|
unsigned char b2;
|
||||||
|
v = v >> 7;
|
||||||
|
b2 = ((unsigned char)(v)) | 0x80;
|
||||||
|
bs->Write(b2);
|
||||||
|
}
|
||||||
|
|
||||||
|
bs->Write(b3);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unsigned char b1;
|
||||||
|
unsigned char b2;
|
||||||
|
unsigned char b3;
|
||||||
|
|
||||||
|
v = v >> 8;
|
||||||
|
b3 = ((unsigned char)(v)) | 0x80;
|
||||||
|
v = v >> 7;
|
||||||
|
b2 = ((unsigned char)(v)) | 0x80;
|
||||||
|
v = v >> 7;
|
||||||
|
b1 = ((unsigned char)(v)) | 0x80;
|
||||||
|
|
||||||
|
bs->Write(b1);
|
||||||
|
bs->Write(b2);
|
||||||
|
bs->Write(b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
bs->Write(b4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a flag number to a RakNet::BitStream
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteFlagNumber(RakNet::BitStream* bs, uint32_t v) {
|
||||||
|
v = (v << 1) | 0x01;
|
||||||
|
WriteUInt29(bs, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an AMFString to a RakNet::BitStream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFString(RakNet::BitStream* bs, const std::string& str) {
|
||||||
|
WriteFlagNumber(bs, (uint32_t)str.size());
|
||||||
|
bs->Write(str.c_str(), (uint32_t)str.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an U16 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFU16(RakNet::BitStream* bs, uint16_t value) {
|
||||||
|
bs->Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an U32 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFU32(RakNet::BitStream* bs, uint32_t value) {
|
||||||
|
bs->Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes an U64 to a bitstream
|
||||||
|
*
|
||||||
|
* RakNet writes in the correct byte order - do not reverse this.
|
||||||
|
*/
|
||||||
|
void WriteAMFU64(RakNet::BitStream* bs, uint64_t value) {
|
||||||
|
bs->Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFIntegerValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value) {
|
||||||
|
WriteUInt29(this, value.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFDoubleValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value) {
|
||||||
|
double d = value.GetValue();
|
||||||
|
WriteAMFU64(this, *reinterpret_cast<uint64_t*>(&d));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFStringValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value) {
|
||||||
|
WriteAMFString(this, value.GetValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writes an AMFArrayValue to BitStream
|
||||||
|
template<>
|
||||||
|
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value) {
|
||||||
|
uint32_t denseSize = value.GetDense().size();
|
||||||
|
WriteFlagNumber(this, denseSize);
|
||||||
|
|
||||||
|
auto it = value.GetAssociative().begin();
|
||||||
|
auto end = value.GetAssociative().end();
|
||||||
|
|
||||||
|
while (it != end) {
|
||||||
|
WriteAMFString(this, it->first);
|
||||||
|
this->Write<AMFBaseValue&>(*it->second);
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Write(eAmf::Null);
|
||||||
|
|
||||||
|
if (denseSize > 0) {
|
||||||
|
auto it2 = value.GetDense().begin();
|
||||||
|
auto end2 = value.GetDense().end();
|
||||||
|
|
||||||
|
while (it2 != end2) {
|
||||||
|
this->Write<AMFBaseValue&>(**it2);
|
||||||
|
it2++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
dCommon/AmfSerialize.h
Normal file
50
dCommon/AmfSerialize.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Custom Classes
|
||||||
|
#include "Amf3.h"
|
||||||
|
|
||||||
|
// RakNet
|
||||||
|
#include <BitStream.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file AmfSerialize.h
|
||||||
|
\brief A class that implements native writing of AMF values to RakNet::BitStream
|
||||||
|
*/
|
||||||
|
|
||||||
|
// We are using the RakNet namespace
|
||||||
|
namespace RakNet {
|
||||||
|
//! Writes an AMFValue pointer to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFBaseValue&>(AMFBaseValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFIntegerValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFIntValue&>(AMFIntValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFDoubleValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFDoubleValue&>(AMFDoubleValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFStringValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFStringValue&>(AMFStringValue& value);
|
||||||
|
|
||||||
|
//! Writes an AMFArrayValue to a RakNet::BitStream
|
||||||
|
/*!
|
||||||
|
\param value The value to write
|
||||||
|
*/
|
||||||
|
template <>
|
||||||
|
void RakNet::BitStream::Write<AMFArrayValue&>(AMFArrayValue& value);
|
||||||
|
} // namespace RakNet
|
@ -1,6 +1,6 @@
|
|||||||
set(DCOMMON_SOURCES "AMFFormat.cpp"
|
set(DCOMMON_SOURCES
|
||||||
"AMFDeserialize.cpp"
|
"AMFDeserialize.cpp"
|
||||||
"AMFFormat_BitStream.cpp"
|
"AmfSerialize.cpp"
|
||||||
"BinaryIO.cpp"
|
"BinaryIO.cpp"
|
||||||
"dConfig.cpp"
|
"dConfig.cpp"
|
||||||
"Diagnostics.cpp"
|
"Diagnostics.cpp"
|
||||||
|
12
dCommon/DluAssert.h
Normal file
12
dCommon/DluAssert.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef __DLUASSERT__H__
|
||||||
|
#define __DLUASSERT__H__
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
# define DluAssert(expression) assert(expression)
|
||||||
|
#else
|
||||||
|
# define DluAssert(expression)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //!__DLUASSERT__H__
|
@ -10,6 +10,8 @@ class dConfig;
|
|||||||
class RakPeerInterface;
|
class RakPeerInterface;
|
||||||
class AssetManager;
|
class AssetManager;
|
||||||
struct SystemAddress;
|
struct SystemAddress;
|
||||||
|
class EntityManager;
|
||||||
|
class dZoneManager;
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
extern dLogger* logger;
|
extern dLogger* logger;
|
||||||
@ -22,4 +24,6 @@ namespace Game {
|
|||||||
extern AssetManager* assetManager;
|
extern AssetManager* assetManager;
|
||||||
extern SystemAddress chatSysAddr;
|
extern SystemAddress chatSysAddr;
|
||||||
extern bool shouldShutdown;
|
extern bool shouldShutdown;
|
||||||
|
extern EntityManager* entityManager;
|
||||||
|
extern dZoneManager* zoneManager;
|
||||||
}
|
}
|
||||||
|
@ -111,29 +111,6 @@ namespace GeneralUtils {
|
|||||||
*/
|
*/
|
||||||
bool CheckBit(int64_t value, uint32_t index);
|
bool CheckBit(int64_t value, uint32_t index);
|
||||||
|
|
||||||
// MARK: Random Number Generation
|
|
||||||
|
|
||||||
//! Generates a random number
|
|
||||||
/*!
|
|
||||||
\param min The minimum the generate from
|
|
||||||
\param max The maximum to generate to
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
|
||||||
// Make sure it is a numeric type
|
|
||||||
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
|
||||||
|
|
||||||
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
|
||||||
std::uniform_int_distribution<T> distribution(min, max);
|
|
||||||
return distribution(Game::randomEngine);
|
|
||||||
} else if (std::is_floating_point_v<T>) {
|
|
||||||
std::uniform_real_distribution<T> distribution(min, max);
|
|
||||||
return distribution(Game::randomEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
return T();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
bool ReplaceInString(std::string& str, const std::string& from, const std::string& to);
|
||||||
|
|
||||||
std::u16string ReadWString(RakNet::BitStream* inStream);
|
std::u16string ReadWString(RakNet::BitStream* inStream);
|
||||||
@ -223,4 +200,42 @@ namespace GeneralUtils {
|
|||||||
std::hash<T> h;
|
std::hash<T> h;
|
||||||
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
s ^= h(v) + 0x9e3779b9 + (s << 6) + (s >> 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Random Number Generation
|
||||||
|
|
||||||
|
//! Generates a random number
|
||||||
|
/*!
|
||||||
|
\param min The minimum the generate from
|
||||||
|
\param max The maximum to generate to
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
inline T GenerateRandomNumber(std::size_t min, std::size_t max) {
|
||||||
|
// Make sure it is a numeric type
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
|
if constexpr (std::is_integral_v<T>) { // constexpr only necessary on first statement
|
||||||
|
std::uniform_int_distribution<T> distribution(min, max);
|
||||||
|
return distribution(Game::randomEngine);
|
||||||
|
} else if (std::is_floating_point_v<T>) {
|
||||||
|
std::uniform_real_distribution<T> distribution(min, max);
|
||||||
|
return distribution(Game::randomEngine);
|
||||||
|
}
|
||||||
|
|
||||||
|
return T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// on Windows we need to undef these or else they conflict with our numeric limits calls
|
||||||
|
// DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS DEVELOPERS
|
||||||
|
#ifdef _WIN32
|
||||||
|
#undef min
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T GenerateRandomNumber() {
|
||||||
|
// Make sure it is a numeric type
|
||||||
|
static_assert(std::is_arithmetic<T>::value, "Not an arithmetic type");
|
||||||
|
|
||||||
|
return GenerateRandomNumber<T>(std::numeric_limits<T>::min(), std::numeric_limits<T>::max());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,8 +28,10 @@ constexpr uint32_t lowFrameDelta = FRAMES_TO_MS(lowFramerate);
|
|||||||
|
|
||||||
//========== MACROS ===========
|
//========== MACROS ===========
|
||||||
|
|
||||||
|
#define HEADER_SIZE 8
|
||||||
#define CBITSTREAM RakNet::BitStream bitStream;
|
#define CBITSTREAM RakNet::BitStream bitStream;
|
||||||
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
#define CINSTREAM RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
|
#define CINSTREAM_SKIP_HEADER CINSTREAM if (inStream.GetNumberOfUnreadBits() >= BYTES_TO_BITS(HEADER_SIZE)) inStream.IgnoreBytes(HEADER_SIZE); else inStream.IgnoreBits(inStream.GetNumberOfUnreadBits());
|
||||||
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
#define CMSGHEADER PacketUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GAME_MSG);
|
||||||
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
#define SEND_PACKET Game::server->Send(&bitStream, sysAddr, false);
|
||||||
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
#define SEND_PACKET_BROADCAST Game::server->Send(&bitStream, UNASSIGNED_SYSTEM_ADDRESS, true);
|
||||||
|
@ -273,7 +273,7 @@ enum class eGameMessageType : uint16_t {
|
|||||||
TEAM_SET_LEADER = 1557,
|
TEAM_SET_LEADER = 1557,
|
||||||
TEAM_INVITE_CONFIRM = 1558,
|
TEAM_INVITE_CONFIRM = 1558,
|
||||||
TEAM_GET_STATUS_RESPONSE = 1559,
|
TEAM_GET_STATUS_RESPONSE = 1559,
|
||||||
TEAM_ADD_PLAYER = 1526,
|
TEAM_ADD_PLAYER = 1562,
|
||||||
TEAM_REMOVE_PLAYER = 1563,
|
TEAM_REMOVE_PLAYER = 1563,
|
||||||
START_CELEBRATION_EFFECT = 1618,
|
START_CELEBRATION_EFFECT = 1618,
|
||||||
ADD_BUFF = 1647,
|
ADD_BUFF = 1647,
|
||||||
|
@ -107,7 +107,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
DONATION_VENDOR,
|
DONATION_VENDOR,
|
||||||
COMBAT_MEDIATOR,
|
COMBAT_MEDIATOR,
|
||||||
COMMENDATION_VENDOR,
|
COMMENDATION_VENDOR,
|
||||||
UNKNOWN_103,
|
GATE_RUSH_CONTROL,
|
||||||
RAIL_ACTIVATOR,
|
RAIL_ACTIVATOR,
|
||||||
ROLLER,
|
ROLLER,
|
||||||
PLAYER_FORCED_MOVEMENT,
|
PLAYER_FORCED_MOVEMENT,
|
||||||
@ -119,7 +119,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
UNKNOWN_112,
|
UNKNOWN_112,
|
||||||
PROPERTY_PLAQUE,
|
PROPERTY_PLAQUE,
|
||||||
BUILD_BORDER,
|
BUILD_BORDER,
|
||||||
UNKOWN_115,
|
UNKNOWN_115,
|
||||||
CULLING_PLANE,
|
CULLING_PLANE,
|
||||||
DESTROYABLE = 1000 // Actually 7
|
DESTROYABLE = 1000 // Actually 7
|
||||||
};
|
};
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
// Enable this to cache all entries in each table for fast access, comes with more memory cost
|
||||||
//#define CDCLIENT_CACHE_ALL
|
//#define CDCLIENT_CACHE_ALL
|
||||||
|
|
||||||
// Enable this to skip some unused columns in some tables
|
|
||||||
#define UNUSED(v)
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\file CDClientDatabase.hpp
|
\file CDClientDatabase.hpp
|
||||||
\brief An interface between the CDClient.sqlite file and the server
|
\brief An interface between the CDClient.sqlite file and the server
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
CDClientManager::CDClientManager() {
|
CDClientManager::CDClientManager() {
|
||||||
CDActivityRewardsTable::Instance();
|
CDActivityRewardsTable::Instance();
|
||||||
UNUSED(CDAnimationsTable::Instance());
|
CDAnimationsTable::Instance();
|
||||||
CDBehaviorParameterTable::Instance();
|
CDBehaviorParameterTable::Instance();
|
||||||
CDBehaviorTemplateTable::Instance();
|
CDBehaviorTemplateTable::Instance();
|
||||||
CDComponentsRegistryTable::Instance();
|
CDComponentsRegistryTable::Instance();
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include "Singleton.h"
|
#include "Singleton.h"
|
||||||
|
|
||||||
|
#define UNUSED_TABLE(v)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the CDClient tables so they are all loaded into memory.
|
* Initialize the CDClient tables so they are all loaded into memory.
|
||||||
*/
|
*/
|
||||||
|
@ -1,56 +1,83 @@
|
|||||||
#include "CDAnimationsTable.h"
|
#include "CDAnimationsTable.h"
|
||||||
|
#include "GeneralUtils.h"
|
||||||
|
#include "Game.h"
|
||||||
|
|
||||||
CDAnimationsTable::CDAnimationsTable(void) {
|
bool CDAnimationsTable::CacheData(CppSQLite3Statement& queryToCache) {
|
||||||
|
auto tableData = queryToCache.execQuery();
|
||||||
|
// If we received a bad lookup, cache it anyways so we do not run the query again.
|
||||||
|
if (tableData.eof()) return false;
|
||||||
|
|
||||||
// First, get the size of the table
|
do {
|
||||||
unsigned int size = 0;
|
std::string animation_type = tableData.getStringField("animation_type", "");
|
||||||
auto tableSize = CDClientDatabase::ExecuteQuery("SELECT COUNT(*) FROM Animations");
|
DluAssert(!animation_type.empty());
|
||||||
while (!tableSize.eof()) {
|
AnimationGroupID animationGroupID = tableData.getIntField("animationGroupID", -1);
|
||||||
size = tableSize.getIntField(0, 0);
|
DluAssert(animationGroupID != -1);
|
||||||
|
|
||||||
tableSize.nextRow();
|
CDAnimation entry;
|
||||||
}
|
|
||||||
|
|
||||||
tableSize.finalize();
|
|
||||||
|
|
||||||
// Reserve the size
|
|
||||||
this->entries.reserve(size);
|
|
||||||
|
|
||||||
// Now get the data
|
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery("SELECT * FROM Animations");
|
|
||||||
while (!tableData.eof()) {
|
|
||||||
CDAnimations entry;
|
|
||||||
entry.animationGroupID = tableData.getIntField("animationGroupID", -1);
|
|
||||||
entry.animation_type = tableData.getStringField("animation_type", "");
|
|
||||||
entry.animation_name = tableData.getStringField("animation_name", "");
|
entry.animation_name = tableData.getStringField("animation_name", "");
|
||||||
entry.chance_to_play = tableData.getFloatField("chance_to_play", -1.0f);
|
entry.chance_to_play = tableData.getFloatField("chance_to_play", 1.0f);
|
||||||
entry.min_loops = tableData.getIntField("min_loops", -1);
|
UNUSED_COLUMN(entry.min_loops = tableData.getIntField("min_loops", 0);)
|
||||||
entry.max_loops = tableData.getIntField("max_loops", -1);
|
UNUSED_COLUMN(entry.max_loops = tableData.getIntField("max_loops", 0);)
|
||||||
entry.animation_length = tableData.getFloatField("animation_length", -1.0f);
|
entry.animation_length = tableData.getFloatField("animation_length", 0.0f);
|
||||||
entry.hideEquip = tableData.getIntField("hideEquip", -1) == 1 ? true : false;
|
UNUSED_COLUMN(entry.hideEquip = tableData.getIntField("hideEquip", 0) == 1;)
|
||||||
entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", -1) == 1 ? true : false;
|
UNUSED_COLUMN(entry.ignoreUpperBody = tableData.getIntField("ignoreUpperBody", 0) == 1;)
|
||||||
entry.restartable = tableData.getIntField("restartable", -1) == 1 ? true : false;
|
UNUSED_COLUMN(entry.restartable = tableData.getIntField("restartable", 0) == 1;)
|
||||||
entry.face_animation_name = tableData.getStringField("face_animation_name", "");
|
UNUSED_COLUMN(entry.face_animation_name = tableData.getStringField("face_animation_name", "");)
|
||||||
entry.priority = tableData.getFloatField("priority", -1.0f);
|
UNUSED_COLUMN(entry.priority = tableData.getFloatField("priority", 0.0f);)
|
||||||
entry.blendTime = tableData.getFloatField("blendTime", -1.0f);
|
UNUSED_COLUMN(entry.blendTime = tableData.getFloatField("blendTime", 0.0f);)
|
||||||
|
|
||||||
this->entries.push_back(entry);
|
this->animations[CDAnimationKey(animation_type, animationGroupID)].push_back(entry);
|
||||||
tableData.nextRow();
|
tableData.nextRow();
|
||||||
}
|
} while (!tableData.eof());
|
||||||
|
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDAnimations> CDAnimationsTable::Query(std::function<bool(CDAnimations)> predicate) {
|
void CDAnimationsTable::CacheAnimations(const CDAnimationKey animationKey) {
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ? and animation_type = ?");
|
||||||
std::vector<CDAnimations> data = cpplinq::from(this->entries)
|
query.bind(1, static_cast<int32_t>(animationKey.second));
|
||||||
>> cpplinq::where(predicate)
|
query.bind(2, animationKey.first.c_str());
|
||||||
>> cpplinq::to_vector();
|
// If we received a bad lookup, cache it anyways so we do not run the query again.
|
||||||
|
if (!CacheData(query)) {
|
||||||
return data;
|
this->animations[animationKey];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CDAnimations> CDAnimationsTable::GetEntries(void) const {
|
void CDAnimationsTable::CacheAnimationGroup(AnimationGroupID animationGroupID) {
|
||||||
return this->entries;
|
auto animationEntryCached = this->animations.find(CDAnimationKey("", animationGroupID));
|
||||||
|
if (animationEntryCached != this->animations.end()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM Animations WHERE animationGroupID = ?");
|
||||||
|
query.bind(1, static_cast<int32_t>(animationGroupID));
|
||||||
|
|
||||||
|
// Cache the query so we don't run the query again.
|
||||||
|
CacheData(query);
|
||||||
|
this->animations[CDAnimationKey("", animationGroupID)];
|
||||||
|
}
|
||||||
|
|
||||||
|
CDAnimationLookupResult CDAnimationsTable::GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID) {
|
||||||
|
CDAnimationKey animationKey(animationType, animationGroupID);
|
||||||
|
auto animationEntryCached = this->animations.find(animationKey);
|
||||||
|
if (animationEntryCached == this->animations.end()) {
|
||||||
|
this->CacheAnimations(animationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto animationEntry = this->animations.find(animationKey);
|
||||||
|
// If we have only one animation, return it regardless of the chance to play.
|
||||||
|
if (animationEntry->second.size() == 1) {
|
||||||
|
return CDAnimationLookupResult(animationEntry->second.front());
|
||||||
|
}
|
||||||
|
auto randomAnimation = GeneralUtils::GenerateRandomNumber<float>(0, 1);
|
||||||
|
|
||||||
|
for (auto& animationEntry : animationEntry->second) {
|
||||||
|
randomAnimation -= animationEntry.chance_to_play;
|
||||||
|
// This is how the client gets the random animation.
|
||||||
|
if (animationEntry.animation_name != previousAnimationName && randomAnimation <= 0.0f) return CDAnimationLookupResult(animationEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CDAnimationLookupResult();
|
||||||
|
}
|
||||||
|
@ -1,33 +1,66 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Custom Classes
|
|
||||||
#include "CDTable.h"
|
#include "CDTable.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
struct CDAnimations {
|
struct CDAnimation {
|
||||||
unsigned int animationGroupID; //!< The animation group ID
|
// unsigned int animationGroupID;
|
||||||
std::string animation_type; //!< The animation type
|
// std::string animation_type;
|
||||||
|
// The above two are a pair to represent a primary key in the map.
|
||||||
std::string animation_name; //!< The animation name
|
std::string animation_name; //!< The animation name
|
||||||
float chance_to_play; //!< The chance to play the animation
|
float chance_to_play; //!< The chance to play the animation
|
||||||
unsigned int min_loops; //!< The minimum number of loops
|
UNUSED_COLUMN(unsigned int min_loops;) //!< The minimum number of loops
|
||||||
unsigned int max_loops; //!< The maximum number of loops
|
UNUSED_COLUMN(unsigned int max_loops;) //!< The maximum number of loops
|
||||||
float animation_length; //!< The animation length
|
float animation_length; //!< The animation length
|
||||||
bool hideEquip; //!< Whether or not to hide the equip
|
UNUSED_COLUMN(bool hideEquip;) //!< Whether or not to hide the equip
|
||||||
bool ignoreUpperBody; //!< Whether or not to ignore the upper body
|
UNUSED_COLUMN(bool ignoreUpperBody;) //!< Whether or not to ignore the upper body
|
||||||
bool restartable; //!< Whether or not the animation is restartable
|
UNUSED_COLUMN(bool restartable;) //!< Whether or not the animation is restartable
|
||||||
std::string face_animation_name; //!< The face animation name
|
UNUSED_COLUMN(std::string face_animation_name;) //!< The face animation name
|
||||||
float priority; //!< The priority
|
UNUSED_COLUMN(float priority;) //!< The priority
|
||||||
float blendTime; //!< The blend time
|
UNUSED_COLUMN(float blendTime;) //!< The blend time
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef LookupResult<CDAnimation> CDAnimationLookupResult;
|
||||||
|
|
||||||
class CDAnimationsTable : public CDTable<CDAnimationsTable> {
|
class CDAnimationsTable : public CDTable<CDAnimationsTable> {
|
||||||
private:
|
typedef int32_t AnimationGroupID;
|
||||||
std::vector<CDAnimations> entries;
|
typedef std::string AnimationID;
|
||||||
|
typedef std::pair<std::string, AnimationGroupID> CDAnimationKey;
|
||||||
public:
|
public:
|
||||||
CDAnimationsTable();
|
/**
|
||||||
// Queries the table with a custom "where" clause
|
* Given an animationType and the previousAnimationName played, return the next animationType to play.
|
||||||
std::vector<CDAnimations> Query(std::function<bool(CDAnimations)> predicate);
|
* If there are more than 1 animationTypes that can be played, one is selected at random but also does not allow
|
||||||
|
* the previousAnimationName to be played twice.
|
||||||
|
*
|
||||||
|
* @param animationType The animationID to lookup
|
||||||
|
* @param previousAnimationName The previously played animation
|
||||||
|
* @param animationGroupID The animationGroupID to lookup
|
||||||
|
* @return CDAnimationLookupResult
|
||||||
|
*/
|
||||||
|
[[nodiscard]] CDAnimationLookupResult GetAnimation(const AnimationID& animationType, const std::string& previousAnimationName, const AnimationGroupID animationGroupID);
|
||||||
|
|
||||||
std::vector<CDAnimations> GetEntries(void) const;
|
/**
|
||||||
|
* Cache a full AnimationGroup by its ID.
|
||||||
|
*/
|
||||||
|
void CacheAnimationGroup(AnimationGroupID animationGroupID);
|
||||||
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache all animations given a premade key
|
||||||
|
*/
|
||||||
|
void CacheAnimations(const CDAnimationKey animationKey);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the query responsible for caching the data.
|
||||||
|
* @param queryToCache
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
bool CacheData(CppSQLite3Statement& queryToCache);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Each animation is key'd by its animationName and its animationGroupID. Each
|
||||||
|
* animation has a possible list of animations. This is because there can be animations have a percent chance to play so one is selected at random.
|
||||||
|
*/
|
||||||
|
std::map<CDAnimationKey, std::list<CDAnimation>> animations;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "CDClientDatabase.h"
|
#include "CDClientDatabase.h"
|
||||||
#include "Singleton.h"
|
#include "Singleton.h"
|
||||||
|
#include "DluAssert.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -15,6 +16,12 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "cpplinq.hpp"
|
#include "cpplinq.hpp"
|
||||||
|
|
||||||
|
// Used for legacy
|
||||||
|
#define UNUSED(x)
|
||||||
|
|
||||||
|
// Enable this to skip some unused columns in some tables
|
||||||
|
#define UNUSED_COLUMN(v)
|
||||||
|
|
||||||
#pragma warning (disable : 4244) //Disable double to float conversion warnings
|
#pragma warning (disable : 4244) //Disable double to float conversion warnings
|
||||||
#pragma warning (disable : 4715) //Disable "not all control paths return a value"
|
#pragma warning (disable : 4715) //Disable "not all control paths return a value"
|
||||||
|
|
||||||
@ -23,3 +30,15 @@ class CDTable : public Singleton<Table> {
|
|||||||
protected:
|
protected:
|
||||||
virtual ~CDTable() = default;
|
virtual ~CDTable() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class LookupResult {
|
||||||
|
typedef std::pair<T, bool> DataType;
|
||||||
|
public:
|
||||||
|
LookupResult() { m_data.first = T(); m_data.second = false; };
|
||||||
|
LookupResult(T& data) { m_data.first = data; m_data.second = true; };
|
||||||
|
inline const T& Data() { return m_data.first; };
|
||||||
|
inline const bool& FoundData() { return m_data.second; };
|
||||||
|
private:
|
||||||
|
DataType m_data;
|
||||||
|
};
|
||||||
|
@ -241,7 +241,7 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
//To try and fix the AG landing into:
|
//To try and fix the AG landing into:
|
||||||
if (m_ZoneID == 1000 && Game::server->GetZoneID() == 1100) {
|
if (m_ZoneID == 1000 && Game::server->GetZoneID() == 1100) {
|
||||||
//sneakily insert our position:
|
//sneakily insert our position:
|
||||||
auto pos = dZoneManager::Instance()->GetZone()->GetSpawnPos();
|
auto pos = Game::zoneManager->GetZone()->GetSpawnPos();
|
||||||
character->SetAttribute("lzx", pos.x);
|
character->SetAttribute("lzx", pos.x);
|
||||||
character->SetAttribute("lzy", pos.y);
|
character->SetAttribute("lzy", pos.y);
|
||||||
character->SetAttribute("lzz", pos.z);
|
character->SetAttribute("lzz", pos.z);
|
||||||
@ -290,13 +290,13 @@ void Character::DoQuickXMLDataParse() {
|
|||||||
|
|
||||||
void Character::UnlockEmote(int emoteID) {
|
void Character::UnlockEmote(int emoteID) {
|
||||||
m_UnlockedEmotes.push_back(emoteID);
|
m_UnlockedEmotes.push_back(emoteID);
|
||||||
GameMessages::SendSetEmoteLockState(EntityManager::Instance()->GetEntity(m_ObjectID), false, emoteID);
|
GameMessages::SendSetEmoteLockState(Game::entityManager->GetEntity(m_ObjectID), false, emoteID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::SetBuildMode(bool buildMode) {
|
void Character::SetBuildMode(bool buildMode) {
|
||||||
m_BuildMode = buildMode;
|
m_BuildMode = buildMode;
|
||||||
|
|
||||||
auto* controller = dZoneManager::Instance()->GetZoneControlObject();
|
auto* controller = Game::zoneManager->GetZoneControlObject();
|
||||||
|
|
||||||
controller->OnFireEventServerSide(m_OurEntity, buildMode ? "OnBuildModeEnter" : "OnBuildModeLeave");
|
controller->OnFireEventServerSide(m_OurEntity, buildMode ? "OnBuildModeEnter" : "OnBuildModeLeave");
|
||||||
}
|
}
|
||||||
@ -312,7 +312,7 @@ void Character::SaveXMLToDatabase() {
|
|||||||
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
|
character->SetAttribute("gm", static_cast<uint32_t>(m_GMLevel));
|
||||||
character->SetAttribute("cc", m_Coins);
|
character->SetAttribute("cc", m_Coins);
|
||||||
|
|
||||||
auto zoneInfo = dZoneManager::Instance()->GetZone()->GetZoneID();
|
auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID();
|
||||||
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
|
// lzid garbage, binary concat of zoneID, zoneInstance and zoneClone
|
||||||
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
|
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
|
||||||
uint64_t lzidConcat = zoneInfo.GetCloneID();
|
uint64_t lzidConcat = zoneInfo.GetCloneID();
|
||||||
@ -373,7 +373,7 @@ void Character::SaveXMLToDatabase() {
|
|||||||
|
|
||||||
//Call upon the entity to update our xmlDoc:
|
//Call upon the entity to update our xmlDoc:
|
||||||
if (!m_OurEntity) {
|
if (!m_OurEntity) {
|
||||||
Game::logger->Log("Character", "We didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!");
|
Game::logger->Log("Character", "%i:%s didn't have an entity set while saving! CHARACTER WILL NOT BE SAVED!", this->GetID(), this->GetName().c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -384,7 +384,7 @@ void Character::SaveXMLToDatabase() {
|
|||||||
//For metrics, log the time it took to save:
|
//For metrics, log the time it took to save:
|
||||||
auto end = std::chrono::system_clock::now();
|
auto end = std::chrono::system_clock::now();
|
||||||
std::chrono::duration<double> elapsed = end - start;
|
std::chrono::duration<double> elapsed = end - start;
|
||||||
Game::logger->Log("Character", "Saved character to Database in: %fs", elapsed.count());
|
Game::logger->Log("Character", "%i:%s Saved character to Database in: %fs", this->GetID(), this->GetName().c_str(), elapsed.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::SetIsNewLogin() {
|
void Character::SetIsNewLogin() {
|
||||||
@ -396,7 +396,7 @@ void Character::SetIsNewLogin() {
|
|||||||
while (currentChild) {
|
while (currentChild) {
|
||||||
if (currentChild->Attribute("si")) {
|
if (currentChild->Attribute("si")) {
|
||||||
flags->DeleteChild(currentChild);
|
flags->DeleteChild(currentChild);
|
||||||
Game::logger->Log("Character", "Removed isLoggedIn flag from character %i, saving character to database", GetID());
|
Game::logger->Log("Character", "Removed isLoggedIn flag from character %i:%s, saving character to database", GetID(), GetName().c_str());
|
||||||
WriteToDatabase();
|
WriteToDatabase();
|
||||||
}
|
}
|
||||||
currentChild = currentChild->NextSiblingElement();
|
currentChild = currentChild->NextSiblingElement();
|
||||||
@ -418,13 +418,13 @@ void Character::WriteToDatabase() {
|
|||||||
delete printer;
|
delete printer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Character::SetPlayerFlag(const int32_t flagId, const bool value) {
|
void Character::SetPlayerFlag(const uint32_t flagId, const bool value) {
|
||||||
// If the flag is already set, we don't have to recalculate it
|
// If the flag is already set, we don't have to recalculate it
|
||||||
if (GetPlayerFlag(flagId) == value) return;
|
if (GetPlayerFlag(flagId) == value) return;
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
// Update the mission component:
|
// Update the mission component:
|
||||||
auto* player = EntityManager::Instance()->GetEntity(m_ObjectID);
|
auto* player = Game::entityManager->GetEntity(m_ObjectID);
|
||||||
|
|
||||||
if (player != nullptr) {
|
if (player != nullptr) {
|
||||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||||
@ -465,7 +465,7 @@ void Character::SetPlayerFlag(const int32_t flagId, const bool value) {
|
|||||||
GameMessages::SendNotifyClientFlagChange(m_ObjectID, flagId, value, m_ParentUser->GetSystemAddress());
|
GameMessages::SendNotifyClientFlagChange(m_ObjectID, flagId, value, m_ParentUser->GetSystemAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Character::GetPlayerFlag(const int32_t flagId) const {
|
bool Character::GetPlayerFlag(const uint32_t flagId) const {
|
||||||
// Calculate the index first
|
// Calculate the index first
|
||||||
const auto flagIndex = uint32_t(std::floor(flagId / 64));
|
const auto flagIndex = uint32_t(std::floor(flagId / 64));
|
||||||
|
|
||||||
@ -602,7 +602,7 @@ void Character::SetCoins(int64_t newCoins, eLootSourceType lootSource) {
|
|||||||
|
|
||||||
m_Coins = newCoins;
|
m_Coins = newCoins;
|
||||||
|
|
||||||
GameMessages::SendSetCurrency(EntityManager::Instance()->GetEntity(m_ObjectID), m_Coins, 0, 0, 0, 0, true, lootSource);
|
GameMessages::SendSetCurrency(Game::entityManager->GetEntity(m_ObjectID), m_Coins, 0, 0, 0, 0, true, lootSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Character::HasBeenToWorld(LWOMAPID mapID) const {
|
bool Character::HasBeenToWorld(LWOMAPID mapID) const {
|
||||||
|
@ -415,14 +415,14 @@ public:
|
|||||||
* @param flagId the ID of the flag to set
|
* @param flagId the ID of the flag to set
|
||||||
* @param value the value to set for the flag
|
* @param value the value to set for the flag
|
||||||
*/
|
*/
|
||||||
void SetPlayerFlag(int32_t flagId, bool value);
|
void SetPlayerFlag(uint32_t flagId, bool value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the value for a certain character flag
|
* Gets the value for a certain character flag
|
||||||
* @param flagId the ID of the flag to get a value for
|
* @param flagId the ID of the flag to get a value for
|
||||||
* @return the value of the flag given the ID (the default is false, obviously)
|
* @return the value of the flag given the ID (the default is false, obviously)
|
||||||
*/
|
*/
|
||||||
bool GetPlayerFlag(int32_t flagId) const;
|
bool GetPlayerFlag(uint32_t flagId) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the character that they're now muted
|
* Notifies the character that they're now muted
|
||||||
|
@ -263,17 +263,17 @@ void Entity::Initialize() {
|
|||||||
NiQuaternion rot;
|
NiQuaternion rot;
|
||||||
|
|
||||||
const auto& targetSceneName = m_Character->GetTargetScene();
|
const auto& targetSceneName = m_Character->GetTargetScene();
|
||||||
auto* targetScene = EntityManager::Instance()->GetSpawnPointEntity(targetSceneName);
|
auto* targetScene = Game::entityManager->GetSpawnPointEntity(targetSceneName);
|
||||||
|
|
||||||
if (m_Character->HasBeenToWorld(mapID) && targetSceneName.empty()) {
|
if (m_Character->HasBeenToWorld(mapID) && targetSceneName.empty()) {
|
||||||
pos = m_Character->GetRespawnPoint(mapID);
|
pos = m_Character->GetRespawnPoint(mapID);
|
||||||
rot = dZoneManager::Instance()->GetZone()->GetSpawnRot();
|
rot = Game::zoneManager->GetZone()->GetSpawnRot();
|
||||||
} else if (targetScene != nullptr) {
|
} else if (targetScene != nullptr) {
|
||||||
pos = targetScene->GetPosition();
|
pos = targetScene->GetPosition();
|
||||||
rot = targetScene->GetRotation();
|
rot = targetScene->GetRotation();
|
||||||
} else {
|
} else {
|
||||||
pos = dZoneManager::Instance()->GetZone()->GetSpawnPos();
|
pos = Game::zoneManager->GetZone()->GetSpawnPos();
|
||||||
rot = dZoneManager::Instance()->GetZone()->GetSpawnRot();
|
rot = Game::zoneManager->GetZone()->GetSpawnRot();
|
||||||
}
|
}
|
||||||
|
|
||||||
controllablePhysics->SetPosition(pos);
|
controllablePhysics->SetPosition(pos);
|
||||||
@ -386,8 +386,8 @@ void Entity::Initialize() {
|
|||||||
comp->SetMaxCoins(currencyValues[0].maxvalue);
|
comp->SetMaxCoins(currencyValues[0].maxvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
// extraInfo overrides
|
// extraInfo overrides. Client ORs the database smashable and the luz smashable.
|
||||||
comp->SetIsSmashable(GetVarAs<int32_t>(u"is_smashable") != 0);
|
comp->SetIsSmashable(comp->GetIsSmashable() | (GetVarAs<int32_t>(u"is_smashable") != 0));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
comp->SetHealth(1);
|
comp->SetHealth(1);
|
||||||
@ -505,7 +505,7 @@ void Entity::Initialize() {
|
|||||||
// ZoneControl script
|
// ZoneControl script
|
||||||
if (m_TemplateID == 2365) {
|
if (m_TemplateID == 2365) {
|
||||||
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
|
CDZoneTableTable* zoneTable = CDClientManager::Instance().GetTable<CDZoneTableTable>();
|
||||||
const auto zoneID = dZoneManager::Instance()->GetZoneID();
|
const auto zoneID = Game::zoneManager->GetZoneID();
|
||||||
const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID());
|
const CDZoneTable* zoneData = zoneTable->Query(zoneID.GetMapID());
|
||||||
|
|
||||||
if (zoneData != nullptr) {
|
if (zoneData != nullptr) {
|
||||||
@ -595,8 +595,9 @@ void Entity::Initialize() {
|
|||||||
m_Components.insert(std::make_pair(eReplicaComponentType::BOUNCER, comp));
|
m_Components.insert(std::make_pair(eReplicaComponentType::BOUNCER, comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER) > 0 && m_TemplateID != 2365) || m_Character) {
|
int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER);
|
||||||
RenderComponent* render = new RenderComponent(this);
|
if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) {
|
||||||
|
RenderComponent* render = new RenderComponent(this, renderComponentId);
|
||||||
m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render));
|
m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +691,7 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string pathName = GetVarAsString(u"attached_path");
|
std::string pathName = GetVarAsString(u"attached_path");
|
||||||
const Path* path = dZoneManager::Instance()->GetZone()->GetPath(pathName);
|
const Path* path = Game::zoneManager->GetZone()->GetPath(pathName);
|
||||||
|
|
||||||
//Check to see if we have an attached path and add the appropiate component to handle it:
|
//Check to see if we have an attached path and add the appropiate component to handle it:
|
||||||
if (path){
|
if (path){
|
||||||
@ -707,6 +708,13 @@ void Entity::Initialize() {
|
|||||||
// TODO: create movementAIcomp and set path
|
// 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);
|
||||||
|
if (movingPlatformComponentId >= 0) {
|
||||||
|
MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName);
|
||||||
|
m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
|
int proximityMonitorID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROXIMITY_MONITOR);
|
||||||
@ -727,7 +735,7 @@ void Entity::Initialize() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!m_Character && EntityManager::Instance()->GetGhostingEnabled()) {
|
if (!m_Character && Game::entityManager->GetGhostingEnabled()) {
|
||||||
// Don't ghost what is likely large scene elements
|
// Don't ghost what is likely large scene elements
|
||||||
if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) {
|
if (HasComponent(eReplicaComponentType::SIMPLE_PHYSICS) && HasComponent(eReplicaComponentType::RENDER) && (m_Components.size() == 2 || (HasComponent(eReplicaComponentType::TRIGGER) && m_Components.size() == 3))) {
|
||||||
goto no_ghosting;
|
goto no_ghosting;
|
||||||
@ -1276,12 +1284,12 @@ void Entity::Update(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_ShouldDestroyAfterUpdate) {
|
if (m_ShouldDestroyAfterUpdate) {
|
||||||
EntityManager::Instance()->DestroyEntity(this->GetObjectID());
|
Game::entityManager->DestroyEntity(this->GetObjectID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxName, const std::string& status) {
|
void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxName, const std::string& status) {
|
||||||
Entity* other = EntityManager::Instance()->GetEntity(otherEntity);
|
Entity* other = Game::entityManager->GetEntity(otherEntity);
|
||||||
if (!other) return;
|
if (!other) return;
|
||||||
|
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
||||||
@ -1295,7 +1303,7 @@ void Entity::OnCollisionProximity(LWOOBJID otherEntity, const std::string& proxN
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
||||||
auto* other = EntityManager::Instance()->GetEntity(otherEntity);
|
auto* other = Game::entityManager->GetEntity(otherEntity);
|
||||||
if (!other) return;
|
if (!other) return;
|
||||||
|
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
||||||
@ -1342,7 +1350,7 @@ void Entity::OnCollisionPhantom(const LWOOBJID otherEntity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entity::OnCollisionLeavePhantom(const LWOOBJID otherEntity) {
|
void Entity::OnCollisionLeavePhantom(const LWOOBJID otherEntity) {
|
||||||
auto* other = EntityManager::Instance()->GetEntity(otherEntity);
|
auto* other = Game::entityManager->GetEntity(otherEntity);
|
||||||
if (!other) return;
|
if (!other) return;
|
||||||
|
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
||||||
@ -1485,18 +1493,24 @@ void Entity::OnChoiceBoxResponse(Entity* sender, int32_t button, const std::u16s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Entity::RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled) {
|
||||||
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) {
|
||||||
|
script->OnRequestActivityExit(sender, player, canceled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Entity::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType) {
|
void Entity::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType) {
|
||||||
if (!m_PlayerIsReadyForUpdates) return;
|
if (!m_PlayerIsReadyForUpdates) return;
|
||||||
|
|
||||||
auto* destroyableComponent = GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = GetComponent<DestroyableComponent>();
|
||||||
if (destroyableComponent == nullptr) {
|
if (destroyableComponent == nullptr) {
|
||||||
Kill(EntityManager::Instance()->GetEntity(source));
|
Kill(Game::entityManager->GetEntity(source));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto* possessorComponent = GetComponent<PossessorComponent>();
|
auto* possessorComponent = GetComponent<PossessorComponent>();
|
||||||
if (possessorComponent) {
|
if (possessorComponent) {
|
||||||
if (possessorComponent->GetPossessable() != LWOOBJID_EMPTY) {
|
if (possessorComponent->GetPossessable() != LWOOBJID_EMPTY) {
|
||||||
auto* mount = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable());
|
auto* mount = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
||||||
if (mount) possessorComponent->Dismount(mount, true);
|
if (mount) possessorComponent->Dismount(mount, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1524,20 +1538,20 @@ void Entity::Kill(Entity* murderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!IsPlayer()) {
|
if (!IsPlayer()) {
|
||||||
EntityManager::Instance()->DestroyEntity(this);
|
Game::entityManager->DestroyEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& grpNameQBShowBricks = GetVar<std::string>(u"grpNameQBShowBricks");
|
const auto& grpNameQBShowBricks = GetVar<std::string>(u"grpNameQBShowBricks");
|
||||||
|
|
||||||
if (!grpNameQBShowBricks.empty()) {
|
if (!grpNameQBShowBricks.empty()) {
|
||||||
auto spawners = dZoneManager::Instance()->GetSpawnersByName(grpNameQBShowBricks);
|
auto spawners = Game::zoneManager->GetSpawnersByName(grpNameQBShowBricks);
|
||||||
|
|
||||||
Spawner* spawner = nullptr;
|
Spawner* spawner = nullptr;
|
||||||
|
|
||||||
if (!spawners.empty()) {
|
if (!spawners.empty()) {
|
||||||
spawner = spawners[0];
|
spawner = spawners[0];
|
||||||
} else {
|
} else {
|
||||||
spawners = dZoneManager::Instance()->GetSpawnersInGroup(grpNameQBShowBricks);
|
spawners = Game::zoneManager->GetSpawnersInGroup(grpNameQBShowBricks);
|
||||||
|
|
||||||
if (!spawners.empty()) {
|
if (!spawners.empty()) {
|
||||||
spawner = spawners[0];
|
spawner = spawners[0];
|
||||||
@ -1705,7 +1719,7 @@ void Entity::CancelCallbackTimers() {
|
|||||||
|
|
||||||
void Entity::ScheduleKillAfterUpdate(Entity* murderer) {
|
void Entity::ScheduleKillAfterUpdate(Entity* murderer) {
|
||||||
//if (m_Info.spawner) m_Info.spawner->ScheduleKill(this);
|
//if (m_Info.spawner) m_Info.spawner->ScheduleKill(this);
|
||||||
EntityManager::Instance()->ScheduleForKill(this);
|
Game::entityManager->ScheduleForKill(this);
|
||||||
|
|
||||||
if (murderer) m_ScheduleKiller = murderer;
|
if (murderer) m_ScheduleKiller = murderer;
|
||||||
}
|
}
|
||||||
@ -1749,7 +1763,7 @@ void Entity::TriggerEvent(eTriggerEventType event, Entity* optionalTarget) {
|
|||||||
|
|
||||||
Entity* Entity::GetOwner() const {
|
Entity* Entity::GetOwner() const {
|
||||||
if (m_OwnerOverride != LWOOBJID_EMPTY) {
|
if (m_OwnerOverride != LWOOBJID_EMPTY) {
|
||||||
auto* other = EntityManager::Instance()->GetEntity(m_OwnerOverride);
|
auto* other = Game::entityManager->GetEntity(m_OwnerOverride);
|
||||||
|
|
||||||
if (other != nullptr) {
|
if (other != nullptr) {
|
||||||
return other->GetOwner();
|
return other->GetOwner();
|
||||||
@ -1813,8 +1827,6 @@ bool Entity::IsSleeping() const {
|
|||||||
|
|
||||||
|
|
||||||
const NiPoint3& Entity::GetPosition() const {
|
const NiPoint3& Entity::GetPosition() const {
|
||||||
if (!this) return NiPoint3::ZERO;
|
|
||||||
|
|
||||||
auto* controllable = GetComponent<ControllablePhysicsComponent>();
|
auto* controllable = GetComponent<ControllablePhysicsComponent>();
|
||||||
|
|
||||||
if (controllable != nullptr) {
|
if (controllable != nullptr) {
|
||||||
@ -1895,7 +1907,7 @@ void Entity::SetPosition(NiPoint3 position) {
|
|||||||
vehicel->SetPosition(position);
|
vehicel->SetPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(this);
|
Game::entityManager->SerializeEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::SetRotation(NiQuaternion rotation) {
|
void Entity::SetRotation(NiQuaternion rotation) {
|
||||||
@ -1923,7 +1935,7 @@ void Entity::SetRotation(NiQuaternion rotation) {
|
|||||||
vehicel->SetRotation(rotation);
|
vehicel->SetRotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(this);
|
Game::entityManager->SerializeEntity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entity::GetBoolean(const std::u16string& name) const {
|
bool Entity::GetBoolean(const std::u16string& name) const {
|
||||||
@ -1975,7 +1987,7 @@ std::vector<LWOOBJID>& Entity::GetTargetsInPhantom() {
|
|||||||
for (auto i = 0u; i < m_TargetsInPhantom.size(); ++i) {
|
for (auto i = 0u; i < m_TargetsInPhantom.size(); ++i) {
|
||||||
const auto id = m_TargetsInPhantom.at(i);
|
const auto id = m_TargetsInPhantom.at(i);
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(id);
|
auto* entity = Game::entityManager->GetEntity(id);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -207,6 +207,7 @@ public:
|
|||||||
|
|
||||||
void OnMessageBoxResponse(Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData);
|
void OnMessageBoxResponse(Entity* sender, int32_t button, const std::u16string& identifier, const std::u16string& userData);
|
||||||
void OnChoiceBoxResponse(Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier);
|
void OnChoiceBoxResponse(Entity* sender, int32_t button, const std::u16string& buttonIdentifier, const std::u16string& identifier);
|
||||||
|
void RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled);
|
||||||
|
|
||||||
void Smash(const LWOOBJID source = LWOOBJID_EMPTY, const eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"");
|
void Smash(const LWOOBJID source = LWOOBJID_EMPTY, const eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"");
|
||||||
void Kill(Entity* murderer = nullptr);
|
void Kill(Entity* murderer = nullptr);
|
||||||
|
@ -25,8 +25,6 @@
|
|||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
#include "eReplicaPacketType.h"
|
#include "eReplicaPacketType.h"
|
||||||
|
|
||||||
EntityManager* EntityManager::m_Address = nullptr;
|
|
||||||
|
|
||||||
// Configure which zones have ghosting disabled, mostly small worlds.
|
// Configure which zones have ghosting disabled, mostly small worlds.
|
||||||
std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = {
|
std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = {
|
||||||
// Small zones
|
// Small zones
|
||||||
@ -62,7 +60,7 @@ void EntityManager::Initialize() {
|
|||||||
m_GhostingEnabled = std::find(
|
m_GhostingEnabled = std::find(
|
||||||
m_GhostingExcludedZones.begin(),
|
m_GhostingExcludedZones.begin(),
|
||||||
m_GhostingExcludedZones.end(),
|
m_GhostingExcludedZones.end(),
|
||||||
dZoneManager::Instance()->GetZoneID().GetMapID()
|
Game::zoneManager->GetZoneID().GetMapID()
|
||||||
) == m_GhostingExcludedZones.end();
|
) == m_GhostingExcludedZones.end();
|
||||||
|
|
||||||
// grab hardcore mode settings and load them with sane defaults
|
// grab hardcore mode settings and load them with sane defaults
|
||||||
@ -77,10 +75,7 @@ void EntityManager::Initialize() {
|
|||||||
|
|
||||||
// If cloneID is not zero, then hardcore mode is disabled
|
// If cloneID is not zero, then hardcore mode is disabled
|
||||||
// aka minigames and props
|
// aka minigames and props
|
||||||
if (dZoneManager::Instance()->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
|
if (Game::zoneManager->GetZoneID().GetCloneID() != 0) m_HardcoreMode = false;
|
||||||
}
|
|
||||||
|
|
||||||
EntityManager::~EntityManager() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentEntity, const bool controller, const LWOOBJID explicitId) {
|
Entity* EntityManager::CreateEntity(EntityInfo info, User* user, Entity* parentEntity, const bool controller, const LWOOBJID explicitId) {
|
||||||
@ -161,9 +156,7 @@ void EntityManager::DestroyEntity(const LWOOBJID& objectID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::DestroyEntity(Entity* entity) {
|
void EntityManager::DestroyEntity(Entity* entity) {
|
||||||
if (entity == nullptr) {
|
if (!entity) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity->TriggerEvent(eTriggerEventType::DESTROY, entity);
|
entity->TriggerEvent(eTriggerEventType::DESTROY, entity);
|
||||||
|
|
||||||
@ -182,15 +175,11 @@ void EntityManager::DestroyEntity(Entity* entity) {
|
|||||||
ScheduleForDeletion(id);
|
ScheduleForDeletion(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::UpdateEntities(const float deltaTime) {
|
void EntityManager::SerializeEntities() {
|
||||||
for (const auto& e : m_Entities) {
|
|
||||||
e.second->Update(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) {
|
for (auto entry = m_EntitiesToSerialize.begin(); entry != m_EntitiesToSerialize.end(); entry++) {
|
||||||
auto* entity = GetEntity(*entry);
|
auto* entity = GetEntity(*entry);
|
||||||
|
|
||||||
if (entity == nullptr) continue;
|
if (!entity) continue;
|
||||||
|
|
||||||
m_SerializationCounter++;
|
m_SerializationCounter++;
|
||||||
|
|
||||||
@ -212,11 +201,16 @@ void EntityManager::UpdateEntities(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_EntitiesToSerialize.clear();
|
m_EntitiesToSerialize.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityManager::KillEntities() {
|
||||||
for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) {
|
for (auto entry = m_EntitiesToKill.begin(); entry != m_EntitiesToKill.end(); entry++) {
|
||||||
auto* entity = GetEntity(*entry);
|
auto* entity = GetEntity(*entry);
|
||||||
|
|
||||||
if (!entity) continue;
|
if (!entity) {
|
||||||
|
Game::logger->Log("EntityManager", "Attempting to kill null entity %llu", *entry);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (entity->GetScheduledKiller()) {
|
if (entity->GetScheduledKiller()) {
|
||||||
entity->Smash(entity->GetScheduledKiller()->GetObjectID(), eKillType::SILENT);
|
entity->Smash(entity->GetScheduledKiller()->GetObjectID(), eKillType::SILENT);
|
||||||
@ -225,32 +219,41 @@ void EntityManager::UpdateEntities(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_EntitiesToKill.clear();
|
m_EntitiesToKill.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityManager::DeleteEntities() {
|
||||||
for (auto entry = m_EntitiesToDelete.begin(); entry != m_EntitiesToDelete.end(); entry++) {
|
for (auto entry = m_EntitiesToDelete.begin(); entry != m_EntitiesToDelete.end(); entry++) {
|
||||||
|
|
||||||
// Get all this info first before we delete the player.
|
|
||||||
auto entityToDelete = GetEntity(*entry);
|
auto entityToDelete = GetEntity(*entry);
|
||||||
|
if (entityToDelete) {
|
||||||
|
// Get all this info first before we delete the player.
|
||||||
auto networkIdToErase = entityToDelete->GetNetworkId();
|
auto networkIdToErase = entityToDelete->GetNetworkId();
|
||||||
const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete);
|
const auto& ghostingToDelete = std::find(m_EntitiesToGhost.begin(), m_EntitiesToGhost.end(), entityToDelete);
|
||||||
|
|
||||||
if (entityToDelete) {
|
|
||||||
// If we are a player run through the player destructor.
|
|
||||||
if (entityToDelete->IsPlayer()) {
|
|
||||||
delete dynamic_cast<Player*>(entityToDelete);
|
|
||||||
} else {
|
|
||||||
delete entityToDelete;
|
delete entityToDelete;
|
||||||
}
|
|
||||||
entityToDelete = nullptr;
|
entityToDelete = nullptr;
|
||||||
|
|
||||||
if (networkIdToErase != 0) m_LostNetworkIds.push(networkIdToErase);
|
if (networkIdToErase != 0) m_LostNetworkIds.push(networkIdToErase);
|
||||||
}
|
|
||||||
|
|
||||||
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
|
if (ghostingToDelete != m_EntitiesToGhost.end()) m_EntitiesToGhost.erase(ghostingToDelete);
|
||||||
|
} else {
|
||||||
|
Game::logger->Log("EntityManager", "Attempted to delete non-existent entity %llu", *entry);
|
||||||
|
}
|
||||||
m_Entities.erase(*entry);
|
m_Entities.erase(*entry);
|
||||||
}
|
}
|
||||||
m_EntitiesToDelete.clear();
|
m_EntitiesToDelete.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityManager::UpdateEntities(const float deltaTime) {
|
||||||
|
for (const auto& e : m_Entities) {
|
||||||
|
e.second->Update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializeEntities();
|
||||||
|
KillEntities();
|
||||||
|
DeleteEntities();
|
||||||
|
}
|
||||||
|
|
||||||
Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const {
|
Entity* EntityManager::GetEntity(const LWOOBJID& objectId) const {
|
||||||
const auto& index = m_Entities.find(objectId);
|
const auto& index = m_Entities.find(objectId);
|
||||||
|
|
||||||
@ -316,6 +319,11 @@ const std::unordered_map<std::string, LWOOBJID>& EntityManager::GetSpawnPointEnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
|
void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr, const bool skipChecks) {
|
||||||
|
if (!entity) {
|
||||||
|
Game::logger->Log("EntityManager", "Attempted to construct null entity");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (entity->GetNetworkId() == 0) {
|
if (entity->GetNetworkId() == 0) {
|
||||||
uint16_t networkId;
|
uint16_t networkId;
|
||||||
|
|
||||||
@ -395,9 +403,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
|
||||||
if (entity->GetNetworkId() == 0) {
|
if (!entity || entity->GetNetworkId() == 0) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RakNet::BitStream stream;
|
RakNet::BitStream stream;
|
||||||
|
|
||||||
@ -414,9 +420,7 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EntityManager::SerializeEntity(Entity* entity) {
|
void EntityManager::SerializeEntity(Entity* entity) {
|
||||||
if (entity->GetNetworkId() == 0) {
|
if (!entity || entity->GetNetworkId() == 0) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) {
|
if (std::find(m_EntitiesToSerialize.begin(), m_EntitiesToSerialize.end(), entity->GetObjectID()) == m_EntitiesToSerialize.end()) {
|
||||||
m_EntitiesToSerialize.push_back(entity->GetObjectID());
|
m_EntitiesToSerialize.push_back(entity->GetObjectID());
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#ifndef ENTITYMANAGER_H
|
#ifndef ENTITYMANAGER_H
|
||||||
#define ENTITYMANAGER_H
|
#define ENTITYMANAGER_H
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
class EntityInfo;
|
class EntityInfo;
|
||||||
class Player;
|
class Player;
|
||||||
@ -17,19 +18,8 @@ struct SystemAddress;
|
|||||||
|
|
||||||
class EntityManager {
|
class EntityManager {
|
||||||
public:
|
public:
|
||||||
static EntityManager* Instance() {
|
|
||||||
if (!m_Address) {
|
|
||||||
m_Address = new EntityManager();
|
|
||||||
m_Address->Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_Address;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
||||||
~EntityManager();
|
|
||||||
|
|
||||||
void UpdateEntities(float deltaTime);
|
void UpdateEntities(float deltaTime);
|
||||||
Entity* CreateEntity(EntityInfo info, User* user = nullptr, Entity* parentEntity = nullptr, bool controller = false, LWOOBJID explicitId = LWOOBJID_EMPTY);
|
Entity* CreateEntity(EntityInfo info, User* user = nullptr, Entity* parentEntity = nullptr, bool controller = false, LWOOBJID explicitId = LWOOBJID_EMPTY);
|
||||||
void DestroyEntity(const LWOOBJID& objectID);
|
void DestroyEntity(const LWOOBJID& objectID);
|
||||||
@ -85,7 +75,10 @@ public:
|
|||||||
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
const uint32_t GetHardcoreUscoreEnemiesMultiplier() { return m_HardcoreUscoreEnemiesMultiplier; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static EntityManager* m_Address; //For singleton method
|
void SerializeEntities();
|
||||||
|
void KillEntities();
|
||||||
|
void DeleteEntities();
|
||||||
|
|
||||||
static std::vector<LWOMAPID> m_GhostingExcludedZones;
|
static std::vector<LWOMAPID> m_GhostingExcludedZones;
|
||||||
static std::vector<LOT> m_GhostingExcludedLOTs;
|
static std::vector<LOT> m_GhostingExcludedLOTs;
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include "LeaderboardManager.h"
|
#include "LeaderboardManager.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
#include "Character.h"
|
#include "Character.h"
|
||||||
@ -10,461 +13,400 @@
|
|||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
#include "GeneralUtils.h"
|
#include "GeneralUtils.h"
|
||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
|
#include "LDFFormat.h"
|
||||||
|
#include "DluAssert.h"
|
||||||
|
|
||||||
#include "CDActivitiesTable.h"
|
#include "CDActivitiesTable.h"
|
||||||
|
#include "Metrics.hpp"
|
||||||
|
|
||||||
Leaderboard::Leaderboard(uint32_t gameID, uint32_t infoType, bool weekly, std::vector<LeaderboardEntry> entries,
|
namespace LeaderboardManager {
|
||||||
LWOOBJID relatedPlayer, LeaderboardType leaderboardType) {
|
std::map<GameID, Leaderboard::Type> leaderboardCache;
|
||||||
this->relatedPlayer = relatedPlayer;
|
}
|
||||||
|
|
||||||
|
Leaderboard::Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type leaderboardType) {
|
||||||
this->gameID = gameID;
|
this->gameID = gameID;
|
||||||
this->weekly = weekly;
|
this->weekly = weekly;
|
||||||
this->infoType = infoType;
|
this->infoType = infoType;
|
||||||
this->entries = std::move(entries);
|
|
||||||
this->leaderboardType = leaderboardType;
|
this->leaderboardType = leaderboardType;
|
||||||
|
this->relatedPlayer = relatedPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string Leaderboard::ToString() const {
|
Leaderboard::~Leaderboard() {
|
||||||
std::string leaderboard;
|
Clear();
|
||||||
|
|
||||||
leaderboard += "ADO.Result=7:1\n";
|
|
||||||
leaderboard += "Result.Count=1:1\n";
|
|
||||||
leaderboard += "Result[0].Index=0:RowNumber\n";
|
|
||||||
leaderboard += "Result[0].RowCount=1:" + std::to_string(entries.size()) + "\n";
|
|
||||||
|
|
||||||
auto index = 0;
|
|
||||||
for (const auto& entry : entries) {
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].LastPlayed=8:" + std::to_string(entry.lastPlayed) + "\n";
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].CharacterID=8:" + std::to_string(entry.playerID) + "\n";
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].NumPlayed=1:1\n";
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].RowNumber=8:" + std::to_string(entry.placement) + "\n";
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].Time=1:" + std::to_string(entry.time) + "\n";
|
|
||||||
|
|
||||||
// Only these minigames have a points system
|
|
||||||
if (leaderboardType == Survival || leaderboardType == ShootingGallery) {
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].Points=1:" + std::to_string(entry.score) + "\n";
|
|
||||||
} else if (leaderboardType == SurvivalNS) {
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].Wave=1:" + std::to_string(entry.score) + "\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
leaderboard += "Result[0].Row[" + std::to_string(index) + "].name=0:" + entry.playerName + "\n";
|
void Leaderboard::Clear() {
|
||||||
index++;
|
for (auto& entry : entries) for (auto ldfData : entry) delete ldfData;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GeneralUtils::UTF8ToUTF16(leaderboard);
|
inline void WriteLeaderboardRow(std::ostringstream& leaderboard, const uint32_t& index, LDFBaseData* data) {
|
||||||
|
leaderboard << "\nResult[0].Row[" << index << "]." << data->GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LeaderboardEntry> Leaderboard::GetEntries() {
|
void Leaderboard::Serialize(RakNet::BitStream* bitStream) const {
|
||||||
return entries;
|
bitStream->Write(gameID);
|
||||||
|
bitStream->Write(infoType);
|
||||||
|
|
||||||
|
std::ostringstream leaderboard;
|
||||||
|
|
||||||
|
leaderboard << "ADO.Result=7:1"; // Unused in 1.10.64, but is in captures
|
||||||
|
leaderboard << "\nResult.Count=1:1"; // number of results, always 1
|
||||||
|
if (!this->entries.empty()) leaderboard << "\nResult[0].Index=0:RowNumber"; // "Primary key". Live doesn't include this if there are no entries.
|
||||||
|
leaderboard << "\nResult[0].RowCount=1:" << entries.size();
|
||||||
|
|
||||||
|
int32_t rowNumber = 0;
|
||||||
|
for (auto& entry : entries) {
|
||||||
|
for (auto* data : entry) {
|
||||||
|
WriteLeaderboardRow(leaderboard, rowNumber, data);
|
||||||
|
}
|
||||||
|
rowNumber++;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Leaderboard::GetGameID() const {
|
// Serialize the thing to a BitStream
|
||||||
return gameID;
|
uint32_t leaderboardSize = leaderboard.tellp();
|
||||||
|
bitStream->Write<uint32_t>(leaderboardSize);
|
||||||
|
// Doing this all in 1 call so there is no possbility of a dangling pointer.
|
||||||
|
bitStream->WriteAlignedBytes(reinterpret_cast<const unsigned char*>(GeneralUtils::ASCIIToUTF16(leaderboard.str()).c_str()), leaderboardSize * sizeof(char16_t));
|
||||||
|
if (leaderboardSize > 0) bitStream->Write<uint16_t>(0);
|
||||||
|
bitStream->Write0();
|
||||||
|
bitStream->Write0();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Leaderboard::GetInfoType() const {
|
void Leaderboard::QueryToLdf(std::unique_ptr<sql::ResultSet>& rows) {
|
||||||
return infoType;
|
Clear();
|
||||||
|
if (rows->rowsCount() == 0) return;
|
||||||
|
|
||||||
|
this->entries.reserve(rows->rowsCount());
|
||||||
|
while (rows->next()) {
|
||||||
|
constexpr int32_t MAX_NUM_DATA_PER_ROW = 9;
|
||||||
|
this->entries.push_back(std::vector<LDFBaseData*>());
|
||||||
|
auto& entry = this->entries.back();
|
||||||
|
entry.reserve(MAX_NUM_DATA_PER_ROW);
|
||||||
|
entry.push_back(new LDFData<uint64_t>(u"CharacterID", rows->getInt("character_id")));
|
||||||
|
entry.push_back(new LDFData<uint64_t>(u"LastPlayed", rows->getUInt64("lastPlayed")));
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"NumPlayed", rows->getInt("timesPlayed")));
|
||||||
|
entry.push_back(new LDFData<std::u16string>(u"name", GeneralUtils::ASCIIToUTF16(rows->getString("name").c_str())));
|
||||||
|
entry.push_back(new LDFData<uint64_t>(u"RowNumber", rows->getInt("ranking")));
|
||||||
|
switch (leaderboardType) {
|
||||||
|
case Type::ShootingGallery:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Score", rows->getInt("primaryScore")));
|
||||||
|
// Score:1
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Streak", rows->getInt("secondaryScore")));
|
||||||
|
// Streak:1
|
||||||
|
entry.push_back(new LDFData<float>(u"HitPercentage", (rows->getInt("tertiaryScore") / 100.0f)));
|
||||||
|
// HitPercentage:3 between 0 and 1
|
||||||
|
break;
|
||||||
|
case Type::Racing:
|
||||||
|
entry.push_back(new LDFData<float>(u"BestTime", rows->getDouble("primaryScore")));
|
||||||
|
// BestLapTime:3
|
||||||
|
entry.push_back(new LDFData<float>(u"BestLapTime", rows->getDouble("secondaryScore")));
|
||||||
|
// BestTime:3
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"License", 1));
|
||||||
|
// License:1 - 1 if player has completed mission 637 and 0 otherwise
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"NumWins", rows->getInt("numWins")));
|
||||||
|
// NumWins:1
|
||||||
|
break;
|
||||||
|
case Type::UnusedLeaderboard4:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
|
||||||
|
// Points:1
|
||||||
|
break;
|
||||||
|
case Type::MonumentRace:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("primaryScore")));
|
||||||
|
// Time:1(?)
|
||||||
|
break;
|
||||||
|
case Type::FootRace:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("primaryScore")));
|
||||||
|
// Time:1
|
||||||
|
break;
|
||||||
|
case Type::Survival:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
|
||||||
|
// Points:1
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("secondaryScore")));
|
||||||
|
// Time:1
|
||||||
|
break;
|
||||||
|
case Type::SurvivalNS:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Wave", rows->getInt("primaryScore")));
|
||||||
|
// Wave:1
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Time", rows->getInt("secondaryScore")));
|
||||||
|
// Time:1
|
||||||
|
break;
|
||||||
|
case Type::Donations:
|
||||||
|
entry.push_back(new LDFData<int32_t>(u"Points", rows->getInt("primaryScore")));
|
||||||
|
// Score:1
|
||||||
|
break;
|
||||||
|
case Type::None:
|
||||||
|
// This type is included here simply to resolve a compiler warning on mac about unused enum types
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Leaderboard::Send(LWOOBJID targetID) const {
|
const std::string_view Leaderboard::GetOrdering(Leaderboard::Type leaderboardType) {
|
||||||
auto* player = EntityManager::Instance()->GetEntity(relatedPlayer);
|
// Use a switch case and return desc for all 3 columns if higher is better and asc if lower is better
|
||||||
|
switch (leaderboardType) {
|
||||||
|
case Type::Racing:
|
||||||
|
case Type::MonumentRace:
|
||||||
|
return "primaryScore ASC, secondaryScore ASC, tertiaryScore ASC";
|
||||||
|
case Type::Survival:
|
||||||
|
return Game::config->GetValue("classic_survival_scoring") == "1" ?
|
||||||
|
"secondaryScore DESC, primaryScore DESC, tertiaryScore DESC" :
|
||||||
|
"primaryScore DESC, secondaryScore DESC, tertiaryScore DESC";
|
||||||
|
case Type::SurvivalNS:
|
||||||
|
return "primaryScore DESC, secondaryScore ASC, tertiaryScore DESC";
|
||||||
|
case Type::ShootingGallery:
|
||||||
|
case Type::FootRace:
|
||||||
|
case Type::UnusedLeaderboard4:
|
||||||
|
case Type::Donations:
|
||||||
|
case Type::None:
|
||||||
|
default:
|
||||||
|
return "primaryScore DESC, secondaryScore DESC, tertiaryScore DESC";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Leaderboard::SetupLeaderboard(bool weekly, uint32_t resultStart, uint32_t resultEnd) {
|
||||||
|
resultStart++;
|
||||||
|
resultEnd++;
|
||||||
|
// We need everything except 1 column so i'm selecting * from leaderboard
|
||||||
|
const std::string queryBase =
|
||||||
|
R"QUERY(
|
||||||
|
WITH leaderboardsRanked AS (
|
||||||
|
SELECT leaderboard.*, charinfo.name,
|
||||||
|
RANK() OVER
|
||||||
|
(
|
||||||
|
ORDER BY %s, UNIX_TIMESTAMP(last_played) ASC, id DESC
|
||||||
|
) AS ranking
|
||||||
|
FROM leaderboard JOIN charinfo on charinfo.id = leaderboard.character_id
|
||||||
|
WHERE game_id = ? %s
|
||||||
|
),
|
||||||
|
myStanding AS (
|
||||||
|
SELECT
|
||||||
|
ranking as myRank
|
||||||
|
FROM leaderboardsRanked
|
||||||
|
WHERE id = ?
|
||||||
|
),
|
||||||
|
lowestRanking AS (
|
||||||
|
SELECT MAX(ranking) AS lowestRank
|
||||||
|
FROM leaderboardsRanked
|
||||||
|
)
|
||||||
|
SELECT leaderboardsRanked.*, character_id, UNIX_TIMESTAMP(last_played) as lastPlayed, leaderboardsRanked.name, leaderboardsRanked.ranking FROM leaderboardsRanked, myStanding, lowestRanking
|
||||||
|
WHERE leaderboardsRanked.ranking
|
||||||
|
BETWEEN
|
||||||
|
LEAST(GREATEST(CAST(myRank AS SIGNED) - 5, %i), lowestRanking.lowestRank - 9)
|
||||||
|
AND
|
||||||
|
LEAST(GREATEST(myRank + 5, %i), lowestRanking.lowestRank)
|
||||||
|
ORDER BY ranking ASC;
|
||||||
|
)QUERY";
|
||||||
|
|
||||||
|
std::string friendsFilter =
|
||||||
|
R"QUERY(
|
||||||
|
AND (
|
||||||
|
character_id IN (
|
||||||
|
SELECT fr.requested_player FROM (
|
||||||
|
SELECT CASE
|
||||||
|
WHEN player_id = ? THEN friend_id
|
||||||
|
WHEN friend_id = ? THEN player_id
|
||||||
|
END AS requested_player
|
||||||
|
FROM friends
|
||||||
|
) AS fr
|
||||||
|
JOIN charinfo AS ci
|
||||||
|
ON ci.id = fr.requested_player
|
||||||
|
WHERE fr.requested_player IS NOT NULL
|
||||||
|
)
|
||||||
|
OR character_id = ?
|
||||||
|
)
|
||||||
|
)QUERY";
|
||||||
|
|
||||||
|
std::string weeklyFilter = " AND UNIX_TIMESTAMP(last_played) BETWEEN UNIX_TIMESTAMP(date_sub(now(),INTERVAL 1 WEEK)) AND UNIX_TIMESTAMP(now()) ";
|
||||||
|
|
||||||
|
std::string filter;
|
||||||
|
// Setup our filter based on the query type
|
||||||
|
if (this->infoType == InfoType::Friends) filter += friendsFilter;
|
||||||
|
if (this->weekly) filter += weeklyFilter;
|
||||||
|
const auto orderBase = GetOrdering(this->leaderboardType);
|
||||||
|
|
||||||
|
// For top query, we want to just rank all scores, but for all others we need the scores around a specific player
|
||||||
|
std::string baseLookup;
|
||||||
|
if (this->infoType == InfoType::Top) {
|
||||||
|
baseLookup = "SELECT id, last_played FROM leaderboard WHERE game_id = ? " + (this->weekly ? weeklyFilter : std::string("")) + " ORDER BY ";
|
||||||
|
baseLookup += orderBase.data();
|
||||||
|
} else {
|
||||||
|
baseLookup = "SELECT id, last_played FROM leaderboard WHERE game_id = ? " + (this->weekly ? weeklyFilter : std::string("")) + " AND character_id = ";
|
||||||
|
baseLookup += std::to_string(static_cast<uint32_t>(this->relatedPlayer));
|
||||||
|
}
|
||||||
|
baseLookup += " LIMIT 1";
|
||||||
|
Game::logger->LogDebug("LeaderboardManager", "query is %s", baseLookup.c_str());
|
||||||
|
std::unique_ptr<sql::PreparedStatement> baseQuery(Database::CreatePreppedStmt(baseLookup));
|
||||||
|
baseQuery->setInt(1, this->gameID);
|
||||||
|
std::unique_ptr<sql::ResultSet> baseResult(baseQuery->executeQuery());
|
||||||
|
|
||||||
|
if (!baseResult->next()) return; // In this case, there are no entries in the leaderboard for this game.
|
||||||
|
|
||||||
|
uint32_t relatedPlayerLeaderboardId = baseResult->getInt("id");
|
||||||
|
|
||||||
|
// Create and execute the actual save here. Using a heap allocated buffer to avoid stack overflow
|
||||||
|
constexpr uint16_t STRING_LENGTH = 4096;
|
||||||
|
std::unique_ptr<char[]> lookupBuffer = std::make_unique<char[]>(STRING_LENGTH);
|
||||||
|
int32_t res = snprintf(lookupBuffer.get(), STRING_LENGTH, queryBase.c_str(), orderBase.data(), filter.c_str(), resultStart, resultEnd);
|
||||||
|
DluAssert(res != -1);
|
||||||
|
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt(lookupBuffer.get()));
|
||||||
|
Game::logger->LogDebug("LeaderboardManager", "Query is %s vars are %i %i %i", lookupBuffer.get(), this->gameID, this->relatedPlayer, relatedPlayerLeaderboardId);
|
||||||
|
query->setInt(1, this->gameID);
|
||||||
|
if (this->infoType == InfoType::Friends) {
|
||||||
|
query->setInt(2, this->relatedPlayer);
|
||||||
|
query->setInt(3, this->relatedPlayer);
|
||||||
|
query->setInt(4, this->relatedPlayer);
|
||||||
|
query->setInt(5, relatedPlayerLeaderboardId);
|
||||||
|
} else {
|
||||||
|
query->setInt(2, relatedPlayerLeaderboardId);
|
||||||
|
}
|
||||||
|
std::unique_ptr<sql::ResultSet> result(query->executeQuery());
|
||||||
|
QueryToLdf(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Leaderboard::Send(const LWOOBJID targetID) const {
|
||||||
|
auto* player = Game::entityManager->GetEntity(relatedPlayer);
|
||||||
if (player != nullptr) {
|
if (player != nullptr) {
|
||||||
GameMessages::SendActivitySummaryLeaderboardData(targetID, this, player->GetSystemAddress());
|
GameMessages::SendActivitySummaryLeaderboardData(targetID, this, player->GetSystemAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LeaderboardManager::SaveScore(LWOOBJID playerID, uint32_t gameID, uint32_t score, uint32_t time) {
|
std::string FormatInsert(const Leaderboard::Type& type, const Score& score, const bool useUpdate) {
|
||||||
const auto* player = EntityManager::Instance()->GetEntity(playerID);
|
std::string insertStatement;
|
||||||
if (player == nullptr)
|
if (useUpdate) {
|
||||||
return;
|
insertStatement =
|
||||||
|
R"QUERY(
|
||||||
|
UPDATE leaderboard
|
||||||
|
SET primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
|
||||||
|
timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;
|
||||||
|
)QUERY";
|
||||||
|
} else {
|
||||||
|
insertStatement =
|
||||||
|
R"QUERY(
|
||||||
|
INSERT leaderboard SET
|
||||||
|
primaryScore = %f, secondaryScore = %f, tertiaryScore = %f,
|
||||||
|
character_id = ?, game_id = ?;
|
||||||
|
)QUERY";
|
||||||
|
}
|
||||||
|
|
||||||
auto* character = player->GetCharacter();
|
constexpr uint16_t STRING_LENGTH = 400;
|
||||||
if (character == nullptr)
|
// Then fill in our score
|
||||||
return;
|
char finishedQuery[STRING_LENGTH];
|
||||||
|
int32_t res = snprintf(finishedQuery, STRING_LENGTH, insertStatement.c_str(), score.GetPrimaryScore(), score.GetSecondaryScore(), score.GetTertiaryScore());
|
||||||
|
DluAssert(res != -1);
|
||||||
|
return finishedQuery;
|
||||||
|
}
|
||||||
|
|
||||||
auto* select = Database::CreatePreppedStmt("SELECT time, score FROM leaderboard WHERE character_id = ? AND game_id = ?;");
|
void LeaderboardManager::SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore, const float tertiaryScore) {
|
||||||
|
const Leaderboard::Type leaderboardType = GetLeaderboardType(activityId);
|
||||||
|
auto* lookup = "SELECT * FROM leaderboard WHERE character_id = ? AND game_id = ?;";
|
||||||
|
|
||||||
select->setUInt64(1, character->GetID());
|
std::unique_ptr<sql::PreparedStatement> query(Database::CreatePreppedStmt(lookup));
|
||||||
select->setInt(2, gameID);
|
query->setInt(1, playerID);
|
||||||
|
query->setInt(2, activityId);
|
||||||
auto any = false;
|
std::unique_ptr<sql::ResultSet> myScoreResult(query->executeQuery());
|
||||||
auto* result = select->executeQuery();
|
|
||||||
auto leaderboardType = GetLeaderboardType(gameID);
|
|
||||||
|
|
||||||
// Check if the new score is a high score
|
|
||||||
while (result->next()) {
|
|
||||||
any = true;
|
|
||||||
|
|
||||||
const auto storedTime = result->getInt(1);
|
|
||||||
const auto storedScore = result->getInt(2);
|
|
||||||
auto highscore = true;
|
|
||||||
bool classicSurvivalScoring = Game::config->GetValue("classic_survival_scoring") == "1";
|
|
||||||
|
|
||||||
|
std::string saveQuery("UPDATE leaderboard SET timesPlayed = timesPlayed + 1 WHERE character_id = ? AND game_id = ?;");
|
||||||
|
Score newScore(primaryScore, secondaryScore, tertiaryScore);
|
||||||
|
if (myScoreResult->next()) {
|
||||||
|
Score oldScore;
|
||||||
|
bool lowerScoreBetter = false;
|
||||||
switch (leaderboardType) {
|
switch (leaderboardType) {
|
||||||
case ShootingGallery:
|
// Higher score better
|
||||||
if (score <= storedScore)
|
case Leaderboard::Type::ShootingGallery: {
|
||||||
highscore = false;
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
|
||||||
|
oldScore.SetTertiaryScore(myScoreResult->getInt("tertiaryScore"));
|
||||||
break;
|
break;
|
||||||
case Racing:
|
}
|
||||||
if (time >= storedTime)
|
case Leaderboard::Type::FootRace: {
|
||||||
highscore = false;
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
break;
|
break;
|
||||||
case MonumentRace:
|
}
|
||||||
if (time >= storedTime)
|
case Leaderboard::Type::Survival: {
|
||||||
highscore = false;
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
|
||||||
break;
|
break;
|
||||||
case FootRace:
|
}
|
||||||
if (time <= storedTime)
|
case Leaderboard::Type::SurvivalNS: {
|
||||||
highscore = false;
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
|
||||||
break;
|
break;
|
||||||
case Survival:
|
}
|
||||||
if (classicSurvivalScoring) {
|
case Leaderboard::Type::UnusedLeaderboard4:
|
||||||
if (time <= storedTime) { // Based on time (LU live)
|
case Leaderboard::Type::Donations: {
|
||||||
highscore = false;
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Leaderboard::Type::Racing: {
|
||||||
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
oldScore.SetSecondaryScore(myScoreResult->getInt("secondaryScore"));
|
||||||
|
|
||||||
|
// For wins we dont care about the score, just the time, so zero out the tertiary.
|
||||||
|
// Wins are updated later.
|
||||||
|
oldScore.SetTertiaryScore(0);
|
||||||
|
newScore.SetTertiaryScore(0);
|
||||||
|
lowerScoreBetter = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Leaderboard::Type::MonumentRace: {
|
||||||
|
oldScore.SetPrimaryScore(myScoreResult->getInt("primaryScore"));
|
||||||
|
lowerScoreBetter = true;
|
||||||
|
// Do score checking here
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Leaderboard::Type::None:
|
||||||
|
default:
|
||||||
|
Game::logger->Log("LeaderboardManager", "Unknown leaderboard type %i for game %i. Cannot save score!", leaderboardType, activityId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool newHighScore = lowerScoreBetter ? newScore < oldScore : newScore > oldScore;
|
||||||
|
// Nimbus station has a weird leaderboard where we need a custom scoring system
|
||||||
|
if (leaderboardType == Leaderboard::Type::SurvivalNS) {
|
||||||
|
newHighScore = newScore.GetPrimaryScore() > oldScore.GetPrimaryScore() ||
|
||||||
|
(newScore.GetPrimaryScore() == oldScore.GetPrimaryScore() && newScore.GetSecondaryScore() < oldScore.GetSecondaryScore());
|
||||||
|
} else if (leaderboardType == Leaderboard::Type::Survival && Game::config->GetValue("classic_survival_scoring") == "1") {
|
||||||
|
Score oldScoreFlipped(oldScore.GetSecondaryScore(), oldScore.GetPrimaryScore());
|
||||||
|
Score newScoreFlipped(newScore.GetSecondaryScore(), newScore.GetPrimaryScore());
|
||||||
|
newHighScore = newScoreFlipped > oldScoreFlipped;
|
||||||
|
}
|
||||||
|
if (newHighScore) {
|
||||||
|
saveQuery = FormatInsert(leaderboardType, newScore, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (score <= storedScore) // Based on score (DLU)
|
saveQuery = FormatInsert(leaderboardType, newScore, false);
|
||||||
highscore = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SurvivalNS:
|
|
||||||
if (!(score > storedScore || (time < storedTime && score >= storedScore)))
|
|
||||||
highscore = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
highscore = false;
|
|
||||||
}
|
}
|
||||||
|
Game::logger->Log("LeaderboardManager", "save query %s %i %i", saveQuery.c_str(), playerID, activityId);
|
||||||
|
std::unique_ptr<sql::PreparedStatement> saveStatement(Database::CreatePreppedStmt(saveQuery));
|
||||||
|
saveStatement->setInt(1, playerID);
|
||||||
|
saveStatement->setInt(2, activityId);
|
||||||
|
saveStatement->execute();
|
||||||
|
|
||||||
if (!highscore) {
|
// track wins separately
|
||||||
delete select;
|
if (leaderboardType == Leaderboard::Type::Racing && tertiaryScore != 0.0f) {
|
||||||
delete result;
|
std::unique_ptr<sql::PreparedStatement> winUpdate(Database::CreatePreppedStmt("UPDATE leaderboard SET numWins = numWins + 1 WHERE character_id = ? AND game_id = ?;"));
|
||||||
return;
|
winUpdate->setInt(1, playerID);
|
||||||
|
winUpdate->setInt(2, activityId);
|
||||||
|
winUpdate->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete select;
|
void LeaderboardManager::SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t resultStart, const uint32_t resultEnd) {
|
||||||
delete result;
|
Leaderboard leaderboard(gameID, infoType, weekly, playerID, GetLeaderboardType(gameID));
|
||||||
|
leaderboard.SetupLeaderboard(weekly, resultStart, resultEnd);
|
||||||
if (any) {
|
leaderboard.Send(targetID);
|
||||||
auto* statement = Database::CreatePreppedStmt("UPDATE leaderboard SET time = ?, score = ?, last_played=SYSDATE() WHERE character_id = ? AND game_id = ?;");
|
|
||||||
statement->setInt(1, time);
|
|
||||||
statement->setInt(2, score);
|
|
||||||
statement->setUInt64(3, character->GetID());
|
|
||||||
statement->setInt(4, gameID);
|
|
||||||
statement->execute();
|
|
||||||
|
|
||||||
delete statement;
|
|
||||||
} else {
|
|
||||||
// Note: last_played will be set to SYSDATE() by default when inserting into leaderboard
|
|
||||||
auto* statement = Database::CreatePreppedStmt("INSERT INTO leaderboard (character_id, game_id, time, score) VALUES (?, ?, ?, ?);");
|
|
||||||
statement->setUInt64(1, character->GetID());
|
|
||||||
statement->setInt(2, gameID);
|
|
||||||
statement->setInt(3, time);
|
|
||||||
statement->setInt(4, score);
|
|
||||||
statement->execute();
|
|
||||||
|
|
||||||
delete statement;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Leaderboard* LeaderboardManager::GetLeaderboard(uint32_t gameID, InfoType infoType, bool weekly, LWOOBJID playerID) {
|
Leaderboard::Type LeaderboardManager::GetLeaderboardType(const GameID gameID) {
|
||||||
auto leaderboardType = GetLeaderboardType(gameID);
|
auto lookup = leaderboardCache.find(gameID);
|
||||||
|
if (lookup != leaderboardCache.end()) return lookup->second;
|
||||||
|
|
||||||
std::string query;
|
|
||||||
bool classicSurvivalScoring = Game::config->GetValue("classic_survival_scoring") == "1";
|
|
||||||
switch (infoType) {
|
|
||||||
case InfoType::Standings:
|
|
||||||
switch (leaderboardType) {
|
|
||||||
case ShootingGallery:
|
|
||||||
query = standingsScoreQuery; // Shooting gallery is based on the highest score.
|
|
||||||
break;
|
|
||||||
case FootRace:
|
|
||||||
query = standingsTimeQuery; // The higher your time, the better for FootRace.
|
|
||||||
break;
|
|
||||||
case Survival:
|
|
||||||
query = classicSurvivalScoring ? standingsTimeQuery : standingsScoreQuery;
|
|
||||||
break;
|
|
||||||
case SurvivalNS:
|
|
||||||
query = standingsScoreQueryAsc; // BoNS is scored by highest wave (score) first, then time.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
query = standingsTimeQueryAsc; // MonumentRace and Racing are based on the shortest time.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case InfoType::Friends:
|
|
||||||
switch (leaderboardType) {
|
|
||||||
case ShootingGallery:
|
|
||||||
query = friendsScoreQuery; // Shooting gallery is based on the highest score.
|
|
||||||
break;
|
|
||||||
case FootRace:
|
|
||||||
query = friendsTimeQuery; // The higher your time, the better for FootRace.
|
|
||||||
break;
|
|
||||||
case Survival:
|
|
||||||
query = classicSurvivalScoring ? friendsTimeQuery : friendsScoreQuery;
|
|
||||||
break;
|
|
||||||
case SurvivalNS:
|
|
||||||
query = friendsScoreQueryAsc; // BoNS is scored by highest wave (score) first, then time.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
query = friendsTimeQueryAsc; // MonumentRace and Racing are based on the shortest time.
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
switch (leaderboardType) {
|
|
||||||
case ShootingGallery:
|
|
||||||
query = topPlayersScoreQuery; // Shooting gallery is based on the highest score.
|
|
||||||
break;
|
|
||||||
case FootRace:
|
|
||||||
query = topPlayersTimeQuery; // The higher your time, the better for FootRace.
|
|
||||||
break;
|
|
||||||
case Survival:
|
|
||||||
query = classicSurvivalScoring ? topPlayersTimeQuery : topPlayersScoreQuery;
|
|
||||||
break;
|
|
||||||
case SurvivalNS:
|
|
||||||
query = topPlayersScoreQueryAsc; // BoNS is scored by highest wave (score) first, then time.
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
query = topPlayersTimeQueryAsc; // MonumentRace and Racing are based on the shortest time.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* statement = Database::CreatePreppedStmt(query);
|
|
||||||
statement->setUInt(1, gameID);
|
|
||||||
|
|
||||||
// Only the standings and friends leaderboards require the character ID to be set
|
|
||||||
if (infoType == Standings || infoType == Friends) {
|
|
||||||
auto characterID = 0;
|
|
||||||
|
|
||||||
const auto* player = EntityManager::Instance()->GetEntity(playerID);
|
|
||||||
if (player != nullptr) {
|
|
||||||
auto* character = player->GetCharacter();
|
|
||||||
if (character != nullptr)
|
|
||||||
characterID = character->GetID();
|
|
||||||
}
|
|
||||||
|
|
||||||
statement->setUInt64(2, characterID);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* res = statement->executeQuery();
|
|
||||||
|
|
||||||
std::vector<LeaderboardEntry> entries{};
|
|
||||||
|
|
||||||
uint32_t index = 0;
|
|
||||||
while (res->next()) {
|
|
||||||
LeaderboardEntry entry;
|
|
||||||
entry.playerID = res->getUInt64(4);
|
|
||||||
entry.playerName = res->getString(5);
|
|
||||||
entry.time = res->getUInt(1);
|
|
||||||
entry.score = res->getUInt(2);
|
|
||||||
entry.placement = res->getUInt(3);
|
|
||||||
entry.lastPlayed = res->getUInt(6);
|
|
||||||
|
|
||||||
entries.push_back(entry);
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete res;
|
|
||||||
delete statement;
|
|
||||||
|
|
||||||
return new Leaderboard(gameID, infoType, weekly, entries, playerID, leaderboardType);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LeaderboardManager::SendLeaderboard(uint32_t gameID, InfoType infoType, bool weekly, LWOOBJID targetID,
|
|
||||||
LWOOBJID playerID) {
|
|
||||||
const auto* leaderboard = LeaderboardManager::GetLeaderboard(gameID, infoType, weekly, playerID);
|
|
||||||
leaderboard->Send(targetID);
|
|
||||||
delete leaderboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
LeaderboardType LeaderboardManager::GetLeaderboardType(uint32_t gameID) {
|
|
||||||
auto* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
auto* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
||||||
std::vector<CDActivities> activities = activitiesTable->Query([=](const CDActivities& entry) {
|
std::vector<CDActivities> activities = activitiesTable->Query([gameID](const CDActivities& entry) {
|
||||||
return (entry.ActivityID == gameID);
|
return entry.ActivityID == gameID;
|
||||||
});
|
});
|
||||||
|
auto type = !activities.empty() ? static_cast<Leaderboard::Type>(activities.at(0).leaderboardType) : Leaderboard::Type::None;
|
||||||
for (const auto& activity : activities) {
|
leaderboardCache.insert_or_assign(gameID, type);
|
||||||
return static_cast<LeaderboardType>(activity.leaderboardType);
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LeaderboardType::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::topPlayersScoreQuery =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
"RANK() OVER ( ORDER BY l.score DESC, l.time DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
"INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
"WHERE l.game_id = ? "
|
|
||||||
"ORDER BY leaderboard_rank) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales LIMIT 11;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::friendsScoreQuery =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.score DESC, l.time DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" INNER JOIN friends f ON f.player_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
" personal_values AS ( "
|
|
||||||
" SELECT id as related_player_id, "
|
|
||||||
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::standingsScoreQuery =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.score DESC, l.time DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
"personal_values AS ( "
|
|
||||||
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::topPlayersScoreQueryAsc =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
"RANK() OVER ( ORDER BY l.score DESC, l.time ASC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
"INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
"WHERE l.game_id = ? "
|
|
||||||
"ORDER BY leaderboard_rank) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales LIMIT 11;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::friendsScoreQueryAsc =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.score DESC, l.time ASC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" INNER JOIN friends f ON f.player_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
" personal_values AS ( "
|
|
||||||
" SELECT id as related_player_id, "
|
|
||||||
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::standingsScoreQueryAsc =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.score DESC, l.time ASC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
"personal_values AS ( "
|
|
||||||
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::topPlayersTimeQuery =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
"RANK() OVER ( ORDER BY l.time DESC, l.score DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
"INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
"WHERE l.game_id = ? "
|
|
||||||
"ORDER BY leaderboard_rank) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales LIMIT 11;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::friendsTimeQuery =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.time DESC, l.score DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" INNER JOIN friends f ON f.player_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
" personal_values AS ( "
|
|
||||||
" SELECT id as related_player_id, "
|
|
||||||
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::standingsTimeQuery =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.time DESC, l.score DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
"personal_values AS ( "
|
|
||||||
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::topPlayersTimeQueryAsc =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
"RANK() OVER ( ORDER BY l.time ASC, l.score DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
"INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
"WHERE l.game_id = ? "
|
|
||||||
"ORDER BY leaderboard_rank) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales LIMIT 11;";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::friendsTimeQueryAsc =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, f.friend_id, f.player_id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.time ASC, l.score DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" INNER JOIN friends f ON f.player_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
" personal_values AS ( "
|
|
||||||
" SELECT id as related_player_id, "
|
|
||||||
" GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE leaderboard_vales.id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank AND (player_id = related_player_id OR friend_id = related_player_id);";
|
|
||||||
|
|
||||||
const std::string LeaderboardManager::standingsTimeQueryAsc =
|
|
||||||
"WITH leaderboard_vales AS ( "
|
|
||||||
" SELECT l.time, l.score, UNIX_TIMESTAMP(l.last_played) last_played, c.name, c.id, "
|
|
||||||
" RANK() OVER ( ORDER BY l.time ASC, l.score DESC, last_played ) leaderboard_rank "
|
|
||||||
" FROM leaderboard l "
|
|
||||||
" INNER JOIN charinfo c ON l.character_id = c.id "
|
|
||||||
" WHERE l.game_id = ? "
|
|
||||||
" ORDER BY leaderboard_rank), "
|
|
||||||
"personal_values AS ( "
|
|
||||||
" SELECT GREATEST(CAST(leaderboard_rank AS SIGNED) - 5, 1) AS min_rank, "
|
|
||||||
" GREATEST(leaderboard_rank + 5, 11) AS max_rank "
|
|
||||||
" FROM leaderboard_vales WHERE id = ? LIMIT 1) "
|
|
||||||
"SELECT time, score, leaderboard_rank, id, name, last_played "
|
|
||||||
"FROM leaderboard_vales, personal_values "
|
|
||||||
"WHERE leaderboard_rank BETWEEN min_rank AND max_rank;";
|
|
||||||
|
@ -1,80 +1,134 @@
|
|||||||
#pragma once
|
#ifndef __LEADERBOARDMANAGER__H__
|
||||||
#include <vector>
|
#define __LEADERBOARDMANAGER__H__
|
||||||
#include <climits>
|
|
||||||
#include "dCommonVars.h"
|
|
||||||
|
|
||||||
struct LeaderboardEntry {
|
#include <map>
|
||||||
uint64_t playerID;
|
#include <memory>
|
||||||
std::string playerName;
|
#include <string_view>
|
||||||
uint32_t time;
|
#include <vector>
|
||||||
uint32_t score;
|
|
||||||
uint32_t placement;
|
#include "Singleton.h"
|
||||||
time_t lastPlayed;
|
#include "dCommonVars.h"
|
||||||
|
#include "LDFFormat.h"
|
||||||
|
|
||||||
|
namespace sql {
|
||||||
|
class ResultSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace RakNet {
|
||||||
|
class BitStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Score {
|
||||||
|
public:
|
||||||
|
Score() {
|
||||||
|
primaryScore = 0;
|
||||||
|
secondaryScore = 0;
|
||||||
|
tertiaryScore = 0;
|
||||||
|
}
|
||||||
|
Score(const float primaryScore, const float secondaryScore = 0, const float tertiaryScore = 0) {
|
||||||
|
this->primaryScore = primaryScore;
|
||||||
|
this->secondaryScore = secondaryScore;
|
||||||
|
this->tertiaryScore = tertiaryScore;
|
||||||
|
}
|
||||||
|
bool operator<(const Score& rhs) const {
|
||||||
|
return primaryScore < rhs.primaryScore || (primaryScore == rhs.primaryScore && secondaryScore < rhs.secondaryScore) || (primaryScore == rhs.primaryScore && secondaryScore == rhs.secondaryScore && tertiaryScore < rhs.tertiaryScore);
|
||||||
|
}
|
||||||
|
bool operator>(const Score& rhs) const {
|
||||||
|
return primaryScore > rhs.primaryScore || (primaryScore == rhs.primaryScore && secondaryScore > rhs.secondaryScore) || (primaryScore == rhs.primaryScore && secondaryScore == rhs.secondaryScore && tertiaryScore > rhs.tertiaryScore);
|
||||||
|
}
|
||||||
|
void SetPrimaryScore(const float score) { primaryScore = score; }
|
||||||
|
float GetPrimaryScore() const { return primaryScore; }
|
||||||
|
|
||||||
|
void SetSecondaryScore(const float score) { secondaryScore = score; }
|
||||||
|
float GetSecondaryScore() const { return secondaryScore; }
|
||||||
|
|
||||||
|
void SetTertiaryScore(const float score) { tertiaryScore = score; }
|
||||||
|
float GetTertiaryScore() const { return tertiaryScore; }
|
||||||
|
private:
|
||||||
|
float primaryScore;
|
||||||
|
float secondaryScore;
|
||||||
|
float tertiaryScore;
|
||||||
|
};
|
||||||
|
|
||||||
|
using GameID = uint32_t;
|
||||||
|
|
||||||
|
class Leaderboard {
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Enums for leaderboards
|
||||||
enum InfoType : uint32_t {
|
enum InfoType : uint32_t {
|
||||||
Top, // Top 11 all time players
|
Top, // Top 11 all time players
|
||||||
Standings, // Ranking of the current player
|
MyStanding, // Ranking of the current player
|
||||||
Friends // Ranking between friends
|
Friends // Ranking between friends
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LeaderboardType : uint32_t {
|
enum Type : uint32_t {
|
||||||
ShootingGallery,
|
ShootingGallery,
|
||||||
Racing,
|
Racing,
|
||||||
MonumentRace,
|
MonumentRace,
|
||||||
FootRace,
|
FootRace,
|
||||||
Survival = 5,
|
UnusedLeaderboard4, // There is no 4 defined anywhere in the cdclient, but it takes a Score.
|
||||||
SurvivalNS = 6,
|
Survival,
|
||||||
None = UINT_MAX
|
SurvivalNS,
|
||||||
|
Donations,
|
||||||
|
None
|
||||||
};
|
};
|
||||||
|
Leaderboard() = delete;
|
||||||
|
Leaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, LWOOBJID relatedPlayer, const Leaderboard::Type = None);
|
||||||
|
|
||||||
class Leaderboard {
|
~Leaderboard();
|
||||||
public:
|
|
||||||
Leaderboard(uint32_t gameID, uint32_t infoType, bool weekly, std::vector<LeaderboardEntry> entries,
|
/**
|
||||||
LWOOBJID relatedPlayer = LWOOBJID_EMPTY, LeaderboardType = None);
|
* @brief Resets the leaderboard state and frees its allocated memory
|
||||||
std::vector<LeaderboardEntry> GetEntries();
|
*
|
||||||
[[nodiscard]] std::u16string ToString() const;
|
*/
|
||||||
[[nodiscard]] uint32_t GetGameID() const;
|
void Clear();
|
||||||
[[nodiscard]] uint32_t GetInfoType() const;
|
|
||||||
void Send(LWOOBJID targetID) const;
|
/**
|
||||||
|
* Serialize the Leaderboard to a BitStream
|
||||||
|
*
|
||||||
|
* Expensive! Leaderboards are very string intensive so be wary of performatnce calling this method.
|
||||||
|
*/
|
||||||
|
void Serialize(RakNet::BitStream* bitStream) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the leaderboard from the database based on the associated gameID
|
||||||
|
*
|
||||||
|
* @param resultStart The index to start the leaderboard at. Zero indexed.
|
||||||
|
* @param resultEnd The index to end the leaderboard at. Zero indexed.
|
||||||
|
*/
|
||||||
|
void SetupLeaderboard(bool weekly, uint32_t resultStart = 0, uint32_t resultEnd = 10);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends the leaderboard to the client specified by targetID.
|
||||||
|
*/
|
||||||
|
void Send(const LWOOBJID targetID) const;
|
||||||
|
|
||||||
|
// Helper function to get the columns, ordering and insert format for a leaderboard
|
||||||
|
static const std::string_view GetOrdering(Type leaderboardType);
|
||||||
private:
|
private:
|
||||||
std::vector<LeaderboardEntry> entries{};
|
// Takes the resulting query from a leaderboard lookup and converts it to the LDF we need
|
||||||
|
// to send it to a client.
|
||||||
|
void QueryToLdf(std::unique_ptr<sql::ResultSet>& rows);
|
||||||
|
|
||||||
|
using LeaderboardEntry = std::vector<LDFBaseData*>;
|
||||||
|
using LeaderboardEntries = std::vector<LeaderboardEntry>;
|
||||||
|
|
||||||
|
LeaderboardEntries entries;
|
||||||
LWOOBJID relatedPlayer;
|
LWOOBJID relatedPlayer;
|
||||||
uint32_t gameID;
|
GameID gameID;
|
||||||
uint32_t infoType;
|
InfoType infoType;
|
||||||
LeaderboardType leaderboardType;
|
Leaderboard::Type leaderboardType;
|
||||||
bool weekly;
|
bool weekly;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LeaderboardManager {
|
namespace LeaderboardManager {
|
||||||
public:
|
void SendLeaderboard(const GameID gameID, const Leaderboard::InfoType infoType, const bool weekly, const LWOOBJID playerID, const LWOOBJID targetID, const uint32_t resultStart = 0, const uint32_t resultEnd = 10);
|
||||||
static LeaderboardManager* Instance() {
|
|
||||||
if (address == nullptr)
|
|
||||||
address = new LeaderboardManager;
|
|
||||||
return address;
|
|
||||||
}
|
|
||||||
static void SendLeaderboard(uint32_t gameID, InfoType infoType, bool weekly, LWOOBJID targetID,
|
|
||||||
LWOOBJID playerID = LWOOBJID_EMPTY);
|
|
||||||
static Leaderboard* GetLeaderboard(uint32_t gameID, InfoType infoType, bool weekly, LWOOBJID playerID = LWOOBJID_EMPTY);
|
|
||||||
static void SaveScore(LWOOBJID playerID, uint32_t gameID, uint32_t score, uint32_t time);
|
|
||||||
static LeaderboardType GetLeaderboardType(uint32_t gameID);
|
|
||||||
private:
|
|
||||||
static LeaderboardManager* address;
|
|
||||||
|
|
||||||
// Modified 12/12/2021: Existing queries were renamed to be more descriptive.
|
void SaveScore(const LWOOBJID& playerID, const GameID activityId, const float primaryScore, const float secondaryScore = 0, const float tertiaryScore = 0);
|
||||||
static const std::string topPlayersScoreQuery;
|
|
||||||
static const std::string friendsScoreQuery;
|
|
||||||
static const std::string standingsScoreQuery;
|
|
||||||
static const std::string topPlayersScoreQueryAsc;
|
|
||||||
static const std::string friendsScoreQueryAsc;
|
|
||||||
static const std::string standingsScoreQueryAsc;
|
|
||||||
|
|
||||||
// Added 12/12/2021: Queries dictated by time are needed for certain minigames.
|
Leaderboard::Type GetLeaderboardType(const GameID gameID);
|
||||||
static const std::string topPlayersTimeQuery;
|
extern std::map<GameID, Leaderboard::Type> leaderboardCache;
|
||||||
static const std::string friendsTimeQuery;
|
|
||||||
static const std::string standingsTimeQuery;
|
|
||||||
static const std::string topPlayersTimeQueryAsc;
|
|
||||||
static const std::string friendsTimeQueryAsc;
|
|
||||||
static const std::string standingsTimeQueryAsc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //!__LEADERBOARDMANAGER__H__
|
||||||
|
@ -62,7 +62,7 @@ void Player::SetSystemAddress(const SystemAddress& value) {
|
|||||||
void Player::SetRespawnPos(const NiPoint3 position) {
|
void Player::SetRespawnPos(const NiPoint3 position) {
|
||||||
m_respawnPos = position;
|
m_respawnPos = position;
|
||||||
|
|
||||||
m_Character->SetRespawnPoint(dZoneManager::Instance()->GetZone()->GetWorldID(), position);
|
m_Character->SetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID(), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SetRespawnRot(const NiQuaternion rotation) {
|
void Player::SetRespawnRot(const NiQuaternion rotation) {
|
||||||
@ -85,7 +85,7 @@ void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) {
|
|||||||
const auto objid = GetObjectID();
|
const auto objid = GetObjectID();
|
||||||
|
|
||||||
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneId, cloneId, false, [objid](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
|
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, zoneId, cloneId, false, [objid](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(objid);
|
auto* entity = Game::entityManager->GetEntity(objid);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -108,7 +108,7 @@ void Player::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) {
|
|||||||
|
|
||||||
WorldPackets::SendTransferToWorld(sysAddr, serverIP, serverPort, mythranShift);
|
WorldPackets::SendTransferToWorld(sysAddr, serverIP, serverPort, mythranShift);
|
||||||
|
|
||||||
EntityManager::Instance()->DestructEntity(entity);
|
Game::entityManager->DestructEntity(entity);
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -135,13 +135,13 @@ void Player::RemoveLimboConstruction(LWOOBJID objectId) {
|
|||||||
|
|
||||||
void Player::ConstructLimboEntities() {
|
void Player::ConstructLimboEntities() {
|
||||||
for (const auto objectId : m_LimboConstructions) {
|
for (const auto objectId : m_LimboConstructions) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(objectId);
|
auto* entity = Game::entityManager->GetEntity(objectId);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->ConstructEntity(entity, m_SystemAddress);
|
Game::entityManager->ConstructEntity(entity, m_SystemAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_LimboConstructions.clear();
|
m_LimboConstructions.clear();
|
||||||
@ -224,7 +224,7 @@ Player* Player::GetPlayer(const SystemAddress& sysAddr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Player* Player::GetPlayer(const std::string& name) {
|
Player* Player::GetPlayer(const std::string& name) {
|
||||||
const auto characters = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
|
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
|
||||||
|
|
||||||
for (auto* character : characters) {
|
for (auto* character : characters) {
|
||||||
if (!character->IsPlayer()) continue;
|
if (!character->IsPlayer()) continue;
|
||||||
@ -269,7 +269,7 @@ Player::~Player() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetGhostCandidate(id);
|
auto* entity = Game::entityManager->GetGhostCandidate(id);
|
||||||
|
|
||||||
if (entity != nullptr) {
|
if (entity != nullptr) {
|
||||||
entity->SetObservers(entity->GetObservers() - 1);
|
entity->SetObservers(entity->GetObservers() - 1);
|
||||||
@ -285,12 +285,12 @@ Player::~Player() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IsPlayer()) {
|
if (IsPlayer()) {
|
||||||
Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity();
|
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
||||||
script->OnPlayerExit(zoneControl, this);
|
script->OnPlayerExit(zoneControl, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Entity*> scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
||||||
for (Entity* scriptEntity : scriptedActs) {
|
for (Entity* scriptEntity : scriptedActs) {
|
||||||
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
||||||
|
@ -40,11 +40,11 @@ LWOOBJID Trade::GetParticipantB() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity* Trade::GetParticipantAEntity() const {
|
Entity* Trade::GetParticipantAEntity() const {
|
||||||
return EntityManager::Instance()->GetEntity(m_ParticipantA);
|
return Game::entityManager->GetEntity(m_ParticipantA);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* Trade::GetParticipantBEntity() const {
|
Entity* Trade::GetParticipantBEntity() const {
|
||||||
return EntityManager::Instance()->GetEntity(m_ParticipantB);
|
return Game::entityManager->GetEntity(m_ParticipantB);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Trade::SetCoins(LWOOBJID participant, uint64_t coins) {
|
void Trade::SetCoins(LWOOBJID participant, uint64_t coins) {
|
||||||
|
@ -220,7 +220,7 @@ void UserManager::RequestCharacterList(const SystemAddress& sysAddr) {
|
|||||||
skillComponent->Reset();
|
skillComponent->Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->DestroyEntity(chars[i]->GetEntity());
|
Game::entityManager->DestroyEntity(chars[i]->GetEntity());
|
||||||
|
|
||||||
chars[i]->SaveXMLToDatabase();
|
chars[i]->SaveXMLToDatabase();
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ void AirMovementBehavior::Sync(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
|
|
||||||
auto* behavior = CreateBehavior(behaviorId);
|
auto* behavior = CreateBehavior(behaviorId);
|
||||||
|
|
||||||
if (EntityManager::Instance()->GetEntity(target) != nullptr) {
|
if (Game::entityManager->GetEntity(target) != nullptr) {
|
||||||
branch.target = target;
|
branch.target = target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target == LWOOBJID_EMPTY ? context->originator : branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target == LWOOBJID_EMPTY ? context->originator : branch.target);
|
||||||
|
|
||||||
if (entity == nullptr) return;
|
if (entity == nullptr) return;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (entity == nullptr) return;
|
if (entity == nullptr) return;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream* b
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* self = EntityManager::Instance()->GetEntity(context->caster);
|
auto* self = Game::entityManager->GetEntity(context->caster);
|
||||||
if (self == nullptr) {
|
if (self == nullptr) {
|
||||||
Game::logger->Log("AreaOfEffectBehavior", "Invalid self for (%llu)!", context->originator);
|
Game::logger->Log("AreaOfEffectBehavior", "Invalid self for (%llu)!", context->originator);
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
|
|||||||
|
|
||||||
std::vector<Entity*> targets;
|
std::vector<Entity*> targets;
|
||||||
|
|
||||||
auto* presetTarget = EntityManager::Instance()->GetEntity(branch.target);
|
auto* presetTarget = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (presetTarget != nullptr) {
|
if (presetTarget != nullptr) {
|
||||||
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition())) {
|
if (this->m_radius * this->m_radius >= Vector3::DistanceSquared(reference, presetTarget->GetPosition())) {
|
||||||
@ -75,7 +75,7 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
|
|||||||
|
|
||||||
// Gets all of the valid targets, passing in if should target enemies and friends
|
// Gets all of the valid targets, passing in if should target enemies and friends
|
||||||
for (auto validTarget : context->GetValidTargets(m_ignoreFaction, includeFaction, m_TargetSelf == 1, m_targetEnemy == 1, m_targetFriend == 1)) {
|
for (auto validTarget : context->GetValidTargets(m_ignoreFaction, includeFaction, m_TargetSelf == 1, m_targetEnemy == 1, m_targetFriend == 1)) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(validTarget);
|
auto* entity = Game::entityManager->GetEntity(validTarget);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("AreaOfEffectBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
|
Game::logger->Log("AreaOfEffectBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
if (context->unmanaged) {
|
if (context->unmanaged) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = entity->GetComponent<DestroyableComponent>();
|
||||||
if (destroyableComponent != nullptr) {
|
if (destroyableComponent != nullptr) {
|
||||||
@ -38,7 +38,7 @@ void BasicAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* targetEntity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* targetEntity = Game::entityManager->GetEntity(branch.target);
|
||||||
if (!targetEntity) {
|
if (!targetEntity) {
|
||||||
Game::logger->Log("BasicAttackBehavior", "Target targetEntity %llu not found.", branch.target);
|
Game::logger->Log("BasicAttackBehavior", "Target targetEntity %llu not found.", branch.target);
|
||||||
return;
|
return;
|
||||||
@ -61,7 +61,7 @@ void BasicAttackBehavior::DoHandleBehavior(BehaviorContext* context, RakNet::Bit
|
|||||||
|
|
||||||
if (isBlocked) {
|
if (isBlocked) {
|
||||||
destroyableComponent->SetAttacksToBlock(std::min(destroyableComponent->GetAttacksToBlock() - 1, 0U));
|
destroyableComponent->SetAttacksToBlock(std::min(destroyableComponent->GetAttacksToBlock() - 1, 0U));
|
||||||
EntityManager::Instance()->SerializeEntity(targetEntity);
|
Game::entityManager->SerializeEntity(targetEntity);
|
||||||
this->m_OnFailBlocked->Handle(context, bitStream, branch);
|
this->m_OnFailBlocked->Handle(context, bitStream, branch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ void BasicAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream*
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* targetEntity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* targetEntity = Game::entityManager->GetEntity(branch.target);
|
||||||
if (!targetEntity) {
|
if (!targetEntity) {
|
||||||
Game::logger->Log("BasicAttackBehavior", "Target entity %llu is null!", branch.target);
|
Game::logger->Log("BasicAttackBehavior", "Target entity %llu is null!", branch.target);
|
||||||
return;
|
return;
|
||||||
@ -173,7 +173,7 @@ void BasicAttackBehavior::DoBehaviorCalculation(BehaviorContext* context, RakNet
|
|||||||
|
|
||||||
if (isBlocking) {
|
if (isBlocking) {
|
||||||
destroyableComponent->SetAttacksToBlock(destroyableComponent->GetAttacksToBlock() - 1);
|
destroyableComponent->SetAttacksToBlock(destroyableComponent->GetAttacksToBlock() - 1);
|
||||||
EntityManager::Instance()->SerializeEntity(targetEntity);
|
Game::entityManager->SerializeEntity(targetEntity);
|
||||||
this->m_OnFailBlocked->Calculate(context, bitStream, branch);
|
this->m_OnFailBlocked->Calculate(context, bitStream, branch);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include "SpeedBehavior.h"
|
#include "SpeedBehavior.h"
|
||||||
#include "DamageReductionBehavior.h"
|
#include "DamageReductionBehavior.h"
|
||||||
#include "JetPackBehavior.h"
|
#include "JetPackBehavior.h"
|
||||||
|
#include "FallSpeedBehavior.h"
|
||||||
#include "ChangeIdleFlagsBehavior.h"
|
#include "ChangeIdleFlagsBehavior.h"
|
||||||
#include "DarkInspirationBehavior.h"
|
#include "DarkInspirationBehavior.h"
|
||||||
|
|
||||||
@ -164,7 +165,9 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
|
|||||||
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
|
case BehaviorTemplates::BEHAVIOR_CAR_BOOST:
|
||||||
behavior = new CarBoostBehavior(behaviorId);
|
behavior = new CarBoostBehavior(behaviorId);
|
||||||
break;
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_FALL_SPEED: break;
|
case BehaviorTemplates::BEHAVIOR_FALL_SPEED:
|
||||||
|
behavior = new FallSpeedBehavior(behaviorId);
|
||||||
|
break;
|
||||||
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
|
case BehaviorTemplates::BEHAVIOR_SHIELD: break;
|
||||||
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
|
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR:
|
||||||
behavior = new RepairBehavior(behaviorId);
|
behavior = new RepairBehavior(behaviorId);
|
||||||
@ -311,7 +314,7 @@ BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
|
|||||||
|
|
||||||
// For use with enemies, to display the correct damage animations on the players
|
// For use with enemies, to display the correct damage animations on the players
|
||||||
void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID secondary) {
|
void Behavior::PlayFx(std::u16string type, const LWOOBJID target, const LWOOBJID secondary) {
|
||||||
auto* targetEntity = EntityManager::Instance()->GetEntity(target);
|
auto* targetEntity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (targetEntity == nullptr) {
|
if (targetEntity == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -27,7 +27,7 @@ BehaviorEndEntry::BehaviorEndEntry() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t BehaviorContext::GetUniqueSkillId() const {
|
uint32_t BehaviorContext::GetUniqueSkillId() const {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(this->originator);
|
auto* entity = Game::entityManager->GetEntity(this->originator);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!", this->originator);
|
Game::logger->Log("BehaviorContext", "Invalid entity for (%llu)!", this->originator);
|
||||||
@ -94,11 +94,11 @@ void BehaviorContext::ScheduleUpdate(const LWOOBJID id) {
|
|||||||
|
|
||||||
void BehaviorContext::ExecuteUpdates() {
|
void BehaviorContext::ExecuteUpdates() {
|
||||||
for (const auto& id : this->scheduledUpdates) {
|
for (const auto& id : this->scheduledUpdates) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(id);
|
auto* entity = Game::entityManager->GetEntity(id);
|
||||||
|
|
||||||
if (entity == nullptr) continue;
|
if (entity == nullptr) continue;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(entity);
|
Game::entityManager->SerializeEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->scheduledUpdates.clear();
|
this->scheduledUpdates.clear();
|
||||||
@ -308,7 +308,7 @@ void BehaviorContext::Reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, int32_t includeFaction, bool targetSelf, bool targetEnemy, bool targetFriend) const {
|
std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, int32_t includeFaction, bool targetSelf, bool targetEnemy, bool targetFriend) const {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(this->caster);
|
auto* entity = Game::entityManager->GetEntity(this->caster);
|
||||||
|
|
||||||
std::vector<LWOOBJID> targets;
|
std::vector<LWOOBJID> targets;
|
||||||
|
|
||||||
@ -320,7 +320,7 @@ std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, in
|
|||||||
|
|
||||||
if (!ignoreFaction && !includeFaction) {
|
if (!ignoreFaction && !includeFaction) {
|
||||||
for (auto entry : entity->GetTargetsInPhantom()) {
|
for (auto entry : entity->GetTargetsInPhantom()) {
|
||||||
auto* instance = EntityManager::Instance()->GetEntity(entry);
|
auto* instance = Game::entityManager->GetEntity(entry);
|
||||||
|
|
||||||
if (instance == nullptr) {
|
if (instance == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -336,7 +336,7 @@ std::vector<LWOOBJID> BehaviorContext::GetValidTargets(int32_t ignoreFaction, in
|
|||||||
return targets;
|
return targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto entities = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
auto entities = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
||||||
for (auto* candidate : entities) {
|
for (auto* candidate : entities) {
|
||||||
const auto id = candidate->GetObjectID();
|
const auto id = candidate->GetObjectID();
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void BlockBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
const auto target = context->originator;
|
const auto target = context->originator;
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
auto* entity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -40,7 +40,7 @@ void BlockBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitSt
|
|||||||
void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void BlockBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
const auto target = context->originator;
|
const auto target = context->originator;
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
auto* entity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
|
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
auto* entity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!", target);
|
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!", target);
|
||||||
@ -30,7 +30,7 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream
|
|||||||
component->SetMaxArmor(component->GetMaxArmor() + this->m_armor);
|
component->SetMaxArmor(component->GetMaxArmor() + this->m_armor);
|
||||||
component->SetMaxImagination(component->GetMaxImagination() + this->m_imagination);
|
component->SetMaxImagination(component->GetMaxImagination() + this->m_imagination);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(entity);
|
Game::entityManager->SerializeEntity(entity);
|
||||||
|
|
||||||
if (!context->unmanaged) {
|
if (!context->unmanaged) {
|
||||||
if (branch.duration > 0) {
|
if (branch.duration > 0) {
|
||||||
@ -44,7 +44,7 @@ void BuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream
|
|||||||
void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
|
const auto target = branch.target != LWOOBJID_EMPTY ? branch.target : context->originator;
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
auto* entity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!", target);
|
Game::logger->Log("BuffBehavior", "Invalid target (%llu)!", target);
|
||||||
@ -64,7 +64,7 @@ void BuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch
|
|||||||
component->SetMaxArmor(component->GetMaxArmor() - this->m_armor);
|
component->SetMaxArmor(component->GetMaxArmor() - this->m_armor);
|
||||||
component->SetMaxImagination(component->GetMaxImagination() - this->m_imagination);
|
component->SetMaxImagination(component->GetMaxImagination() - this->m_imagination);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(entity);
|
Game::entityManager->SerializeEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuffBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second) {
|
void BuffBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, LWOOBJID second) {
|
||||||
|
@ -22,6 +22,7 @@ set(DGAME_DBEHAVIORS_SOURCES "AirMovementBehavior.cpp"
|
|||||||
"DurationBehavior.cpp"
|
"DurationBehavior.cpp"
|
||||||
"EmptyBehavior.cpp"
|
"EmptyBehavior.cpp"
|
||||||
"EndBehavior.cpp"
|
"EndBehavior.cpp"
|
||||||
|
"FallSpeedBehavior.cpp"
|
||||||
"ForceMovementBehavior.cpp"
|
"ForceMovementBehavior.cpp"
|
||||||
"HealBehavior.cpp"
|
"HealBehavior.cpp"
|
||||||
"ImaginationBehavior.cpp"
|
"ImaginationBehavior.cpp"
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
GameMessages::SendVehicleAddPassiveBoostAction(branch.target, UNASSIGNED_SYSTEM_ADDRESS);
|
GameMessages::SendVehicleAddPassiveBoostAction(branch.target, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -22,7 +22,7 @@ void CarBoostBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitSt
|
|||||||
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
|
auto* possessableComponent = entity->GetComponent<PossessableComponent>();
|
||||||
if (possessableComponent != nullptr) {
|
if (possessableComponent != nullptr) {
|
||||||
|
|
||||||
auto* possessor = EntityManager::Instance()->GetEntity(possessableComponent->GetPossessor());
|
auto* possessor = Game::entityManager->GetEntity(possessableComponent->GetPossessor());
|
||||||
if (possessor != nullptr) {
|
if (possessor != nullptr) {
|
||||||
|
|
||||||
auto* characterComponent = possessor->GetComponent<CharacterComponent>();
|
auto* characterComponent = possessor->GetComponent<CharacterComponent>();
|
||||||
|
@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
Entity* sourceEntity;
|
Entity* sourceEntity;
|
||||||
if (this->m_orientCaster) sourceEntity = EntityManager::Instance()->GetEntity(context->originator);
|
if (this->m_orientCaster) sourceEntity = Game::entityManager->GetEntity(context->originator);
|
||||||
else sourceEntity = EntityManager::Instance()->GetEntity(branch.target);
|
else sourceEntity = Game::entityManager->GetEntity(branch.target);
|
||||||
if (!sourceEntity) return;
|
if (!sourceEntity) return;
|
||||||
|
|
||||||
if (this->m_toTarget) {
|
if (this->m_toTarget) {
|
||||||
Entity* destinationEntity;
|
Entity* destinationEntity;
|
||||||
if (this->m_orientCaster) destinationEntity = EntityManager::Instance()->GetEntity(branch.target);
|
if (this->m_orientCaster) destinationEntity = Game::entityManager->GetEntity(branch.target);
|
||||||
else destinationEntity = EntityManager::Instance()->GetEntity(context->originator);
|
else destinationEntity = Game::entityManager->GetEntity(context->originator);
|
||||||
if (!destinationEntity) return;
|
if (!destinationEntity) return;
|
||||||
|
|
||||||
sourceEntity->SetRotation(
|
sourceEntity->SetRotation(
|
||||||
@ -23,7 +23,7 @@ void ChangeOrientationBehavior::Calculate(BehaviorContext* context, RakNet::BitS
|
|||||||
if (this->m_relative) baseAngle += sourceEntity->GetRotation().GetForwardVector();
|
if (this->m_relative) baseAngle += sourceEntity->GetRotation().GetForwardVector();
|
||||||
sourceEntity->SetRotation(NiQuaternion::FromEulerAngles(baseAngle));
|
sourceEntity->SetRotation(NiQuaternion::FromEulerAngles(baseAngle));
|
||||||
} else return;
|
} else return;
|
||||||
EntityManager::Instance()->SerializeEntity(sourceEntity);
|
Game::entityManager->SerializeEntity(sourceEntity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "DestroyableComponent.h"
|
#include "DestroyableComponent.h"
|
||||||
|
|
||||||
void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
void DamageAbsorptionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -34,7 +34,7 @@ void DamageAbsorptionBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
|
void DamageAbsorptionBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(second);
|
auto* target = Game::entityManager->GetEntity(second);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", second);
|
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", second);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "DestroyableComponent.h"
|
#include "DestroyableComponent.h"
|
||||||
|
|
||||||
void DamageReductionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
void DamageReductionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("DamageReductionBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("DamageReductionBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -32,7 +32,7 @@ void DamageReductionBehavior::Calculate(BehaviorContext* context, RakNet::BitStr
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DamageReductionBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
|
void DamageReductionBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(second);
|
auto* target = Game::entityManager->GetEntity(second);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("DamageReductionBehavior", "Failed to find target (%llu)!", second);
|
Game::logger->Log("DamageReductionBehavior", "Failed to find target (%llu)!", second);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "BehaviorContext.h"
|
#include "BehaviorContext.h"
|
||||||
|
|
||||||
void DarkInspirationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
void DarkInspirationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->LogDebug("DarkInspirationBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->LogDebug("DarkInspirationBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -26,7 +26,7 @@ void DarkInspirationBehavior::Handle(BehaviorContext* context, RakNet::BitStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DarkInspirationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void DarkInspirationBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->LogDebug("DarkInspirationBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->LogDebug("DarkInspirationBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
|
50
dGame/dBehaviors/FallSpeedBehavior.cpp
Normal file
50
dGame/dBehaviors/FallSpeedBehavior.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "FallSpeedBehavior.h"
|
||||||
|
|
||||||
|
#include "ControllablePhysicsComponent.h"
|
||||||
|
#include "BehaviorContext.h"
|
||||||
|
#include "BehaviorBranchContext.h"
|
||||||
|
|
||||||
|
|
||||||
|
void FallSpeedBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
|
// make sure required parameter has non-default value
|
||||||
|
if (m_PercentSlowed == 0.0f) return;
|
||||||
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||||
|
if (!controllablePhysicsComponent) return;
|
||||||
|
controllablePhysicsComponent->SetGravityScale(m_PercentSlowed);
|
||||||
|
Game::entityManager->SerializeEntity(target);
|
||||||
|
|
||||||
|
if (branch.duration > 0.0f) {
|
||||||
|
context->RegisterTimerBehavior(this, branch);
|
||||||
|
} else if (branch.start > 0) {
|
||||||
|
context->RegisterEndBehavior(this, branch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FallSpeedBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
|
Handle(context, bitStream, branch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FallSpeedBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
|
||||||
|
End(context, branch, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FallSpeedBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
|
End(context, branch, LWOOBJID_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FallSpeedBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
|
||||||
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||||
|
if (!controllablePhysicsComponent) return;
|
||||||
|
controllablePhysicsComponent->SetGravityScale(1);
|
||||||
|
Game::entityManager->SerializeEntity(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FallSpeedBehavior::Load(){
|
||||||
|
m_PercentSlowed = GetFloat("percent_slowed");
|
||||||
|
}
|
18
dGame/dBehaviors/FallSpeedBehavior.h
Normal file
18
dGame/dBehaviors/FallSpeedBehavior.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Behavior.h"
|
||||||
|
|
||||||
|
class FallSpeedBehavior final : public Behavior
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FallSpeedBehavior(const uint32_t behaviorId) : Behavior(behaviorId) {}
|
||||||
|
|
||||||
|
void Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
void Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||||
|
void End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) override;
|
||||||
|
void UnCast(BehaviorContext* context, BehaviorBranchContext branch) override;
|
||||||
|
void Load() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_PercentSlowed;
|
||||||
|
};
|
@ -42,7 +42,7 @@ void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStrea
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* casterEntity = EntityManager::Instance()->GetEntity(context->caster);
|
auto* casterEntity = Game::entityManager->GetEntity(context->caster);
|
||||||
if (casterEntity != nullptr) {
|
if (casterEntity != nullptr) {
|
||||||
auto* controllablePhysicsComponent = casterEntity->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = casterEntity->GetComponent<ControllablePhysicsComponent>();
|
||||||
if (controllablePhysicsComponent != nullptr) {
|
if (controllablePhysicsComponent != nullptr) {
|
||||||
@ -51,7 +51,7 @@ void ForceMovementBehavior::Calculate(BehaviorContext* context, RakNet::BitStrea
|
|||||||
controllablePhysicsComponent->SetVelocity(controllablePhysicsComponent->GetRotation().GetForwardVector() * 25);
|
controllablePhysicsComponent->SetVelocity(controllablePhysicsComponent->GetRotation().GetForwardVector() * 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(casterEntity);
|
Game::entityManager->SerializeEntity(casterEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ void ForceMovementBehavior::Load() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ForceMovementBehavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void ForceMovementBehavior::SyncCalculation(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* casterEntity = EntityManager::Instance()->GetEntity(context->caster);
|
auto* casterEntity = Game::entityManager->GetEntity(context->caster);
|
||||||
if (casterEntity != nullptr) {
|
if (casterEntity != nullptr) {
|
||||||
auto* controllablePhysicsComponent = casterEntity->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = casterEntity->GetComponent<ControllablePhysicsComponent>();
|
||||||
if (controllablePhysicsComponent != nullptr) {
|
if (controllablePhysicsComponent != nullptr) {
|
||||||
@ -80,7 +80,7 @@ void ForceMovementBehavior::SyncCalculation(BehaviorContext* context, RakNet::Bi
|
|||||||
controllablePhysicsComponent->SetPosition(controllablePhysicsComponent->GetPosition() + controllablePhysicsComponent->GetVelocity() * m_Duration);
|
controllablePhysicsComponent->SetPosition(controllablePhysicsComponent->GetPosition() + controllablePhysicsComponent->GetVelocity() * m_Duration);
|
||||||
controllablePhysicsComponent->SetVelocity({});
|
controllablePhysicsComponent->SetVelocity({});
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(casterEntity);
|
Game::entityManager->SerializeEntity(casterEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void HealBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
void HealBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("HealBehavior", "Failed to find entity for (%llu)!", branch.target);
|
Game::logger->Log("HealBehavior", "Failed to find entity for (%llu)!", branch.target);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void ImaginationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
void ImaginationBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "eStateChangeType.h"
|
#include "eStateChangeType.h"
|
||||||
|
|
||||||
void ImmunityBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
void ImmunityBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -56,7 +56,7 @@ void ImmunityBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
|
void ImmunityBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, const LWOOBJID second) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(second);
|
auto* target = Game::entityManager->GetEntity(second);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", second);
|
Game::logger->Log("DamageAbsorptionBehavior", "Failed to find target (%llu)!", second);
|
||||||
|
@ -42,7 +42,7 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
|
|
||||||
if (branch.target == context->originator) return;
|
if (branch.target == context->originator) return;
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) return;
|
if (target == nullptr) return;
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* b
|
|||||||
|
|
||||||
if (branch.target == context->originator) return;
|
if (branch.target == context->originator) return;
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) return;
|
if (target == nullptr) return;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "Character.h"
|
#include "Character.h"
|
||||||
|
|
||||||
void JetPackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
void JetPackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
GameMessages::SendSetJetPackMode(entity, true, this->m_BypassChecks, this->m_EnableHover, this->m_effectId, this->m_Airspeed, this->m_MaxAirspeed, this->m_VerticalVelocity, this->m_WarningEffectID);
|
GameMessages::SendSetJetPackMode(entity, true, this->m_BypassChecks, this->m_EnableHover, this->m_effectId, this->m_Airspeed, this->m_MaxAirspeed, this->m_VerticalVelocity, this->m_WarningEffectID);
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ void JetPackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_st
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JetPackBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void JetPackBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
GameMessages::SendSetJetPackMode(entity, false);
|
GameMessages::SendSetJetPackMode(entity, false);
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ void KnockbackBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
void KnockbackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void KnockbackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
bool blocked = false;
|
bool blocked = false;
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target != nullptr) {
|
if (target != nullptr) {
|
||||||
auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#include "LootBuffBehavior.h"
|
#include "LootBuffBehavior.h"
|
||||||
|
|
||||||
void LootBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void LootBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto target = EntityManager::Instance()->GetEntity(context->caster);
|
auto target = Game::entityManager->GetEntity(context->caster);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
auto controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
auto controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||||
if (!controllablePhysicsComponent) return;
|
if (!controllablePhysicsComponent) return;
|
||||||
|
|
||||||
controllablePhysicsComponent->AddPickupRadiusScale(m_Scale);
|
controllablePhysicsComponent->AddPickupRadiusScale(m_Scale);
|
||||||
EntityManager::Instance()->SerializeEntity(target);
|
Game::entityManager->SerializeEntity(target);
|
||||||
|
|
||||||
if (branch.duration > 0) context->RegisterTimerBehavior(this, branch);
|
if (branch.duration > 0) context->RegisterTimerBehavior(this, branch);
|
||||||
|
|
||||||
@ -19,14 +19,14 @@ void LootBuffBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LootBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void LootBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
auto target = EntityManager::Instance()->GetEntity(context->caster);
|
auto target = Game::entityManager->GetEntity(context->caster);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
auto controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
auto controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||||
if (!controllablePhysicsComponent) return;
|
if (!controllablePhysicsComponent) return;
|
||||||
|
|
||||||
controllablePhysicsComponent->RemovePickupRadiusScale(m_Scale);
|
controllablePhysicsComponent->RemovePickupRadiusScale(m_Scale);
|
||||||
EntityManager::Instance()->SerializeEntity(target);
|
Game::entityManager->SerializeEntity(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LootBuffBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
|
void LootBuffBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
|
||||||
|
@ -14,13 +14,13 @@
|
|||||||
void OverTimeBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void OverTimeBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
const auto originator = context->originator;
|
const auto originator = context->originator;
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(originator);
|
auto* entity = Game::entityManager->GetEntity(originator);
|
||||||
|
|
||||||
if (entity == nullptr) return;
|
if (entity == nullptr) return;
|
||||||
|
|
||||||
for (size_t i = 0; i < m_NumIntervals; i++) {
|
for (size_t i = 0; i < m_NumIntervals; i++) {
|
||||||
entity->AddCallbackTimer((i + 1) * m_Delay, [originator, branch, this]() {
|
entity->AddCallbackTimer((i + 1) * m_Delay, [originator, branch, this]() {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(originator);
|
auto* entity = Game::entityManager->GetEntity(originator);
|
||||||
|
|
||||||
if (entity == nullptr) return;
|
if (entity == nullptr) return;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("ProjectileAttackBehavior", "Failed to find originator (%llu)!", context->originator);
|
Game::logger->Log("ProjectileAttackBehavior", "Failed to find originator (%llu)!", context->originator);
|
||||||
@ -40,7 +40,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* targetEntity = EntityManager::Instance()->GetEntity(target);
|
auto* targetEntity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
for (auto i = 0u; i < this->m_projectileCount; ++i) {
|
for (auto i = 0u; i < this->m_projectileCount; ++i) {
|
||||||
LWOOBJID projectileId{};
|
LWOOBJID projectileId{};
|
||||||
@ -61,7 +61,7 @@ void ProjectileAttackBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
|||||||
void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
bitStream->Write(branch.target);
|
bitStream->Write(branch.target);
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("ProjectileAttackBehavior", "Failed to find originator (%llu)!", context->originator);
|
Game::logger->Log("ProjectileAttackBehavior", "Failed to find originator (%llu)!", context->originator);
|
||||||
@ -78,7 +78,7 @@ void ProjectileAttackBehavior::Calculate(BehaviorContext* context, RakNet::BitSt
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* other = EntityManager::Instance()->GetEntity(branch.target);
|
auto* other = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (other == nullptr) {
|
if (other == nullptr) {
|
||||||
Game::logger->Log("ProjectileAttackBehavior", "Invalid projectile target (%llu)!", branch.target);
|
Game::logger->Log("ProjectileAttackBehavior", "Invalid projectile target (%llu)!", branch.target);
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
|
|
||||||
void PropertyTeleportBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void PropertyTeleportBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* caster = EntityManager::Instance()->GetEntity(context->caster);
|
auto* caster = Game::entityManager->GetEntity(context->caster);
|
||||||
if (!caster) return;
|
if (!caster) return;
|
||||||
|
|
||||||
auto* character = caster->GetCharacter();
|
auto* character = caster->GetCharacter();
|
||||||
@ -23,16 +23,16 @@ void PropertyTeleportBehavior::Handle(BehaviorContext* context, RakNet::BitStrea
|
|||||||
LWOMAPID targetMapId = m_MapId;
|
LWOMAPID targetMapId = m_MapId;
|
||||||
LWOCLONEID targetCloneId = character->GetPropertyCloneID();
|
LWOCLONEID targetCloneId = character->GetPropertyCloneID();
|
||||||
|
|
||||||
if (dZoneManager::Instance()->GetZoneID().GetCloneID() == character->GetPropertyCloneID()) {
|
if (Game::zoneManager->GetZoneID().GetCloneID() == character->GetPropertyCloneID()) {
|
||||||
targetMapId = character->GetLastNonInstanceZoneID();
|
targetMapId = character->GetLastNonInstanceZoneID();
|
||||||
targetCloneId = 0;
|
targetCloneId = 0;
|
||||||
} else {
|
} else {
|
||||||
character->SetLastNonInstanceZoneID(dZoneManager::Instance()->GetZoneID().GetMapID());
|
character->SetLastNonInstanceZoneID(Game::zoneManager->GetZoneID().GetMapID());
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, targetMapId, targetCloneId, false, [objId](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
|
ZoneInstanceManager::Instance()->RequestZoneTransfer(Game::server, targetMapId, targetCloneId, false, [objId](bool mythranShift, uint32_t zoneID, uint32_t zoneInstance, uint32_t zoneClone, std::string serverIP, uint16_t serverPort) {
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(objId);
|
auto* entity = Game::entityManager->GetEntity(objId);
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
|
|
||||||
const auto sysAddr = entity->GetSystemAddress();
|
const auto sysAddr = entity->GetSystemAddress();
|
||||||
|
@ -6,9 +6,9 @@
|
|||||||
#include "MovementAIComponent.h"
|
#include "MovementAIComponent.h"
|
||||||
|
|
||||||
void PullToPointBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void PullToPointBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (entity == nullptr || target == nullptr) {
|
if (entity == nullptr || target == nullptr) {
|
||||||
return;
|
return;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "BuffComponent.h"
|
#include "BuffComponent.h"
|
||||||
|
|
||||||
void RemoveBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void RemoveBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(context->caster);
|
auto* entity = Game::entityManager->GetEntity(context->caster);
|
||||||
if (!entity) return;
|
if (!entity) return;
|
||||||
|
|
||||||
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
auto* buffComponent = entity->GetComponent<BuffComponent>();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
void RepairBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
void RepairBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit_stream, const BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("RepairBehavior", "Failed to find entity for (%llu)!", branch.target);
|
Game::logger->Log("RepairBehavior", "Failed to find entity for (%llu)!", branch.target);
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include "CppScripts.h"
|
#include "CppScripts.h"
|
||||||
|
|
||||||
void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
auto* caster = EntityManager::Instance()->GetEntity(context->originator);
|
auto* caster = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(target)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(target)) {
|
||||||
@ -17,8 +17,8 @@ void SkillEventBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bit
|
|||||||
|
|
||||||
void
|
void
|
||||||
SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
SkillEventBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
auto* caster = EntityManager::Instance()->GetEntity(context->originator);
|
auto* caster = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
if (caster != nullptr && target != nullptr && this->m_effectHandle != nullptr && !this->m_effectHandle->empty()) {
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(target)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(target)) {
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* origin = EntityManager::Instance()->GetEntity(context->originator);
|
auto* origin = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (origin == nullptr) {
|
if (origin == nullptr) {
|
||||||
Game::logger->Log("SpawnBehavior", "Failed to find self entity (%llu)!", context->originator);
|
Game::logger->Log("SpawnBehavior", "Failed to find self entity (%llu)!", context->originator);
|
||||||
@ -21,7 +21,7 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStrea
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (branch.isProjectile) {
|
if (branch.isProjectile) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target != nullptr) {
|
if (target != nullptr) {
|
||||||
origin = target;
|
origin = target;
|
||||||
@ -38,10 +38,10 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStrea
|
|||||||
info.spawnerNodeID = 0;
|
info.spawnerNodeID = 0;
|
||||||
info.pos = info.pos + (info.rot.GetForwardVector() * m_Distance);
|
info.pos = info.pos + (info.rot.GetForwardVector() * m_Distance);
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->CreateEntity(
|
auto* entity = Game::entityManager->CreateEntity(
|
||||||
info,
|
info,
|
||||||
nullptr,
|
nullptr,
|
||||||
EntityManager::Instance()->GetEntity(context->originator)
|
Game::entityManager->GetEntity(context->originator)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
@ -59,7 +59,7 @@ void SpawnBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStrea
|
|||||||
rebuildComponent->SetRepositionPlayer(false);
|
rebuildComponent->SetRepositionPlayer(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->ConstructEntity(entity);
|
Game::entityManager->ConstructEntity(entity);
|
||||||
|
|
||||||
if (branch.duration > 0) {
|
if (branch.duration > 0) {
|
||||||
context->RegisterTimerBehavior(this, branch, entity->GetObjectID());
|
context->RegisterTimerBehavior(this, branch, entity->GetObjectID());
|
||||||
@ -79,7 +79,7 @@ void SpawnBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitSt
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SpawnBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, const LWOOBJID second) {
|
void SpawnBehavior::Timer(BehaviorContext* context, const BehaviorBranchContext branch, const LWOOBJID second) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(second);
|
auto* entity = Game::entityManager->GetEntity(second);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("SpawnBehavior", "Failed to find spawned entity (%llu)!", second);
|
Game::logger->Log("SpawnBehavior", "Failed to find spawned entity (%llu)!", second);
|
||||||
|
@ -9,14 +9,14 @@
|
|||||||
void SpeedBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void SpeedBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
if (m_AffectsCaster) branch.target = context->caster;
|
if (m_AffectsCaster) branch.target = context->caster;
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||||
if (!controllablePhysicsComponent) return;
|
if (!controllablePhysicsComponent) return;
|
||||||
|
|
||||||
controllablePhysicsComponent->AddSpeedboost(m_RunSpeed);
|
controllablePhysicsComponent->AddSpeedboost(m_RunSpeed);
|
||||||
EntityManager::Instance()->SerializeEntity(target);
|
Game::entityManager->SerializeEntity(target);
|
||||||
|
|
||||||
if (branch.duration > 0.0f) {
|
if (branch.duration > 0.0f) {
|
||||||
context->RegisterTimerBehavior(this, branch);
|
context->RegisterTimerBehavior(this, branch);
|
||||||
@ -38,14 +38,14 @@ void SpeedBehavior::Timer(BehaviorContext* context, BehaviorBranchContext branch
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SpeedBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
|
void SpeedBehavior::End(BehaviorContext* context, BehaviorBranchContext branch, LWOOBJID second) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = target->GetComponent<ControllablePhysicsComponent>();
|
||||||
if (!controllablePhysicsComponent) return;
|
if (!controllablePhysicsComponent) return;
|
||||||
|
|
||||||
controllablePhysicsComponent->RemoveSpeedboost(m_RunSpeed);
|
controllablePhysicsComponent->RemoveSpeedboost(m_RunSpeed);
|
||||||
EntityManager::Instance()->SerializeEntity(target);
|
Game::entityManager->SerializeEntity(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeedBehavior::Load() {
|
void SpeedBehavior::Load() {
|
||||||
|
@ -21,7 +21,7 @@ void StunBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("StunBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("StunBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -44,7 +44,7 @@ void StunBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream
|
|||||||
|
|
||||||
void StunBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
void StunBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, const BehaviorBranchContext branch) {
|
||||||
if (this->m_stunCaster || branch.target == context->originator) {
|
if (this->m_stunCaster || branch.target == context->originator) {
|
||||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
auto* self = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (self == nullptr) {
|
if (self == nullptr) {
|
||||||
Game::logger->Log("StunBehavior", "Invalid self entity (%llu)!", context->originator);
|
Game::logger->Log("StunBehavior", "Invalid self entity (%llu)!", context->originator);
|
||||||
@ -69,7 +69,7 @@ void StunBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStr
|
|||||||
|
|
||||||
bool blocked = false;
|
bool blocked = false;
|
||||||
|
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target != nullptr) {
|
if (target != nullptr) {
|
||||||
auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = target->GetComponent<DestroyableComponent>();
|
||||||
|
@ -16,7 +16,7 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStre
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(context->originator);
|
auto* entity = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -30,7 +30,7 @@ void SwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStre
|
|||||||
|
|
||||||
Game::logger->LogDebug("SwitchBehavior", "[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
|
Game::logger->LogDebug("SwitchBehavior", "[%i] State: (%d), imagination: (%i) / (%f)", entity->GetLOT(), state, destroyableComponent->GetImagination(), destroyableComponent->GetMaxImagination());
|
||||||
|
|
||||||
if (state || (entity->GetLOT() == 8092 && destroyableComponent->GetImagination() >= m_imagination)) {
|
if (state) {
|
||||||
this->m_actionTrue->Handle(context, bitStream, branch);
|
this->m_actionTrue->Handle(context, bitStream, branch);
|
||||||
} else {
|
} else {
|
||||||
this->m_actionFalse->Handle(context, bitStream, branch);
|
this->m_actionFalse->Handle(context, bitStream, branch);
|
||||||
@ -41,7 +41,7 @@ void SwitchBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
auto state = true;
|
auto state = true;
|
||||||
|
|
||||||
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
|
if (this->m_imagination > 0 || !this->m_isEnemyFaction) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
state = entity != nullptr;
|
state = entity != nullptr;
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ void TacArcBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStre
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
auto* self = Game::entityManager->GetEntity(context->originator);
|
||||||
if (self == nullptr) {
|
if (self == nullptr) {
|
||||||
Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!", context->originator);
|
Game::logger->Log("TacArcBehavior", "Invalid self for (%llu)!", context->originator);
|
||||||
return;
|
return;
|
||||||
@ -85,7 +85,7 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
const auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
const auto* destroyableComponent = self->GetComponent<DestroyableComponent>();
|
||||||
|
|
||||||
if ((this->m_usePickedTarget || context->clientInitalized) && branch.target > 0) {
|
if ((this->m_usePickedTarget || context->clientInitalized) && branch.target > 0) {
|
||||||
const auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
const auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -120,7 +120,7 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
// Find all valid targets, based on whether we target enemies or friends
|
// Find all valid targets, based on whether we target enemies or friends
|
||||||
for (const auto& contextTarget : context->GetValidTargets()) {
|
for (const auto& contextTarget : context->GetValidTargets()) {
|
||||||
if (destroyableComponent != nullptr) {
|
if (destroyableComponent != nullptr) {
|
||||||
const auto* targetEntity = EntityManager::Instance()->GetEntity(contextTarget);
|
const auto* targetEntity = Game::entityManager->GetEntity(contextTarget);
|
||||||
|
|
||||||
if (m_targetEnemy && destroyableComponent->IsEnemy(targetEntity)
|
if (m_targetEnemy && destroyableComponent->IsEnemy(targetEntity)
|
||||||
|| m_targetFriend && destroyableComponent->IsFriend(targetEntity)) {
|
|| m_targetFriend && destroyableComponent->IsFriend(targetEntity)) {
|
||||||
@ -136,7 +136,7 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(validTarget);
|
auto* entity = Game::entityManager->GetEntity(validTarget);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
|
Game::logger->Log("TacArcBehavior", "Invalid target (%llu) for (%llu)!", validTarget, context->originator);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
void TauntBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void TauntBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("TauntBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("TauntBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
@ -23,7 +23,7 @@ void TauntBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStrea
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TauntBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void TauntBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* target = EntityManager::Instance()->GetEntity(branch.target);
|
auto* target = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
Game::logger->Log("TauntBehavior", "Failed to find target (%llu)!", branch.target);
|
Game::logger->Log("TauntBehavior", "Failed to find target (%llu)!", branch.target);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
void VentureVisionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void VentureVisionBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
|
|
||||||
const auto targetEntity = EntityManager::Instance()->GetEntity(branch.target);
|
const auto targetEntity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (targetEntity) {
|
if (targetEntity) {
|
||||||
auto characterComponent = targetEntity->GetComponent<CharacterComponent>();
|
auto characterComponent = targetEntity->GetComponent<CharacterComponent>();
|
||||||
@ -21,7 +21,7 @@ void VentureVisionBehavior::Handle(BehaviorContext* context, RakNet::BitStream*
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VentureVisionBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void VentureVisionBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
const auto targetEntity = EntityManager::Instance()->GetEntity(branch.target);
|
const auto targetEntity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
if (targetEntity) {
|
if (targetEntity) {
|
||||||
auto characterComponent = targetEntity->GetComponent<CharacterComponent>();
|
auto characterComponent = targetEntity->GetComponent<CharacterComponent>();
|
||||||
|
@ -8,14 +8,14 @@
|
|||||||
|
|
||||||
|
|
||||||
void VerifyBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
void VerifyBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(branch.target);
|
auto* entity = Game::entityManager->GetEntity(branch.target);
|
||||||
|
|
||||||
auto success = true;
|
auto success = true;
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
success = false;
|
success = false;
|
||||||
} else if (this->m_rangeCheck) {
|
} else if (this->m_rangeCheck) {
|
||||||
auto* self = EntityManager::Instance()->GetEntity(context->originator);
|
auto* self = Game::entityManager->GetEntity(context->originator);
|
||||||
|
|
||||||
if (self == nullptr) {
|
if (self == nullptr) {
|
||||||
Game::logger->Log("VerifyBehavior", "Invalid self for (%llu)", context->originator);
|
Game::logger->Log("VerifyBehavior", "Invalid self for (%llu)", context->originator);
|
||||||
|
@ -173,7 +173,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_SoftTimer <= 0.0f) {
|
if (m_SoftTimer <= 0.0f) {
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
m_SoftTimer = 5.0f;
|
m_SoftTimer = 5.0f;
|
||||||
} else {
|
} else {
|
||||||
@ -305,7 +305,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (serilizationRequired) {
|
if (serilizationRequired) {
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether");
|
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 6270, u"tether", "tether");
|
||||||
@ -412,7 +412,7 @@ LWOOBJID BaseCombatAIComponent::FindTarget() {
|
|||||||
float biggestThreat = 0;
|
float biggestThreat = 0;
|
||||||
|
|
||||||
for (const auto& entry : possibleTargets) {
|
for (const auto& entry : possibleTargets) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(entry);
|
auto* entity = Game::entityManager->GetEntity(entry);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -458,7 +458,7 @@ LWOOBJID BaseCombatAIComponent::FindTarget() {
|
|||||||
std::vector<LWOOBJID> deadThreats{};
|
std::vector<LWOOBJID> deadThreats{};
|
||||||
|
|
||||||
for (const auto& threatTarget : m_ThreatEntries) {
|
for (const auto& threatTarget : m_ThreatEntries) {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(threatTarget.first);
|
auto* entity = Game::entityManager->GetEntity(threatTarget.first);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
deadThreats.push_back(threatTarget.first);
|
deadThreats.push_back(threatTarget.first);
|
||||||
@ -497,7 +497,7 @@ std::vector<LWOOBJID> BaseCombatAIComponent::GetTargetWithinAggroRange() const {
|
|||||||
std::vector<LWOOBJID> targets;
|
std::vector<LWOOBJID> targets;
|
||||||
|
|
||||||
for (auto id : m_Parent->GetTargetsInPhantom()) {
|
for (auto id : m_Parent->GetTargetsInPhantom()) {
|
||||||
auto* other = EntityManager::Instance()->GetEntity(id);
|
auto* other = Game::entityManager->GetEntity(id);
|
||||||
|
|
||||||
const auto distance = Vector3::DistanceSquared(m_Parent->GetPosition(), other->GetPosition());
|
const auto distance = Vector3::DistanceSquared(m_Parent->GetPosition(), other->GetPosition());
|
||||||
|
|
||||||
@ -535,11 +535,11 @@ void BaseCombatAIComponent::SetAiState(AiState newState) {
|
|||||||
if (newState == this->m_State) return;
|
if (newState == this->m_State) return;
|
||||||
this->m_State = newState;
|
this->m_State = newState;
|
||||||
m_DirtyStateOrTarget = true;
|
m_DirtyStateOrTarget = true;
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
|
bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
auto* entity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
Game::logger->Log("BaseCombatAIComponent", "Invalid entity for checking validity (%llu)!", target);
|
Game::logger->Log("BaseCombatAIComponent", "Invalid entity for checking validity (%llu)!", target);
|
||||||
@ -588,11 +588,11 @@ void BaseCombatAIComponent::SetTarget(const LWOOBJID target) {
|
|||||||
if (this->m_Target == target) return;
|
if (this->m_Target == target) return;
|
||||||
m_Target = target;
|
m_Target = target;
|
||||||
m_DirtyStateOrTarget = true;
|
m_DirtyStateOrTarget = true;
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* BaseCombatAIComponent::GetTargetEntity() const {
|
Entity* BaseCombatAIComponent::GetTargetEntity() const {
|
||||||
return EntityManager::Instance()->GetEntity(m_Target);
|
return Game::entityManager->GetEntity(m_Target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseCombatAIComponent::Taunt(LWOOBJID offender, float threat) {
|
void BaseCombatAIComponent::Taunt(LWOOBJID offender, float threat) {
|
||||||
|
@ -36,7 +36,7 @@ Entity* BouncerComponent::GetParentEntity() const {
|
|||||||
void BouncerComponent::SetPetEnabled(bool value) {
|
void BouncerComponent::SetPetEnabled(bool value) {
|
||||||
m_PetEnabled = value;
|
m_PetEnabled = value;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BouncerComponent::SetPetBouncerEnabled(bool value) {
|
void BouncerComponent::SetPetBouncerEnabled(bool value) {
|
||||||
@ -44,7 +44,7 @@ void BouncerComponent::SetPetBouncerEnabled(bool value) {
|
|||||||
|
|
||||||
GameMessages::SendBouncerActiveStatus(m_Parent->GetObjectID(), value, UNASSIGNED_SYSTEM_ADDRESS);
|
GameMessages::SendBouncerActiveStatus(m_Parent->GetObjectID(), value, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
m_Parent->TriggerEvent(eTriggerEventType::PET_ON_SWITCH, m_Parent);
|
m_Parent->TriggerEvent(eTriggerEventType::PET_ON_SWITCH, m_Parent);
|
||||||
@ -68,7 +68,7 @@ void BouncerComponent::LookupPetSwitch() {
|
|||||||
const auto& groups = m_Parent->GetGroups();
|
const auto& groups = m_Parent->GetGroups();
|
||||||
|
|
||||||
for (const auto& group : groups) {
|
for (const auto& group : groups) {
|
||||||
const auto& entities = EntityManager::Instance()->GetEntitiesInGroup(group);
|
const auto& entities = Game::entityManager->GetEntitiesInGroup(group);
|
||||||
|
|
||||||
for (auto* entity : entities) {
|
for (auto* entity : entities) {
|
||||||
auto* switchComponent = entity->GetComponent<SwitchComponent>();
|
auto* switchComponent = entity->GetComponent<SwitchComponent>();
|
||||||
@ -79,7 +79,7 @@ void BouncerComponent::LookupPetSwitch() {
|
|||||||
m_PetSwitchLoaded = true;
|
m_PetSwitchLoaded = true;
|
||||||
m_PetEnabled = true;
|
m_PetEnabled = true;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
Game::logger->Log("BouncerComponent", "Loaded pet bouncer");
|
Game::logger->Log("BouncerComponent", "Loaded pet bouncer");
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ BuildBorderComponent::~BuildBorderComponent() {
|
|||||||
|
|
||||||
void BuildBorderComponent::OnUse(Entity* originator) {
|
void BuildBorderComponent::OnUse(Entity* originator) {
|
||||||
if (originator->GetCharacter()) {
|
if (originator->GetCharacter()) {
|
||||||
const auto& entities = EntityManager::Instance()->GetEntitiesInGroup("PropertyPlaque");
|
const auto& entities = Game::entityManager->GetEntitiesInGroup("PropertyPlaque");
|
||||||
|
|
||||||
auto buildArea = m_Parent->GetObjectID();
|
auto buildArea = m_Parent->GetObjectID();
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "VehiclePhysicsComponent.h"
|
#include "VehiclePhysicsComponent.h"
|
||||||
#include "GameMessages.h"
|
#include "GameMessages.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
#include "AMFFormat.h"
|
#include "Amf3.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "eGameActivity.h"
|
#include "eGameActivity.h"
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ void CharacterComponent::TrackMissionCompletion(bool isAchievement) {
|
|||||||
|
|
||||||
// Achievements are tracked separately for the zone
|
// Achievements are tracked separately for the zone
|
||||||
if (isAchievement) {
|
if (isAchievement) {
|
||||||
const auto mapID = dZoneManager::Instance()->GetZoneID().GetMapID();
|
const auto mapID = Game::zoneManager->GetZoneID().GetMapID();
|
||||||
GetZoneStatisticsForMap(mapID).m_AchievementsCollected++;
|
GetZoneStatisticsForMap(mapID).m_AchievementsCollected++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ void CharacterComponent::TrackArmorDelta(int32_t armor) {
|
|||||||
void CharacterComponent::TrackRebuildComplete() {
|
void CharacterComponent::TrackRebuildComplete() {
|
||||||
UpdatePlayerStatistic(QuickBuildsCompleted);
|
UpdatePlayerStatistic(QuickBuildsCompleted);
|
||||||
|
|
||||||
const auto mapID = dZoneManager::Instance()->GetZoneID().GetMapID();
|
const auto mapID = Game::zoneManager->GetZoneID().GetMapID();
|
||||||
GetZoneStatisticsForMap(mapID).m_QuickBuildsCompleted++;
|
GetZoneStatisticsForMap(mapID).m_QuickBuildsCompleted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,6 +734,6 @@ void CharacterComponent::RemoveVentureVisionEffect(std::string ventureVisionType
|
|||||||
void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const {
|
void CharacterComponent::UpdateClientMinimap(bool showFaction, std::string ventureVisionType) const {
|
||||||
if (!m_Parent) return;
|
if (!m_Parent) return;
|
||||||
AMFArrayValue arrayToSend;
|
AMFArrayValue arrayToSend;
|
||||||
arrayToSend.InsertValue(ventureVisionType, showFaction ? static_cast<AMFValue*>(new AMFTrueValue()) : static_cast<AMFValue*>(new AMFFalseValue()));
|
arrayToSend.Insert(ventureVisionType, showFaction);
|
||||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", &arrayToSend);
|
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent ? m_Parent->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS, "SetFactionVisibility", arrayToSend);
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ void ControllablePhysicsComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto zoneInfo = dZoneManager::Instance()->GetZone()->GetZoneID();
|
auto zoneInfo = Game::zoneManager->GetZone()->GetZoneID();
|
||||||
|
|
||||||
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
|
if (zoneInfo.GetMapID() != 0 && zoneInfo.GetCloneID() == 0) {
|
||||||
character->SetAttribute("lzx", m_Position.x);
|
character->SetAttribute("lzx", m_Position.x);
|
||||||
@ -300,7 +300,7 @@ void ControllablePhysicsComponent::RemovePickupRadiusScale(float value) {
|
|||||||
auto candidateRadius = m_ActivePickupRadiusScales[i];
|
auto candidateRadius = m_ActivePickupRadiusScales[i];
|
||||||
if (m_PickupRadius < candidateRadius) m_PickupRadius = candidateRadius;
|
if (m_PickupRadius < candidateRadius) m_PickupRadius = candidateRadius;
|
||||||
}
|
}
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::AddSpeedboost(float value) {
|
void ControllablePhysicsComponent::AddSpeedboost(float value) {
|
||||||
@ -320,14 +320,14 @@ void ControllablePhysicsComponent::RemoveSpeedboost(float value) {
|
|||||||
|
|
||||||
// Recalculate speedboost since we removed one
|
// Recalculate speedboost since we removed one
|
||||||
m_SpeedBoost = 0.0f;
|
m_SpeedBoost = 0.0f;
|
||||||
if (m_ActiveSpeedBoosts.size() == 0) { // no active speed boosts left, so return to base speed
|
if (m_ActiveSpeedBoosts.empty()) { // no active speed boosts left, so return to base speed
|
||||||
auto* levelProgressionComponent = m_Parent->GetComponent<LevelProgressionComponent>();
|
auto* levelProgressionComponent = m_Parent->GetComponent<LevelProgressionComponent>();
|
||||||
if (levelProgressionComponent) m_SpeedBoost = levelProgressionComponent->GetSpeedBase();
|
if (levelProgressionComponent) m_SpeedBoost = levelProgressionComponent->GetSpeedBase();
|
||||||
} else { // Used the last applied speedboost
|
} else { // Used the last applied speedboost
|
||||||
m_SpeedBoost = m_ActiveSpeedBoosts.back();
|
m_SpeedBoost = m_ActiveSpeedBoosts.back();
|
||||||
}
|
}
|
||||||
SetSpeedMultiplier(m_SpeedBoost / 500.0f); // 500 being the base speed
|
SetSpeedMultiplier(m_SpeedBoost / 500.0f); // 500 being the base speed
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims){
|
void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims){
|
||||||
@ -339,13 +339,13 @@ void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bo
|
|||||||
m_IsInBubble = true;
|
m_IsInBubble = true;
|
||||||
m_DirtyBubble = true;
|
m_DirtyBubble = true;
|
||||||
m_SpecialAnims = specialAnims;
|
m_SpecialAnims = specialAnims;
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllablePhysicsComponent::DeactivateBubbleBuff(){
|
void ControllablePhysicsComponent::DeactivateBubbleBuff(){
|
||||||
m_DirtyBubble = true;
|
m_DirtyBubble = true;
|
||||||
m_IsInBubble = false;
|
m_IsInBubble = false;
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
};
|
};
|
||||||
|
|
||||||
void ControllablePhysicsComponent::SetStunImmunity(
|
void ControllablePhysicsComponent::SetStunImmunity(
|
||||||
|
@ -276,7 +276,7 @@ public:
|
|||||||
* The speed boosts of this component.
|
* The speed boosts of this component.
|
||||||
* @return All active Speed boosts for this component.
|
* @return All active Speed boosts for this component.
|
||||||
*/
|
*/
|
||||||
std::vector<float> GetActiveSpeedboosts() { return m_ActivePickupRadiusScales; };
|
std::vector<float> GetActiveSpeedboosts() { return m_ActiveSpeedBoosts; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the Bubble Buff
|
* Activates the Bubble Buff
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
|
|
||||||
#include "AMFFormat.h"
|
#include "Amf3.h"
|
||||||
#include "AMFFormat_BitStream.h"
|
#include "AmfSerialize.h"
|
||||||
#include "GameMessages.h"
|
#include "GameMessages.h"
|
||||||
#include "User.h"
|
#include "User.h"
|
||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
@ -51,7 +51,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
|||||||
m_IsGMImmune = false;
|
m_IsGMImmune = false;
|
||||||
m_IsShielded = false;
|
m_IsShielded = false;
|
||||||
m_DamageToAbsorb = 0;
|
m_DamageToAbsorb = 0;
|
||||||
m_HasBricks = false;
|
m_IsModuleAssembly = m_Parent->HasComponent(eReplicaComponentType::MODULE_ASSEMBLY);
|
||||||
m_DirtyThreatList = false;
|
m_DirtyThreatList = false;
|
||||||
m_HasThreats = false;
|
m_HasThreats = false;
|
||||||
m_ExplodeFactor = 1.0f;
|
m_ExplodeFactor = 1.0f;
|
||||||
@ -163,7 +163,7 @@ void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIn
|
|||||||
outBitStream->Write(m_IsSmashed);
|
outBitStream->Write(m_IsSmashed);
|
||||||
|
|
||||||
if (m_IsSmashable) {
|
if (m_IsSmashable) {
|
||||||
outBitStream->Write(m_HasBricks);
|
outBitStream->Write(m_IsModuleAssembly);
|
||||||
outBitStream->Write(m_ExplodeFactor != 1.0f);
|
outBitStream->Write(m_ExplodeFactor != 1.0f);
|
||||||
if (m_ExplodeFactor != 1.0f) outBitStream->Write(m_ExplodeFactor);
|
if (m_ExplodeFactor != 1.0f) outBitStream->Write(m_ExplodeFactor);
|
||||||
}
|
}
|
||||||
@ -245,19 +245,15 @@ void DestroyableComponent::SetMaxHealth(float value, bool playAnim) {
|
|||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
// Now update the player bar
|
// Now update the player bar
|
||||||
if (!m_Parent->GetParentUser()) return;
|
if (!m_Parent->GetParentUser()) return;
|
||||||
AMFStringValue* amount = new AMFStringValue();
|
|
||||||
amount->SetStringValue(std::to_string(difference));
|
|
||||||
AMFStringValue* type = new AMFStringValue();
|
|
||||||
type->SetStringValue("health");
|
|
||||||
|
|
||||||
AMFArrayValue args;
|
AMFArrayValue args;
|
||||||
args.InsertValue("amount", amount);
|
args.Insert("amount", std::to_string(difference));
|
||||||
args.InsertValue("type", type);
|
args.Insert("type", "health");
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args);
|
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::SetArmor(int32_t value) {
|
void DestroyableComponent::SetArmor(int32_t value) {
|
||||||
@ -290,19 +286,15 @@ void DestroyableComponent::SetMaxArmor(float value, bool playAnim) {
|
|||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
// Now update the player bar
|
// Now update the player bar
|
||||||
if (!m_Parent->GetParentUser()) return;
|
if (!m_Parent->GetParentUser()) return;
|
||||||
AMFStringValue* amount = new AMFStringValue();
|
|
||||||
amount->SetStringValue(std::to_string(value));
|
|
||||||
AMFStringValue* type = new AMFStringValue();
|
|
||||||
type->SetStringValue("armor");
|
|
||||||
|
|
||||||
AMFArrayValue args;
|
AMFArrayValue args;
|
||||||
args.InsertValue("amount", amount);
|
args.Insert("amount", std::to_string(value));
|
||||||
args.InsertValue("type", type);
|
args.Insert("type", "armor");
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args);
|
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::SetImagination(int32_t value) {
|
void DestroyableComponent::SetImagination(int32_t value) {
|
||||||
@ -334,18 +326,14 @@ void DestroyableComponent::SetMaxImagination(float value, bool playAnim) {
|
|||||||
if (playAnim) {
|
if (playAnim) {
|
||||||
// Now update the player bar
|
// Now update the player bar
|
||||||
if (!m_Parent->GetParentUser()) return;
|
if (!m_Parent->GetParentUser()) return;
|
||||||
AMFStringValue* amount = new AMFStringValue();
|
|
||||||
amount->SetStringValue(std::to_string(difference));
|
|
||||||
AMFStringValue* type = new AMFStringValue();
|
|
||||||
type->SetStringValue("imagination");
|
|
||||||
|
|
||||||
AMFArrayValue args;
|
AMFArrayValue args;
|
||||||
args.InsertValue("amount", amount);
|
args.Insert("amount", std::to_string(difference));
|
||||||
args.InsertValue("type", type);
|
args.Insert("type", "imagination");
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", &args);
|
GameMessages::SendUIMessageServerToSingleClient(m_Parent, m_Parent->GetParentUser()->GetSystemAddress(), "MaxPlayerBarUpdate", args);
|
||||||
}
|
}
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::SetDamageToAbsorb(int32_t value) {
|
void DestroyableComponent::SetDamageToAbsorb(int32_t value) {
|
||||||
@ -494,11 +482,11 @@ LWOOBJID DestroyableComponent::GetKillerID() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity* DestroyableComponent::GetKiller() const {
|
Entity* DestroyableComponent::GetKiller() const {
|
||||||
return EntityManager::Instance()->GetEntity(m_KillerID);
|
return Game::entityManager->GetEntity(m_KillerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DestroyableComponent::CheckValidity(const LWOOBJID target, const bool ignoreFactions, const bool targetEnemy, const bool targetFriend) const {
|
bool DestroyableComponent::CheckValidity(const LWOOBJID target, const bool ignoreFactions, const bool targetEnemy, const bool targetFriend) const {
|
||||||
auto* targetEntity = EntityManager::Instance()->GetEntity(target);
|
auto* targetEntity = Game::entityManager->GetEntity(target);
|
||||||
|
|
||||||
if (targetEntity == nullptr) {
|
if (targetEntity == nullptr) {
|
||||||
Game::logger->Log("DestroyableComponent", "Invalid entity for checking validity (%llu)!", target);
|
Game::logger->Log("DestroyableComponent", "Invalid entity for checking validity (%llu)!", target);
|
||||||
@ -544,7 +532,7 @@ void DestroyableComponent::Heal(const uint32_t health) {
|
|||||||
|
|
||||||
SetHealth(current);
|
SetHealth(current);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -562,7 +550,7 @@ void DestroyableComponent::Imagine(const int32_t deltaImagination) {
|
|||||||
|
|
||||||
SetImagination(current);
|
SetImagination(current);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -576,7 +564,7 @@ void DestroyableComponent::Repair(const uint32_t armor) {
|
|||||||
|
|
||||||
SetArmor(current);
|
SetArmor(current);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -638,7 +626,7 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
|||||||
if (possessor) {
|
if (possessor) {
|
||||||
auto possessableId = possessor->GetPossessable();
|
auto possessableId = possessor->GetPossessable();
|
||||||
if (possessableId != LWOOBJID_EMPTY) {
|
if (possessableId != LWOOBJID_EMPTY) {
|
||||||
auto possessable = EntityManager::Instance()->GetEntity(possessableId);
|
auto possessable = Game::entityManager->GetEntity(possessableId);
|
||||||
if (possessable) {
|
if (possessable) {
|
||||||
possessor->Dismount(possessable);
|
possessor->Dismount(possessable);
|
||||||
}
|
}
|
||||||
@ -650,10 +638,10 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (echo) {
|
if (echo) {
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* attacker = EntityManager::Instance()->GetEntity(source);
|
auto* attacker = Game::entityManager->GetEntity(source);
|
||||||
m_Parent->OnHit(attacker);
|
m_Parent->OnHit(attacker);
|
||||||
m_Parent->OnHitOrHealResult(attacker, sourceDamage);
|
m_Parent->OnHitOrHealResult(attacker, sourceDamage);
|
||||||
NotifySubscribers(attacker, sourceDamage);
|
NotifySubscribers(attacker, sourceDamage);
|
||||||
@ -673,7 +661,7 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check if hardcore mode is enabled
|
//check if hardcore mode is enabled
|
||||||
if (EntityManager::Instance()->GetHardcoreMode()) {
|
if (Game::entityManager->GetHardcoreMode()) {
|
||||||
DoHardcoreModeDrops(source);
|
DoHardcoreModeDrops(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,12 +696,12 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
SetArmor(0);
|
SetArmor(0);
|
||||||
SetHealth(0);
|
SetHealth(0);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_KillerID = source;
|
m_KillerID = source;
|
||||||
|
|
||||||
auto* owner = EntityManager::Instance()->GetEntity(source);
|
auto* owner = Game::entityManager->GetEntity(source);
|
||||||
|
|
||||||
if (owner != nullptr) {
|
if (owner != nullptr) {
|
||||||
owner = owner->GetOwner(); // If the owner is overwritten, we collect that here
|
owner = owner->GetOwner(); // If the owner is overwritten, we collect that here
|
||||||
@ -733,7 +721,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
if (missions != nullptr) {
|
if (missions != nullptr) {
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
for (const auto memberId : team->members) {
|
for (const auto memberId : team->members) {
|
||||||
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
auto* member = Game::entityManager->GetEntity(memberId);
|
||||||
|
|
||||||
if (member == nullptr) continue;
|
if (member == nullptr) continue;
|
||||||
|
|
||||||
@ -773,12 +761,12 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
if (team->lootOption == 0) { // Round robin
|
if (team->lootOption == 0) { // Round robin
|
||||||
specificOwner = TeamManager::Instance()->GetNextLootOwner(team);
|
specificOwner = TeamManager::Instance()->GetNextLootOwner(team);
|
||||||
|
|
||||||
auto* member = EntityManager::Instance()->GetEntity(specificOwner);
|
auto* member = Game::entityManager->GetEntity(specificOwner);
|
||||||
|
|
||||||
if (member) LootGenerator::Instance().DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
if (member) LootGenerator::Instance().DropLoot(member, m_Parent, lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||||
} else {
|
} else {
|
||||||
for (const auto memberId : team->members) { // Free for all
|
for (const auto memberId : team->members) { // Free for all
|
||||||
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
auto* member = Game::entityManager->GetEntity(memberId);
|
||||||
|
|
||||||
if (member == nullptr) continue;
|
if (member == nullptr) continue;
|
||||||
|
|
||||||
@ -791,13 +779,13 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Check if this zone allows coin drops
|
//Check if this zone allows coin drops
|
||||||
if (dZoneManager::Instance()->GetPlayerLoseCoinOnDeath()) {
|
if (Game::zoneManager->GetPlayerLoseCoinOnDeath()) {
|
||||||
auto* character = m_Parent->GetCharacter();
|
auto* character = m_Parent->GetCharacter();
|
||||||
uint64_t coinsTotal = character->GetCoins();
|
uint64_t coinsTotal = character->GetCoins();
|
||||||
const uint64_t minCoinsToLose = dZoneManager::Instance()->GetWorldConfig()->coinsLostOnDeathMin;
|
const uint64_t minCoinsToLose = Game::zoneManager->GetWorldConfig()->coinsLostOnDeathMin;
|
||||||
if (coinsTotal >= minCoinsToLose) {
|
if (coinsTotal >= minCoinsToLose) {
|
||||||
const uint64_t maxCoinsToLose = dZoneManager::Instance()->GetWorldConfig()->coinsLostOnDeathMax;
|
const uint64_t maxCoinsToLose = Game::zoneManager->GetWorldConfig()->coinsLostOnDeathMax;
|
||||||
const float coinPercentageToLose = dZoneManager::Instance()->GetWorldConfig()->coinsLostOnDeathPercent;
|
const float coinPercentageToLose = Game::zoneManager->GetWorldConfig()->coinsLostOnDeathPercent;
|
||||||
|
|
||||||
uint64_t coinsToLose = std::max(static_cast<uint64_t>(coinsTotal * coinPercentageToLose), minCoinsToLose);
|
uint64_t coinsToLose = std::max(static_cast<uint64_t>(coinsTotal * coinPercentageToLose), minCoinsToLose);
|
||||||
coinsToLose = std::min(maxCoinsToLose, coinsToLose);
|
coinsToLose = std::min(maxCoinsToLose, coinsToLose);
|
||||||
@ -809,12 +797,12 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* zoneControl = EntityManager::Instance()->GetZoneControlEntity();
|
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
|
||||||
script->OnPlayerDied(zoneControl, m_Parent);
|
script->OnPlayerDied(zoneControl, m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Entity*> scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
||||||
for (Entity* scriptEntity : scriptedActs) {
|
for (Entity* scriptEntity : scriptedActs) {
|
||||||
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
||||||
@ -977,7 +965,7 @@ void DestroyableComponent::FixStats() {
|
|||||||
destroyableComponent->SetImagination(currentImagination);
|
destroyableComponent->SetImagination(currentImagination);
|
||||||
|
|
||||||
// Serialize the entity
|
// Serialize the entity
|
||||||
EntityManager::Instance()->SerializeEntity(entity);
|
Game::entityManager->SerializeEntity(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::AddOnHitCallback(const std::function<void(Entity*)>& callback) {
|
void DestroyableComponent::AddOnHitCallback(const std::function<void(Entity*)>& callback) {
|
||||||
@ -991,12 +979,12 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
|
|||||||
auto* character = m_Parent->GetComponent<CharacterComponent>();
|
auto* character = m_Parent->GetComponent<CharacterComponent>();
|
||||||
auto uscore = character->GetUScore();
|
auto uscore = character->GetUScore();
|
||||||
|
|
||||||
auto uscoreToLose = uscore * (EntityManager::Instance()->GetHardcoreLoseUscoreOnDeathPercent() / 100);
|
auto uscoreToLose = uscore * (Game::entityManager->GetHardcoreLoseUscoreOnDeathPercent() / 100);
|
||||||
character->SetUScore(uscore - uscoreToLose);
|
character->SetUScore(uscore - uscoreToLose);
|
||||||
|
|
||||||
GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION);
|
GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION);
|
||||||
|
|
||||||
if (EntityManager::Instance()->GetHardcoreDropinventoryOnDeath()) {
|
if (Game::entityManager->GetHardcoreDropinventoryOnDeath()) {
|
||||||
//drop all items from inventory:
|
//drop all items from inventory:
|
||||||
auto* inventory = m_Parent->GetComponent<InventoryComponent>();
|
auto* inventory = m_Parent->GetComponent<InventoryComponent>();
|
||||||
if (inventory) {
|
if (inventory) {
|
||||||
@ -1013,7 +1001,7 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
|
|||||||
GameMessages::SendDropClientLoot(m_Parent, source, item.second->GetLot(), 0, m_Parent->GetPosition(), item.second->GetCount());
|
GameMessages::SendDropClientLoot(m_Parent, source, item.second->GetLot(), 0, m_Parent->GetPosition(), item.second->GetCount());
|
||||||
item.second->SetCount(0, false, false);
|
item.second->SetCount(0, false, false);
|
||||||
}
|
}
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1033,25 +1021,25 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
|
|||||||
|
|
||||||
// Reload the player since we can't normally reduce uscore from the server and we want the UI to update
|
// Reload the player since we can't normally reduce uscore from the server and we want the UI to update
|
||||||
// do this last so we don't get killed.... again
|
// do this last so we don't get killed.... again
|
||||||
EntityManager::Instance()->DestructEntity(m_Parent);
|
Game::entityManager->DestructEntity(m_Parent);
|
||||||
EntityManager::Instance()->ConstructEntity(m_Parent);
|
Game::entityManager->ConstructEntity(m_Parent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//award the player some u-score:
|
//award the player some u-score:
|
||||||
auto* player = EntityManager::Instance()->GetEntity(source);
|
auto* player = Game::entityManager->GetEntity(source);
|
||||||
if (player && player->IsPlayer()) {
|
if (player && player->IsPlayer()) {
|
||||||
auto* playerStats = player->GetComponent<CharacterComponent>();
|
auto* playerStats = player->GetComponent<CharacterComponent>();
|
||||||
if (playerStats) {
|
if (playerStats) {
|
||||||
//get the maximum health from this enemy:
|
//get the maximum health from this enemy:
|
||||||
auto maxHealth = GetMaxHealth();
|
auto maxHealth = GetMaxHealth();
|
||||||
|
|
||||||
int uscore = maxHealth * EntityManager::Instance()->GetHardcoreUscoreEnemiesMultiplier();
|
int uscore = maxHealth * Game::entityManager->GetHardcoreUscoreEnemiesMultiplier();
|
||||||
|
|
||||||
playerStats->SetUScore(playerStats->GetUScore() + uscore);
|
playerStats->SetUScore(playerStats->GetUScore() + uscore);
|
||||||
GameMessages::SendModifyLEGOScore(player, player->GetSystemAddress(), uscore, eLootSourceType::MISSION);
|
GameMessages::SendModifyLEGOScore(player, player->GetSystemAddress(), uscore, eLootSourceType::MISSION);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ public:
|
|||||||
* Returns whether or not this entity has bricks flying out when smashed
|
* Returns whether or not this entity has bricks flying out when smashed
|
||||||
* @return whether or not this entity has bricks flying out when smashed
|
* @return whether or not this entity has bricks flying out when smashed
|
||||||
*/
|
*/
|
||||||
bool GetHasBricks() const { return m_HasBricks; }
|
bool GetHasBricks() const { return m_IsModuleAssembly; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
* Sets the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
||||||
@ -546,7 +546,7 @@ private:
|
|||||||
/**
|
/**
|
||||||
* Whether this entity has bricks flying out when smashed (causes the client to look up the files)
|
* Whether this entity has bricks flying out when smashed (causes the client to look up the files)
|
||||||
*/
|
*/
|
||||||
bool m_HasBricks;
|
bool m_IsModuleAssembly;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The rate at which bricks fly out when smashed
|
* The rate at which bricks fly out when smashed
|
||||||
|
@ -826,18 +826,26 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
|||||||
if (character != nullptr && !skipChecks) {
|
if (character != nullptr && !skipChecks) {
|
||||||
// Hacky proximity rocket
|
// Hacky proximity rocket
|
||||||
if (item->GetLot() == 6416) {
|
if (item->GetLot() == 6416) {
|
||||||
const auto rocketLauchPads = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::ROCKET_LAUNCH);
|
const auto rocketLauchPads = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::ROCKET_LAUNCH);
|
||||||
|
|
||||||
const auto position = m_Parent->GetPosition();
|
const auto position = m_Parent->GetPosition();
|
||||||
|
|
||||||
for (auto* lauchPad : rocketLauchPads) {
|
for (auto* launchPad : rocketLauchPads) {
|
||||||
if (Vector3::DistanceSquared(lauchPad->GetPosition(), position) > 13 * 13) continue;
|
if (!launchPad) continue;
|
||||||
|
|
||||||
|
auto prereq = launchPad->GetVarAsString(u"rocketLaunchPreCondition");
|
||||||
|
if (!prereq.empty()) {
|
||||||
|
PreconditionExpression expression(prereq);
|
||||||
|
if (!expression.Check(m_Parent)) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vector3::DistanceSquared(launchPad->GetPosition(), position) > 13 * 13) continue;
|
||||||
|
|
||||||
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||||
|
|
||||||
if (characterComponent != nullptr) characterComponent->SetLastRocketItemID(item->GetId());
|
if (characterComponent != nullptr) characterComponent->SetLastRocketItemID(item->GetId());
|
||||||
|
|
||||||
lauchPad->OnUse(m_Parent);
|
launchPad->OnUse(m_Parent);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -879,7 +887,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
|||||||
|
|
||||||
EquipScripts(item);
|
EquipScripts(item);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::UnEquipItem(Item* item) {
|
void InventoryComponent::UnEquipItem(Item* item) {
|
||||||
@ -909,12 +917,12 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
|||||||
|
|
||||||
UnequipScripts(item);
|
UnequipScripts(item);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
// Trigger property event
|
// Trigger property event
|
||||||
if (PropertyManagementComponent::Instance() != nullptr && item->GetCount() > 0 && Inventory::FindInventoryTypeForLot(item->GetLot()) == MODELS) {
|
if (PropertyManagementComponent::Instance() != nullptr && item->GetCount() > 0 && Inventory::FindInventoryTypeForLot(item->GetLot()) == MODELS) {
|
||||||
PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
PropertyManagementComponent::Instance()->GetParent()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
||||||
dZoneManager::Instance()->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
Game::zoneManager->GetZoneControlObject()->OnZonePropertyModelRemovedWhileEquipped(m_Parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -960,7 +968,7 @@ void InventoryComponent::HandlePossession(Item* item) {
|
|||||||
if (possessorComponent->GetIsDismounting()) return;
|
if (possessorComponent->GetIsDismounting()) return;
|
||||||
|
|
||||||
// Check to see if we are already mounting something
|
// Check to see if we are already mounting something
|
||||||
auto* currentlyPossessedEntity = EntityManager::Instance()->GetEntity(possessorComponent->GetPossessable());
|
auto* currentlyPossessedEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
||||||
auto currentlyPossessedItem = possessorComponent->GetMountItemID();
|
auto currentlyPossessedItem = possessorComponent->GetMountItemID();
|
||||||
|
|
||||||
if (currentlyPossessedItem) {
|
if (currentlyPossessedItem) {
|
||||||
@ -983,26 +991,15 @@ void InventoryComponent::HandlePossession(Item* item) {
|
|||||||
info.rot = startRotation;
|
info.rot = startRotation;
|
||||||
info.spawnerID = m_Parent->GetObjectID();
|
info.spawnerID = m_Parent->GetObjectID();
|
||||||
|
|
||||||
auto* mount = EntityManager::Instance()->CreateEntity(info, nullptr, m_Parent);
|
auto* mount = Game::entityManager->CreateEntity(info, nullptr, m_Parent);
|
||||||
|
|
||||||
// Check to see if the mount is a vehicle, if so, flip it
|
// Check to see if the mount is a vehicle, if so, flip it
|
||||||
auto* vehicleComponent = mount->GetComponent<VehiclePhysicsComponent>();
|
auto* vehicleComponent = mount->GetComponent<VehiclePhysicsComponent>();
|
||||||
if (vehicleComponent) {
|
if (vehicleComponent) characterComponent->SetIsRacing(true);
|
||||||
auto angles = startRotation.GetEulerAngles();
|
|
||||||
// Make it right side up
|
|
||||||
angles.x -= PI;
|
|
||||||
// Make it going in the direction of the player
|
|
||||||
angles.y -= PI;
|
|
||||||
startRotation = NiQuaternion::FromEulerAngles(angles);
|
|
||||||
mount->SetRotation(startRotation);
|
|
||||||
// We're pod racing now
|
|
||||||
characterComponent->SetIsRacing(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the destroyable stats
|
// Setup the destroyable stats
|
||||||
auto* destroyableComponent = mount->GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = mount->GetComponent<DestroyableComponent>();
|
||||||
if (destroyableComponent) {
|
if (destroyableComponent) {
|
||||||
destroyableComponent->SetIsSmashable(false);
|
|
||||||
destroyableComponent->SetIsImmune(true);
|
destroyableComponent->SetIsImmune(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1019,9 +1016,9 @@ void InventoryComponent::HandlePossession(Item* item) {
|
|||||||
GameMessages::SendSetJetPackMode(m_Parent, false);
|
GameMessages::SendSetJetPackMode(m_Parent, false);
|
||||||
|
|
||||||
// Make it go to the client
|
// Make it go to the client
|
||||||
EntityManager::Instance()->ConstructEntity(mount);
|
Game::entityManager->ConstructEntity(mount);
|
||||||
// Update the possessor
|
// Update the possessor
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
// have to unlock the input so it vehicle can be driven
|
// have to unlock the input so it vehicle can be driven
|
||||||
if (vehicleComponent) GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress());
|
if (vehicleComponent) GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress());
|
||||||
@ -1083,7 +1080,7 @@ void InventoryComponent::PopEquippedItems() {
|
|||||||
destroyableComponent->SetHealth(static_cast<int32_t>(destroyableComponent->GetMaxHealth()));
|
destroyableComponent->SetHealth(static_cast<int32_t>(destroyableComponent->GetMaxHealth()));
|
||||||
destroyableComponent->SetArmor(static_cast<int32_t>(destroyableComponent->GetMaxArmor()));
|
destroyableComponent->SetArmor(static_cast<int32_t>(destroyableComponent->GetMaxArmor()));
|
||||||
destroyableComponent->SetImagination(static_cast<int32_t>(destroyableComponent->GetMaxImagination()));
|
destroyableComponent->SetImagination(static_cast<int32_t>(destroyableComponent->GetMaxImagination()));
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Dirty = true;
|
m_Dirty = true;
|
||||||
@ -1259,7 +1256,7 @@ void InventoryComponent::SpawnPet(Item* item) {
|
|||||||
info.rot = NiQuaternion::IDENTITY;
|
info.rot = NiQuaternion::IDENTITY;
|
||||||
info.spawnerID = m_Parent->GetObjectID();
|
info.spawnerID = m_Parent->GetObjectID();
|
||||||
|
|
||||||
auto* pet = EntityManager::Instance()->CreateEntity(info);
|
auto* pet = Game::entityManager->CreateEntity(info);
|
||||||
|
|
||||||
auto* petComponent = pet->GetComponent<PetComponent>();
|
auto* petComponent = pet->GetComponent<PetComponent>();
|
||||||
|
|
||||||
@ -1267,7 +1264,7 @@ void InventoryComponent::SpawnPet(Item* item) {
|
|||||||
petComponent->Activate(item);
|
petComponent->Activate(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->ConstructEntity(pet);
|
Game::entityManager->ConstructEntity(pet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryComponent::SetDatabasePet(LWOOBJID id, const DatabasePet& data) {
|
void InventoryComponent::SetDatabasePet(LWOOBJID id, const DatabasePet& data) {
|
||||||
@ -1376,7 +1373,7 @@ void InventoryComponent::SetNPCItems(const std::vector<LOT>& items) {
|
|||||||
UpdateSlot(info.equipLocation, { id, static_cast<LOT>(item), 1, slot++ }, true);
|
UpdateSlot(info.equipLocation, { id, static_cast<LOT>(item), 1, slot++ }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryComponent::~InventoryComponent() {
|
InventoryComponent::~InventoryComponent() {
|
||||||
|
@ -35,7 +35,7 @@ void LUPExhibitComponent::NextExhibit() {
|
|||||||
|
|
||||||
m_Exhibit = m_Exhibits[m_ExhibitIndex];
|
m_Exhibit = m_Exhibits[m_ExhibitIndex];
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include "InventoryComponent.h"
|
#include "InventoryComponent.h"
|
||||||
#include "GameMessages.h"
|
#include "GameMessages.h"
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "AMFFormat.h"
|
#include "Amf3.h"
|
||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
#include "Mail.h"
|
#include "Mail.h"
|
||||||
#include "MissionPrerequisites.h"
|
#include "MissionPrerequisites.h"
|
||||||
@ -26,7 +26,7 @@ std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent:
|
|||||||
|
|
||||||
//! Initializer
|
//! Initializer
|
||||||
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
|
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
|
||||||
m_LastUsedMissionOrderUID = dZoneManager::Instance()->GetUniqueMissionIdStartingValue();
|
m_LastUsedMissionOrderUID = Game::zoneManager->GetUniqueMissionIdStartingValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
|
@ -377,7 +377,7 @@ bool MovementAIComponent::Warp(const NiPoint3& point) {
|
|||||||
|
|
||||||
SetPosition(destination);
|
SetPosition(destination);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ void MovementAIComponent::Stop() {
|
|||||||
|
|
||||||
m_CurrentSpeed = 0;
|
m_CurrentSpeed = 0;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
void MovementAIComponent::PullToPoint(const NiPoint3& point) {
|
||||||
@ -448,13 +448,14 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
|||||||
|
|
||||||
foundComponent:
|
foundComponent:
|
||||||
|
|
||||||
float speed;
|
// Client defaults speed to 10 and if the speed is also null in the table, it defaults to 10.
|
||||||
|
float speed = 10.0f;
|
||||||
|
|
||||||
if (physicsComponent == nullptr) {
|
if (physicsComponent) speed = physicsComponent->speed;
|
||||||
speed = 8;
|
|
||||||
} else {
|
float delta = fabs(speed) - 1.0f;
|
||||||
speed = physicsComponent->speed;
|
|
||||||
}
|
if (delta <= std::numeric_limits<float>::epsilon()) speed = 10.0f;
|
||||||
|
|
||||||
m_PhysicsSpeedCache[lot] = speed;
|
m_PhysicsSpeedCache[lot] = speed;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::stri
|
|||||||
m_MoverSubComponentType = eMoverSubComponentType::mover;
|
m_MoverSubComponentType = eMoverSubComponentType::mover;
|
||||||
m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition());
|
m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition());
|
||||||
m_PathName = GeneralUtils::ASCIIToUTF16(pathName);
|
m_PathName = GeneralUtils::ASCIIToUTF16(pathName);
|
||||||
m_Path = dZoneManager::Instance()->GetZone()->GetPath(pathName);
|
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
|
||||||
m_NoAutoStart = false;
|
m_NoAutoStart = false;
|
||||||
|
|
||||||
if (m_Path == nullptr) {
|
if (m_Path == nullptr) {
|
||||||
@ -133,7 +133,7 @@ void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) {
|
|||||||
|
|
||||||
subComponent->mState = value;
|
subComponent->mState = value;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) {
|
void MovingPlatformComponent::GotoWaypoint(uint32_t index, bool stopAtWaypoint) {
|
||||||
@ -194,7 +194,7 @@ void MovingPlatformComponent::StartPathing() {
|
|||||||
|
|
||||||
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovingPlatformComponent::ContinuePathing() {
|
void MovingPlatformComponent::ContinuePathing() {
|
||||||
@ -242,7 +242,7 @@ void MovingPlatformComponent::ContinuePathing() {
|
|||||||
subComponent->mCurrentWaypointIndex = pathSize;
|
subComponent->mCurrentWaypointIndex = pathSize;
|
||||||
switch (behavior) {
|
switch (behavior) {
|
||||||
case PathBehavior::Once:
|
case PathBehavior::Once:
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case PathBehavior::Bounce:
|
case PathBehavior::Bounce:
|
||||||
@ -304,7 +304,7 @@ void MovingPlatformComponent::ContinuePathing() {
|
|||||||
ContinuePathing();
|
ContinuePathing();
|
||||||
});
|
});
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MovingPlatformComponent::StopPathing() {
|
void MovingPlatformComponent::StopPathing() {
|
||||||
@ -318,7 +318,7 @@ void MovingPlatformComponent::StopPathing() {
|
|||||||
subComponent->mDesiredWaypointIndex = -1;
|
subComponent->mDesiredWaypointIndex = -1;
|
||||||
subComponent->mShouldStopAtDesiredWaypoint = false;
|
subComponent->mShouldStopAtDesiredWaypoint = false;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
//GameMessages::SendPlatformResync(m_Parent, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
}
|
}
|
||||||
@ -341,7 +341,7 @@ void MovingPlatformComponent::WarpToWaypoint(size_t index) {
|
|||||||
m_Parent->SetPosition(waypoint.position);
|
m_Parent->SetPosition(waypoint.position);
|
||||||
m_Parent->SetRotation(waypoint.rotation);
|
m_Parent->SetRotation(waypoint.rotation);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MovingPlatformComponent::GetLastWaypointIndex() const {
|
size_t MovingPlatformComponent::GetLastWaypointIndex() const {
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
#include "EntityInfo.h"
|
#include "EntityInfo.h"
|
||||||
#include "eMissionTaskType.h"
|
#include "eMissionTaskType.h"
|
||||||
|
#include "RenderComponent.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ void PetComponent::OnUse(Entity* originator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_Tamer != LWOOBJID_EMPTY) {
|
if (m_Tamer != LWOOBJID_EMPTY) {
|
||||||
auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer);
|
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||||
|
|
||||||
if (tamer != nullptr) {
|
if (tamer != nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -235,7 +236,7 @@ void PetComponent::OnUse(Entity* originator) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& bricks = BrickDatabase::Instance()->GetBricks(buildFile);
|
const auto& bricks = BrickDatabase::GetBricks(buildFile);
|
||||||
|
|
||||||
if (bricks.empty()) {
|
if (bricks.empty()) {
|
||||||
ChatPackets::SendSystemMessage(originator->GetSystemAddress(), u"Failed to load the puzzle minigame for this pet.");
|
ChatPackets::SendSystemMessage(originator->GetSystemAddress(), u"Failed to load the puzzle minigame for this pet.");
|
||||||
@ -343,7 +344,7 @@ void PetComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
if (m_Timer <= 0) {
|
if (m_Timer <= 0) {
|
||||||
Wander();
|
Wander();
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Timer = 5;
|
m_Timer = 5;
|
||||||
@ -368,7 +369,7 @@ void PetComponent::Update(float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_TresureTime > 0) {
|
if (m_TresureTime > 0) {
|
||||||
auto* tresure = EntityManager::Instance()->GetEntity(m_Interaction);
|
auto* tresure = Game::entityManager->GetEntity(m_Interaction);
|
||||||
|
|
||||||
if (tresure == nullptr) {
|
if (tresure == nullptr) {
|
||||||
m_TresureTime = 0;
|
m_TresureTime = 0;
|
||||||
@ -448,7 +449,7 @@ void PetComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
NiPoint3 tresurePosition = closestTresure->GetPosition();
|
NiPoint3 tresurePosition = closestTresure->GetPosition();
|
||||||
float distance = Vector3::DistanceSquared(position, tresurePosition);
|
float distance = Vector3::DistanceSquared(position, tresurePosition);
|
||||||
if (distance < 3 * 3) {
|
if (distance < 5 * 5) {
|
||||||
m_Interaction = closestTresure->GetObjectID();
|
m_Interaction = closestTresure->GetObjectID();
|
||||||
|
|
||||||
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, 202, true);
|
Command(NiPoint3::ZERO, LWOOBJID_EMPTY, 1, 202, true);
|
||||||
@ -475,7 +476,7 @@ skipTresure:
|
|||||||
void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) {
|
void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) {
|
||||||
if (m_Tamer == LWOOBJID_EMPTY) return;
|
if (m_Tamer == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer);
|
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||||
|
|
||||||
if (tamer == nullptr) {
|
if (tamer == nullptr) {
|
||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
@ -497,7 +498,7 @@ void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) {
|
|||||||
|
|
||||||
destroyableComponent->SetImagination(imagination);
|
destroyableComponent->SetImagination(imagination);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(tamer);
|
Game::entityManager->SerializeEntity(tamer);
|
||||||
|
|
||||||
if (clientFailed) {
|
if (clientFailed) {
|
||||||
if (imagination < cached->second.imaginationCost) {
|
if (imagination < cached->second.imaginationCost) {
|
||||||
@ -515,7 +516,7 @@ void PetComponent::TryBuild(uint32_t numBricks, bool clientFailed) {
|
|||||||
void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||||
if (m_Tamer == LWOOBJID_EMPTY) return;
|
if (m_Tamer == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer);
|
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||||
|
|
||||||
if (tamer == nullptr) {
|
if (tamer == nullptr) {
|
||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
@ -530,7 +531,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameMessages::SendPlayFXEffect(tamer, -1, u"petceleb", "", LWOOBJID_EMPTY, 1, 1, true);
|
GameMessages::SendPlayFXEffect(tamer, -1, u"petceleb", "", LWOOBJID_EMPTY, 1, 1, true);
|
||||||
GameMessages::SendPlayAnimation(tamer, u"rebuild-celebrate");
|
RenderComponent::PlayAnimation(tamer, u"rebuild-celebrate");
|
||||||
|
|
||||||
EntityInfo info{};
|
EntityInfo info{};
|
||||||
info.lot = cached->second.puzzleModelLot;
|
info.lot = cached->second.puzzleModelLot;
|
||||||
@ -538,11 +539,11 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
|||||||
info.rot = NiQuaternion::IDENTITY;
|
info.rot = NiQuaternion::IDENTITY;
|
||||||
info.spawnerID = tamer->GetObjectID();
|
info.spawnerID = tamer->GetObjectID();
|
||||||
|
|
||||||
auto* modelEntity = EntityManager::Instance()->CreateEntity(info);
|
auto* modelEntity = Game::entityManager->CreateEntity(info);
|
||||||
|
|
||||||
m_ModelId = modelEntity->GetObjectID();
|
m_ModelId = modelEntity->GetObjectID();
|
||||||
|
|
||||||
EntityManager::Instance()->ConstructEntity(modelEntity);
|
Game::entityManager->ConstructEntity(modelEntity);
|
||||||
|
|
||||||
GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress());
|
GameMessages::SendNotifyTamingModelLoadedOnServer(m_Tamer, tamer->GetSystemAddress());
|
||||||
|
|
||||||
@ -638,7 +639,7 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer);
|
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||||
|
|
||||||
if (tamer == nullptr) {
|
if (tamer == nullptr) {
|
||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
@ -660,7 +661,7 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
|||||||
//Save our pet's new name to the db:
|
//Save our pet's new name to the db:
|
||||||
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
|
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
std::u16string u16name = GeneralUtils::UTF8ToUTF16(m_Name);
|
std::u16string u16name = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||||
std::u16string u16ownerName = GeneralUtils::UTF8ToUTF16(m_OwnerName);
|
std::u16string u16ownerName = GeneralUtils::UTF8ToUTF16(m_OwnerName);
|
||||||
@ -683,7 +684,7 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
|||||||
|
|
||||||
GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
GameMessages::SendTerminateInteraction(m_Tamer, eTerminateType::FROM_INTERACTION, m_Parent->GetObjectID());
|
||||||
|
|
||||||
auto* modelEntity = EntityManager::Instance()->GetEntity(m_ModelId);
|
auto* modelEntity = Game::entityManager->GetEntity(m_ModelId);
|
||||||
|
|
||||||
if (modelEntity != nullptr) {
|
if (modelEntity != nullptr) {
|
||||||
modelEntity->Smash(m_Tamer);
|
modelEntity->Smash(m_Tamer);
|
||||||
@ -702,7 +703,7 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
|||||||
void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) {
|
void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) {
|
||||||
if (m_Tamer == LWOOBJID_EMPTY) return;
|
if (m_Tamer == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer);
|
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||||
|
|
||||||
if (tamer == nullptr) {
|
if (tamer == nullptr) {
|
||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
@ -732,7 +733,7 @@ void PetComponent::ClientExitTamingMinigame(bool voluntaryExit) {
|
|||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
m_Timer = 0;
|
m_Timer = 0;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
// Notify the end of a pet taming minigame
|
// Notify the end of a pet taming minigame
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
|
||||||
@ -753,7 +754,7 @@ void PetComponent::StartTimer() {
|
|||||||
void PetComponent::ClientFailTamingMinigame() {
|
void PetComponent::ClientFailTamingMinigame() {
|
||||||
if (m_Tamer == LWOOBJID_EMPTY) return;
|
if (m_Tamer == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* tamer = EntityManager::Instance()->GetEntity(m_Tamer);
|
auto* tamer = Game::entityManager->GetEntity(m_Tamer);
|
||||||
|
|
||||||
if (tamer == nullptr) {
|
if (tamer == nullptr) {
|
||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
@ -783,7 +784,7 @@ void PetComponent::ClientFailTamingMinigame() {
|
|||||||
m_Tamer = LWOOBJID_EMPTY;
|
m_Tamer = LWOOBJID_EMPTY;
|
||||||
m_Timer = 0;
|
m_Timer = 0;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
// Notify the end of a pet taming minigame
|
// Notify the end of a pet taming minigame
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(m_Parent)) {
|
||||||
@ -886,7 +887,7 @@ void PetComponent::Activate(Item* item, bool registerPet, bool fromTaming) {
|
|||||||
|
|
||||||
m_Timer = 3;
|
m_Timer = 3;
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
owner->GetCharacter()->SetPlayerFlag(ePlayerFlag::FIRST_MANUAL_PET_HIBERNATE, true);
|
owner->GetCharacter()->SetPlayerFlag(ePlayerFlag::FIRST_MANUAL_PET_HIBERNATE, true);
|
||||||
|
|
||||||
@ -1003,7 +1004,7 @@ LWOOBJID PetComponent::GetOwnerId() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity* PetComponent::GetOwner() const {
|
Entity* PetComponent::GetOwner() const {
|
||||||
return EntityManager::Instance()->GetEntity(m_Owner);
|
return Game::entityManager->GetEntity(m_Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
LWOOBJID PetComponent::GetDatabaseId() const {
|
LWOOBJID PetComponent::GetDatabaseId() const {
|
||||||
@ -1045,7 +1046,7 @@ PetComponent* PetComponent::GetTamingPet(LWOOBJID tamer) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(pair->second);
|
auto* entity = Game::entityManager->GetEntity(pair->second);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
currentActivities.erase(tamer);
|
currentActivities.erase(tamer);
|
||||||
@ -1063,7 +1064,7 @@ PetComponent* PetComponent::GetActivePet(LWOOBJID owner) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(pair->second);
|
auto* entity = Game::entityManager->GetEntity(pair->second);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
activePets.erase(owner);
|
activePets.erase(owner);
|
||||||
|
@ -362,7 +362,7 @@ void PhantomPhysicsComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
//If we are a respawn volume, inform the client:
|
//If we are a respawn volume, inform the client:
|
||||||
if (m_IsRespawnVolume) {
|
if (m_IsRespawnVolume) {
|
||||||
auto entity = EntityManager::Instance()->GetEntity(en->GetObjectID());
|
auto entity = Game::entityManager->GetEntity(en->GetObjectID());
|
||||||
|
|
||||||
if (entity) {
|
if (entity) {
|
||||||
GameMessages::SendPlayerReachedRespawnCheckpoint(entity, m_RespawnPos, m_RespawnRot);
|
GameMessages::SendPlayerReachedRespawnCheckpoint(entity, m_RespawnPos, m_RespawnRot);
|
||||||
@ -403,8 +403,8 @@ void PhantomPhysicsComponent::SpawnVertices() {
|
|||||||
info.spawnerID = m_Parent->GetObjectID();
|
info.spawnerID = m_Parent->GetObjectID();
|
||||||
info.spawnerNodeID = 0;
|
info.spawnerNodeID = 0;
|
||||||
|
|
||||||
Entity* newEntity = EntityManager::Instance()->CreateEntity(info, nullptr);
|
Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr);
|
||||||
EntityManager::Instance()->ConstructEntity(newEntity);
|
Game::entityManager->ConstructEntity(newEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ PossessorComponent::PossessorComponent(Entity* parent) : Component(parent) {
|
|||||||
|
|
||||||
PossessorComponent::~PossessorComponent() {
|
PossessorComponent::~PossessorComponent() {
|
||||||
if (m_Possessable != LWOOBJID_EMPTY) {
|
if (m_Possessable != LWOOBJID_EMPTY) {
|
||||||
auto* mount = EntityManager::Instance()->GetEntity(m_Possessable);
|
auto* mount = Game::entityManager->GetEntity(m_Possessable);
|
||||||
if (mount) {
|
if (mount) {
|
||||||
auto* possessable = mount->GetComponent<PossessableComponent>();
|
auto* possessable = mount->GetComponent<PossessableComponent>();
|
||||||
if (possessable) {
|
if (possessable) {
|
||||||
@ -58,8 +58,8 @@ void PossessorComponent::Mount(Entity* mount) {
|
|||||||
GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress());
|
GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress());
|
||||||
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
EntityManager::Instance()->SerializeEntity(mount);
|
Game::entityManager->SerializeEntity(mount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PossessorComponent::Dismount(Entity* mount, bool forceDismount) {
|
void PossessorComponent::Dismount(Entity* mount, bool forceDismount) {
|
||||||
@ -73,8 +73,8 @@ void PossessorComponent::Dismount(Entity* mount, bool forceDismount) {
|
|||||||
possessableComponent->SetPossessor(LWOOBJID_EMPTY);
|
possessableComponent->SetPossessor(LWOOBJID_EMPTY);
|
||||||
if (forceDismount) possessableComponent->ForceDepossess();
|
if (forceDismount) possessableComponent->ForceDepossess();
|
||||||
}
|
}
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
EntityManager::Instance()->SerializeEntity(mount);
|
Game::entityManager->SerializeEntity(mount);
|
||||||
|
|
||||||
auto characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
auto characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||||
if (characterComponent) characterComponent->SetIsRacing(false);
|
if (characterComponent) characterComponent->SetIsRacing(false);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
#include "UserManager.h"
|
#include "UserManager.h"
|
||||||
#include "dLogger.h"
|
#include "dLogger.h"
|
||||||
#include "AMFFormat.h"
|
#include "Amf3.h"
|
||||||
#include "eObjectBits.h"
|
#include "eObjectBits.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
|
||||||
@ -36,12 +36,9 @@ void PropertyEntranceComponent::OnUse(Entity* entity) {
|
|||||||
|
|
||||||
AMFArrayValue args;
|
AMFArrayValue args;
|
||||||
|
|
||||||
auto* state = new AMFStringValue();
|
args.Insert("state", "property_menu");
|
||||||
state->SetStringValue("property_menu");
|
|
||||||
|
|
||||||
args.InsertValue("state", state);
|
GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", args);
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient(entity, entity->GetSystemAddress(), "pushGameState", &args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr) {
|
void PropertyEntranceComponent::OnEnterProperty(Entity* entity, uint32_t index, bool returnToZone, const SystemAddress& sysAddr) {
|
||||||
|
@ -38,7 +38,7 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo
|
|||||||
|
|
||||||
instance = this;
|
instance = this;
|
||||||
|
|
||||||
const auto& worldId = dZoneManager::Instance()->GetZone()->GetZoneID();
|
const auto& worldId = Game::zoneManager->GetZone()->GetZoneID();
|
||||||
|
|
||||||
const auto zoneId = worldId.GetMapID();
|
const auto zoneId = worldId.GetMapID();
|
||||||
const auto cloneId = worldId.GetCloneID();
|
const auto cloneId = worldId.GetCloneID();
|
||||||
@ -90,7 +90,7 @@ LWOOBJID PropertyManagementComponent::GetOwnerId() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity* PropertyManagementComponent::GetOwner() const {
|
Entity* PropertyManagementComponent::GetOwner() const {
|
||||||
return EntityManager::Instance()->GetEntity(owner);
|
return Game::entityManager->GetEntity(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyManagementComponent::SetOwner(Entity* value) {
|
void PropertyManagementComponent::SetOwner(Entity* value) {
|
||||||
@ -98,7 +98,7 @@ void PropertyManagementComponent::SetOwner(Entity* value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NiPoint3> PropertyManagementComponent::GetPaths() const {
|
std::vector<NiPoint3> PropertyManagementComponent::GetPaths() const {
|
||||||
const auto zoneId = dZoneManager::Instance()->GetZone()->GetWorldID();
|
const auto zoneId = Game::zoneManager->GetZone()->GetWorldID();
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||||
"SELECT path FROM PropertyTemplate WHERE mapID = ?;");
|
"SELECT path FROM PropertyTemplate WHERE mapID = ?;");
|
||||||
@ -185,14 +185,14 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(playerId);
|
auto* entity = Game::entityManager->GetEntity(playerId);
|
||||||
|
|
||||||
auto* user = entity->GetParentUser();
|
auto* user = entity->GetParentUser();
|
||||||
|
|
||||||
auto character = entity->GetCharacter();
|
auto character = entity->GetCharacter();
|
||||||
if (!character) return false;
|
if (!character) return false;
|
||||||
|
|
||||||
auto* zone = dZoneManager::Instance()->GetZone();
|
auto* zone = Game::zoneManager->GetZone();
|
||||||
|
|
||||||
const auto& worldId = zone->GetZoneID();
|
const auto& worldId = zone->GetZoneID();
|
||||||
const auto propertyZoneId = worldId.GetMapID();
|
const auto propertyZoneId = worldId.GetMapID();
|
||||||
@ -240,7 +240,7 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* zoneControlObject = dZoneManager::Instance()->GetZoneControlObject();
|
auto* zoneControlObject = Game::zoneManager->GetZoneControlObject();
|
||||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControlObject)) {
|
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControlObject)) {
|
||||||
script->OnZonePropertyRented(zoneControlObject, entity);
|
script->OnZonePropertyRented(zoneControlObject, entity);
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ void PropertyManagementComponent::OnStartBuilding() {
|
|||||||
|
|
||||||
LWOMAPID zoneId = 1100;
|
LWOMAPID zoneId = 1100;
|
||||||
|
|
||||||
const auto entrance = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::PROPERTY_ENTRANCE);
|
const auto entrance = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::PROPERTY_ENTRANCE);
|
||||||
|
|
||||||
originalPrivacyOption = privacyOption;
|
originalPrivacyOption = privacyOption;
|
||||||
|
|
||||||
@ -339,9 +339,9 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
|||||||
info.settings.push_back(setting->Copy());
|
info.settings.push_back(setting->Copy());
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* newEntity = EntityManager::Instance()->CreateEntity(info);
|
Entity* newEntity = Game::entityManager->CreateEntity(info);
|
||||||
if (newEntity != nullptr) {
|
if (newEntity != nullptr) {
|
||||||
EntityManager::Instance()->ConstructEntity(newEntity);
|
Game::entityManager->ConstructEntity(newEntity);
|
||||||
|
|
||||||
// Make sure the propMgmt doesn't delete our model after the server dies
|
// Make sure the propMgmt doesn't delete our model after the server dies
|
||||||
// Trying to do this after the entity is constructed. Shouldn't really change anything but
|
// Trying to do this after the entity is constructed. Shouldn't really change anything but
|
||||||
@ -371,14 +371,14 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
|||||||
info.respawnTime = 10;
|
info.respawnTime = 10;
|
||||||
|
|
||||||
info.emulated = true;
|
info.emulated = true;
|
||||||
info.emulator = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
|
info.emulator = Game::entityManager->GetZoneControlEntity()->GetObjectID();
|
||||||
|
|
||||||
info.spawnerID = persistentId;
|
info.spawnerID = persistentId;
|
||||||
GeneralUtils::SetBit(info.spawnerID, eObjectBits::CLIENT);
|
GeneralUtils::SetBit(info.spawnerID, eObjectBits::CLIENT);
|
||||||
|
|
||||||
const auto spawnerId = dZoneManager::Instance()->MakeSpawner(info);
|
const auto spawnerId = Game::zoneManager->MakeSpawner(info);
|
||||||
|
|
||||||
auto* spawner = dZoneManager::Instance()->GetSpawner(spawnerId);
|
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
|
||||||
|
|
||||||
auto ldfModelBehavior = new LDFData<LWOOBJID>(u"modelBehaviors", 0);
|
auto ldfModelBehavior = new LDFData<LWOOBJID>(u"modelBehaviors", 0);
|
||||||
auto userModelID = new LDFData<LWOOBJID>(u"userModelID", info.spawnerID);
|
auto userModelID = new LDFData<LWOOBJID>(u"userModelID", info.spawnerID);
|
||||||
@ -401,7 +401,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
|||||||
|
|
||||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
|
||||||
EntityManager::Instance()->GetZoneControlEntity()->OnZonePropertyModelPlaced(entity);
|
Game::entityManager->GetZoneControlEntity()->OnZonePropertyModelPlaced(entity);
|
||||||
});
|
});
|
||||||
// Progress place model missions
|
// Progress place model missions
|
||||||
auto missionComponent = entity->GetComponent<MissionComponent>();
|
auto missionComponent = entity->GetComponent<MissionComponent>();
|
||||||
@ -433,7 +433,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
|||||||
|
|
||||||
const auto spawnerId = index->second;
|
const auto spawnerId = index->second;
|
||||||
|
|
||||||
auto* spawner = dZoneManager::Instance()->GetSpawner(spawnerId);
|
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
|
||||||
|
|
||||||
models.erase(id);
|
models.erase(id);
|
||||||
|
|
||||||
@ -441,7 +441,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
|||||||
Game::logger->Log("PropertyManagementComponent", "Failed to find spawner");
|
Game::logger->Log("PropertyManagementComponent", "Failed to find spawner");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* model = EntityManager::Instance()->GetEntity(id);
|
auto* model = Game::entityManager->GetEntity(id);
|
||||||
|
|
||||||
if (model == nullptr) {
|
if (model == nullptr) {
|
||||||
Game::logger->Log("PropertyManagementComponent", "Failed to find model entity");
|
Game::logger->Log("PropertyManagementComponent", "Failed to find model entity");
|
||||||
@ -449,7 +449,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->DestructEntity(model);
|
Game::entityManager->DestructEntity(model);
|
||||||
|
|
||||||
Game::logger->Log("PropertyManagementComponent", "Deleting model LOT %i", model->GetLOT());
|
Game::logger->Log("PropertyManagementComponent", "Deleting model LOT %i", model->GetLOT());
|
||||||
|
|
||||||
@ -496,7 +496,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
|||||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY);
|
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY);
|
||||||
|
|
||||||
if (spawner != nullptr) {
|
if (spawner != nullptr) {
|
||||||
dZoneManager::Instance()->RemoveSpawner(spawner->m_Info.spawnerID);
|
Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID);
|
||||||
} else {
|
} else {
|
||||||
model->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
model->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
||||||
}
|
}
|
||||||
@ -520,13 +520,13 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
|||||||
item->Equip();
|
item->Equip();
|
||||||
|
|
||||||
GameMessages::SendUGCEquipPostDeleteBasedOnEditMode(entity->GetObjectID(), entity->GetSystemAddress(), item->GetId(), item->GetCount());
|
GameMessages::SendUGCEquipPostDeleteBasedOnEditMode(entity->GetObjectID(), entity->GetSystemAddress(), item->GetId(), item->GetCount());
|
||||||
EntityManager::Instance()->GetZoneControlEntity()->OnZonePropertyModelPickedUp(entity);
|
Game::entityManager->GetZoneControlEntity()->OnZonePropertyModelPickedUp(entity);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: // Return to inv
|
case 1: // Return to inv
|
||||||
{
|
{
|
||||||
EntityManager::Instance()->GetZoneControlEntity()->OnZonePropertyModelRemoved(entity);
|
Game::entityManager->GetZoneControlEntity()->OnZonePropertyModelRemoved(entity);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -549,7 +549,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
|||||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY);
|
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), NiPoint3::ZERO, LWOOBJID_EMPTY, 16, NiQuaternion::IDENTITY);
|
||||||
|
|
||||||
if (spawner != nullptr) {
|
if (spawner != nullptr) {
|
||||||
dZoneManager::Instance()->RemoveSpawner(spawner->m_Info.spawnerID);
|
Game::zoneManager->RemoveSpawner(spawner->m_Info.spawnerID);
|
||||||
} else {
|
} else {
|
||||||
model->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
model->Smash(LWOOBJID_EMPTY, eKillType::SILENT);
|
||||||
}
|
}
|
||||||
@ -613,7 +613,7 @@ void PropertyManagementComponent::Load() {
|
|||||||
info.respawnTime = 10;
|
info.respawnTime = 10;
|
||||||
|
|
||||||
//info.emulated = true;
|
//info.emulated = true;
|
||||||
//info.emulator = EntityManager::Instance()->GetZoneControlEntity()->GetObjectID();
|
//info.emulator = Game::entityManager->GetZoneControlEntity()->GetObjectID();
|
||||||
|
|
||||||
info.spawnerID = id;
|
info.spawnerID = id;
|
||||||
|
|
||||||
@ -652,9 +652,9 @@ void PropertyManagementComponent::Load() {
|
|||||||
|
|
||||||
node->config = settings;
|
node->config = settings;
|
||||||
|
|
||||||
const auto spawnerId = dZoneManager::Instance()->MakeSpawner(info);
|
const auto spawnerId = Game::zoneManager->MakeSpawner(info);
|
||||||
|
|
||||||
auto* spawner = dZoneManager::Instance()->GetSpawner(spawnerId);
|
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
|
||||||
|
|
||||||
auto* model = spawner->Spawn();
|
auto* model = spawner->Spawn();
|
||||||
|
|
||||||
@ -698,7 +698,7 @@ void PropertyManagementComponent::Save() {
|
|||||||
|
|
||||||
modelIds.push_back(id);
|
modelIds.push_back(id);
|
||||||
|
|
||||||
auto* entity = EntityManager::Instance()->GetEntity(pair.first);
|
auto* entity = Game::entityManager->GetEntity(pair.first);
|
||||||
|
|
||||||
if (entity == nullptr) {
|
if (entity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -786,7 +786,7 @@ void PropertyManagementComponent::OnQueryPropertyData(Entity* originator, const
|
|||||||
author = m_Parent->GetObjectID();
|
author = m_Parent->GetObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& worldId = dZoneManager::Instance()->GetZone()->GetZoneID();
|
const auto& worldId = Game::zoneManager->GetZone()->GetZoneID();
|
||||||
const auto zoneId = worldId.GetMapID();
|
const auto zoneId = worldId.GetMapID();
|
||||||
|
|
||||||
Game::logger->Log("Properties", "Getting property info for %d", zoneId);
|
Game::logger->Log("Properties", "Getting property info for %d", zoneId);
|
||||||
|
@ -43,7 +43,7 @@ void PropertyVendorComponent::OnBuyFromVendor(Entity* originator, const bool con
|
|||||||
|
|
||||||
GameMessages::SendPropertyRentalResponse(m_Parent->GetObjectID(), 0, 0, 0, 0, originator->GetSystemAddress());
|
GameMessages::SendPropertyRentalResponse(m_Parent->GetObjectID(), 0, 0, 0, 0, originator->GetSystemAddress());
|
||||||
|
|
||||||
auto* controller = dZoneManager::Instance()->GetZoneControlObject();
|
auto* controller = Game::zoneManager->GetZoneControlObject();
|
||||||
|
|
||||||
controller->OnFireEventServerSide(m_Parent, "propertyRented");
|
controller->OnFireEventServerSide(m_Parent, "propertyRented");
|
||||||
|
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "Loot.h"
|
#include "Loot.h"
|
||||||
#include "eMissionTaskType.h"
|
#include "eMissionTaskType.h"
|
||||||
|
#include "LeaderboardManager.h"
|
||||||
|
#include "dZoneManager.h"
|
||||||
|
#include "CDActivitiesTable.h"
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
#define M_PI 3.14159265358979323846264338327950288
|
#define M_PI 3.14159265358979323846264338327950288
|
||||||
@ -45,36 +48,14 @@ RacingControlComponent::RacingControlComponent(Entity* parent)
|
|||||||
m_EmptyTimer = 0;
|
m_EmptyTimer = 0;
|
||||||
m_SoloRacing = Game::config->GetValue("solo_racing") == "1";
|
m_SoloRacing = Game::config->GetValue("solo_racing") == "1";
|
||||||
|
|
||||||
// Select the main world ID as fallback when a player fails to load.
|
m_MainWorld = 1200;
|
||||||
|
|
||||||
const auto worldID = Game::server->GetZoneID();
|
const auto worldID = Game::server->GetZoneID();
|
||||||
|
if (Game::zoneManager->CheckIfAccessibleZone((worldID/10)*10)) m_MainWorld = (worldID/10)*10;
|
||||||
|
|
||||||
switch (worldID) {
|
|
||||||
case 1203:
|
|
||||||
m_ActivityID = 42;
|
m_ActivityID = 42;
|
||||||
m_MainWorld = 1200;
|
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
||||||
break;
|
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.instanceMapID == worldID); });
|
||||||
|
for (CDActivities activity : activities) m_ActivityID = activity.ActivityID;
|
||||||
case 1261:
|
|
||||||
m_ActivityID = 60;
|
|
||||||
m_MainWorld = 1260;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1303:
|
|
||||||
m_ActivityID = 39;
|
|
||||||
m_MainWorld = 1300;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1403:
|
|
||||||
m_ActivityID = 54;
|
|
||||||
m_MainWorld = 1400;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
m_ActivityID = 42;
|
|
||||||
m_MainWorld = 1200;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RacingControlComponent::~RacingControlComponent() {}
|
RacingControlComponent::~RacingControlComponent() {}
|
||||||
@ -125,10 +106,10 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
|
|
||||||
// Calculate the vehicle's starting position.
|
// Calculate the vehicle's starting position.
|
||||||
|
|
||||||
auto* path = dZoneManager::Instance()->GetZone()->GetPath(
|
auto* path = Game::zoneManager->GetZone()->GetPath(
|
||||||
GeneralUtils::UTF16ToWTF8(m_PathName));
|
GeneralUtils::UTF16ToWTF8(m_PathName));
|
||||||
|
|
||||||
auto spawnPointEntities = EntityManager::Instance()->GetEntitiesByLOT(4843);
|
auto spawnPointEntities = Game::entityManager->GetEntitiesByLOT(4843);
|
||||||
auto startPosition = NiPoint3::ZERO;
|
auto startPosition = NiPoint3::ZERO;
|
||||||
auto startRotation = NiQuaternion::IDENTITY;
|
auto startRotation = NiQuaternion::IDENTITY;
|
||||||
const std::string placementAsString = std::to_string(positionNumber);
|
const std::string placementAsString = std::to_string(positionNumber);
|
||||||
@ -144,8 +125,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
// Make sure the player is at the correct position.
|
// Make sure the player is at the correct position.
|
||||||
|
|
||||||
GameMessages::SendTeleport(player->GetObjectID(), startPosition,
|
GameMessages::SendTeleport(player->GetObjectID(), startPosition,
|
||||||
startRotation, player->GetSystemAddress(), true,
|
startRotation, player->GetSystemAddress(), true);
|
||||||
true);
|
|
||||||
|
|
||||||
// Spawn the vehicle entity.
|
// Spawn the vehicle entity.
|
||||||
|
|
||||||
@ -156,7 +136,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
info.spawnerID = m_Parent->GetObjectID();
|
info.spawnerID = m_Parent->GetObjectID();
|
||||||
|
|
||||||
auto* carEntity =
|
auto* carEntity =
|
||||||
EntityManager::Instance()->CreateEntity(info, nullptr, m_Parent);
|
Game::entityManager->CreateEntity(info, nullptr, m_Parent);
|
||||||
|
|
||||||
// Make the vehicle a child of the racing controller.
|
// Make the vehicle a child of the racing controller.
|
||||||
m_Parent->AddChild(carEntity);
|
m_Parent->AddChild(carEntity);
|
||||||
@ -227,9 +207,9 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
|
|
||||||
// Construct and serialize everything when done.
|
// Construct and serialize everything when done.
|
||||||
|
|
||||||
EntityManager::Instance()->ConstructEntity(carEntity);
|
Game::entityManager->ConstructEntity(carEntity);
|
||||||
EntityManager::Instance()->SerializeEntity(player);
|
Game::entityManager->SerializeEntity(player);
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
GameMessages::SendRacingSetPlayerResetInfo(
|
GameMessages::SendRacingSetPlayerResetInfo(
|
||||||
m_Parent->GetObjectID(), 0, 0, player->GetObjectID(), startPosition, 1,
|
m_Parent->GetObjectID(), 0, 0, player->GetObjectID(), startPosition, 1,
|
||||||
@ -240,7 +220,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
// Reset the player to the start position during downtime, in case something
|
// Reset the player to the start position during downtime, in case something
|
||||||
// went wrong.
|
// went wrong.
|
||||||
m_Parent->AddCallbackTimer(1, [this, playerID]() {
|
m_Parent->AddCallbackTimer(1, [this, playerID]() {
|
||||||
auto* player = EntityManager::Instance()->GetEntity(playerID);
|
auto* player = Game::entityManager->GetEntity(playerID);
|
||||||
|
|
||||||
if (player == nullptr) {
|
if (player == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -263,11 +243,9 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
|
|
||||||
// Make sure everything has the correct position.
|
// Make sure everything has the correct position.
|
||||||
GameMessages::SendTeleport(player->GetObjectID(), startPosition,
|
GameMessages::SendTeleport(player->GetObjectID(), startPosition,
|
||||||
startRotation, player->GetSystemAddress(), true,
|
startRotation, player->GetSystemAddress(), true);
|
||||||
true);
|
|
||||||
GameMessages::SendTeleport(carEntity->GetObjectID(), startPosition,
|
GameMessages::SendTeleport(carEntity->GetObjectID(), startPosition,
|
||||||
startRotation, player->GetSystemAddress(), true,
|
startRotation, player->GetSystemAddress(), true);
|
||||||
true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RacingControlComponent::OnRacingClientReady(Entity* player) {
|
void RacingControlComponent::OnRacingClientReady(Entity* player) {
|
||||||
@ -291,7 +269,7 @@ void RacingControlComponent::OnRacingClientReady(Entity* player) {
|
|||||||
racingPlayer.vehicleID, UNASSIGNED_SYSTEM_ADDRESS);
|
racingPlayer.vehicleID, UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RacingControlComponent::OnRequestDie(Entity* player) {
|
void RacingControlComponent::OnRequestDie(Entity* player) {
|
||||||
@ -304,7 +282,7 @@ void RacingControlComponent::OnRequestDie(Entity* player) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* vehicle =
|
auto* vehicle =
|
||||||
EntityManager::Instance()->GetEntity(racingPlayer.vehicleID);
|
Game::entityManager->GetEntity(racingPlayer.vehicleID);
|
||||||
|
|
||||||
if (!vehicle) return;
|
if (!vehicle) return;
|
||||||
|
|
||||||
@ -341,7 +319,7 @@ void RacingControlComponent::OnRequestDie(Entity* player) {
|
|||||||
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
|
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
|
||||||
// Reset imagination to half its current value, rounded up to the nearest value divisible by 10, as it was done in live.
|
// Reset imagination to half its current value, rounded up to the nearest value divisible by 10, as it was done in live.
|
||||||
if (destroyableComponent) destroyableComponent->SetImagination(respawnImagination);
|
if (destroyableComponent) destroyableComponent->SetImagination(respawnImagination);
|
||||||
EntityManager::Instance()->SerializeEntity(vehicle);
|
Game::entityManager->SerializeEntity(vehicle);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||||
@ -370,7 +348,7 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto* vehicle =
|
auto* vehicle =
|
||||||
EntityManager::Instance()->GetEntity(racingPlayer.vehicleID);
|
Game::entityManager->GetEntity(racingPlayer.vehicleID);
|
||||||
|
|
||||||
if (vehicle == nullptr) {
|
if (vehicle == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -382,8 +360,7 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
|
void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t button, const std::string& id) {
|
||||||
const std::string& id) {
|
|
||||||
auto* data = GetPlayerData(player->GetObjectID());
|
auto* data = GetPlayerData(player->GetObjectID());
|
||||||
|
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
@ -391,15 +368,17 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (id == "rewardButton") {
|
if (id == "rewardButton") {
|
||||||
if (data->collectedRewards) {
|
if (data->collectedRewards) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->collectedRewards = true;
|
data->collectedRewards = true;
|
||||||
|
|
||||||
// Calculate the score, different loot depending on player count
|
// Calculate the score, different loot depending on player count
|
||||||
const auto score = m_LoadedPlayers * 10 + data->finished;
|
auto playersRating = m_LoadedPlayers;
|
||||||
|
if(m_LoadedPlayers == 1 && m_SoloRacing) {
|
||||||
|
playersRating *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto score = playersRating * 10 + data->finished;
|
||||||
LootGenerator::Instance().GiveActivityLoot(player, m_Parent, m_ActivityID, score);
|
LootGenerator::Instance().GiveActivityLoot(player, m_Parent, m_ActivityID, score);
|
||||||
|
|
||||||
// Giving rewards
|
// Giving rewards
|
||||||
@ -418,15 +397,15 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
|
|||||||
if (m_SoloRacing || m_LoadedPlayers > 2) {
|
if (m_SoloRacing || m_LoadedPlayers > 2) {
|
||||||
missionComponent->Progress(eMissionTaskType::RACING, data->finished, (LWOOBJID)eRacingTaskParam::FINISH_WITH_PLACEMENT); // Finish in 1st place on a race
|
missionComponent->Progress(eMissionTaskType::RACING, data->finished, (LWOOBJID)eRacingTaskParam::FINISH_WITH_PLACEMENT); // Finish in 1st place on a race
|
||||||
if (data->finished == 1) {
|
if (data->finished == 1) {
|
||||||
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks.
|
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks.
|
||||||
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::WIN_RACE_IN_WORLD); // Finished first place in specific world.
|
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::WIN_RACE_IN_WORLD); // Finished first place in specific world.
|
||||||
}
|
}
|
||||||
if (data->finished == m_LoadedPlayers) {
|
if (data->finished == m_LoadedPlayers) {
|
||||||
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::LAST_PLACE_FINISH); // Finished first place in specific world.
|
missionComponent->Progress(eMissionTaskType::RACING, Game::zoneManager->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::LAST_PLACE_FINISH); // Finished first place in specific world.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") {
|
} else if ((id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") && button == m_ActivityExitConfirm) {
|
||||||
auto* vehicle = EntityManager::Instance()->GetEntity(data->vehicleID);
|
auto* vehicle = Game::entityManager->GetEntity(data->vehicleID);
|
||||||
|
|
||||||
if (vehicle == nullptr) {
|
if (vehicle == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -527,7 +506,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
// Check if any players has disconnected before loading in
|
// Check if any players has disconnected before loading in
|
||||||
for (size_t i = 0; i < m_LobbyPlayers.size(); i++) {
|
for (size_t i = 0; i < m_LobbyPlayers.size(); i++) {
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(m_LobbyPlayers[i]);
|
Game::entityManager->GetEntity(m_LobbyPlayers[i]);
|
||||||
|
|
||||||
if (playerEntity == nullptr) {
|
if (playerEntity == nullptr) {
|
||||||
--m_LoadedPlayers;
|
--m_LoadedPlayers;
|
||||||
@ -549,7 +528,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
if (m_EmptyTimer >= 30) {
|
if (m_EmptyTimer >= 30) {
|
||||||
for (const auto player : m_LobbyPlayers) {
|
for (const auto player : m_LobbyPlayers) {
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(player);
|
Game::entityManager->GetEntity(player);
|
||||||
|
|
||||||
if (playerEntity == nullptr) {
|
if (playerEntity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -574,7 +553,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
"Loading player now!");
|
"Loading player now!");
|
||||||
|
|
||||||
auto* player =
|
auto* player =
|
||||||
EntityManager::Instance()->GetEntity(m_LobbyPlayers[positionNumber]);
|
Game::entityManager->GetEntity(m_LobbyPlayers[positionNumber]);
|
||||||
|
|
||||||
if (player == nullptr) {
|
if (player == nullptr) {
|
||||||
return;
|
return;
|
||||||
@ -598,7 +577,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
if (!m_Started) {
|
if (!m_Started) {
|
||||||
// Check if anyone has disconnected during this period
|
// Check if anyone has disconnected during this period
|
||||||
for (size_t i = 0; i < m_RacingPlayers.size(); i++) {
|
for (size_t i = 0; i < m_RacingPlayers.size(); i++) {
|
||||||
auto* playerEntity = EntityManager::Instance()->GetEntity(
|
auto* playerEntity = Game::entityManager->GetEntity(
|
||||||
m_RacingPlayers[i].playerID);
|
m_RacingPlayers[i].playerID);
|
||||||
|
|
||||||
if (playerEntity == nullptr) {
|
if (playerEntity == nullptr) {
|
||||||
@ -614,7 +593,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
if (m_LoadedPlayers < 2 && !(m_LoadedPlayers == 1 && m_SoloRacing)) {
|
if (m_LoadedPlayers < 2 && !(m_LoadedPlayers == 1 && m_SoloRacing)) {
|
||||||
for (const auto player : m_LobbyPlayers) {
|
for (const auto player : m_LobbyPlayers) {
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(player);
|
Game::entityManager->GetEntity(player);
|
||||||
|
|
||||||
if (playerEntity == nullptr) {
|
if (playerEntity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -647,15 +626,15 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
for (const auto& player : m_RacingPlayers) {
|
for (const auto& player : m_RacingPlayers) {
|
||||||
auto* vehicle =
|
auto* vehicle =
|
||||||
EntityManager::Instance()->GetEntity(player.vehicleID);
|
Game::entityManager->GetEntity(player.vehicleID);
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(player.playerID);
|
Game::entityManager->GetEntity(player.playerID);
|
||||||
|
|
||||||
if (vehicle != nullptr && playerEntity != nullptr) {
|
if (vehicle != nullptr && playerEntity != nullptr) {
|
||||||
GameMessages::SendTeleport(
|
GameMessages::SendTeleport(
|
||||||
player.playerID, player.respawnPosition,
|
player.playerID, player.respawnPosition,
|
||||||
player.respawnRotation,
|
player.respawnRotation,
|
||||||
playerEntity->GetSystemAddress(), true, true);
|
playerEntity->GetSystemAddress(), true);
|
||||||
|
|
||||||
vehicle->SetPosition(player.respawnPosition);
|
vehicle->SetPosition(player.respawnPosition);
|
||||||
vehicle->SetRotation(player.respawnRotation);
|
vehicle->SetRotation(player.respawnRotation);
|
||||||
@ -667,18 +646,18 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
destroyableComponent->SetImagination(0);
|
destroyableComponent->SetImagination(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(vehicle);
|
Game::entityManager->SerializeEntity(vehicle);
|
||||||
EntityManager::Instance()->SerializeEntity(
|
Game::entityManager->SerializeEntity(
|
||||||
playerEntity);
|
playerEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn imagination pickups
|
// Spawn imagination pickups
|
||||||
auto* minSpawner = dZoneManager::Instance()->GetSpawnersByName(
|
auto* minSpawner = Game::zoneManager->GetSpawnersByName(
|
||||||
"ImaginationSpawn_Min")[0];
|
"ImaginationSpawn_Min")[0];
|
||||||
auto* medSpawner = dZoneManager::Instance()->GetSpawnersByName(
|
auto* medSpawner = Game::zoneManager->GetSpawnersByName(
|
||||||
"ImaginationSpawn_Med")[0];
|
"ImaginationSpawn_Med")[0];
|
||||||
auto* maxSpawner = dZoneManager::Instance()->GetSpawnersByName(
|
auto* maxSpawner = Game::zoneManager->GetSpawnersByName(
|
||||||
"ImaginationSpawn_Max")[0];
|
"ImaginationSpawn_Max")[0];
|
||||||
|
|
||||||
minSpawner->Activate();
|
minSpawner->Activate();
|
||||||
@ -694,9 +673,9 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
// Reset players to their start location, without smashing them
|
// Reset players to their start location, without smashing them
|
||||||
for (auto& player : m_RacingPlayers) {
|
for (auto& player : m_RacingPlayers) {
|
||||||
auto* vehicleEntity =
|
auto* vehicleEntity =
|
||||||
EntityManager::Instance()->GetEntity(player.vehicleID);
|
Game::entityManager->GetEntity(player.vehicleID);
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(player.playerID);
|
Game::entityManager->GetEntity(player.playerID);
|
||||||
|
|
||||||
if (vehicleEntity == nullptr || playerEntity == nullptr) {
|
if (vehicleEntity == nullptr || playerEntity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -713,9 +692,9 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
// Activate the players movement
|
// Activate the players movement
|
||||||
for (auto& player : m_RacingPlayers) {
|
for (auto& player : m_RacingPlayers) {
|
||||||
auto* vehicleEntity =
|
auto* vehicleEntity =
|
||||||
EntityManager::Instance()->GetEntity(player.vehicleID);
|
Game::entityManager->GetEntity(player.vehicleID);
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(player.playerID);
|
Game::entityManager->GetEntity(player.playerID);
|
||||||
|
|
||||||
if (vehicleEntity == nullptr || playerEntity == nullptr) {
|
if (vehicleEntity == nullptr || playerEntity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -733,7 +712,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
Game::logger->Log("RacingControlComponent", "Starting race");
|
Game::logger->Log("RacingControlComponent", "Starting race");
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
m_StartTime = std::time(nullptr);
|
m_StartTime = std::time(nullptr);
|
||||||
}
|
}
|
||||||
@ -747,13 +726,13 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Race routines
|
// Race routines
|
||||||
auto* path = dZoneManager::Instance()->GetZone()->GetPath(
|
auto* path = Game::zoneManager->GetZone()->GetPath(
|
||||||
GeneralUtils::UTF16ToWTF8(m_PathName));
|
GeneralUtils::UTF16ToWTF8(m_PathName));
|
||||||
|
|
||||||
for (auto& player : m_RacingPlayers) {
|
for (auto& player : m_RacingPlayers) {
|
||||||
auto* vehicle = EntityManager::Instance()->GetEntity(player.vehicleID);
|
auto* vehicle = Game::entityManager->GetEntity(player.vehicleID);
|
||||||
auto* playerEntity =
|
auto* playerEntity =
|
||||||
EntityManager::Instance()->GetEntity(player.playerID);
|
Game::entityManager->GetEntity(player.playerID);
|
||||||
|
|
||||||
if (vehicle == nullptr || playerEntity == nullptr) {
|
if (vehicle == nullptr || playerEntity == nullptr) {
|
||||||
continue;
|
continue;
|
||||||
@ -859,6 +838,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
"Completed time %llu, %llu",
|
"Completed time %llu, %llu",
|
||||||
raceTime, raceTime * 1000);
|
raceTime, raceTime * 1000);
|
||||||
|
|
||||||
|
LeaderboardManager::SaveScore(playerEntity->GetObjectID(), m_ActivityID, static_cast<float>(player.raceTime), static_cast<float>(player.bestLapTime), static_cast<float>(player.finished == 1));
|
||||||
// Entire race time
|
// Entire race time
|
||||||
missionComponent->Progress(eMissionTaskType::RACING, (raceTime) * 1000, (LWOOBJID)eRacingTaskParam::TOTAL_TRACK_TIME);
|
missionComponent->Progress(eMissionTaskType::RACING, (raceTime) * 1000, (LWOOBJID)eRacingTaskParam::TOTAL_TRACK_TIME);
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user