Merge branch 'main' into slash-command-refactor

This commit is contained in:
Aaron Kimbre 2024-04-01 15:17:02 -05:00
commit 3c36662b20
33 changed files with 526 additions and 477 deletions

View File

@ -4,8 +4,9 @@ include(CTest)
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CXX_STANDARD_REQUIRED ON) set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Export the compile commands for debugging
set(CMAKE_CXX_VISIBILITY_PRESET hidden) # Set C++ symbol visibility to default to hidden set(CMAKE_POLICY_DEFAULT_CMP0063 NEW) # Set CMAKE visibility policy to NEW on project and subprojects
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # Set C and C++ symbol visibility to hide inlined functions
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Read variables from file # Read variables from file

View File

@ -73,7 +73,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve
``` ```
#### Required CMake version #### Required CMake version
This project uses <font size="4">**CMake version 3.18**</font> or higher and as such you will need to ensure you have this version installed. This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed.
You can check your CMake version by using the following command in a terminal. You can check your CMake version by using the following command in a terminal.
```bash ```bash
cmake --version cmake --version

View File

@ -1,6 +1,6 @@
#include "ChatIgnoreList.h" #include "ChatIgnoreList.h"
#include "PlayerContainer.h" #include "PlayerContainer.h"
#include "eChatInternalMessageType.h" #include "eChatMessageType.h"
#include "BitStreamUtils.h" #include "BitStreamUtils.h"
#include "Game.h" #include "Game.h"
#include "Logger.h" #include "Logger.h"
@ -13,7 +13,7 @@
// The only thing not auto-handled is instance activities force joining the team on the server. // The only thing not auto-handled is instance activities force joining the team on the server.
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) { void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receivingPlayer); bitStream.Write(receivingPlayer);
//portion that will get routed: //portion that will get routed:

View File

@ -14,7 +14,6 @@
#include "eObjectBits.h" #include "eObjectBits.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eChatMessageType.h" #include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eClientMessageType.h" #include "eClientMessageType.h"
#include "eGameMessageType.h" #include "eGameMessageType.h"
#include "StringifiedEnum.h" #include "StringifiedEnum.h"
@ -60,7 +59,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Now, we need to send the friendlist to the server they came from: //Now, we need to send the friendlist to the server they came from:
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(playerID); bitStream.Write(playerID);
//portion that will get routed: //portion that will get routed:
@ -454,7 +453,7 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) { void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(routeTo.playerID); bitStream.Write(routeTo.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
@ -696,7 +695,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) { void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -711,7 +710,7 @@ void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerD
void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) { void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -738,7 +737,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool b
void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) { void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -763,7 +762,7 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) { void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -780,7 +779,7 @@ void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i
void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) { void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -809,7 +808,7 @@ void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFr
void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) { void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -835,7 +834,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bD
void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) { void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -869,7 +868,7 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
[bool] - is FTP*/ [bool] - is FTP*/
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(friendData.playerID); bitStream.Write(friendData.playerID);
//portion that will get routed: //portion that will get routed:
@ -906,7 +905,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
} }
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
@ -920,7 +919,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) { void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
// Portion that will get routed: // Portion that will get routed:
@ -943,7 +942,7 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) { void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::WORLD_ROUTE_PACKET);
bitStream.Write(receiver.playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:

View File

@ -17,7 +17,6 @@
#include "PlayerContainer.h" #include "PlayerContainer.h"
#include "ChatPacketHandler.h" #include "ChatPacketHandler.h"
#include "eChatMessageType.h" #include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h" #include "eWorldMessageType.h"
#include "ChatIgnoreList.h" #include "ChatIgnoreList.h"
#include "StringifiedEnum.h" #include "StringifiedEnum.h"
@ -182,47 +181,29 @@ int main(int argc, char** argv) {
void HandlePacket(Packet* packet) { void HandlePacket(Packet* packet) {
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) { if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
LOG("A server has disconnected, erasing their connected players from the list."); LOG("A server has disconnected, erasing their connected players from the list.");
} } else if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
if (packet->data[0] == ID_NEW_INCOMING_CONNECTION) {
LOG("A server is connecting, awaiting user list."); LOG("A server is connecting, awaiting user list.");
} } else if (packet->length < 4 || packet->data[0] != ID_USER_PACKET_ENUM) return; // Nothing left to process or not the right packet type
if (packet->length < 4) return; // Nothing left to process. Need 4 bytes to continue. CINSTREAM;
inStream.SetReadOffset(BYTES_TO_BITS(1));
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) { eConnectionType connection;
switch (static_cast<eChatInternalMessageType>(packet->data[3])) { eChatMessageType chatMessageID;
case eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION:
Game::playerContainer.InsertPlayer(packet);
break;
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION: inStream.Read(connection);
Game::playerContainer.RemovePlayer(packet); if (connection != eConnectionType::CHAT) return;
break; inStream.Read(chatMessageID);
case eChatInternalMessageType::MUTE_UPDATE: switch (chatMessageID) {
case eChatMessageType::GM_MUTE:
Game::playerContainer.MuteUpdate(packet); Game::playerContainer.MuteUpdate(packet);
break; break;
case eChatInternalMessageType::CREATE_TEAM: case eChatMessageType::CREATE_TEAM:
Game::playerContainer.CreateTeamServer(packet); Game::playerContainer.CreateTeamServer(packet);
break; break;
case eChatInternalMessageType::ANNOUNCEMENT: {
//we just forward this packet to every connected server
CINSTREAM;
Game::server->Send(inStream, packet->systemAddress, true); //send to everyone except origin
break;
}
default:
LOG("Unknown CHAT_INTERNAL id: %i", int(packet->data[3]));
}
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
eChatMessageType chat_message_type = static_cast<eChatMessageType>(packet->data[3]);
switch (chat_message_type) {
case eChatMessageType::GET_FRIENDS_LIST: case eChatMessageType::GET_FRIENDS_LIST:
ChatPacketHandler::HandleFriendlistRequest(packet); ChatPacketHandler::HandleFriendlistRequest(packet);
break; break;
@ -296,6 +277,19 @@ void HandlePacket(Packet* packet) {
ChatPacketHandler::HandleGMLevelUpdate(packet); ChatPacketHandler::HandleGMLevelUpdate(packet);
break; break;
case eChatMessageType::LOGIN_SESSION_NOTIFY: case eChatMessageType::LOGIN_SESSION_NOTIFY:
Game::playerContainer.InsertPlayer(packet);
break;
case eChatMessageType::GM_ANNOUNCE:{
// we just forward this packet to every connected server
inStream.ResetReadPointer();
Game::server->Send(inStream, packet->systemAddress, true); // send to everyone except origin
}
break;
case eChatMessageType::UNEXPECTED_DISCONNECT:
Game::playerContainer.RemovePlayer(packet);
break;
case eChatMessageType::WHO:
case eChatMessageType::SHOW_ALL:
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE: case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
case eChatMessageType::WORLD_DISCONNECT_REQUEST: case eChatMessageType::WORLD_DISCONNECT_REQUEST:
case eChatMessageType::WORLD_PROXIMITY_RESPONSE: case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
@ -308,7 +302,6 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::GUILD_KICK: case eChatMessageType::GUILD_KICK:
case eChatMessageType::GUILD_GET_STATUS: case eChatMessageType::GUILD_GET_STATUS:
case eChatMessageType::GUILD_GET_ALL: case eChatMessageType::GUILD_GET_ALL:
case eChatMessageType::SHOW_ALL:
case eChatMessageType::BLUEPRINT_MODERATED: case eChatMessageType::BLUEPRINT_MODERATED:
case eChatMessageType::BLUEPRINT_MODEL_READY: case eChatMessageType::BLUEPRINT_MODEL_READY:
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL: case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
@ -323,7 +316,6 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::CSR_REQUEST: case eChatMessageType::CSR_REQUEST:
case eChatMessageType::CSR_REPLY: case eChatMessageType::CSR_REPLY:
case eChatMessageType::GM_KICK: case eChatMessageType::GM_KICK:
case eChatMessageType::GM_ANNOUNCE:
case eChatMessageType::WORLD_ROUTE_PACKET: case eChatMessageType::WORLD_ROUTE_PACKET:
case eChatMessageType::GET_ZONE_POPULATIONS: case eChatMessageType::GET_ZONE_POPULATIONS:
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE: case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
@ -332,33 +324,18 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE: case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT: case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
case eChatMessageType::UGCC_REQUEST: case eChatMessageType::UGCC_REQUEST:
case eChatMessageType::WHO:
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE: case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
case eChatMessageType::ACHIEVEMENT_NOTIFY: case eChatMessageType::ACHIEVEMENT_NOTIFY:
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW: case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
case eChatMessageType::UNEXPECTED_DISCONNECT:
case eChatMessageType::PLAYER_READY: case eChatMessageType::PLAYER_READY:
case eChatMessageType::GET_DONATION_TOTAL: case eChatMessageType::GET_DONATION_TOTAL:
case eChatMessageType::UPDATE_DONATION: case eChatMessageType::UPDATE_DONATION:
case eChatMessageType::PRG_CSR_COMMAND: case eChatMessageType::PRG_CSR_COMMAND:
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD: case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS: case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chat_message_type).data(), chat_message_type); LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chatMessageID).data(), chatMessageID);
break; break;
default: default:
LOG("Unknown CHAT Message id: %i", chat_message_type); LOG("Unknown CHAT Message id: %i", chatMessageID);
}
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::WORLD) {
switch (static_cast<eWorldMessageType>(packet->data[3])) {
case eWorldMessageType::ROUTE_PACKET: {
LOG("Routing packet from world");
break;
}
default:
LOG("Unknown World id: %i", int(packet->data[3]));
}
} }
} }

View File

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

View File

@ -166,7 +166,7 @@ namespace GeneralUtils {
return isParsed ? static_cast<T>(result) : std::optional<T>{}; return isParsed ? static_cast<T>(result) : std::optional<T>{};
} }
#ifdef DARKFLAME_PLATFORM_MACOS #if !(__GNUC__ >= 11 || _MSC_VER >= 1924)
// MacOS floating-point parse helper function specializations // MacOS floating-point parse helper function specializations
namespace details { namespace details {

View File

@ -1,31 +0,0 @@
#ifndef __ECHATINTERNALMESSAGETYPE__H__
#define __ECHATINTERNALMESSAGETYPE__H__
#include <cstdint>
enum eChatInternalMessageType : uint32_t {
PLAYER_ADDED_NOTIFICATION = 0,
PLAYER_REMOVED_NOTIFICATION,
ADD_FRIEND,
ADD_BEST_FRIEND,
ADD_TO_TEAM,
ADD_BLOCK,
REMOVE_FRIEND,
REMOVE_BLOCK,
REMOVE_FROM_TEAM,
DELETE_TEAM,
REPORT,
PRIVATE_CHAT,
PRIVATE_CHAT_RESPONSE,
ANNOUNCEMENT,
MAIL_COUNT_UPDATE,
MAIL_SEND_NOTIFY,
REQUEST_USER_LIST,
FRIEND_LIST,
ROUTE_TO_PLAYER,
TEAM_UPDATE,
MUTE_UPDATE,
CREATE_TEAM,
};
#endif //!__ECHATINTERNALMESSAGETYPE__H__

View File

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

View File

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

View File

@ -731,15 +731,21 @@ void Entity::Initialize() {
// if we have a moving platform path, then we need a moving platform component // if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) { if (path->pathType == PathType::MovingPlatform) {
AddComponent<MovingPlatformComponent>(pathName); AddComponent<MovingPlatformComponent>(pathName);
// else if we are a movement path } else if (path->pathType == PathType::Movement) {
} /*else if (path->pathType == PathType::Movement) { auto movementAIcomponent = GetComponent<MovementAIComponent>();
auto movementAIcomp = GetComponent<MovementAIComponent>(); if (movementAIcomponent && combatAiId == 0) {
if (movementAIcomp){ movementAIcomponent->SetPath(pathName);
// TODO: set path in existing movementAIComp
} else { } else {
// TODO: create movementAIcomp and set path MovementAIInfo moveInfo = MovementAIInfo();
moveInfo.movementType = "";
moveInfo.wanderChance = 0;
moveInfo.wanderRadius = 16;
moveInfo.wanderSpeed = 2.5f;
moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2;
AddComponent<MovementAIComponent>(moveInfo);
} }
}*/ }
} else { } else {
// else we still need to setup moving platform if it has a moving platform comp but no path // else we still need to setup moving platform if it has a moving platform comp but no path
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1); int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);

View File

@ -26,7 +26,7 @@
#include "eCharacterCreationResponse.h" #include "eCharacterCreationResponse.h"
#include "eRenameResponse.h" #include "eRenameResponse.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eChatInternalMessageType.h" #include "eChatMessageType.h"
#include "BitStreamUtils.h" #include "BitStreamUtils.h"
#include "CheatDetection.h" #include "CheatDetection.h"
@ -422,7 +422,7 @@ void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet)
Database::Get()->DeleteCharacter(charID); Database::Get()->DeleteCharacter(charID);
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
bitStream.Write(objectID); bitStream.Write(objectID);
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);

View File

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

View File

@ -5,7 +5,7 @@
#include "CDActivitiesTable.h" #include "CDActivitiesTable.h"
#include "Game.h" #include "Game.h"
#include "Logger.h" #include "Logger.h"
#include "BehaviorTemplates.h" #include "BehaviorTemplate.h"
#include "BehaviorBranchContext.h" #include "BehaviorBranchContext.h"
#include <unordered_map> #include <unordered_map>
@ -110,176 +110,176 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
Behavior* behavior = nullptr; Behavior* behavior = nullptr;
switch (templateId) { switch (templateId) {
case BehaviorTemplates::BEHAVIOR_EMPTY: break; case BehaviorTemplate::EMPTY: break;
case BehaviorTemplates::BEHAVIOR_BASIC_ATTACK: case BehaviorTemplate::BASIC_ATTACK:
behavior = new BasicAttackBehavior(behaviorId); behavior = new BasicAttackBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_TAC_ARC: case BehaviorTemplate::TAC_ARC:
behavior = new TacArcBehavior(behaviorId); behavior = new TacArcBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_AND: case BehaviorTemplate::AND:
behavior = new AndBehavior(behaviorId); behavior = new AndBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_PROJECTILE_ATTACK: case BehaviorTemplate::PROJECTILE_ATTACK:
behavior = new ProjectileAttackBehavior(behaviorId); behavior = new ProjectileAttackBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_HEAL: case BehaviorTemplate::HEAL:
behavior = new HealBehavior(behaviorId); behavior = new HealBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_MOVEMENT_SWITCH: case BehaviorTemplate::MOVEMENT_SWITCH:
behavior = new MovementSwitchBehavior(behaviorId); behavior = new MovementSwitchBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_AREA_OF_EFFECT: case BehaviorTemplate::AREA_OF_EFFECT:
behavior = new AreaOfEffectBehavior(behaviorId); behavior = new AreaOfEffectBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_PLAY_EFFECT: case BehaviorTemplate::PLAY_EFFECT:
behavior = new PlayEffectBehavior(behaviorId); behavior = new PlayEffectBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_IMMUNITY: case BehaviorTemplate::IMMUNITY:
behavior = new ImmunityBehavior(behaviorId); behavior = new ImmunityBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_BUFF: break; case BehaviorTemplate::DAMAGE_BUFF: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_ABSORBTION: case BehaviorTemplate::DAMAGE_ABSORBTION:
behavior = new DamageAbsorptionBehavior(behaviorId); behavior = new DamageAbsorptionBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_OVER_TIME: case BehaviorTemplate::OVER_TIME:
behavior = new OverTimeBehavior(behaviorId); behavior = new OverTimeBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_IMAGINATION: case BehaviorTemplate::IMAGINATION:
behavior = new ImaginationBehavior(behaviorId); behavior = new ImaginationBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_TARGET_CASTER: case BehaviorTemplate::TARGET_CASTER:
behavior = new TargetCasterBehavior(behaviorId); behavior = new TargetCasterBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_STUN: case BehaviorTemplate::STUN:
behavior = new StunBehavior(behaviorId); behavior = new StunBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_DURATION: case BehaviorTemplate::DURATION:
behavior = new DurationBehavior(behaviorId); behavior = new DurationBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_KNOCKBACK: case BehaviorTemplate::KNOCKBACK:
behavior = new KnockbackBehavior(behaviorId); behavior = new KnockbackBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_ATTACK_DELAY: case BehaviorTemplate::ATTACK_DELAY:
behavior = new AttackDelayBehavior(behaviorId); behavior = new AttackDelayBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_CAR_BOOST: case BehaviorTemplate::CAR_BOOST:
behavior = new CarBoostBehavior(behaviorId); behavior = new CarBoostBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_FALL_SPEED: case BehaviorTemplate::FALL_SPEED:
behavior = new FallSpeedBehavior(behaviorId); behavior = new FallSpeedBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SHIELD: break; case BehaviorTemplate::SHIELD: break;
case BehaviorTemplates::BEHAVIOR_REPAIR_ARMOR: case BehaviorTemplate::REPAIR_ARMOR:
behavior = new RepairBehavior(behaviorId); behavior = new RepairBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SPEED: case BehaviorTemplate::SPEED:
behavior = new SpeedBehavior(behaviorId); behavior = new SpeedBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_DARK_INSPIRATION: case BehaviorTemplate::DARK_INSPIRATION:
behavior = new DarkInspirationBehavior(behaviorId); behavior = new DarkInspirationBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_LOOT_BUFF: case BehaviorTemplate::LOOT_BUFF:
behavior = new LootBuffBehavior(behaviorId); behavior = new LootBuffBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_VENTURE_VISION: case BehaviorTemplate::VENTURE_VISION:
behavior = new VentureVisionBehavior(behaviorId); behavior = new VentureVisionBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SPAWN_OBJECT: case BehaviorTemplate::SPAWN_OBJECT:
behavior = new SpawnBehavior(behaviorId); behavior = new SpawnBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_LAY_BRICK: break; case BehaviorTemplate::LAY_BRICK: break;
case BehaviorTemplates::BEHAVIOR_SWITCH: case BehaviorTemplate::SWITCH:
behavior = new SwitchBehavior(behaviorId); behavior = new SwitchBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_BUFF: case BehaviorTemplate::BUFF:
behavior = new BuffBehavior(behaviorId); behavior = new BuffBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_JETPACK: case BehaviorTemplate::JETPACK:
behavior = new JetPackBehavior(behaviorId); behavior = new JetPackBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SKILL_EVENT: case BehaviorTemplate::SKILL_EVENT:
behavior = new SkillEventBehavior(behaviorId); behavior = new SkillEventBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_CONSUME_ITEM: case BehaviorTemplate::CONSUME_ITEM:
behavior = new ConsumeItemBehavior(behaviorId); behavior = new ConsumeItemBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SKILL_CAST_FAILED: case BehaviorTemplate::SKILL_CAST_FAILED:
behavior = new SkillCastFailedBehavior(behaviorId); behavior = new SkillCastFailedBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_IMITATION_SKUNK_STINK: break; case BehaviorTemplate::IMITATION_SKUNK_STINK: break;
case BehaviorTemplates::BEHAVIOR_CHANGE_IDLE_FLAGS: case BehaviorTemplate::CHANGE_IDLE_FLAGS:
behavior = new ChangeIdleFlagsBehavior(behaviorId); behavior = new ChangeIdleFlagsBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_APPLY_BUFF: case BehaviorTemplate::APPLY_BUFF:
behavior = new ApplyBuffBehavior(behaviorId); behavior = new ApplyBuffBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_CHAIN: case BehaviorTemplate::CHAIN:
behavior = new ChainBehavior(behaviorId); behavior = new ChainBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_CHANGE_ORIENTATION: case BehaviorTemplate::CHANGE_ORIENTATION:
behavior = new ChangeOrientationBehavior(behaviorId); behavior = new ChangeOrientationBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_FORCE_MOVEMENT: case BehaviorTemplate::FORCE_MOVEMENT:
behavior = new ForceMovementBehavior(behaviorId); behavior = new ForceMovementBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_INTERRUPT: case BehaviorTemplate::INTERRUPT:
behavior = new InterruptBehavior(behaviorId); behavior = new InterruptBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_ALTER_COOLDOWN: break; case BehaviorTemplate::ALTER_COOLDOWN: break;
case BehaviorTemplates::BEHAVIOR_CHARGE_UP: case BehaviorTemplate::CHARGE_UP:
behavior = new ChargeUpBehavior(behaviorId); behavior = new ChargeUpBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SWITCH_MULTIPLE: case BehaviorTemplate::SWITCH_MULTIPLE:
behavior = new SwitchMultipleBehavior(behaviorId); behavior = new SwitchMultipleBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_START: case BehaviorTemplate::START:
behavior = new StartBehavior(behaviorId); behavior = new StartBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_END: case BehaviorTemplate::END:
behavior = new EndBehavior(behaviorId); behavior = new EndBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_ALTER_CHAIN_DELAY: break; case BehaviorTemplate::ALTER_CHAIN_DELAY: break;
case BehaviorTemplates::BEHAVIOR_CAMERA: break; case BehaviorTemplate::CAMERA: break;
case BehaviorTemplates::BEHAVIOR_REMOVE_BUFF: case BehaviorTemplate::REMOVE_BUFF:
behavior = new RemoveBuffBehavior(behaviorId); behavior = new RemoveBuffBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_GRAB: break; case BehaviorTemplate::GRAB: break;
case BehaviorTemplates::BEHAVIOR_MODULAR_BUILD: break; case BehaviorTemplate::MODULAR_BUILD: break;
case BehaviorTemplates::BEHAVIOR_NPC_COMBAT_SKILL: case BehaviorTemplate::NPC_COMBAT_SKILL:
behavior = new NpcCombatSkillBehavior(behaviorId); behavior = new NpcCombatSkillBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_BLOCK: case BehaviorTemplate::BLOCK:
behavior = new BlockBehavior(behaviorId); behavior = new BlockBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_VERIFY: case BehaviorTemplate::VERIFY:
behavior = new VerifyBehavior(behaviorId); behavior = new VerifyBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_TAUNT: case BehaviorTemplate::TAUNT:
behavior = new TauntBehavior(behaviorId); behavior = new TauntBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_AIR_MOVEMENT: case BehaviorTemplate::AIR_MOVEMENT:
behavior = new AirMovementBehavior(behaviorId); behavior = new AirMovementBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_SPAWN_QUICKBUILD: case BehaviorTemplate::SPAWN_QUICKBUILD:
behavior = new SpawnBehavior(behaviorId); behavior = new SpawnBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_PULL_TO_POINT: case BehaviorTemplate::PULL_TO_POINT:
behavior = new PullToPointBehavior(behaviorId); behavior = new PullToPointBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_ROTATE: break; case BehaviorTemplate::PROPERTY_ROTATE: break;
case BehaviorTemplates::BEHAVIOR_DAMAGE_REDUCTION: case BehaviorTemplate::DAMAGE_REDUCTION:
behavior = new DamageReductionBehavior(behaviorId); behavior = new DamageReductionBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_TELEPORT: case BehaviorTemplate::PROPERTY_TELEPORT:
behavior = new PropertyTeleportBehavior(behaviorId); behavior = new PropertyTeleportBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_PROPERTY_CLEAR_TARGET: case BehaviorTemplate::PROPERTY_CLEAR_TARGET:
behavior = new ClearTargetBehavior(behaviorId); behavior = new ClearTargetBehavior(behaviorId);
break; break;
case BehaviorTemplates::BEHAVIOR_TAKE_PICTURE: break; case BehaviorTemplate::TAKE_PICTURE: break;
case BehaviorTemplates::BEHAVIOR_MOUNT: break; case BehaviorTemplate::MOUNT: break;
case BehaviorTemplates::BEHAVIOR_SKILL_SET: break; case BehaviorTemplate::SKILL_SET: break;
default: default:
//LOG("Failed to load behavior with invalid template id (%i)!", templateId); //LOG("Failed to load behavior with invalid template id (%i)!", templateId);
break; break;
@ -296,19 +296,19 @@ Behavior* Behavior::CreateBehavior(const uint32_t behaviorId) {
return behavior; return behavior;
} }
BehaviorTemplates Behavior::GetBehaviorTemplate(const uint32_t behaviorId) { BehaviorTemplate Behavior::GetBehaviorTemplate(const uint32_t behaviorId) {
auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>(); auto behaviorTemplateTable = CDClientManager::GetTable<CDBehaviorTemplateTable>();
BehaviorTemplates templateID = BehaviorTemplates::BEHAVIOR_EMPTY; BehaviorTemplate templateID = BehaviorTemplate::EMPTY;
// Find behavior template by its behavior id. Default to 0. // Find behavior template by its behavior id. Default to 0.
if (behaviorTemplateTable) { if (behaviorTemplateTable) {
auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId); auto templateEntry = behaviorTemplateTable->GetByBehaviorID(behaviorId);
if (templateEntry.behaviorID == behaviorId) { if (templateEntry.behaviorID == behaviorId) {
templateID = static_cast<BehaviorTemplates>(templateEntry.templateID); templateID = static_cast<BehaviorTemplate>(templateEntry.templateID);
} }
} }
if (templateID == BehaviorTemplates::BEHAVIOR_EMPTY && behaviorId != 0) { if (templateID == BehaviorTemplate::EMPTY && behaviorId != 0) {
LOG("Failed to load behavior template with id (%i)!", behaviorId); LOG("Failed to load behavior template with id (%i)!", behaviorId);
} }
@ -419,7 +419,7 @@ Behavior::Behavior(const uint32_t behaviorId) {
if (behaviorId == 0) { if (behaviorId == 0) {
this->m_effectId = 0; this->m_effectId = 0;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; this->m_templateId = BehaviorTemplate::EMPTY;
} }
// Make sure we do not proceed if we are trying to load an invalid behavior // Make sure we do not proceed if we are trying to load an invalid behavior
@ -427,12 +427,12 @@ Behavior::Behavior(const uint32_t behaviorId) {
LOG("Failed to load behavior with id (%i)!", behaviorId); LOG("Failed to load behavior with id (%i)!", behaviorId);
this->m_effectId = 0; this->m_effectId = 0;
this->m_templateId = BehaviorTemplates::BEHAVIOR_EMPTY; this->m_templateId = BehaviorTemplate::EMPTY;
return; return;
} }
this->m_templateId = static_cast<BehaviorTemplates>(templateInDatabase.templateID); this->m_templateId = static_cast<BehaviorTemplate>(templateInDatabase.templateID);
this->m_effectId = templateInDatabase.effectID; this->m_effectId = templateInDatabase.effectID;

View File

@ -6,7 +6,7 @@
#include <unordered_map> #include <unordered_map>
#include "BitStream.h" #include "BitStream.h"
#include "BehaviorTemplates.h" #include "BehaviorTemplate.h"
#include "dCommonVars.h" #include "dCommonVars.h"
struct BehaviorContext; struct BehaviorContext;
@ -26,7 +26,7 @@ public:
static Behavior* CreateBehavior(uint32_t behaviorId); static Behavior* CreateBehavior(uint32_t behaviorId);
static BehaviorTemplates GetBehaviorTemplate(uint32_t behaviorId); static BehaviorTemplate GetBehaviorTemplate(uint32_t behaviorId);
/* /*
* Utilities * Utilities
@ -39,7 +39,7 @@ public:
*/ */
uint32_t m_behaviorId; uint32_t m_behaviorId;
BehaviorTemplates m_templateId; BehaviorTemplate m_templateId;
uint32_t m_effectId; uint32_t m_effectId;
std::string m_effectHandle; std::string m_effectHandle;
std::unordered_map<std::string, std::string> m_effectNames; std::unordered_map<std::string, std::string> m_effectNames;

View File

@ -0,0 +1,70 @@
#pragma once
enum class BehaviorTemplate : unsigned int {
EMPTY, // Not a real behavior, indicates invalid behaviors
BASIC_ATTACK,
TAC_ARC,
AND,
PROJECTILE_ATTACK,
HEAL,
MOVEMENT_SWITCH,
AREA_OF_EFFECT,
PLAY_EFFECT,
IMMUNITY,
DAMAGE_BUFF,
DAMAGE_ABSORBTION,
OVER_TIME,
IMAGINATION,
TARGET_CASTER,
STUN,
DURATION,
KNOCKBACK,
ATTACK_DELAY,
CAR_BOOST,
FALL_SPEED,
SHIELD,
REPAIR_ARMOR,
SPEED,
DARK_INSPIRATION,
LOOT_BUFF,
VENTURE_VISION,
SPAWN_OBJECT,
LAY_BRICK,
SWITCH,
BUFF,
JETPACK,
SKILL_EVENT,
CONSUME_ITEM,
SKILL_CAST_FAILED,
IMITATION_SKUNK_STINK,
CHANGE_IDLE_FLAGS,
APPLY_BUFF,
CHAIN,
CHANGE_ORIENTATION,
FORCE_MOVEMENT,
INTERRUPT,
ALTER_COOLDOWN,
CHARGE_UP,
SWITCH_MULTIPLE,
START,
END,
ALTER_CHAIN_DELAY,
CAMERA,
REMOVE_BUFF,
GRAB,
MODULAR_BUILD,
NPC_COMBAT_SKILL,
BLOCK,
VERIFY,
TAUNT,
AIR_MOVEMENT,
SPAWN_QUICKBUILD,
PULL_TO_POINT,
PROPERTY_ROTATE,
DAMAGE_REDUCTION,
PROPERTY_TELEPORT,
PROPERTY_CLEAR_TARGET,
TAKE_PICTURE,
MOUNT,
SKILL_SET
};

View File

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

View File

@ -1,70 +0,0 @@
#pragma once
enum class BehaviorTemplates : unsigned int {
BEHAVIOR_EMPTY, // Not a real behavior, indicates invalid behaviors
BEHAVIOR_BASIC_ATTACK,
BEHAVIOR_TAC_ARC,
BEHAVIOR_AND,
BEHAVIOR_PROJECTILE_ATTACK,
BEHAVIOR_HEAL,
BEHAVIOR_MOVEMENT_SWITCH,
BEHAVIOR_AREA_OF_EFFECT,
BEHAVIOR_PLAY_EFFECT,
BEHAVIOR_IMMUNITY,
BEHAVIOR_DAMAGE_BUFF,
BEHAVIOR_DAMAGE_ABSORBTION,
BEHAVIOR_OVER_TIME,
BEHAVIOR_IMAGINATION,
BEHAVIOR_TARGET_CASTER,
BEHAVIOR_STUN,
BEHAVIOR_DURATION,
BEHAVIOR_KNOCKBACK,
BEHAVIOR_ATTACK_DELAY,
BEHAVIOR_CAR_BOOST,
BEHAVIOR_FALL_SPEED,
BEHAVIOR_SHIELD,
BEHAVIOR_REPAIR_ARMOR,
BEHAVIOR_SPEED,
BEHAVIOR_DARK_INSPIRATION,
BEHAVIOR_LOOT_BUFF,
BEHAVIOR_VENTURE_VISION,
BEHAVIOR_SPAWN_OBJECT,
BEHAVIOR_LAY_BRICK,
BEHAVIOR_SWITCH,
BEHAVIOR_BUFF,
BEHAVIOR_JETPACK,
BEHAVIOR_SKILL_EVENT,
BEHAVIOR_CONSUME_ITEM,
BEHAVIOR_SKILL_CAST_FAILED,
BEHAVIOR_IMITATION_SKUNK_STINK,
BEHAVIOR_CHANGE_IDLE_FLAGS,
BEHAVIOR_APPLY_BUFF,
BEHAVIOR_CHAIN,
BEHAVIOR_CHANGE_ORIENTATION,
BEHAVIOR_FORCE_MOVEMENT,
BEHAVIOR_INTERRUPT,
BEHAVIOR_ALTER_COOLDOWN,
BEHAVIOR_CHARGE_UP,
BEHAVIOR_SWITCH_MULTIPLE,
BEHAVIOR_START,
BEHAVIOR_END,
BEHAVIOR_ALTER_CHAIN_DELAY,
BEHAVIOR_CAMERA,
BEHAVIOR_REMOVE_BUFF,
BEHAVIOR_GRAB,
BEHAVIOR_MODULAR_BUILD,
BEHAVIOR_NPC_COMBAT_SKILL,
BEHAVIOR_BLOCK,
BEHAVIOR_VERIFY,
BEHAVIOR_TAUNT,
BEHAVIOR_AIR_MOVEMENT,
BEHAVIOR_SPAWN_QUICKBUILD,
BEHAVIOR_PULL_TO_POINT,
BEHAVIOR_PROPERTY_ROTATE,
BEHAVIOR_DAMAGE_REDUCTION,
BEHAVIOR_PROPERTY_TELEPORT,
BEHAVIOR_PROPERTY_CLEAR_TARGET,
BEHAVIOR_TAKE_PICTURE,
BEHAVIOR_MOUNT,
BEHAVIOR_SKILL_SET
};

View File

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

View File

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

View File

@ -8,36 +8,50 @@
void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (branch.target != context->originator) { LWOOBJID usedTarget = m_target ? branch.target : context->originator;
bool unknown = false;
if (!bitStream.Read(unknown)) { if (usedTarget != context->originator) {
LOG("Unable to read unknown1 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); bool isTargetImmuneStuns = false;
if (!bitStream.Read(isTargetImmuneStuns)) {
LOG("Unable to read isTargetImmune from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return; return;
}; };
if (unknown) return; if (isTargetImmuneStuns) return;
} }
if (!this->m_interruptBlock) { if (!this->m_interruptBlock) {
bool unknown = false; bool isBlockingInterrupts = false;
if (!bitStream.Read(isBlockingInterrupts)) {
if (!bitStream.Read(unknown)) { LOG("Unable to read isBlockingInterrupts from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
LOG("Unable to read unknown2 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return; return;
}; };
if (unknown) return; if (isBlockingInterrupts) return;
} }
if (this->m_target) // Guess... bool hasInterruptedStatusEffects = false;
{ if (!bitStream.Read(hasInterruptedStatusEffects)) {
bool unknown = false; LOG("Unable to read hasInterruptedStatusEffects from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
return;
};
if (!bitStream.Read(unknown)) { if (hasInterruptedStatusEffects) {
LOG("Unable to read unknown3 from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); bool hasMoreInterruptedStatusEffects = false;
return; int32_t loopLimit = 0;
}; while (bitStream.Read(hasMoreInterruptedStatusEffects) && hasMoreInterruptedStatusEffects) {
int32_t statusEffectID = 0;
bitStream.Read(statusEffectID);
// nothing happens with this data yes. I have no idea why or what it was used for, but the client literally just reads it and does nothing with it.
// 0x004faca4 for a reference. it also has a hard loop limit of 100 soo,
loopLimit++;
if (loopLimit > 100) {
// if this is hit you have a problem
LOG("Loop limit reached for interrupted status effects, aborting Handle due to bad bitstream! %i", bitStream.GetNumberOfUnreadBits());
break;
}
LOG_DEBUG("Interrupted status effect ID: %i", statusEffectID);
}
} }
if (branch.target == context->originator) return; if (branch.target == context->originator) return;
@ -55,7 +69,8 @@ void InterruptBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitS
void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) { void InterruptBehavior::Calculate(BehaviorContext* context, RakNet::BitStream& bitStream, BehaviorBranchContext branch) {
if (branch.target != context->originator) { LWOOBJID usedTarget = m_target ? branch.target : context->originator;
if (usedTarget != context->originator) {
bitStream.Write(false); bitStream.Write(false);
} }

View File

@ -6,13 +6,13 @@
void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) { void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream& bitStream, const BehaviorBranchContext branch) {
uint32_t movementType{}; uint32_t movementType{};
if (!bitStream.Read(movementType)) { if (!bitStream.Read(movementType)) {
if (this->m_groundAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && if (this->m_groundAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_jumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_fallingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_fallingAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_doubleJumpAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_doubleJumpAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_airAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_airAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_jetpackAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY && this->m_jetpackAction->m_templateId == BehaviorTemplate::EMPTY &&
this->m_movingAction->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) { this->m_movingAction->m_templateId == BehaviorTemplate::EMPTY) {
return; return;
} }
LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits()); LOG("Unable to read movementType from bitStream, aborting Handle! %i", bitStream.GetNumberOfUnreadBits());
@ -47,7 +47,7 @@ void MovementSwitchBehavior::Handle(BehaviorContext* context, RakNet::BitStream&
Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) { Behavior* MovementSwitchBehavior::LoadMovementType(std::string movementType) {
float actionValue = GetFloat(movementType, -1.0f); float actionValue = GetFloat(movementType, -1.0f);
auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f); auto loadedBehavior = GetAction(actionValue != -1.0f ? actionValue : 0.0f);
if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplates::BEHAVIOR_EMPTY) { if (actionValue == -1.0f && loadedBehavior->m_templateId == BehaviorTemplate::EMPTY) {
loadedBehavior = this->m_groundAction; loadedBehavior = this->m_groundAction;
} }
return loadedBehavior; return loadedBehavior;

View File

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

View File

@ -50,9 +50,44 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
m_CurrentSpeed = 0; m_CurrentSpeed = 0;
m_MaxSpeed = 0; m_MaxSpeed = 0;
m_LockRotation = false; m_LockRotation = false;
m_Path = nullptr;
m_SourcePosition = m_Parent->GetPosition();
m_Paused = false;
m_SavedVelocity = NiPoint3Constant::ZERO;
if (!m_Parent->GetComponent<BaseCombatAIComponent>()) SetPath(m_Parent->GetVarAsString(u"attached_path"));
}
void MovementAIComponent::SetPath(const std::string pathName) {
m_Path = Game::zoneManager->GetZone()->GetPath(pathName);
if (!pathName.empty()) LOG("WARNING: %s path %s", m_Path ? "Found" : "Failed to find", pathName.c_str());
if (!m_Path) return;
SetMaxSpeed(1);
SetCurrentSpeed(m_BaseSpeed);
SetPath(m_Path->pathWaypoints);
}
void MovementAIComponent::Pause() {
if (m_Paused) return;
m_Paused = true;
SetPosition(ApproximateLocation());
m_SavedVelocity = GetVelocity();
SetVelocity(NiPoint3Constant::ZERO);
Game::entityManager->SerializeEntity(m_Parent);
}
void MovementAIComponent::Resume() {
if (!m_Paused) return;
m_Paused = false;
SetVelocity(m_SavedVelocity);
m_SavedVelocity = NiPoint3Constant::ZERO;
SetRotation(NiQuaternion::LookAt(m_Parent->GetPosition(), m_NextWaypoint));
Game::entityManager->SerializeEntity(m_Parent);
} }
void MovementAIComponent::Update(const float deltaTime) { void MovementAIComponent::Update(const float deltaTime) {
if (m_Paused) return;
if (m_PullingToPoint) { if (m_PullingToPoint) {
const auto source = GetCurrentWaypoint(); const auto source = GetCurrentWaypoint();
@ -81,27 +116,24 @@ void MovementAIComponent::Update(const float deltaTime) {
} }
m_TimeTravelled += deltaTime; m_TimeTravelled += deltaTime;
SetPosition(ApproximateLocation());
if (m_TimeTravelled < m_TimeToTravel) return; if (m_TimeTravelled < m_TimeToTravel) return;
m_TimeTravelled = 0.0f; m_TimeTravelled = 0.0f;
const auto source = GetCurrentWaypoint(); const auto source = GetCurrentWaypoint();
SetPosition(source); SetPosition(source);
m_SourcePosition = source;
NiPoint3 velocity = NiPoint3Constant::ZERO;
if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek? if (m_Acceleration > 0 && m_BaseSpeed > 0 && AdvanceWaypointIndex()) // Do we have another waypoint to seek?
{ {
m_NextWaypoint = GetCurrentWaypoint(); m_NextWaypoint = GetCurrentWaypoint();
if (m_NextWaypoint == source) { if (m_NextWaypoint == source) {
m_TimeToTravel = 0.0f; m_TimeToTravel = 0.0f;
} else { } else {
if (m_CurrentSpeed < m_MaxSpeed) { m_CurrentSpeed = std::min(m_CurrentSpeed + m_Acceleration, m_MaxSpeed);
m_CurrentSpeed += m_Acceleration;
}
m_CurrentSpeed = std::min(m_CurrentSpeed, m_MaxSpeed);
const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed const auto speed = m_CurrentSpeed * m_BaseSpeed; // scale speed based on base speed
@ -110,7 +142,7 @@ void MovementAIComponent::Update(const float deltaTime) {
// Normalize the vector // Normalize the vector
const auto length = delta.Length(); const auto length = delta.Length();
if (length > 0.0f) { if (length > 0.0f) {
velocity = (delta / length) * speed; SetVelocity((delta / length) * speed);
} }
// Calclute the time it will take to reach the next waypoint with the current speed // Calclute the time it will take to reach the next waypoint with the current speed
@ -122,17 +154,27 @@ void MovementAIComponent::Update(const float deltaTime) {
} else { } else {
// Check if there are more waypoints in the queue, if so set our next destination to the next waypoint // Check if there are more waypoints in the queue, if so set our next destination to the next waypoint
if (m_CurrentPath.empty()) { if (m_CurrentPath.empty()) {
Stop(); if (m_Path) {
if (m_Path->pathBehavior == PathBehavior::Loop) {
return; SetPath(m_Path->pathWaypoints);
} else if (m_Path->pathBehavior == PathBehavior::Bounce) {
std::vector<PathWaypoint> waypoints = m_Path->pathWaypoints;
std::reverse(waypoints.begin(), waypoints.end());
SetPath(waypoints);
} else if (m_Path->pathBehavior == PathBehavior::Once) {
Stop();
return;
}
} else {
Stop();
return;
}
} }
SetDestination(m_CurrentPath.top()); SetDestination(m_CurrentPath.top().position);
m_CurrentPath.pop(); m_CurrentPath.pop();
} }
SetVelocity(velocity);
Game::entityManager->SerializeEntity(m_Parent); Game::entityManager->SerializeEntity(m_Parent);
} }
@ -155,7 +197,7 @@ NiPoint3 MovementAIComponent::GetCurrentWaypoint() const {
} }
NiPoint3 MovementAIComponent::ApproximateLocation() const { NiPoint3 MovementAIComponent::ApproximateLocation() const {
auto source = m_Parent->GetPosition(); auto source = m_SourcePosition;
if (AtFinalWaypoint()) return source; if (AtFinalWaypoint()) return source;
@ -221,13 +263,13 @@ void MovementAIComponent::PullToPoint(const NiPoint3& point) {
m_PullPoint = point; m_PullPoint = point;
} }
void MovementAIComponent::SetPath(std::vector<NiPoint3> path) { void MovementAIComponent::SetPath(std::vector<PathWaypoint> path) {
if (path.empty()) return; if (path.empty()) return;
std::for_each(path.rbegin(), path.rend() - 1, [this](const NiPoint3& point) { std::for_each(path.rbegin(), path.rend() - 1, [this](const PathWaypoint& point) {
this->m_CurrentPath.push(point); this->m_CurrentPath.push(point);
}); });
SetDestination(path.front()); SetDestination(path.front().position);
} }
float MovementAIComponent::GetBaseSpeed(LOT lot) { float MovementAIComponent::GetBaseSpeed(LOT lot) {
@ -272,6 +314,23 @@ void MovementAIComponent::SetRotation(const NiQuaternion& value) {
if (!m_LockRotation) m_Parent->SetRotation(value); if (!m_LockRotation) m_Parent->SetRotation(value);
} }
NiPoint3 MovementAIComponent::GetVelocity() const {
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent != nullptr) {
return controllablePhysicsComponent->GetVelocity();
}
auto* simplePhysicsComponent = m_Parent->GetComponent<SimplePhysicsComponent>();
if (simplePhysicsComponent != nullptr) {
return simplePhysicsComponent->GetVelocity();
}
return NiPoint3Constant::ZERO;
}
void MovementAIComponent::SetVelocity(const NiPoint3& value) { void MovementAIComponent::SetVelocity(const NiPoint3& value) {
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>(); auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
@ -288,7 +347,7 @@ void MovementAIComponent::SetVelocity(const NiPoint3& value) {
} }
} }
void MovementAIComponent::SetDestination(const NiPoint3& destination) { void MovementAIComponent::SetDestination(const NiPoint3 destination) {
if (m_PullingToPoint) return; if (m_PullingToPoint) return;
const auto location = ApproximateLocation(); const auto location = ApproximateLocation();
@ -297,6 +356,8 @@ void MovementAIComponent::SetDestination(const NiPoint3& destination) {
SetPosition(location); SetPosition(location);
} }
m_SourcePosition = location;
std::vector<NiPoint3> computedPath; std::vector<NiPoint3> computedPath;
if (dpWorld::IsLoaded()) { if (dpWorld::IsLoaded()) {
computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed); computedPath = dpWorld::GetNavMesh()->GetPath(m_Parent->GetPosition(), destination, m_Info.wanderSpeed);

View File

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

View File

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

View File

@ -70,7 +70,7 @@
#include "RenderComponent.h" #include "RenderComponent.h"
#include "eControlScheme.h" #include "eControlScheme.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eChatInternalMessageType.h" #include "eChatMessageType.h"
#include "eMasterMessageType.h" #include "eMasterMessageType.h"
#include "PlayerManager.h" #include "PlayerManager.h"
@ -2118,7 +2118,7 @@ namespace GreaterThanZeroCommands {
//Notify chat about it //Notify chat about it
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::MUTE_UPDATE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_MUTE);
bitStream.Write(characterId); bitStream.Write(characterId);
bitStream.Write(expire); bitStream.Write(expire);
@ -2220,7 +2220,7 @@ void SlashCommandHandler::SendAnnouncement(const std::string& title, const std::
//Notify chat about it //Notify chat about it
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ANNOUNCEMENT); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GM_ANNOUNCE);
bitStream.Write<uint32_t>(title.size()); bitStream.Write<uint32_t>(title.size());
for (auto character : title) { for (auto character : title) {

View File

@ -1,11 +1,11 @@
#include "WanderingVendor.h" #include "WanderingVendor.h"
#include "MovementAIComponent.h" #include "MovementAIComponent.h"
#include "ProximityMonitorComponent.h" #include "ProximityMonitorComponent.h"
#include <ranges>
void WanderingVendor::OnStartup(Entity* self) { void WanderingVendor::OnStartup(Entity* self) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>(); auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return; if (!movementAIComponent) return;
// movementAIComponent->Resume();
self->SetProximityRadius(10, "playermonitor"); self->SetProximityRadius(10, "playermonitor");
} }
@ -13,14 +13,23 @@ void WanderingVendor::OnProximityUpdate(Entity* self, Entity* entering, std::str
if (status == "ENTER" && entering->IsPlayer()) { if (status == "ENTER" && entering->IsPlayer()) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>(); auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return; if (!movementAIComponent) return;
// movementAIComponent->Pause(); movementAIComponent->Pause();
self->CancelTimer("startWalking"); self->CancelTimer("startWalking");
} else if (status == "LEAVE") { } else if (status == "LEAVE") {
auto* proximityMonitorComponent = self->GetComponent<ProximityMonitorComponent>(); auto* proximityMonitorComponent = self->GetComponent<ProximityMonitorComponent>();
if (!proximityMonitorComponent) self->AddComponent<ProximityMonitorComponent>(); if (!proximityMonitorComponent) self->AddComponent<ProximityMonitorComponent>();
const auto proxObjs = proximityMonitorComponent->GetProximityObjects("playermonitor"); const auto proxObjs = proximityMonitorComponent->GetProximityObjects("playermonitor");
if (proxObjs.empty()) self->AddTimer("startWalking", 1.5); bool foundPlayer = false;
for (const auto id : proxObjs | std::views::keys) {
auto* entity = Game::entityManager->GetEntity(id);
if (entity && entity->IsPlayer()) {
foundPlayer = true;
break;
}
}
if (!foundPlayer) self->AddTimer("startWalking", 1.5);
} }
} }
@ -28,6 +37,6 @@ void WanderingVendor::OnTimerDone(Entity* self, std::string timerName) {
if (timerName == "startWalking") { if (timerName == "startWalking") {
auto movementAIComponent = self->GetComponent<MovementAIComponent>(); auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return; if (!movementAIComponent) return;
// movementAIComponent->Resume(); movementAIComponent->Resume();
} }
} }

View File

@ -307,11 +307,7 @@ void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) {
movementAI->SetCurrentSpeed(toSpawn.initialSpeed); movementAI->SetCurrentSpeed(toSpawn.initialSpeed);
movementAI->SetHaltDistance(0.0f); movementAI->SetHaltDistance(0.0f);
std::vector<NiPoint3> pathWaypoints; std::vector<PathWaypoint> pathWaypoints = path->pathWaypoints;
for (const auto& waypoint : path->pathWaypoints) {
pathWaypoints.push_back(waypoint.position);
}
if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) { if (GeneralUtils::GenerateRandomNumber<float_t>(0, 1) < 0.5f) {
std::reverse(pathWaypoints.begin(), pathWaypoints.end()); std::reverse(pathWaypoints.begin(), pathWaypoints.end());

View File

@ -5,20 +5,19 @@
void WblRobotCitizen::OnStartup(Entity* self) { void WblRobotCitizen::OnStartup(Entity* self) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>(); auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return; if (!movementAIComponent) return;
// movementAIComponent->Resume();
} }
void WblRobotCitizen::OnUse(Entity* self, Entity* user) { void WblRobotCitizen::OnUse(Entity* self, Entity* user) {
// auto movementAIComponent = self->GetComponent<MovementAIComponent>(); auto movementAIComponent = self->GetComponent<MovementAIComponent>();
// if (!movementAIComponent) movementAIComponent->Pause(); if (movementAIComponent) movementAIComponent->Pause();
auto face = NiQuaternion::LookAt(self->GetPosition(), user->GetPosition()); auto face = NiQuaternion::LookAt(self->GetPosition(), user->GetPosition());
self->SetRotation(face); self->SetRotation(face);
auto timer = RenderComponent::PlayAnimation(self, "wave"); auto timer = RenderComponent::PlayAnimation(self, "wave", 0.4f);
self->AddTimer("animation time", timer); self->AddTimer("animation time", timer);
} }
void WblRobotCitizen::OnTimerDone(Entity* self, std::string timerName) { void WblRobotCitizen::OnTimerDone(Entity* self, std::string timerName) {
auto movementAIComponent = self->GetComponent<MovementAIComponent>(); auto movementAIComponent = self->GetComponent<MovementAIComponent>();
if (!movementAIComponent) return; if (!movementAIComponent) return;
// movementAIComponent->Resume(); movementAIComponent->Resume();
} }

View File

@ -66,7 +66,7 @@
#include "eObjectBits.h" #include "eObjectBits.h"
#include "eConnectionType.h" #include "eConnectionType.h"
#include "eServerMessageType.h" #include "eServerMessageType.h"
#include "eChatInternalMessageType.h" #include "eChatMessageType.h"
#include "eWorldMessageType.h" #include "eWorldMessageType.h"
#include "eMasterMessageType.h" #include "eMasterMessageType.h"
#include "eGameMessageType.h" #include "eGameMessageType.h"
@ -545,118 +545,116 @@ void HandlePacketChat(Packet* packet) {
} }
if (packet->data[0] == ID_USER_PACKET_ENUM) { if (packet->data[0] == ID_USER_PACKET_ENUM) {
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT_INTERNAL) { if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
switch (static_cast<eChatInternalMessageType>(packet->data[3])) { switch (static_cast<eChatMessageType>(packet->data[3])) {
case eChatInternalMessageType::ROUTE_TO_PLAYER: { case eChatMessageType::WORLD_ROUTE_PACKET: {
CINSTREAM_SKIP_HEADER; CINSTREAM_SKIP_HEADER;
LWOOBJID playerID; LWOOBJID playerID;
inStream.Read(playerID); inStream.Read(playerID);
auto player = Game::entityManager->GetEntity(playerID); auto player = Game::entityManager->GetEntity(playerID);
if (!player) return; if (!player) return;
auto sysAddr = player->GetSystemAddress(); auto sysAddr = player->GetSystemAddress();
//Write our stream outwards: //Write our stream outwards:
CBITSTREAM; CBITSTREAM;
for (BitSize_t i = 0; i < inStream.GetNumberOfBytesUsed(); i++) { for (BitSize_t i = 0; i < inStream.GetNumberOfBytesUsed(); i++) {
bitStream.Write(packet->data[i + 16]); //16 bytes == header + playerID to skip bitStream.Write(packet->data[i + 16]); //16 bytes == header + playerID to skip
}
SEND_PACKET; //send routed packet to player
break;
} }
SEND_PACKET; //send routed packet to player case eChatMessageType::GM_ANNOUNCE: {
CINSTREAM_SKIP_HEADER;
break; std::string title;
} std::string msg;
case eChatInternalMessageType::ANNOUNCEMENT: { uint32_t len;
CINSTREAM_SKIP_HEADER; inStream.Read<uint32_t>(len);
for (uint32_t i = 0; len > i; i++) {
char character;
inStream.Read<char>(character);
title += character;
}
std::string title; len = 0;
std::string msg; inStream.Read<uint32_t>(len);
for (uint32_t i = 0; len > i; i++) {
char character;
inStream.Read<char>(character);
msg += character;
}
uint32_t len; //Send to our clients:
inStream.Read<uint32_t>(len); AMFArrayValue args;
for (uint32_t i = 0; len > i; i++) {
char character;
inStream.Read<char>(character);
title += character;
}
len = 0; args.Insert("title", title);
inStream.Read<uint32_t>(len); args.Insert("message", msg);
for (uint32_t i = 0; len > i; i++) {
char character;
inStream.Read<char>(character);
msg += character;
}
//Send to our clients: GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args);
AMFArrayValue args;
args.Insert("title", title);
args.Insert("message", msg);
GameMessages::SendUIMessageServerToAllClients("ToggleAnnounce", args);
break;
}
case eChatInternalMessageType::MUTE_UPDATE: {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerId;
time_t expire = 0;
inStream.Read(playerId);
inStream.Read(expire);
auto* entity = Game::entityManager->GetEntity(playerId);
auto* character = entity != nullptr ? entity->GetCharacter() : nullptr;
auto* user = character != nullptr ? character->GetParentUser() : nullptr;
if (user) {
user->SetMuteExpire(expire);
entity->GetCharacter()->SendMuteNotice();
}
break;
}
case eChatInternalMessageType::TEAM_UPDATE: {
CINSTREAM_SKIP_HEADER;
LWOOBJID teamID = 0;
char lootOption = 0;
char memberCount = 0;
std::vector<LWOOBJID> members;
inStream.Read(teamID);
bool deleteTeam = inStream.ReadBit();
if (deleteTeam) {
TeamManager::Instance()->DeleteTeam(teamID);
LOG("Deleting team (%llu)", teamID);
break; break;
} }
inStream.Read(lootOption); case eChatMessageType::GM_MUTE: {
inStream.Read(memberCount); CINSTREAM_SKIP_HEADER;
LOG("Updating team (%llu), (%i), (%i)", teamID, lootOption, memberCount); LWOOBJID playerId;
for (char i = 0; i < memberCount; i++) { time_t expire = 0;
LWOOBJID member = LWOOBJID_EMPTY; inStream.Read(playerId);
inStream.Read(member); inStream.Read(expire);
members.push_back(member);
LOG("Updating team member (%llu)", member); auto* entity = Game::entityManager->GetEntity(playerId);
auto* character = entity != nullptr ? entity->GetCharacter() : nullptr;
auto* user = character != nullptr ? character->GetParentUser() : nullptr;
if (user) {
user->SetMuteExpire(expire);
entity->GetCharacter()->SendMuteNotice();
}
break;
} }
TeamManager::Instance()->UpdateTeam(teamID, lootOption, members); case eChatMessageType::TEAM_GET_STATUS: {
CINSTREAM_SKIP_HEADER;
break; LWOOBJID teamID = 0;
} char lootOption = 0;
char memberCount = 0;
std::vector<LWOOBJID> members;
default: inStream.Read(teamID);
LOG("Received an unknown chat internal: %i", int(packet->data[3])); bool deleteTeam = inStream.ReadBit();
if (deleteTeam) {
TeamManager::Instance()->DeleteTeam(teamID);
LOG("Deleting team (%llu)", teamID);
break;
}
inStream.Read(lootOption);
inStream.Read(memberCount);
LOG("Updating team (%llu), (%i), (%i)", teamID, lootOption, memberCount);
for (char i = 0; i < memberCount; i++) {
LWOOBJID member = LWOOBJID_EMPTY;
inStream.Read(member);
members.push_back(member);
LOG("Updating team member (%llu)", member);
}
TeamManager::Instance()->UpdateTeam(teamID, lootOption, members);
break;
}
default:
LOG("Received an unknown chat: %i", int(packet->data[3]));
} }
} }
} }
@ -821,7 +819,7 @@ void HandlePacket(Packet* packet) {
{ {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
bitStream.Write(user->GetLoggedInChar()); bitStream.Write(user->GetLoggedInChar());
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
} }
@ -990,7 +988,7 @@ void HandlePacket(Packet* packet) {
// This means we swapped characters and we need to remove the previous player from the container. // This means we swapped characters and we need to remove the previous player from the container.
if (static_cast<uint32_t>(lastCharacter) != playerID) { if (static_cast<uint32_t>(lastCharacter) != playerID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::UNEXPECTED_DISCONNECT);
bitStream.Write(lastCharacter); bitStream.Write(lastCharacter);
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false); Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
} }
@ -1136,7 +1134,7 @@ void HandlePacket(Packet* packet) {
const auto& playerName = character->GetName(); const auto& playerName = character->GetName();
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::PLAYER_ADDED_NOTIFICATION); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::LOGIN_SESSION_NOTIFY);
bitStream.Write(player->GetObjectID()); bitStream.Write(player->GetObjectID());
bitStream.Write<uint32_t>(playerName.size()); bitStream.Write<uint32_t>(playerName.size());
for (size_t i = 0; i < playerName.size(); i++) { for (size_t i = 0; i < playerName.size(); i++) {

View File

@ -16,57 +16,57 @@ class Level;
enum class eWaypointCommandType : uint32_t; enum class eWaypointCommandType : uint32_t;
struct WaypointCommand { struct WaypointCommand {
eWaypointCommandType command; eWaypointCommandType command{};
std::string data; std::string data;
}; };
struct SceneRef { struct SceneRef {
std::string filename; std::string filename;
uint32_t id; uint32_t id{};
uint32_t sceneType; //0 = general, 1 = audio? uint32_t sceneType{}; //0 = general, 1 = audio?
std::string name; std::string name;
NiPoint3 unknown1; NiPoint3 unknown1;
float unknown2; float unknown2{};
uint8_t color_r; uint8_t color_r{};
uint8_t color_g; uint8_t color_g{};
uint8_t color_b; uint8_t color_b{};
Level* level; Level* level;
std::map<uint32_t, LUTriggers::Trigger*> triggers; std::map<uint32_t, LUTriggers::Trigger*> triggers;
}; };
struct SceneTransitionInfo { struct SceneTransitionInfo {
uint64_t sceneID; //id of the scene being transitioned to. uint64_t sceneID{}; //id of the scene being transitioned to.
NiPoint3 position; NiPoint3 position;
}; };
struct SceneTransition { struct SceneTransition {
std::string name; std::string name;
std::vector<SceneTransitionInfo> points; std::vector<SceneTransitionInfo> points;
float width; float width{};
}; };
struct MovingPlatformPathWaypoint { struct MovingPlatformPathWaypoint {
uint8_t lockPlayer; uint8_t lockPlayer{};
float wait; float wait{};
std::string departSound; std::string departSound;
std::string arriveSound; std::string arriveSound;
}; };
struct CameraPathWaypoint { struct CameraPathWaypoint {
float time; float time{};
float fov; float fov{};
float tension; float tension{};
float continuity; float continuity{};
float bias; float bias{};
}; };
struct RacingPathWaypoint { struct RacingPathWaypoint {
uint8_t isResetNode; uint8_t isResetNode{};
uint8_t isNonHorizontalCamera; uint8_t isNonHorizontalCamera{};
float planeWidth; float planeWidth{};
float planeHeight; float planeHeight{};
float shortestDistanceToEnd; float shortestDistanceToEnd{};
}; };
struct PathWaypoint { struct PathWaypoint {
@ -75,7 +75,7 @@ struct PathWaypoint {
MovingPlatformPathWaypoint movingPlatform; MovingPlatformPathWaypoint movingPlatform;
CameraPathWaypoint camera; CameraPathWaypoint camera;
RacingPathWaypoint racing; RacingPathWaypoint racing;
float speed; float speed{};
std::vector<LDFBaseData*> config; std::vector<LDFBaseData*> config;
std::vector<WaypointCommand> commands; std::vector<WaypointCommand> commands;
}; };
@ -137,49 +137,49 @@ enum class PropertyAchievmentRequired : uint32_t {
struct MovingPlatformPath { struct MovingPlatformPath {
std::string platformTravelSound; std::string platformTravelSound;
uint8_t timeBasedMovement; uint8_t timeBasedMovement{};
}; };
struct PropertyPath { struct PropertyPath {
PropertyPathType pathType; PropertyPathType pathType{};
int32_t price; int32_t price{};
uint32_t rentalTime; uint32_t rentalTime{};
uint64_t associatedZone; uint64_t associatedZone{};
std::string displayName; std::string displayName;
std::string displayDesc; std::string displayDesc;
PropertyType type; PropertyType type{};
uint32_t cloneLimit; uint32_t cloneLimit{};
float repMultiplier; float repMultiplier{};
PropertyRentalPeriod rentalPeriod; PropertyRentalPeriod rentalPeriod{};
PropertyAchievmentRequired achievementRequired; PropertyAchievmentRequired achievementRequired{};
// Player respawn coordinates in the main zone (not the property zone) // Player respawn coordinates in the main zone (not the property zone)
NiPoint3 playerZoneCoords; NiPoint3 playerZoneCoords;
float maxBuildHeight; float maxBuildHeight{};
}; };
struct CameraPath { struct CameraPath {
std::string nextPath; std::string nextPath;
uint8_t rotatePlayer; uint8_t rotatePlayer{};
}; };
struct SpawnerPath { struct SpawnerPath {
LOT spawnedLOT; LOT spawnedLOT{};
uint32_t respawnTime; uint32_t respawnTime{};
int32_t maxToSpawn; int32_t maxToSpawn{};
uint32_t amountMaintained; uint32_t amountMaintained{};
LWOOBJID spawnerObjID; LWOOBJID spawnerObjID;
uint8_t spawnerNetActive; uint8_t spawnerNetActive{};
}; };
struct Path { struct Path {
uint32_t pathVersion; uint32_t pathVersion{};
PathType pathType; PathType pathType;
std::string pathName; std::string pathName;
uint32_t flags; uint32_t flags{};
PathBehavior pathBehavior; PathBehavior pathBehavior;
uint32_t waypointCount; uint32_t waypointCount{};
std::vector<PathWaypoint> pathWaypoints; std::vector<PathWaypoint> pathWaypoints;
SpawnerPath spawner; SpawnerPath spawner;
MovingPlatformPath movingPlatform; MovingPlatformPath movingPlatform;

View File

@ -11,7 +11,7 @@ ALTER TABLE leaderboard CHANGE time secondaryScore FLOAT NOT NULL DEFAULT 0 AFTE
/* A bit messy, but better than going through a bunch of code fixes all to be run once. */ /* A bit messy, but better than going through a bunch of code fixes all to be run once. */
UPDATE leaderboard SET UPDATE leaderboard SET
primaryScore = secondaryScore, primaryScore = secondaryScore,
secondaryScore = 0 WHERE game_id IN (1, 44, 46, 47, 48, 49, 53, 103, 104, 108, 1901); secondaryScore = 0 WHERE game_id IN (1, 44, 46, 47, 48, 49, 53, 103, 104, 108, 1901) AND secondaryScore > 0;
/* Do this last so we dont update entry times erroneously */ /* Do this last so we dont update entry times erroneously */
ALTER TABLE leaderboard ALTER TABLE leaderboard