mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-22 05:27:19 +00:00
Merge remote-tracking branch 'upstream/main' into speed
This commit is contained in:
commit
d77657782e
@ -23,6 +23,9 @@ We do not recommend hosting public servers. Darkflame Universe is intended for s
|
|||||||
### Supply of resource files
|
### Supply of resource files
|
||||||
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
Darkflame Universe is a server emulator and does not distribute any LEGO® Universe files. A separate game client is required to setup this server emulator and play the game, which we cannot supply. Users are strongly suggested to refer to the safe checksums listed [here](#verifying-your-client-files) to see if a client will work.
|
||||||
|
|
||||||
|
## Step by step walkthrough for a single-player server
|
||||||
|
If you would like a setup for a single player server only on a Windows machine, use the [Native Windows Setup Guide by HailStorm](https://gist.github.com/HailStorm32/169df65a47a104199b5cc57d10fa57de) and skip this README.
|
||||||
|
|
||||||
## Steps to setup server
|
## Steps to setup server
|
||||||
* [Clone this repository](#clone-the-repository)
|
* [Clone this repository](#clone-the-repository)
|
||||||
* [Install dependencies](#install-dependencies)
|
* [Install dependencies](#install-dependencies)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
set(DCHATSERVER_SOURCES
|
set(DCHATSERVER_SOURCES
|
||||||
|
"ChatIgnoreList.cpp"
|
||||||
"ChatPacketHandler.cpp"
|
"ChatPacketHandler.cpp"
|
||||||
"PlayerContainer.cpp"
|
"PlayerContainer.cpp"
|
||||||
)
|
)
|
||||||
|
173
dChatServer/ChatIgnoreList.cpp
Normal file
173
dChatServer/ChatIgnoreList.cpp
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
#include "ChatIgnoreList.h"
|
||||||
|
#include "PlayerContainer.h"
|
||||||
|
#include "eChatInternalMessageType.h"
|
||||||
|
#include "BitStreamUtils.h"
|
||||||
|
#include "PacketUtils.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "eObjectBits.h"
|
||||||
|
|
||||||
|
#include "Database.h"
|
||||||
|
|
||||||
|
// A note to future readers, The client handles all the actual ignoring logic:
|
||||||
|
// not allowing teams, rejecting DMs, friends requets etc.
|
||||||
|
// The only thing not auto-handled is instance activities force joining the team on the server.
|
||||||
|
|
||||||
|
void WriteOutgoingReplyHeader(RakNet::BitStream& bitStream, const LWOOBJID& receivingPlayer, const ChatIgnoreList::Response type) {
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||||
|
bitStream.Write(receivingPlayer);
|
||||||
|
|
||||||
|
//portion that will get routed:
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatIgnoreList::GetIgnoreList(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
LWOOBJID playerId;
|
||||||
|
inStream.Read(playerId);
|
||||||
|
|
||||||
|
auto* receiver = Game::playerContainer.GetPlayerData(playerId);
|
||||||
|
if (!receiver) {
|
||||||
|
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!receiver->ignoredPlayers.empty()) {
|
||||||
|
LOG_DEBUG("Player %llu already has an ignore list", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
|
||||||
|
if (ignoreList.empty()) {
|
||||||
|
LOG_DEBUG("Player %llu has no ignores", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& ignoredPlayer : ignoreList) {
|
||||||
|
receiver->ignoredPlayers.push_back(IgnoreData{ ignoredPlayer.id, ignoredPlayer.name });
|
||||||
|
GeneralUtils::SetBit(receiver->ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(receiver->ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::GET_IGNORE);
|
||||||
|
|
||||||
|
bitStream.Write<uint8_t>(false); // Probably is Is Free Trial, but we don't care about that
|
||||||
|
bitStream.Write<uint16_t>(0); // literally spacing due to struct alignment
|
||||||
|
|
||||||
|
bitStream.Write<uint16_t>(receiver->ignoredPlayers.size());
|
||||||
|
for (const auto& ignoredPlayer : receiver->ignoredPlayers) {
|
||||||
|
bitStream.Write(ignoredPlayer.playerId);
|
||||||
|
bitStream.Write(LUWString(ignoredPlayer.playerName, 36));
|
||||||
|
}
|
||||||
|
|
||||||
|
Game::server->Send(&bitStream, packet->systemAddress, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatIgnoreList::AddIgnore(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
LWOOBJID playerId;
|
||||||
|
inStream.Read(playerId);
|
||||||
|
|
||||||
|
auto* receiver = Game::playerContainer.GetPlayerData(playerId);
|
||||||
|
if (!receiver) {
|
||||||
|
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int32_t MAX_IGNORES = 32;
|
||||||
|
if (receiver->ignoredPlayers.size() > MAX_IGNORES) {
|
||||||
|
LOG_DEBUG("Player %llu has too many ignores", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream.IgnoreBytes(4); // ignore some garbage zeros idk
|
||||||
|
|
||||||
|
LUWString toIgnoreName(33);
|
||||||
|
inStream.Read(toIgnoreName);
|
||||||
|
std::string toIgnoreStr = toIgnoreName.GetAsString();
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::ADD_IGNORE);
|
||||||
|
|
||||||
|
// Check if the player exists
|
||||||
|
LWOOBJID ignoredPlayerId = LWOOBJID_EMPTY;
|
||||||
|
if (toIgnoreStr == receiver->playerName || toIgnoreStr.find("[GM]") == 0) {
|
||||||
|
LOG_DEBUG("Player %llu tried to ignore themselves", playerId);
|
||||||
|
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::GENERAL_ERROR);
|
||||||
|
} else if (std::count(receiver->ignoredPlayers.begin(), receiver->ignoredPlayers.end(), toIgnoreStr) > 0) {
|
||||||
|
LOG_DEBUG("Player %llu is already ignoring %s", playerId, toIgnoreStr.c_str());
|
||||||
|
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::ALREADY_IGNORED);
|
||||||
|
} else {
|
||||||
|
// Get the playerId falling back to query if not online
|
||||||
|
auto* playerData = Game::playerContainer.GetPlayerData(toIgnoreStr);
|
||||||
|
if (!playerData) {
|
||||||
|
// Fall back to query
|
||||||
|
auto player = Database::Get()->GetCharacterInfo(toIgnoreStr);
|
||||||
|
if (!player || player->name != toIgnoreStr) {
|
||||||
|
LOG_DEBUG("Player %s not found", toIgnoreStr.c_str());
|
||||||
|
} else {
|
||||||
|
ignoredPlayerId = player->id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ignoredPlayerId = playerData->playerID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ignoredPlayerId != LWOOBJID_EMPTY) {
|
||||||
|
Database::Get()->AddIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(ignoredPlayerId));
|
||||||
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
|
||||||
|
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
|
||||||
|
|
||||||
|
receiver->ignoredPlayers.push_back(IgnoreData{ ignoredPlayerId, toIgnoreStr });
|
||||||
|
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
|
||||||
|
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS);
|
||||||
|
} else {
|
||||||
|
bitStream.Write(ChatIgnoreList::AddResponse::PLAYER_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LUWString playerNameSend(toIgnoreStr, 33);
|
||||||
|
bitStream.Write(playerNameSend);
|
||||||
|
bitStream.Write(ignoredPlayerId);
|
||||||
|
|
||||||
|
Game::server->Send(&bitStream, packet->systemAddress, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatIgnoreList::RemoveIgnore(Packet* packet) {
|
||||||
|
CINSTREAM_SKIP_HEADER;
|
||||||
|
LWOOBJID playerId;
|
||||||
|
inStream.Read(playerId);
|
||||||
|
|
||||||
|
auto* receiver = Game::playerContainer.GetPlayerData(playerId);
|
||||||
|
if (!receiver) {
|
||||||
|
LOG("Tried to get ignore list, but player %llu not found in container", playerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inStream.IgnoreBytes(4); // ignore some garbage zeros idk
|
||||||
|
|
||||||
|
LUWString removedIgnoreName(33);
|
||||||
|
inStream.Read(removedIgnoreName);
|
||||||
|
std::string removedIgnoreStr = removedIgnoreName.GetAsString();
|
||||||
|
|
||||||
|
auto toRemove = std::remove(receiver->ignoredPlayers.begin(), receiver->ignoredPlayers.end(), removedIgnoreStr);
|
||||||
|
if (toRemove == receiver->ignoredPlayers.end()) {
|
||||||
|
LOG_DEBUG("Player %llu is not ignoring %s", playerId, removedIgnoreStr.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
|
||||||
|
receiver->ignoredPlayers.erase(toRemove, receiver->ignoredPlayers.end());
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::REMOVE_IGNORE);
|
||||||
|
|
||||||
|
bitStream.Write<int8_t>(0);
|
||||||
|
LUWString playerNameSend(removedIgnoreStr, 33);
|
||||||
|
bitStream.Write(playerNameSend);
|
||||||
|
|
||||||
|
Game::server->Send(&bitStream, packet->systemAddress, false);
|
||||||
|
}
|
27
dChatServer/ChatIgnoreList.h
Normal file
27
dChatServer/ChatIgnoreList.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef __CHATIGNORELIST__H__
|
||||||
|
#define __CHATIGNORELIST__H__
|
||||||
|
|
||||||
|
struct Packet;
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace ChatIgnoreList {
|
||||||
|
void GetIgnoreList(Packet* packet);
|
||||||
|
void AddIgnore(Packet* packet);
|
||||||
|
void RemoveIgnore(Packet* packet);
|
||||||
|
|
||||||
|
enum class Response : uint8_t {
|
||||||
|
ADD_IGNORE = 32,
|
||||||
|
REMOVE_IGNORE = 33,
|
||||||
|
GET_IGNORE = 34,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class AddResponse : uint8_t {
|
||||||
|
SUCCESS,
|
||||||
|
ALREADY_IGNORED,
|
||||||
|
PLAYER_NOT_FOUND,
|
||||||
|
GENERAL_ERROR,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__CHATIGNORELIST__H__
|
@ -19,15 +19,13 @@
|
|||||||
#include "eClientMessageType.h"
|
#include "eClientMessageType.h"
|
||||||
#include "eGameMessageType.h"
|
#include "eGameMessageType.h"
|
||||||
|
|
||||||
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_SKIP_HEADER;
|
CINSTREAM_SKIP_HEADER;
|
||||||
LWOOBJID playerID = 0;
|
LWOOBJID playerID = 0;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
auto player = playerContainer.GetPlayerData(playerID);
|
auto player = Game::playerContainer.GetPlayerData(playerID);
|
||||||
if (!player) return;
|
if (!player) return;
|
||||||
|
|
||||||
auto friendsList = Database::Get()->GetFriendsList(playerID);
|
auto friendsList = Database::Get()->GetFriendsList(playerID);
|
||||||
@ -43,7 +41,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
|||||||
fd.friendName = friendData.friendName;
|
fd.friendName = friendData.friendName;
|
||||||
|
|
||||||
//Now check if they're online:
|
//Now check if they're online:
|
||||||
auto fr = playerContainer.GetPlayerData(fd.friendID);
|
auto fr = Game::playerContainer.GetPlayerData(fd.friendID);
|
||||||
|
|
||||||
if (fr) {
|
if (fr) {
|
||||||
fd.isOnline = true;
|
fd.isOnline = true;
|
||||||
@ -97,7 +95,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
char isBestFriendRequest{};
|
char isBestFriendRequest{};
|
||||||
inStream.Read(isBestFriendRequest);
|
inStream.Read(isBestFriendRequest);
|
||||||
|
|
||||||
auto requestor = playerContainer.GetPlayerData(requestorPlayerID);
|
auto requestor = Game::playerContainer.GetPlayerData(requestorPlayerID);
|
||||||
if (!requestor) {
|
if (!requestor) {
|
||||||
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
|
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
|
||||||
return;
|
return;
|
||||||
@ -107,7 +105,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
|
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
std::unique_ptr<PlayerData> requestee(playerContainer.GetPlayerData(playerName));
|
std::unique_ptr<PlayerData> requestee(Game::playerContainer.GetPlayerData(playerName));
|
||||||
|
|
||||||
// Check if player is online first
|
// Check if player is online first
|
||||||
if (isBestFriendRequest && !requestee) {
|
if (isBestFriendRequest && !requestee) {
|
||||||
@ -175,7 +173,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
|
|
||||||
// Only do updates if there was a change in the bff status.
|
// Only do updates if there was a change in the bff status.
|
||||||
if (oldBestFriendStatus != bestFriendStatus) {
|
if (oldBestFriendStatus != bestFriendStatus) {
|
||||||
auto maxBestFriends = playerContainer.GetMaxNumberOfBestFriends();
|
auto maxBestFriends = Game::playerContainer.GetMaxNumberOfBestFriends();
|
||||||
if (requestee->countOfBestFriends >= maxBestFriends || requestor->countOfBestFriends >= maxBestFriends) {
|
if (requestee->countOfBestFriends >= maxBestFriends || requestor->countOfBestFriends >= maxBestFriends) {
|
||||||
if (requestee->countOfBestFriends >= maxBestFriends) {
|
if (requestee->countOfBestFriends >= maxBestFriends) {
|
||||||
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
||||||
@ -208,7 +206,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
|||||||
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::WAITINGAPPROVAL, true, true);
|
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::WAITINGAPPROVAL, true, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto maxFriends = playerContainer.GetMaxNumberOfFriends();
|
auto maxFriends = Game::playerContainer.GetMaxNumberOfFriends();
|
||||||
if (requestee->friends.size() >= maxFriends) {
|
if (requestee->friends.size() >= maxFriends) {
|
||||||
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
|
||||||
} else if (requestor->friends.size() >= maxFriends) {
|
} else if (requestor->friends.size() >= maxFriends) {
|
||||||
@ -232,8 +230,8 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
|
|||||||
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
|
||||||
|
|
||||||
//Now to try and find both of these:
|
//Now to try and find both of these:
|
||||||
auto requestor = playerContainer.GetPlayerData(playerID);
|
auto requestor = Game::playerContainer.GetPlayerData(playerID);
|
||||||
auto requestee = playerContainer.GetPlayerData(friendName);
|
auto requestee = Game::playerContainer.GetPlayerData(friendName);
|
||||||
if (!requestor || !requestee) return;
|
if (!requestor || !requestee) return;
|
||||||
|
|
||||||
eAddFriendResponseType serverResponseCode{};
|
eAddFriendResponseType serverResponseCode{};
|
||||||
@ -315,7 +313,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
Database::Get()->RemoveFriend(playerID, friendID);
|
Database::Get()->RemoveFriend(playerID, friendID);
|
||||||
|
|
||||||
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
|
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
|
||||||
auto goonA = playerContainer.GetPlayerData(playerID);
|
auto goonA = Game::playerContainer.GetPlayerData(playerID);
|
||||||
if (goonA) {
|
if (goonA) {
|
||||||
// Remove the friend from our list of friends
|
// Remove the friend from our list of friends
|
||||||
for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) {
|
for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) {
|
||||||
@ -328,7 +326,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
SendRemoveFriend(goonA, friendName, true);
|
SendRemoveFriend(goonA, friendName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto goonB = playerContainer.GetPlayerData(friendID);
|
auto goonB = Game::playerContainer.GetPlayerData(friendID);
|
||||||
if (!goonB) return;
|
if (!goonB) return;
|
||||||
// Do it again for other person
|
// Do it again for other person
|
||||||
for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) {
|
for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) {
|
||||||
@ -339,7 +337,7 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string goonAName = GeneralUtils::UTF16ToWTF8(playerContainer.GetName(playerID));
|
std::string goonAName = GeneralUtils::UTF16ToWTF8(Game::playerContainer.GetName(playerID));
|
||||||
SendRemoveFriend(goonB, goonAName, true);
|
SendRemoveFriend(goonB, goonAName, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,11 +346,11 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
auto* sender = playerContainer.GetPlayerData(playerID);
|
auto* sender = Game::playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (sender == nullptr) return;
|
if (sender == nullptr) return;
|
||||||
|
|
||||||
if (playerContainer.GetIsMuted(sender)) return;
|
if (Game::playerContainer.GetIsMuted(sender)) return;
|
||||||
|
|
||||||
const auto senderName = std::string(sender->playerName.c_str());
|
const auto senderName = std::string(sender->playerName.c_str());
|
||||||
|
|
||||||
@ -367,12 +365,12 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
|||||||
|
|
||||||
if (channel != 8) return;
|
if (channel != 8) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team == nullptr) return;
|
if (team == nullptr) return;
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs) {
|
for (const auto memberId : team->memberIDs) {
|
||||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
auto* otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||||
|
|
||||||
if (otherMember == nullptr) return;
|
if (otherMember == nullptr) return;
|
||||||
|
|
||||||
@ -406,11 +404,11 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
|||||||
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
|
||||||
|
|
||||||
//Get the bois:
|
//Get the bois:
|
||||||
auto goonA = playerContainer.GetPlayerData(senderID);
|
auto goonA = Game::playerContainer.GetPlayerData(senderID);
|
||||||
auto goonB = playerContainer.GetPlayerData(receiverName);
|
auto goonB = Game::playerContainer.GetPlayerData(receiverName);
|
||||||
if (!goonA || !goonB) return;
|
if (!goonA || !goonB) return;
|
||||||
|
|
||||||
if (playerContainer.GetIsMuted(goonA)) return;
|
if (Game::playerContainer.GetIsMuted(goonA)) return;
|
||||||
|
|
||||||
std::string goonAName = goonA->playerName.c_str();
|
std::string goonAName = goonA->playerName.c_str();
|
||||||
std::string goonBName = goonB->playerName.c_str();
|
std::string goonBName = goonB->playerName.c_str();
|
||||||
@ -468,25 +466,25 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
|
|||||||
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 = Game::playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (player == nullptr) {
|
if (player == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team == nullptr) {
|
if (team == nullptr) {
|
||||||
team = playerContainer.CreateTeam(playerID);
|
team = Game::playerContainer.CreateTeam(playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* other = playerContainer.GetPlayerData(invitedPlayer);
|
auto* other = Game::playerContainer.GetPlayerData(invitedPlayer);
|
||||||
|
|
||||||
if (other == nullptr) {
|
if (other == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (playerContainer.GetTeam(other->playerID) != nullptr) {
|
if (Game::playerContainer.GetTeam(other->playerID) != nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,12 +517,12 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(leaderID);
|
auto* team = Game::playerContainer.GetTeam(leaderID);
|
||||||
|
|
||||||
if (team == nullptr) {
|
if (team == nullptr) {
|
||||||
LOG("Failed to find team for leader (%llu)", leaderID);
|
LOG("Failed to find team for leader (%llu)", leaderID);
|
||||||
|
|
||||||
team = playerContainer.GetTeam(playerID);
|
team = Game::playerContainer.GetTeam(playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team == nullptr) {
|
if (team == nullptr) {
|
||||||
@ -532,7 +530,7 @@ void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.AddMember(team, playerID);
|
Game::playerContainer.AddMember(team, playerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
||||||
@ -542,12 +540,12 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
|
|||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
inStream.Read(size);
|
inStream.Read(size);
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
LOG("(%llu) leaving team", playerID);
|
LOG("(%llu) leaving team", playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
playerContainer.RemoveMember(team, playerID, false, false, true);
|
Game::playerContainer.RemoveMember(team, playerID, false, false, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,24 +558,24 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
|
|||||||
|
|
||||||
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
|
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
|
||||||
|
|
||||||
auto* kicked = playerContainer.GetPlayerData(kickedPlayer);
|
auto* kicked = Game::playerContainer.GetPlayerData(kickedPlayer);
|
||||||
|
|
||||||
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
LWOOBJID kickedId = LWOOBJID_EMPTY;
|
||||||
|
|
||||||
if (kicked != nullptr) {
|
if (kicked != nullptr) {
|
||||||
kickedId = kicked->playerID;
|
kickedId = kicked->playerID;
|
||||||
} else {
|
} else {
|
||||||
kickedId = playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
|
kickedId = Game::playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kickedId == LWOOBJID_EMPTY) return;
|
if (kickedId == LWOOBJID_EMPTY) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
if (team->leaderID != playerID || team->leaderID == kickedId) return;
|
if (team->leaderID != playerID || team->leaderID == kickedId) return;
|
||||||
|
|
||||||
playerContainer.RemoveMember(team, kickedId, false, true, false);
|
Game::playerContainer.RemoveMember(team, kickedId, false, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,16 +588,16 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
|
|||||||
|
|
||||||
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
|
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
|
||||||
|
|
||||||
auto* promoted = playerContainer.GetPlayerData(promotedPlayer);
|
auto* promoted = Game::playerContainer.GetPlayerData(promotedPlayer);
|
||||||
|
|
||||||
if (promoted == nullptr) return;
|
if (promoted == nullptr) return;
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
if (team->leaderID != playerID) return;
|
if (team->leaderID != playerID) return;
|
||||||
|
|
||||||
playerContainer.PromoteMember(team, promoted->playerID);
|
Game::playerContainer.PromoteMember(team, promoted->playerID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -613,16 +611,16 @@ void ChatPacketHandler::HandleTeamLootOption(Packet* packet) {
|
|||||||
char option;
|
char option;
|
||||||
inStream.Read(option);
|
inStream.Read(option);
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
|
|
||||||
if (team != nullptr) {
|
if (team != nullptr) {
|
||||||
if (team->leaderID != playerID) return;
|
if (team->leaderID != playerID) return;
|
||||||
|
|
||||||
team->lootFlag = option;
|
team->lootFlag = option;
|
||||||
|
|
||||||
playerContainer.TeamStatusUpdate(team);
|
Game::playerContainer.TeamStatusUpdate(team);
|
||||||
|
|
||||||
playerContainer.UpdateTeamsOnWorld(team, false);
|
Game::playerContainer.UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -631,18 +629,18 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||||
inStream.Read(playerID);
|
inStream.Read(playerID);
|
||||||
|
|
||||||
auto* team = playerContainer.GetTeam(playerID);
|
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||||
auto* data = playerContainer.GetPlayerData(playerID);
|
auto* data = Game::playerContainer.GetPlayerData(playerID);
|
||||||
|
|
||||||
if (team != nullptr && data != nullptr) {
|
if (team != nullptr && data != nullptr) {
|
||||||
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
|
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
|
||||||
playerContainer.RemoveMember(team, playerID, false, false, true, true);
|
Game::playerContainer.RemoveMember(team, playerID, false, false, true, true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (team->memberIDs.size() <= 1 && !team->local) {
|
if (team->memberIDs.size() <= 1 && !team->local) {
|
||||||
playerContainer.DisbandTeam(team);
|
Game::playerContainer.DisbandTeam(team);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -653,16 +651,16 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
|
ChatPacketHandler::SendTeamSetLeader(data, LWOOBJID_EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.TeamStatusUpdate(team);
|
Game::playerContainer.TeamStatusUpdate(team);
|
||||||
|
|
||||||
const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName);
|
const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName);
|
||||||
|
|
||||||
for (const auto memberId : team->memberIDs) {
|
for (const auto memberId : team->memberIDs) {
|
||||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
auto* otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||||
|
|
||||||
if (memberId == playerID) continue;
|
if (memberId == playerID) continue;
|
||||||
|
|
||||||
const auto memberName = playerContainer.GetName(memberId);
|
const auto memberName = Game::playerContainer.GetName(memberId);
|
||||||
|
|
||||||
if (otherMember != nullptr) {
|
if (otherMember != nullptr) {
|
||||||
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID);
|
||||||
@ -670,7 +668,7 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
|||||||
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
playerContainer.UpdateTeamsOnWorld(team, false);
|
Game::playerContainer.UpdateTeamsOnWorld(team, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "eChatMessageType.h"
|
#include "eChatMessageType.h"
|
||||||
#include "eChatInternalMessageType.h"
|
#include "eChatInternalMessageType.h"
|
||||||
#include "eWorldMessageType.h"
|
#include "eWorldMessageType.h"
|
||||||
|
#include "ChatIgnoreList.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
|
||||||
@ -34,14 +35,12 @@ namespace Game {
|
|||||||
AssetManager* assetManager = nullptr;
|
AssetManager* assetManager = nullptr;
|
||||||
bool shouldShutdown = false;
|
bool shouldShutdown = false;
|
||||||
std::mt19937 randomEngine;
|
std::mt19937 randomEngine;
|
||||||
|
PlayerContainer playerContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Logger* SetupLogger();
|
Logger* SetupLogger();
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
PlayerContainer playerContainer;
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
constexpr uint32_t chatFramerate = mediumFramerate;
|
constexpr uint32_t chatFramerate = mediumFramerate;
|
||||||
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
|
constexpr uint32_t chatFrameDelta = mediumFrameDelta;
|
||||||
@ -108,7 +107,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
Game::randomEngine = std::mt19937(time(0));
|
Game::randomEngine = std::mt19937(time(0));
|
||||||
|
|
||||||
playerContainer.Initialize();
|
Game::playerContainer.Initialize();
|
||||||
|
|
||||||
//Run it until server gets a kill message from Master:
|
//Run it until server gets a kill message from Master:
|
||||||
auto t = std::chrono::high_resolution_clock::now();
|
auto t = std::chrono::high_resolution_clock::now();
|
||||||
@ -200,19 +199,19 @@ void HandlePacket(Packet* packet) {
|
|||||||
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:
|
||||||
playerContainer.InsertPlayer(packet);
|
Game::playerContainer.InsertPlayer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
|
case eChatInternalMessageType::PLAYER_REMOVED_NOTIFICATION:
|
||||||
playerContainer.RemovePlayer(packet);
|
Game::playerContainer.RemovePlayer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::MUTE_UPDATE:
|
case eChatInternalMessageType::MUTE_UPDATE:
|
||||||
playerContainer.MuteUpdate(packet);
|
Game::playerContainer.MuteUpdate(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::CREATE_TEAM:
|
case eChatInternalMessageType::CREATE_TEAM:
|
||||||
playerContainer.CreateTeamServer(packet);
|
Game::playerContainer.CreateTeamServer(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatInternalMessageType::ANNOUNCEMENT: {
|
case eChatInternalMessageType::ANNOUNCEMENT: {
|
||||||
@ -234,7 +233,15 @@ void HandlePacket(Packet* packet) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::GET_IGNORE_LIST:
|
case eChatMessageType::GET_IGNORE_LIST:
|
||||||
LOG("Asked for ignore list, but is unimplemented right now.");
|
ChatIgnoreList::GetIgnoreList(packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eChatMessageType::ADD_IGNORE:
|
||||||
|
ChatIgnoreList::AddIgnore(packet);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case eChatMessageType::REMOVE_IGNORE:
|
||||||
|
ChatIgnoreList::RemoveIgnore(packet);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eChatMessageType::TEAM_GET_STATUS:
|
case eChatMessageType::TEAM_GET_STATUS:
|
||||||
|
@ -7,12 +7,26 @@
|
|||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
struct IgnoreData {
|
||||||
|
inline bool operator==(const std::string& other) const noexcept {
|
||||||
|
return playerName == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const LWOOBJID& other) const noexcept {
|
||||||
|
return playerId == other;
|
||||||
|
}
|
||||||
|
|
||||||
|
LWOOBJID playerId;
|
||||||
|
std::string playerName;
|
||||||
|
};
|
||||||
|
|
||||||
struct PlayerData {
|
struct PlayerData {
|
||||||
LWOOBJID playerID;
|
LWOOBJID playerID;
|
||||||
std::string playerName;
|
std::string playerName;
|
||||||
SystemAddress sysAddr;
|
SystemAddress sysAddr;
|
||||||
LWOZONEID zoneID;
|
LWOZONEID zoneID;
|
||||||
std::vector<FriendData> friends;
|
std::vector<FriendData> friends;
|
||||||
|
std::vector<IgnoreData> ignoredPlayers;
|
||||||
time_t muteExpire;
|
time_t muteExpire;
|
||||||
uint8_t countOfBestFriends = 0;
|
uint8_t countOfBestFriends = 0;
|
||||||
};
|
};
|
||||||
|
@ -12,6 +12,7 @@ class AssetManager;
|
|||||||
struct SystemAddress;
|
struct SystemAddress;
|
||||||
class EntityManager;
|
class EntityManager;
|
||||||
class dZoneManager;
|
class dZoneManager;
|
||||||
|
class PlayerContainer;
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
extern Logger* logger;
|
extern Logger* logger;
|
||||||
@ -26,4 +27,5 @@ namespace Game {
|
|||||||
extern bool shouldShutdown;
|
extern bool shouldShutdown;
|
||||||
extern EntityManager* entityManager;
|
extern EntityManager* entityManager;
|
||||||
extern dZoneManager* zoneManager;
|
extern dZoneManager* zoneManager;
|
||||||
|
extern PlayerContainer playerContainer;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
PLATFORM_BOUNDARY,
|
PLATFORM_BOUNDARY,
|
||||||
MODULE,
|
MODULE,
|
||||||
ARCADE,
|
ARCADE,
|
||||||
VEHICLE_PHYSICS, // Havok demo based
|
HAVOK_VEHICLE_PHYSICS,
|
||||||
MOVEMENT_AI,
|
MOVEMENT_AI,
|
||||||
EXHIBIT,
|
EXHIBIT,
|
||||||
OVERHEAD_ICON,
|
OVERHEAD_ICON,
|
||||||
@ -50,11 +50,11 @@ enum class eReplicaComponentType : uint32_t {
|
|||||||
PROPERTY_ENTRANCE,
|
PROPERTY_ENTRANCE,
|
||||||
FX,
|
FX,
|
||||||
PROPERTY_MANAGEMENT,
|
PROPERTY_MANAGEMENT,
|
||||||
VEHICLE_PHYSICS_NEW, // internal physics based on havok
|
VEHICLE_PHYSICS,
|
||||||
PHYSICS_SYSTEM,
|
PHYSICS_SYSTEM,
|
||||||
QUICK_BUILD,
|
QUICK_BUILD,
|
||||||
SWITCH,
|
SWITCH,
|
||||||
ZONE_CONTROL, // Minigame
|
MINI_GAME_CONTROL,
|
||||||
CHANGLING,
|
CHANGLING,
|
||||||
CHOICE_BUILD,
|
CHOICE_BUILD,
|
||||||
PACKAGE,
|
PACKAGE,
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "ICharInfo.h"
|
#include "ICharInfo.h"
|
||||||
#include "IAccounts.h"
|
#include "IAccounts.h"
|
||||||
#include "IActivityLog.h"
|
#include "IActivityLog.h"
|
||||||
|
#include "IIgnoreList.h"
|
||||||
#include "IAccountsRewardCodes.h"
|
#include "IAccountsRewardCodes.h"
|
||||||
|
|
||||||
namespace sql {
|
namespace sql {
|
||||||
@ -39,7 +40,7 @@ class GameDatabase :
|
|||||||
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
||||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes {
|
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList {
|
||||||
public:
|
public:
|
||||||
virtual ~GameDatabase() = default;
|
virtual ~GameDatabase() = default;
|
||||||
// TODO: These should be made private.
|
// TODO: These should be made private.
|
||||||
|
20
dDatabase/GameDatabase/ITables/IIgnoreList.h
Normal file
20
dDatabase/GameDatabase/ITables/IIgnoreList.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __IIGNORELIST__H__
|
||||||
|
#define __IIGNORELIST__H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class IIgnoreList {
|
||||||
|
public:
|
||||||
|
struct Info {
|
||||||
|
std::string name;
|
||||||
|
uint32_t id;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual std::vector<Info> GetIgnoreList(const uint32_t playerId) = 0;
|
||||||
|
virtual void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
||||||
|
virtual void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__IIGNORELIST__H__
|
@ -103,6 +103,9 @@ public:
|
|||||||
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
|
||||||
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
|
||||||
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) override;
|
||||||
|
void AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||||
|
void RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) override;
|
||||||
|
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||||
private:
|
private:
|
||||||
|
@ -7,6 +7,7 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
|||||||
"CharXml.cpp"
|
"CharXml.cpp"
|
||||||
"CommandLog.cpp"
|
"CommandLog.cpp"
|
||||||
"Friends.cpp"
|
"Friends.cpp"
|
||||||
|
"IgnoreList.cpp"
|
||||||
"Leaderboard.cpp"
|
"Leaderboard.cpp"
|
||||||
"Mail.cpp"
|
"Mail.cpp"
|
||||||
"MigrationHistory.cpp"
|
"MigrationHistory.cpp"
|
||||||
|
22
dDatabase/GameDatabase/MySQL/Tables/IgnoreList.cpp
Normal file
22
dDatabase/GameDatabase/MySQL/Tables/IgnoreList.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "MySQLDatabase.h"
|
||||||
|
|
||||||
|
std::vector<IIgnoreList::Info> MySQLDatabase::GetIgnoreList(const uint32_t playerId) {
|
||||||
|
auto result = ExecuteSelect("SELECT ci.name AS name, il.ignored_player_id AS ignore_id FROM ignore_list AS il JOIN charinfo AS ci ON il.ignored_player_id = ci.id WHERE il.player_id = ?", playerId);
|
||||||
|
|
||||||
|
std::vector<IIgnoreList::Info> ignoreList;
|
||||||
|
|
||||||
|
ignoreList.reserve(result->rowsCount());
|
||||||
|
while (result->next()) {
|
||||||
|
ignoreList.push_back(IIgnoreList::Info{ result->getString("name").c_str(), result->getUInt("ignore_id") });
|
||||||
|
}
|
||||||
|
|
||||||
|
return ignoreList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MySQLDatabase::AddIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||||
|
ExecuteInsert("INSERT IGNORE INTO ignore_list (player_id, ignored_player_id) VALUES (?, ?)", playerId, ignoredPlayerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MySQLDatabase::RemoveIgnore(const uint32_t playerId, const uint32_t ignoredPlayerId) {
|
||||||
|
ExecuteDelete("DELETE FROM ignore_list WHERE player_id = ? AND ignored_player_id = ?", playerId, ignoredPlayerId);
|
||||||
|
}
|
@ -62,7 +62,7 @@
|
|||||||
#include "ModelComponent.h"
|
#include "ModelComponent.h"
|
||||||
#include "ZCompression.h"
|
#include "ZCompression.h"
|
||||||
#include "PetComponent.h"
|
#include "PetComponent.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
#include "ModuleAssemblyComponent.h"
|
#include "ModuleAssemblyComponent.h"
|
||||||
@ -76,7 +76,7 @@
|
|||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
#include "eReplicaPacketType.h"
|
#include "eReplicaPacketType.h"
|
||||||
#include "ZoneControlComponent.h"
|
#include "MiniGameControlComponent.h"
|
||||||
#include "RacingStatsComponent.h"
|
#include "RacingStatsComponent.h"
|
||||||
#include "CollectibleComponent.h"
|
#include "CollectibleComponent.h"
|
||||||
#include "ItemComponent.h"
|
#include "ItemComponent.h"
|
||||||
@ -217,8 +217,8 @@ void Entity::Initialize() {
|
|||||||
AddComponent<PetComponent>(petComponentId);
|
AddComponent<PetComponent>(petComponentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ZONE_CONTROL) > 0) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MINI_GAME_CONTROL) > 0) {
|
||||||
AddComponent<ZoneControlComponent>();
|
AddComponent<MiniGameControlComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
|
uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
|
||||||
@ -299,10 +299,10 @@ void Entity::Initialize() {
|
|||||||
AddComponent<PhantomPhysicsComponent>()->SetPhysicsEffectActive(false);
|
AddComponent<PhantomPhysicsComponent>()->SetPhysicsEffectActive(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VEHICLE_PHYSICS) > 0) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::HAVOK_VEHICLE_PHYSICS) > 0) {
|
||||||
auto* vehiclePhysicsComponent = AddComponent<VehiclePhysicsComponent>();
|
auto* havokVehiclePhysicsComponent = AddComponent<HavokVehiclePhysicsComponent>();
|
||||||
vehiclePhysicsComponent->SetPosition(m_DefaultPosition);
|
havokVehiclePhysicsComponent->SetPosition(m_DefaultPosition);
|
||||||
vehiclePhysicsComponent->SetRotation(m_DefaultRotation);
|
havokVehiclePhysicsComponent->SetRotation(m_DefaultRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
|
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
|
||||||
@ -554,6 +554,12 @@ void Entity::Initialize() {
|
|||||||
Loot::CacheMatrix(activityID);
|
Loot::CacheMatrix(activityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto timeBeforeSmash = GetVar<float>(u"tmeSmsh");
|
||||||
|
|
||||||
|
if (timeBeforeSmash > 0) {
|
||||||
|
rebuildComponent->SetTimeBeforeSmash(timeBeforeSmash);
|
||||||
|
}
|
||||||
|
|
||||||
const auto compTime = GetVar<float>(u"compTime");
|
const auto compTime = GetVar<float>(u"compTime");
|
||||||
|
|
||||||
if (compTime > 0) {
|
if (compTime > 0) {
|
||||||
@ -738,7 +744,7 @@ void Entity::Initialize() {
|
|||||||
!HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) &&
|
!HasComponent(eReplicaComponentType::PHANTOM_PHYSICS) &&
|
||||||
!HasComponent(eReplicaComponentType::PROPERTY) &&
|
!HasComponent(eReplicaComponentType::PROPERTY) &&
|
||||||
!HasComponent(eReplicaComponentType::RACING_CONTROL) &&
|
!HasComponent(eReplicaComponentType::RACING_CONTROL) &&
|
||||||
!HasComponent(eReplicaComponentType::VEHICLE_PHYSICS)
|
!HasComponent(eReplicaComponentType::HAVOK_VEHICLE_PHYSICS)
|
||||||
)
|
)
|
||||||
//if (HasComponent(eReplicaComponentType::BASE_COMBAT_AI))
|
//if (HasComponent(eReplicaComponentType::BASE_COMBAT_AI))
|
||||||
{
|
{
|
||||||
@ -1017,9 +1023,9 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate);
|
rigidbodyPhantomPhysics->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
VehiclePhysicsComponent* vehiclePhysicsComponent;
|
HavokVehiclePhysicsComponent* havokVehiclePhysicsComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent)) {
|
if (TryGetComponent(eReplicaComponentType::HAVOK_VEHICLE_PHYSICS, havokVehiclePhysicsComponent)) {
|
||||||
vehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
|
havokVehiclePhysicsComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomPhysicsComponent* phantomPhysicsComponent;
|
PhantomPhysicsComponent* phantomPhysicsComponent;
|
||||||
@ -1191,9 +1197,9 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoneControlComponent* zoneControlComponent;
|
MiniGameControlComponent* miniGameControlComponent;
|
||||||
if (TryGetComponent(eReplicaComponentType::ZONE_CONTROL, zoneControlComponent)) {
|
if (TryGetComponent(eReplicaComponentType::MINI_GAME_CONTROL, miniGameControlComponent)) {
|
||||||
zoneControlComponent->Serialize(outBitStream, bIsInitialUpdate);
|
miniGameControlComponent->Serialize(outBitStream, bIsInitialUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// BBB Component, unused currently
|
// BBB Component, unused currently
|
||||||
@ -1503,7 +1509,7 @@ void Entity::Smash(const LWOOBJID source, const eKillType killType, const std::u
|
|||||||
destroyableComponent->Smash(source, killType, deathType);
|
destroyableComponent->Smash(source, killType, deathType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::Kill(Entity* murderer) {
|
void Entity::Kill(Entity* murderer, const eKillType killType) {
|
||||||
if (!m_PlayerIsReadyForUpdates) return;
|
if (!m_PlayerIsReadyForUpdates) return;
|
||||||
|
|
||||||
for (const auto& cb : m_DieCallbacks) {
|
for (const auto& cb : m_DieCallbacks) {
|
||||||
@ -1527,7 +1533,7 @@ void Entity::Kill(Entity* murderer) {
|
|||||||
bool waitForDeathAnimation = false;
|
bool waitForDeathAnimation = false;
|
||||||
|
|
||||||
if (destroyableComponent) {
|
if (destroyableComponent) {
|
||||||
waitForDeathAnimation = destroyableComponent->GetDeathBehavior() == 0;
|
waitForDeathAnimation = destroyableComponent->GetDeathBehavior() == 0 && killType != eKillType::SILENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Live waited a hard coded 12 seconds for death animations of type 0 before networking destruction!
|
// Live waited a hard coded 12 seconds for death animations of type 0 before networking destruction!
|
||||||
@ -1840,7 +1846,7 @@ const NiPoint3& Entity::GetPosition() const {
|
|||||||
return simple->GetPosition();
|
return simple->GetPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* vehicel = GetComponent<VehiclePhysicsComponent>();
|
auto* vehicel = GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
|
|
||||||
if (vehicel != nullptr) {
|
if (vehicel != nullptr) {
|
||||||
return vehicel->GetPosition();
|
return vehicel->GetPosition();
|
||||||
@ -1868,7 +1874,7 @@ const NiQuaternion& Entity::GetRotation() const {
|
|||||||
return simple->GetRotation();
|
return simple->GetRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* vehicel = GetComponent<VehiclePhysicsComponent>();
|
auto* vehicel = GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
|
|
||||||
if (vehicel != nullptr) {
|
if (vehicel != nullptr) {
|
||||||
return vehicel->GetRotation();
|
return vehicel->GetRotation();
|
||||||
@ -1896,7 +1902,7 @@ void Entity::SetPosition(NiPoint3 position) {
|
|||||||
simple->SetPosition(position);
|
simple->SetPosition(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* vehicel = GetComponent<VehiclePhysicsComponent>();
|
auto* vehicel = GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
|
|
||||||
if (vehicel != nullptr) {
|
if (vehicel != nullptr) {
|
||||||
vehicel->SetPosition(position);
|
vehicel->SetPosition(position);
|
||||||
@ -1924,7 +1930,7 @@ void Entity::SetRotation(NiQuaternion rotation) {
|
|||||||
simple->SetRotation(rotation);
|
simple->SetRotation(rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* vehicel = GetComponent<VehiclePhysicsComponent>();
|
auto* vehicel = GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
|
|
||||||
if (vehicel != nullptr) {
|
if (vehicel != nullptr) {
|
||||||
vehicel->SetRotation(rotation);
|
vehicel->SetRotation(rotation);
|
||||||
|
@ -210,7 +210,7 @@ public:
|
|||||||
void RequestActivityExit(Entity* sender, LWOOBJID player, bool canceled);
|
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, const eKillType killType = eKillType::SILENT);
|
||||||
void AddRebuildCompleteCallback(const std::function<void(Entity* user)>& callback) const;
|
void AddRebuildCompleteCallback(const std::function<void(Entity* user)>& callback) const;
|
||||||
void AddCollisionPhantomCallback(const std::function<void(Entity* target)>& callback);
|
void AddCollisionPhantomCallback(const std::function<void(Entity* target)>& callback);
|
||||||
void AddDieCallback(const std::function<void()>& callback);
|
void AddDieCallback(const std::function<void()>& callback);
|
||||||
|
@ -110,3 +110,7 @@ void User::UserOutOfSync() {
|
|||||||
Game::server->Disconnect(this->m_SystemAddress, eServerDisconnectIdentifiers::PLAY_SCHEDULE_TIME_DONE);
|
Game::server->Disconnect(this->m_SystemAddress, eServerDisconnectIdentifiers::PLAY_SCHEDULE_TIME_DONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void User::UpdateBestFriendValue(const std::string_view playerName, const bool newValue) {
|
||||||
|
m_IsBestFriendMap[playerName.data()] = newValue;
|
||||||
|
}
|
||||||
|
@ -43,8 +43,8 @@ public:
|
|||||||
bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; }
|
bool GetLastChatMessageApproved() { return m_LastChatMessageApproved; }
|
||||||
void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; }
|
void SetLastChatMessageApproved(bool approved) { m_LastChatMessageApproved = approved; }
|
||||||
|
|
||||||
std::unordered_map<std::string, bool> GetIsBestFriendMap() { return m_IsBestFriendMap; }
|
const std::unordered_map<std::string, bool>& GetIsBestFriendMap() { return m_IsBestFriendMap; }
|
||||||
void SetIsBestFriendMap(std::unordered_map<std::string, bool> mapToSet) { m_IsBestFriendMap = mapToSet; }
|
void UpdateBestFriendValue(const std::string_view playerName, const bool newValue);
|
||||||
|
|
||||||
bool GetIsMuted() const;
|
bool GetIsMuted() const;
|
||||||
|
|
||||||
|
@ -271,36 +271,36 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream xml;
|
std::stringstream xml;
|
||||||
xml << "<obj v=\"1\"><mf hc=\"" << hairColor << "\" hs=\"" << hairStyle << "\" hd=\"0\" t=\"" << shirtColor << "\" l=\"" << pantsColor;
|
xml << "<obj v=\"1\">";
|
||||||
|
|
||||||
|
xml << "<mf hc=\"" << hairColor << "\" hs=\"" << hairStyle << "\" hd=\"0\" t=\"" << shirtColor << "\" l=\"" << pantsColor;
|
||||||
xml << "\" hdc=\"0\" cd=\"" << shirtStyle << "\" lh=\"" << lh << "\" rh=\"" << rh << "\" es=\"" << eyebrows << "\" ";
|
xml << "\" hdc=\"0\" cd=\"" << shirtStyle << "\" lh=\"" << lh << "\" rh=\"" << rh << "\" es=\"" << eyebrows << "\" ";
|
||||||
xml << "ess=\"" << eyes << "\" ms=\"" << mouth << "\"/>";
|
xml << "ess=\"" << eyes << "\" ms=\"" << mouth << "\"/>";
|
||||||
|
|
||||||
xml << "<char acct=\"" << u->GetAccountID() << "\" cc=\"0\" gm=\"0\" ft=\"0\" llog=\"" << time(NULL) << "\" ";
|
xml << "<char acct=\"" << u->GetAccountID() << "\" cc=\"0\" gm=\"0\" ft=\"0\" llog=\"" << time(NULL) << "\" ";
|
||||||
xml << "ls=\"0\" lzx=\"-626.5847\" lzy=\"613.3515\" lzz=\"-28.6374\" lzrx=\"0.0\" lzry=\"0.7015\" lzrz=\"0.0\" lzrw=\"0.7126\" ";
|
xml << "ls=\"0\" lzx=\"-626.5847\" lzy=\"613.3515\" lzz=\"-28.6374\" lzrx=\"0.0\" lzry=\"0.7015\" lzrz=\"0.0\" lzrw=\"0.7126\" ";
|
||||||
xml << "stt=\"0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;\"></char>";
|
xml << "stt=\"0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;\"></char>";
|
||||||
|
|
||||||
xml << "<dest hm=\"4\" hc=\"4\" im=\"0\" ic=\"0\" am=\"0\" ac=\"0\" d=\"0\"/>";
|
xml << "<dest hm=\"4\" hc=\"4\" im=\"0\" ic=\"0\" am=\"0\" ac=\"0\" d=\"0\"/>";
|
||||||
|
|
||||||
xml << "<inv><bag><b t=\"0\" m=\"20\"/><b t=\"1\" m=\"40\"/><b t=\"2\" m=\"240\"/><b t=\"3\" m=\"240\"/><b t=\"14\" m=\"40\"/></bag><items><in t=\"0\">";
|
xml << "<inv><bag><b t=\"0\" m=\"20\"/><b t=\"1\" m=\"40\"/><b t=\"2\" m=\"240\"/><b t=\"3\" m=\"240\"/><b t=\"14\" m=\"40\"/></bag><items><in t=\"0\">";
|
||||||
std::string xmlSave1 = xml.str();
|
|
||||||
|
|
||||||
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t idforshirt) {
|
LWOOBJID lwoidforshirt = ObjectIDManager::GenerateRandomObjectID();
|
||||||
std::stringstream xml2;
|
LWOOBJID lwoidforpants;
|
||||||
|
|
||||||
|
do {
|
||||||
|
lwoidforpants = ObjectIDManager::GenerateRandomObjectID();
|
||||||
|
} while (lwoidforpants == lwoidforshirt); //Make sure we don't have the same ID for both shirt and pants
|
||||||
|
|
||||||
LWOOBJID lwoidforshirt = idforshirt;
|
|
||||||
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::PERSISTENT);
|
GeneralUtils::SetBit(lwoidforshirt, eObjectBits::PERSISTENT);
|
||||||
xml2 << xmlSave1 << "<i l=\"" << shirtLOT << "\" id=\"" << lwoidforshirt << "\" s=\"0\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
|
||||||
|
|
||||||
std::string xmlSave2 = xml2.str();
|
|
||||||
|
|
||||||
ObjectIDManager::Instance()->RequestPersistentID([=](uint32_t idforpants) {
|
|
||||||
LWOOBJID lwoidforpants = idforpants;
|
|
||||||
GeneralUtils::SetBit(lwoidforpants, eObjectBits::CHARACTER);
|
GeneralUtils::SetBit(lwoidforpants, eObjectBits::CHARACTER);
|
||||||
GeneralUtils::SetBit(lwoidforpants, eObjectBits::PERSISTENT);
|
GeneralUtils::SetBit(lwoidforpants, eObjectBits::PERSISTENT);
|
||||||
|
|
||||||
std::stringstream xml3;
|
xml << "<i l=\"" << shirtLOT << "\" id=\"" << lwoidforshirt << "\" s=\"0\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||||
xml3 << xmlSave2 << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
xml << "<i l=\"" << pantsLOT << "\" id=\"" << lwoidforpants << "\" s=\"1\" c=\"1\" eq=\"1\" b=\"1\"/>";
|
||||||
|
|
||||||
xml3 << "</in></items></inv><lvl l=\"1\" cv=\"1\" sb=\"500\"/><flag></flag></obj>";
|
xml << "</in></items></inv><lvl l=\"1\" cv=\"1\" sb=\"500\"/><flag></flag></obj>";
|
||||||
|
|
||||||
//Check to see if our name was pre-approved:
|
//Check to see if our name was pre-approved:
|
||||||
bool nameOk = IsNamePreapproved(name);
|
bool nameOk = IsNamePreapproved(name);
|
||||||
@ -318,13 +318,11 @@ void UserManager::CreateCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
Database::Get()->InsertNewCharacter(info);
|
Database::Get()->InsertNewCharacter(info);
|
||||||
|
|
||||||
//Now finally insert our character xml:
|
//Now finally insert our character xml:
|
||||||
Database::Get()->InsertCharacterXml(objectID, xml3.str());
|
Database::Get()->InsertCharacterXml(objectID, xml.str());
|
||||||
|
|
||||||
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
WorldPackets::SendCharacterCreationResponse(sysAddr, eCharacterCreationResponse::SUCCESS);
|
||||||
UserManager::RequestCharacterList(sysAddr);
|
UserManager::RequestCharacterList(sysAddr);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
void UserManager::DeleteCharacter(const SystemAddress& sysAddr, Packet* packet) {
|
||||||
@ -403,7 +401,7 @@ void UserManager::RenameCharacter(const SystemAddress& sysAddr, Packet* packet)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Database::Get()->GetCharacterInfo(newName)) {
|
if (!Database::Get()->GetCharacterInfo(newName)) {
|
||||||
if (IsNamePreapproved(newName)) {
|
if (IsNamePreapproved(newName)) {
|
||||||
Database::Get()->SetCharacterName(charID, newName);
|
Database::Get()->SetCharacterName(charID, newName);
|
||||||
LOG("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
|
LOG("Character %s now known as %s", character->GetName().c_str(), newName.c_str());
|
||||||
@ -462,16 +460,18 @@ void UserManager::LoginCharacter(const SystemAddress& sysAddr, uint32_t playerID
|
|||||||
|
|
||||||
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
||||||
try {
|
try {
|
||||||
std::string shirtQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"character create shirt\" AND icc.color1 == ";
|
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
||||||
shirtQuery += std::to_string(shirtColor);
|
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ? AND icc.decal == ?"
|
||||||
shirtQuery += " AND icc.decal == ";
|
);
|
||||||
shirtQuery = shirtQuery + std::to_string(shirtStyle);
|
stmt.bind(1, "character create shirt");
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery(shirtQuery);
|
stmt.bind(2, static_cast<int>(shirtColor));
|
||||||
auto shirtLOT = tableData.getIntField(0, -1);
|
stmt.bind(3, static_cast<int>(shirtStyle));
|
||||||
|
auto tableData = stmt.execQuery();
|
||||||
|
auto shirtLOT = tableData.getIntField(0, 4069);
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
return shirtLOT;
|
return shirtLOT;
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception& ex) {
|
||||||
LOG("Failed to execute query! Using backup...");
|
LOG("Could not look up shirt %i %i: %s", shirtColor, shirtStyle, ex.what());
|
||||||
// in case of no shirt found in CDServer, return problematic red vest.
|
// in case of no shirt found in CDServer, return problematic red vest.
|
||||||
return 4069;
|
return 4069;
|
||||||
}
|
}
|
||||||
@ -479,14 +479,17 @@ uint32_t FindCharShirtID(uint32_t shirtColor, uint32_t shirtStyle) {
|
|||||||
|
|
||||||
uint32_t FindCharPantsID(uint32_t pantsColor) {
|
uint32_t FindCharPantsID(uint32_t pantsColor) {
|
||||||
try {
|
try {
|
||||||
std::string pantsQuery = "select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == \"cc pants\" AND icc.color1 == ";
|
auto stmt = CDClientDatabase::CreatePreppedStmt(
|
||||||
pantsQuery += std::to_string(pantsColor);
|
"select obj.id from Objects as obj JOIN (select * from ComponentsRegistry as cr JOIN ItemComponent as ic on ic.id = cr.component_id where cr.component_type == 11) as icc on icc.id = obj.id where lower(obj._internalNotes) == ? AND icc.color1 == ?"
|
||||||
auto tableData = CDClientDatabase::ExecuteQuery(pantsQuery);
|
);
|
||||||
auto pantsLOT = tableData.getIntField(0, -1);
|
stmt.bind(1, "cc pants");
|
||||||
|
stmt.bind(2, static_cast<int>(pantsColor));
|
||||||
|
auto tableData = stmt.execQuery();
|
||||||
|
auto pantsLOT = tableData.getIntField(0, 2508);
|
||||||
tableData.finalize();
|
tableData.finalize();
|
||||||
return pantsLOT;
|
return pantsLOT;
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception& ex) {
|
||||||
LOG("Failed to execute query! Using backup...");
|
LOG("Could not look up pants %i: %s", pantsColor, ex.what());
|
||||||
// in case of no pants color found in CDServer, return red pants.
|
// in case of no pants color found in CDServer, return red pants.
|
||||||
return 2508;
|
return 2508;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ void ApplyBuffBehavior::Handle(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
if (buffComponent == nullptr) return;
|
if (buffComponent == nullptr) return;
|
||||||
|
|
||||||
buffComponent->ApplyBuff(m_BuffId, m_Duration, context->originator, addImmunity, cancelOnDamaged, cancelOnDeath,
|
buffComponent->ApplyBuff(m_BuffId, m_Duration, context->originator, addImmunity, cancelOnDamaged, cancelOnDeath,
|
||||||
cancelOnLogout, cancelonRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone);
|
cancelOnLogout, cancelonRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone, m_ApplyOnTeammates);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
void ApplyBuffBehavior::UnCast(BehaviorContext* context, BehaviorBranchContext branch) {
|
||||||
@ -45,4 +45,5 @@ void ApplyBuffBehavior::Load() {
|
|||||||
cancelOnUi = GetBoolean("cancel_on_ui");
|
cancelOnUi = GetBoolean("cancel_on_ui");
|
||||||
cancelOnUnequip = GetBoolean("cancel_on_unequip");
|
cancelOnUnequip = GetBoolean("cancel_on_unequip");
|
||||||
cancelOnZone = GetBoolean("cancel_on_zone");
|
cancelOnZone = GetBoolean("cancel_on_zone");
|
||||||
|
m_ApplyOnTeammates = GetBoolean("apply_on_teammates");
|
||||||
}
|
}
|
||||||
|
@ -31,4 +31,6 @@ public:
|
|||||||
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
void Calculate(BehaviorContext* context, RakNet::BitStream* bitStream, BehaviorBranchContext branch) override;
|
||||||
|
|
||||||
void Load() override;
|
void Load() override;
|
||||||
|
private:
|
||||||
|
bool m_ApplyOnTeammates;
|
||||||
};
|
};
|
||||||
|
@ -38,10 +38,12 @@ void JetPackBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bit
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JetPackBehavior::Load() {
|
void JetPackBehavior::Load() {
|
||||||
this->m_WarningEffectID = GetInt("warning_effect_id");
|
this->m_WarningEffectID = GetInt("warning_effect_id", -1);
|
||||||
this->m_Airspeed = GetFloat("airspeed");
|
this->m_Airspeed = GetFloat("airspeed", 10);
|
||||||
this->m_MaxAirspeed = GetFloat("max_airspeed");
|
this->m_MaxAirspeed = GetFloat("max_airspeed", 15);
|
||||||
this->m_VerticalVelocity = GetFloat("vertical_velocity");
|
this->m_VerticalVelocity = GetFloat("vertical_velocity", 1);
|
||||||
this->m_EnableHover = GetBoolean("enable_hover");
|
this->m_EnableHover = GetBoolean("enable_hover", false);
|
||||||
|
|
||||||
|
// TODO: Implement proper jetpack checks, so we can set this default to false
|
||||||
this->m_BypassChecks = GetBoolean("bypass_checks", true);
|
this->m_BypassChecks = GetBoolean("bypass_checks", true);
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
|
|
||||||
const auto casterPosition = self->GetPosition();
|
const auto casterPosition = self->GetPosition();
|
||||||
|
|
||||||
auto reference = self->GetPosition(); //+ m_offset;
|
auto reference = self->GetPosition() + m_offset;
|
||||||
|
|
||||||
targets.clear();
|
targets.clear();
|
||||||
|
|
||||||
@ -114,46 +114,34 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
context->FilterTargets(validTargets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
|
context->FilterTargets(validTargets, this->m_ignoreFactionList, this->m_includeFactionList, this->m_targetSelf, this->m_targetEnemy, this->m_targetFriend, this->m_targetTeam);
|
||||||
|
|
||||||
for (auto validTarget : validTargets) {
|
for (auto validTarget : validTargets) {
|
||||||
if (targets.size() >= this->m_maxTargets) {
|
if (targets.size() >= this->m_maxTargets) break;
|
||||||
break;
|
if (std::find(targets.begin(), targets.end(), validTarget) != targets.end()) continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (std::find(targets.begin(), targets.end(), validTarget) != targets.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (validTarget->GetIsDead()) continue;
|
if (validTarget->GetIsDead()) continue;
|
||||||
|
|
||||||
const auto otherPosition = validTarget->GetPosition();
|
const auto targetPos = validTarget->GetPosition();
|
||||||
|
|
||||||
const auto heightDifference = std::abs(otherPosition.y - casterPosition.y);
|
// make sure we aren't too high or low in comparison to the targer
|
||||||
|
const auto heightDifference = std::abs(reference.y - targetPos.y);
|
||||||
/*if (otherPosition.y > reference.y && heightDifference > this->m_upperBound || otherPosition.y < reference.y && heightDifference > this->m_lowerBound)
|
if (targetPos.y > reference.y && heightDifference > this->m_upperBound || targetPos.y < reference.y && heightDifference > this->m_lowerBound)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}*/
|
|
||||||
|
|
||||||
const auto forward = self->GetRotation().GetForwardVector();
|
const auto forward = self->GetRotation().GetForwardVector();
|
||||||
|
|
||||||
// forward is a normalized vector of where the caster is facing.
|
// forward is a normalized vector of where the caster is facing.
|
||||||
// otherPosition is the position of the target.
|
// targetPos is the position of the target.
|
||||||
// reference is the position of the caster.
|
// reference is the position of the caster.
|
||||||
// If we cast a ray forward from the caster, does it come within m_farWidth of the target?
|
// If we cast a ray forward from the caster, does it come within m_farWidth of the target?
|
||||||
|
|
||||||
const auto distance = Vector3::Distance(reference, otherPosition);
|
const auto distance = Vector3::Distance(reference, targetPos);
|
||||||
|
|
||||||
if (m_method == 2) {
|
if (m_method == 2) {
|
||||||
NiPoint3 rayPoint = casterPosition + forward * distance;
|
NiPoint3 rayPoint = casterPosition + forward * distance;
|
||||||
|
if (m_farWidth > 0 && Vector3::DistanceSquared(rayPoint, targetPos) > this->m_farWidth * this->m_farWidth)
|
||||||
if (m_farWidth > 0 && Vector3::DistanceSquared(rayPoint, otherPosition) > this->m_farWidth * this->m_farWidth) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto normalized = (reference - otherPosition) / distance;
|
|
||||||
|
|
||||||
|
auto normalized = (reference - targetPos) / distance;
|
||||||
const float degreeAngle = std::abs(Vector3::Angle(forward, normalized) * (180 / 3.14) - 180);
|
const float degreeAngle = std::abs(Vector3::Angle(forward, normalized) * (180 / 3.14) - 180);
|
||||||
|
|
||||||
if (distance >= this->m_minRange && this->m_maxRange >= distance && degreeAngle <= 2 * this->m_angle) {
|
if (distance >= this->m_minRange && this->m_maxRange >= distance && degreeAngle <= 2 * this->m_angle) {
|
||||||
targets.push_back(validTarget);
|
targets.push_back(validTarget);
|
||||||
}
|
}
|
||||||
@ -167,33 +155,26 @@ void TacArcBehavior::Calculate(BehaviorContext* context, RakNet::BitStream* bitS
|
|||||||
});
|
});
|
||||||
|
|
||||||
const auto hit = !targets.empty();
|
const auto hit = !targets.empty();
|
||||||
|
|
||||||
bitStream->Write(hit);
|
bitStream->Write(hit);
|
||||||
|
|
||||||
if (this->m_checkEnv) {
|
if (this->m_checkEnv) {
|
||||||
const auto blocked = false; // TODO
|
const auto blocked = false; // TODO
|
||||||
|
|
||||||
bitStream->Write(blocked);
|
bitStream->Write(blocked);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hit) {
|
if (hit) {
|
||||||
if (combatAi != nullptr) {
|
if (combatAi) combatAi->LookAt(targets[0]->GetPosition());
|
||||||
combatAi->LookAt(targets[0]->GetPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
context->foundTarget = true; // We want to continue with this behavior
|
context->foundTarget = true; // We want to continue with this behavior
|
||||||
|
|
||||||
const auto count = static_cast<uint32_t>(targets.size());
|
const auto count = static_cast<uint32_t>(targets.size());
|
||||||
|
|
||||||
bitStream->Write(count);
|
bitStream->Write(count);
|
||||||
|
|
||||||
for (auto* target : targets) {
|
for (auto* target : targets) {
|
||||||
bitStream->Write(target->GetObjectID());
|
bitStream->Write(target->GetObjectID());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* target : targets) {
|
for (auto* target : targets) {
|
||||||
branch.target = target->GetObjectID();
|
branch.target = target->GetObjectID();
|
||||||
|
|
||||||
this->m_action->Calculate(context, bitStream, branch);
|
this->m_action->Calculate(context, bitStream, branch);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -214,8 +195,8 @@ void TacArcBehavior::Load() {
|
|||||||
GetFloat("offset_z", 0.0f)
|
GetFloat("offset_z", 0.0f)
|
||||||
);
|
);
|
||||||
this->m_method = GetInt("method", 1);
|
this->m_method = GetInt("method", 1);
|
||||||
this->m_upperBound = GetFloat("upper_bound", 4.4f);
|
this->m_upperBound = std::abs(GetFloat("upper_bound", 4.4f));
|
||||||
this->m_lowerBound = GetFloat("lower_bound", 0.4f);
|
this->m_lowerBound = std::abs(GetFloat("lower_bound", 0.4f));
|
||||||
this->m_usePickedTarget = GetBoolean("use_picked_target", false);
|
this->m_usePickedTarget = GetBoolean("use_picked_target", false);
|
||||||
this->m_useTargetPostion = GetBoolean("use_target_position", false);
|
this->m_useTargetPostion = GetBoolean("use_target_position", false);
|
||||||
this->m_checkEnv = GetBoolean("check_env", false);
|
this->m_checkEnv = GetBoolean("check_env", false);
|
||||||
|
@ -11,9 +11,21 @@
|
|||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
#include "CDClientManager.h"
|
#include "CDClientManager.h"
|
||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
|
#include "TeamManager.h"
|
||||||
|
|
||||||
std::unordered_map<int32_t, std::vector<BuffParameter>> BuffComponent::m_Cache{};
|
std::unordered_map<int32_t, std::vector<BuffParameter>> BuffComponent::m_Cache{};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::map<std::string, std::string> BuffFx = {
|
||||||
|
{ "overtime", "OTB_" },
|
||||||
|
{ "max_health", "HEALTH_" },
|
||||||
|
{ "max_imagination", "IMAGINATION_" },
|
||||||
|
{ "max_armor", "ARMOR_" },
|
||||||
|
{ "speed", "SPEED_" },
|
||||||
|
{ "loot", "LOOT_" }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
BuffComponent::BuffComponent(Entity* parent) : Component(parent) {
|
BuffComponent::BuffComponent(Entity* parent) : Component(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -22,32 +34,38 @@ BuffComponent::~BuffComponent() {
|
|||||||
|
|
||||||
void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
void BuffComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
if (!bIsInitialUpdate) return;
|
if (!bIsInitialUpdate) return;
|
||||||
if (m_Buffs.empty()) {
|
outBitStream->Write(!m_Buffs.empty());
|
||||||
outBitStream->Write0();
|
if (!m_Buffs.empty()) {
|
||||||
} else {
|
|
||||||
outBitStream->Write1();
|
|
||||||
outBitStream->Write<uint32_t>(m_Buffs.size());
|
outBitStream->Write<uint32_t>(m_Buffs.size());
|
||||||
|
|
||||||
for (const auto& buff : m_Buffs) {
|
for (const auto& [id, buff] : m_Buffs) {
|
||||||
outBitStream->Write<uint32_t>(buff.first);
|
outBitStream->Write<uint32_t>(id);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.time != 0.0f);
|
||||||
outBitStream->Write0();
|
if (buff.time != 0.0f) outBitStream->Write(static_cast<uint32_t>(buff.time * 1000.0f));
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnDeath);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnZone);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnDamaged);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnRemoveBuff);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnUi);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnLogout);
|
||||||
outBitStream->Write0();
|
outBitStream->Write(buff.cancelOnUnequip);
|
||||||
|
outBitStream->Write0(); // Cancel on Damage Absorb Ran Out. Generally false from what I can tell
|
||||||
|
|
||||||
outBitStream->Write0();
|
auto* team = TeamManager::Instance()->GetTeam(buff.source);
|
||||||
outBitStream->Write0();
|
bool addedByTeammate = false;
|
||||||
|
if (team) {
|
||||||
|
addedByTeammate = std::count(team->members.begin(), team->members.end(), m_Parent->GetObjectID()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
outBitStream->Write<uint32_t>(0);
|
outBitStream->Write(addedByTeammate); // Added by teammate. If source is in the same team as the target, this is true. Otherwise, false.
|
||||||
|
outBitStream->Write(buff.applyOnTeammates);
|
||||||
|
if (addedByTeammate) outBitStream->Write(buff.source);
|
||||||
|
|
||||||
|
outBitStream->Write<uint32_t>(buff.refCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream->Write0();
|
outBitStream->Write0(); // something to do with immunity buffs?
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuffComponent::Update(float deltaTime) {
|
void BuffComponent::Update(float deltaTime) {
|
||||||
@ -83,17 +101,55 @@ void BuffComponent::Update(float deltaTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string& GetFxName(const std::string& buffname) {
|
||||||
|
const auto& toReturn = BuffFx[buffname];
|
||||||
|
if (toReturn.empty()) {
|
||||||
|
LOG_DEBUG("No fx name for %s", buffname.c_str());
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuffComponent::ApplyBuffFx(uint32_t buffId, const BuffParameter& buff) {
|
||||||
|
std::string fxToPlay;
|
||||||
|
const auto& buffName = GetFxName(buff.name);
|
||||||
|
|
||||||
|
if (buffName.empty()) return;
|
||||||
|
|
||||||
|
fxToPlay += std::to_string(buffId);
|
||||||
|
LOG_DEBUG("Playing %s %i", fxToPlay.c_str(), buff.effectId);
|
||||||
|
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), buff.effectId, u"cast", fxToPlay, LWOOBJID_EMPTY, 1.07f, 1.0f, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BuffComponent::RemoveBuffFx(uint32_t buffId, const BuffParameter& buff) {
|
||||||
|
std::string fxToPlay;
|
||||||
|
const auto& buffName = GetFxName(buff.name);
|
||||||
|
|
||||||
|
if (buffName.empty()) return;
|
||||||
|
|
||||||
|
fxToPlay += std::to_string(buffId);
|
||||||
|
LOG_DEBUG("Stopping %s", fxToPlay.c_str());
|
||||||
|
GameMessages::SendStopFXEffect(m_Parent, false, fxToPlay);
|
||||||
|
}
|
||||||
|
|
||||||
void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOOBJID source, bool addImmunity,
|
void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOOBJID source, bool addImmunity,
|
||||||
bool cancelOnDamaged, bool cancelOnDeath, bool cancelOnLogout, bool cancelOnRemoveBuff,
|
bool cancelOnDamaged, bool cancelOnDeath, bool cancelOnLogout, bool cancelOnRemoveBuff,
|
||||||
bool cancelOnUi, bool cancelOnUnequip, bool cancelOnZone) {
|
bool cancelOnUi, bool cancelOnUnequip, bool cancelOnZone, bool applyOnTeammates) {
|
||||||
// Prevent buffs from stacking.
|
// Prevent buffs from stacking.
|
||||||
if (HasBuff(id)) {
|
if (HasBuff(id)) {
|
||||||
|
m_Buffs[id].refCount++;
|
||||||
|
m_Buffs[id].time = duration;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto* team = TeamManager::Instance()->GetTeam(source);
|
||||||
|
bool addedByTeammate = false;
|
||||||
|
if (team) {
|
||||||
|
addedByTeammate = std::count(team->members.begin(), team->members.end(), m_Parent->GetObjectID()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
GameMessages::SendAddBuff(const_cast<LWOOBJID&>(m_Parent->GetObjectID()), source, (uint32_t)id,
|
GameMessages::SendAddBuff(const_cast<LWOOBJID&>(m_Parent->GetObjectID()), source, (uint32_t)id,
|
||||||
(uint32_t)duration * 1000, addImmunity, cancelOnDamaged, cancelOnDeath,
|
(uint32_t)duration * 1000, addImmunity, cancelOnDamaged, cancelOnDeath,
|
||||||
cancelOnLogout, cancelOnRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone);
|
cancelOnLogout, cancelOnRemoveBuff, cancelOnUi, cancelOnUnequip, cancelOnZone, addedByTeammate, applyOnTeammates);
|
||||||
|
|
||||||
float tick = 0;
|
float tick = 0;
|
||||||
float stacks = 0;
|
float stacks = 0;
|
||||||
@ -121,17 +177,43 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO
|
|||||||
buff.stacks = stacks;
|
buff.stacks = stacks;
|
||||||
buff.source = source;
|
buff.source = source;
|
||||||
buff.behaviorID = behaviorID;
|
buff.behaviorID = behaviorID;
|
||||||
|
buff.cancelOnDamaged = cancelOnDamaged;
|
||||||
|
buff.cancelOnDeath = cancelOnDeath;
|
||||||
|
buff.cancelOnLogout = cancelOnLogout;
|
||||||
|
buff.cancelOnRemoveBuff = cancelOnRemoveBuff;
|
||||||
|
buff.cancelOnUi = cancelOnUi;
|
||||||
|
buff.cancelOnUnequip = cancelOnUnequip;
|
||||||
|
buff.cancelOnZone = cancelOnZone;
|
||||||
|
buff.refCount = 1;
|
||||||
|
|
||||||
m_Buffs.emplace(id, buff);
|
m_Buffs.emplace(id, buff);
|
||||||
|
|
||||||
|
auto* parent = GetParent();
|
||||||
|
if (!cancelOnDeath) return;
|
||||||
|
|
||||||
|
m_Parent->AddDieCallback([parent, id]() {
|
||||||
|
LOG_DEBUG("Removing buff %i because parent died", id);
|
||||||
|
if (!parent) return;
|
||||||
|
auto* buffComponent = parent->GetComponent<BuffComponent>();
|
||||||
|
if (buffComponent) buffComponent->RemoveBuff(id, false, false, true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity) {
|
void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity, bool ignoreRefCount) {
|
||||||
const auto& iter = m_Buffs.find(id);
|
const auto& iter = m_Buffs.find(id);
|
||||||
|
|
||||||
if (iter == m_Buffs.end()) {
|
if (iter == m_Buffs.end()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ignoreRefCount && !iter->second.cancelOnRemoveBuff) {
|
||||||
|
iter->second.refCount--;
|
||||||
|
LOG_DEBUG("refCount for buff %i is now %i", id, iter->second.refCount);
|
||||||
|
if (iter->second.refCount > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
|
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
|
||||||
|
|
||||||
m_Buffs.erase(iter);
|
m_Buffs.erase(iter);
|
||||||
@ -146,6 +228,7 @@ bool BuffComponent::HasBuff(int32_t id) {
|
|||||||
void BuffComponent::ApplyBuffEffect(int32_t id) {
|
void BuffComponent::ApplyBuffEffect(int32_t id) {
|
||||||
const auto& parameters = GetBuffParameters(id);
|
const auto& parameters = GetBuffParameters(id);
|
||||||
for (const auto& parameter : parameters) {
|
for (const auto& parameter : parameters) {
|
||||||
|
ApplyBuffFx(id, parameter);
|
||||||
if (parameter.name == "max_health") {
|
if (parameter.name == "max_health") {
|
||||||
const auto maxHealth = parameter.value;
|
const auto maxHealth = parameter.value;
|
||||||
|
|
||||||
@ -182,6 +265,7 @@ void BuffComponent::ApplyBuffEffect(int32_t id) {
|
|||||||
void BuffComponent::RemoveBuffEffect(int32_t id) {
|
void BuffComponent::RemoveBuffEffect(int32_t id) {
|
||||||
const auto& parameters = GetBuffParameters(id);
|
const auto& parameters = GetBuffParameters(id);
|
||||||
for (const auto& parameter : parameters) {
|
for (const auto& parameter : parameters) {
|
||||||
|
RemoveBuffFx(id, parameter);
|
||||||
if (parameter.name == "max_health") {
|
if (parameter.name == "max_health") {
|
||||||
const auto maxHealth = parameter.value;
|
const auto maxHealth = parameter.value;
|
||||||
|
|
||||||
@ -251,13 +335,25 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
auto* buffEntry = buffElement->FirstChildElement("b");
|
auto* buffEntry = buffElement->FirstChildElement("b");
|
||||||
|
|
||||||
while (buffEntry != nullptr) {
|
while (buffEntry) {
|
||||||
int32_t id = buffEntry->IntAttribute("id");
|
int32_t id = buffEntry->IntAttribute("id");
|
||||||
float t = buffEntry->FloatAttribute("t");
|
float t = buffEntry->FloatAttribute("t");
|
||||||
float tk = buffEntry->FloatAttribute("tk");
|
float tk = buffEntry->FloatAttribute("tk");
|
||||||
|
float tt = buffEntry->FloatAttribute("tt");
|
||||||
int32_t s = buffEntry->FloatAttribute("s");
|
int32_t s = buffEntry->FloatAttribute("s");
|
||||||
LWOOBJID sr = buffEntry->Int64Attribute("sr");
|
LWOOBJID sr = buffEntry->Int64Attribute("sr");
|
||||||
int32_t b = buffEntry->IntAttribute("b");
|
int32_t b = buffEntry->IntAttribute("b");
|
||||||
|
int32_t refCount = buffEntry->IntAttribute("refCount");
|
||||||
|
|
||||||
|
bool cancelOnDamaged = buffEntry->BoolAttribute("cancelOnDamaged");
|
||||||
|
bool cancelOnDeath = buffEntry->BoolAttribute("cancelOnDeath");
|
||||||
|
bool cancelOnLogout = buffEntry->BoolAttribute("cancelOnLogout");
|
||||||
|
bool cancelOnRemoveBuff = buffEntry->BoolAttribute("cancelOnRemoveBuff");
|
||||||
|
bool cancelOnUi = buffEntry->BoolAttribute("cancelOnUi");
|
||||||
|
bool cancelOnUnequip = buffEntry->BoolAttribute("cancelOnUnequip");
|
||||||
|
bool cancelOnZone = buffEntry->BoolAttribute("cancelOnZone");
|
||||||
|
bool applyOnTeammates = buffEntry->BoolAttribute("applyOnTeammates");
|
||||||
|
|
||||||
|
|
||||||
Buff buff;
|
Buff buff;
|
||||||
buff.id = id;
|
buff.id = id;
|
||||||
@ -266,6 +362,18 @@ void BuffComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
buff.stacks = s;
|
buff.stacks = s;
|
||||||
buff.source = sr;
|
buff.source = sr;
|
||||||
buff.behaviorID = b;
|
buff.behaviorID = b;
|
||||||
|
buff.refCount = refCount;
|
||||||
|
buff.tickTime = tt;
|
||||||
|
|
||||||
|
buff.cancelOnDamaged = cancelOnDamaged;
|
||||||
|
buff.cancelOnDeath = cancelOnDeath;
|
||||||
|
buff.cancelOnLogout = cancelOnLogout;
|
||||||
|
buff.cancelOnRemoveBuff = cancelOnRemoveBuff;
|
||||||
|
buff.cancelOnUi = cancelOnUi;
|
||||||
|
buff.cancelOnUnequip = cancelOnUnequip;
|
||||||
|
buff.cancelOnZone = cancelOnZone;
|
||||||
|
buff.applyOnTeammates = applyOnTeammates;
|
||||||
|
|
||||||
|
|
||||||
m_Buffs.emplace(id, buff);
|
m_Buffs.emplace(id, buff);
|
||||||
|
|
||||||
@ -288,15 +396,27 @@ void BuffComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
buffElement->DeleteChildren();
|
buffElement->DeleteChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& buff : m_Buffs) {
|
for (const auto& [id, buff] : m_Buffs) {
|
||||||
auto* buffEntry = doc->NewElement("b");
|
auto* buffEntry = doc->NewElement("b");
|
||||||
|
if (buff.cancelOnZone || buff.cancelOnLogout) continue;
|
||||||
|
|
||||||
buffEntry->SetAttribute("id", buff.first);
|
buffEntry->SetAttribute("id", id);
|
||||||
buffEntry->SetAttribute("t", buff.second.time);
|
buffEntry->SetAttribute("t", buff.time);
|
||||||
buffEntry->SetAttribute("tk", buff.second.tick);
|
buffEntry->SetAttribute("tk", buff.tick);
|
||||||
buffEntry->SetAttribute("s", buff.second.stacks);
|
buffEntry->SetAttribute("tt", buff.tickTime);
|
||||||
buffEntry->SetAttribute("sr", buff.second.source);
|
buffEntry->SetAttribute("s", buff.stacks);
|
||||||
buffEntry->SetAttribute("b", buff.second.behaviorID);
|
buffEntry->SetAttribute("sr", buff.source);
|
||||||
|
buffEntry->SetAttribute("b", buff.behaviorID);
|
||||||
|
buffEntry->SetAttribute("refCount", buff.refCount);
|
||||||
|
|
||||||
|
buffEntry->SetAttribute("cancelOnDamaged", buff.cancelOnDamaged);
|
||||||
|
buffEntry->SetAttribute("cancelOnDeath", buff.cancelOnDeath);
|
||||||
|
buffEntry->SetAttribute("cancelOnLogout", buff.cancelOnLogout);
|
||||||
|
buffEntry->SetAttribute("cancelOnRemoveBuff", buff.cancelOnRemoveBuff);
|
||||||
|
buffEntry->SetAttribute("cancelOnUi", buff.cancelOnUi);
|
||||||
|
buffEntry->SetAttribute("cancelOnUnequip", buff.cancelOnUnequip);
|
||||||
|
buffEntry->SetAttribute("cancelOnZone", buff.cancelOnZone);
|
||||||
|
buffEntry->SetAttribute("applyOnTeammates", buff.applyOnTeammates);
|
||||||
|
|
||||||
buffElement->LinkEndChild(buffEntry);
|
buffElement->LinkEndChild(buffEntry);
|
||||||
}
|
}
|
||||||
@ -309,8 +429,7 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
|
|||||||
return pair->second;
|
return pair->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM BuffParameters WHERE BuffID = ?;");
|
||||||
"SELECT * FROM BuffParameters WHERE BuffID = ?;");
|
|
||||||
query.bind(1, (int)buffId);
|
query.bind(1, (int)buffId);
|
||||||
|
|
||||||
auto result = query.execQuery();
|
auto result = query.execQuery();
|
||||||
@ -321,11 +440,12 @@ const std::vector<BuffParameter>& BuffComponent::GetBuffParameters(int32_t buffI
|
|||||||
BuffParameter param;
|
BuffParameter param;
|
||||||
|
|
||||||
param.buffId = buffId;
|
param.buffId = buffId;
|
||||||
param.name = result.getStringField(1);
|
param.name = result.getStringField("ParameterName");
|
||||||
param.value = result.getFloatField(2);
|
param.value = result.getFloatField("NumberValue");
|
||||||
|
param.effectId = result.getIntField("EffectID");
|
||||||
|
|
||||||
if (!result.fieldIsNull(3)) {
|
if (!result.fieldIsNull(3)) {
|
||||||
std::istringstream stream(result.getStringField(3));
|
std::istringstream stream(result.getStringField("StringValue"));
|
||||||
std::string token;
|
std::string token;
|
||||||
|
|
||||||
while (std::getline(stream, token, ',')) {
|
while (std::getline(stream, token, ',')) {
|
||||||
|
@ -14,8 +14,7 @@ class Entity;
|
|||||||
/**
|
/**
|
||||||
* Extra information on effects to apply after applying a buff, for example whether to buff armor, imag or health and by how much
|
* Extra information on effects to apply after applying a buff, for example whether to buff armor, imag or health and by how much
|
||||||
*/
|
*/
|
||||||
struct BuffParameter
|
struct BuffParameter {
|
||||||
{
|
|
||||||
int32_t buffId;
|
int32_t buffId;
|
||||||
std::string name;
|
std::string name;
|
||||||
float value;
|
float value;
|
||||||
@ -26,8 +25,7 @@ struct BuffParameter
|
|||||||
/**
|
/**
|
||||||
* Meta information about a buff that can be applied, e.g. how long it's applied, who applied it, etc.
|
* Meta information about a buff that can be applied, e.g. how long it's applied, who applied it, etc.
|
||||||
*/
|
*/
|
||||||
struct Buff
|
struct Buff {
|
||||||
{
|
|
||||||
int32_t id = 0;
|
int32_t id = 0;
|
||||||
float time = 0;
|
float time = 0;
|
||||||
float tick = 0;
|
float tick = 0;
|
||||||
@ -35,6 +33,15 @@ struct Buff
|
|||||||
int32_t stacks = 0;
|
int32_t stacks = 0;
|
||||||
LWOOBJID source = 0;
|
LWOOBJID source = 0;
|
||||||
int32_t behaviorID = 0;
|
int32_t behaviorID = 0;
|
||||||
|
bool cancelOnDamaged = false;
|
||||||
|
bool cancelOnDeath = false;
|
||||||
|
bool cancelOnLogout = false;
|
||||||
|
bool cancelOnRemoveBuff = false;
|
||||||
|
bool cancelOnUi = false;
|
||||||
|
bool cancelOnUnequip = false;
|
||||||
|
bool cancelOnZone = false;
|
||||||
|
bool applyOnTeammates = false;
|
||||||
|
uint32_t refCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,14 +81,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
void ApplyBuff(int32_t id, float duration, LWOOBJID source, bool addImmunity = false, bool cancelOnDamaged = false,
|
void ApplyBuff(int32_t id, float duration, LWOOBJID source, bool addImmunity = false, bool cancelOnDamaged = false,
|
||||||
bool cancelOnDeath = true, bool cancelOnLogout = false, bool cancelOnRemoveBuff = true,
|
bool cancelOnDeath = true, bool cancelOnLogout = false, bool cancelOnRemoveBuff = true,
|
||||||
bool cancelOnUi = false, bool cancelOnUnequip = false, bool cancelOnZone = false);
|
bool cancelOnUi = false, bool cancelOnUnequip = false, bool cancelOnZone = false, bool applyOnTeammates = false);
|
||||||
|
|
||||||
|
void ApplyBuffFx(uint32_t buffId, const BuffParameter& buffName);
|
||||||
|
void RemoveBuffFx(uint32_t buffId, const BuffParameter& buffName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a buff from the parent entity, reversing its effects
|
* Removes a buff from the parent entity, reversing its effects
|
||||||
* @param id the id of the buff to remove
|
* @param id the id of the buff to remove
|
||||||
* @param removeImmunity whether or not to remove immunity on removing the buff
|
* @param removeImmunity whether or not to remove immunity on removing the buff
|
||||||
*/
|
*/
|
||||||
void RemoveBuff(int32_t id, bool fromUnEquip = false, bool removeImmunity = false);
|
void RemoveBuff(int32_t id, bool fromUnEquip = false, bool removeImmunity = false, bool ignoreRefCount = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not the entity has a buff identified by `id`
|
* Returns whether or not the entity has a buff identified by `id`
|
||||||
|
@ -43,8 +43,8 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
|
|||||||
"SoundTriggerComponent.cpp"
|
"SoundTriggerComponent.cpp"
|
||||||
"SwitchComponent.cpp"
|
"SwitchComponent.cpp"
|
||||||
"TriggerComponent.cpp"
|
"TriggerComponent.cpp"
|
||||||
"VehiclePhysicsComponent.cpp"
|
"HavokVehiclePhysicsComponent.cpp"
|
||||||
"VendorComponent.cpp"
|
"VendorComponent.cpp"
|
||||||
"ZoneControlComponent.cpp"
|
"MiniGameControlComponent.cpp"
|
||||||
PARENT_SCOPE
|
PARENT_SCOPE
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "InventoryComponent.h"
|
#include "InventoryComponent.h"
|
||||||
#include "ControllablePhysicsComponent.h"
|
#include "ControllablePhysicsComponent.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "GameMessages.h"
|
#include "GameMessages.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
#include "Amf3.h"
|
#include "Amf3.h"
|
||||||
|
@ -796,7 +796,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Parent->Kill(owner);
|
m_Parent->Kill(owner, killType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
|
void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
|
|
||||||
VehiclePhysicsComponent::VehiclePhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
|
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent) : PhysicsComponent(parent) {
|
||||||
m_Velocity = NiPoint3::ZERO;
|
m_Velocity = NiPoint3::ZERO;
|
||||||
m_AngularVelocity = NiPoint3::ZERO;
|
m_AngularVelocity = NiPoint3::ZERO;
|
||||||
m_IsOnGround = true;
|
m_IsOnGround = true;
|
||||||
@ -12,45 +12,45 @@ VehiclePhysicsComponent::VehiclePhysicsComponent(Entity* parent) : PhysicsCompon
|
|||||||
m_EndBehavior = GeneralUtils::GenerateRandomNumber<uint32_t>(0, 7);
|
m_EndBehavior = GeneralUtils::GenerateRandomNumber<uint32_t>(0, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetVelocity(const NiPoint3& vel) {
|
void HavokVehiclePhysicsComponent::SetVelocity(const NiPoint3& vel) {
|
||||||
if (vel == m_Velocity) return;
|
if (vel == m_Velocity) return;
|
||||||
m_DirtyPosition = true;
|
m_DirtyPosition = true;
|
||||||
m_Velocity = vel;
|
m_Velocity = vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetAngularVelocity(const NiPoint3& vel) {
|
void HavokVehiclePhysicsComponent::SetAngularVelocity(const NiPoint3& vel) {
|
||||||
if (vel == m_AngularVelocity) return;
|
if (vel == m_AngularVelocity) return;
|
||||||
m_DirtyPosition = true;
|
m_DirtyPosition = true;
|
||||||
m_AngularVelocity = vel;
|
m_AngularVelocity = vel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetIsOnGround(bool val) {
|
void HavokVehiclePhysicsComponent::SetIsOnGround(bool val) {
|
||||||
if (val == m_IsOnGround) return;
|
if (val == m_IsOnGround) return;
|
||||||
m_DirtyPosition = true;
|
m_DirtyPosition = true;
|
||||||
m_IsOnGround = val;
|
m_IsOnGround = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetIsOnRail(bool val) {
|
void HavokVehiclePhysicsComponent::SetIsOnRail(bool val) {
|
||||||
if (val == m_IsOnRail) return;
|
if (val == m_IsOnRail) return;
|
||||||
m_DirtyPosition = true;
|
m_DirtyPosition = true;
|
||||||
m_IsOnRail = val;
|
m_IsOnRail = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetRemoteInputInfo(const RemoteInputInfo& remoteInputInfo) {
|
void HavokVehiclePhysicsComponent::SetRemoteInputInfo(const RemoteInputInfo& remoteInputInfo) {
|
||||||
if (m_RemoteInputInfo == remoteInputInfo) return;
|
if (m_RemoteInputInfo == remoteInputInfo) return;
|
||||||
this->m_RemoteInputInfo = remoteInputInfo;
|
this->m_RemoteInputInfo = remoteInputInfo;
|
||||||
m_DirtyRemoteInput = true;
|
m_DirtyRemoteInput = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetDirtyVelocity(bool val) {
|
void HavokVehiclePhysicsComponent::SetDirtyVelocity(bool val) {
|
||||||
m_DirtyVelocity = val;
|
m_DirtyVelocity = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::SetDirtyAngularVelocity(bool val) {
|
void HavokVehiclePhysicsComponent::SetDirtyAngularVelocity(bool val) {
|
||||||
m_DirtyAngularVelocity = val;
|
m_DirtyAngularVelocity = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
void HavokVehiclePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
outBitStream->Write(bIsInitialUpdate || m_DirtyPosition);
|
outBitStream->Write(bIsInitialUpdate || m_DirtyPosition);
|
||||||
|
|
||||||
if (bIsInitialUpdate || m_DirtyPosition) {
|
if (bIsInitialUpdate || m_DirtyPosition) {
|
||||||
@ -111,7 +111,7 @@ void VehiclePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bool bI
|
|||||||
outBitStream->Write0();
|
outBitStream->Write0();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VehiclePhysicsComponent::Update(float deltaTime) {
|
void HavokVehiclePhysicsComponent::Update(float deltaTime) {
|
||||||
if (m_SoftUpdate > 5) {
|
if (m_SoftUpdate > 5) {
|
||||||
Game::entityManager->SerializeEntity(m_Parent);
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
m_SoftUpdate = 0;
|
m_SoftUpdate = 0;
|
@ -6,6 +6,13 @@
|
|||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
struct RemoteInputInfo {
|
struct RemoteInputInfo {
|
||||||
|
RemoteInputInfo() {
|
||||||
|
m_RemoteInputX = 0;
|
||||||
|
m_RemoteInputY = 0;
|
||||||
|
m_IsPowersliding = false;
|
||||||
|
m_IsModified = false;
|
||||||
|
}
|
||||||
|
|
||||||
void operator=(const RemoteInputInfo& other) {
|
void operator=(const RemoteInputInfo& other) {
|
||||||
m_RemoteInputX = other.m_RemoteInputX;
|
m_RemoteInputX = other.m_RemoteInputX;
|
||||||
m_RemoteInputY = other.m_RemoteInputY;
|
m_RemoteInputY = other.m_RemoteInputY;
|
||||||
@ -26,11 +33,11 @@ struct RemoteInputInfo {
|
|||||||
/**
|
/**
|
||||||
* Physics component for vehicles.
|
* Physics component for vehicles.
|
||||||
*/
|
*/
|
||||||
class VehiclePhysicsComponent : public PhysicsComponent {
|
class HavokVehiclePhysicsComponent : public PhysicsComponent {
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::VEHICLE_PHYSICS;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
|
||||||
|
|
||||||
VehiclePhysicsComponent(Entity* parentEntity);
|
HavokVehiclePhysicsComponent(Entity* parentEntity);
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
|
||||||
|
|
@ -19,7 +19,7 @@
|
|||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "ModuleAssemblyComponent.h"
|
#include "ModuleAssemblyComponent.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
#include "PropertyManagementComponent.h"
|
#include "PropertyManagementComponent.h"
|
||||||
@ -981,7 +981,7 @@ void InventoryComponent::HandlePossession(Item* item) {
|
|||||||
auto* mount = Game::entityManager->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<HavokVehiclePhysicsComponent>();
|
||||||
if (vehicleComponent) characterComponent->SetIsRacing(true);
|
if (vehicleComponent) characterComponent->SetIsRacing(true);
|
||||||
|
|
||||||
// Setup the destroyable stats
|
// Setup the destroyable stats
|
||||||
|
5
dGame/dComponents/MiniGameControlComponent.cpp
Normal file
5
dGame/dComponents/MiniGameControlComponent.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "MiniGameControlComponent.h"
|
||||||
|
|
||||||
|
void MiniGameControlComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
|
||||||
|
outBitStream->Write<uint32_t>(0x40000000);
|
||||||
|
}
|
15
dGame/dComponents/MiniGameControlComponent.h
Normal file
15
dGame/dComponents/MiniGameControlComponent.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __MINIGAMECONTROLCOMPONENT__H__
|
||||||
|
#define __MINIGAMECONTROLCOMPONENT__H__
|
||||||
|
|
||||||
|
#include "Component.h"
|
||||||
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
|
class MiniGameControlComponent final : public Component {
|
||||||
|
public:
|
||||||
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
|
||||||
|
|
||||||
|
MiniGameControlComponent(Entity* parent) : Component(parent) {}
|
||||||
|
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__MINIGAMECONTROLCOMPONENT__H__
|
5
dGame/dComponents/MinigameComponent.cpp
Normal file
5
dGame/dComponents/MinigameComponent.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#include "MinigameComponent.h"
|
||||||
|
|
||||||
|
void MinigameComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
|
||||||
|
outBitStream->Write<uint32_t>(0x40000000);
|
||||||
|
}
|
@ -145,8 +145,13 @@ void MissionComponent::RemoveMission(uint32_t missionId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
|
void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
|
||||||
for (const auto& pair : m_Missions) {
|
std::vector<uint32_t> acceptedAchievements;
|
||||||
auto* mission = pair.second;
|
if (count > 0 && !ignoreAchievements) {
|
||||||
|
acceptedAchievements = LookForAchievements(type, value, true, associate, targets, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [id, mission] : m_Missions) {
|
||||||
|
if (!mission || std::find(acceptedAchievements.begin(), acceptedAchievements.end(), mission->GetMissionId()) != acceptedAchievements.end()) continue;
|
||||||
|
|
||||||
if (mission->IsAchievement() && ignoreAchievements) continue;
|
if (mission->IsAchievement() && ignoreAchievements) continue;
|
||||||
|
|
||||||
@ -154,10 +159,6 @@ void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID a
|
|||||||
|
|
||||||
mission->Progress(type, value, associate, targets, count);
|
mission->Progress(type, value, associate, targets, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count > 0 && !ignoreAchievements) {
|
|
||||||
LookForAchievements(type, value, true, associate, targets, count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) {
|
void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) {
|
||||||
@ -282,12 +283,12 @@ bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) {
|
|||||||
|
|
||||||
#define MISSION_NEW_METHOD
|
#define MISSION_NEW_METHOD
|
||||||
|
|
||||||
bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) {
|
const std::vector<uint32_t> MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) {
|
||||||
#ifdef MISSION_NEW_METHOD
|
#ifdef MISSION_NEW_METHOD
|
||||||
// Query for achievments, using the cache
|
// Query for achievments, using the cache
|
||||||
const auto& result = QueryAchievements(type, value, targets);
|
const auto& result = QueryAchievements(type, value, targets);
|
||||||
|
|
||||||
bool any = false;
|
std::vector<uint32_t> acceptedAchievements;
|
||||||
|
|
||||||
for (const uint32_t missionID : result) {
|
for (const uint32_t missionID : result) {
|
||||||
// Check if we already have this achievement
|
// Check if we already have this achievement
|
||||||
@ -309,7 +310,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
|
|||||||
|
|
||||||
instance->Accept();
|
instance->Accept();
|
||||||
|
|
||||||
any = true;
|
acceptedAchievements.push_back(missionID);
|
||||||
|
|
||||||
if (progress) {
|
if (progress) {
|
||||||
// Progress mission to bring it up to speed
|
// Progress mission to bring it up to speed
|
||||||
@ -317,7 +318,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return any;
|
return acceptedAchievements;
|
||||||
#else
|
#else
|
||||||
auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>();
|
auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>();
|
||||||
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
||||||
@ -326,7 +327,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
|
|||||||
return entry.taskType == static_cast<unsigned>(type);
|
return entry.taskType == static_cast<unsigned>(type);
|
||||||
});
|
});
|
||||||
|
|
||||||
auto any = false;
|
std::vector<uint32_t> acceptedAchievements;
|
||||||
|
|
||||||
for (const auto& task : tasks) {
|
for (const auto& task : tasks) {
|
||||||
if (GetMission(task.id) != nullptr) {
|
if (GetMission(task.id) != nullptr) {
|
||||||
@ -380,14 +381,14 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
|
|||||||
|
|
||||||
instance->Accept();
|
instance->Accept();
|
||||||
|
|
||||||
any = true;
|
acceptedAchievements.push_back(mission.id);
|
||||||
|
|
||||||
if (progress) {
|
if (progress) {
|
||||||
instance->Progress(type, value, associate, targets, count);
|
instance->Progress(type, value, associate, targets, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return any;
|
return acceptedAchievements;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +500,7 @@ bool MissionComponent::RequiresItem(const LOT lot) {
|
|||||||
|
|
||||||
const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false);
|
const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false);
|
||||||
|
|
||||||
return required;
|
return !required.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ public:
|
|||||||
* @param count the number of values to progress by (differs by task type)
|
* @param count the number of values to progress by (differs by task type)
|
||||||
* @return true if a achievement was accepted, false otherwise
|
* @return true if a achievement was accepted, false otherwise
|
||||||
*/
|
*/
|
||||||
bool LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1);
|
const std::vector<uint32_t> LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if there's a mission active that requires the collection of the specified LOT
|
* Checks if there's a mission active that requires the collection of the specified LOT
|
||||||
|
@ -164,6 +164,8 @@ public:
|
|||||||
|
|
||||||
LWOCLONEID GetCloneId() { return clone_Id; };
|
LWOCLONEID GetCloneId() { return clone_Id; };
|
||||||
|
|
||||||
|
LWOOBJID GetId() const noexcept { return propertyId; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* This
|
* This
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
#include "eRacingTaskParam.h"
|
#include "eRacingTaskParam.h"
|
||||||
#include "Spawner.h"
|
#include "Spawner.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "dServer.h"
|
#include "dServer.h"
|
||||||
#include "dZoneManager.h"
|
#include "dZoneManager.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
@ -51,7 +51,7 @@ RacingControlComponent::RacingControlComponent(Entity* parent)
|
|||||||
|
|
||||||
m_MainWorld = 1200;
|
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;
|
if (Game::zoneManager->CheckIfAccessibleZone((worldID / 10) * 10)) m_MainWorld = (worldID / 10) * 10;
|
||||||
|
|
||||||
m_ActivityID = 42;
|
m_ActivityID = 42;
|
||||||
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
||||||
@ -72,7 +72,7 @@ void RacingControlComponent::OnPlayerLoaded(Entity* player) {
|
|||||||
// If the race has already started, send the player back to the main world.
|
// If the race has already started, send the player back to the main world.
|
||||||
if (m_Loaded || !vehicle) {
|
if (m_Loaded || !vehicle) {
|
||||||
auto* playerInstance = dynamic_cast<Player*>(player);
|
auto* playerInstance = dynamic_cast<Player*>(player);
|
||||||
if(playerInstance){
|
if (playerInstance) {
|
||||||
playerInstance->SendToZone(m_MainWorld);
|
playerInstance->SendToZone(m_MainWorld);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -106,7 +106,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
if (item == nullptr) {
|
if (item == nullptr) {
|
||||||
LOG("Failed to find item");
|
LOG("Failed to find item");
|
||||||
auto* playerInstance = dynamic_cast<Player*>(player);
|
auto* playerInstance = dynamic_cast<Player*>(player);
|
||||||
if(playerInstance){
|
if (playerInstance) {
|
||||||
m_LoadedPlayers--;
|
m_LoadedPlayers--;
|
||||||
playerInstance->SendToZone(m_MainWorld);
|
playerInstance->SendToZone(m_MainWorld);
|
||||||
}
|
}
|
||||||
@ -213,6 +213,7 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
|||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0 });
|
0 });
|
||||||
|
m_AllPlayersReady = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct and serialize everything when done.
|
// Construct and serialize everything when done.
|
||||||
@ -384,7 +385,7 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu
|
|||||||
|
|
||||||
// Calculate the score, different loot depending on player count
|
// Calculate the score, different loot depending on player count
|
||||||
auto playersRating = m_LoadedPlayers;
|
auto playersRating = m_LoadedPlayers;
|
||||||
if(m_LoadedPlayers == 1 && m_SoloRacing) {
|
if (m_LoadedPlayers == 1 && m_SoloRacing) {
|
||||||
playersRating *= 2;
|
playersRating *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,64 +437,82 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player, int32_t bu
|
|||||||
|
|
||||||
void RacingControlComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
void RacingControlComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) {
|
||||||
// BEGIN Scripted Activity
|
// BEGIN Scripted Activity
|
||||||
|
|
||||||
outBitStream->Write1();
|
outBitStream->Write1();
|
||||||
|
|
||||||
outBitStream->Write(static_cast<uint32_t>(m_RacingPlayers.size()));
|
outBitStream->Write(static_cast<uint32_t>(m_RacingPlayers.size()));
|
||||||
for (const auto& player : m_RacingPlayers) {
|
for (const auto& player : m_RacingPlayers) {
|
||||||
outBitStream->Write(player.playerID);
|
outBitStream->Write(player.playerID);
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++) {
|
outBitStream->Write(player.data[0]);
|
||||||
outBitStream->Write(player.data[i]);
|
if (player.finished != 0) outBitStream->Write<float>(player.raceTime);
|
||||||
}
|
else outBitStream->Write(player.data[1]);
|
||||||
|
if (player.finished != 0) outBitStream->Write<float>(player.bestLapTime);
|
||||||
|
else outBitStream->Write(player.data[2]);
|
||||||
|
if (player.finished == 1) outBitStream->Write<float>(1.0f);
|
||||||
|
else outBitStream->Write(player.data[3]);
|
||||||
|
outBitStream->Write(player.data[4]);
|
||||||
|
outBitStream->Write(player.data[5]);
|
||||||
|
outBitStream->Write(player.data[6]);
|
||||||
|
outBitStream->Write(player.data[7]);
|
||||||
|
outBitStream->Write(player.data[8]);
|
||||||
|
outBitStream->Write(player.data[9]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// END Scripted Activity
|
// END Scripted Activity
|
||||||
|
|
||||||
outBitStream->Write1(); // Dirty?
|
outBitStream->Write1();
|
||||||
outBitStream->Write(static_cast<uint16_t>(m_RacingPlayers.size()));
|
outBitStream->Write(static_cast<uint16_t>(m_RacingPlayers.size()));
|
||||||
|
|
||||||
outBitStream->Write(!m_RacingPlayers.empty());
|
outBitStream->Write(!m_AllPlayersReady);
|
||||||
if (!m_RacingPlayers.empty()) {
|
if (!m_AllPlayersReady) {
|
||||||
|
int32_t numReady = 0;
|
||||||
for (const auto& player : m_RacingPlayers) {
|
for (const auto& player : m_RacingPlayers) {
|
||||||
outBitStream->Write1(); // Has more date
|
outBitStream->Write1(); // Has more player data
|
||||||
|
|
||||||
outBitStream->Write(player.playerID);
|
outBitStream->Write(player.playerID);
|
||||||
outBitStream->Write(player.vehicleID);
|
outBitStream->Write(player.vehicleID);
|
||||||
outBitStream->Write(player.playerIndex);
|
outBitStream->Write(player.playerIndex);
|
||||||
outBitStream->Write(player.playerLoaded);
|
outBitStream->Write(player.playerLoaded);
|
||||||
|
if (player.playerLoaded) numReady++;
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream->Write0(); // No more data
|
outBitStream->Write0(); // No more data
|
||||||
|
if (numReady == m_RacingPlayers.size()) m_AllPlayersReady = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream->Write(!m_RacingPlayers.empty());
|
outBitStream->Write(!m_RacingPlayers.empty());
|
||||||
if (!m_RacingPlayers.empty()) {
|
if (!m_RacingPlayers.empty()) {
|
||||||
for (const auto& player : m_RacingPlayers) {
|
for (const auto& player : m_RacingPlayers) {
|
||||||
|
if (player.finished == 0) continue;
|
||||||
outBitStream->Write1(); // Has more date
|
outBitStream->Write1(); // Has more date
|
||||||
|
|
||||||
outBitStream->Write(player.playerID);
|
outBitStream->Write(player.playerID);
|
||||||
outBitStream->Write<uint32_t>(0);
|
outBitStream->Write(player.finished);
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream->Write0(); // No more data
|
outBitStream->Write0(); // No more data
|
||||||
}
|
}
|
||||||
|
|
||||||
outBitStream->Write1(); // Dirty?
|
outBitStream->Write(bIsInitialUpdate);
|
||||||
|
if (bIsInitialUpdate) {
|
||||||
outBitStream->Write(m_RemainingLaps);
|
outBitStream->Write(m_RemainingLaps);
|
||||||
|
|
||||||
outBitStream->Write(static_cast<uint16_t>(m_PathName.size()));
|
outBitStream->Write(static_cast<uint16_t>(m_PathName.size()));
|
||||||
for (const auto character : m_PathName) {
|
for (const auto character : m_PathName) {
|
||||||
outBitStream->Write(character);
|
outBitStream->Write(character);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
outBitStream->Write1(); // ???
|
outBitStream->Write(!m_RacingPlayers.empty());
|
||||||
outBitStream->Write1(); // ???
|
if (!m_RacingPlayers.empty()) {
|
||||||
|
for (const auto& player : m_RacingPlayers) {
|
||||||
|
if (player.finished == 0) continue;
|
||||||
|
outBitStream->Write1(); // Has more data
|
||||||
|
outBitStream->Write(player.playerID);
|
||||||
|
outBitStream->Write<float>(player.bestLapTime);
|
||||||
|
outBitStream->Write<float>(player.raceTime);
|
||||||
|
}
|
||||||
|
|
||||||
outBitStream->Write(m_LeadingPlayer);
|
outBitStream->Write0(); // No more data
|
||||||
outBitStream->Write(m_RaceBestLap);
|
}
|
||||||
outBitStream->Write(m_RaceBestTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RacingPlayerInfo* RacingControlComponent::GetPlayerData(LWOOBJID playerID) {
|
RacingPlayerInfo* RacingControlComponent::GetPlayerData(LWOOBJID playerID) {
|
||||||
@ -569,7 +588,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
|
|
||||||
LoadPlayerVehicle(player, positionNumber + 1, true);
|
LoadPlayerVehicle(player, positionNumber + 1, true);
|
||||||
|
|
||||||
m_Loaded = true;
|
Game::entityManager->SerializeEntity(m_Parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Loaded = true;
|
m_Loaded = true;
|
||||||
@ -757,6 +776,8 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_Finished != 0) Game::entityManager->SerializeEntity(m_Parent);
|
||||||
|
|
||||||
// Loop through all the waypoints and see if the player has reached a
|
// Loop through all the waypoints and see if the player has reached a
|
||||||
// new checkpoint
|
// new checkpoint
|
||||||
uint32_t respawnIndex = 0;
|
uint32_t respawnIndex = 0;
|
||||||
@ -849,8 +870,6 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
if (characterComponent != nullptr) {
|
if (characterComponent != nullptr) {
|
||||||
characterComponent->TrackRaceCompleted(m_Finished == 1);
|
characterComponent->TrackRaceCompleted(m_Finished == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Figure out how to update the GUI leaderboard.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,28 +884,3 @@ void RacingControlComponent::Update(float deltaTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string RacingControlComponent::FormatTimeString(time_t time) {
|
|
||||||
int32_t min = time / 60;
|
|
||||||
time -= min * 60;
|
|
||||||
int32_t sec = time;
|
|
||||||
|
|
||||||
std::string minText;
|
|
||||||
std::string secText;
|
|
||||||
|
|
||||||
if (min <= 0) {
|
|
||||||
minText = "0";
|
|
||||||
} else {
|
|
||||||
minText = std::to_string(min);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sec <= 0) {
|
|
||||||
secText = "00";
|
|
||||||
} else if (sec <= 9) {
|
|
||||||
secText = "0" + std::to_string(sec);
|
|
||||||
} else {
|
|
||||||
secText = std::to_string(sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
return minText + ":" + secText + ".00";
|
|
||||||
}
|
|
||||||
|
@ -151,13 +151,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
RacingPlayerInfo* GetPlayerData(LWOOBJID playerID);
|
RacingPlayerInfo* GetPlayerData(LWOOBJID playerID);
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a time to a string, currently unused
|
|
||||||
* @param time the time to format
|
|
||||||
* @return the time formatted as string
|
|
||||||
*/
|
|
||||||
static std::string FormatTimeString(time_t time);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -251,4 +244,5 @@ private:
|
|||||||
* Value for message box response to know if we are exiting the race via the activity dialogue
|
* Value for message box response to know if we are exiting the race via the activity dialogue
|
||||||
*/
|
*/
|
||||||
const int32_t m_ActivityExitConfirm = 1;
|
const int32_t m_ActivityExitConfirm = 1;
|
||||||
|
bool m_AllPlayersReady = false;
|
||||||
};
|
};
|
||||||
|
@ -197,18 +197,17 @@ void RebuildComponent::Update(float deltaTime) {
|
|||||||
DestroyableComponent* destComp = builder->GetComponent<DestroyableComponent>();
|
DestroyableComponent* destComp = builder->GetComponent<DestroyableComponent>();
|
||||||
if (!destComp) break;
|
if (!destComp) break;
|
||||||
|
|
||||||
int newImagination = destComp->GetImagination();
|
|
||||||
|
|
||||||
++m_DrainedImagination;
|
++m_DrainedImagination;
|
||||||
--newImagination;
|
const int32_t imaginationCostRemaining = m_TakeImagination - m_DrainedImagination;
|
||||||
|
|
||||||
|
const int32_t newImagination = destComp->GetImagination() - 1;
|
||||||
destComp->SetImagination(newImagination);
|
destComp->SetImagination(newImagination);
|
||||||
Game::entityManager->SerializeEntity(builder);
|
Game::entityManager->SerializeEntity(builder);
|
||||||
|
|
||||||
if (newImagination <= 0) {
|
if (newImagination <= 0 && imaginationCostRemaining > 0) {
|
||||||
CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true);
|
CancelRebuild(builder, eQuickBuildFailReason::OUT_OF_IMAGINATION, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Timer >= m_CompleteTime && m_DrainedImagination >= m_TakeImagination) {
|
if (m_Timer >= m_CompleteTime && m_DrainedImagination >= m_TakeImagination) {
|
||||||
|
@ -285,7 +285,7 @@ private:
|
|||||||
float m_CompleteTime = 0;
|
float m_CompleteTime = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The imagination that's deducted when compeleting the rebuild
|
* The imagination that's deducted when completing the rebuild
|
||||||
*/
|
*/
|
||||||
int m_TakeImagination = 0;
|
int m_TakeImagination = 0;
|
||||||
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
#include "ZoneControlComponent.h"
|
|
||||||
|
|
||||||
void ZoneControlComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
|
|
||||||
outBitStream->Write<uint32_t>(0x40000000);
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef __ZONECONTROLCOMPONENT__H__
|
|
||||||
#define __ZONECONTROLCOMPONENT__H__
|
|
||||||
|
|
||||||
#include "Component.h"
|
|
||||||
#include "eReplicaComponentType.h"
|
|
||||||
|
|
||||||
class ZoneControlComponent final : public Component {
|
|
||||||
public:
|
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ZONE_CONTROL;
|
|
||||||
|
|
||||||
ZoneControlComponent(Entity* parent) : Component(parent) {}
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //!__ZONECONTROLCOMPONENT__H__
|
|
@ -71,7 +71,7 @@
|
|||||||
#include "MovingPlatformComponent.h"
|
#include "MovingPlatformComponent.h"
|
||||||
#include "PetComponent.h"
|
#include "PetComponent.h"
|
||||||
#include "ModuleAssemblyComponent.h"
|
#include "ModuleAssemblyComponent.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "RenderComponent.h"
|
#include "RenderComponent.h"
|
||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
@ -946,13 +946,6 @@ void GameMessages::SendResurrect(Entity* entity) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
auto cont = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS));
|
|
||||||
if (cont && entity->GetLOT() == 1) {
|
|
||||||
cont->SetPosition(entity->GetRespawnPosition());
|
|
||||||
cont->SetRotation(entity->GetRespawnRotation());
|
|
||||||
}
|
|
||||||
|
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
|
|
||||||
@ -1144,17 +1137,15 @@ void GameMessages::SendPlayerReachedRespawnCheckpoint(Entity* entity, const NiPo
|
|||||||
bitStream.Write(position.y);
|
bitStream.Write(position.y);
|
||||||
bitStream.Write(position.z);
|
bitStream.Write(position.z);
|
||||||
|
|
||||||
auto con = static_cast<ControllablePhysicsComponent*>(entity->GetComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS));
|
const bool isNotIdentity = rotation != NiQuaternion::IDENTITY;
|
||||||
if (con) {
|
bitStream.Write(isNotIdentity);
|
||||||
auto rot = con->GetRotation();
|
|
||||||
bitStream.Write(rot.x);
|
|
||||||
bitStream.Write(rot.y);
|
|
||||||
bitStream.Write(rot.z);
|
|
||||||
bitStream.Write(rot.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
//bitStream.Write(position);
|
if (isNotIdentity) {
|
||||||
//bitStream.Write(rotation);
|
bitStream.Write(rotation.w);
|
||||||
|
bitStream.Write(rotation.x);
|
||||||
|
bitStream.Write(rotation.y);
|
||||||
|
bitStream.Write(rotation.z);
|
||||||
|
}
|
||||||
|
|
||||||
SystemAddress sysAddr = entity->GetSystemAddress();
|
SystemAddress sysAddr = entity->GetSystemAddress();
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@ -4486,7 +4477,7 @@ void GameMessages::SendVehicleNotifyFinishedRace(LWOOBJID objectId, const System
|
|||||||
|
|
||||||
void GameMessages::SendAddBuff(LWOOBJID& objectID, const LWOOBJID& casterID, uint32_t buffID, uint32_t msDuration,
|
void GameMessages::SendAddBuff(LWOOBJID& objectID, const LWOOBJID& casterID, uint32_t buffID, uint32_t msDuration,
|
||||||
bool addImmunity, bool cancelOnDamaged, bool cancelOnDeath, bool cancelOnLogout,
|
bool addImmunity, bool cancelOnDamaged, bool cancelOnDeath, bool cancelOnLogout,
|
||||||
bool cancelOnRemoveBuff, bool cancelOnUi, bool cancelOnUnequip, bool cancelOnZone,
|
bool cancelOnRemoveBuff, bool cancelOnUi, bool cancelOnUnequip, bool cancelOnZone, bool addedByTeammate, bool applyOnTeammates,
|
||||||
const SystemAddress& sysAddr) {
|
const SystemAddress& sysAddr) {
|
||||||
CBITSTREAM;
|
CBITSTREAM;
|
||||||
CMSGHEADER;
|
CMSGHEADER;
|
||||||
@ -4494,27 +4485,29 @@ void GameMessages::SendAddBuff(LWOOBJID& objectID, const LWOOBJID& casterID, uin
|
|||||||
bitStream.Write(objectID);
|
bitStream.Write(objectID);
|
||||||
bitStream.Write(eGameMessageType::ADD_BUFF);
|
bitStream.Write(eGameMessageType::ADD_BUFF);
|
||||||
|
|
||||||
bitStream.Write(false); // Added by teammate
|
bitStream.Write(addedByTeammate); // Added by teammate
|
||||||
bitStream.Write(false); // Apply on teammates
|
bitStream.Write(applyOnTeammates); // Apply on teammates
|
||||||
bitStream.Write(false); // Cancel on damage absorb ran out
|
|
||||||
bitStream.Write(cancelOnDamaged);
|
bitStream.Write(cancelOnDamaged);
|
||||||
bitStream.Write(cancelOnDeath);
|
bitStream.Write(cancelOnDeath);
|
||||||
bitStream.Write(cancelOnLogout);
|
bitStream.Write(cancelOnLogout);
|
||||||
|
|
||||||
bitStream.Write(false); // Cancel on move
|
bitStream.Write(false); // Cancel on move
|
||||||
bitStream.Write(cancelOnRemoveBuff);
|
bitStream.Write(cancelOnRemoveBuff);
|
||||||
|
|
||||||
bitStream.Write(cancelOnUi);
|
bitStream.Write(cancelOnUi);
|
||||||
bitStream.Write(cancelOnUnequip);
|
bitStream.Write(cancelOnUnequip);
|
||||||
bitStream.Write(cancelOnZone);
|
bitStream.Write(cancelOnZone);
|
||||||
|
|
||||||
bitStream.Write(false); // Ignore immunities
|
bitStream.Write(false); // Ignore immunities
|
||||||
bitStream.Write(addImmunity);
|
bitStream.Write(addImmunity);
|
||||||
bitStream.Write(false); // Use ref count
|
bitStream.Write(false); // Use ref count
|
||||||
|
|
||||||
bitStream.Write(buffID);
|
bitStream.Write(casterID != LWOOBJID_EMPTY);
|
||||||
bitStream.Write(msDuration);
|
if (casterID != LWOOBJID_EMPTY) bitStream.Write(casterID);
|
||||||
|
|
||||||
bitStream.Write(casterID);
|
bitStream.Write(buffID);
|
||||||
bitStream.Write(casterID);
|
|
||||||
|
bitStream.Write(msDuration != 0);
|
||||||
|
if (msDuration != 0) bitStream.Write(msDuration);
|
||||||
|
|
||||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) SEND_PACKET_BROADCAST;
|
||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
@ -5017,6 +5010,14 @@ void GameMessages::HandlePlayEmote(RakNet::BitStream* inStream, Entity* entity)
|
|||||||
if (emoteID == 0) return;
|
if (emoteID == 0) return;
|
||||||
std::string sAnimationName = "deaded"; //Default name in case we fail to get the emote
|
std::string sAnimationName = "deaded"; //Default name in case we fail to get the emote
|
||||||
|
|
||||||
|
CDEmoteTableTable* emotes = CDClientManager::Instance().GetTable<CDEmoteTableTable>();
|
||||||
|
if (emotes) {
|
||||||
|
CDEmoteTable* emote = emotes->GetEmote(emoteID);
|
||||||
|
if (emote) sAnimationName = emote->animationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderComponent::PlayAnimation(entity, sAnimationName);
|
||||||
|
|
||||||
MissionComponent* missionComponent = entity->GetComponent<MissionComponent>();
|
MissionComponent* missionComponent = entity->GetComponent<MissionComponent>();
|
||||||
if (!missionComponent) return;
|
if (!missionComponent) return;
|
||||||
|
|
||||||
@ -5042,14 +5043,6 @@ void GameMessages::HandlePlayEmote(RakNet::BitStream* inStream, Entity* entity)
|
|||||||
missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, scripted->GetObjectID());
|
missionComponent->Progress(eMissionTaskType::EMOTE, emoteID, scripted->GetObjectID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CDEmoteTableTable* emotes = CDClientManager::Instance().GetTable<CDEmoteTableTable>();
|
|
||||||
if (emotes) {
|
|
||||||
CDEmoteTable* emote = emotes->GetEmote(emoteID);
|
|
||||||
if (emote) sAnimationName = emote->animationName;
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderComponent::PlayAnimation(entity, sAnimationName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameMessages::HandleModularBuildConvertModel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
void GameMessages::HandleModularBuildConvertModel(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr) {
|
||||||
@ -5585,7 +5578,7 @@ void GameMessages::HandleModularBuildFinish(RakNet::BitStream* inStream, Entity*
|
|||||||
|
|
||||||
std::unique_ptr<sql::PreparedStatement> stmt(Database::Get()->CreatePreppedStmt("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)"));
|
std::unique_ptr<sql::PreparedStatement> stmt(Database::Get()->CreatePreppedStmt("INSERT INTO ugc_modular_build (ugc_id, ldf_config, character_id) VALUES (?,?,?)"));
|
||||||
stmt->setUInt64(1, newIdBig);
|
stmt->setUInt64(1, newIdBig);
|
||||||
stmt->setString(2, GeneralUtils::UTF16ToWTF8(modules));
|
stmt->setString(2, GeneralUtils::UTF16ToWTF8(modules).c_str());
|
||||||
auto* pCharacter = character->GetCharacter();
|
auto* pCharacter = character->GetCharacter();
|
||||||
pCharacter ? stmt->setUInt(3, pCharacter->GetID()) : stmt->setNull(3, sql::DataType::BIGINT);
|
pCharacter ? stmt->setUInt(3, pCharacter->GetID()) : stmt->setNull(3, sql::DataType::BIGINT);
|
||||||
stmt->execute();
|
stmt->execute();
|
||||||
|
@ -206,7 +206,7 @@ namespace GameMessages {
|
|||||||
void SendAddBuff(LWOOBJID& objectID, const LWOOBJID& casterID, uint32_t buffID, uint32_t msDuration,
|
void SendAddBuff(LWOOBJID& objectID, const LWOOBJID& casterID, uint32_t buffID, uint32_t msDuration,
|
||||||
bool addImmunity = false, bool cancelOnDamaged = false, bool cancelOnDeath = true,
|
bool addImmunity = false, bool cancelOnDamaged = false, bool cancelOnDeath = true,
|
||||||
bool cancelOnLogout = false, bool cancelOnRemoveBuff = true, bool cancelOnUi = false,
|
bool cancelOnLogout = false, bool cancelOnRemoveBuff = true, bool cancelOnUi = false,
|
||||||
bool cancelOnUnequip = false, bool cancelOnZone = false, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
bool cancelOnUnequip = false, bool cancelOnZone = false, bool addedByTeammate = false, bool applyOnTeammates = false, const SystemAddress& sysAddr = UNASSIGNED_SYSTEM_ADDRESS);
|
||||||
|
|
||||||
void SendToggleGMInvis(LWOOBJID objectId, bool enabled, const SystemAddress& sysAddr);
|
void SendToggleGMInvis(LWOOBJID objectId, bool enabled, const SystemAddress& sysAddr);
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
#include "dpShapeSphere.h"
|
#include "dpShapeSphere.h"
|
||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "BuffComponent.h"
|
#include "BuffComponent.h"
|
||||||
#include "SkillComponent.h"
|
#include "SkillComponent.h"
|
||||||
#include "VanityUtilities.h"
|
#include "VanityUtilities.h"
|
||||||
@ -938,9 +938,9 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
|||||||
auto* possassableEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
auto* possassableEntity = Game::entityManager->GetEntity(possessorComponent->GetPossessable());
|
||||||
|
|
||||||
if (possassableEntity != nullptr) {
|
if (possassableEntity != nullptr) {
|
||||||
auto* vehiclePhysicsComponent = possassableEntity->GetComponent<VehiclePhysicsComponent>();
|
auto* havokVehiclePhysicsComponent = possassableEntity->GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
if (vehiclePhysicsComponent) {
|
if (havokVehiclePhysicsComponent) {
|
||||||
vehiclePhysicsComponent->SetPosition(pos);
|
havokVehiclePhysicsComponent->SetPosition(pos);
|
||||||
Game::entityManager->SerializeEntity(possassableEntity);
|
Game::entityManager->SerializeEntity(possassableEntity);
|
||||||
} else GameMessages::SendTeleport(possassableEntity->GetObjectID(), pos, NiQuaternion(), sysAddr);
|
} else GameMessages::SendTeleport(possassableEntity->GetObjectID(), pos, NiQuaternion(), sysAddr);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "Zone.h"
|
#include "Zone.h"
|
||||||
#include "PossessorComponent.h"
|
#include "PossessorComponent.h"
|
||||||
#include "PossessableComponent.h"
|
#include "PossessableComponent.h"
|
||||||
#include "VehiclePhysicsComponent.h"
|
#include "HavokVehiclePhysicsComponent.h"
|
||||||
#include "dConfig.h"
|
#include "dConfig.h"
|
||||||
#include "CharacterComponent.h"
|
#include "CharacterComponent.h"
|
||||||
#include "Database.h"
|
#include "Database.h"
|
||||||
@ -187,17 +187,17 @@ void ClientPackets::HandleClientPositionUpdate(const SystemAddress& sysAddr, Pac
|
|||||||
if (possessableComponent->GetPossessionType() != ePossessionType::ATTACHED_VISIBLE) updateChar = false;
|
if (possessableComponent->GetPossessionType() != ePossessionType::ATTACHED_VISIBLE) updateChar = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* vehiclePhysicsComponent = possassableEntity->GetComponent<VehiclePhysicsComponent>();
|
auto* havokVehiclePhysicsComponent = possassableEntity->GetComponent<HavokVehiclePhysicsComponent>();
|
||||||
if (vehiclePhysicsComponent != nullptr) {
|
if (havokVehiclePhysicsComponent != nullptr) {
|
||||||
vehiclePhysicsComponent->SetPosition(position);
|
havokVehiclePhysicsComponent->SetPosition(position);
|
||||||
vehiclePhysicsComponent->SetRotation(rotation);
|
havokVehiclePhysicsComponent->SetRotation(rotation);
|
||||||
vehiclePhysicsComponent->SetIsOnGround(onGround);
|
havokVehiclePhysicsComponent->SetIsOnGround(onGround);
|
||||||
vehiclePhysicsComponent->SetIsOnRail(onRail);
|
havokVehiclePhysicsComponent->SetIsOnRail(onRail);
|
||||||
vehiclePhysicsComponent->SetVelocity(velocity);
|
havokVehiclePhysicsComponent->SetVelocity(velocity);
|
||||||
vehiclePhysicsComponent->SetDirtyVelocity(velocityFlag);
|
havokVehiclePhysicsComponent->SetDirtyVelocity(velocityFlag);
|
||||||
vehiclePhysicsComponent->SetAngularVelocity(angVelocity);
|
havokVehiclePhysicsComponent->SetAngularVelocity(angVelocity);
|
||||||
vehiclePhysicsComponent->SetDirtyAngularVelocity(angVelocityFlag);
|
havokVehiclePhysicsComponent->SetDirtyAngularVelocity(angVelocityFlag);
|
||||||
vehiclePhysicsComponent->SetRemoteInputInfo(remoteInput);
|
havokVehiclePhysicsComponent->SetRemoteInputInfo(remoteInput);
|
||||||
} else {
|
} else {
|
||||||
// Need to get the mount's controllable physics
|
// Need to get the mount's controllable physics
|
||||||
auto* controllablePhysicsComponent = possassableEntity->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = possassableEntity->GetComponent<ControllablePhysicsComponent>();
|
||||||
@ -359,8 +359,8 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
|
|||||||
idOfReceiver = characterIdFetch->id;
|
idOfReceiver = characterIdFetch->id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const auto& bffMap = user->GetIsBestFriendMap();
|
||||||
if (user->GetIsBestFriendMap().find(receiver) == user->GetIsBestFriendMap().end() && idOfReceiver != LWOOBJID_EMPTY) {
|
if (bffMap.find(receiver) == bffMap.end() && idOfReceiver != LWOOBJID_EMPTY) {
|
||||||
auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver);
|
auto bffInfo = Database::Get()->GetBestFriendStatus(entity->GetObjectID(), idOfReceiver);
|
||||||
|
|
||||||
if (bffInfo) {
|
if (bffInfo) {
|
||||||
@ -368,11 +368,9 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isBestFriend) {
|
if (isBestFriend) {
|
||||||
auto tmpBestFriendMap = user->GetIsBestFriendMap();
|
user->UpdateBestFriendValue(receiver, true);
|
||||||
tmpBestFriendMap[receiver] = true;
|
|
||||||
user->SetIsBestFriendMap(tmpBestFriendMap);
|
|
||||||
}
|
}
|
||||||
} else if (user->GetIsBestFriendMap().find(receiver) != user->GetIsBestFriendMap().end()) {
|
} else if (bffMap.find(receiver) != bffMap.end()) {
|
||||||
isBestFriend = true;
|
isBestFriend = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ void BasePropertyServer::BasePlayerLoaded(Entity* self, Entity* player) {
|
|||||||
missionComponent->Progress(
|
missionComponent->Progress(
|
||||||
eMissionTaskType::VISIT_PROPERTY,
|
eMissionTaskType::VISIT_PROPERTY,
|
||||||
mapID.GetMapID(),
|
mapID.GetMapID(),
|
||||||
mapID.GetCloneID()
|
PropertyManagementComponent::Instance()->GetId()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "PerformanceManager.h"
|
#include "PerformanceManager.h"
|
||||||
#include "Diagnostics.h"
|
#include "Diagnostics.h"
|
||||||
#include "BinaryPathFinder.h"
|
#include "BinaryPathFinder.h"
|
||||||
|
#include "dPlatforms.h"
|
||||||
|
|
||||||
//RakNet includes:
|
//RakNet includes:
|
||||||
#include "RakNetDefines.h"
|
#include "RakNetDefines.h"
|
||||||
@ -1284,12 +1285,14 @@ void WorldShutdownProcess(uint32_t zoneId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorldShutdownSequence() {
|
void WorldShutdownSequence() {
|
||||||
if (Game::shouldShutdown || worldShutdownSequenceComplete) {
|
Game::shouldShutdown = true;
|
||||||
|
#ifndef DARKFLAME_PLATFORM_WIN32
|
||||||
|
if (Game::shouldShutdown || worldShutdownSequenceComplete)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::shouldShutdown = true;
|
|
||||||
|
|
||||||
LOG("Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID);
|
LOG("Zone (%i) instance (%i) shutting down outside of main loop!", Game::server->GetZoneID(), instanceID);
|
||||||
WorldShutdownProcess(Game::server->GetZoneID());
|
WorldShutdownProcess(Game::server->GetZoneID());
|
||||||
FinalizeShutdown();
|
FinalizeShutdown();
|
||||||
@ -1302,11 +1305,17 @@ void FinalizeShutdown() {
|
|||||||
Metrics::Clear();
|
Metrics::Clear();
|
||||||
Database::Destroy("WorldServer");
|
Database::Destroy("WorldServer");
|
||||||
if (Game::chatFilter) delete Game::chatFilter;
|
if (Game::chatFilter) delete Game::chatFilter;
|
||||||
|
Game::chatFilter = nullptr;
|
||||||
if (Game::zoneManager) delete Game::zoneManager;
|
if (Game::zoneManager) delete Game::zoneManager;
|
||||||
|
Game::zoneManager = nullptr;
|
||||||
if (Game::server) delete Game::server;
|
if (Game::server) delete Game::server;
|
||||||
|
Game::server = nullptr;
|
||||||
if (Game::config) delete Game::config;
|
if (Game::config) delete Game::config;
|
||||||
|
Game::config = nullptr;
|
||||||
if (Game::entityManager) delete Game::entityManager;
|
if (Game::entityManager) delete Game::entityManager;
|
||||||
|
Game::entityManager = nullptr;
|
||||||
if (Game::logger) delete Game::logger;
|
if (Game::logger) delete Game::logger;
|
||||||
|
Game::logger = nullptr;
|
||||||
|
|
||||||
worldShutdownSequenceComplete = true;
|
worldShutdownSequenceComplete = true;
|
||||||
|
|
||||||
|
@ -79,8 +79,6 @@ dZoneManager::~dZoneManager() {
|
|||||||
delete p.second;
|
delete p.second;
|
||||||
p.second = nullptr;
|
p.second = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Spawners.erase(p.first);
|
|
||||||
}
|
}
|
||||||
if (m_WorldConfig) delete m_WorldConfig;
|
if (m_WorldConfig) delete m_WorldConfig;
|
||||||
}
|
}
|
||||||
|
6
migrations/dlu/13_ignore_list.sql
Normal file
6
migrations/dlu/13_ignore_list.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS ignore_list (
|
||||||
|
player_id BIGINT NOT NULL REFERENCES charinfo(id) ON DELETE CASCADE,
|
||||||
|
ignored_player_id BIGINT NOT NULL REFERENCES charinfo(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
PRIMARY KEY (player_id, ignored_player_id)
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user